1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-22 01:47:08 +02:00

Implemented remembering login data with radio button (#126)

This commit is contained in:
Alex 2022-04-24 21:33:10 -05:00 committed by GitHub
parent c1ccf026f0
commit da9eb61532
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 20 deletions

View File

@ -3,9 +3,9 @@ const String userInfoBox = "immichBoxUserInfo"; // Box
const String accessTokenKey = "immichBoxAccessTokenKey"; // Key 1 const String accessTokenKey = "immichBoxAccessTokenKey"; // Key 1
const String deviceIdKey = 'immichBoxDeviceIdKey'; // Key 2 const String deviceIdKey = 'immichBoxDeviceIdKey'; // Key 2
// SERVER ENDPOINT // Server endpoint
const String serverEndpointKey = 'immichBoxServerEndpoint'; const String serverEndpointKey = 'immichBoxServerEndpoint';
// KEY // Login Info
const String hiveAllAsssetKey = "allAssets"; const String hiveLoginInfoBox = "immichLoginInfoBox";
const String hiveBackupProgressKey = "backupProgressAssets"; const String savedLoginInfoKey = "immichSavedLoginInfoKey";

View File

@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_flutter/hive_flutter.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/immich_colors.dart'; import 'package:immich_mobile/constants/immich_colors.dart';
import 'package:immich_mobile/modules/login/models/hive_saved_login_info.model.dart';
import 'package:immich_mobile/shared/providers/asset.provider.dart'; import 'package:immich_mobile/shared/providers/asset.provider.dart';
import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/routing/tab_navigation_observer.dart'; import 'package:immich_mobile/routing/tab_navigation_observer.dart';
@ -15,7 +16,9 @@ import 'constants/hive_box.dart';
void main() async { void main() async {
await Hive.initFlutter(); await Hive.initFlutter();
Hive.registerAdapter(HiveSavedLoginInfoAdapter());
await Hive.openBox(userInfoBox); await Hive.openBox(userInfoBox);
await Hive.openBox<HiveSavedLoginInfo>(hiveLoginInfoBox);
SystemChrome.setSystemUIOverlayStyle( SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle( const SystemUiOverlayStyle(

View File

@ -0,0 +1,20 @@
import 'package:hive/hive.dart';
part 'hive_saved_login_info.model.g.dart';
@HiveType(typeId: 0)
class HiveSavedLoginInfo {
@HiveField(0)
String email;
@HiveField(1)
String password;
@HiveField(2)
String serverUrl;
@HiveField(3)
bool isSaveLogin;
HiveSavedLoginInfo({required this.email, required this.password, required this.serverUrl, required this.isSaveLogin});
}

View File

@ -4,6 +4,7 @@ import 'package:hive/hive.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/hive_box.dart'; import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/modules/login/models/authentication_state.model.dart'; import 'package:immich_mobile/modules/login/models/authentication_state.model.dart';
import 'package:immich_mobile/modules/login/models/hive_saved_login_info.model.dart';
import 'package:immich_mobile/modules/login/models/login_response.model.dart'; import 'package:immich_mobile/modules/login/models/login_response.model.dart';
import 'package:immich_mobile/shared/services/backup.service.dart'; import 'package:immich_mobile/shared/services/backup.service.dart';
import 'package:immich_mobile/shared/services/device_info.service.dart'; import 'package:immich_mobile/shared/services/device_info.service.dart';
@ -36,7 +37,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
final BackupService _backupService = BackupService(); final BackupService _backupService = BackupService();
final NetworkService _networkService = NetworkService(); final NetworkService _networkService = NetworkService();
Future<bool> login(String email, String password, String serverEndpoint) async { Future<bool> login(String email, String password, String serverEndpoint, bool isSavedLoginInfo) async {
// Store server endpoint to Hive and test endpoint // Store server endpoint to Hive and test endpoint
if (serverEndpoint[serverEndpoint.length - 1] == "/") { if (serverEndpoint[serverEndpoint.length - 1] == "/") {
var validUrl = serverEndpoint.substring(0, serverEndpoint.length - 1); var validUrl = serverEndpoint.substring(0, serverEndpoint.length - 1);
@ -76,6 +77,20 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
userId: payload.userId, userId: payload.userId,
userEmail: payload.userEmail, userEmail: payload.userEmail,
); );
if (isSavedLoginInfo) {
// Save login info to local storage
Hive.box<HiveSavedLoginInfo>(hiveLoginInfoBox).put(
savedLoginInfoKey,
HiveSavedLoginInfo(
email: email,
password: password,
isSaveLogin: true,
serverUrl: Hive.box(userInfoBox).get(serverEndpointKey)),
);
} else {
Hive.box<HiveSavedLoginInfo>(hiveLoginInfoBox).delete(savedLoginInfoKey);
}
} catch (e) { } catch (e) {
return false; return false;
} }

View File

@ -1,7 +1,10 @@
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hive/hive.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/modules/login/models/hive_saved_login_info.model.dart';
import 'package:immich_mobile/shared/providers/asset.provider.dart'; import 'package:immich_mobile/shared/providers/asset.provider.dart';
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart'; import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
import 'package:immich_mobile/shared/providers/backup.provider.dart'; import 'package:immich_mobile/shared/providers/backup.provider.dart';
@ -12,22 +15,36 @@ class LoginForm extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final usernameController = useTextEditingController(text: 'testuser@email.com'); final usernameController = useTextEditingController.fromValue(TextEditingValue.empty);
final passwordController = useTextEditingController(text: 'password'); final passwordController = useTextEditingController.fromValue(TextEditingValue.empty);
final serverEndpointController = useTextEditingController(text: 'http://192.168.1.216:2283'); final serverEndpointController = useTextEditingController(text: 'http://your-server-ip:2283');
final isSaveLoginInfo = useState<bool>(false);
useEffect(() {
var loginInfo = Hive.box<HiveSavedLoginInfo>(hiveLoginInfoBox).get(savedLoginInfoKey);
if (loginInfo != null) {
usernameController.text = loginInfo.email;
passwordController.text = loginInfo.password;
serverEndpointController.text = loginInfo.serverUrl;
isSaveLoginInfo.value = loginInfo.isSaveLogin;
}
return null;
}, []);
return Center( return Center(
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 300), constraints: const BoxConstraints(maxWidth: 300),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Wrap( child: Wrap(
spacing: 32, spacing: 16,
runSpacing: 32, runSpacing: 16,
alignment: WrapAlignment.center, alignment: WrapAlignment.center,
children: [ children: [
const Image( const Image(
image: AssetImage('assets/immich-logo-no-outline.png'), image: AssetImage('assets/immich-logo-no-outline.png'),
width: 128, width: 100,
filterQuality: FilterQuality.high, filterQuality: FilterQuality.high,
), ),
Text( Text(
@ -42,10 +59,29 @@ class LoginForm extends HookConsumerWidget {
EmailInput(controller: usernameController), EmailInput(controller: usernameController),
PasswordInput(controller: passwordController), PasswordInput(controller: passwordController),
ServerEndpointInput(controller: serverEndpointController), ServerEndpointInput(controller: serverEndpointController),
CheckboxListTile(
activeColor: Theme.of(context).primaryColor,
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
dense: true,
side: const BorderSide(color: Colors.grey, width: 1.5),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
enableFeedback: true,
title: const Text(
"Save login",
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.grey),
),
value: isSaveLoginInfo.value,
onChanged: (switchValue) {
if (switchValue != null) {
isSaveLoginInfo.value = switchValue;
}
},
),
LoginButton( LoginButton(
emailController: usernameController, emailController: usernameController,
passwordController: passwordController, passwordController: passwordController,
serverEndpointController: serverEndpointController, serverEndpointController: serverEndpointController,
isSavedLoginInfo: isSaveLoginInfo.value,
), ),
], ],
), ),
@ -104,29 +140,34 @@ class LoginButton extends ConsumerWidget {
final TextEditingController emailController; final TextEditingController emailController;
final TextEditingController passwordController; final TextEditingController passwordController;
final TextEditingController serverEndpointController; final TextEditingController serverEndpointController;
final bool isSavedLoginInfo;
const LoginButton( const LoginButton({
{Key? key, Key? key,
required this.emailController, required this.emailController,
required this.passwordController, required this.passwordController,
required this.serverEndpointController}) required this.serverEndpointController,
: super(key: key); required this.isSavedLoginInfo,
}) : super(key: key);
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
return ElevatedButton( return ElevatedButton(
style: ButtonStyle(
visualDensity: VisualDensity.standard,
padding: MaterialStateProperty.all<EdgeInsets>(const EdgeInsets.symmetric(vertical: 10, horizontal: 25)),
),
onPressed: () async { onPressed: () async {
// This will remove current cache asset state of previous user login. // This will remove current cache asset state of previous user login.
ref.watch(assetProvider.notifier).clearAllAsset(); ref.watch(assetProvider.notifier).clearAllAsset();
var isAuthenticated = await ref var isAuthenticated = await ref
.read(authenticationProvider.notifier) .read(authenticationProvider.notifier)
.login(emailController.text, passwordController.text, serverEndpointController.text); .login(emailController.text, passwordController.text, serverEndpointController.text, isSavedLoginInfo);
if (isAuthenticated) { if (isAuthenticated) {
// Resume backup (if enable) then navigate // Resume backup (if enable) then navigate
ref.watch(backupProvider.notifier).resumeBackup(); ref.watch(backupProvider.notifier).resumeBackup();
// AutoRouter.of(context).pushNamed("/home-page");
AutoRouter.of(context).pushNamed("/tab-controller-page"); AutoRouter.of(context).pushNamed("/tab-controller-page");
} else { } else {
ImmichToast.show( ImmichToast.show(
@ -136,6 +177,9 @@ class LoginButton extends ConsumerWidget {
); );
} }
}, },
child: const Text("Login")); child: const Text(
"Login",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
));
} }
} }