瀏覽代碼

TrashFile: extend File

Neeraj Gupta 3 年之前
父節點
當前提交
ceaed8def3
共有 5 個文件被更改,包括 96 次插入112 次删除
  1. 62 66
      lib/db/trash_db.dart
  2. 1 2
      lib/models/trash_file.dart
  3. 8 3
      lib/services/trash_sync_service.dart
  4. 3 16
      lib/ui/trash_page.dart
  5. 22 25
      lib/utils/trash_diff_fetcher.dart

+ 62 - 66
lib/db/trash_db.dart

@@ -3,7 +3,6 @@ import 'dart:io';
 import 'package:logging/logging.dart';
 import 'package:logging/logging.dart';
 import 'package:path/path.dart';
 import 'package:path/path.dart';
 import 'package:path_provider/path_provider.dart';
 import 'package:path_provider/path_provider.dart';
-import 'package:photos/models/file.dart';
 import 'package:photos/models/file_load_result.dart';
 import 'package:photos/models/file_load_result.dart';
 import 'package:photos/models/file_type.dart';
 import 'package:photos/models/file_type.dart';
 import 'package:photos/models/location.dart';
 import 'package:photos/models/location.dart';
@@ -107,12 +106,12 @@ class TrashDB {
     await db.delete(tableName);
     await db.delete(tableName);
   }
   }
 
 
