immich/mobile/lib/utils/backup_progress.dart
shalong-tanwen deaf81e2a4
feat(mobile): Manual asset upload (#3445)
* fix: exclude albums filter in backup provider

* refactor: Separate builder methods for Top Control App Bar buttons

* fix: Show download button only for Remote only assets

* fix(mobile): Force Refresh duration is too low to trigger it consistently

* feat(mobile): Make Buttons dynamic in Home Selection DraggableScrollableSheet

* feat(mobile): Manual Asset upload

* refactor(mobile): Replace _showToast with ImmichToast calls

* refactor(mobile): home_page selectionAssetState handling

* chore(mobile): min and initial size of DraggableScrollState increased

This is to prevent the buttons in the bottom sheet getting clipped behind the 3 way navigation buttons
in the default density of Android devices

* feat(mobile): notifications for manual upload progress

* wording

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
2023-08-06 02:40:50 +00:00

70 lines
1.9 KiB
Dart

import 'dart:async';
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
final NumberFormat numberFormat = NumberFormat("###0.##");
String formatAssetBackupProgress(int uploadedAssets, int assetsToUpload) {
final int percent = (uploadedAssets * 100) ~/ assetsToUpload;
return "$percent% ($uploadedAssets/$assetsToUpload)";
}
/// prints percentage and absolute progress in useful (kilo/mega/giga)bytes
String humanReadableBytesProgress(int bytes, int bytesTotal) {
String unit = "KB"; // Kilobyte
if (bytesTotal >= 0x40000000) {
unit = "GB"; // Gigabyte
bytes >>= 20;
bytesTotal >>= 20;
} else if (bytesTotal >= 0x100000) {
unit = "MB"; // Megabyte
bytes >>= 10;
bytesTotal >>= 10;
} else if (bytesTotal < 0x400) {
return "$bytes / $bytesTotal B";
}
final int percent = (bytes * 100) ~/ bytesTotal;
final String done = numberFormat.format(bytes / 1024.0);
final String total = numberFormat.format(bytesTotal / 1024.0);
return "$percent% ($done/$total$unit)";
}
class ThrottleProgressUpdate {
ThrottleProgressUpdate(this._fun, Duration interval)
: _interval = interval.inMicroseconds;
final void Function(String?, int, int) _fun;
final int _interval;
int _invokedAt = 0;
Timer? _timer;
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;
this.title = title ?? this.title;
this.progress = progress;
this.total = total;
if (time > _invokedAt + _interval) {
_timer?.cancel();
_onTimeElapsed();
} else {
_timer ??= Timer(Duration(microseconds: _interval), _onTimeElapsed);
}
}
void _onTimeElapsed() {
_invokedAt = Timeline.now;
_fun(title, progress, total);
_timer = null;
// clear title to not send/overwrite it next time if unchanged
title = null;
}
}