diff --git a/mobile/lib/db/common/base.dart b/mobile/lib/db/common/base.dart index 9266e67033..6d01cf4ff4 100644 --- a/mobile/lib/db/common/base.dart +++ b/mobile/lib/db/common/base.dart @@ -4,7 +4,7 @@ import "package:sqlite_async/sqlite_async.dart"; mixin SqlDbBase { static const _params = {}; - static String getParams(int count) { + String getParams(int count) { if (!_params.containsKey(count)) { final params = List.generate(count, (_) => "?").join(", "); _params[count] = params; diff --git a/mobile/lib/db/local/db.dart b/mobile/lib/db/local/db.dart index 465e9687fd..91d0737366 100644 --- a/mobile/lib/db/local/db.dart +++ b/mobile/lib/db/local/db.dart @@ -5,12 +5,13 @@ import "package:flutter/foundation.dart"; import "package:path/path.dart"; import "package:path_provider/path_provider.dart"; import "package:photo_manager/photo_manager.dart"; +import "package:photos/db/common/base.dart"; import "package:photos/db/local/mappers.dart"; import "package:photos/db/local/schema.dart"; import "package:photos/log/devlog.dart"; import "package:sqlite_async/sqlite_async.dart"; -class LocalDB { +class LocalDB with SqlDbBase { static const _databaseName = "local_2.db"; static const _batchInsertMaxCount = 1000; static const _smallTableBatchInsertMaxCount = 5000; @@ -23,7 +24,7 @@ class LocalDB { final String path = join(documentsDirectory.path, _databaseName); final database = SqliteDatabase(path: path); - await LocalDBMigration.migrate(database); + await migrate(database, LocalDBMigration.migrationScripts); _sqliteDB = database; devLog("LocalDB init complete $path"); } @@ -35,7 +36,7 @@ class LocalDB { final List> values = slice.map((e) => LocalDBMappers.assetsRow(e)).toList(); await _sqliteDB.executeBatch( - 'INSERT OR REPLACE INTO assets ($assetColumns) values(${placeHolderMap[15]})', + 'INSERT OR REPLACE INTO assets ($assetColumns) values(${getParams(15)})', values, ); }); @@ -52,7 +53,7 @@ class LocalDB { final List> values = slice.map((e) => LocalDBMappers.devicePathRow(e)).toList(); await _sqliteDB.executeBatch( - 'INSERT OR REPLACE INTO device_path ($devicePathColumns) values(${placeHolderMap[5]})', + 'INSERT OR REPLACE INTO device_path ($devicePathColumns) values(${getParams(5)})', values, ); }); diff --git a/mobile/lib/db/local/schema.dart b/mobile/lib/db/local/schema.dart index 85cc353253..4244dbbaad 100644 --- a/mobile/lib/db/local/schema.dart +++ b/mobile/lib/db/local/schema.dart @@ -6,23 +6,6 @@ const assetColumns = const devicePathColumns = "path_id, name, album_type, ios_album_type, ios_album_subtype"; -const placeHolderMap = { - 1: "?", - 2: "?,?", - 3: "?,?,?", - 4: "?,?,?,?", - 5: "?,?,?,?,?", - 6: "?,?,?,?,?,?", - 7: "?,?,?,?,?,?,?", - 8: "?,?,?,?,?,?,?,?", - 9: "?,?,?,?,?,?,?,?,?", - 10: "?,?,?,?,?,?,?,?,?,?", - 11: "?,?,?,?,?,?,?,?,?,?,?", - 12: "?,?,?,?,?,?,?,?,?,?,?,?", - 13: "?,?,?,?,?,?,?,?,?,?,?,?,?", - 14: "?,?,?,?,?,?,?,?,?,?,?,?,?,?", - 15: "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?", -}; class LocalDBMigration { static const migrationScripts = [ diff --git a/mobile/lib/services/local/import/device_assets.service.dart b/mobile/lib/services/local/import/device_assets.service.dart index df5db7fc76..b65b282f73 100644 --- a/mobile/lib/services/local/import/device_assets.service.dart +++ b/mobile/lib/services/local/import/device_assets.service.dart @@ -11,6 +11,9 @@ import "package:photos/services/local/import/model.dart"; class DeviceAssetsService { final _logger = Logger("DeviceAssetsService"); + // The ignoreSizeConstraint is used to ignore the size constraint, otherwise + // photo manager will only give assets that meet it's default constraint where + // only assets with w/h in [0,100000] dim will be returned static const ignoreSizeConstraint = SizeConstraint(ignoreSize: true); static const assetFetchPageSize = 2000; @@ -62,6 +65,9 @@ class DeviceAssetsService { return r; } + // _getAssetPaths will return AssetEntityPath and assets that will meet the + // specified filter conditions. If fromTimeInMs and toTimeInMs are provided, + // we will only get those assets that were updated in the specified time. Future> _getDevicePathAssets({ int? fromTimeInMs, int? toTimeInMs, @@ -95,6 +101,7 @@ class DeviceAssetsService { final OrderOption? orderOption, }) async { final filterOptionGroup = FilterOptionGroup(); + filterOptionGroup.setOption( AssetType.image, FilterOption(needTitle: needsTitle, sizeConstraint: ignoreSizeConstraint), @@ -113,6 +120,10 @@ class DeviceAssetsService { max: DateTime.fromMillisecondsSinceEpoch(updateToTimeInMs), ); } else { + // During full diff, ignore the default creation time filter otherwise + // photo manager will only give assets with creation time between [0, now()] + // utc. This will cause the app to miss out on assets that have creation_time + // outside this time window. filterOptionGroup.createTimeCond = DateTimeCond.def().copyWith(ignore: true); }