fix(mobile, Android): throttle all background backup notifications

This commit is contained in:
Fynn Petersen-Frey 2022-11-01 09:16:46 +01:00
parent dcefd53bfe
commit dc7df5bcfa

View File

@ -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;
}
}