diff --git a/lib/app.dart b/lib/app.dart index b8f4b2a..2e1e771 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -90,6 +90,7 @@ class _AppState extends State with WidgetsBindingObserver { } else if (state == AppLifecycleState.paused) { wasPaused = true; globalIsAppInBackground = true; + handleUploadWhenAppGoesBackground(); } } diff --git a/lib/src/services/api/media_upload.dart b/lib/src/services/api/media_upload.dart index 60b117e..e16fdcd 100644 --- a/lib/src/services/api/media_upload.dart +++ b/lib/src/services/api/media_upload.dart @@ -447,6 +447,8 @@ Future handleUploadStatusUpdate(TaskStatusUpdate update) async { Future handleUploadSuccess(MediaUpload media) async { Log.info("Upload of ${media.mediaUploadId} success!"); + currentUploadTasks.remove(media.mediaUploadId); + await twonlyDB.mediaUploadsDao.updateMediaUpload( media.mediaUploadId, MediaUploadsCompanion( @@ -596,35 +598,63 @@ Future handleMediaUpload(MediaUpload media) async { try { Log.info("Starting upload from ${media.mediaUploadId}"); + final task = UploadTask.fromFile( + taskId: "upload_${media.mediaUploadId}", + displayName: (media.metadata?.isVideo ?? false) ? "image" : "video", + file: uploadRequestFile, + url: apiUrl, + priority: 0, + retries: 10, + headers: { + 'x-twonly-auth-token': apiAuthToken, + }, + ); + + currentUploadTasks[media.mediaUploadId] = task; + try { await uploadFileFast(media, uploadRequestBytes, apiUrl, apiAuthToken); } catch (e) { - Log.error("Fast upload failed: $e. Using slow method."); - final task = UploadTask.fromFile( - taskId: "upload_${media.mediaUploadId}", - displayName: (media.metadata?.isVideo ?? false) ? "image" : "video", - file: uploadRequestFile, - url: apiUrl, - priority: 0, - retries: 10, - headers: { - 'x-twonly-auth-token': apiAuthToken, - }, - ); - await FileDownloader().enqueue(task); + Log.error("Fast upload failed: $e. Using slow method directly."); + enqueueUploadTask(media.mediaUploadId); } - - await twonlyDB.mediaUploadsDao.updateMediaUpload( - media.mediaUploadId, - MediaUploadsCompanion( - state: Value(UploadState.uploadTaskStarted), - ), - ); } catch (e) { Log.error("Exception during upload: $e"); } } +Map currentUploadTasks = {}; + +Future enqueueUploadTask(int mediaUploadId) async { + if (currentUploadTasks[mediaUploadId] == null) { + Log.info("could not enqueue upload task: $mediaUploadId"); + return; + } + + Log.info("Enqueue upload task: $mediaUploadId"); + + await FileDownloader().enqueue(currentUploadTasks[mediaUploadId]!); + currentUploadTasks.remove(mediaUploadId); + + await twonlyDB.mediaUploadsDao.updateMediaUpload( + mediaUploadId, + MediaUploadsCompanion( + state: Value(UploadState.uploadTaskStarted), + ), + ); +} + +Future handleUploadWhenAppGoesBackground() async { + if (currentUploadTasks.keys.isEmpty) { + return; + } + Log.info("App goes into background. Enqueue uploads to the background."); + final keys = currentUploadTasks.keys.toList(); + for (final key in keys) { + enqueueUploadTask(key); + } +} + Future uploadFileFast( MediaUpload media, Uint8List uploadRequestFile, @@ -643,7 +673,7 @@ Future uploadFileFast( filename: "upload", )); - final response = await requestMultipart.send().timeout(Duration(seconds: 3)); + final response = await requestMultipart.send(); if (response.statusCode == 200) { Log.info('Upload successful!'); await handleUploadSuccess(media); diff --git a/pubspec.yaml b/pubspec.yaml index f193c91..5c1389e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "twonly, a privacy-friendly way to connect with friends through sec # Prevent accidental publishing to pub.dev. publish_to: 'none' -version: 0.0.48+48 +version: 0.0.49+49 environment: sdk: ^3.6.0