-  Future<void> insertMultiple(List<Trash> trashFiles) async {
+  Future<void> insertMultiple(List<TrashFile> trashFiles) async {
     final startTime = DateTime.now();
     final startTime = DateTime.now();
     final db = await instance.database;
     final db = await instance.database;
     var batch = db.batch();
     var batch = db.batch();
     int batchCounter = 0;
     int batchCounter = 0;
-    for (Trash trash in trashFiles) {
+    for (TrashFile trash in trashFiles) {
       if (batchCounter == 400) {
       if (batchCounter == 400) {
         await batch.commit(noResult: true);
         await batch.commit(noResult: true);
         batch = db.batch();
         batch = db.batch();
@@ -129,7 +128,7 @@ class TrashDB {
     final endTime = DateTime.now();
     final endTime = DateTime.now();
     final duration = Duration(
     final duration = Duration(
         microseconds:
         microseconds:
-        endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch);
+            endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch);
     _logger.info("Batch insert of " +
     _logger.info("Batch insert of " +
         trashFiles.length.toString() +
         trashFiles.length.toString() +
         " took " +
         " took " +
@@ -137,7 +136,7 @@ class TrashDB {
         "ms.");
         "ms.");
   }
   }
 
 
-  Future<int> insert(Trash trash) async {
+  Future<int> insert(TrashFile trash) async {
     final db = await instance.database;
     final db = await instance.database;
     return db.insert(
     return db.insert(
       tableName,
       tableName,
@@ -160,88 +159,85 @@ class TrashDB {
     final order = (asc ?? false ? 'ASC' : 'DESC');
     final order = (asc ?? false ? 'ASC' : 'DESC');
     final results = await db.query(
     final results = await db.query(
       tableName,
       tableName,
-      where:
-      '$columnCreationTime >= ? AND $columnCreationTime <= ?',
+      where: '$columnCreationTime >= ? AND $columnCreationTime <= ?',
       whereArgs: [startTime, endTime],
       whereArgs: [startTime, endTime],
       orderBy:
       orderBy:
-      '$columnCreationTime ' + order + ', $columnModificationTime ' + order,
+          '$columnCreationTime ' + order + ', $columnModificationTime ' + order,
       limit: limit,
       limit: limit,
     );
     );
     final files = _convertToFiles(results);
     final files = _convertToFiles(results);
     return FileLoadResult(files, files.length == limit);
     return FileLoadResult(files, files.length == limit);
   }
   }
 
 
-  List<File> _convertToFiles(List<Map<String, dynamic>> results) {
-    final List<File> files = [];
+  List<TrashFile> _convertToFiles(List<Map<String, dynamic>> results) {
+    final List<TrashFile> trashedFiles = [];
     for (final result in results) {
     for (final result in results) {
-      files.add(_getTrashFromRow(result).file);
+      trashedFiles.add(_getTrashFromRow(result));
     }
     }
-    return files;
+    return trashedFiles;
   }
   }
 
 
-  Trash _getTrashFromRow(Map<String, dynamic> row) {
-    final trash = Trash();
-    final file = File();
-    file.uploadedFileID =
-    row[columnUploadedFileID] == -1 ? null : row[columnUploadedFileID];
-    file.localID = row[columnLocalID];
-    file.ownerID = row[columnOwnerID];
-    file.collectionID =
-    row[columnCollectionID] == -1 ? null : row[columnCollectionID];
-    file.title = row[columnTitle];
-    file.deviceFolder = row[columnDeviceFolder];
+  TrashFile _getTrashFromRow(Map<String, dynamic> row) {
+    final trashFile = TrashFile();
+    trashFile.updateAt = row[columnTrashUpdatedAt];
+    trashFile.deleteBy = row[columnTrashDeleteBy];
+    trashFile.uploadedFileID =
+        row[columnUploadedFileID] == -1 ? null : row[columnUploadedFileID];
+    trashFile.localID = row[columnLocalID];
+    trashFile.ownerID = row[columnOwnerID];
+    trashFile.collectionID =
+        row[columnCollectionID] == -1 ? null : row[columnCollectionID];
+    trashFile.title = row[columnTitle];
+    trashFile.deviceFolder = row[columnDeviceFolder];
     if (row[columnLatitude] != null && row[columnLongitude] != null) {
     if (row[columnLatitude] != null && row[columnLongitude] != null) {
-      file.location = Location(row[columnLatitude], row[columnLongitude]);
+      trashFile.location = Location(row[columnLatitude], row[columnLongitude]);
     }
     }
-    file.fileType = getFileType(row[columnFileType]);
-    file.creationTime = row[columnCreationTime];
-    file.modificationTime = row[columnModificationTime];
-    file.encryptedKey = row[columnEncryptedKey];
-    file.keyDecryptionNonce = row[columnKeyDecryptionNonce];
-    file.fileDecryptionHeader = row[columnFileDecryptionHeader];
-    file.thumbnailDecryptionHeader = row[columnThumbnailDecryptionHeader];
-    file.fileSubType = row[columnFileSubType] ?? -1;
-    file.duration = row[columnDuration] ?? 0;
-    file.hash = row[columnHash];
-    file.metadataVersion = row[columnMetadataVersion] ?? 0;
-    file.mMdVersion = row[columnMMdVersion] ?? 0;
-    file.mMdEncodedJson = row[columnMMdEncodedJson] ?? '{}';
-    trash.file = file;
-    trash.updateAt = row[columnTrashUpdatedAt];
-    trash.deleteBy = row[columnTrashDeleteBy];
-    return trash;
+    trashFile.fileType = getFileType(row[columnFileType]);
+    trashFile.creationTime = row[columnCreationTime];
+    trashFile.modificationTime = row[columnModificationTime];
+    trashFile.encryptedKey = row[columnEncryptedKey];
+    trashFile.keyDecryptionNonce = row[columnKeyDecryptionNonce];
+    trashFile.fileDecryptionHeader = row[columnFileDecryptionHeader];
+    trashFile.thumbnailDecryptionHeader = row[columnThumbnailDecryptionHeader];
+    trashFile.fileSubType = row[columnFileSubType] ?? -1;
+    trashFile.duration = row[columnDuration] ?? 0;
+    trashFile.hash = row[columnHash];
+    trashFile.metadataVersion = row[columnMetadataVersion] ?? 0;
+    trashFile.mMdVersion = row[columnMMdVersion] ?? 0;
+    trashFile.mMdEncodedJson = row[columnMMdEncodedJson] ?? '{}';
+
+    return trashFile;
   }
   }
 
 
-  Map<String, dynamic> _getRowForTrash(Trash trash) {
-    final file = trash.file;
+  Map<String, dynamic> _getRowForTrash(TrashFile trash) {
     final row = <String, dynamic>{};
     final row = <String, dynamic>{};
     row[columnTrashUpdatedAt] = trash.updateAt;
     row[columnTrashUpdatedAt] = trash.updateAt;
     row[columnTrashDeleteBy] = trash.deleteBy;
     row[columnTrashDeleteBy] = trash.deleteBy;
-    row[columnUploadedFileID] = file.uploadedFileID;
-    row[columnCollectionID] = file.collectionID;
-    row[columnOwnerID] = file.ownerID;
-    row[columnLocalID] = file.localID;
-    row[columnTitle] = file.title;
-    row[columnDeviceFolder] = file.deviceFolder;
-    if (file.location != null) {
-      row[columnLatitude] = file.location.latitude;
-      row[columnLongitude] = file.location.longitude;
+    row[columnUploadedFileID] = trash.uploadedFileID;
+    row[columnCollectionID] = trash.collectionID;
+    row[columnOwnerID] = trash.ownerID;
+    row[columnLocalID] = trash.localID;
+    row[columnTitle] = trash.title;
+    row[columnDeviceFolder] = trash.deviceFolder;
+    if (trash.location != null) {
+      row[columnLatitude] = trash.location.latitude;
+      row[columnLongitude] = trash.location.longitude;
     }
     }
-    row[columnFileType] = getInt(file.fileType);
-    row[columnCreationTime] = file.creationTime;
-    row[columnModificationTime] = file.modificationTime;
-    row[columnEncryptedKey] = file.encryptedKey;
-    row[columnKeyDecryptionNonce] = file.keyDecryptionNonce;
-    row[columnFileDecryptionHeader] = file.fileDecryptionHeader;
-    row[columnThumbnailDecryptionHeader] = file.thumbnailDecryptionHeader;
-    row[columnFileSubType] = file.fileSubType ?? -1;
-    row[columnDuration] = file.duration ?? 0;
-    row[columnHash] = file.hash;
-    row[columnMetadataVersion] = file.metadataVersion;
-    row[columnMMdVersion] = file.mMdVersion ?? 0;
-    row[columnMMdEncodedJson] = file.mMdEncodedJson ?? '{}';
+    row[columnFileType] = getInt(trash.fileType);
+    row[columnCreationTime] = trash.creationTime;
+    row[columnModificationTime] = trash.modificationTime;
+    row[columnEncryptedKey] = trash.encryptedKey;
+    row[columnKeyDecryptionNonce] = trash.keyDecryptionNonce;
+    row[columnFileDecryptionHeader] = trash.fileDecryptionHeader;
+    row[columnThumbnailDecryptionHeader] = trash.thumbnailDecryptionHeader;
+    row[columnFileSubType] = trash.fileSubType ?? -1;
+    row[columnDuration] = trash.duration ?? 0;
+    row[columnHash] = trash.hash;
+    row[columnMetadataVersion] = trash.metadataVersion;
+    row[columnMMdVersion] = trash.mMdVersion ?? 0;
+    row[columnMMdEncodedJson] = trash.mMdEncodedJson ?? '{}';
     row[columnMMdVisibility] =
     row[columnMMdVisibility] =
-        file.magicMetadata?.visibility ?? kVisibilityVisible;
+        trash.magicMetadata?.visibility ?? kVisibilityVisible;
     return row;
     return row;
   }
   }
 }
 }

+ 1 - 2
lib/models/trash_file.dart

@@ -1,7 +1,6 @@
 import 'package:photos/models/file.dart';
 import 'package:photos/models/file.dart';
 
 
-class Trash {
-  File file;
+class TrashFile extends File {
 
 
   // time when file was put in the trash for first time
   // time when file was put in the trash for first time
   int createdAt;
   int createdAt;

+ 8 - 3
lib/services/trash_sync_service.dart

@@ -38,12 +38,12 @@ class TrashSyncService {
     if (diff.deletedFiles.isNotEmpty) {
     if (diff.deletedFiles.isNotEmpty) {
       _logger.fine("discard ${diff.deletedFiles.length} deleted items");
       _logger.fine("discard ${diff.deletedFiles.length} deleted items");
       await _trashDB
       await _trashDB
-          .delete(diff.deletedFiles.map((e) => e.file.uploadedFileID).toList());
+          .delete(diff.deletedFiles.map((e) => e.uploadedFileID).toList());
     }
     }
     if (diff.restoredFiles.isNotEmpty) {
     if (diff.restoredFiles.isNotEmpty) {
       _logger.fine("discard ${diff.restoredFiles.length} restored items");
       _logger.fine("discard ${diff.restoredFiles.length} restored items");
       await _trashDB.delete(
       await _trashDB.delete(
-          diff.restoredFiles.map((e) => e.file.uploadedFileID).toList());
+          diff.restoredFiles.map((e) => e.uploadedFileID).toList());
     }
     }
     if (diff.lastSyncedTimeStamp != 0) {
     if (diff.lastSyncedTimeStamp != 0) {
       await setSyncTime(diff.lastSyncedTimeStamp);
       await setSyncTime(diff.lastSyncedTimeStamp);
@@ -66,9 +66,14 @@ class TrashSyncService {
 
 
   Future<void> trashFilesOnServer(List<TrashRequest> trashRequestItems) async {
   Future<void> trashFilesOnServer(List<TrashRequest> trashRequestItems) async {
     final params = <String, dynamic>{};
     final params = <String, dynamic>{};
+    final includedFileIDs = <int>{};
     params["items"] = [];
     params["items"] = [];
+
     for (final item in trashRequestItems) {
     for (final item in trashRequestItems) {
-      params["items"].add(item.toJson());
+      if (!includedFileIDs.contains(item.fileID)) {
+        params["items"].add(item.toJson());
+        includedFileIDs.add(item.fileID);
+      }
     }
     }
     return await _dio.post(
     return await _dio.post(
       Configuration.instance.getHttpEndpoint() + "/files/trash",
       Configuration.instance.getHttpEndpoint() + "/files/trash",

+ 3 - 16
lib/ui/trash_page.dart

@@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/material.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/db/trash_db.dart';
 import 'package:photos/db/trash_db.dart';
+import 'package:photos/events/collection_updated_event.dart';
 import 'package:photos/events/files_updated_event.dart';
 import 'package:photos/events/files_updated_event.dart';
 import 'package:photos/models/selected_files.dart';
 import 'package:photos/models/selected_files.dart';
 
 
@@ -29,22 +30,8 @@ class TrashPage extends StatelessWidget {
             creationStartTime, creationEndTime,
             creationStartTime, creationEndTime,
             limit: limit, asc: asc);
             limit: limit, asc: asc);
       },
       },
-      reloadEvent: Bus.instance.on<FilesUpdatedEvent>().where(
-            (event) =>
-                event.updatedFiles.firstWhere(
-                    (element) => element.uploadedFileID != null,
-                    orElse: () => null) !=
-                null,
-          ),
-      forceReloadEvents: [
-        Bus.instance.on<FilesUpdatedEvent>().where(
-              (event) =>
-                  event.updatedFiles.firstWhere(
-                      (element) => element.uploadedFileID != null,
-                      orElse: () => null) !=
-                  null,
-            ),
-      ],
+      reloadEvent: Bus.instance.on<CollectionUpdatedEvent>(),
+      forceReloadEvents: [Bus.instance.on<CollectionUpdatedEvent>()],
       tagPrefix: tagPrefix,
       tagPrefix: tagPrefix,
       selectedFiles: _selectedFiles,
       selectedFiles: _selectedFiles,
       initialFiles: null,
       initialFiles: null,

+ 22 - 25
lib/utils/trash_diff_fetcher.dart

@@ -8,7 +8,6 @@ import 'package:photos/core/configuration.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/event_bus.dart';
 import 'package:photos/core/network.dart';
 import 'package:photos/core/network.dart';
 import 'package:photos/events/remote_sync_event.dart';
 import 'package:photos/events/remote_sync_event.dart';
-import 'package:photos/models/file.dart';
 import 'package:photos/models/trash_file.dart';
 import 'package:photos/models/trash_file.dart';
 import 'package:photos/utils/crypto_util.dart';
 import 'package:photos/utils/crypto_util.dart';
 import 'package:photos/utils/file_download_util.dart';
 import 'package:photos/utils/file_download_util.dart';
@@ -29,48 +28,46 @@ class TrashDiffFetcher {
         },
         },
       );
       );
       int latestUpdatedAtTime = 0;
       int latestUpdatedAtTime = 0;
-      final trashedFiles = <Trash>[];
-      final deletedFiles = <Trash>[];
-      final restoredFiles = <Trash>[];
+      final trashedFiles = <TrashFile>[];
+      final deletedFiles = <TrashFile>[];
+      final restoredFiles = <TrashFile>[];
       if (response != null) {
       if (response != null) {
         Bus.instance.fire(RemoteSyncEvent(true));
         Bus.instance.fire(RemoteSyncEvent(true));
         final diff = response.data["diff"] as List;
         final diff = response.data["diff"] as List;
         final startTime = DateTime.now();
         final startTime = DateTime.now();
         for (final item in diff) {
         for (final item in diff) {
-          final trash = Trash();
+          final trash = TrashFile();
           trash.createdAt = item['createdAt'];
           trash.createdAt = item['createdAt'];
           trash.updateAt = item['updatedAt'];
           trash.updateAt = item['updatedAt'];
           latestUpdatedAtTime = max(latestUpdatedAtTime, trash.updateAt);
           latestUpdatedAtTime = max(latestUpdatedAtTime, trash.updateAt);
           trash.deleteBy = item['deleteBy'];
           trash.deleteBy = item['deleteBy'];
-          trash.file = File();
-          trash.file.uploadedFileID = item["file"]["id"];
-          trash.file.collectionID = item["file"]["collectionID"];
-          trash.file.updationTime = item["file"]["updationTime"];
-          trash.file.ownerID = item["file"]["ownerID"];
-          trash.file.encryptedKey = item["file"]["encryptedKey"];
-          trash.file.keyDecryptionNonce = item["file"]["keyDecryptionNonce"];
-          trash.file.fileDecryptionHeader =
-              item["file"]["file"]["decryptionHeader"];
-          trash.file.thumbnailDecryptionHeader =
+          trash.uploadedFileID = item["file"]["id"];
+          trash.collectionID = item["file"]["collectionID"];
+          trash.updationTime = item["file"]["updationTime"];
+          trash.ownerID = item["file"]["ownerID"];
+          trash.encryptedKey = item["file"]["encryptedKey"];
+          trash.keyDecryptionNonce = item["file"]["keyDecryptionNonce"];
+          trash.fileDecryptionHeader = item["file"]["file"]["decryptionHeader"];
+          trash.thumbnailDecryptionHeader =
               item["file"]["thumbnail"]["decryptionHeader"];
               item["file"]["thumbnail"]["decryptionHeader"];
-          trash.file.metadataDecryptionHeader =
+          trash.metadataDecryptionHeader =
               item["file"]["metadata"]["decryptionHeader"];
               item["file"]["metadata"]["decryptionHeader"];
-          final fileDecryptionKey = decryptFileKey(trash.file);
+          final fileDecryptionKey = decryptFileKey(trash);
           final encodedMetadata = await CryptoUtil.decryptChaCha(
           final encodedMetadata = await CryptoUtil.decryptChaCha(
             Sodium.base642bin(item["file"]["metadata"]["encryptedData"]),
             Sodium.base642bin(item["file"]["metadata"]["encryptedData"]),
             fileDecryptionKey,
             fileDecryptionKey,
-            Sodium.base642bin(trash.file.metadataDecryptionHeader),
+            Sodium.base642bin(trash.metadataDecryptionHeader),
           );
           );
           Map<String, dynamic> metadata =
           Map<String, dynamic> metadata =
               jsonDecode(utf8.decode(encodedMetadata));
               jsonDecode(utf8.decode(encodedMetadata));
-          trash.file.applyMetadata(metadata);
+          trash.applyMetadata(metadata);
           if (item["file"]['magicMetadata'] != null) {
           if (item["file"]['magicMetadata'] != null) {
             final utfEncodedMmd = await CryptoUtil.decryptChaCha(
             final utfEncodedMmd = await CryptoUtil.decryptChaCha(
                 Sodium.base642bin(item["file"]['magicMetadata']['data']),
                 Sodium.base642bin(item["file"]['magicMetadata']['data']),
                 fileDecryptionKey,
                 fileDecryptionKey,
                 Sodium.base642bin(item["file"]['magicMetadata']['header']));
                 Sodium.base642bin(item["file"]['magicMetadata']['header']));
-            trash.file.mMdEncodedJson = utf8.decode(utfEncodedMmd);
-            trash.file.mMdVersion = item["file"]['magicMetadata']['version'];
+            trash.mMdEncodedJson = utf8.decode(utfEncodedMmd);
+            trash.mMdVersion = item["file"]['magicMetadata']['version'];
           }
           }
           if (item["isDeleted"]) {
           if (item["isDeleted"]) {
             deletedFiles.add(trash);
             deletedFiles.add(trash);
@@ -96,7 +93,7 @@ class TrashDiffFetcher {
             latestUpdatedAtTime);
             latestUpdatedAtTime);
       } else {
       } else {
         Bus.instance.fire(RemoteSyncEvent(false));
         Bus.instance.fire(RemoteSyncEvent(false));
-        return Diff(<Trash>[], <Trash>[], <Trash>[], 0, 0);
+        return Diff(<TrashFile>[], <TrashFile>[], <TrashFile>[], 0, 0);
       }
       }
     } catch (e, s) {
     } catch (e, s) {
       _logger.severe(e, s);
       _logger.severe(e, s);
@@ -106,9 +103,9 @@ class TrashDiffFetcher {
 }
 }
 
 
 class Diff {
 class Diff {
-  final List<Trash> trashedFiles;
-  final List<Trash> restoredFiles;
-  final List<Trash> deletedFiles;
+  final List<TrashFile> trashedFiles;
+  final List<TrashFile> restoredFiles;
+  final List<TrashFile> deletedFiles;
   final int fetchCount;
   final int fetchCount;
   final int lastSyncedTimeStamp;
   final int lastSyncedTimeStamp;