Files
Qlyra/lib/backend/modules/upload_manager.dart
T

104 lines
3.0 KiB
Dart

import 'dart:async';
import 'dart:io';
import '../../main.dart';
import 'cloud_storage.dart';
import 'file_uploader.dart';
import 'upload_notification_service.dart';
class UploadManager {
UploadManager._();
static final instance = UploadManager._();
StreamSubscription<UploadEvent>? _sub;
bool get isActive => _sub != null;
// UI callbacks — registered by the screen while it is mounted
void Function(double progress, int speedBps)? onProgress;
void Function(CloudFile file)? onDone;
void Function(String error)? onError;
Future<void> start({
required int chatId,
required int accountId,
required File file,
required String filename,
required int totalSize,
}) async {
await cancel(); // cancel any previous upload
await UploadNotificationService.start(filename);
var lastSentBytes = 0;
var lastSpeedMs = DateTime.now().millisecondsSinceEpoch;
var speedBps = 0;
var lastNotifPercent = -1;
_sub = fileUploader
.upload(
chatId: chatId,
file: file,
filename: filename,
totalSize: totalSize,
)
.listen(
(event) async {
switch (event) {
case UploadProgress(:final sent, :final total):
final progress = total > 0 ? sent / total : 0.0;
// Speed: recompute every 500 ms
final nowMs = DateTime.now().millisecondsSinceEpoch;
final elapsed = nowMs - lastSpeedMs;
if (elapsed >= 500) {
speedBps = ((sent - lastSentBytes) * 1000 / elapsed).round();
lastSentBytes = sent;
lastSpeedMs = nowMs;
}
onProgress?.call(progress, speedBps);
// Throttle notification to once per 1% change
final percent = total > 0 ? (sent * 100 ~/ total) : 0;
if (percent != lastNotifPercent) {
lastNotifPercent = percent;
UploadNotificationService.update(
filename: filename,
progressPercent: percent,
speedBps: speedBps,
);
}
case UploadDone(:final fileId):
_sub = null;
UploadNotificationService.stop();
final newest = await CloudStorageModule.fetchLatestFile(
messagesModule,
accountId,
chatId,
expectedFileId: fileId,
);
if (newest != null) {
onDone?.call(newest);
}
case UploadError(:final message):
_sub = null;
UploadNotificationService.stop();
onError?.call(message);
}
},
onError: (_) {
_sub = null;
UploadNotificationService.stop();
},
);
}
Future<void> cancel() async {
await _sub?.cancel();
_sub = null;
await UploadNotificationService.stop();
}
}