fix: use smart-album entityType and remove merge logic + better id

This commit is contained in:
Prateek Sunal
2025-07-23 15:40:49 +05:30
parent e9c084bd54
commit 3387361489
4 changed files with 27 additions and 105 deletions

View File

@@ -5,7 +5,7 @@ enum EntityType {
person,
cgroup,
unknown,
smartConfig,
smartAlbum,
}
EntityType typeFromString(String type) {
@@ -28,6 +28,7 @@ extension EntityTypeExtn on EntityType {
switch (this) {
case EntityType.location:
case EntityType.person:
case EntityType.smartAlbum:
return false;
default:
return true;
@@ -42,8 +43,8 @@ extension EntityTypeExtn on EntityType {
return "person";
case EntityType.cgroup:
return "cgroup";
case EntityType.smartConfig:
return "sconfig";
case EntityType.smartAlbum:
return "smart_album";
case EntityType.unknown:
return "unknown";
}

View File

@@ -69,10 +69,8 @@ class SmartAlbumConfig {
// toJson and fromJson methods
Map<String, dynamic> toJson() {
return {
"remote_id": id,
"collection_id": collectionId,
"person_ids": personIDs.toList(),
"updated_at": updatedAt,
"info_map": infoMap.map(
(key, value) => MapEntry(
key,
@@ -110,34 +108,4 @@ class SmartAlbumConfig {
updatedAt: updatedAt ?? DateTime.now().millisecondsSinceEpoch,
);
}
SmartAlbumConfig merge(SmartAlbumConfig b) {
if (id == b.id) {
if (updatedAt >= b.updatedAt) {
return this;
}
return b;
}
return SmartAlbumConfig(
id: b.updatedAt <= updatedAt ? b.id : id,
collectionId: b.collectionId,
personIDs: personIDs.union(b.personIDs),
infoMap: {
...infoMap,
...b.infoMap.map(
(key, value) => MapEntry(
key,
(
updatedAt: infoMap[key]?.updatedAt != null &&
infoMap[key]!.updatedAt > value.updatedAt
? infoMap[key]!.updatedAt
: value.updatedAt,
addedFiles: infoMap[key]?.addedFiles.union(value.addedFiles) ??
value.addedFiles,
),
),
),
},
);
}
}

View File

@@ -60,6 +60,7 @@ class EntityService {
EntityType type,
Map<String, dynamic> jsonMap, {
String? id,
bool addWithCustomID = false,
}) async {
final String plainText = jsonEncode(jsonMap);
final key = await getOrCreateEntityKey(type);
@@ -81,7 +82,7 @@ class EntityService {
);
late LocalEntityData localData;
final EntityData data = id == null
final EntityData data = id == null || addWithCustomID
? await _gateway.createEntity(type, encryptedData, header)
: await _gateway.updateEntity(type, id, encryptedData, header);
localData = LocalEntityData(
@@ -106,8 +107,7 @@ class EntityService {
try {
await _remoteToLocalSync(EntityType.location);
await _remoteToLocalSync(EntityType.cgroup);
// TODO: Change to smart config
await _remoteToLocalSync(EntityType.person);
await _remoteToLocalSync(EntityType.smartAlbum);
} catch (e) {
_logger.severe("Failed to sync entities", e);
}

View File

@@ -2,6 +2,7 @@ import "dart:async";
import "dart:convert";
import "package:logging/logging.dart";
import "package:photos/core/configuration.dart";
import "package:photos/models/api/entity/type.dart";
import "package:photos/models/collection/smart_album_config.dart";
import "package:photos/models/local_entity_data.dart";
@@ -18,15 +19,13 @@ class SmartAlbumsService {
Future<Map<int, SmartAlbumConfig>>? _cachedConfigsFuture;
static const type = EntityType.person;
void clearCache() {
_cachedConfigsFuture = null;
_lastCacheRefreshTime = 0;
}
int lastRemoteSyncTime() {
return entityService.lastSyncTime(type);
return entityService.lastSyncTime(EntityType.smartAlbum);
}
Future<Map<int, SmartAlbumConfig>> getSmartConfigs() async {
@@ -42,79 +41,28 @@ class SmartAlbumsService {
Future<Map<int, SmartAlbumConfig>> _fetchAndCacheSConfigs() async {
_logger.finest("reading all smart configs from local db");
final entities = await entityService.getEntities(type);
final entities = await entityService.getEntities(EntityType.smartAlbum);
final result = _decodeSConfigEntities(
{"entity": entities},
);
final result = _decodeSConfigEntities({"entity": entities});
final sconfigs = result["sconfigs"] as Map<int, SmartAlbumConfig>;
final collectionToUpdate = result["collectionToUpdate"] as Set<int>;
final idToDelete = result["idToDelete"] as Set<String>;
// update the merged config to remote db
for (final collectionid in collectionToUpdate) {
try {
await saveConfig(sconfigs[collectionid]!);
} catch (error, stackTrace) {
_logger.severe(
"Failed to update smart album config for collection $collectionid",
error,
stackTrace,
);
}
}
// delete all remote ids that are merged into the config
for (final remoteId in idToDelete) {
try {
await _deleteEntry(id: remoteId);
} catch (error, stackTrace) {
_logger.severe(
"Failed to delete smart album config for remote id $remoteId",
error,
stackTrace,
);
}
}
return sconfigs;
return result;
}
Map<String, dynamic> _decodeSConfigEntities(
Map<int, SmartAlbumConfig> _decodeSConfigEntities(
Map<String, dynamic> param,
) {
final entities = (param["entity"] as List<LocalEntityData>);
final Map<int, SmartAlbumConfig> sconfigs = {};
final Set<int> collectionToUpdate = {};
final Set<String> idToDelete = {};
for (final entity in entities) {
try {
var config = SmartAlbumConfig.fromJson(
final config = SmartAlbumConfig.fromJson(
json.decode(entity.data),
entity.id,
entity.updatedAt,
);
if (sconfigs.containsKey(config.collectionId)) {
final existingConfig = sconfigs[config.collectionId]!;
final collectionIdToKeep = config.updatedAt < existingConfig.updatedAt
? config.collectionId
: existingConfig.collectionId;
final remoteIdToDelete = config.updatedAt < existingConfig.updatedAt
? existingConfig.id
: config.id;
config = config.merge(sconfigs[config.collectionId]!);
// Update the config to be updated and deleted list
collectionToUpdate.add(collectionIdToKeep);
idToDelete.add(remoteIdToDelete!);
}
sconfigs[config.collectionId] = config;
} catch (error, stackTrace) {
_logger.severe(
@@ -125,11 +73,7 @@ class SmartAlbumsService {
}
}
return {
"sconfigs": sconfigs,
"collectionToUpdate": collectionToUpdate,
"idToDelete": idToDelete,
};
return sconfigs;
}
Future<void> syncSmartAlbums() async {
@@ -191,10 +135,14 @@ class SmartAlbumsService {
}
Future<void> saveConfig(SmartAlbumConfig config) async {
final userId = Configuration.instance.getUserID();
await _addOrUpdateEntity(
type,
EntityType.smartAlbum,
config.toJson(),
id: config.id,
collectionId: config.collectionId,
addWithCustomID: config.id == null,
userId: userId,
);
}
@@ -207,13 +155,18 @@ class SmartAlbumsService {
Future<LocalEntityData> _addOrUpdateEntity(
EntityType type,
Map<String, dynamic> jsonMap, {
String? id,
required int collectionId,
bool addWithCustomID = false,
int? userId,
}) async {
final id = "sa_${userId!}_$collectionId";
final result = await entityService.addOrUpdate(
type,
jsonMap,
id: id,
addWithCustomID: addWithCustomID,
);
_lastCacheRefreshTime = 0; // Invalidate cache
return result;
}