diff --git a/packages/chicken/lib/data/di/chicken_di.dart b/packages/chicken/lib/data/di/chicken_di.dart index 402abce..5ceb8b4 100644 --- a/packages/chicken/lib/data/di/chicken_di.dart +++ b/packages/chicken/lib/data/di/chicken_di.dart @@ -15,7 +15,6 @@ import 'package:rasadyar_core/core.dart'; GetIt diChicken = GetIt.instance; Future setupChickenDI() async { - tLog("setup 1"); diChicken.registerSingleton(DioErrorHandler()); var tokenService = Get.find(); @@ -52,7 +51,6 @@ Future setupChickenDI() async { diChicken.registerLazySingleton( () => AuthRepositoryImpl(diChicken.get()), - instanceName: 'oldRepo', ); diChicken.registerLazySingleton( @@ -95,11 +93,10 @@ Future newSetupAuthDI(String newUrl) async { ); } - if (diChicken.isRegistered(instanceName: 'oldRepo')) { - await diChicken.unregister(instanceName: 'oldRepo'); + if (diChicken.isRegistered()) { + await diChicken.unregister(); diChicken.registerLazySingleton( () => AuthRepositoryImpl(diChicken.get()), - instanceName: 'newRepo', ); } diff --git a/packages/chicken/lib/presentation/pages/auth/logic.dart b/packages/chicken/lib/presentation/pages/auth/logic.dart index a73a304..b1cfbe2 100644 --- a/packages/chicken/lib/presentation/pages/auth/logic.dart +++ b/packages/chicken/lib/presentation/pages/auth/logic.dart @@ -23,6 +23,7 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin { late AnimationController _textAnimationController; late Animation textAnimation; RxBool showCard = false.obs; + RxBool rememberMe = false.obs; Rx> formKeyOtp = GlobalKey().obs; Rx> formKeySentOtp = GlobalKey().obs; @@ -45,7 +46,7 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin { RxInt secondsRemaining = 120.obs; Timer? _timer; - AuthRepository authRepository = diChicken.get(instanceName: 'oldRepo'); + AuthRepository authRepository = diChicken.get(); final Module _module = Get.arguments; @@ -60,6 +61,8 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin { }); textAnimation = CurvedAnimation(parent: _textAnimationController, curve: Curves.easeInOut); + + initUserPassData(); } @override @@ -118,7 +121,7 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin { Future submitLoginForm() async { if (!_isFormValid()) return; - AuthRepository authTmp = diChicken.get(instanceName: 'newRepo'); + AuthRepository authTmp = diChicken.get(); isLoading.value = true; await safeCall( call: () => authTmp.login( @@ -131,6 +134,16 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin { await tokenStorageService.saveModule(_module); await tokenStorageService.saveAccessToken(result?.accessToken ?? ''); await tokenStorageService.saveRefreshToken(result?.accessToken ?? ''); + if (rememberMe.value) { + await tokenStorageService.saveUserPass( + UserLocalModel( + username: usernameController.value.text, + password: passwordController.value.text, + module: _module, + ), + ); + } + Get.offAndToNamed(ChickenRoutes.init); }, onError: (error, stackTrace) { @@ -163,4 +176,13 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin { ); isLoading.value = false; } + + void initUserPassData() { + UserLocalModel? userPass = tokenStorageService.getUserPass(_module); + if (userPass != null) { + usernameController.value.text = userPass.username ?? ''; + passwordController.value.text = userPass.password ?? ''; + rememberMe.value = true; + } + } } diff --git a/packages/chicken/lib/presentation/pages/auth/view.dart b/packages/chicken/lib/presentation/pages/auth/view.dart index 2fb0544..2f2e85c 100644 --- a/packages/chicken/lib/presentation/pages/auth/view.dart +++ b/packages/chicken/lib/presentation/pages/auth/view.dart @@ -197,7 +197,28 @@ class AuthPage extends GetView { ), SizedBox(height: 26), CaptchaWidget(), - SizedBox(height: 23), + + Row( + children: [ + ObxValue((data) { + return Checkbox( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + visualDensity: VisualDensity(horizontal: -4, vertical: 4), + tristate: true, + value: data.value, + onChanged: (value) { + data.value = value ?? false; + }, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(4)), + activeColor: AppColor.blueNormal, + ); + }, controller.rememberMe), + Text( + 'مرا به خاطر بسپار', + style: AppFonts.yekan14.copyWith(color: AppColor.darkGreyDark), + ), + ], + ), Obx(() { return RElevated( diff --git a/packages/chicken/lib/presentation/pages/profile/view.dart b/packages/chicken/lib/presentation/pages/profile/view.dart index 23ccba7..7328c0d 100644 --- a/packages/chicken/lib/presentation/pages/profile/view.dart +++ b/packages/chicken/lib/presentation/pages/profile/view.dart @@ -3,9 +3,9 @@ import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:rasadyar_chicken/chicken.dart'; +import 'package:rasadyar_chicken/data/di/chicken_di.dart'; import 'package:rasadyar_chicken/data/models/response/iran_province_city/iran_province_city_model.dart'; import 'package:rasadyar_chicken/data/models/response/user_profile/user_profile.dart'; - import 'package:rasadyar_core/core.dart'; import 'logic.dart'; @@ -27,49 +27,41 @@ class ProfilePage extends GetView { crossAxisAlignment: CrossAxisAlignment.center, children: [ Row(), - ObxValue( - (data) { - final status = data.value.status; + ObxValue((data) { + final status = data.value.status; - if (status == ResourceStatus.loading) { - return Container( - width: 128.w, - height: 128.h, - child: Center(child: CupertinoActivityIndicator(color: AppColor - .greenNormal,)), - ); - } - - if (status == ResourceStatus.error) { - return Container( - width: 128.w, - height: 128.h, - child: Center(child: Text('خطا در دریافت اطلاعات')), - ); - } - - - // Default UI + if (status == ResourceStatus.loading) { return Container( width: 128.w, height: 128.h, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: AppColor.blueLightActive, - ), - child: Center( - child: CircleAvatar( - radius: 64.w, - backgroundImage: - NetworkImage(data.value.data!.image!) - - - ), - ), + child: Center(child: CupertinoActivityIndicator(color: AppColor.greenNormal)), ); - }, - controller.userProfile, - ) + } + + if (status == ResourceStatus.error) { + return Container( + width: 128.w, + height: 128.h, + child: Center(child: Text('خطا در دریافت اطلاعات')), + ); + } + + // Default UI + return Container( + width: 128.w, + height: 128.h, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: AppColor.blueLightActive, + ), + child: Center( + child: CircleAvatar( + radius: 64.w, + backgroundImage: NetworkImage(data.value.data!.image!), + ), + ), + ); + }, controller.userProfile), ], ), ), @@ -126,17 +118,16 @@ class ProfilePage extends GetView { Container invoiceIssuanceInformation() => Container(); - Widget bankInformationWidget() => - Column( - spacing: 16, - children: [ - itemList(title: 'نام بانک', content: 'سامان'), - itemList(title: 'نام صاحب حساب', content: 'رضا رضایی'), - itemList(title: 'شماره کارت ', content: '54154545415'), - itemList(title: 'شماره حساب', content: '62565263263652'), - itemList(title: 'شماره شبا', content: '62565263263652'), - ], - ); + Widget bankInformationWidget() => Column( + spacing: 16, + children: [ + itemList(title: 'نام بانک', content: 'سامان'), + itemList(title: 'نام صاحب حساب', content: 'رضا رضایی'), + itemList(title: 'شماره کارت ', content: '54154545415'), + itemList(title: 'شماره حساب', content: '62565263263652'), + itemList(title: 'شماره شبا', content: '62565263263652'), + ], + ); Widget userProfileInformation() { return ObxValue((data) { @@ -152,7 +143,10 @@ class ProfilePage extends GetView { buildRowOnTapped( onTap: () { Get.bottomSheet( - userInformationBottomSheet(), isScrollControlled: true, ignoreSafeArea: false); + userInformationBottomSheet(), + isScrollControlled: true, + ignoreSafeArea: false, + ); }, titleWidget: Column( spacing: 3, @@ -216,34 +210,33 @@ class ProfilePage extends GetView { required String content, String? icon, bool hasColoredBox = false, - }) => - Container( - padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 6.h), - decoration: BoxDecoration( - color: hasColoredBox ? AppColor.greenLight : Colors.transparent, - borderRadius: BorderRadius.circular(8), - border: hasColoredBox - ? Border.all(width: 0.25, color: AppColor.bgDark) - : Border.all(width: 0, color: Colors.transparent), - ), - child: Row( - spacing: 4, - children: [ - if (icon != null) - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: SvgGenImage.vec(icon).svg( - width: 20.w, - height: 20.h, - colorFilter: ColorFilter.mode(AppColor.mediumGreyNormalActive, BlendMode.srcIn), - ), - ), - Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyNormalActive)), - Spacer(), - Text(content, style: AppFonts.yekan13.copyWith(color: AppColor.mediumGreyNormalHover)), - ], - ), - ); + }) => Container( + padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 6.h), + decoration: BoxDecoration( + color: hasColoredBox ? AppColor.greenLight : Colors.transparent, + borderRadius: BorderRadius.circular(8), + border: hasColoredBox + ? Border.all(width: 0.25, color: AppColor.bgDark) + : Border.all(width: 0, color: Colors.transparent), + ), + child: Row( + spacing: 4, + children: [ + if (icon != null) + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: SvgGenImage.vec(icon).svg( + width: 20.w, + height: 20.h, + colorFilter: ColorFilter.mode(AppColor.mediumGreyNormalActive, BlendMode.srcIn), + ), + ), + Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyNormalActive)), + Spacer(), + Text(content, style: AppFonts.yekan13.copyWith(color: AppColor.mediumGreyNormalHover)), + ], + ), + ); Widget cardActionWidget({ required String title, @@ -271,7 +264,7 @@ class ProfilePage extends GetView { width: 40, height: 40, colorFilter: - color ?? + color ?? ColorFilter.mode( selected ? AppColor.blueNormal : AppColor.whiteLight, BlendMode.srcIn, @@ -355,8 +348,6 @@ class ProfilePage extends GetView { }, controller.birthDate), SizedBox(), - - ], ), ), @@ -372,8 +363,10 @@ class ProfilePage extends GetView { child: Column( spacing: 8, children: [ - Text('عکس پروفایل', - style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal)), + Text( + 'عکس پروفایل', + style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal), + ), ObxValue((data) { return Container( width: Get.width, @@ -386,9 +379,11 @@ class ProfilePage extends GetView { child: Center( child: data.value == null ? Padding( - padding: const EdgeInsets.fromLTRB(30, 10, 10, 30), - child: Image.network(controller.userProfile.value.data?.image ?? '') - ) + padding: const EdgeInsets.fromLTRB(30, 10, 10, 30), + child: Image.network( + controller.userProfile.value.data?.image ?? '', + ), + ) : Image.file(File(data.value!.path), fit: BoxFit.cover), ), ); @@ -447,7 +442,7 @@ class ProfilePage extends GetView { Get.back(); }, ); - },controller.isOnLoading), + }, controller.isOnLoading), ROutlinedElevated( height: 40.h, text: 'انصراف', @@ -618,7 +613,7 @@ class ProfilePage extends GetView { text: 'خروج', backgroundColor: AppColor.error, onPressed: () async { - await controller.rootLogic.tokenService.deleteTokens().then((value) { + await controller.rootLogic.tokenService.deleteTokens().then((value){ Get.back(); Get.offAllNamed(ChickenRoutes.auth, arguments: Module.chicken); }); diff --git a/packages/core/lib/core.dart b/packages/core/lib/core.dart index 25499a4..55eeb79 100644 --- a/packages/core/lib/core.dart +++ b/packages/core/lib/core.dart @@ -2,7 +2,8 @@ library; export 'package:android_intent_plus/android_intent.dart'; export 'package:android_intent_plus/flag.dart'; -export 'package:cached_network_image/cached_network_image.dart' ; +export 'package:cached_network_image/cached_network_image.dart'; +export 'package:collection/collection.dart'; export 'package:connectivity_plus/connectivity_plus.dart'; export 'package:device_info_plus/device_info_plus.dart'; export 'package:dio/dio.dart'; diff --git a/packages/core/lib/data/model/local/user_local/user_local_model.dart b/packages/core/lib/data/model/local/user_local/user_local_model.dart index beb08f2..d5a4afd 100644 --- a/packages/core/lib/data/model/local/user_local/user_local_model.dart +++ b/packages/core/lib/data/model/local/user_local/user_local_model.dart @@ -1,5 +1,4 @@ import 'package:rasadyar_core/core.dart'; -import 'package:rasadyar_core/utils/local/local_utils.dart'; part 'user_local_model.g.dart'; @@ -13,27 +12,18 @@ class UserLocalModel extends HiveObject { String? token; @HiveField(3) String? refreshToken; - @HiveField(4) - String? name; - @HiveField(5) Module? module; - @HiveField(6) String? backend; - @HiveField(7) - String? apiKey; - UserLocalModel({ this.username, this.password, this.token, this.refreshToken, - this.name, this.module, this.backend, - this.apiKey, }); UserLocalModel copyWith({ @@ -41,20 +31,16 @@ class UserLocalModel extends HiveObject { String? password, String? token, String? refreshToken, - String? name, Module? module, String? backend, - String? apiKey, }) { return UserLocalModel( username: username ?? this.username, password: password ?? this.password, token: token ?? this.token, refreshToken: refreshToken ?? this.refreshToken, - name: name ?? this.name, module: module ?? this.module, backend: backend ?? this.backend, - apiKey: apiKey ?? this.apiKey, ); } } diff --git a/packages/core/lib/data/model/local/user_local/user_local_model.g.dart b/packages/core/lib/data/model/local/user_local/user_local_model.g.dart index 93e49af..cde7c65 100644 --- a/packages/core/lib/data/model/local/user_local/user_local_model.g.dart +++ b/packages/core/lib/data/model/local/user_local/user_local_model.g.dart @@ -21,17 +21,15 @@ class UserLocalModelAdapter extends TypeAdapter { password: fields[1] as String?, token: fields[2] as String?, refreshToken: fields[3] as String?, - name: fields[4] as String?, module: fields[5] as Module?, backend: fields[6] as String?, - apiKey: fields[7] as String?, ); } @override void write(BinaryWriter writer, UserLocalModel obj) { writer - ..writeByte(8) + ..writeByte(6) ..writeByte(0) ..write(obj.username) ..writeByte(1) @@ -40,14 +38,10 @@ class UserLocalModelAdapter extends TypeAdapter { ..write(obj.token) ..writeByte(3) ..write(obj.refreshToken) - ..writeByte(4) - ..write(obj.name) ..writeByte(5) ..write(obj.module) ..writeByte(6) - ..write(obj.backend) - ..writeByte(7) - ..write(obj.apiKey); + ..write(obj.backend); } @override diff --git a/packages/core/lib/data/services/token_storage_service.dart b/packages/core/lib/data/services/token_storage_service.dart index a5fb162..0755272 100644 --- a/packages/core/lib/data/services/token_storage_service.dart +++ b/packages/core/lib/data/services/token_storage_service.dart @@ -5,6 +5,7 @@ import 'package:rasadyar_core/hive_registrar.g.dart'; class TokenStorageService extends GetxService { static const String _tokenBoxName = 'TokenBox'; + static const String _userPassBox = 'UserPassBox'; static const String _appBoxName = 'AppBox'; static const String _accessTokenKey = 'accessToken'; static const String _refreshTokenKey = 'refreshToken'; @@ -21,7 +22,6 @@ class TokenStorageService extends GetxService { Rxn appModule = Rxn(null); Future init() async { - Hive.registerAdapters(); final String? encryptedKey = await _secureStorage.read(key: 'hive_enc_key'); @@ -36,6 +36,7 @@ class TokenStorageService extends GetxService { await _localStorage.init(); await _localStorage.openBox(_tokenBoxName, encryptionCipher: HiveAesCipher(encryptionKey)); await _localStorage.openBox(_appBoxName); + await _localStorage.openBox(_userPassBox); accessToken.value = _localStorage.read(boxName: _tokenBoxName, key: _accessTokenKey); refreshToken.value = _localStorage.read(boxName: _tokenBoxName, key: _refreshTokenKey); @@ -88,4 +89,18 @@ class TokenStorageService extends GetxService { Future saveApiKey(String key) async { await _localStorage.save(boxName: _tokenBoxName, key: _apiKey, value: key); } + + Future saveUserPass(UserLocalModel model) async { + await _localStorage.save( + boxName: _userPassBox, + key: model.module!.name, + value: model, + ); + } + + UserLocalModel? getUserPass(Module module) { + return _localStorage + .readBox(boxName: _userPassBox) + ?.firstWhereOrNull((element) => element.module == module); + } } diff --git a/packages/core/lib/presentation/utils/list_extensions.dart b/packages/core/lib/presentation/utils/list_extensions.dart index b97cced..621e529 100644 --- a/packages/core/lib/presentation/utils/list_extensions.dart +++ b/packages/core/lib/presentation/utils/list_extensions.dart @@ -1,4 +1,4 @@ -extension ListExtensions on List { +extension AppListExtensions on List { void toggle(T item) { if (contains(item)) { diff --git a/packages/core/pubspec.lock b/packages/core/pubspec.lock index b220691..c191946 100644 --- a/packages/core/pubspec.lock +++ b/packages/core/pubspec.lock @@ -202,7 +202,7 @@ packages: source: hosted version: "4.10.1" collection: - dependency: transitive + dependency: "direct main" description: name: collection sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" diff --git a/packages/core/pubspec.yaml b/packages/core/pubspec.yaml index 620200e..88331f2 100644 --- a/packages/core/pubspec.yaml +++ b/packages/core/pubspec.yaml @@ -62,6 +62,7 @@ dependencies: permission_handler: ^12.0.1 persian_datetime_picker: ^3.1.1 encrypt: ^5.0.3 + collection: ^1.19.1 #L10N tools intl: ^0.20.2