import 'dart:io'; import 'package:background_downloader/background_downloader.dart'; import 'package:flutter/foundation.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/extensions/string_extensions.dart'; import 'package:immich_mobile/models/upload/share_intent_attachment.model.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/services/share_intent_service.dart'; import 'package:immich_mobile/services/upload.service.dart'; final shareIntentUploadProvider = StateNotifierProvider< ShareIntentUploadStateNotifier, List>( ((ref) => ShareIntentUploadStateNotifier( ref.watch(appRouterProvider), ref.watch(uploadServiceProvider), ref.watch(shareIntentServiceProvider), )), ); class ShareIntentUploadStateNotifier extends StateNotifier> { final AppRouter router; final UploadService _uploadService; final ShareIntentService _shareIntentService; ShareIntentUploadStateNotifier( this.router, this._uploadService, this._shareIntentService, ) : super([]) { _uploadService.onUploadStatus = _uploadStatusCallback; _uploadService.onTaskProgress = _taskProgressCallback; } void init() { _shareIntentService.onSharedMedia = onSharedMedia; _shareIntentService.init(); } void onSharedMedia(List attachments) { router.removeWhere((route) => route.name == "ShareIntentRoute"); clearAttachments(); addAttachments(attachments); router.push(ShareIntentRoute(attachments: attachments)); } void addAttachments(List attachments) { if (attachments.isEmpty) { return; } state = [...state, ...attachments]; } void removeAttachment(ShareIntentAttachment attachment) { final updatedState = state.where((element) => element != attachment).toList(); if (updatedState.length != state.length) { state = updatedState; } } void clearAttachments() { if (state.isEmpty) { return; } state = []; } void _updateUploadStatus(TaskStatusUpdate task, TaskStatus status) async { if (status == TaskStatus.canceled) { return; } final taskId = task.task.taskId; final uploadStatus = switch (task.status) { TaskStatus.complete => UploadStatus.complete, TaskStatus.failed => UploadStatus.failed, TaskStatus.canceled => UploadStatus.canceled, TaskStatus.enqueued => UploadStatus.enqueued, TaskStatus.running => UploadStatus.running, TaskStatus.paused => UploadStatus.paused, TaskStatus.notFound => UploadStatus.notFound, TaskStatus.waitingToRetry => UploadStatus.waitingtoRetry }; state = [ for (final attachment in state) if (attachment.id == taskId.toInt()) attachment.copyWith(status: uploadStatus) else attachment, ]; } void _uploadStatusCallback(TaskStatusUpdate update) { _updateUploadStatus(update, update.status); switch (update.status) { case TaskStatus.complete: if (update.responseStatusCode == 200) { if (kDebugMode) { debugPrint("[COMPLETE] ${update.task.taskId} - DUPLICATE"); } } else { if (kDebugMode) { debugPrint("[COMPLETE] ${update.task.taskId}"); } } break; default: break; } } void _taskProgressCallback(TaskProgressUpdate update) { // Ignore if the task is canceled or completed if (update.progress == downloadFailed || update.progress == downloadCompleted) { return; } final taskId = update.task.taskId; state = [ for (final attachment in state) if (attachment.id == taskId.toInt()) attachment.copyWith(uploadProgress: update.progress) else attachment, ]; } Future upload(File file) { return _uploadService.upload(file); } Future cancelUpload(String id) { return _uploadService.cancelUpload(id); } }