Compare commits

...

54 commits

Author SHA1 Message Date
Laurens Priem 5e18ae1938
[mob][photos] Bump (#1889)
## Description

Bump
2024-05-27 18:35:31 +05:30
laurenspriem 37d3776e28 [mob][photos] Bump 2024-05-27 18:34:26 +05:30
Laurens Priem 05579ef368
[mob][photos] Fetch remote feedback before clustering (#1888)
## Description

See title
2024-05-27 18:33:22 +05:30
laurenspriem 90e467c7c0 [mob][photos] Fetch remote feedback before clustering 2024-05-27 18:31:17 +05:30
ashilkn 99cf23d286 [mob][photos] Resolve conflicts and merge main 2024-05-27 18:03:01 +05:30
laurenspriem 7a6fa1cd80 Merge remote-tracking branch 'origin/main' into migrate_files_db_to_sqlite_async 2024-05-24 18:23:32 +05:30
ashilkn 022448155d [mob][photos] Bump up version to v0.8.111 2024-05-24 15:48:39 +05:30
ashilkn ed830dc387 Merge branch 'main' into migrate_files_db_to_sqlite_async 2024-05-24 15:04:50 +05:30
ashilkn a79d11c263 [mob][photos] Add more info in error message 2024-05-24 14:43:39 +05:30
ashilkn a470ed4dfa Merge branch 'main' into migrate_files_db_to_sqlite_async 2024-05-24 14:39:46 +05:30
ashilkn 500d7da306 [mob][photos] Remove log lines used for testing 2024-05-24 14:39:16 +05:30
ashilkn 637adb4617 [mob][photos] Simplify how FilesDB migrates 2024-05-24 14:21:02 +05:30
ashilkn 320f79bb52 Merge branch 'main' into migrate_files_db_to_sqlite_async 2024-05-24 09:53:44 +05:30
ashilkn 484d2dc6cb Merge branch 'main' into migrate_files_db_to_sqlite_async 2024-05-23 19:04:07 +05:30
ashilkn a63558a309 [mob][photos] Resolve merge conflicts and merge main 2024-05-23 17:36:10 +05:30
ashilkn 7aa26a950d [mob][photos] Bump up to version 0.8.103 2024-05-22 20:44:10 +05:30
ashilkn b74be0b8f1 Merge branch 'main' into migrate_files_db_to_sqlite_async 2024-05-22 20:41:31 +05:30
ashilkn 8caa559812 [mob][photos] Resolve merge conflicts and merge main 2024-05-22 18:33:43 +05:30
ashilkn 22fc67c8c3 [mob][photos] Remove unnecessary parameters 2024-05-22 16:17:05 +05:30
ashilkn cb9ac0d939 [mob][photos] bump up version to 0.8.100 2024-05-22 14:21:31 +05:30
ashilkn f513473362 [mob][photos] Check db version when sqflite was used and run only migrations that are necessary using sqlite_async
Tested adding a new migration and it works. Tested two cases (a)Fresh install (b)Opening app with new migration added and the last db migration was done when sqflite was used
2024-05-22 14:20:29 +05:30
ashilkn 4fb9e75394 [mob][photos] Bump up version to 0.8.99 2024-05-21 18:36:01 +05:30
ashilkn ee348f5585 Merge branch 'main' into migrate_files_db_to_sqlite_async 2024-05-21 18:34:48 +05:30
ashilkn eaca151a9f [mob][photos] Minor change 2024-05-21 18:34:11 +05:30
ashilkn e3ea22f479 [mob][photos] add comment 2024-05-21 17:44:38 +05:30
ashilkn 5a017616f5 [mob][photos] Fix sqlite command syntax errors 2024-05-21 17:10:42 +05:30
ashilkn 159fdf83ad [mob][photos] Migrate to sqlite_async(14) 2024-05-21 16:54:09 +05:30
ashilkn b2a359ca59 [mob][photos] Migrate to sqlite_async(13): Use getAll() instead of execute() for SELECT commands 2024-05-21 16:53:49 +05:30
ashilkn cae3748995 [mob][photos] Resolve conflicts and merge main 2024-05-21 16:32:03 +05:30
ashilkn 49e64b3d4c [mob][photos] Fix issue with EnteFile not having location data 2024-05-21 16:12:44 +05:30
ashilkn a7e0f3df7b [mob][photos] Remove sqflite import in filesDB 2024-05-17 17:05:58 +05:30
ashilkn ab9cef689d [mob][photos] Create ConflictAlgorithm enum and stop using it from sqflite 2024-05-17 16:40:59 +05:30
ashilkn 18d68bbdf3 Migrate to sqlite_async(13): Migrate db migration to use sqlite_async 2024-05-17 16:34:04 +05:30
ashilkn 48436694eb [mob][photos] Fix incorrent sqlite operation 2024-05-17 16:28:13 +05:30
ashilkn 16178b6f09 [mob][photos] Add missing paranthesis 2024-05-17 15:09:10 +05:30
ashilkn c2b6032b6f [mob][photos] Fix broken query 2024-05-17 13:40:38 +05:30
ashilkn a44e5f9505 [mob][photos] Migrate to sqlite_async(12): Migrate entities 2024-05-17 11:47:32 +05:30
ashilkn 28ddb93747 [mob][photos] Add missing parameters for query 2024-05-16 20:17:58 +05:30
ashilkn 2b0fa9bae6 [mob][photos] Migrate to sqlite_async(11) 2024-05-16 19:34:59 +05:30
ashilkn 16d54645bc [mob][photos] Migrate to sqlite_async(10) 2024-05-16 18:02:39 +05:30
ashilkn dec7c45310 [mob][photos] Migrate to sqlite_async(9) 2024-05-16 16:41:57 +05:30
ashilkn 1a360d3ee7 [mob][photos] Migrate to sqlite_async(8): Migrate insert() + rearrange + clean up 2024-05-16 15:37:00 +05:30
ashilkn 584a37d2a2 [mob][photos] Remove obsolete code
This code is from when we used to support favoriting un-uploaded files
2024-05-16 14:20:03 +05:30
ashilkn cd023b621a [mob][photos] Remove optional parameter which should never be used
Since generatedID (_id) has NOT NULL constrain, it shouldn't be in a parameter set of a query
2024-05-16 12:59:19 +05:30
ashilkn 7fdc2b5e66 [mob][photos] Migrate to sqlite_async(8): Fix faulty update statements due to incorrect query generation 2024-05-16 12:48:21 +05:30
ashilkn 1e7779a819 [mob][photos] Remove method inline annotation which doesn
't have noticeable perf improvement + remove commented out code
2024-05-15 21:18:14 +05:30
ashilkn 56478fcb8a [mob][photos] avoid unnecessary compute 2024-05-15 21:10:37 +05:30
ashilkn e179d351d9 [mob][photos] Migrate to sqlite_async(7): Assign String '{}' instead of map object {} to fix unexpected behaviour 2024-05-15 21:04:32 +05:30
ashilkn 25554209ec [mob][photos] Migrate to sqlite_async)(6): Migrate insertMultipleNew to use sqlite_async 2024-05-15 19:52:55 +05:30
ashilkn d1a5921c27 [mob][photos] Migrate to sqlite_async(5): Create a method to get parameter set from file without calling getRowForFile() 2024-05-15 15:28:24 +05:30
ashilkn ff14eb1d5a [mob][photos] Migrate to sqlite_async (4) 2024-05-14 14:59:03 +05:30
ashilkn 8fcd05b95f [mob][photos] Migrate to sqlite_async (3) 2024-05-13 18:29:01 +05:30
ashilkn 3a0882a1a9 [mob][photos] Migrate to sqlite_async (2): Migrate all update queries in filesDB 2024-05-13 17:57:22 +05:30
ashilkn 5bd845d32b [mob][photos] Migrate to sqlite_async (1) 2024-05-13 15:39:35 +05:30
14 changed files with 890 additions and 628 deletions

View file

@ -22,61 +22,55 @@ extension DeviceFiles on FilesDB {
ConflictAlgorithm conflictAlgorithm = ConflictAlgorithm.ignore,
}) async {
debugPrint("Inserting missing PathIDToLocalIDMapping");
final db = await database;
var batch = db.batch();
final parameterSets = <List<Object?>>[];
int batchCounter = 0;
for (MapEntry e in mappingToAdd.entries) {
final String pathID = e.key;
for (String localID in e.value) {
parameterSets.add([localID, pathID]);
batchCounter++;
if (batchCounter == 400) {
await batch.commit(noResult: true);
batch = db.batch();
await _insertBatch(parameterSets, conflictAlgorithm);
parameterSets.clear();
batchCounter = 0;
}
batch.insert(
"device_files",
{
"id": localID,
"path_id": pathID,
},
conflictAlgorithm: conflictAlgorithm,
);
batchCounter++;
}
}
await batch.commit(noResult: true);
await _insertBatch(parameterSets, conflictAlgorithm);
parameterSets.clear();
batchCounter = 0;
}
Future<void> deletePathIDToLocalIDMapping(
Map<String, Set<String>> mappingsToRemove,
) async {
debugPrint("removing PathIDToLocalIDMapping");
final db = await database;
var batch = db.batch();
final parameterSets = <List<Object?>>[];
int batchCounter = 0;
for (MapEntry e in mappingsToRemove.entries) {
final String pathID = e.key;
for (String localID in e.value) {
parameterSets.add([localID, pathID]);
batchCounter++;
if (batchCounter == 400) {
await batch.commit(noResult: true);
batch = db.batch();
await _deleteBatch(parameterSets);
parameterSets.clear();
batchCounter = 0;
}
batch.delete(
"device_files",
where: 'id = ? AND path_id = ?',
whereArgs: [localID, pathID],
);
batchCounter++;
}
}
await batch.commit(noResult: true);
await _deleteBatch(parameterSets);
parameterSets.clear();
batchCounter = 0;
}
Future<Map<String, int>> getDevicePathIDToImportedFileCount() async {
try {
final db = await database;
final rows = await db.rawQuery(
final db = await sqliteAsyncDB;
final rows = await db.getAll(
'''
SELECT count(*) as count, path_id
FROM device_files
@ -96,8 +90,8 @@ extension DeviceFiles on FilesDB {
Future<Map<String, Set<String>>> getDevicePathIDToLocalIDMap() async {
try {
final db = await database;
final rows = await db.rawQuery(
final db = await sqliteAsyncDB;
final rows = await db.getAll(
''' SELECT id, path_id FROM device_files; ''',
);
final result = <String, Set<String>>{};
@ -116,8 +110,8 @@ extension DeviceFiles on FilesDB {
}
Future<Set<String>> getDevicePathIDs() async {
final Database db = await database;
final rows = await db.rawQuery(
final db = await sqliteAsyncDB;
final rows = await db.getAll(
'''
SELECT id FROM device_collections
''',
@ -133,34 +127,42 @@ extension DeviceFiles on FilesDB {
List<LocalPathAsset> localPathAssets, {
bool shouldAutoBackup = false,
}) async {
final Database db = await database;
final db = await sqliteAsyncDB;
final Map<String, Set<String>> pathIDToLocalIDsMap = {};
try {
final batch = db.batch();
final Set<String> existingPathIds = await getDevicePathIDs();
final parameterSetsForUpdate = <List<Object?>>[];
final parameterSetsForInsert = <List<Object?>>[];
for (LocalPathAsset localPathAsset in localPathAssets) {
if (localPathAsset.localIDs.isNotEmpty) {
pathIDToLocalIDsMap[localPathAsset.pathID] = localPathAsset.localIDs;
}
if (existingPathIds.contains(localPathAsset.pathID)) {
batch.rawUpdate(
"UPDATE device_collections SET name = ? where id = "
"?",
[localPathAsset.pathName, localPathAsset.pathID],
);
parameterSetsForUpdate
.add([localPathAsset.pathName, localPathAsset.pathID]);
} else if (localPathAsset.localIDs.isNotEmpty) {
batch.insert(
"device_collections",
{
"id": localPathAsset.pathID,
"name": localPathAsset.pathName,
"should_backup": shouldAutoBackup ? _sqlBoolTrue : _sqlBoolFalse,
},
conflictAlgorithm: ConflictAlgorithm.ignore,
);
parameterSetsForInsert.add([
localPathAsset.pathID,
localPathAsset.pathName,
shouldAutoBackup ? _sqlBoolTrue : _sqlBoolFalse,
]);
}
}
await batch.commit(noResult: true);
await db.executeBatch(
'''
INSERT OR IGNORE INTO device_collections (id, name, should_backup) VALUES (?, ?, ?);
''',
parameterSetsForInsert,
);
await db.executeBatch(
'''
UPDATE device_collections SET name = ? WHERE id = ?;
''',
parameterSetsForUpdate,
);
// add the mappings for localIDs
if (pathIDToLocalIDsMap.isNotEmpty) {
await insertPathIDToLocalIDMapping(pathIDToLocalIDsMap);
@ -177,7 +179,7 @@ extension DeviceFiles on FilesDB {
}) async {
bool hasUpdated = false;
try {
final Database db = await database;
final db = await sqliteAsyncDB;
final Set<String> existingPathIds = await getDevicePathIDs();
for (Tuple2<AssetPathEntity, String> tup in devicePathInfo) {
final AssetPathEntity pathEntity = tup.item1;
@ -185,35 +187,42 @@ extension DeviceFiles on FilesDB {
final String localID = tup.item2;
final bool shouldUpdate = existingPathIds.contains(pathEntity.id);
if (shouldUpdate) {
final rowUpdated = await db.rawUpdate(
"UPDATE device_collections SET name = ?, cover_id = ?, count"
" = ? where id = ? AND (name != ? OR cover_id != ? OR count != ?)",
[
pathEntity.name,
localID,
assetCount,
pathEntity.id,
pathEntity.name,
localID,
assetCount,
],
);
final rowUpdated = await db.writeTransaction((tx) async {
await tx.execute(
"UPDATE device_collections SET name = ?, cover_id = ?, count"
" = ? where id = ? AND (name != ? OR cover_id != ? OR count != ?)",
[
pathEntity.name,
localID,
assetCount,
pathEntity.id,
pathEntity.name,
localID,
assetCount,
],
);
final result = await tx.get("SELECT changes();");
return result["changes()"] as int;
});
if (rowUpdated > 0) {
_logger.fine("Updated $rowUpdated rows for ${pathEntity.name}");
hasUpdated = true;
}
} else {
hasUpdated = true;
await db.insert(
"device_collections",
{
"id": pathEntity.id,
"name": pathEntity.name,
"count": assetCount,
"cover_id": localID,
"should_backup": shouldBackup ? _sqlBoolTrue : _sqlBoolFalse,
},
conflictAlgorithm: ConflictAlgorithm.ignore,
await db.execute(
'''
INSERT INTO device_collections (id, name, count, cover_id, should_backup)
VALUES (?, ?, ?, ?, ?);
''',
[
pathEntity.id,
pathEntity.name,
assetCount,
localID,
shouldBackup ? _sqlBoolTrue : _sqlBoolFalse,
],
);
}
}
@ -231,15 +240,17 @@ extension DeviceFiles on FilesDB {
// feature, where we delete files which are backed up. Deleting such
// entries here result in us losing out on the information that
// those folders were marked for automatic backup.
await db.delete(
"device_collections",
where: 'id = ? and should_backup = $_sqlBoolFalse ',
whereArgs: [pathID],
await db.execute(
'''
DELETE FROM device_collections WHERE id = ? AND should_backup = $_sqlBoolFalse;
''',
[pathID],
);
await db.delete(
"device_files",
where: 'path_id = ?',
whereArgs: [pathID],
await db.execute(
'''
DELETE FROM device_files WHERE path_id = ?;
''',
[pathID],
);
}
}
@ -253,8 +264,8 @@ extension DeviceFiles on FilesDB {
// getDeviceSyncCollectionIDs returns the collectionIDs for the
// deviceCollections which are marked for auto-backup
Future<Set<int>> getDeviceSyncCollectionIDs() async {
final Database db = await database;
final rows = await db.rawQuery(
final db = await sqliteAsyncDB;
final rows = await db.getAll(
'''
SELECT collection_id FROM device_collections where should_backup =
$_sqlBoolTrue
@ -268,40 +279,47 @@ extension DeviceFiles on FilesDB {
return result;
}
Future<void> updateDevicePathSyncStatus(Map<String, bool> syncStatus) async {
final db = await database;
var batch = db.batch();
Future<void> updateDevicePathSyncStatus(
Map<String, bool> syncStatus,
) async {
final db = await sqliteAsyncDB;
int batchCounter = 0;
final parameterSets = <List<Object?>>[];
for (MapEntry e in syncStatus.entries) {
final String pathID = e.key;
parameterSets.add([e.value ? _sqlBoolTrue : _sqlBoolFalse, pathID]);
batchCounter++;
if (batchCounter == 400) {
await batch.commit(noResult: true);
batch = db.batch();
await db.executeBatch(
'''
UPDATE device_collections SET should_backup = ? WHERE id = ?;
''',
parameterSets,
);
parameterSets.clear();
batchCounter = 0;
}
batch.update(
"device_collections",
{
"should_backup": e.value ? _sqlBoolTrue : _sqlBoolFalse,
},
where: 'id = ?',
whereArgs: [pathID],
);
batchCounter++;
}
await batch.commit(noResult: true);
await db.executeBatch(
'''
UPDATE device_collections SET should_backup = ? WHERE id = ?;
''',
parameterSets,
);
}
Future<void> updateDeviceCollection(
String pathID,
int collectionID,
) async {
final db = await database;
await db.update(
"device_collections",
{"collection_id": collectionID},
where: 'id = ?',
whereArgs: [pathID],
final db = await sqliteAsyncDB;
await db.execute(
'''
UPDATE device_collections SET collection_id = ? WHERE id = ?;
''',
[collectionID, pathID],
);
return;
}
@ -314,7 +332,7 @@ extension DeviceFiles on FilesDB {
int? limit,
bool? asc,
}) async {
final db = await database;
final db = await sqliteAsyncDB;
final order = (asc ?? false ? 'ASC' : 'DESC');
final String rawQuery = '''
SELECT *
@ -329,7 +347,7 @@ extension DeviceFiles on FilesDB {
ORDER BY ${FilesDB.columnCreationTime} $order , ${FilesDB.columnModificationTime} $order
''' +
(limit != null ? ' limit $limit;' : ';');
final results = await db.rawQuery(rawQuery);
final results = await db.getAll(rawQuery);
final files = convertToFiles(results);
final dedupe = deduplicateByLocalID(files);
return FileLoadResult(dedupe, files.length == limit);
@ -339,7 +357,7 @@ extension DeviceFiles on FilesDB {
String pathID,
int ownerID,
) async {
final db = await database;
final db = await sqliteAsyncDB;
const String rawQuery = '''
SELECT ${FilesDB.columnLocalID}, ${FilesDB.columnUploadedFileID},
${FilesDB.columnFileSize}
@ -351,7 +369,7 @@ extension DeviceFiles on FilesDB {
${FilesDB.columnLocalID} IN
(SELECT id FROM device_files where path_id = ?)
''';
final results = await db.rawQuery(rawQuery, [ownerID, pathID]);
final results = await db.getAll(rawQuery, [ownerID, pathID]);
final localIDs = <String>{};
final uploadedIDs = <int>{};
int localSize = 0;
@ -375,17 +393,17 @@ extension DeviceFiles on FilesDB {
"$includeCoverThumbnail",
);
try {
final db = await database;
final db = await sqliteAsyncDB;
final coverFiles = <EnteFile>[];
if (includeCoverThumbnail) {
final fileRows = await db.rawQuery(
final fileRows = await db.getAll(
'''SELECT * FROM FILES where local_id in (select cover_id from device_collections) group by local_id;
''',
);
final files = convertToFiles(fileRows);
coverFiles.addAll(files);
}
final deviceCollectionRows = await db.rawQuery(
final deviceCollectionRows = await db.getAll(
'''SELECT * from device_collections''',
);
final List<DeviceCollection> deviceCollections = [];
@ -433,8 +451,8 @@ extension DeviceFiles on FilesDB {
Future<EnteFile?> getDeviceCollectionThumbnail(String pathID) async {
debugPrint("Call fallback method to get potential thumbnail");
final db = await database;
final fileRows = await db.rawQuery(
final db = await sqliteAsyncDB;
final fileRows = await db.getAll(
'''SELECT * FROM FILES f JOIN device_files df on f.local_id = df.id
and df.path_id= ? order by f.creation_time DESC limit 1;
''',
@ -447,4 +465,28 @@ extension DeviceFiles on FilesDB {
return null;
}
}
Future<void> _insertBatch(
List<List<Object?>> parameterSets,
ConflictAlgorithm conflictAlgorithm,
) async {
final db = await sqliteAsyncDB;
await db.executeBatch(
'''
INSERT OR ${conflictAlgorithm.name.toUpperCase()}
INTO device_files (id, path_id) VALUES (?, ?);
''',
parameterSets,
);
}
Future<void> _deleteBatch(List<List<Object?>> parameterSets) async {
final db = await sqliteAsyncDB;
await db.executeBatch(
'''
DELETE FROM device_files WHERE id = ? AND path_id = ?;
''',
parameterSets,
);
}
}

View file

@ -10,53 +10,78 @@ extension EntitiesDB on FilesDB {
ConflictAlgorithm conflictAlgorithm = ConflictAlgorithm.replace,
}) async {
debugPrint("entitiesDB: upsertEntities ${data.length} entities");
final db = await database;
var batch = db.batch();
final db = await sqliteAsyncDB;
final parameterSets = <List<Object?>>[];
int batchCounter = 0;
for (LocalEntityData e in data) {
parameterSets.add([
e.id,
e.type.name,
e.ownerID,
e.data,
e.updatedAt,
]);
batchCounter++;
if (batchCounter == 400) {
await batch.commit(noResult: true);
batch = db.batch();
await db.executeBatch(
'''
INSERT OR ${conflictAlgorithm.name.toUpperCase()}
INTO entities (id, type, ownerID, data, updatedAt)
VALUES (?, ?, ?, ?, ?)
''',
parameterSets,
);
parameterSets.clear();
batchCounter = 0;
}
batch.insert(
"entities",
e.toJson(),
conflictAlgorithm: conflictAlgorithm,
);
batchCounter++;
}
await batch.commit(noResult: true);
await db.executeBatch(
'''
INSERT OR ${conflictAlgorithm.name.toUpperCase()}
INTO entities (id, type, ownerID, data, updatedAt)
VALUES (?, ?, ?, ?, ?)
''',
parameterSets,
);
}
Future<void> deleteEntities(
List<String> ids,
) async {
final db = await database;
var batch = db.batch();
final db = await sqliteAsyncDB;
final parameterSets = <List<Object?>>[];
int batchCounter = 0;
for (String id in ids) {
if (batchCounter == 400) {
await batch.commit(noResult: true);
batch = db.batch();
batchCounter = 0;
}
batch.delete(
"entities",
where: "id = ?",
whereArgs: [id],
parameterSets.add(
[id],
);
batchCounter++;
if (batchCounter == 400) {
await db.executeBatch(
'''
DELETE FROM entities WHERE id = ?
''',
parameterSets,
);
parameterSets.clear();
batchCounter = 0;
}
}
await batch.commit(noResult: true);
await db.executeBatch(
'''
DELETE FROM entities WHERE id = ?
''',
parameterSets,
);
}
Future<List<LocalEntityData>> getEntities(EntityType type) async {
final db = await database;
final List<Map<String, dynamic>> maps = await db.query(
"entities",
where: "type = ?",
whereArgs: [type.typeToString()],
final db = await sqliteAsyncDB;
final List<Map<String, dynamic>> maps = await db.getAll(
'SELECT * FROM entities WHERE type = ?',
[type.name],
);
return List.generate(maps.length, (i) {
return LocalEntityData.fromJson(maps[i]);
@ -64,11 +89,10 @@ extension EntitiesDB on FilesDB {
}
Future<LocalEntityData?> getEntity(EntityType type, String id) async {
final db = await database;
final List<Map<String, dynamic>> maps = await db.query(
"entities",
where: "type = ? AND id = ?",
whereArgs: [type.typeToString(), id],
final db = await sqliteAsyncDB;
final List<Map<String, dynamic>> maps = await db.getAll(
'SELECT * FROM entities WHERE type = ? AND id = ?',
[type.name, id],
);
if (maps.isEmpty) {
return null;

File diff suppressed because it is too large Load diff

View file

@ -151,9 +151,7 @@ class FavoritesService {
final collectionID = await _getOrCreateFavoriteCollectionID();
final List<EnteFile> files = [file];
if (file.uploadedFileID == null) {
file.collectionID = collectionID;
await _filesDB.insert(file);
Bus.instance.fire(CollectionUpdatedEvent(collectionID, files, "addTFav"));
throw AssertionError("Can only favorite uploaded items");
} else {
await _collectionsService.addOrCopyToCollection(collectionID, files);
}

View file

@ -193,7 +193,7 @@ class LocalFileUpdateService {
} else if (e.reason == InvalidReason.imageToLivePhotoTypeChanged) {
fileType = FileType.livePhoto;
}
final int count = await FilesDB.instance.markFilesForReUpload(
await FilesDB.instance.markFilesForReUpload(
userID,
file.localID!,
file.title,
@ -202,8 +202,7 @@ class LocalFileUpdateService {
file.modificationTime!,
fileType,
);
_logger.fine('fileType changed for ${file.tag} to ${e.reason} for '
'$count files');
_logger.fine('fileType changed for ${file.tag} to ${e.reason} for ');
} else {
_logger.severe("failed to check hash: invalid file ${file.tag}", e);
}

View file

@ -21,8 +21,8 @@ import "package:photos/services/ignored_files_service.dart";
import 'package:photos/services/local/local_sync_util.dart';
import "package:photos/utils/debouncer.dart";
import "package:photos/utils/photo_manager_util.dart";
import "package:photos/utils/sqlite_util.dart";
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sqflite/sqflite.dart';
import 'package:tuple/tuple.dart';
class LocalSyncService {
@ -184,7 +184,7 @@ class LocalSyncService {
if (hasUnsyncedFiles) {
await _db.insertMultiple(
localDiffResult.uniqueLocalFiles!,
conflictAlgorithm: ConflictAlgorithm.ignore,
conflictAlgorithm: SqliteAsyncConflictAlgorithm.ignore,
);
_logger.info(
"Inserted ${localDiffResult.uniqueLocalFiles?.length} "
@ -321,7 +321,7 @@ class LocalSyncService {
files.removeWhere((file) => existingLocalDs.contains(file.localID));
await _db.insertMultiple(
files,
conflictAlgorithm: ConflictAlgorithm.ignore,
conflictAlgorithm: SqliteAsyncConflictAlgorithm.ignore,
);
_logger.info('Inserted ${files.length} files');
Bus.instance.fire(

View file

@ -580,6 +580,9 @@ class FaceMlService {
_isIndexingOrClusteringRunning = true;
final clusterAllImagesTime = DateTime.now();
_logger.info('Pulling remote feedback before actually clustering');
await PersonService.instance.fetchRemoteClusterFeedback();
try {
// Get a sense of the total number of faces in the database
final int totalFaces = await FaceMLDataDB.instance

View file

@ -73,7 +73,7 @@ class PersonService {
Future<void> reconcileClusters() async {
final EnteWatch? w = kDebugMode ? EnteWatch("reconcileClusters") : null;
w?.start();
await storeRemoteFeedback();
await fetchRemoteClusterFeedback();
w?.log("Stored remote feedback");
final dbPersonClusterInfo =
await faceMLDataDB.getPersonToClusterIdToFaceIds();
@ -225,7 +225,7 @@ class PersonService {
Bus.instance.fire(PeopleChangedEvent());
}
Future<void> storeRemoteFeedback() async {
Future<void> fetchRemoteClusterFeedback() async {
await entityService.syncEntities();
final entities = await entityService.getEntities(EntityType.person);
entities.sort((a, b) => a.updatedAt.compareTo(b.updatedAt));

View file

@ -193,7 +193,7 @@ class _FaceDebugSectionWidgetState extends State<FaceDebugSectionWidget> {
trailingIconIsMuted: true,
onTap: () async {
try {
await PersonService.instance.storeRemoteFeedback();
await PersonService.instance.fetchRemoteClusterFeedback();
FaceMlService.instance.debugIndexingDisabled = false;
await FaceMlService.instance
.clusterAllImages(clusterInBuckets: true);

View file

@ -371,7 +371,7 @@ class _ImageEditorPageState extends State<ImageEditorPage> {
);
}
}
newFile.generatedID = await FilesDB.instance.insert(newFile);
newFile.generatedID = await FilesDB.instance.insertAndGetId(newFile);
Bus.instance.fire(LocalPhotosUpdatedEvent([newFile], source: "editSave"));
unawaited(SyncService.instance.sync());
showShortToast(context, S.of(context).editsSaved);

View file

@ -146,6 +146,8 @@ class _LocationGalleryWidgetState extends State<LocationGalleryWidget> {
late final StreamSubscription<LocalPhotosUpdatedEvent> _filesUpdateEvent;
@override
void initState() {
super.initState();
final collectionsToHide =
CollectionsService.instance.archivedOrHiddenCollectionIds();
fileLoadResult = FilesDB.instance
@ -179,8 +181,6 @@ class _LocationGalleryWidgetState extends State<LocationGalleryWidget> {
});
galleryHeaderWidget = const GalleryHeaderWidget();
super.initState();
}
@override

View file

@ -0,0 +1,6 @@
///This is useful when you want to pass a primitive by reference.
class PrimitiveWrapper {
var value;
PrimitiveWrapper(this.value);
}

View file

@ -0,0 +1,39 @@
enum SqliteAsyncConflictAlgorithm {
/// When a constraint violation occurs, an immediate ROLLBACK occurs,
/// thus ending the current transaction, and the command aborts with a
/// return code of SQLITE_CONSTRAINT. If no transaction is active
/// (other than the implied transaction that is created on every command)
/// then this algorithm works the same as ABORT.
rollback,
/// When a constraint violation occurs,no ROLLBACK is executed
/// so changes from prior commands within the same transaction
/// are preserved. This is the default behavior.
abort,
/// When a constraint violation occurs, the command aborts with a return
/// code SQLITE_CONSTRAINT. But any changes to the database that
/// the command made prior to encountering the constraint violation
/// are preserved and are not backed out.
fail,
/// When a constraint violation occurs, the one row that contains
/// the constraint violation is not inserted or changed.
/// But the command continues executing normally. Other rows before and
/// after the row that contained the constraint violation continue to be
/// inserted or updated normally. No error is returned.
ignore,
/// When a UNIQUE constraint violation occurs, the pre-existing rows that
/// are causing the constraint violation are removed prior to inserting
/// or updating the current row. Thus the insert or update always occurs.
/// The command continues executing normally. No error is returned.
/// If a NOT NULL constraint violation occurs, the NULL value is replaced
/// by the default value for that column. If the column has no default
/// value, then the ABORT algorithm is used. If a CHECK constraint
/// violation occurs then the IGNORE algorithm is used. When this conflict
/// resolution strategy deletes rows in order to satisfy a constraint,
/// it does not invoke delete triggers on those rows.
/// This behavior might change in a future release.
replace,
}

View file

@ -12,7 +12,7 @@ description: ente photos application
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.8.112+636
version: 0.8.113+637
publish_to: none
environment: