mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:17:11 -05:00 
			
		
		
		
	Implemented auto backup (#11)
This commit is contained in:
		
							parent
							
								
									2a4d4ea999
								
							
						
					
					
						commit
						919928ab70
					
				@ -4,6 +4,7 @@ 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/routing/router.dart';
 | 
					import 'package:immich_mobile/routing/router.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/providers/app_state.provider.dart';
 | 
					import 'package:immich_mobile/shared/providers/app_state.provider.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/shared/providers/backup.provider.dart';
 | 
				
			||||||
import 'constants/hive_box.dart';
 | 
					import 'constants/hive_box.dart';
 | 
				
			||||||
import 'package:google_fonts/google_fonts.dart';
 | 
					import 'package:google_fonts/google_fonts.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,6 +37,7 @@ class _ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserv
 | 
				
			|||||||
      case AppLifecycleState.resumed:
 | 
					      case AppLifecycleState.resumed:
 | 
				
			||||||
        debugPrint("[APP STATE] resumed");
 | 
					        debugPrint("[APP STATE] resumed");
 | 
				
			||||||
        ref.read(appStateProvider.notifier).state = AppStateEnum.resumed;
 | 
					        ref.read(appStateProvider.notifier).state = AppStateEnum.resumed;
 | 
				
			||||||
 | 
					        ref.read(backupProvider.notifier).resumeBackup();
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case AppLifecycleState.inactive:
 | 
					      case AppLifecycleState.inactive:
 | 
				
			||||||
        debugPrint("[APP STATE] inactive");
 | 
					        debugPrint("[APP STATE] inactive");
 | 
				
			||||||
@ -53,7 +55,7 @@ class _ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserv
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<void> initApp() async {
 | 
					  Future<void> initApp() async {
 | 
				
			||||||
    // WidgetsBinding.instance?.addObserver(this);
 | 
					    WidgetsBinding.instance?.addObserver(this);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
 | 
				
			|||||||
@ -56,10 +56,9 @@ class ProfileDrawer extends ConsumerWidget {
 | 
				
			|||||||
            onTap: () async {
 | 
					            onTap: () async {
 | 
				
			||||||
              bool res = await ref.read(authenticationProvider.notifier).logout();
 | 
					              bool res = await ref.read(authenticationProvider.notifier).logout();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              ref.read(assetProvider.notifier).clearAllAsset();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              if (res) {
 | 
					              if (res) {
 | 
				
			||||||
                AutoRouter.of(context).popUntilRoot();
 | 
					                AutoRouter.of(context).popUntilRoot();
 | 
				
			||||||
 | 
					                ref.read(assetProvider.notifier).clearAllAsset();
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ import 'package:immich_mobile/shared/services/network.service.dart';
 | 
				
			|||||||
import 'package:immich_mobile/shared/models/device_info.model.dart';
 | 
					import 'package:immich_mobile/shared/models/device_info.model.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
 | 
					class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
 | 
				
			||||||
  AuthenticationNotifier()
 | 
					  AuthenticationNotifier(this.ref)
 | 
				
			||||||
      : super(
 | 
					      : super(
 | 
				
			||||||
          AuthenticationState(
 | 
					          AuthenticationState(
 | 
				
			||||||
            deviceId: "",
 | 
					            deviceId: "",
 | 
				
			||||||
@ -31,6 +31,7 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
 | 
				
			|||||||
          ),
 | 
					          ),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final Ref ref;
 | 
				
			||||||
  final DeviceInfoService _deviceInfoService = DeviceInfoService();
 | 
					  final DeviceInfoService _deviceInfoService = DeviceInfoService();
 | 
				
			||||||
  final BackupService _backupService = BackupService();
 | 
					  final BackupService _backupService = BackupService();
 | 
				
			||||||
  final NetworkService _networkService = NetworkService();
 | 
					  final NetworkService _networkService = NetworkService();
 | 
				
			||||||
@ -126,5 +127,5 @@ class AuthenticationNotifier extends StateNotifier<AuthenticationState> {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
final authenticationProvider = StateNotifierProvider<AuthenticationNotifier, AuthenticationState>((ref) {
 | 
					final authenticationProvider = StateNotifierProvider<AuthenticationNotifier, AuthenticationState>((ref) {
 | 
				
			||||||
  return AuthenticationNotifier();
 | 
					  return AuthenticationNotifier(ref);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,9 @@ import 'package:flutter/material.dart';
 | 
				
			|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
 | 
					import 'package:flutter_hooks/flutter_hooks.dart';
 | 
				
			||||||
import 'package:google_fonts/google_fonts.dart';
 | 
					import 'package:google_fonts/google_fonts.dart';
 | 
				
			||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/home/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/ui/immich_toast.dart';
 | 
					import 'package:immich_mobile/shared/ui/immich_toast.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LoginForm extends HookConsumerWidget {
 | 
					class LoginForm extends HookConsumerWidget {
 | 
				
			||||||
@ -110,11 +112,16 @@ class LoginButton extends ConsumerWidget {
 | 
				
			|||||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
					  Widget build(BuildContext context, WidgetRef ref) {
 | 
				
			||||||
    return ElevatedButton(
 | 
					    return ElevatedButton(
 | 
				
			||||||
        onPressed: () async {
 | 
					        onPressed: () async {
 | 
				
			||||||
 | 
					          // This will remove current cache asset state of previous user login.
 | 
				
			||||||
 | 
					          ref.watch(assetProvider.notifier).clearAllAsset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          var isAuthenicated = await ref
 | 
					          var isAuthenicated = await ref
 | 
				
			||||||
              .read(authenticationProvider.notifier)
 | 
					              .read(authenticationProvider.notifier)
 | 
				
			||||||
              .login(emailController.text, passwordController.text, serverEndpointController.text);
 | 
					              .login(emailController.text, passwordController.text, serverEndpointController.text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          if (isAuthenicated) {
 | 
					          if (isAuthenicated) {
 | 
				
			||||||
 | 
					            // Resume backup (if enable) then navigate
 | 
				
			||||||
 | 
					            ref.watch(backupProvider.notifier).resumeBackup();
 | 
				
			||||||
            AutoRouter.of(context).pushNamed("/home-page");
 | 
					            AutoRouter.of(context).pushNamed("/home-page");
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            ImmichToast.show(
 | 
					            ImmichToast.show(
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,9 @@
 | 
				
			|||||||
import 'package:dio/dio.dart';
 | 
					import 'package:dio/dio.dart';
 | 
				
			||||||
import 'package:flutter/foundation.dart';
 | 
					import 'package:flutter/foundation.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/hive_box.dart';
 | 
				
			||||||
 | 
					import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/services/server_info.service.dart';
 | 
					import 'package:immich_mobile/shared/services/server_info.service.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/models/backup_state.model.dart';
 | 
					import 'package:immich_mobile/shared/models/backup_state.model.dart';
 | 
				
			||||||
import 'package:immich_mobile/shared/models/server_info.model.dart';
 | 
					import 'package:immich_mobile/shared/models/server_info.model.dart';
 | 
				
			||||||
@ -8,7 +11,7 @@ import 'package:immich_mobile/shared/services/backup.service.dart';
 | 
				
			|||||||
import 'package:photo_manager/photo_manager.dart';
 | 
					import 'package:photo_manager/photo_manager.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BackupNotifier extends StateNotifier<BackUpState> {
 | 
					class BackupNotifier extends StateNotifier<BackUpState> {
 | 
				
			||||||
  BackupNotifier()
 | 
					  BackupNotifier(this.ref)
 | 
				
			||||||
      : super(
 | 
					      : super(
 | 
				
			||||||
          BackUpState(
 | 
					          BackUpState(
 | 
				
			||||||
            backupProgress: BackUpProgressEnum.idle,
 | 
					            backupProgress: BackUpProgressEnum.idle,
 | 
				
			||||||
@ -29,6 +32,7 @@ class BackupNotifier extends StateNotifier<BackUpState> {
 | 
				
			|||||||
          ),
 | 
					          ),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final Ref ref;
 | 
				
			||||||
  final BackupService _backupService = BackupService();
 | 
					  final BackupService _backupService = BackupService();
 | 
				
			||||||
  final ServerInfoService _serverInfoService = ServerInfoService();
 | 
					  final ServerInfoService _serverInfoService = ServerInfoService();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -96,7 +100,7 @@ class BackupNotifier extends StateNotifier<BackUpState> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  void cancelBackup() {
 | 
					  void cancelBackup() {
 | 
				
			||||||
    state.cancelToken.cancel('Cancel Backup');
 | 
					    state.cancelToken.cancel('Cancel Backup');
 | 
				
			||||||
    state = state.copyWith(backupProgress: BackUpProgressEnum.idle);
 | 
					    state = state.copyWith(backupProgress: BackUpProgressEnum.idle, progressInPercentage: 0.0);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void _onAssetUploaded() {
 | 
					  void _onAssetUploaded() {
 | 
				
			||||||
@ -130,8 +134,38 @@ class BackupNotifier extends StateNotifier<BackUpState> {
 | 
				
			|||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void resumeBackup() {
 | 
				
			||||||
 | 
					    debugPrint("[resumeBackup]");
 | 
				
			||||||
 | 
					    var authState = ref.read(authenticationProvider);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Check if user is login
 | 
				
			||||||
 | 
					    var accessKey = Hive.box(userInfoBox).get(accessTokenKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // User has been logged out return
 | 
				
			||||||
 | 
					    if (accessKey == null || !authState.isAuthenticated) {
 | 
				
			||||||
 | 
					      debugPrint("[resumeBackup] not authenticated - abort");
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Check if this device is enable backup by the user
 | 
				
			||||||
 | 
					    if ((authState.deviceInfo.deviceId == authState.deviceId) && authState.deviceInfo.isAutoBackup) {
 | 
				
			||||||
 | 
					      // check if backup is alreayd in process - then return
 | 
				
			||||||
 | 
					      if (state.backupProgress == BackUpProgressEnum.inProgress) {
 | 
				
			||||||
 | 
					        debugPrint("[resumeBackup] Backup is already in progress - abort");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Run backup
 | 
				
			||||||
 | 
					      debugPrint("[resumeBackup] Start back up");
 | 
				
			||||||
 | 
					      startBackupProcess();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    debugPrint("[resumeBackup] User disables auto backup");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
final backupProvider = StateNotifierProvider<BackupNotifier, BackUpState>((ref) {
 | 
					final backupProvider = StateNotifierProvider<BackupNotifier, BackUpState>((ref) {
 | 
				
			||||||
  return BackupNotifier();
 | 
					  return BackupNotifier(ref);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10685
									
								
								server/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10685
									
								
								server/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -44,6 +44,6 @@ import { ServerInfoModule } from './api-v1/server-info/server-info.module';
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class AppModule implements NestModule {
 | 
					export class AppModule implements NestModule {
 | 
				
			||||||
  configure(consumer: MiddlewareConsumer): void {
 | 
					  configure(consumer: MiddlewareConsumer): void {
 | 
				
			||||||
    consumer.apply(AppLoggerMiddleware).forRoutes('*');
 | 
					    // consumer.apply(AppLoggerMiddleware).forRoutes('*');
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user