diff --git a/mobile/drift_schemas/main/drift_schema_v1.json b/mobile/drift_schemas/main/drift_schema_v1.json index 1508394b75..65986584d9 100644 --- a/mobile/drift_schemas/main/drift_schema_v1.json +++ b/mobile/drift_schemas/main/drift_schema_v1.json @@ -1 +1 @@ -{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":true},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"user_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_admin","getter_name":"isAdmin","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_admin\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_admin\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"profile_image_path","getter_name":"profileImagePath","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"quota_size_in_bytes","getter_name":"quotaSizeInBytes","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"quota_usage_in_bytes","getter_name":"quotaUsageInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":1,"references":[0],"type":"table","data":{"name":"user_metadata_entity","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"preferences","getter_name":"preferences","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"userPreferenceConverter","dart_type_name":"UserPreferences"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["user_id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"partner_entity","was_declared_in_moor":false,"columns":[{"name":"shared_by_id","getter_name":"sharedById","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"shared_with_id","getter_name":"sharedWithId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"in_timeline","getter_name":"inTimeline","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"in_timeline\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"in_timeline\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["shared_by_id","shared_with_id"]}},{"id":3,"references":[],"type":"table","data":{"name":"local_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter<AssetType>(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"local_id","getter_name":"localId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["local_id"]}},{"id":4,"references":[3],"type":"table","data":{"name":"local_album_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"asset_count","getter_name":"assetCount","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"thumbnail_id","getter_name":"thumbnailId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES local_asset_entity (local_id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (local_id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"backup_selection","getter_name":"backupSelection","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter<BackupSelection>(BackupSelection.values)","dart_type_name":"BackupSelection"}},{"name":"is_all","getter_name":"isAll","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_all\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_all\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":5,"references":[3,4],"type":"table","data":{"name":"local_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_asset_entity (local_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (local_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","album_id"]}},{"id":6,"references":[3],"type":"index","data":{"on":3,"name":"local_asset_checksum","sql":null,"unique":false,"columns":["checksum"]}}]} \ No newline at end of file +{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":true},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"user_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_admin","getter_name":"isAdmin","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_admin\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_admin\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"profile_image_path","getter_name":"profileImagePath","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"quota_size_in_bytes","getter_name":"quotaSizeInBytes","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"quota_usage_in_bytes","getter_name":"quotaUsageInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":1,"references":[0],"type":"table","data":{"name":"user_metadata_entity","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"preferences","getter_name":"preferences","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"userPreferenceConverter","dart_type_name":"UserPreferences"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["user_id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"partner_entity","was_declared_in_moor":false,"columns":[{"name":"shared_by_id","getter_name":"sharedById","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"shared_with_id","getter_name":"sharedWithId","moor_type":"blob","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"in_timeline","getter_name":"inTimeline","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"in_timeline\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"in_timeline\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["shared_by_id","shared_with_id"]}},{"id":3,"references":[],"type":"table","data":{"name":"local_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter<AssetType>(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"local_id","getter_name":"localId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_favorite","getter_name":"isFavorite","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_favorite\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_favorite\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["local_id"]}},{"id":4,"references":[3],"type":"table","data":{"name":"local_album_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"thumbnail_id","getter_name":"thumbnailId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES local_asset_entity (local_id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (local_id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"backup_selection","getter_name":"backupSelection","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter<BackupSelection>(BackupSelection.values)","dart_type_name":"BackupSelection"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":5,"references":[3,4],"type":"table","data":{"name":"local_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_asset_entity (local_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (local_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","album_id"]}},{"id":6,"references":[3],"type":"index","data":{"on":3,"name":"local_asset_checksum","sql":null,"unique":false,"columns":["checksum"]}}]} \ No newline at end of file diff --git a/mobile/lib/domain/interfaces/album_media.interface.dart b/mobile/lib/domain/interfaces/album_media.interface.dart index 6257de9f17..feb3adeb25 100644 --- a/mobile/lib/domain/interfaces/album_media.interface.dart +++ b/mobile/lib/domain/interfaces/album_media.interface.dart @@ -1,4 +1,4 @@ -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/local_album.model.dart'; abstract interface class IAlbumMediaRepository { diff --git a/mobile/lib/domain/interfaces/local_album.interface.dart b/mobile/lib/domain/interfaces/local_album.interface.dart index 85fff14893..611527d08a 100644 --- a/mobile/lib/domain/interfaces/local_album.interface.dart +++ b/mobile/lib/domain/interfaces/local_album.interface.dart @@ -1,9 +1,9 @@ import 'package:immich_mobile/domain/interfaces/db.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/local_album.model.dart'; abstract interface class ILocalAlbumRepository implements IDatabaseRepository { - Future<void> insert(LocalAlbum localAlbum, Iterable<LocalAsset> assets); + Future<void> insert(LocalAlbum album, Iterable<LocalAsset> assets); Future<void> addAssets(String albumId, Iterable<LocalAsset> assets); @@ -11,7 +11,7 @@ abstract interface class ILocalAlbumRepository implements IDatabaseRepository { Future<List<LocalAsset>> getAssetsForAlbum(String albumId); - Future<void> update(LocalAlbum localAlbum); + Future<void> update(LocalAlbum album); Future<void> delete(String albumId); diff --git a/mobile/lib/domain/interfaces/local_asset.interface.dart b/mobile/lib/domain/interfaces/local_asset.interface.dart index 7cf05a55be..2f9fbd143f 100644 --- a/mobile/lib/domain/interfaces/local_asset.interface.dart +++ b/mobile/lib/domain/interfaces/local_asset.interface.dart @@ -1,5 +1,5 @@ import 'package:immich_mobile/domain/interfaces/db.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; abstract interface class ILocalAssetRepository implements IDatabaseRepository { Future<LocalAsset> get(String assetId); diff --git a/mobile/lib/domain/models/asset/asset.model.dart b/mobile/lib/domain/models/asset/asset.model.dart index e6b11c3130..211d24985f 100644 --- a/mobile/lib/domain/models/asset/asset.model.dart +++ b/mobile/lib/domain/models/asset/asset.model.dart @@ -1,72 +1,46 @@ -part 'local_asset.model.dart'; -part 'merged_asset.model.dart'; -part 'remote_asset.model.dart'; +part of 'base_asset.model.dart'; -enum AssetType { - // do not change this order! - other, - image, - video, - audio, -} - -sealed class Asset { - final String name; - final String? checksum; - final AssetType type; - final DateTime createdAt; - final DateTime updatedAt; - final int? width; - final int? height; - final int? durationInSeconds; +class Asset extends BaseAsset { + final String id; + final String? localId; const Asset({ - required this.name, - required this.checksum, - required this.type, - required this.createdAt, - required this.updatedAt, - this.width, - this.height, - this.durationInSeconds, + required this.id, + this.localId, + required super.name, + required super.checksum, + required super.type, + required super.createdAt, + required super.updatedAt, + super.width, + super.height, + super.durationInSeconds, + super.isFavorite = false, }); @override String toString() { return '''Asset { - name: $name, - type: $type, - createdAt: $createdAt, - updatedAt: $updatedAt, - width: ${width ?? "<NA>"}, - height: ${height ?? "<NA>"}, - durationInSeconds: ${durationInSeconds ?? "<NA>"} -}'''; + id: $id, + name: $name, + type: $type, + createdAt: $createdAt, + updatedAt: $updatedAt, + width: ${width ?? "<NA>"}, + height: ${height ?? "<NA>"}, + durationInSeconds: ${durationInSeconds ?? "<NA>"}, + localId: ${localId ?? "<NA>"}, + isFavorite: $isFavorite, + }'''; } @override bool operator ==(Object other) { + if (other is! Asset) return false; if (identical(this, other)) return true; - if (other is Asset) { - return name == other.name && - type == other.type && - createdAt == other.createdAt && - updatedAt == other.updatedAt && - width == other.width && - height == other.height && - durationInSeconds == other.durationInSeconds; - } - return false; + return super == other && id == other.id && localId == other.localId; } @override - int get hashCode { - return name.hashCode ^ - type.hashCode ^ - createdAt.hashCode ^ - updatedAt.hashCode ^ - width.hashCode ^ - height.hashCode ^ - durationInSeconds.hashCode; - } + int get hashCode => super.hashCode ^ id.hashCode ^ localId.hashCode; } diff --git a/mobile/lib/domain/models/asset/base_asset.model.dart b/mobile/lib/domain/models/asset/base_asset.model.dart new file mode 100644 index 0000000000..fb95437659 --- /dev/null +++ b/mobile/lib/domain/models/asset/base_asset.model.dart @@ -0,0 +1,76 @@ +part 'asset.model.dart'; +part 'local_asset.model.dart'; + +enum AssetType { + // do not change this order! + other, + image, + video, + audio, +} + +sealed class BaseAsset { + final String name; + final String? checksum; + final AssetType type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final bool isFavorite; + + const BaseAsset({ + required this.name, + required this.checksum, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + this.isFavorite = false, + }); + + @override + String toString() { + return '''BaseAsset { + name: $name, + type: $type, + createdAt: $createdAt, + updatedAt: $updatedAt, + width: ${width ?? "<NA>"}, + height: ${height ?? "<NA>"}, + durationInSeconds: ${durationInSeconds ?? "<NA>"}, + isFavorite: $isFavorite, +}'''; + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + if (other is BaseAsset) { + return name == other.name && + type == other.type && + createdAt == other.createdAt && + updatedAt == other.updatedAt && + width == other.width && + height == other.height && + durationInSeconds == other.durationInSeconds && + isFavorite == other.isFavorite; + } + return false; + } + + @override + int get hashCode { + return name.hashCode ^ + type.hashCode ^ + createdAt.hashCode ^ + updatedAt.hashCode ^ + width.hashCode ^ + height.hashCode ^ + durationInSeconds.hashCode ^ + isFavorite.hashCode; + } +} diff --git a/mobile/lib/domain/models/asset/local_asset.model.dart b/mobile/lib/domain/models/asset/local_asset.model.dart index afab9832b5..25e617d8ed 100644 --- a/mobile/lib/domain/models/asset/local_asset.model.dart +++ b/mobile/lib/domain/models/asset/local_asset.model.dart @@ -1,10 +1,12 @@ -part of 'asset.model.dart'; +part of 'base_asset.model.dart'; -class LocalAsset extends Asset { - final String localId; +class LocalAsset extends BaseAsset { + final String id; + final String? remoteId; const LocalAsset({ - required this.localId, + required this.id, + this.remoteId, required super.name, super.checksum, required super.type, @@ -13,19 +15,22 @@ class LocalAsset extends Asset { super.width, super.height, super.durationInSeconds, + super.isFavorite = false, }); @override String toString() { return '''LocalAsset { - localId: $localId, + id: $id, name: $name, type: $type, createdAt: $createdAt, updatedAt: $updatedAt, width: ${width ?? "<NA>"}, height: ${height ?? "<NA>"}, - durationInSeconds: ${durationInSeconds ?? "<NA>"} + durationInSeconds: ${durationInSeconds ?? "<NA>"}, + remoteId: ${remoteId ?? "<NA>"} + isFavorite: $isFavorite, }'''; } @@ -33,16 +38,15 @@ class LocalAsset extends Asset { bool operator ==(Object other) { if (other is! LocalAsset) return false; if (identical(this, other)) return true; - return super == other && localId == other.localId; + return super == other && id == other.id && remoteId == other.remoteId; } @override - int get hashCode { - return super.hashCode ^ localId.hashCode; - } + int get hashCode => super.hashCode ^ id.hashCode ^ remoteId.hashCode; LocalAsset copyWith({ - String? localId, + String? id, + String? remoteId, String? name, String? checksum, AssetType? type, @@ -51,9 +55,11 @@ class LocalAsset extends Asset { int? width, int? height, int? durationInSeconds, + bool? isFavorite, }) { return LocalAsset( - localId: localId ?? this.localId, + id: id ?? this.id, + remoteId: remoteId ?? this.remoteId, name: name ?? this.name, checksum: checksum ?? this.checksum, type: type ?? this.type, @@ -62,6 +68,7 @@ class LocalAsset extends Asset { width: width ?? this.width, height: height ?? this.height, durationInSeconds: durationInSeconds ?? this.durationInSeconds, + isFavorite: isFavorite ?? this.isFavorite, ); } } diff --git a/mobile/lib/domain/models/asset/merged_asset.model.dart b/mobile/lib/domain/models/asset/merged_asset.model.dart deleted file mode 100644 index 7b0b6e16c4..0000000000 --- a/mobile/lib/domain/models/asset/merged_asset.model.dart +++ /dev/null @@ -1,48 +0,0 @@ -part of 'asset.model.dart'; - -class MergedAsset extends Asset { - final String remoteId; - final String localId; - - const MergedAsset({ - required this.remoteId, - required this.localId, - required super.name, - required super.checksum, - required super.type, - required super.createdAt, - required super.updatedAt, - super.width, - super.height, - super.durationInSeconds, - }); - - @override - String toString() { - return '''MergedAsset { - remoteId: $remoteId, - localId: $localId, - name: $name, - type: $type, - createdAt: $createdAt, - updatedAt: $updatedAt, - width: ${width ?? "<NA>"}, - height: ${height ?? "<NA>"}, - durationInSeconds: ${durationInSeconds ?? "<NA>"} - }'''; - } - - @override - bool operator ==(Object other) { - if (other is! MergedAsset) return false; - if (identical(this, other)) return true; - return super == other && - remoteId == other.remoteId && - localId == other.localId; - } - - @override - int get hashCode { - return super.hashCode ^ remoteId.hashCode ^ localId.hashCode; - } -} diff --git a/mobile/lib/domain/models/asset/remote_asset.model.dart b/mobile/lib/domain/models/asset/remote_asset.model.dart deleted file mode 100644 index ae04499574..0000000000 --- a/mobile/lib/domain/models/asset/remote_asset.model.dart +++ /dev/null @@ -1,43 +0,0 @@ -part of 'asset.model.dart'; - -class RemoteAsset extends Asset { - final String remoteId; - - const RemoteAsset({ - required this.remoteId, - required super.name, - required super.checksum, - required super.type, - required super.createdAt, - required super.updatedAt, - super.width, - super.height, - super.durationInSeconds, - }); - - @override - String toString() { - return '''RemoteAsset { - remoteId: $remoteId, - name: $name, - type: $type, - createdAt: $createdAt, - updatedAt: $updatedAt, - width: ${width ?? "<NA>"}, - height: ${height ?? "<NA>"}, - durationInSeconds: ${durationInSeconds ?? "<NA>"} - }'''; - } - - @override - bool operator ==(Object other) { - if (other is! RemoteAsset) return false; - if (identical(this, other)) return true; - return super == other && remoteId == other.remoteId; - } - - @override - int get hashCode { - return super.hashCode ^ remoteId.hashCode; - } -} diff --git a/mobile/lib/domain/models/local_album.model.dart b/mobile/lib/domain/models/local_album.model.dart index de7c86a64f..ea3d9989f0 100644 --- a/mobile/lib/domain/models/local_album.model.dart +++ b/mobile/lib/domain/models/local_album.model.dart @@ -11,8 +11,6 @@ class LocalAlbum { final String name; final DateTime updatedAt; - /// Whether the album contains all photos (i.e, the virtual "Recent" album) - final bool isAll; final int assetCount; final String? thumbnailId; final BackupSelection backupSelection; @@ -24,7 +22,6 @@ class LocalAlbum { this.assetCount = 0, this.thumbnailId, this.backupSelection = BackupSelection.none, - this.isAll = false, }); LocalAlbum copyWith({ @@ -34,7 +31,6 @@ class LocalAlbum { int? assetCount, NullableValue<String>? thumbnailId, BackupSelection? backupSelection, - bool? isAll, }) { return LocalAlbum( id: id ?? this.id, @@ -43,7 +39,6 @@ class LocalAlbum { assetCount: assetCount ?? this.assetCount, thumbnailId: thumbnailId?.getOrDefault(this.thumbnailId), backupSelection: backupSelection ?? this.backupSelection, - isAll: isAll ?? this.isAll, ); } @@ -56,7 +51,6 @@ class LocalAlbum { other.name == name && other.updatedAt == updatedAt && other.assetCount == assetCount && - other.isAll == isAll && other.thumbnailId == thumbnailId && other.backupSelection == backupSelection; } @@ -67,7 +61,6 @@ class LocalAlbum { name.hashCode ^ updatedAt.hashCode ^ assetCount.hashCode ^ - isAll.hashCode ^ thumbnailId.hashCode ^ backupSelection.hashCode; } @@ -81,7 +74,6 @@ updatedAt: $updatedAt, assetCount: $assetCount, thumbnailId: ${thumbnailId ?? '<NA>'}, backupSelection: $backupSelection, -isAll: $isAll }'''; } } diff --git a/mobile/lib/domain/services/device_sync.service.dart b/mobile/lib/domain/services/device_sync.service.dart index 09f71fe76e..4a7b1c7c07 100644 --- a/mobile/lib/domain/services/device_sync.service.dart +++ b/mobile/lib/domain/services/device_sync.service.dart @@ -5,7 +5,7 @@ import 'package:flutter/widgets.dart'; import 'package:immich_mobile/domain/interfaces/album_media.interface.dart'; import 'package:immich_mobile/domain/interfaces/local_album.interface.dart'; import 'package:immich_mobile/domain/interfaces/local_asset.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/local_album.model.dart'; import 'package:immich_mobile/utils/diff.dart'; import 'package:immich_mobile/utils/nullable_value.dart'; @@ -34,6 +34,7 @@ class DeviceSyncService { // and not the albums. final deviceAlbums = (await _albumMediaRepository.getAll()).sortedBy((a) => a.id); + final dbAlbums = await _localAlbumRepository.getAll(sortBy: SortLocalAlbumsBy.id); @@ -64,7 +65,7 @@ class DeviceSyncService { final album = deviceAlbum.copyWith( // The below assumes the list is already sorted by createdDate from the filter - thumbnailId: NullableValue.valueOrEmpty(assets.firstOrNull?.localId), + thumbnailId: NullableValue.valueOrEmpty(assets.firstOrNull?.id), ); await _localAlbumRepository.insert(album, assets); @@ -100,7 +101,7 @@ class DeviceSyncService { return false; } - _log.fine("Device album ${dbAlbum.name} has changed. Syncing..."); + _log.info("Device album ${dbAlbum.name} has changed. Syncing..."); // Faster path - only new assets added if (await checkAddition(dbAlbum, deviceAlbum)) { @@ -157,13 +158,13 @@ class DeviceSyncService { String? thumbnailId = dbAlbum.thumbnailId; if (thumbnailId == null || newAssets.isNotEmpty) { if (thumbnailId == null) { - thumbnailId = newAssets.firstOrNull?.localId; + thumbnailId = newAssets.firstOrNull?.id; } else if (newAssets.isNotEmpty) { // The below assumes the list is already sorted by createdDate from the filter final oldThumbAsset = await _localAssetRepository.get(thumbnailId); if (oldThumbAsset.createdAt .isBefore(newAssets.firstOrNull!.createdAt)) { - thumbnailId = newAssets.firstOrNull?.localId; + thumbnailId = newAssets.firstOrNull?.id; } } } @@ -205,14 +206,14 @@ class DeviceSyncService { thumbnailId: const NullableValue.empty(), backupSelection: dbAlbum.backupSelection, ), - assetIdsToDelete: assetsInDb.map((a) => a.localId), + assetIdsToDelete: assetsInDb.map((a) => a.id), ); return true; } // The below assumes the list is already sorted by createdDate from the filter String? thumbnailId = assetsInDevice.isNotEmpty - ? assetsInDevice.firstOrNull?.localId + ? assetsInDevice.firstOrNull?.id : dbAlbum.thumbnailId; final updatedDeviceAlbum = deviceAlbum.copyWith( @@ -228,8 +229,8 @@ class DeviceSyncService { return true; } - assert(assetsInDb.isSortedBy((a) => a.localId)); - assetsInDevice.sort((a, b) => a.localId.compareTo(b.localId)); + assert(assetsInDb.isSortedBy((a) => a.id)); + assetsInDevice.sort((a, b) => a.id.compareTo(b.id)); final assetsToUpsert = <LocalAsset>[]; final assetsToDelete = <String>[]; @@ -237,7 +238,7 @@ class DeviceSyncService { diffSortedListsSync( assetsInDb, assetsInDevice, - compare: (a, b) => a.localId.compareTo(b.localId), + compare: (a, b) => a.id.compareTo(b.id), both: (dbAsset, deviceAsset) { // Custom comparison to check if the asset has been modified without // comparing the checksum @@ -247,7 +248,7 @@ class DeviceSyncService { } return false; }, - onlyFirst: (dbAsset) => assetsToDelete.add(dbAsset.localId), + onlyFirst: (dbAsset) => assetsToDelete.add(dbAsset.id), onlySecond: (deviceAsset) => assetsToUpsert.add(deviceAsset), ); diff --git a/mobile/lib/infrastructure/entities/local_album.entity.dart b/mobile/lib/infrastructure/entities/local_album.entity.dart index 5d5f766fd4..4eff2a1154 100644 --- a/mobile/lib/infrastructure/entities/local_album.entity.dart +++ b/mobile/lib/infrastructure/entities/local_album.entity.dart @@ -10,12 +10,10 @@ class LocalAlbumEntity extends Table with DriftDefaultsMixin { TextColumn get id => text()(); TextColumn get name => text()(); DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); - IntColumn get assetCount => integer().withDefault(const Constant(0))(); TextColumn get thumbnailId => text() .nullable() .references(LocalAssetEntity, #localId, onDelete: KeyAction.setNull)(); IntColumn get backupSelection => intEnum<BackupSelection>()(); - BoolColumn get isAll => boolean().withDefault(const Constant(false))(); @override Set<Column> get primaryKey => {id}; @@ -30,7 +28,6 @@ extension LocalAlbumEntityX on LocalAlbumEntityData { assetCount: assetCount, thumbnailId: thumbnailId, backupSelection: backupSelection, - isAll: isAll, ); } } diff --git a/mobile/lib/infrastructure/entities/local_album.entity.drift.dart b/mobile/lib/infrastructure/entities/local_album.entity.drift.dart index 19ada47e87..ee6c5b8c61 100644 --- a/mobile/lib/infrastructure/entities/local_album.entity.drift.dart +++ b/mobile/lib/infrastructure/entities/local_album.entity.drift.dart @@ -16,20 +16,16 @@ typedef $$LocalAlbumEntityTableCreateCompanionBuilder required String id, required String name, i0.Value<DateTime> updatedAt, - i0.Value<int> assetCount, i0.Value<String?> thumbnailId, required i2.BackupSelection backupSelection, - i0.Value<bool> isAll, }); typedef $$LocalAlbumEntityTableUpdateCompanionBuilder = i1.LocalAlbumEntityCompanion Function({ i0.Value<String> id, i0.Value<String> name, i0.Value<DateTime> updatedAt, - i0.Value<int> assetCount, i0.Value<String?> thumbnailId, i0.Value<i2.BackupSelection> backupSelection, - i0.Value<bool> isAll, }); final class $$LocalAlbumEntityTableReferences extends i0.BaseReferences< @@ -82,17 +78,11 @@ class $$LocalAlbumEntityTableFilterComposer i0.ColumnFilters<DateTime> get updatedAt => $composableBuilder( column: $table.updatedAt, builder: (column) => i0.ColumnFilters(column)); - i0.ColumnFilters<int> get assetCount => $composableBuilder( - column: $table.assetCount, builder: (column) => i0.ColumnFilters(column)); - i0.ColumnWithTypeConverterFilters<i2.BackupSelection, i2.BackupSelection, int> get backupSelection => $composableBuilder( column: $table.backupSelection, builder: (column) => i0.ColumnWithTypeConverterFilters(column)); - i0.ColumnFilters<bool> get isAll => $composableBuilder( - column: $table.isAll, builder: (column) => i0.ColumnFilters(column)); - i5.$$LocalAssetEntityTableFilterComposer get thumbnailId { final i5.$$LocalAssetEntityTableFilterComposer composer = $composerBuilder( composer: this, @@ -135,17 +125,10 @@ class $$LocalAlbumEntityTableOrderingComposer column: $table.updatedAt, builder: (column) => i0.ColumnOrderings(column)); - i0.ColumnOrderings<int> get assetCount => $composableBuilder( - column: $table.assetCount, - builder: (column) => i0.ColumnOrderings(column)); - i0.ColumnOrderings<int> get backupSelection => $composableBuilder( column: $table.backupSelection, builder: (column) => i0.ColumnOrderings(column)); - i0.ColumnOrderings<bool> get isAll => $composableBuilder( - column: $table.isAll, builder: (column) => i0.ColumnOrderings(column)); - i5.$$LocalAssetEntityTableOrderingComposer get thumbnailId { final i5.$$LocalAssetEntityTableOrderingComposer composer = $composerBuilder( @@ -189,16 +172,10 @@ class $$LocalAlbumEntityTableAnnotationComposer i0.GeneratedColumn<DateTime> get updatedAt => $composableBuilder(column: $table.updatedAt, builder: (column) => column); - i0.GeneratedColumn<int> get assetCount => $composableBuilder( - column: $table.assetCount, builder: (column) => column); - i0.GeneratedColumnWithTypeConverter<i2.BackupSelection, int> get backupSelection => $composableBuilder( column: $table.backupSelection, builder: (column) => column); - i0.GeneratedColumn<bool> get isAll => - $composableBuilder(column: $table.isAll, builder: (column) => column); - i5.$$LocalAssetEntityTableAnnotationComposer get thumbnailId { final i5.$$LocalAssetEntityTableAnnotationComposer composer = $composerBuilder( @@ -252,38 +229,30 @@ class $$LocalAlbumEntityTableTableManager extends i0.RootTableManager< i0.Value<String> id = const i0.Value.absent(), i0.Value<String> name = const i0.Value.absent(), i0.Value<DateTime> updatedAt = const i0.Value.absent(), - i0.Value<int> assetCount = const i0.Value.absent(), i0.Value<String?> thumbnailId = const i0.Value.absent(), i0.Value<i2.BackupSelection> backupSelection = const i0.Value.absent(), - i0.Value<bool> isAll = const i0.Value.absent(), }) => i1.LocalAlbumEntityCompanion( id: id, name: name, updatedAt: updatedAt, - assetCount: assetCount, thumbnailId: thumbnailId, backupSelection: backupSelection, - isAll: isAll, ), createCompanionCallback: ({ required String id, required String name, i0.Value<DateTime> updatedAt = const i0.Value.absent(), - i0.Value<int> assetCount = const i0.Value.absent(), i0.Value<String?> thumbnailId = const i0.Value.absent(), required i2.BackupSelection backupSelection, - i0.Value<bool> isAll = const i0.Value.absent(), }) => i1.LocalAlbumEntityCompanion.insert( id: id, name: name, updatedAt: updatedAt, - assetCount: assetCount, thumbnailId: thumbnailId, backupSelection: backupSelection, - isAll: isAll, ), withReferenceMapper: (p0) => p0 .map((e) => ( @@ -368,14 +337,6 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity type: i0.DriftSqlType.dateTime, requiredDuringInsert: false, defaultValue: i4.currentDateAndTime); - static const i0.VerificationMeta _assetCountMeta = - const i0.VerificationMeta('assetCount'); - @override - late final i0.GeneratedColumn<int> assetCount = i0.GeneratedColumn<int>( - 'asset_count', aliasedName, false, - type: i0.DriftSqlType.int, - requiredDuringInsert: false, - defaultValue: const i4.Constant(0)); static const i0.VerificationMeta _thumbnailIdMeta = const i0.VerificationMeta('thumbnailId'); @override @@ -392,19 +353,9 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity type: i0.DriftSqlType.int, requiredDuringInsert: true) .withConverter<i2.BackupSelection>( i1.$LocalAlbumEntityTable.$converterbackupSelection); - static const i0.VerificationMeta _isAllMeta = - const i0.VerificationMeta('isAll'); - @override - late final i0.GeneratedColumn<bool> isAll = i0.GeneratedColumn<bool>( - 'is_all', aliasedName, false, - type: i0.DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: - i0.GeneratedColumn.constraintIsAlways('CHECK ("is_all" IN (0, 1))'), - defaultValue: const i4.Constant(false)); @override List<i0.GeneratedColumn> get $columns => - [id, name, updatedAt, assetCount, thumbnailId, backupSelection, isAll]; + [id, name, updatedAt, thumbnailId, backupSelection]; @override String get aliasedName => _alias ?? actualTableName; @override @@ -431,22 +382,12 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity context.handle(_updatedAtMeta, updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); } - if (data.containsKey('asset_count')) { - context.handle( - _assetCountMeta, - assetCount.isAcceptableOrUnknown( - data['asset_count']!, _assetCountMeta)); - } if (data.containsKey('thumbnail_id')) { context.handle( _thumbnailIdMeta, thumbnailId.isAcceptableOrUnknown( data['thumbnail_id']!, _thumbnailIdMeta)); } - if (data.containsKey('is_all')) { - context.handle( - _isAllMeta, isAll.isAcceptableOrUnknown(data['is_all']!, _isAllMeta)); - } return context; } @@ -463,15 +404,11 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity .read(i0.DriftSqlType.string, data['${effectivePrefix}name'])!, updatedAt: attachedDatabase.typeMapping.read( i0.DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, - assetCount: attachedDatabase.typeMapping - .read(i0.DriftSqlType.int, data['${effectivePrefix}asset_count'])!, thumbnailId: attachedDatabase.typeMapping .read(i0.DriftSqlType.string, data['${effectivePrefix}thumbnail_id']), backupSelection: i1.$LocalAlbumEntityTable.$converterbackupSelection .fromSql(attachedDatabase.typeMapping.read(i0.DriftSqlType.int, data['${effectivePrefix}backup_selection'])!), - isAll: attachedDatabase.typeMapping - .read(i0.DriftSqlType.bool, data['${effectivePrefix}is_all'])!, ); } @@ -495,25 +432,20 @@ class LocalAlbumEntityData extends i0.DataClass final String id; final String name; final DateTime updatedAt; - final int assetCount; final String? thumbnailId; final i2.BackupSelection backupSelection; - final bool isAll; const LocalAlbumEntityData( {required this.id, required this.name, required this.updatedAt, - required this.assetCount, this.thumbnailId, - required this.backupSelection, - required this.isAll}); + required this.backupSelection}); @override Map<String, i0.Expression> toColumns(bool nullToAbsent) { final map = <String, i0.Expression>{}; map['id'] = i0.Variable<String>(id); map['name'] = i0.Variable<String>(name); map['updated_at'] = i0.Variable<DateTime>(updatedAt); - map['asset_count'] = i0.Variable<int>(assetCount); if (!nullToAbsent || thumbnailId != null) { map['thumbnail_id'] = i0.Variable<String>(thumbnailId); } @@ -522,7 +454,6 @@ class LocalAlbumEntityData extends i0.DataClass .$LocalAlbumEntityTable.$converterbackupSelection .toSql(backupSelection)); } - map['is_all'] = i0.Variable<bool>(isAll); return map; } @@ -533,11 +464,9 @@ class LocalAlbumEntityData extends i0.DataClass id: serializer.fromJson<String>(json['id']), name: serializer.fromJson<String>(json['name']), updatedAt: serializer.fromJson<DateTime>(json['updatedAt']), - assetCount: serializer.fromJson<int>(json['assetCount']), thumbnailId: serializer.fromJson<String?>(json['thumbnailId']), backupSelection: i1.$LocalAlbumEntityTable.$converterbackupSelection .fromJson(serializer.fromJson<int>(json['backupSelection'])), - isAll: serializer.fromJson<bool>(json['isAll']), ); } @override @@ -547,12 +476,10 @@ class LocalAlbumEntityData extends i0.DataClass 'id': serializer.toJson<String>(id), 'name': serializer.toJson<String>(name), 'updatedAt': serializer.toJson<DateTime>(updatedAt), - 'assetCount': serializer.toJson<int>(assetCount), 'thumbnailId': serializer.toJson<String?>(thumbnailId), 'backupSelection': serializer.toJson<int>(i1 .$LocalAlbumEntityTable.$converterbackupSelection .toJson(backupSelection)), - 'isAll': serializer.toJson<bool>(isAll), }; } @@ -560,32 +487,25 @@ class LocalAlbumEntityData extends i0.DataClass {String? id, String? name, DateTime? updatedAt, - int? assetCount, i0.Value<String?> thumbnailId = const i0.Value.absent(), - i2.BackupSelection? backupSelection, - bool? isAll}) => + i2.BackupSelection? backupSelection}) => i1.LocalAlbumEntityData( id: id ?? this.id, name: name ?? this.name, updatedAt: updatedAt ?? this.updatedAt, - assetCount: assetCount ?? this.assetCount, thumbnailId: thumbnailId.present ? thumbnailId.value : this.thumbnailId, backupSelection: backupSelection ?? this.backupSelection, - isAll: isAll ?? this.isAll, ); LocalAlbumEntityData copyWithCompanion(i1.LocalAlbumEntityCompanion data) { return LocalAlbumEntityData( id: data.id.present ? data.id.value : this.id, name: data.name.present ? data.name.value : this.name, updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, - assetCount: - data.assetCount.present ? data.assetCount.value : this.assetCount, thumbnailId: data.thumbnailId.present ? data.thumbnailId.value : this.thumbnailId, backupSelection: data.backupSelection.present ? data.backupSelection.value : this.backupSelection, - isAll: data.isAll.present ? data.isAll.value : this.isAll, ); } @@ -595,17 +515,15 @@ class LocalAlbumEntityData extends i0.DataClass ..write('id: $id, ') ..write('name: $name, ') ..write('updatedAt: $updatedAt, ') - ..write('assetCount: $assetCount, ') ..write('thumbnailId: $thumbnailId, ') - ..write('backupSelection: $backupSelection, ') - ..write('isAll: $isAll') + ..write('backupSelection: $backupSelection') ..write(')')) .toString(); } @override - int get hashCode => Object.hash( - id, name, updatedAt, assetCount, thumbnailId, backupSelection, isAll); + int get hashCode => + Object.hash(id, name, updatedAt, thumbnailId, backupSelection); @override bool operator ==(Object other) => identical(this, other) || @@ -613,10 +531,8 @@ class LocalAlbumEntityData extends i0.DataClass other.id == this.id && other.name == this.name && other.updatedAt == this.updatedAt && - other.assetCount == this.assetCount && other.thumbnailId == this.thumbnailId && - other.backupSelection == this.backupSelection && - other.isAll == this.isAll); + other.backupSelection == this.backupSelection); } class LocalAlbumEntityCompanion @@ -624,27 +540,21 @@ class LocalAlbumEntityCompanion final i0.Value<String> id; final i0.Value<String> name; final i0.Value<DateTime> updatedAt; - final i0.Value<int> assetCount; final i0.Value<String?> thumbnailId; final i0.Value<i2.BackupSelection> backupSelection; - final i0.Value<bool> isAll; const LocalAlbumEntityCompanion({ this.id = const i0.Value.absent(), this.name = const i0.Value.absent(), this.updatedAt = const i0.Value.absent(), - this.assetCount = const i0.Value.absent(), this.thumbnailId = const i0.Value.absent(), this.backupSelection = const i0.Value.absent(), - this.isAll = const i0.Value.absent(), }); LocalAlbumEntityCompanion.insert({ required String id, required String name, this.updatedAt = const i0.Value.absent(), - this.assetCount = const i0.Value.absent(), this.thumbnailId = const i0.Value.absent(), required i2.BackupSelection backupSelection, - this.isAll = const i0.Value.absent(), }) : id = i0.Value(id), name = i0.Value(name), backupSelection = i0.Value(backupSelection); @@ -652,19 +562,15 @@ class LocalAlbumEntityCompanion i0.Expression<String>? id, i0.Expression<String>? name, i0.Expression<DateTime>? updatedAt, - i0.Expression<int>? assetCount, i0.Expression<String>? thumbnailId, i0.Expression<int>? backupSelection, - i0.Expression<bool>? isAll, }) { return i0.RawValuesInsertable({ if (id != null) 'id': id, if (name != null) 'name': name, if (updatedAt != null) 'updated_at': updatedAt, - if (assetCount != null) 'asset_count': assetCount, if (thumbnailId != null) 'thumbnail_id': thumbnailId, if (backupSelection != null) 'backup_selection': backupSelection, - if (isAll != null) 'is_all': isAll, }); } @@ -672,18 +578,14 @@ class LocalAlbumEntityCompanion {i0.Value<String>? id, i0.Value<String>? name, i0.Value<DateTime>? updatedAt, - i0.Value<int>? assetCount, i0.Value<String?>? thumbnailId, - i0.Value<i2.BackupSelection>? backupSelection, - i0.Value<bool>? isAll}) { + i0.Value<i2.BackupSelection>? backupSelection}) { return i1.LocalAlbumEntityCompanion( id: id ?? this.id, name: name ?? this.name, updatedAt: updatedAt ?? this.updatedAt, - assetCount: assetCount ?? this.assetCount, thumbnailId: thumbnailId ?? this.thumbnailId, backupSelection: backupSelection ?? this.backupSelection, - isAll: isAll ?? this.isAll, ); } @@ -699,9 +601,6 @@ class LocalAlbumEntityCompanion if (updatedAt.present) { map['updated_at'] = i0.Variable<DateTime>(updatedAt.value); } - if (assetCount.present) { - map['asset_count'] = i0.Variable<int>(assetCount.value); - } if (thumbnailId.present) { map['thumbnail_id'] = i0.Variable<String>(thumbnailId.value); } @@ -710,9 +609,6 @@ class LocalAlbumEntityCompanion .$LocalAlbumEntityTable.$converterbackupSelection .toSql(backupSelection.value)); } - if (isAll.present) { - map['is_all'] = i0.Variable<bool>(isAll.value); - } return map; } @@ -722,10 +618,8 @@ class LocalAlbumEntityCompanion ..write('id: $id, ') ..write('name: $name, ') ..write('updatedAt: $updatedAt, ') - ..write('assetCount: $assetCount, ') ..write('thumbnailId: $thumbnailId, ') - ..write('backupSelection: $backupSelection, ') - ..write('isAll: $isAll') + ..write('backupSelection: $backupSelection') ..write(')')) .toString(); } diff --git a/mobile/lib/infrastructure/entities/local_asset.entity.dart b/mobile/lib/infrastructure/entities/local_asset.entity.dart index 1620e703f4..0f3dd25936 100644 --- a/mobile/lib/infrastructure/entities/local_asset.entity.dart +++ b/mobile/lib/infrastructure/entities/local_asset.entity.dart @@ -1,5 +1,5 @@ import 'package:drift/drift.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart'; import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart'; @@ -12,6 +12,9 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin { TextColumn get checksum => text().nullable()(); + // Only used during backup to mirror the favorite status of the asset in the server + BoolColumn get isFavorite => boolean().withDefault(const Constant(false))(); + @override Set<Column> get primaryKey => {localId}; } @@ -19,7 +22,7 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin { extension LocalAssetEntityX on LocalAssetEntityData { LocalAsset toDto() { return LocalAsset( - localId: localId, + id: localId, name: name, checksum: checksum, type: type, @@ -28,6 +31,7 @@ extension LocalAssetEntityX on LocalAssetEntityData { width: width, height: height, durationInSeconds: durationInSeconds, + isFavorite: isFavorite, ); } } diff --git a/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart b/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart index e9ab09e8cf..2cec2d329c 100644 --- a/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart +++ b/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart @@ -3,7 +3,7 @@ import 'package:drift/drift.dart' as i0; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart' as i1; -import 'package:immich_mobile/domain/models/asset/asset.model.dart' as i2; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart' as i2; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart' as i3; import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4; @@ -19,6 +19,7 @@ typedef $$LocalAssetEntityTableCreateCompanionBuilder i0.Value<int?> durationInSeconds, required String localId, i0.Value<String?> checksum, + i0.Value<bool> isFavorite, }); typedef $$LocalAssetEntityTableUpdateCompanionBuilder = i1.LocalAssetEntityCompanion Function({ @@ -31,6 +32,7 @@ typedef $$LocalAssetEntityTableUpdateCompanionBuilder i0.Value<int?> durationInSeconds, i0.Value<String> localId, i0.Value<String?> checksum, + i0.Value<bool> isFavorite, }); class $$LocalAssetEntityTableFilterComposer @@ -71,6 +73,9 @@ class $$LocalAssetEntityTableFilterComposer i0.ColumnFilters<String> get checksum => $composableBuilder( column: $table.checksum, builder: (column) => i0.ColumnFilters(column)); + + i0.ColumnFilters<bool> get isFavorite => $composableBuilder( + column: $table.isFavorite, builder: (column) => i0.ColumnFilters(column)); } class $$LocalAssetEntityTableOrderingComposer @@ -111,6 +116,10 @@ class $$LocalAssetEntityTableOrderingComposer i0.ColumnOrderings<String> get checksum => $composableBuilder( column: $table.checksum, builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings<bool> get isFavorite => $composableBuilder( + column: $table.isFavorite, + builder: (column) => i0.ColumnOrderings(column)); } class $$LocalAssetEntityTableAnnotationComposer @@ -148,6 +157,9 @@ class $$LocalAssetEntityTableAnnotationComposer i0.GeneratedColumn<String> get checksum => $composableBuilder(column: $table.checksum, builder: (column) => column); + + i0.GeneratedColumn<bool> get isFavorite => $composableBuilder( + column: $table.isFavorite, builder: (column) => column); } class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< @@ -188,6 +200,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< i0.Value<int?> durationInSeconds = const i0.Value.absent(), i0.Value<String> localId = const i0.Value.absent(), i0.Value<String?> checksum = const i0.Value.absent(), + i0.Value<bool> isFavorite = const i0.Value.absent(), }) => i1.LocalAssetEntityCompanion( name: name, @@ -199,6 +212,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< durationInSeconds: durationInSeconds, localId: localId, checksum: checksum, + isFavorite: isFavorite, ), createCompanionCallback: ({ required String name, @@ -210,6 +224,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< i0.Value<int?> durationInSeconds = const i0.Value.absent(), required String localId, i0.Value<String?> checksum = const i0.Value.absent(), + i0.Value<bool> isFavorite = const i0.Value.absent(), }) => i1.LocalAssetEntityCompanion.insert( name: name, @@ -221,6 +236,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< durationInSeconds: durationInSeconds, localId: localId, checksum: checksum, + isFavorite: isFavorite, ), withReferenceMapper: (p0) => p0 .map((e) => (e.readTable(table), i0.BaseReferences(db, table, e))) @@ -312,6 +328,16 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity late final i0.GeneratedColumn<String> checksum = i0.GeneratedColumn<String>( 'checksum', aliasedName, true, type: i0.DriftSqlType.string, requiredDuringInsert: false); + static const i0.VerificationMeta _isFavoriteMeta = + const i0.VerificationMeta('isFavorite'); + @override + late final i0.GeneratedColumn<bool> isFavorite = i0.GeneratedColumn<bool>( + 'is_favorite', aliasedName, false, + type: i0.DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: i0.GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))'), + defaultValue: const i4.Constant(false)); @override List<i0.GeneratedColumn> get $columns => [ name, @@ -322,7 +348,8 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity height, durationInSeconds, localId, - checksum + checksum, + isFavorite ]; @override String get aliasedName => _alias ?? actualTableName; @@ -373,6 +400,12 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity context.handle(_checksumMeta, checksum.isAcceptableOrUnknown(data['checksum']!, _checksumMeta)); } + if (data.containsKey('is_favorite')) { + context.handle( + _isFavoriteMeta, + isFavorite.isAcceptableOrUnknown( + data['is_favorite']!, _isFavoriteMeta)); + } return context; } @@ -402,6 +435,8 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity .read(i0.DriftSqlType.string, data['${effectivePrefix}local_id'])!, checksum: attachedDatabase.typeMapping .read(i0.DriftSqlType.string, data['${effectivePrefix}checksum']), + isFavorite: attachedDatabase.typeMapping + .read(i0.DriftSqlType.bool, data['${effectivePrefix}is_favorite'])!, ); } @@ -429,6 +464,7 @@ class LocalAssetEntityData extends i0.DataClass final int? durationInSeconds; final String localId; final String? checksum; + final bool isFavorite; const LocalAssetEntityData( {required this.name, required this.type, @@ -438,7 +474,8 @@ class LocalAssetEntityData extends i0.DataClass this.height, this.durationInSeconds, required this.localId, - this.checksum}); + this.checksum, + required this.isFavorite}); @override Map<String, i0.Expression> toColumns(bool nullToAbsent) { final map = <String, i0.Expression>{}; @@ -462,6 +499,7 @@ class LocalAssetEntityData extends i0.DataClass if (!nullToAbsent || checksum != null) { map['checksum'] = i0.Variable<String>(checksum); } + map['is_favorite'] = i0.Variable<bool>(isFavorite); return map; } @@ -479,6 +517,7 @@ class LocalAssetEntityData extends i0.DataClass durationInSeconds: serializer.fromJson<int?>(json['durationInSeconds']), localId: serializer.fromJson<String>(json['localId']), checksum: serializer.fromJson<String?>(json['checksum']), + isFavorite: serializer.fromJson<bool>(json['isFavorite']), ); } @override @@ -495,6 +534,7 @@ class LocalAssetEntityData extends i0.DataClass 'durationInSeconds': serializer.toJson<int?>(durationInSeconds), 'localId': serializer.toJson<String>(localId), 'checksum': serializer.toJson<String?>(checksum), + 'isFavorite': serializer.toJson<bool>(isFavorite), }; } @@ -507,7 +547,8 @@ class LocalAssetEntityData extends i0.DataClass i0.Value<int?> height = const i0.Value.absent(), i0.Value<int?> durationInSeconds = const i0.Value.absent(), String? localId, - i0.Value<String?> checksum = const i0.Value.absent()}) => + i0.Value<String?> checksum = const i0.Value.absent(), + bool? isFavorite}) => i1.LocalAssetEntityData( name: name ?? this.name, type: type ?? this.type, @@ -520,6 +561,7 @@ class LocalAssetEntityData extends i0.DataClass : this.durationInSeconds, localId: localId ?? this.localId, checksum: checksum.present ? checksum.value : this.checksum, + isFavorite: isFavorite ?? this.isFavorite, ); LocalAssetEntityData copyWithCompanion(i1.LocalAssetEntityCompanion data) { return LocalAssetEntityData( @@ -534,6 +576,8 @@ class LocalAssetEntityData extends i0.DataClass : this.durationInSeconds, localId: data.localId.present ? data.localId.value : this.localId, checksum: data.checksum.present ? data.checksum.value : this.checksum, + isFavorite: + data.isFavorite.present ? data.isFavorite.value : this.isFavorite, ); } @@ -548,14 +592,15 @@ class LocalAssetEntityData extends i0.DataClass ..write('height: $height, ') ..write('durationInSeconds: $durationInSeconds, ') ..write('localId: $localId, ') - ..write('checksum: $checksum') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite') ..write(')')) .toString(); } @override int get hashCode => Object.hash(name, type, createdAt, updatedAt, width, - height, durationInSeconds, localId, checksum); + height, durationInSeconds, localId, checksum, isFavorite); @override bool operator ==(Object other) => identical(this, other) || @@ -568,7 +613,8 @@ class LocalAssetEntityData extends i0.DataClass other.height == this.height && other.durationInSeconds == this.durationInSeconds && other.localId == this.localId && - other.checksum == this.checksum); + other.checksum == this.checksum && + other.isFavorite == this.isFavorite); } class LocalAssetEntityCompanion @@ -582,6 +628,7 @@ class LocalAssetEntityCompanion final i0.Value<int?> durationInSeconds; final i0.Value<String> localId; final i0.Value<String?> checksum; + final i0.Value<bool> isFavorite; const LocalAssetEntityCompanion({ this.name = const i0.Value.absent(), this.type = const i0.Value.absent(), @@ -592,6 +639,7 @@ class LocalAssetEntityCompanion this.durationInSeconds = const i0.Value.absent(), this.localId = const i0.Value.absent(), this.checksum = const i0.Value.absent(), + this.isFavorite = const i0.Value.absent(), }); LocalAssetEntityCompanion.insert({ required String name, @@ -603,6 +651,7 @@ class LocalAssetEntityCompanion this.durationInSeconds = const i0.Value.absent(), required String localId, this.checksum = const i0.Value.absent(), + this.isFavorite = const i0.Value.absent(), }) : name = i0.Value(name), type = i0.Value(type), localId = i0.Value(localId); @@ -616,6 +665,7 @@ class LocalAssetEntityCompanion i0.Expression<int>? durationInSeconds, i0.Expression<String>? localId, i0.Expression<String>? checksum, + i0.Expression<bool>? isFavorite, }) { return i0.RawValuesInsertable({ if (name != null) 'name': name, @@ -627,6 +677,7 @@ class LocalAssetEntityCompanion if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, if (localId != null) 'local_id': localId, if (checksum != null) 'checksum': checksum, + if (isFavorite != null) 'is_favorite': isFavorite, }); } @@ -639,7 +690,8 @@ class LocalAssetEntityCompanion i0.Value<int?>? height, i0.Value<int?>? durationInSeconds, i0.Value<String>? localId, - i0.Value<String?>? checksum}) { + i0.Value<String?>? checksum, + i0.Value<bool>? isFavorite}) { return i1.LocalAssetEntityCompanion( name: name ?? this.name, type: type ?? this.type, @@ -650,6 +702,7 @@ class LocalAssetEntityCompanion durationInSeconds: durationInSeconds ?? this.durationInSeconds, localId: localId ?? this.localId, checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, ); } @@ -684,6 +737,9 @@ class LocalAssetEntityCompanion if (checksum.present) { map['checksum'] = i0.Variable<String>(checksum.value); } + if (isFavorite.present) { + map['is_favorite'] = i0.Variable<bool>(isFavorite.value); + } return map; } @@ -698,7 +754,8 @@ class LocalAssetEntityCompanion ..write('height: $height, ') ..write('durationInSeconds: $durationInSeconds, ') ..write('localId: $localId, ') - ..write('checksum: $checksum') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite') ..write(')')) .toString(); } diff --git a/mobile/lib/infrastructure/repositories/album_media.repository.dart b/mobile/lib/infrastructure/repositories/album_media.repository.dart index c834169852..0a2da332fc 100644 --- a/mobile/lib/infrastructure/repositories/album_media.repository.dart +++ b/mobile/lib/infrastructure/repositories/album_media.repository.dart @@ -1,11 +1,15 @@ import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/domain/interfaces/album_media.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart' as asset; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart' + as asset; import 'package:immich_mobile/domain/models/local_album.model.dart'; import 'package:photo_manager/photo_manager.dart'; +import 'package:platform/platform.dart'; class AlbumMediaRepository implements IAlbumMediaRepository { - const AlbumMediaRepository(); + final Platform _platform; + const AlbumMediaRepository({Platform platform = const LocalPlatform()}) + : _platform = platform; PMFilter _getAlbumFilter({ withAssetTitle = false, @@ -42,7 +46,12 @@ class AlbumMediaRepository implements IAlbumMediaRepository { ); return PhotoManager.getAssetPathList(hasAll: true, filterOption: filter) - .then((e) => e.toDtoList()); + .then((e) { + if (_platform.isAndroid) { + e.removeWhere((a) => a.isAll); + } + return e.toDtoList(); + }); } @override @@ -85,7 +94,7 @@ class AlbumMediaRepository implements IAlbumMediaRepository { extension on AssetEntity { Future<asset.LocalAsset> toDto() async => asset.LocalAsset( - localId: id, + id: id, name: title ?? await titleAsync, type: switch (type) { AssetType.other => asset.AssetType.other, @@ -114,7 +123,6 @@ extension on AssetPathEntity { // the assetCountAsync call is expensive for larger albums with several thousand assets assetCount: withAssetCount ? await assetCountAsync : 0, backupSelection: BackupSelection.none, - isAll: isAll, ); } diff --git a/mobile/lib/infrastructure/repositories/local_album.repository.dart b/mobile/lib/infrastructure/repositories/local_album.repository.dart index 557c264409..da85380c20 100644 --- a/mobile/lib/infrastructure/repositories/local_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_album.repository.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; import 'package:immich_mobile/domain/interfaces/local_album.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/local_album.model.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart'; @@ -137,10 +137,8 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository id: localAlbum.id, name: localAlbum.name, updatedAt: Value(localAlbum.updatedAt), - assetCount: Value(localAlbum.assetCount), thumbnailId: Value.absentIfNull(localAlbum.thumbnailId), backupSelection: localAlbum.backupSelection, - isAll: Value(localAlbum.isAll), ); return _db.localAlbumEntity @@ -160,7 +158,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository _db.localAlbumAssetEntity, assets.map( (a) => LocalAlbumAssetEntityCompanion.insert( - assetId: a.localId, + assetId: a.id, albumId: albumId, ), ), @@ -223,7 +221,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository width: Value.absentIfNull(a.width), height: Value.absentIfNull(a.height), durationInSeconds: Value.absentIfNull(a.durationInSeconds), - localId: a.localId, + localId: a.id, checksum: Value.absentIfNull(a.checksum), ), ), diff --git a/mobile/lib/infrastructure/repositories/local_asset.repository.dart b/mobile/lib/infrastructure/repositories/local_asset.repository.dart index c77e997d23..cb9119b653 100644 --- a/mobile/lib/infrastructure/repositories/local_asset.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_asset.repository.dart @@ -1,5 +1,5 @@ import 'package:immich_mobile/domain/interfaces/local_asset.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; diff --git a/mobile/lib/infrastructure/utils/asset.mixin.dart b/mobile/lib/infrastructure/utils/asset.mixin.dart index e632b0a49d..4e14a2919f 100644 --- a/mobile/lib/infrastructure/utils/asset.mixin.dart +++ b/mobile/lib/infrastructure/utils/asset.mixin.dart @@ -1,5 +1,5 @@ import 'package:drift/drift.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; mixin AssetEntityMixin on Table { TextColumn get name => text()(); diff --git a/mobile/test/domain/services/device_sync_service_test.dart b/mobile/test/domain/services/device_sync_service_test.dart index 49ccb81117..389872626b 100644 --- a/mobile/test/domain/services/device_sync_service_test.dart +++ b/mobile/test/domain/services/device_sync_service_test.dart @@ -3,7 +3,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:immich_mobile/domain/interfaces/album_media.interface.dart'; import 'package:immich_mobile/domain/interfaces/local_album.interface.dart'; import 'package:immich_mobile/domain/interfaces/local_asset.interface.dart'; -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/local_album.model.dart'; import 'package:immich_mobile/domain/services/device_sync.service.dart'; import 'package:immich_mobile/utils/nullable_value.dart'; @@ -257,9 +257,9 @@ void main() { newAlbum.copyWith(updatedAt: DateTime(2024), assetCount: 2); final assets = [ LocalAssetStub.image1 - .copyWith(localId: "asset1", createdAt: DateTime(2024, 1, 1)), + .copyWith(id: "asset1", createdAt: DateTime(2024, 1, 1)), LocalAssetStub.image2.copyWith( - localId: "asset2", + id: "asset2", createdAt: DateTime(2024, 1, 2), ), ]; @@ -284,7 +284,7 @@ void main() { expect(capturedAlbum.id, newAlbum.id); expect(capturedAlbum.assetCount, refreshedAlbum.assetCount); expect(capturedAlbum.updatedAt, refreshedAlbum.updatedAt); - expect(capturedAlbum.thumbnailId, assets.first.localId); + expect(capturedAlbum.thumbnailId, assets.first.id); expect(listEquals(capturedAssets, assets), isTrue); }, ); @@ -354,7 +354,7 @@ void main() { when(() => mockAlbumMediaRepo.refresh(dbAlbum.id)) .thenAnswer((_) async => refreshedAlbum); - final newAsset = LocalAssetStub.image2.copyWith(localId: "new_asset"); + final newAsset = LocalAssetStub.image2.copyWith(id: "new_asset"); when( () => mockAlbumMediaRepo.getAssetsForAlbum( dbAlbum.id, @@ -387,7 +387,7 @@ void main() { (a) => a.id == dbAlbum.id && a.assetCount == 2 && - a.thumbnailId == newAsset.localId, + a.thumbnailId == newAsset.id, ), ), ), @@ -446,7 +446,7 @@ void main() { ).called(1); verify( () => mockLocalAlbumRepo - .removeAssets(dbAlbum.id, [LocalAssetStub.image1.localId]), + .removeAssets(dbAlbum.id, [LocalAssetStub.image1.id]), ).called(1); }, ); @@ -519,7 +519,7 @@ void main() { test('returns true and updates assets/metadata on success', () async { final newAsset = LocalAssetStub.image2.copyWith( - localId: "asset2", + id: "asset2", createdAt: DateTime(2024, 1, 1, 10, 30, 0), ); when( @@ -531,7 +531,7 @@ void main() { when(() => mockLocalAssetRepo.get("thumb1")).thenAnswer( (_) async => LocalAssetStub.image1.copyWith( - localId: "thumb1", + id: "thumb1", createdAt: DateTime(2024, 1, 1, 9, 0, 0), ), ); @@ -556,7 +556,7 @@ void main() { a.id == dbAlbum.id && a.assetCount == 2 && a.updatedAt == refreshedAlbum.updatedAt && - a.thumbnailId == newAsset.localId, + a.thumbnailId == newAsset.id, ), ), ), @@ -567,7 +567,7 @@ void main() { test('returns true and keeps old thumbnail if newer', () async { final newAsset = LocalAssetStub.image2.copyWith( - localId: "asset2", + id: "asset2", createdAt: DateTime(2024, 1, 1, 8, 0, 0), ); when( @@ -579,7 +579,7 @@ void main() { when(() => mockLocalAssetRepo.get("thumb1")).thenAnswer( (_) async => LocalAssetStub.image1.copyWith( - localId: "thumb1", + id: "thumb1", createdAt: DateTime(2024, 1, 1, 9, 0, 0), ), ); @@ -614,7 +614,7 @@ void main() { test('returns true and sets new thumbnail if db thumb is null', () async { final dbAlbumNoThumb = dbAlbum.copyWith(thumbnailId: null); final newAsset = LocalAssetStub.image2.copyWith( - localId: "asset2", + id: "asset2", createdAt: DateTime(2024, 1, 1, 10, 30, 0), ); when( @@ -644,7 +644,7 @@ void main() { a.id == dbAlbum.id && a.assetCount == 2 && a.updatedAt == refreshedAlbum.updatedAt && - a.thumbnailId == newAsset.localId, + a.thumbnailId == newAsset.id, ), ), ), @@ -731,22 +731,22 @@ void main() { ); final dbAsset1 = LocalAssetStub.image1.copyWith( - localId: "asset1", + id: "asset1", createdAt: DateTime(2024), updatedAt: DateTime(2024), ); final dbAsset2 = LocalAssetStub.image2.copyWith( - localId: "asset2", + id: "asset2", createdAt: DateTime(2024), updatedAt: DateTime(2024), ); // To be deleted final deviceAsset1 = LocalAssetStub.image1.copyWith( - localId: "asset1", + id: "asset1", createdAt: DateTime(2024), updatedAt: DateTime(2025), ); // Updated final deviceAsset3 = LocalAssetStub.video1.copyWith( - localId: "asset3", + id: "asset3", createdAt: DateTime(2024), updatedAt: DateTime(2024), ); // Added @@ -819,7 +819,7 @@ void main() { a.id == emptyDbAlbum.id && a.assetCount == deviceAssets.length && a.updatedAt == refreshedWithAssets.updatedAt && - a.thumbnailId == deviceAssets.first.localId, + a.thumbnailId == deviceAssets.first.id, ), ), ), @@ -833,7 +833,7 @@ void main() { final deviceAssets = [deviceAsset1, deviceAsset3]; deviceAssets.sort((a, b) => a.createdAt.compareTo(b.createdAt)); final dbAssets = [dbAsset1, dbAsset2]; - dbAssets.sort((a, b) => a.localId.compareTo(b.localId)); + dbAssets.sort((a, b) => a.id.compareTo(b.id)); when(() => mockAlbumMediaRepo.getAssetsForAlbum(dbAlbum.id)).thenAnswer( (_) async => deviceAssets, @@ -857,10 +857,10 @@ void main() { return list.length == 2 && list.any( (a) => - a.localId == "asset1" && + a.id == "asset1" && a.updatedAt == deviceAsset1.updatedAt, ) && - list.any((a) => a.localId == "asset3"); + list.any((a) => a.id == "asset3"); }), ), ), @@ -874,7 +874,7 @@ void main() { a.id == dbAlbum.id && a.assetCount == 2 && a.updatedAt == currentRefreshedAlbum.updatedAt && - a.thumbnailId == deviceAssets.first.localId, + a.thumbnailId == deviceAssets.first.id, ), ), ), @@ -892,7 +892,7 @@ void main() { final dbAssets = [dbAsset1, dbAsset2]; final deviceAssets = [dbAsset1, dbAsset2]; deviceAssets.sort((a, b) => a.createdAt.compareTo(b.createdAt)); - dbAssets.sort((a, b) => a.localId.compareTo(b.localId)); + dbAssets.sort((a, b) => a.id.compareTo(b.id)); when(() => mockAlbumMediaRepo.getAssetsForAlbum(dbAlbum.id)) .thenAnswer((_) async => deviceAssets); @@ -915,7 +915,7 @@ void main() { a.id == dbAlbum.id && a.assetCount == 2 && a.updatedAt == currentRefreshedAlbum.updatedAt && - a.thumbnailId == deviceAssets.first.localId, + a.thumbnailId == deviceAssets.first.id, ), ), ), diff --git a/mobile/test/fixtures/local_album.stub.dart b/mobile/test/fixtures/local_album.stub.dart index 32d25ce254..517bdd5189 100644 --- a/mobile/test/fixtures/local_album.stub.dart +++ b/mobile/test/fixtures/local_album.stub.dart @@ -10,7 +10,6 @@ abstract final class LocalAlbumStub { assetCount: 1, thumbnailId: null, backupSelection: BackupSelection.none, - isAll: false, ); static LocalAlbum get album2 => LocalAlbum( @@ -20,7 +19,6 @@ abstract final class LocalAlbumStub { assetCount: 2, thumbnailId: null, backupSelection: BackupSelection.selected, - isAll: true, ); static LocalAlbum get album3 => LocalAlbum( @@ -30,6 +28,5 @@ abstract final class LocalAlbumStub { assetCount: 20, thumbnailId: "123", backupSelection: BackupSelection.excluded, - isAll: false, ); } diff --git a/mobile/test/fixtures/local_asset.stub.dart b/mobile/test/fixtures/local_asset.stub.dart index a399dfdc22..1d47e7abe5 100644 --- a/mobile/test/fixtures/local_asset.stub.dart +++ b/mobile/test/fixtures/local_asset.stub.dart @@ -1,10 +1,10 @@ -import 'package:immich_mobile/domain/models/asset/asset.model.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; abstract final class LocalAssetStub { const LocalAssetStub(); static LocalAsset get image1 => LocalAsset( - localId: "image1", + id: "image1", name: "image1.jpg", checksum: "image1-checksum", type: AssetType.image, @@ -16,7 +16,7 @@ abstract final class LocalAssetStub { ); static LocalAsset get image2 => LocalAsset( - localId: "image2", + id: "image2", name: "image2.jpg", checksum: "image2-checksum", type: AssetType.image, @@ -28,7 +28,7 @@ abstract final class LocalAssetStub { ); static LocalAsset get video1 => LocalAsset( - localId: "video1", + id: "video1", name: "video1.mov", checksum: "video1-checksum", type: AssetType.video,