diff --git a/mobile/lib/providers/background_sync.provider.dart b/mobile/lib/providers/background_sync.provider.dart index a61cd93022..5d6a2f0f4d 100644 --- a/mobile/lib/providers/background_sync.provider.dart +++ b/mobile/lib/providers/background_sync.provider.dart @@ -5,16 +5,21 @@ import 'package:immich_mobile/providers/sync_status.provider.dart'; final backgroundSyncProvider = Provider((ref) { final syncStatusNotifier = ref.read(syncStatusProvider.notifier); - final backupProvider = ref.read(driftBackupProvider.notifier); final manager = BackgroundSyncManager( onRemoteSyncStart: () { syncStatusNotifier.startRemoteSync(); - backupProvider.updateError(BackupError.none); + final backupProvider = ref.read(driftBackupProvider.notifier); + if (backupProvider.mounted) { + backupProvider.updateError(BackupError.none); + } }, onRemoteSyncComplete: (isSuccess) { syncStatusNotifier.completeRemoteSync(); - backupProvider.updateError(isSuccess == true ? BackupError.none : BackupError.syncFailed); + final backupProvider = ref.read(driftBackupProvider.notifier); + if (backupProvider.mounted) { + backupProvider.updateError(isSuccess == true ? BackupError.none : BackupError.syncFailed); + } }, onRemoteSyncError: syncStatusNotifier.errorRemoteSync, onLocalSyncStart: syncStatusNotifier.startLocalSync, diff --git a/mobile/lib/providers/backup/drift_backup.provider.dart b/mobile/lib/providers/backup/drift_backup.provider.dart index f52fc654f2..ec427613f1 100644 --- a/mobile/lib/providers/backup/drift_backup.provider.dart +++ b/mobile/lib/providers/backup/drift_backup.provider.dart @@ -212,8 +212,8 @@ class DriftBackupNotifier extends StateNotifier { ), ) { { - _uploadService.taskStatusStream.listen(_handleTaskStatusUpdate); - _uploadService.taskProgressStream.listen(_handleTaskProgressUpdate); + _statusSubscription = _uploadService.taskStatusStream.listen(_handleTaskStatusUpdate); + _progressSubscription = _uploadService.taskProgressStream.listen(_handleTaskProgressUpdate); } } @@ -224,6 +224,10 @@ class DriftBackupNotifier extends StateNotifier { /// Remove upload item from state void _removeUploadItem(String taskId) { + if (!mounted) { + _logger.warning("Skip _removeUploadItem: notifier disposed"); + return; + } if (state.uploadItems.containsKey(taskId)) { final updatedItems = Map.from(state.uploadItems); updatedItems.remove(taskId); @@ -232,6 +236,10 @@ class DriftBackupNotifier extends StateNotifier { } void _handleTaskStatusUpdate(TaskStatusUpdate update) { + if (!mounted) { + _logger.warning("Skip _handleTaskStatusUpdate: notifier disposed"); + return; + } final taskId = update.task.taskId; switch (update.status) { @@ -291,6 +299,10 @@ class DriftBackupNotifier extends StateNotifier { } void _handleTaskProgressUpdate(TaskProgressUpdate update) { + if (!mounted) { + _logger.warning("Skip _handleTaskProgressUpdate: notifier disposed"); + return; + } final taskId = update.task.taskId; final filename = update.task.displayName; final progress = update.progress; @@ -332,7 +344,15 @@ class DriftBackupNotifier extends StateNotifier { } Future getBackupStatus(String userId) async { + if (!mounted) { + _logger.warning("Skip getBackupStatus (pre-call): notifier disposed"); + return; + } final counts = await _uploadService.getBackupCounts(userId); + if (!mounted) { + _logger.warning("Skip getBackupStatus (post-call): notifier disposed"); + return; + } state = state.copyWith( totalCount: counts.total, @@ -343,6 +363,10 @@ class DriftBackupNotifier extends StateNotifier { } void updateError(BackupError error) async { + if (!mounted) { + _logger.warning("Skip updateError: notifier disposed"); + return; + } state = state.copyWith(error: error); } @@ -360,10 +384,18 @@ class DriftBackupNotifier extends StateNotifier { } Future cancel() async { + if (!mounted) { + _logger.warning("Skip cancel (pre-call): notifier disposed"); + return; + } dPrint(() => "Canceling backup tasks..."); state = state.copyWith(enqueueCount: 0, enqueueTotalCount: 0, isCanceling: true, error: BackupError.none); final activeTaskCount = await _uploadService.cancelBackup(); + if (!mounted) { + _logger.warning("Skip cancel (post-call): notifier disposed"); + return; + } if (activeTaskCount > 0) { dPrint(() => "$activeTaskCount tasks left, continuing to cancel..."); @@ -376,9 +408,17 @@ class DriftBackupNotifier extends StateNotifier { } Future handleBackupResume(String userId) async { + if (!mounted) { + _logger.warning("Skip handleBackupResume (pre-call): notifier disposed"); + return; + } _logger.info("Resuming backup tasks..."); state = state.copyWith(error: BackupError.none); final tasks = await _uploadService.getActiveTasks(kBackupGroup); + if (!mounted) { + _logger.warning("Skip handleBackupResume (post-call): notifier disposed"); + return; + } _logger.info("Found ${tasks.length} tasks"); if (tasks.isEmpty) {