Implement move

This commit is contained in:
Neeraj Gupta
2025-06-20 13:02:42 +05:30
parent 733be57df8
commit 37674deba0
3 changed files with 41 additions and 90 deletions

View File

@@ -1,4 +1,6 @@
import 'dart:convert';
import "dart:typed_data";
import "package:ente_crypto/ente_crypto.dart";
class CollectionFileItem {
final int id;
@@ -11,16 +13,16 @@ class CollectionFileItem {
this.keyDecryptionNonce,
);
CollectionFileItem copyWith({
int? id,
String? encryptedKey,
String? keyDecryptionNonce,
static Map<String, dynamic> req(
int fileID, {
required Uint8List encryptedKey,
required Uint8List keyDecryptionNonce,
}) {
return CollectionFileItem(
id ?? this.id,
encryptedKey ?? this.encryptedKey,
keyDecryptionNonce ?? this.keyDecryptionNonce,
);
return {
'fileID': fileID,
'encryptedKey': CryptoUtil.bin2base64(encryptedKey),
'keyDecryptionNonce': CryptoUtil.bin2base64(keyDecryptionNonce),
};
}
Map<String, dynamic> toMap() {
@@ -30,37 +32,4 @@ class CollectionFileItem {
'keyDecryptionNonce': keyDecryptionNonce,
};
}
static fromMap(Map<String, dynamic>? map) {
if (map == null) return null;
return CollectionFileItem(
map['id'],
map['encryptedKey'],
map['keyDecryptionNonce'],
);
}
String toJson() => json.encode(toMap());
factory CollectionFileItem.fromJson(String source) =>
CollectionFileItem.fromMap(json.decode(source));
@override
String toString() =>
'CollectionFileItem(id: $id, encryptedKey: $encryptedKey, keyDecryptionNonce: $keyDecryptionNonce)';
@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
return o is CollectionFileItem &&
o.id == id &&
o.encryptedKey == encryptedKey &&
o.keyDecryptionNonce == keyDecryptionNonce;
}
@override
int get hashCode =>
id.hashCode ^ encryptedKey.hashCode ^ keyDecryptionNonce.hashCode;
}

View File

@@ -1523,15 +1523,15 @@ class CollectionsService {
final List<EnteFile> newFiles = [];
for (final file in batch) {
final newFile = moveOrAddEntry(file, destCollection);
final item = mapDiffItem(newFile);
collectionDiffItems.add(item);
final localDiffItem = buildDiffItem(newFile);
collectionDiffItems.add(localDiffItem);
newFiles.add(newFile);
params["files"].add(
CollectionFileItem(
item.fileID,
CryptoUtil.bin2base64(item.encFileKey!),
CryptoUtil.bin2base64(item.encFileKeyNonce!),
).toMap(),
CollectionFileItem.req(
localDiffItem.fileID,
encryptedKey: localDiffItem.encFileKey!,
keyDecryptionNonce: localDiffItem.encFileKeyNonce!,
),
);
}
try {
@@ -1618,9 +1618,6 @@ class CollectionsService {
params["files"] = [];
for (final batchFile in batch) {
final fileKey = getFileKey(batchFile);
_logger.info(
"srcCollection : $srcCollectionID file: ${batchFile.uploadedFileID} key: ${CryptoUtil.bin2base64(fileKey)} ",
);
final encryptedKeyData =
CryptoUtil.encryptSync(fileKey, getCollectionKey(dstCollectionID));
batchFile.encryptedKey =
@@ -1847,48 +1844,38 @@ class CollectionsService {
}
final batchedFiles = files.chunks(batchSize);
final List<EnteFile> movedFiles = [];
for (final batch in batchedFiles) {
final params = <String, dynamic>{};
params["toCollectionID"] = toCollectionID;
params["fromCollectionID"] = fromCollectionID;
params["files"] = [];
final List<EnteFile> batchMovedFiles = [];
final List<DiffFileItem> collectionDiffItems = [];
for (final file in batch) {
final fileKey = getFileKey(file);
file.generatedID =
null; // So that a new entry is created in the FilesDB
file.collectionID = toCollectionID;
final encryptedKeyData =
CryptoUtil.encryptSync(fileKey, getCollectionKey(toCollectionID));
file.encryptedKey =
CryptoUtil.bin2base64(encryptedKeyData.encryptedData!);
file.keyDecryptionNonce =
CryptoUtil.bin2base64(encryptedKeyData.nonce!);
final newFile = moveOrAddEntry(file, toCollectionID);
final DiffFileItem localDiffItem = buildDiffItem(newFile);
batchMovedFiles.add(newFile);
collectionDiffItems.add(localDiffItem);
params["files"].add(
CollectionFileItem(
file.uploadedFileID!,
file.encryptedKey!,
file.keyDecryptionNonce!,
).toMap(),
CollectionFileItem.req(
localDiffItem.fileID,
encryptedKey: localDiffItem.encFileKey!,
keyDecryptionNonce: localDiffItem.encFileKeyNonce!,
),
);
}
await _enteDio.post(
"/collections/move-files",
data: params,
);
await remoteDB.insertFilesDiff(collectionDiffItems);
await remoteDB.deleteCFEnteries(
fromCollectionID,
files.map((e) => e.uploadedFileID!).toList(),
);
movedFiles.addAll(batchMovedFiles);
}
// insert new files in the toCollection which are not part of the toCollection
final existingUploadedIDs =
await remoteDB.getUploadedFileIDs(toCollectionID);
files.removeWhere(
(element) => existingUploadedIDs.contains(element.uploadedFileID),
);
await _filesDB.insertMultiple(files);
// remove files from old collection
await remoteDB.deleteCFEnteries(
fromCollectionID,
files.map((e) => e.uploadedFileID!).toList(),
);
Bus.instance.fire(
CollectionUpdatedEvent(
fromCollectionID,
@@ -1898,7 +1885,7 @@ class CollectionsService {
),
);
Bus.instance.fire(
CollectionUpdatedEvent(toCollectionID, files, "moveTo"),
CollectionUpdatedEvent(toCollectionID, movedFiles, "moveTo"),
);
}

View File

@@ -1,7 +1,6 @@
import "package:ente_crypto/ente_crypto.dart";
import "package:photos/models/api/diff/diff.dart";
import "package:photos/models/file/file.dart";
import "package:photos/models/file/remote/asset.dart";
import "package:photos/models/file/remote/file_entry.dart";
import "package:photos/services/collections_service.dart";
import "package:photos/utils/file_key.dart";
@@ -33,18 +32,14 @@ extension CollectionsServiceMapper on CollectionsService {
);
}
DiffFileItem mapDiffItem(EnteFile file) {
DiffFileItem buildDiffItem(EnteFile file) {
if (file.remoteAsset == null || file.fileEntry == null) {
throw ArgumentError(
"File must have remoteAsset and fileEntry to be mapped.",
);
throw ArgumentError("must have remoteAsset and fileEntry");
}
final remoteAsset = file.remoteAsset!;
final cf = file.fileEntry!;
if (remoteAsset.id != cf.fileID) {
throw ArgumentError(
"File ID in remote asset does not match file entry.",
);
throw ArgumentError("File ID in remote asset does not match file entry.");
}
return DiffFileItem(