From dc7df5bcfae00dcd1db91673c386fd69fa5bf918 Mon Sep 17 00:00:00 2001 From: Fynn Petersen-Frey Date: Tue, 1 Nov 2022 09:16:46 +0100 Subject: [PATCH] fix(mobile, Android): throttle all background backup notifications --- .../background.service.dart | 79 +++++++++++-------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/mobile/lib/modules/backup/background_service/background.service.dart b/mobile/lib/modules/backup/background_service/background.service.dart index 377824ec0d..ad3e35d883 100644 --- a/mobile/lib/modules/backup/background_service/background.service.dart +++ b/mobile/lib/modules/backup/background_service/background.service.dart @@ -33,6 +33,7 @@ class BackgroundService { static const MethodChannel _backgroundChannel = MethodChannel('immich/backgroundChannel'); static final NumberFormat numberFormat = NumberFormat("###0.##"); + static const notifyInterval = Duration(milliseconds: 400); bool _isBackgroundInitialized = false; CancellationToken? _cancellationToken; bool _canceledBySystem = false; @@ -43,9 +44,12 @@ class BackgroundService { bool _errorGracePeriodExceeded = true; int _uploadedAssetsCount = 0; int _assetsToUploadCount = 0; - String _lastPrintedProgress = ""; - late final _Throttle _throttleNotificationUpdates = - _Throttle(_updateDetailProgress, const Duration(milliseconds: 400)); + String _lastPrintedDetailContent = ""; + String? _lastPrintedDetailTitle; + late final _Throttle _throttledNotifiy = + _Throttle(_updateProgress, notifyInterval); + late final _Throttle _throttledDetailNotify = + _Throttle(_updateDetailProgress, notifyInterval); bool get isBackgroundInitialized { return _isBackgroundInitialized; @@ -438,33 +442,40 @@ class BackgroundService { } void _onAssetUploaded(String deviceAssetId, String deviceId, bool isDup) { - debugPrint("Uploaded $deviceAssetId from $deviceId"); _uploadedAssetsCount++; - _updateNotification( - progress: _uploadedAssetsCount, - max: _assetsToUploadCount, - content: _formatAssetBackupProgress(), - ); + _throttledNotifiy(); } void _onProgress(int sent, int total) { - _throttleNotificationUpdates(sent, total); + _throttledDetailNotify(progress: sent, total: total); } - void _updateDetailProgress(int sent, int total) { - final String msg = _humanReadableBytesProgress(sent, total); + void _updateDetailProgress(String? title, int progress, int total) { + final String msg = + total > 0 ? _humanReadableBytesProgress(progress, total) : ""; // only update if message actually differs (to stop many useless notification updates on large assets or slow connections) - if (msg != _lastPrintedProgress) { - _lastPrintedProgress = msg; + if (msg != _lastPrintedDetailContent || _lastPrintedDetailTitle != title) { + _lastPrintedDetailContent = msg; + _lastPrintedDetailTitle = title; _updateNotification( - progress: sent, - max: total, + progress: total > 0 ? (progress * 1000) ~/ total : 0, + max: 1000, isDetail: true, + title: title, content: msg, ); } } + void _updateProgress(String? title, int progress, int total) { + _updateNotification( + progress: _uploadedAssetsCount, + max: _assetsToUploadCount, + title: title, + content: _formatAssetBackupProgress(), + ); + } + void _onBackupError(ErrorUploadAsset errorAssetInfo) { _showErrorNotification( title: "backup_background_service_upload_failure_notification" @@ -474,14 +485,11 @@ class BackgroundService { } void _onSetCurrentBackupAsset(CurrentUploadAsset currentUploadAsset) { - _updateNotification( - title: "backup_background_service_current_upload_notification" - .tr(args: [currentUploadAsset.fileName]), - content: "", - isDetail: true, - progress: 0, - max: 0, - ); + _throttledDetailNotify.title = + "backup_background_service_current_upload_notification" + .tr(args: [currentUploadAsset.fileName]); + _throttledDetailNotify.progress = 0; + _throttledDetailNotify.total = 0; } bool _isErrorGracePeriodExceeded(AppSettingsService appSettingsService) { @@ -534,17 +542,24 @@ class BackgroundService { class _Throttle { _Throttle(this._fun, Duration interval) : _interval = interval.inMicroseconds; - final void Function(int, int) _fun; + final void Function(String?, int, int) _fun; final int _interval; int _invokedAt = 0; Timer? _timer; - int _progress = 0; - int _total = 0; - void call(int progress, int total) { + String? title; + int progress = 0; + int total = 0; + + void call({ + final String? title, + final int progress = 0, + final int total = 0, + }) { final time = Timeline.now; - _progress = progress; - _total = total; + this.title = title ?? this.title; + this.progress = progress; + this.total = total; if (time > _invokedAt + _interval) { _timer?.cancel(); _onTimeElapsed(); @@ -555,8 +570,10 @@ class _Throttle { void _onTimeElapsed() { _invokedAt = Timeline.now; - _fun(_progress, _total); + _fun(title, progress, total); _timer = null; + // clear title to not send/overwrite it next time if unchanged + title = null; } }