From ca62012a6f957670c0701a60903e96277a166a7d Mon Sep 17 00:00:00 2001 From: Neeraj Gupta <254676+ua741@users.noreply.github.com> Date: Mon, 21 Apr 2025 15:04:42 +0530 Subject: [PATCH] Store local mapping & creation time for remote files --- mobile/lib/db/remote/db.dart | 2 +- mobile/lib/db/remote/schema.dart | 31 +++++++++++--- mobile/lib/models/api/diff/diff.dart | 61 ++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 7 deletions(-) diff --git a/mobile/lib/db/remote/db.dart b/mobile/lib/db/remote/db.dart index 8ae024832a..2f2ededd93 100644 --- a/mobile/lib/db/remote/db.dart +++ b/mobile/lib/db/remote/db.dart @@ -78,7 +78,7 @@ class RemoteDB with SqlDbBase { collectionFileValues, ), _sqliteDB.executeBatch( - 'INSERT OR REPLACE INTO files ($filesColumns) values(?, ?, ?, ?, ?, ?, ?, ?)', + 'INSERT INTO files ($filesColumns) values(${getParams(17)}) ON CONFLICT(id) DO UPDATE SET $filesUpdateColumns', fileValues, ), ]); diff --git a/mobile/lib/db/remote/schema.dart b/mobile/lib/db/remote/schema.dart index 76d2bbbf8d..6e3efcbf3f 100644 --- a/mobile/lib/db/remote/schema.dart +++ b/mobile/lib/db/remote/schema.dart @@ -12,9 +12,20 @@ final String updateCollectionColumns = collectionColumns const collectionFilesColumns = 'collection_id, file_id, enc_key, enc_key_nonce, created_at, updated_at, is_deleted'; - const filesColumns = - 'id, owner_id, file_header, thumb_header, metadata, priv_metadata, pub_metadata, info'; + 'id, owner_id, file_header, thumb_header, creation_time, modification_time, title, size, hash, lat, lng, ' + 'metadata, priv_metadata, pub_metadata, info, local_id, local_mapping_src'; + +final String filesUpdateColumns = filesColumns + .split(', ') + .where( + (column) => (column != 'id' || + column != 'local_id' || + column != 'local_mapping_src'), + ) // Exclude primary key from update + .map((column) => '$column = excluded.$column') // Use excluded virtual table + .join(', '); + const trashedFilesColumns = 'id, owner_id, file_header, thumb_header, metadata, priv_metadata, pub_metadata, info, trash_data'; @@ -62,11 +73,19 @@ class RemoteDBMigration { owner_id INTEGER NOT NULL, file_header BLOB NOT NULL, thumb_header BLOB NOT NULL, + creation_time INTEGER NOT NULL, + modification_time INTEGER NOT NULL, + title TEXT NOT NULL, + size INTEGER NOT NULL DEFAULT -1, + hash TEXT, + lat REAL DEFAULT NULL, + lng REAL DEFAULT NULL, metadata TEXT NOT NULL, - priv_metadata TEXT NOT NULL DEFAULT '{}', - pub_metadata TEXT NOT NULL DEFAULT '{}', - info TEXT DEFAULT '{}', - trash_data TEXT + priv_metadata TEXT, + pub_metadata TEXT, + info TEXT, + local_id TEXT DEFAULT NULL, + local_mapping_src TEXT DEFAULT NULL ) ''', ''' diff --git a/mobile/lib/models/api/diff/diff.dart b/mobile/lib/models/api/diff/diff.dart index d58c7b1777..ad0ac5c424 100644 --- a/mobile/lib/models/api/diff/diff.dart +++ b/mobile/lib/models/api/diff/diff.dart @@ -1,6 +1,10 @@ import "dart:convert"; +import "dart:io"; import "dart:typed_data"; +import "package:photos/models/location/location.dart"; +import "package:photos/models/metadata/file_magic.dart"; + class Info { final int fileSize; final int thumbSize; @@ -92,17 +96,74 @@ class FileItem { } List rowValues() { + final Location? loc = location; return [ fileID, ownerID, fileDecryotionHeader, thumnailDecryptionHeader, + creationTime, + modificationTime, + title, + fileSize, + hash, + loc?.latitude, + loc?.longitude, metadata?.toEncodedJson(), magicMetadata?.toEncodedJson(), pubMagicMetadata?.toEncodedJson(), info?.toEncodedJson(), + matchLocalID, + 'remote_data', ]; } + + String get title => + pubMagicMetadata?.data['editedName'] ?? metadata?.data['title'] ?? ""; + + String? get localID => metadata?.data['localID']; + + String? get matchLocalID => localID == null || deviceFolder == null + ? null + : Platform.isIOS + ? localID + : '$localID-$deviceFolder-$title'; + + String? get deviceFolder => metadata?.data['deviceFolder']; + + Location? get location { + if (pubMagicMetadata != null && pubMagicMetadata!.data[latKey] != null) { + return Location( + latitude: pubMagicMetadata!.data[latKey], + longitude: pubMagicMetadata!.data[longKey], + ); + } + if (metadata != null && metadata!.data['latitude'] == null || + metadata!.data['longitude'] == null) { + return null; + } + final latitude = double.tryParse(metadata!.data["latitude"].toString()); + final longitude = double.tryParse(metadata!.data["longitude"].toString()); + if (latitude == null || longitude == null) { + return null; + } else { + return Location(latitude: latitude, longitude: longitude); + } + } + + int get creationTime => + pubMagicMetadata?.data['editedTime'] ?? + metadata?.data['creationTime'] ?? + 0; + + int get modificationTime => + metadata?.data['modificationTime'] ?? creationTime; + + // note: during remote to local sync, older live photo hash format from desktop + // is already converted to the new format + String? get hash => metadata?.data['hash']; + + int get fileSize => info?.fileSize ?? -1; } class CollectionFileItem {