mirror of
https://github.com/immich-app/immich.git
synced 2025-01-01 08:31:59 +00:00
Implemented auto backup (#11)
This commit is contained in:
parent
2a4d4ea999
commit
919928ab70
7 changed files with 10715 additions and 31 deletions
|
@ -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…
Reference in a new issue