diff --git a/mobile/lib/pages/backup/drift_backup.page.dart b/mobile/lib/pages/backup/drift_backup.page.dart index b125c35908..bf9ad43f9c 100644 --- a/mobile/lib/pages/backup/drift_backup.page.dart +++ b/mobile/lib/pages/backup/drift_backup.page.dart @@ -3,6 +3,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; +import 'package:immich_mobile/domain/models/store.model.dart'; +import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; @@ -34,21 +36,6 @@ class _DriftBackupPageState extends ConsumerState { ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id); } - Future startBackup() async { - final currentUser = ref.read(currentUserProvider); - if (currentUser == null) { - return; - } - - await ref.read(backgroundSyncProvider).syncRemote(); - await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id); - await ref.read(driftBackupProvider.notifier).startBackup(currentUser.id); - } - - Future stopBackup() async { - await ref.read(driftBackupProvider.notifier).cancel(); - } - @override Widget build(BuildContext context) { final selectedAlbum = ref @@ -56,6 +43,24 @@ class _DriftBackupPageState extends ConsumerState { .where((album) => album.backupSelection == BackupSelection.selected) .toList(); + final backupNotifier = ref.read(driftBackupProvider.notifier); + final backgroundManager = ref.read(backgroundSyncProvider); + + Future startBackup() async { + final currentUser = Store.tryGet(StoreKey.currentUser); + if (currentUser == null) { + return; + } + + await backgroundManager.syncRemote(); + await backupNotifier.getBackupStatus(currentUser.id); + await backupNotifier.startBackup(currentUser.id); + } + + Future stopBackup() async { + await backupNotifier.cancel(); + } + return Scaffold( appBar: AppBar( elevation: 0, diff --git a/mobile/lib/pages/common/splash_screen.page.dart b/mobile/lib/pages/common/splash_screen.page.dart index 0bedae4242..f288464c42 100644 --- a/mobile/lib/pages/common/splash_screen.page.dart +++ b/mobile/lib/pages/common/splash_screen.page.dart @@ -6,6 +6,7 @@ import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/providers/auth.provider.dart'; import 'package:immich_mobile/providers/background_sync.provider.dart'; import 'package:immich_mobile/providers/backup/backup.provider.dart'; +import 'package:immich_mobile/providers/backup/drift_backup.provider.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/websocket.provider.dart'; @@ -22,6 +23,7 @@ class SplashScreenPage extends StatefulHookConsumerWidget { class SplashScreenPageState extends ConsumerState { final log = Logger("SplashScreenPage"); + @override void initState() { super.initState(); @@ -49,6 +51,7 @@ class SplashScreenPageState extends ConsumerState { final infoProvider = ref.read(serverInfoProvider.notifier); final wsProvider = ref.read(websocketProvider.notifier); final backgroundManager = ref.read(backgroundSyncProvider); + final backupProvider = ref.read(driftBackupProvider.notifier); ref.read(authProvider.notifier).saveAuthInfo(accessToken: accessToken).then( (_) async { @@ -57,13 +60,17 @@ class SplashScreenPageState extends ConsumerState { infoProvider.getServerInfo(); if (Store.isBetaTimelineEnabled) { - await backgroundManager.syncLocal(); - await backgroundManager.syncRemote(); - await backgroundManager.hashAssets(); - } + await Future.wait([backgroundManager.syncLocal(), backgroundManager.syncRemote()]); + await Future.wait([ + backgroundManager.hashAssets().then((_) { + _resumeBackup(backupProvider); + }), + _resumeBackup(backupProvider), + ]); - if (Store.get(StoreKey.syncAlbums, false)) { - await backgroundManager.syncLinkedAlbum(); + if (Store.get(StoreKey.syncAlbums, false)) { + await backgroundManager.syncLinkedAlbum(); + } } } catch (e) { log.severe('Failed establishing connection to the server: $e'); @@ -106,6 +113,17 @@ class SplashScreenPageState extends ConsumerState { } } + Future _resumeBackup(DriftBackupNotifier notifier) async { + final isEnableBackup = Store.get(StoreKey.enableBackup, false); + + if (isEnableBackup) { + final currentUser = Store.tryGet(StoreKey.currentUser); + if (currentUser != null) { + notifier.handleBackupResume(currentUser.id); + } + } + } + @override Widget build(BuildContext context) { return const Scaffold( diff --git a/mobile/lib/providers/app_life_cycle.provider.dart b/mobile/lib/providers/app_life_cycle.provider.dart index e5a26272b0..b7f1b9ebb2 100644 --- a/mobile/lib/providers/app_life_cycle.provider.dart +++ b/mobile/lib/providers/app_life_cycle.provider.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/services/log.service.dart'; import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/models/backup/backup_state.model.dart'; @@ -18,7 +19,6 @@ import 'package:immich_mobile/providers/memory.provider.dart'; import 'package:immich_mobile/providers/notification_permission.provider.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/tab.provider.dart'; -import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/providers/websocket.provider.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/services/background.service.dart'; @@ -144,32 +144,42 @@ class AppLifeCycleNotifier extends StateNotifier { final backgroundManager = _ref.read(backgroundSyncProvider); final isAlbumLinkedSyncEnable = _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.syncAlbums); - final isEnableBackup = _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup); try { - // Run operations sequentially with state checks and error handling for each - await _safeRun(backgroundManager.syncLocal(), "syncLocal"); - await _safeRun(backgroundManager.syncRemote(), "syncRemote"); - await _safeRun(backgroundManager.hashAssets(), "hashAssets"); + await Future.wait([ + _safeRun(backgroundManager.syncLocal(), "syncLocal"), + _safeRun(backgroundManager.syncRemote(), "syncRemote"), + ]); + + await Future.wait([ + _safeRun(backgroundManager.hashAssets(), "hashAssets").then((_) { + _resumeBackup(); + }), + _resumeBackup(), + ]); + if (isAlbumLinkedSyncEnable) { await _safeRun(backgroundManager.syncLinkedAlbum(), "syncLinkedAlbum"); } - - // Handle backup resume only if still active - if (isEnableBackup) { - final currentUser = _ref.read(currentUserProvider); - if (currentUser != null) { - await _safeRun( - _ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id), - "handleBackupResume", - ); - } - } } catch (e, stackTrace) { _log.severe("Error during background sync", e, stackTrace); } } + Future _resumeBackup() async { + final isEnableBackup = _ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup); + + if (isEnableBackup) { + final currentUser = Store.tryGet(StoreKey.currentUser); + if (currentUser != null) { + await _safeRun( + _ref.read(driftBackupProvider.notifier).handleBackupResume(currentUser.id), + "handleBackupResume", + ); + } + } + } + // Helper method to check if operations should continue bool _shouldContinueOperation() { return [AppLifeCycleEnum.resumed, AppLifeCycleEnum.active].contains(state) &&