feat : remember me for chicken module
This commit is contained in:
@@ -15,7 +15,6 @@ import 'package:rasadyar_core/core.dart';
|
||||
GetIt diChicken = GetIt.instance;
|
||||
|
||||
Future<void> setupChickenDI() async {
|
||||
tLog("setup 1");
|
||||
diChicken.registerSingleton(DioErrorHandler());
|
||||
var tokenService = Get.find<TokenStorageService>();
|
||||
|
||||
@@ -52,7 +51,6 @@ Future<void> setupChickenDI() async {
|
||||
|
||||
diChicken.registerLazySingleton<AuthRepository>(
|
||||
() => AuthRepositoryImpl(diChicken.get<AuthRemoteDataSource>()),
|
||||
instanceName: 'oldRepo',
|
||||
);
|
||||
|
||||
diChicken.registerLazySingleton<ChickenRemoteDatasource>(
|
||||
@@ -95,11 +93,10 @@ Future<void> newSetupAuthDI(String newUrl) async {
|
||||
);
|
||||
}
|
||||
|
||||
if (diChicken.isRegistered<AuthRepository>(instanceName: 'oldRepo')) {
|
||||
await diChicken.unregister<AuthRepository>(instanceName: 'oldRepo');
|
||||
if (diChicken.isRegistered<AuthRepository>()) {
|
||||
await diChicken.unregister<AuthRepository>();
|
||||
diChicken.registerLazySingleton<AuthRepository>(
|
||||
() => AuthRepositoryImpl(diChicken.get<AuthRemoteDataSource>()),
|
||||
instanceName: 'newRepo',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
late AnimationController _textAnimationController;
|
||||
late Animation<double> textAnimation;
|
||||
RxBool showCard = false.obs;
|
||||
RxBool rememberMe = false.obs;
|
||||
|
||||
Rx<GlobalKey<FormState>> formKeyOtp = GlobalKey<FormState>().obs;
|
||||
Rx<GlobalKey<FormState>> formKeySentOtp = GlobalKey<FormState>().obs;
|
||||
@@ -45,7 +46,7 @@ class AuthLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
RxInt secondsRemaining = 120.obs;
|
||||
Timer? _timer;
|
||||
|
||||
AuthRepository authRepository = diChicken.get<AuthRepository>(instanceName: 'oldRepo');
|
||||
AuthRepository authRepository = diChicken.get<AuthRepository>();
|
||||
|
||||
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<void> submitLoginForm() async {
|
||||
if (!_isFormValid()) return;
|
||||
AuthRepository authTmp = diChicken.get<AuthRepository>(instanceName: 'newRepo');
|
||||
AuthRepository authTmp = diChicken.get<AuthRepository>();
|
||||
isLoading.value = true;
|
||||
await safeCall<UserProfileModel?>(
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,7 +197,28 @@ class AuthPage extends GetView<AuthLogic> {
|
||||
),
|
||||
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(
|
||||
|
||||
@@ -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<ProfileLogic> {
|
||||
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<ProfileLogic> {
|
||||
|
||||
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<ProfileLogic> {
|
||||
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<ProfileLogic> {
|
||||
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<ProfileLogic> {
|
||||
width: 40,
|
||||
height: 40,
|
||||
colorFilter:
|
||||
color ??
|
||||
color ??
|
||||
ColorFilter.mode(
|
||||
selected ? AppColor.blueNormal : AppColor.whiteLight,
|
||||
BlendMode.srcIn,
|
||||
@@ -355,8 +348,6 @@ class ProfilePage extends GetView<ProfileLogic> {
|
||||
}, controller.birthDate),
|
||||
|
||||
SizedBox(),
|
||||
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -372,8 +363,10 @@ class ProfilePage extends GetView<ProfileLogic> {
|
||||
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<ProfileLogic> {
|
||||
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<ProfileLogic> {
|
||||
Get.back();
|
||||
},
|
||||
);
|
||||
},controller.isOnLoading),
|
||||
}, controller.isOnLoading),
|
||||
ROutlinedElevated(
|
||||
height: 40.h,
|
||||
text: 'انصراف',
|
||||
@@ -618,7 +613,7 @@ class ProfilePage extends GetView<ProfileLogic> {
|
||||
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);
|
||||
});
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,17 +21,15 @@ class UserLocalModelAdapter extends TypeAdapter<UserLocalModel> {
|
||||
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<UserLocalModel> {
|
||||
..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
|
||||
|
||||
@@ -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<Module> appModule = Rxn(null);
|
||||
|
||||
Future<void> 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<UserLocalModel>(_userPassBox);
|
||||
|
||||
accessToken.value = _localStorage.read<String?>(boxName: _tokenBoxName, key: _accessTokenKey);
|
||||
refreshToken.value = _localStorage.read<String?>(boxName: _tokenBoxName, key: _refreshTokenKey);
|
||||
@@ -88,4 +89,18 @@ class TokenStorageService extends GetxService {
|
||||
Future<void> saveApiKey(String key) async {
|
||||
await _localStorage.save(boxName: _tokenBoxName, key: _apiKey, value: key);
|
||||
}
|
||||
|
||||
Future<void> saveUserPass(UserLocalModel model) async {
|
||||
await _localStorage.save<UserLocalModel>(
|
||||
boxName: _userPassBox,
|
||||
key: model.module!.name,
|
||||
value: model,
|
||||
);
|
||||
}
|
||||
|
||||
UserLocalModel? getUserPass(Module module) {
|
||||
return _localStorage
|
||||
.readBox<UserLocalModel>(boxName: _userPassBox)
|
||||
?.firstWhereOrNull((element) => element.module == module);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
extension ListExtensions<T> on List<T> {
|
||||
extension AppListExtensions<T> on List<T> {
|
||||
void toggle(T item) {
|
||||
if (contains(item)) {
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ packages:
|
||||
source: hosted
|
||||
version: "4.10.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: collection
|
||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user