浏览代码

Refactor fileHash handling

Neeraj Gupta 2 年之前
父节点
当前提交
68738c5c56

+ 18 - 8
lib/db/files_db.dart

@@ -1,6 +1,5 @@
 import 'dart:io';
 
-import 'package:flutter/foundation.dart';
 import 'package:logging/logging.dart';
 import 'package:path/path.dart';
 import 'package:path_provider/path_provider.dart';
@@ -10,6 +9,7 @@ import 'package:photos/models/file_load_result.dart';
 import 'package:photos/models/file_type.dart';
 import 'package:photos/models/location.dart';
 import 'package:photos/models/magic_metadata.dart';
+import 'package:photos/utils/file_uploader_util.dart';
 import 'package:sqflite/sqflite.dart';
 import 'package:sqflite_migration/sqflite_migration.dart';
 
@@ -816,17 +816,27 @@ class FilesDB {
   }
 
   Future<List<File>> getUploadedFilesWithHashes(
-    List<String> hash,
+    FileHashData hashData,
     FileType fileType,
     int ownerID,
   ) async {
-    // look up two hash at max, for handling live photos
-    assert(hash.length < 3, "number of hash can not be more than 2");
+    String inParam = "'${hashData.fileHash}'";
+    if (fileType == FileType.livePhoto && hashData.zipHash != null) {
+      inParam += ",'${hashData.zipHash}'";
+    }
+
     final db = await instance.database;
-    String rawQuery = 'SELECT * from files where ($columnUploadedFileID != '
-        'NULL OR $columnUploadedFileID != -1) AND $columnOwnerID = $ownerID '
-        'AND ($columnHash = "${hash.first}" OR $columnHash = "${hash.last}")';
-    final rows = await db.rawQuery(rawQuery, []);
+    final rows = await db.query(
+      table,
+      where: '($columnUploadedFileID != NULL OR $columnUploadedFileID != -1) '
+          'AND $columnOwnerID = ? AND $columnFileType ='
+          ' ? '
+          'AND $columnHash IN ($inParam)',
+      whereArgs: [
+        ownerID,
+        getInt(fileType),
+      ],
+    );
     if (rows.isNotEmpty) {
       return _convertToFiles(rows);
     } else {

+ 4 - 8
lib/models/file.dart

@@ -53,7 +53,9 @@ class File extends EnteFile {
 
   set pubMagicMetadata(val) => _pubMmd = val;
 
-  static const kCurrentMetadataVersion = 1;
+  // in Version 1, live photo hash is stored as zip's hash.
+  // in V2: LivePhoto hash is stored as imgHash:vidHash
+  static const kCurrentMetadataVersion = 2;
 
   File();
 
@@ -154,13 +156,7 @@ class File extends EnteFile {
         creationTime = exifTime.microsecondsSinceEpoch;
       }
     }
-    // in metadataVersion V1, the hash for livePhoto is the hash of the
-    // zipped file.
-    // web uploads files without MetadataVersion and upload image hash as 'ha
-    // sh' key and video as 'vidHash'
-    hash = (fileType == FileType.livePhoto)
-        ? mediaUploadData.zipHash
-        : mediaUploadData.fileHash;
+    hash = mediaUploadData.hashData?.fileHash;
     return getMetadata();
   }
 

+ 4 - 3
lib/services/local_file_update_service.dart

@@ -106,9 +106,10 @@ class LocalFileUpdateService {
       MediaUploadData uploadData;
       try {
         uploadData = await getUploadDataFromEnteFile(file);
-        if (file.hash != null ||
-            (file.hash == uploadData.fileHash ||
-                file.hash == uploadData.zipHash)) {
+        if (uploadData.hashData != null &&
+            file.hash != null &&
+            (file.hash == uploadData.hashData.fileHash ||
+                file.hash == uploadData.hashData.zipHash)) {
           _logger.info("Skip file update as hash matched ${file.tag()}");
         } else {
           _logger.info(

+ 6 - 9
lib/utils/file_uploader.dart

@@ -447,10 +447,10 @@ class FileUploader {
   }
 
   /*
-  // _mapToExistingUpload links the current file to be uploaded with the
-  // existing files. If the link is successful, it returns true other false.
-   When false, we should go ahead and re-upload or update the file
-    It performs following checks:
+  _mapToExistingUpload links the fileToUpload with the existing uploaded
+  files. if the link is successful, it returns true otherwise false.
+  When false, we should go ahead and re-upload or update the file.
+  It performs following checks:
     a) Uploaded file with same localID and destination collection. Delete the
      fileToUpload entry
     b) Uploaded file in destination collection but with missing localID.
@@ -476,13 +476,10 @@ class FileUploader {
       );
       return false;
     }
-    List<String> hash = [mediaUploadData.fileHash];
-    if (fileToUpload.fileType == FileType.livePhoto) {
-      hash.add(mediaUploadData.zipHash);
-    }
+
     final List<File> existingUploadedFiles =
         await FilesDB.instance.getUploadedFilesWithHashes(
-      hash,
+      mediaUploadData.hashData,
       fileToUpload.fileType,
       Configuration.instance.getUserID(),
     );

+ 18 - 13
lib/utils/file_uploader_util.dart

@@ -26,22 +26,27 @@ class MediaUploadData {
   final io.File sourceFile;
   final Uint8List thumbnail;
   final bool isDeleted;
-  // presents the hash for the original video or image file.
-  // for livePhotos, fileHash represents the image hash value
-  final String fileHash;
-  final String liveVideoHash;
-  final String zipHash;
+  final FileHashData hashData;
 
   MediaUploadData(
     this.sourceFile,
     this.thumbnail,
     this.isDeleted, {
-    this.fileHash,
-    this.liveVideoHash,
-    this.zipHash,
+    this.hashData,
   });
 }
 
+class FileHashData {
+  // For livePhotos, the fileHash value will be imageHash:videoHash
+  final String fileHash;
+
+  // zipHash is used to take care of existing live photo uploads from older
+  // mobile clients
+  String zipHash;
+
+  FileHashData(this.fileHash, {this.zipHash});
+}
+
 Future<MediaUploadData> getUploadDataFromEnteFile(ente.File file) async {
   if (file.isSharedMediaToAppSandbox()) {
     return await _getMediaUploadDataFromAppCache(file);
@@ -54,7 +59,7 @@ Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
   io.File sourceFile;
   Uint8List thumbnailData;
   bool isDeleted;
-  String fileHash, livePhotoVideoHash, zipHash;
+  String fileHash, zipHash;
 
   // The timeouts are to safeguard against https://github.com/CaiJingLong/flutter_photo_manager/issues/467
   final asset = await file
@@ -97,7 +102,9 @@ Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
       _logger.severe(errMsg);
       throw InvalidFileUploadState(errMsg);
     }
-    livePhotoVideoHash = Sodium.bin2base64(await CryptoUtil.getHash(videoUrl));
+    String livePhotoVideoHash =
+        Sodium.bin2base64(await CryptoUtil.getHash(videoUrl));
+    fileHash = '$fileHash:$livePhotoVideoHash';
     final tempPath = Configuration.instance.getTempDirectory();
     // .elp -> ente live photo
     final livePhotoPath = tempPath + file.generatedID.toString() + ".elp";
@@ -138,9 +145,7 @@ Future<MediaUploadData> _getMediaUploadDataFromAssetFile(ente.File file) async {
     sourceFile,
     thumbnailData,
     isDeleted,
-    fileHash: fileHash,
-    liveVideoHash: livePhotoVideoHash,
-    zipHash: zipHash,
+    hashData: FileHashData(fileHash, zipHash: zipHash),
   );
 }