From 44284b4351dd12e5cfa940b65c3b55e1e3ec279b Mon Sep 17 00:00:00 2001 From: shenlong <139912620+shenlong-tanwen@users.noreply.github.com> Date: Mon, 29 Sep 2025 23:44:01 +0530 Subject: [PATCH] chore: do not remote sync twice in backup page (#22484) do not remote sync twice in backup page Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> --- i18n/en.json | 2 +- .../lib/pages/backup/drift_backup.page.dart | 29 +++++++++++++++---- .../backup/backup_toggle_button.widget.dart | 6 ++-- .../backup/drift_backup.provider.dart | 15 ++++++++-- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/i18n/en.json b/i18n/en.json index 72e2c77e41..e86b56be85 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -599,7 +599,7 @@ "backup_controller_page_turn_on": "Turn on foreground backup", "backup_controller_page_uploading_file_info": "Uploading file info", "backup_err_only_album": "Cannot remove the only album", - "backup_error_sync_failed": "Sync failed. Cannot start backup.", + "backup_error_sync_failed": "Sync failed. Cannot process backup.", "backup_info_card_assets": "assets", "backup_manual_cancelled": "Cancelled", "backup_manual_in_progress": "Upload already in progress. Try after sometime", diff --git a/mobile/lib/pages/backup/drift_backup.page.dart b/mobile/lib/pages/backup/drift_backup.page.dart index 9b4a79c557..5a2cab8dd6 100644 --- a/mobile/lib/pages/backup/drift_backup.page.dart +++ b/mobile/lib/pages/backup/drift_backup.page.dart @@ -31,6 +31,8 @@ class DriftBackupPage extends ConsumerStatefulWidget { } class _DriftBackupPageState extends ConsumerState { + bool? syncSuccess; + @override void initState() { super.initState(); @@ -44,7 +46,13 @@ class _DriftBackupPageState extends ConsumerState { WidgetsBinding.instance.addPostFrameCallback((_) async { await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id); - await ref.read(backgroundSyncProvider).syncRemote(); + + ref.read(driftBackupProvider.notifier).updateSyncing(true); + syncSuccess = await ref.read(backgroundSyncProvider).syncRemote(); + ref + .read(driftBackupProvider.notifier) + .updateError(syncSuccess == true ? BackupError.none : BackupError.syncFailed); + ref.read(driftBackupProvider.notifier).updateSyncing(false); if (mounted) { await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id); @@ -76,12 +84,17 @@ class _DriftBackupPageState extends ConsumerState { return; } - final syncSuccess = await backupSyncManager.syncRemote(); + if (syncSuccess == null) { + ref.read(driftBackupProvider.notifier).updateSyncing(true); + syncSuccess = await backupSyncManager.syncRemote(); + ref.read(driftBackupProvider.notifier).updateSyncing(false); + } + await backupNotifier.getBackupStatus(currentUser.id); - if (!syncSuccess) { + if (syncSuccess == false) { Logger("DriftBackupPage").warning("Remote sync did not complete successfully, skipping backup"); - await backupNotifier.updateError(BackupError.syncFailed); + backupNotifier.updateError(BackupError.syncFailed); return; } await backupNotifier.startBackup(currentUser.id); @@ -125,7 +138,13 @@ class _DriftBackupPageState extends ConsumerState { const _BackupCard(), const _RemainderCard(), const Divider(), - BackupToggleButton(onStart: () async => await startBackup(), onStop: () async => await stopBackup()), + BackupToggleButton( + onStart: () async => await startBackup(), + onStop: () async { + syncSuccess = null; + await stopBackup(); + }, + ), switch (error) { BackupError.none => const SizedBox.shrink(), BackupError.syncFailed => Padding( diff --git a/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart b/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart index a74c169224..8d374f74ff 100644 --- a/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart +++ b/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart @@ -65,7 +65,9 @@ class BackupToggleButtonState extends ConsumerState with Sin final uploadTasks = ref.watch(driftBackupProvider.select((state) => state.uploadItems)); - final isUploading = uploadTasks.isNotEmpty; + final isSyncing = ref.watch(driftBackupProvider.select((state) => state.isSyncing)); + + final isProcessing = uploadTasks.isNotEmpty || isSyncing; return AnimatedBuilder( animation: _animationController, @@ -129,7 +131,7 @@ class BackupToggleButtonState extends ConsumerState with Sin ], ), ), - child: isUploading + child: isProcessing ? const SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2)) : Icon(Icons.cloud_upload_outlined, color: context.primaryColor, size: 24), ), diff --git a/mobile/lib/providers/backup/drift_backup.provider.dart b/mobile/lib/providers/backup/drift_backup.provider.dart index 49455371fa..c045cc4f9f 100644 --- a/mobile/lib/providers/backup/drift_backup.provider.dart +++ b/mobile/lib/providers/backup/drift_backup.provider.dart @@ -109,6 +109,7 @@ class DriftBackupState { final int enqueueCount; final int enqueueTotalCount; + final bool isSyncing; final bool isCanceling; final BackupError error; @@ -122,6 +123,7 @@ class DriftBackupState { required this.enqueueCount, required this.enqueueTotalCount, required this.isCanceling, + required this.isSyncing, required this.uploadItems, this.error = BackupError.none, }); @@ -134,6 +136,7 @@ class DriftBackupState { int? enqueueCount, int? enqueueTotalCount, bool? isCanceling, + bool? isSyncing, Map? uploadItems, BackupError? error, }) { @@ -145,6 +148,7 @@ class DriftBackupState { enqueueCount: enqueueCount ?? this.enqueueCount, enqueueTotalCount: enqueueTotalCount ?? this.enqueueTotalCount, isCanceling: isCanceling ?? this.isCanceling, + isSyncing: isSyncing ?? this.isSyncing, uploadItems: uploadItems ?? this.uploadItems, error: error ?? this.error, ); @@ -152,7 +156,7 @@ class DriftBackupState { @override String toString() { - return 'DriftBackupState(totalCount: $totalCount, backupCount: $backupCount, remainderCount: $remainderCount, processingCount: $processingCount, enqueueCount: $enqueueCount, enqueueTotalCount: $enqueueTotalCount, isCanceling: $isCanceling, uploadItems: $uploadItems, error: $error)'; + return 'DriftBackupState(totalCount: $totalCount, backupCount: $backupCount, remainderCount: $remainderCount, processingCount: $processingCount, enqueueCount: $enqueueCount, enqueueTotalCount: $enqueueTotalCount, isCanceling: $isCanceling, isSyncing: $isSyncing, uploadItems: $uploadItems, error: $error)'; } @override @@ -167,6 +171,7 @@ class DriftBackupState { other.enqueueCount == enqueueCount && other.enqueueTotalCount == enqueueTotalCount && other.isCanceling == isCanceling && + other.isSyncing == isSyncing && mapEquals(other.uploadItems, uploadItems) && other.error == error; } @@ -180,6 +185,7 @@ class DriftBackupState { enqueueCount.hashCode ^ enqueueTotalCount.hashCode ^ isCanceling.hashCode ^ + isSyncing.hashCode ^ uploadItems.hashCode ^ error.hashCode; } @@ -200,6 +206,7 @@ class DriftBackupNotifier extends StateNotifier { enqueueCount: 0, enqueueTotalCount: 0, isCanceling: false, + isSyncing: false, uploadItems: {}, error: BackupError.none, ), @@ -335,10 +342,14 @@ class DriftBackupNotifier extends StateNotifier { ); } - Future updateError(BackupError error) async { + void updateError(BackupError error) async { state = state.copyWith(error: error); } + void updateSyncing(bool isSyncing) async { + state = state.copyWith(isSyncing: isSyncing); + } + Future startBackup(String userId) { state = state.copyWith(error: BackupError.none); return _uploadService.startBackup(userId, _updateEnqueueCount);