diff --git a/mobile/apps/photos/lib/models/similar_files.dart b/mobile/apps/photos/lib/models/similar_files.dart index ee946c499a..eadbc34cb1 100644 --- a/mobile/apps/photos/lib/models/similar_files.dart +++ b/mobile/apps/photos/lib/models/similar_files.dart @@ -1,18 +1,21 @@ +import "dart:convert"; + import "package:photos/models/file/file.dart"; +import "package:photos/services/search_service.dart"; class SimilarFiles { final List files; final Set fileIds; - final double furthestDistance; + double furthestDistance; SimilarFiles( this.files, this.furthestDistance, - ) : fileIds = files.map((file) => file.uploadedFileID!).toSet(); + ) : fileIds = files.map((file) => file.uploadedFileID!).toSet(); - int get totalSize => - files.fold(0, (sum, file) => sum + (file.fileSize ?? 0)); + int get totalSize => files.fold(0, (sum, file) => sum + (file.fileSize ?? 0)); + // TODO: lau: check if we're not using this wrong bool get isEmpty => files.isEmpty; int get length => files.length; @@ -26,7 +29,125 @@ class SimilarFiles { fileIds.remove(file.uploadedFileID); } + void addFile(EnteFile file) { + files.add(file); + fileIds.add(file.uploadedFileID!); + } + bool containsFile(EnteFile file) { return fileIds.contains(file.uploadedFileID); } + + Map toJson() { + return { + 'fileIDs': fileIds.toList(), + 'distance': furthestDistance, + }; + } + + String toJsonString() { + return jsonEncode(toJson()); + } + + factory SimilarFiles.fromJson( + Map json, + Map fileMap, + ) { + final fileIds = List.from(json['fileIDs']); + final furthestDistance = json['distance'].toDouble(); + + final files = []; + for (final fileId in fileIds) { + final file = fileMap[fileId]; + if (file == null) continue; + files.add(file); + } + + return SimilarFiles( + files, + furthestDistance, + ); + } + + static SimilarFiles fromJsonString( + String jsonString, + Map fileMap, + ) { + return SimilarFiles.fromJson(jsonDecode(jsonString), fileMap); + } +} + +class SimilarFilesCache { + final List similarFilesJsonStringList; + final Set allCheckedFileIDs; + final double distanceThreshold; + final bool exact; + + List? _similarFilesList; + + /// Milliseconds since epoch + final int cachedTime; + + SimilarFilesCache({ + required this.similarFilesJsonStringList, + required this.allCheckedFileIDs, + required this.distanceThreshold, + required this.exact, + required this.cachedTime, + }); + + Future> similarFilesList() async { + final allFiles = await SearchService.instance.getAllFilesForSearch(); + final fileMap = {}; + for (final file in allFiles) { + if (file.uploadedFileID == null) continue; + fileMap[file.uploadedFileID!] = file; + } + _similarFilesList ??= similarFilesJsonStringList.map((jsonString) { + return SimilarFiles.fromJson(jsonDecode(jsonString), fileMap); + }).toList(); + return _similarFilesList!; + } + + Future> getGroupedFileIDs() async { + final similarFiles = await similarFilesList(); + final groupedFileIDs = {}; + for (final files in similarFiles) { + groupedFileIDs.addAll(files.fileIds); + } + return groupedFileIDs; + } + + factory SimilarFilesCache.fromJson( + Map json, + ) { + return SimilarFilesCache( + similarFilesJsonStringList: + json['similarFilesJsonStringList'] as List, + allCheckedFileIDs: Set.from(json['allCheckedFileIDs']), + distanceThreshold: json['distanceThreshold'] as double, + exact: json['exact'] as bool, + cachedTime: json['cachedTime'] as int, + ); + } + + Map toJson() { + return { + 'similarFilesJsonStringList': similarFilesJsonStringList, + 'allCheckedFileIDs': allCheckedFileIDs.toList(), + 'distanceThreshold': distanceThreshold, + 'exact': exact, + 'cachedTime': cachedTime, + }; + } + + static String encodeToJsonString(SimilarFilesCache cache) { + return jsonEncode(cache.toJson()); + } + + static SimilarFilesCache decodeFromJsonString( + String jsonString, + ) { + return SimilarFilesCache.fromJson(jsonDecode(jsonString)); + } }