You've already forked immich
							
							
				mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 00:18:28 +02:00 
			
		
		
		
	wip
This commit is contained in:
		| @@ -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, | ||||
|   | ||||
| @@ -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(), | ||||
| @@ -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)) { | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -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); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -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'; | ||||
|   | ||||
| @@ -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", | ||||
|         ); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   | ||||
| @@ -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); | ||||
|   } | ||||
|   | ||||
| @@ -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( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user