Bladeren bron

FileUploader: Move AssetEntity related logic in helper class

Neeraj Gupta 4 jaren geleden
bovenliggende
commit
1c1fb43eda
2 gewijzigde bestanden met toevoegingen van 105 en 61 verwijderingen
  1. 10 61
      lib/utils/file_uploader.dart
  2. 95 0
      lib/utils/file_uploader_util.dart

+ 10 - 61
lib/utils/file_uploader.dart

@@ -20,11 +20,11 @@ import 'package:photos/events/subscription_purchased_event.dart';
 import 'package:photos/main.dart';
 import 'package:photos/models/encryption_result.dart';
 import 'package:photos/models/file.dart';
-import 'package:photos/models/location.dart';
 import 'package:photos/models/upload_url.dart';
 import 'package:photos/services/collections_service.dart';
 import 'package:photos/services/local_sync_service.dart';
 import 'package:photos/services/sync_service.dart';
+import 'package:photos/utils/file_uploader_util.dart';
 import 'package:photos/utils/crypto_util.dart';
 import 'package:photos/utils/file_util.dart';
 import 'package:shared_preferences/shared_preferences.dart';
@@ -267,41 +267,20 @@ class FileUploader {
         "_thumbnail" +
         (_isBackground ? "_bg" : "") +
         ".encrypted";
-    io.File sourceFile;
+    MediaUploadData mediaUploadData;
 
     try {
       _logger.info("Trying to upload " +
           file.toString() +
           ", isForced: " +
           forcedUpload.toString());
-      // The timeouts are to safeguard against https://github.com/CaiJingLong/flutter_photo_manager/issues/467
-      final asset = await file
-          .getAsset()
-          .timeout(Duration(seconds: 3))
-          .catchError((e) async {
-        if (e is TimeoutException) {
-          _logger.info("Asset fetch timed out for " + file.toString());
-          return await file.getAsset();
+      mediaUploadData = await getUploadDataFromEnteFile(file).catchError((e) async {
+        if (e is InvalidFileError) {
+          _onInvalidFileError(file);
         } else {
           throw e;
         }
       });
-      if (asset == null) {
-        await _onInvalidFileError(file);
-      }
-      sourceFile = await asset.originFile
-          .timeout(Duration(seconds: 3))
-          .catchError((e) async {
-        if (e is TimeoutException) {
-          _logger.info("Origin file fetch timed out for " + file.toString());
-          return await asset.originFile;
-        } else {
-          throw e;
-        }
-      });
-      if (!sourceFile.existsSync()) {
-        await _onInvalidFileError(file);
-      }
       var key;
       var isAlreadyUploadedFile = file.uploadedFileID != null;
       if (isAlreadyUploadedFile) {
@@ -314,30 +293,12 @@ class FileUploader {
         io.File(encryptedFilePath).deleteSync();
       }
       final encryptedFile = io.File(encryptedFilePath);
-
       final fileAttributes = await CryptoUtil.encryptFile(
-        sourceFile.path,
+        mediaUploadData.sourceFile.path,
         encryptedFilePath,
         key: key,
       );
-
-      var thumbnailData = await asset.thumbDataWithSize(
-        THUMBNAIL_LARGE_SIZE,
-        THUMBNAIL_LARGE_SIZE,
-        quality: 50,
-      );
-      if (thumbnailData == null) {
-        await _onInvalidFileError(file);
-      }
-      int compressionAttempts = 0;
-      while (thumbnailData.length > THUMBNAIL_DATA_LIMIT &&
-          compressionAttempts < kMaximumThumbnailCompressionAttempts) {
-        _logger.info("Thumbnail size " + thumbnailData.length.toString());
-        thumbnailData = await compressThumbnail(thumbnailData);
-        _logger.info(
-            "Compressed thumbnail size " + thumbnailData.length.toString());
-        compressionAttempts++;
-      }
+      var thumbnailData = mediaUploadData.thumbnail;
 
       final encryptedThumbnailData =
           await CryptoUtil.encryptChaCha(thumbnailData, fileAttributes.key);
@@ -355,18 +316,6 @@ class FileUploader {
       final fileUploadURL = await _getUploadURL();
       String fileObjectKey = await _putFile(fileUploadURL, encryptedFile);
 
-      // h4ck to fetch location data if missing (thank you Android Q+) lazily only during uploads
-      if (file.location == null ||
-          (file.location.latitude == 0 && file.location.longitude == 0)) {
-        final latLong = await asset.latlngAsync();
-        file.location = Location(latLong.latitude, latLong.longitude);
-      }
-
-      if (file.title == null || file.title.isEmpty) {
-        _logger.severe("Title was missing");
-        file.title = await asset.titleAsync;
-      }
-
       final encryptedMetadataData = await CryptoUtil.encryptChaCha(
           utf8.encode(jsonEncode(file.getMetadata())), fileAttributes.key);
       final fileDecryptionHeader = Sodium.bin2base64(fileAttributes.header);
@@ -404,7 +353,7 @@ class FileUploader {
           encryptedMetadata,
           metadataDecryptionHeader,
         );
-        if (asset == null || !(await asset.exists)) {
+        if (mediaUploadData.isDeleted) {
           _logger.info("File found to be deleted");
           remoteFile.localID = null;
         }
@@ -421,8 +370,8 @@ class FileUploader {
       }
       throw e;
     } finally {
-      if (io.Platform.isIOS && sourceFile != null) {
-        sourceFile.deleteSync();
+      if (io.Platform.isIOS && mediaUploadData != null && mediaUploadData.sourceFile != null) {
+        mediaUploadData.sourceFile.deleteSync();
       }
       if (io.File(encryptedFilePath).existsSync()) {
         io.File(encryptedFilePath).deleteSync();

+ 95 - 0
lib/utils/file_uploader_util.dart

@@ -0,0 +1,95 @@
+import 'dart:async';
+import 'dart:io' as io;
+
+import 'dart:typed_data';
+
+import 'package:logging/logging.dart';
+import 'package:photo_manager/photo_manager.dart';
+import 'package:photos/core/constants.dart';
+import 'package:photos/core/errors.dart';
+import 'package:photos/models/location.dart';
+import 'package:photos/models/file.dart' as ente;
+
+import 'file_util.dart';
+
+final _logger = Logger("FileUtil");
+const kMaximumThumbnailCompressionAttempts = 2;
+
+class MediaUploadData {
+  final io.File sourceFile;
+  final Uint8List thumbnail;
+  final bool isDeleted;
+
+  MediaUploadData(this.sourceFile, this.thumbnail, this.isDeleted);
+}
+
+Future<MediaUploadData> getUploadDataFromEnteFile(ente.File file) async {
+  // todo: add local to get data from either Asset/photoManager or app cache
+  return await _getMediaUploadDataFromAssetFile(file);
+}
+
+Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
+  io.File sourceFile;
+  Uint8List thumbnailData;
+  bool isDeleted;
+
+  // The timeouts are to safeguard against https://github.com/CaiJingLong/flutter_photo_manager/issues/467
+  final asset =
+      await file.getAsset().timeout(Duration(seconds: 3)).catchError((e) async {
+    if (e is TimeoutException) {
+      _logger.info("Asset fetch timed out for " + file.toString());
+      return await file.getAsset();
+    } else {
+      throw e;
+    }
+  });
+  if (asset == null) {
+    throw InvalidFileError();
+  }
+  sourceFile = await asset.originFile
+      .timeout(Duration(seconds: 3))
+      .catchError((e) async {
+    if (e is TimeoutException) {
+      _logger.info("Origin file fetch timed out for " + file.toString());
+      return await asset.originFile;
+    } else {
+      throw e;
+    }
+  });
+  if (!sourceFile.existsSync()) {
+    throw InvalidFileError();
+  }
+  thumbnailData = await asset.thumbDataWithSize(
+    THUMBNAIL_SMALL_SIZE,
+    THUMBNAIL_SMALL_SIZE,
+    quality: THUMBNAIL_QUALITY,
+  );
+  int compressionAttempts = 0;
+  while (thumbnailData.length > THUMBNAIL_DATA_LIMIT &&
+      compressionAttempts < kMaximumThumbnailCompressionAttempts) {
+    _logger.info("Thumbnail size " + thumbnailData.length.toString());
+    thumbnailData = await compressThumbnail(thumbnailData);
+    _logger
+        .info("Compressed thumbnail size " + thumbnailData.length.toString());
+    compressionAttempts++;
+  }
+
+  isDeleted = asset == null || !(await asset.exists);
+  // h4ck to fetch location data if missing (thank you Android Q+) lazily only during uploads
+  await _decorateEnteFileData(file, asset);
+  return MediaUploadData(sourceFile, thumbnailData, isDeleted);
+}
+
+Future<void> _decorateEnteFileData(ente.File file, AssetEntity asset) async {
+  // h4ck to fetch location data if missing (thank you Android Q+) lazily only during uploads
+  if (file.location == null ||
+      (file.location.latitude == 0 && file.location.longitude == 0)) {
+    final latLong = await asset.latlngAsync();
+    file.location = Location(latLong.latitude, latLong.longitude);
+  }
+
+  if (file.title == null || file.title.isEmpty) {
+    _logger.severe("Title was missing");
+    file.title = await asset.titleAsync;
+  }
+}