1
0
mirror of https://github.com/immich-app/immich.git synced 2025-10-31 00:18:28 +02:00
This commit is contained in:
Alex
2025-07-16 22:18:50 -05:00
parent dfcf3f6cec
commit 2e1a94645a
10 changed files with 77 additions and 41 deletions

View File

@@ -93,6 +93,13 @@ Future<void> initApp() async {
initializeTimeZones();
// Initialize the file downloader
await FileDownloader().configure(
// maxConcurrent: 5, maxConcurrentByHost: 2, maxConcurrentByGroup: 3
globalConfig: (Config.holdingQueue, (5, 2, 3)),
);
await FileDownloader().trackTasksInGroup(
downloadGroupLivePhoto,
markDownloadedComplete: false,

View File

@@ -20,7 +20,7 @@ class DriftBackupPage extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
useEffect(
() {
ref.read(expBackupProvider.notifier).getBackupStatus();
ref.read(driftBackupProvider.notifier).getBackupStatus();
return null;
},
[],
@@ -34,7 +34,7 @@ class DriftBackupPage extends HookConsumerWidget {
child: Column(
children: [
ElevatedButton(
onPressed: () => ref.read(expBackupProvider.notifier).backup(),
onPressed: () => ref.read(driftBackupProvider.notifier).backup(),
child: const Text(
"backup_controller_page_start_backup",
style: TextStyle(
@@ -44,7 +44,7 @@ class DriftBackupPage extends HookConsumerWidget {
).tr(),
),
OutlinedButton(
onPressed: () => ref.read(expBackupProvider.notifier).cancel(),
onPressed: () => ref.read(driftBackupProvider.notifier).cancel(),
child: const Text(
"cancel",
style: TextStyle(
@@ -55,7 +55,7 @@ class DriftBackupPage extends HookConsumerWidget {
),
OutlinedButton(
onPressed: () =>
ref.read(expBackupProvider.notifier).getDataInfo(),
ref.read(driftBackupProvider.notifier).getDataInfo(),
child: const Text(
"Get database info",
style: TextStyle(
@@ -65,7 +65,17 @@ class DriftBackupPage extends HookConsumerWidget {
).tr(),
),
ElevatedButton(
onPressed: () => ref.read(expBackupProvider.notifier).resume(),
onPressed: () => ref.read(driftBackupProvider.notifier).pause(),
child: const Text(
"Pause",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
).tr(),
),
ElevatedButton(
onPressed: () => ref.read(driftBackupProvider.notifier).resume(),
child: const Text(
"Resume",
style: TextStyle(
@@ -125,7 +135,6 @@ class DriftBackupPage extends HookConsumerWidget {
const RemainderCard(),
const Divider(),
buildControlButtons(),
// const CurrentUploadingAssetInfoBox(),
],
),
),
@@ -243,7 +252,7 @@ class BackupAlbumSelectionCard extends ConsumerWidget {
trailing: ElevatedButton(
onPressed: () async {
await context.pushRoute(const DriftBackupAlbumSelectionRoute());
ref.read(expBackupProvider.notifier).getBackupStatus();
ref.read(driftBackupProvider.notifier).getBackupStatus();
},
child: const Text(
"select",
@@ -262,7 +271,8 @@ class TotalCard extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final totalCount = ref.watch(expBackupProvider.select((p) => p.totalCount));
final totalCount =
ref.watch(driftBackupProvider.select((p) => p.totalCount));
return BackupInfoCard(
title: "total".tr(),
@@ -278,7 +288,7 @@ class BackupCard extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final backupCount =
ref.watch(expBackupProvider.select((p) => p.backupCount));
ref.watch(driftBackupProvider.select((p) => p.backupCount));
return BackupInfoCard(
title: "backup_controller_page_backup".tr(),
@@ -294,7 +304,7 @@ class RemainderCard extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final remainderCount =
ref.watch(expBackupProvider.select((p) => p.remainderCount));
ref.watch(driftBackupProvider.select((p) => p.remainderCount));
return BackupInfoCard(
title: "backup_controller_page_remainder".tr(),
subtitle: "backup_controller_page_remainder_sub".tr(),

View File

@@ -1,5 +1,6 @@
import 'dart:async';
import 'package:background_downloader/background_downloader.dart';
import 'package:flutter/foundation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/services/log.service.dart';
@@ -64,6 +65,8 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
}
await _ref.read(serverInfoProvider.notifier).getServerVersion();
await FileDownloader().start();
}
switch (_ref.read(tabProvider)) {

View File

@@ -154,7 +154,7 @@ class DriftBackupState {
}
}
final expBackupProvider =
final driftBackupProvider =
StateNotifierProvider<ExpBackupNotifier, DriftBackupState>((ref) {
return ExpBackupNotifier(
ref.watch(driftBackupServiceProvider),
@@ -188,6 +188,9 @@ class ExpBackupNotifier extends StateNotifier<DriftBackupState> {
void _handleTaskStatusUpdate(TaskStatusUpdate update) {
switch (update.status) {
case TaskStatus.complete:
// debugPrint(
// "Task completed: ${update.task.displayName} : ${_uploadService.getActiveUploads()}",
// );
state = state.copyWith(
backupCount: state.backupCount + 1,
remainderCount: state.remainderCount - 1,
@@ -202,8 +205,6 @@ class ExpBackupNotifier extends StateNotifier<DriftBackupState> {
void _handleTaskProgressUpdate(TaskProgressUpdate update) {}
Future<void> getBackupStatus() async {
// await _backgroundSyncManager.syncRemote();
final [totalCount, backupCount, remainderCount] = await Future.wait([
_backupService.getTotalCount(),
_backupService.getBackupCount(),
@@ -241,7 +242,21 @@ class ExpBackupNotifier extends StateNotifier<DriftBackupState> {
}
Future<void> resume() async {
await FileDownloader().start();
final tasks = await FileDownloader().resumeAll(group: kBackupGroup);
if (tasks.isNotEmpty) {
debugPrint("Resumed tasks: ${tasks.length}");
} else {
debugPrint("No tasks to resume");
}
}
Future<void> pause() async {
final tasks = await FileDownloader().pauseAll(group: kBackupGroup);
if (tasks.isNotEmpty) {
debugPrint("Paused tasks: ${tasks.length}");
} else {
debugPrint("No tasks to pause");
}
}
@override

View File

@@ -176,7 +176,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
);
});
socket.on('on_upload_success', _handleOnUploadSuccess);
// socket.on('on_upload_success', _handleOnUploadSuccess);
socket.on('on_config_update', _handleOnConfigUpdate);
socket.on('on_asset_delete', _handleOnAssetDelete);
socket.on('on_asset_trash', _handleOnAssetTrash);
@@ -306,7 +306,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
}
Future<void> handlePendingChanges() async {
await _handlePendingUploaded();
// await _handlePendingUploaded();
await _handlePendingDeletes();
await _handlingPendingHidden();
await _handlePendingTrashes();

View File

@@ -9,15 +9,7 @@ class UploadRepository {
void Function(TaskProgressUpdate)? onTaskProgress;
final taskQueue = MemoryTaskQueue();
UploadRepository() {
taskQueue.minInterval = const Duration(milliseconds: 25);
taskQueue.maxConcurrent = 5;
taskQueue.maxConcurrentByHost = 5;
taskQueue.maxConcurrentByGroup = 5;
FileDownloader().addTaskQueue(taskQueue);
FileDownloader().registerCallbacks(
group: kBackupGroup,
taskStatusCallback: (update) => onUploadStatus?.call(update),
@@ -28,16 +20,10 @@ class UploadRepository {
taskStatusCallback: (update) => onUploadStatus?.call(update),
taskProgressCallback: (update) => onTaskProgress?.call(update),
);
taskQueue.enqueueErrors.listen((error) {
// Handle errors from the task queue
// You can log them or take appropriate actions
print('Task Queue Error: $error');
});
}
void enqueueAll(List<UploadTask> tasks) {
taskQueue.addAll(tasks);
FileDownloader().enqueueAll(tasks);
}
Future<void> deleteAllTrackingRecords(String group) {
@@ -49,7 +35,6 @@ class UploadRepository {
}
Future<bool> cancelAll(String group) {
taskQueue.removeTasksWithGroup(group);
return FileDownloader().cancelAll(group: group);
}

View File

@@ -23,7 +23,7 @@ import 'package:immich_mobile/pages/album/album_viewer.page.dart';
import 'package:immich_mobile/pages/albums/albums.page.dart';
import 'package:immich_mobile/pages/backup/album_preview.page.dart';
import 'package:immich_mobile/pages/backup/drift_backup_album_selection.page.dart';
import 'package:immich_mobile/pages/backup/drift_backup_controller.page.dart';
import 'package:immich_mobile/pages/backup/drift_backup.page.dart';
import 'package:immich_mobile/pages/backup/backup_album_selection.page.dart';
import 'package:immich_mobile/pages/backup/backup_controller.page.dart';
import 'package:immich_mobile/pages/backup/backup_options.page.dart';

View File

@@ -65,6 +65,7 @@ class DriftBackupService {
}
const batchSize = 100;
int count = 0;
for (int i = 0; i < candidates.length; i += batchSize) {
if (shouldCancel) {
break;
@@ -81,7 +82,11 @@ class DriftBackupService {
}
if (tasks.isNotEmpty && !shouldCancel) {
count += tasks.length;
_uploadService.enqueueTasks(tasks);
print(
"Enqueued $count/${candidates.length} tasks for backup",
);
}
}
}

View File

@@ -57,6 +57,15 @@ class UploadService {
_taskProgressController.close();
}
Future<List<Task>> getActiveUploads() async {
return await FileDownloader().allTasks(group: kBackupGroup);
}
Future<bool> hasActiveUploads() async {
final tasks = await getActiveUploads();
return tasks.isNotEmpty;
}
Future<bool> cancelUpload(String id) {
return FileDownloader().cancelTaskWithId(id);
}

View File

@@ -74,13 +74,15 @@ class ImmichSliverAppBar extends ConsumerWidget {
),
IconButton(
onPressed: () {
ref.read(backgroundSyncProvider).syncLocal(full: true);
ref.read(backgroundSyncProvider).syncRemote();
Future.delayed(
const Duration(seconds: 10),
() => ref.read(backgroundSyncProvider).hashAssets(),
);
Future.wait([
ref
.read(backgroundSyncProvider)
.syncLocal(full: true)
.then((_) {
ref.read(backgroundSyncProvider).hashAssets();
}),
ref.read(backgroundSyncProvider).syncRemote(),
]);
},
icon: const Icon(
Icons.sync,
@@ -206,7 +208,7 @@ class _BackupIndicator extends ConsumerWidget {
final badgeBackground = context.colorScheme.surfaceContainer;
return InkWell(
onTap: () => context.pushRoute(const BackupControllerRoute()),
onTap: () => context.pushRoute(const DriftBackupRoute()),
borderRadius: const BorderRadius.all(Radius.circular(12)),
child: Badge(
label: Container(