refactor domain models

This commit is contained in:
shenlong-tanwen 2025-04-22 00:29:26 +05:30
parent 5fc1a63810
commit e9f145a477
22 changed files with 270 additions and 356 deletions

File diff suppressed because one or more lines are too long

View File

@ -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'; import 'package:immich_mobile/domain/models/local_album.model.dart';
abstract interface class IAlbumMediaRepository { abstract interface class IAlbumMediaRepository {

View File

@ -1,9 +1,9 @@
import 'package:immich_mobile/domain/interfaces/db.interface.dart'; 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'; import 'package:immich_mobile/domain/models/local_album.model.dart';
abstract interface class ILocalAlbumRepository implements IDatabaseRepository { 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); 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<List<LocalAsset>> getAssetsForAlbum(String albumId);
Future<void> update(LocalAlbum localAlbum); Future<void> update(LocalAlbum album);
Future<void> delete(String albumId); Future<void> delete(String albumId);

View File

@ -1,5 +1,5 @@
import 'package:immich_mobile/domain/interfaces/db.interface.dart'; 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 { abstract interface class ILocalAssetRepository implements IDatabaseRepository {
Future<LocalAsset> get(String assetId); Future<LocalAsset> get(String assetId);

View File

@ -1,72 +1,46 @@
part 'local_asset.model.dart'; part of 'base_asset.model.dart';
part 'merged_asset.model.dart';
part 'remote_asset.model.dart';
enum AssetType { class Asset extends BaseAsset {
// do not change this order! final String id;
other, final String? localId;
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;
const Asset({ const Asset({
required this.name, required this.id,
required this.checksum, this.localId,
required this.type, required super.name,
required this.createdAt, required super.checksum,
required this.updatedAt, required super.type,
this.width, required super.createdAt,
this.height, required super.updatedAt,
this.durationInSeconds, super.width,
super.height,
super.durationInSeconds,
super.isFavorite = false,
}); });
@override @override
String toString() { String toString() {
return '''Asset { return '''Asset {
id: $id,
name: $name, name: $name,
type: $type, type: $type,
createdAt: $createdAt, createdAt: $createdAt,
updatedAt: $updatedAt, updatedAt: $updatedAt,
width: ${width ?? "<NA>"}, width: ${width ?? "<NA>"},
height: ${height ?? "<NA>"}, height: ${height ?? "<NA>"},
durationInSeconds: ${durationInSeconds ?? "<NA>"} durationInSeconds: ${durationInSeconds ?? "<NA>"},
localId: ${localId ?? "<NA>"},
isFavorite: $isFavorite,
}'''; }''';
} }
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
if (other is! Asset) return false;
if (identical(this, other)) return true; if (identical(this, other)) return true;
if (other is Asset) { return super == other && id == other.id && localId == other.localId;
return name == other.name &&
type == other.type &&
createdAt == other.createdAt &&
updatedAt == other.updatedAt &&
width == other.width &&
height == other.height &&
durationInSeconds == other.durationInSeconds;
}
return false;
} }
@override @override
int get hashCode { int get hashCode => super.hashCode ^ id.hashCode ^ localId.hashCode;
return name.hashCode ^
type.hashCode ^
createdAt.hashCode ^
updatedAt.hashCode ^
width.hashCode ^
height.hashCode ^
durationInSeconds.hashCode;
}
} }

View File

@ -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;
}
}

View File

@ -1,10 +1,12 @@
part of 'asset.model.dart'; part of 'base_asset.model.dart';
class LocalAsset extends Asset { class LocalAsset extends BaseAsset {
final String localId; final String id;
final String? remoteId;
const LocalAsset({ const LocalAsset({
required this.localId, required this.id,
this.remoteId,
required super.name, required super.name,
super.checksum, super.checksum,
required super.type, required super.type,
@ -13,19 +15,22 @@ class LocalAsset extends Asset {
super.width, super.width,
super.height, super.height,
super.durationInSeconds, super.durationInSeconds,
super.isFavorite = false,
}); });
@override @override
String toString() { String toString() {
return '''LocalAsset { return '''LocalAsset {
localId: $localId, id: $id,
name: $name, name: $name,
type: $type, type: $type,
createdAt: $createdAt, createdAt: $createdAt,
updatedAt: $updatedAt, updatedAt: $updatedAt,
width: ${width ?? "<NA>"}, width: ${width ?? "<NA>"},
height: ${height ?? "<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) { bool operator ==(Object other) {
if (other is! LocalAsset) return false; if (other is! LocalAsset) return false;
if (identical(this, other)) return true; if (identical(this, other)) return true;
return super == other && localId == other.localId; return super == other && id == other.id && remoteId == other.remoteId;
} }
@override @override
int get hashCode { int get hashCode => super.hashCode ^ id.hashCode ^ remoteId.hashCode;
return super.hashCode ^ localId.hashCode;
}
LocalAsset copyWith({ LocalAsset copyWith({
String? localId, String? id,
String? remoteId,
String? name, String? name,
String? checksum, String? checksum,
AssetType? type, AssetType? type,
@ -51,9 +55,11 @@ class LocalAsset extends Asset {
int? width, int? width,
int? height, int? height,
int? durationInSeconds, int? durationInSeconds,
bool? isFavorite,
}) { }) {
return LocalAsset( return LocalAsset(
localId: localId ?? this.localId, id: id ?? this.id,
remoteId: remoteId ?? this.remoteId,
name: name ?? this.name, name: name ?? this.name,
checksum: checksum ?? this.checksum, checksum: checksum ?? this.checksum,
type: type ?? this.type, type: type ?? this.type,
@ -62,6 +68,7 @@ class LocalAsset extends Asset {
width: width ?? this.width, width: width ?? this.width,
height: height ?? this.height, height: height ?? this.height,
durationInSeconds: durationInSeconds ?? this.durationInSeconds, durationInSeconds: durationInSeconds ?? this.durationInSeconds,
isFavorite: isFavorite ?? this.isFavorite,
); );
} }
} }

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -11,8 +11,6 @@ class LocalAlbum {
final String name; final String name;
final DateTime updatedAt; final DateTime updatedAt;
/// Whether the album contains all photos (i.e, the virtual "Recent" album)
final bool isAll;
final int assetCount; final int assetCount;
final String? thumbnailId; final String? thumbnailId;
final BackupSelection backupSelection; final BackupSelection backupSelection;
@ -24,7 +22,6 @@ class LocalAlbum {
this.assetCount = 0, this.assetCount = 0,
this.thumbnailId, this.thumbnailId,
this.backupSelection = BackupSelection.none, this.backupSelection = BackupSelection.none,
this.isAll = false,
}); });
LocalAlbum copyWith({ LocalAlbum copyWith({
@ -34,7 +31,6 @@ class LocalAlbum {
int? assetCount, int? assetCount,
NullableValue<String>? thumbnailId, NullableValue<String>? thumbnailId,
BackupSelection? backupSelection, BackupSelection? backupSelection,
bool? isAll,
}) { }) {
return LocalAlbum( return LocalAlbum(
id: id ?? this.id, id: id ?? this.id,
@ -43,7 +39,6 @@ class LocalAlbum {
assetCount: assetCount ?? this.assetCount, assetCount: assetCount ?? this.assetCount,
thumbnailId: thumbnailId?.getOrDefault(this.thumbnailId), thumbnailId: thumbnailId?.getOrDefault(this.thumbnailId),
backupSelection: backupSelection ?? this.backupSelection, backupSelection: backupSelection ?? this.backupSelection,
isAll: isAll ?? this.isAll,
); );
} }
@ -56,7 +51,6 @@ class LocalAlbum {
other.name == name && other.name == name &&
other.updatedAt == updatedAt && other.updatedAt == updatedAt &&
other.assetCount == assetCount && other.assetCount == assetCount &&
other.isAll == isAll &&
other.thumbnailId == thumbnailId && other.thumbnailId == thumbnailId &&
other.backupSelection == backupSelection; other.backupSelection == backupSelection;
} }
@ -67,7 +61,6 @@ class LocalAlbum {
name.hashCode ^ name.hashCode ^
updatedAt.hashCode ^ updatedAt.hashCode ^
assetCount.hashCode ^ assetCount.hashCode ^
isAll.hashCode ^
thumbnailId.hashCode ^ thumbnailId.hashCode ^
backupSelection.hashCode; backupSelection.hashCode;
} }
@ -81,7 +74,6 @@ updatedAt: $updatedAt,
assetCount: $assetCount, assetCount: $assetCount,
thumbnailId: ${thumbnailId ?? '<NA>'}, thumbnailId: ${thumbnailId ?? '<NA>'},
backupSelection: $backupSelection, backupSelection: $backupSelection,
isAll: $isAll
}'''; }''';
} }
} }

View File

@ -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/album_media.interface.dart';
import 'package:immich_mobile/domain/interfaces/local_album.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/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/models/local_album.model.dart';
import 'package:immich_mobile/utils/diff.dart'; import 'package:immich_mobile/utils/diff.dart';
import 'package:immich_mobile/utils/nullable_value.dart'; import 'package:immich_mobile/utils/nullable_value.dart';
@ -34,6 +34,7 @@ class DeviceSyncService {
// and not the albums. // and not the albums.
final deviceAlbums = final deviceAlbums =
(await _albumMediaRepository.getAll()).sortedBy((a) => a.id); (await _albumMediaRepository.getAll()).sortedBy((a) => a.id);
final dbAlbums = final dbAlbums =
await _localAlbumRepository.getAll(sortBy: SortLocalAlbumsBy.id); await _localAlbumRepository.getAll(sortBy: SortLocalAlbumsBy.id);
@ -64,7 +65,7 @@ class DeviceSyncService {
final album = deviceAlbum.copyWith( final album = deviceAlbum.copyWith(
// The below assumes the list is already sorted by createdDate from the filter // 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); await _localAlbumRepository.insert(album, assets);
@ -100,7 +101,7 @@ class DeviceSyncService {
return false; 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 // Faster path - only new assets added
if (await checkAddition(dbAlbum, deviceAlbum)) { if (await checkAddition(dbAlbum, deviceAlbum)) {
@ -157,13 +158,13 @@ class DeviceSyncService {
String? thumbnailId = dbAlbum.thumbnailId; String? thumbnailId = dbAlbum.thumbnailId;
if (thumbnailId == null || newAssets.isNotEmpty) { if (thumbnailId == null || newAssets.isNotEmpty) {
if (thumbnailId == null) { if (thumbnailId == null) {
thumbnailId = newAssets.firstOrNull?.localId; thumbnailId = newAssets.firstOrNull?.id;
} else if (newAssets.isNotEmpty) { } else if (newAssets.isNotEmpty) {
// The below assumes the list is already sorted by createdDate from the filter // The below assumes the list is already sorted by createdDate from the filter
final oldThumbAsset = await _localAssetRepository.get(thumbnailId); final oldThumbAsset = await _localAssetRepository.get(thumbnailId);
if (oldThumbAsset.createdAt if (oldThumbAsset.createdAt
.isBefore(newAssets.firstOrNull!.createdAt)) { .isBefore(newAssets.firstOrNull!.createdAt)) {
thumbnailId = newAssets.firstOrNull?.localId; thumbnailId = newAssets.firstOrNull?.id;
} }
} }
} }
@ -205,14 +206,14 @@ class DeviceSyncService {
thumbnailId: const NullableValue.empty(), thumbnailId: const NullableValue.empty(),
backupSelection: dbAlbum.backupSelection, backupSelection: dbAlbum.backupSelection,
), ),
assetIdsToDelete: assetsInDb.map((a) => a.localId), assetIdsToDelete: assetsInDb.map((a) => a.id),
); );
return true; return true;
} }
// The below assumes the list is already sorted by createdDate from the filter // The below assumes the list is already sorted by createdDate from the filter
String? thumbnailId = assetsInDevice.isNotEmpty String? thumbnailId = assetsInDevice.isNotEmpty
? assetsInDevice.firstOrNull?.localId ? assetsInDevice.firstOrNull?.id
: dbAlbum.thumbnailId; : dbAlbum.thumbnailId;
final updatedDeviceAlbum = deviceAlbum.copyWith( final updatedDeviceAlbum = deviceAlbum.copyWith(
@ -228,8 +229,8 @@ class DeviceSyncService {
return true; return true;
} }
assert(assetsInDb.isSortedBy((a) => a.localId)); assert(assetsInDb.isSortedBy((a) => a.id));
assetsInDevice.sort((a, b) => a.localId.compareTo(b.localId)); assetsInDevice.sort((a, b) => a.id.compareTo(b.id));
final assetsToUpsert = <LocalAsset>[]; final assetsToUpsert = <LocalAsset>[];
final assetsToDelete = <String>[]; final assetsToDelete = <String>[];
@ -237,7 +238,7 @@ class DeviceSyncService {
diffSortedListsSync( diffSortedListsSync(
assetsInDb, assetsInDb,
assetsInDevice, assetsInDevice,
compare: (a, b) => a.localId.compareTo(b.localId), compare: (a, b) => a.id.compareTo(b.id),
both: (dbAsset, deviceAsset) { both: (dbAsset, deviceAsset) {
// Custom comparison to check if the asset has been modified without // Custom comparison to check if the asset has been modified without
// comparing the checksum // comparing the checksum
@ -247,7 +248,7 @@ class DeviceSyncService {
} }
return false; return false;
}, },
onlyFirst: (dbAsset) => assetsToDelete.add(dbAsset.localId), onlyFirst: (dbAsset) => assetsToDelete.add(dbAsset.id),
onlySecond: (deviceAsset) => assetsToUpsert.add(deviceAsset), onlySecond: (deviceAsset) => assetsToUpsert.add(deviceAsset),
); );

View File

@ -10,12 +10,10 @@ class LocalAlbumEntity extends Table with DriftDefaultsMixin {
TextColumn get id => text()(); TextColumn get id => text()();
TextColumn get name => text()(); TextColumn get name => text()();
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
IntColumn get assetCount => integer().withDefault(const Constant(0))();
TextColumn get thumbnailId => text() TextColumn get thumbnailId => text()
.nullable() .nullable()
.references(LocalAssetEntity, #localId, onDelete: KeyAction.setNull)(); .references(LocalAssetEntity, #localId, onDelete: KeyAction.setNull)();
IntColumn get backupSelection => intEnum<BackupSelection>()(); IntColumn get backupSelection => intEnum<BackupSelection>()();
BoolColumn get isAll => boolean().withDefault(const Constant(false))();
@override @override
Set<Column> get primaryKey => {id}; Set<Column> get primaryKey => {id};
@ -30,7 +28,6 @@ extension LocalAlbumEntityX on LocalAlbumEntityData {
assetCount: assetCount, assetCount: assetCount,
thumbnailId: thumbnailId, thumbnailId: thumbnailId,
backupSelection: backupSelection, backupSelection: backupSelection,
isAll: isAll,
); );
} }
} }

View File

@ -16,20 +16,16 @@ typedef $$LocalAlbumEntityTableCreateCompanionBuilder
required String id, required String id,
required String name, required String name,
i0.Value<DateTime> updatedAt, i0.Value<DateTime> updatedAt,
i0.Value<int> assetCount,
i0.Value<String?> thumbnailId, i0.Value<String?> thumbnailId,
required i2.BackupSelection backupSelection, required i2.BackupSelection backupSelection,
i0.Value<bool> isAll,
}); });
typedef $$LocalAlbumEntityTableUpdateCompanionBuilder typedef $$LocalAlbumEntityTableUpdateCompanionBuilder
= i1.LocalAlbumEntityCompanion Function({ = i1.LocalAlbumEntityCompanion Function({
i0.Value<String> id, i0.Value<String> id,
i0.Value<String> name, i0.Value<String> name,
i0.Value<DateTime> updatedAt, i0.Value<DateTime> updatedAt,
i0.Value<int> assetCount,
i0.Value<String?> thumbnailId, i0.Value<String?> thumbnailId,
i0.Value<i2.BackupSelection> backupSelection, i0.Value<i2.BackupSelection> backupSelection,
i0.Value<bool> isAll,
}); });
final class $$LocalAlbumEntityTableReferences extends i0.BaseReferences< final class $$LocalAlbumEntityTableReferences extends i0.BaseReferences<
@ -82,17 +78,11 @@ class $$LocalAlbumEntityTableFilterComposer
i0.ColumnFilters<DateTime> get updatedAt => $composableBuilder( i0.ColumnFilters<DateTime> get updatedAt => $composableBuilder(
column: $table.updatedAt, builder: (column) => i0.ColumnFilters(column)); 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> i0.ColumnWithTypeConverterFilters<i2.BackupSelection, i2.BackupSelection, int>
get backupSelection => $composableBuilder( get backupSelection => $composableBuilder(
column: $table.backupSelection, column: $table.backupSelection,
builder: (column) => i0.ColumnWithTypeConverterFilters(column)); builder: (column) => i0.ColumnWithTypeConverterFilters(column));
i0.ColumnFilters<bool> get isAll => $composableBuilder(
column: $table.isAll, builder: (column) => i0.ColumnFilters(column));
i5.$$LocalAssetEntityTableFilterComposer get thumbnailId { i5.$$LocalAssetEntityTableFilterComposer get thumbnailId {
final i5.$$LocalAssetEntityTableFilterComposer composer = $composerBuilder( final i5.$$LocalAssetEntityTableFilterComposer composer = $composerBuilder(
composer: this, composer: this,
@ -135,17 +125,10 @@ class $$LocalAlbumEntityTableOrderingComposer
column: $table.updatedAt, column: $table.updatedAt,
builder: (column) => i0.ColumnOrderings(column)); 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( i0.ColumnOrderings<int> get backupSelection => $composableBuilder(
column: $table.backupSelection, column: $table.backupSelection,
builder: (column) => i0.ColumnOrderings(column)); builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<bool> get isAll => $composableBuilder(
column: $table.isAll, builder: (column) => i0.ColumnOrderings(column));
i5.$$LocalAssetEntityTableOrderingComposer get thumbnailId { i5.$$LocalAssetEntityTableOrderingComposer get thumbnailId {
final i5.$$LocalAssetEntityTableOrderingComposer composer = final i5.$$LocalAssetEntityTableOrderingComposer composer =
$composerBuilder( $composerBuilder(
@ -189,16 +172,10 @@ class $$LocalAlbumEntityTableAnnotationComposer
i0.GeneratedColumn<DateTime> get updatedAt => i0.GeneratedColumn<DateTime> get updatedAt =>
$composableBuilder(column: $table.updatedAt, builder: (column) => column); $composableBuilder(column: $table.updatedAt, builder: (column) => column);
i0.GeneratedColumn<int> get assetCount => $composableBuilder(
column: $table.assetCount, builder: (column) => column);
i0.GeneratedColumnWithTypeConverter<i2.BackupSelection, int> i0.GeneratedColumnWithTypeConverter<i2.BackupSelection, int>
get backupSelection => $composableBuilder( get backupSelection => $composableBuilder(
column: $table.backupSelection, builder: (column) => column); column: $table.backupSelection, builder: (column) => column);
i0.GeneratedColumn<bool> get isAll =>
$composableBuilder(column: $table.isAll, builder: (column) => column);
i5.$$LocalAssetEntityTableAnnotationComposer get thumbnailId { i5.$$LocalAssetEntityTableAnnotationComposer get thumbnailId {
final i5.$$LocalAssetEntityTableAnnotationComposer composer = final i5.$$LocalAssetEntityTableAnnotationComposer composer =
$composerBuilder( $composerBuilder(
@ -252,38 +229,30 @@ class $$LocalAlbumEntityTableTableManager extends i0.RootTableManager<
i0.Value<String> id = const i0.Value.absent(), i0.Value<String> id = const i0.Value.absent(),
i0.Value<String> name = const i0.Value.absent(), i0.Value<String> name = const i0.Value.absent(),
i0.Value<DateTime> updatedAt = 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<String?> thumbnailId = const i0.Value.absent(),
i0.Value<i2.BackupSelection> backupSelection = i0.Value<i2.BackupSelection> backupSelection =
const i0.Value.absent(), const i0.Value.absent(),
i0.Value<bool> isAll = const i0.Value.absent(),
}) => }) =>
i1.LocalAlbumEntityCompanion( i1.LocalAlbumEntityCompanion(
id: id, id: id,
name: name, name: name,
updatedAt: updatedAt, updatedAt: updatedAt,
assetCount: assetCount,
thumbnailId: thumbnailId, thumbnailId: thumbnailId,
backupSelection: backupSelection, backupSelection: backupSelection,
isAll: isAll,
), ),
createCompanionCallback: ({ createCompanionCallback: ({
required String id, required String id,
required String name, required String name,
i0.Value<DateTime> updatedAt = 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<String?> thumbnailId = const i0.Value.absent(),
required i2.BackupSelection backupSelection, required i2.BackupSelection backupSelection,
i0.Value<bool> isAll = const i0.Value.absent(),
}) => }) =>
i1.LocalAlbumEntityCompanion.insert( i1.LocalAlbumEntityCompanion.insert(
id: id, id: id,
name: name, name: name,
updatedAt: updatedAt, updatedAt: updatedAt,
assetCount: assetCount,
thumbnailId: thumbnailId, thumbnailId: thumbnailId,
backupSelection: backupSelection, backupSelection: backupSelection,
isAll: isAll,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper: (p0) => p0
.map((e) => ( .map((e) => (
@ -368,14 +337,6 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity
type: i0.DriftSqlType.dateTime, type: i0.DriftSqlType.dateTime,
requiredDuringInsert: false, requiredDuringInsert: false,
defaultValue: i4.currentDateAndTime); 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 = static const i0.VerificationMeta _thumbnailIdMeta =
const i0.VerificationMeta('thumbnailId'); const i0.VerificationMeta('thumbnailId');
@override @override
@ -392,19 +353,9 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity
type: i0.DriftSqlType.int, requiredDuringInsert: true) type: i0.DriftSqlType.int, requiredDuringInsert: true)
.withConverter<i2.BackupSelection>( .withConverter<i2.BackupSelection>(
i1.$LocalAlbumEntityTable.$converterbackupSelection); 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 @override
List<i0.GeneratedColumn> get $columns => List<i0.GeneratedColumn> get $columns =>
[id, name, updatedAt, assetCount, thumbnailId, backupSelection, isAll]; [id, name, updatedAt, thumbnailId, backupSelection];
@override @override
String get aliasedName => _alias ?? actualTableName; String get aliasedName => _alias ?? actualTableName;
@override @override
@ -431,22 +382,12 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity
context.handle(_updatedAtMeta, context.handle(_updatedAtMeta,
updatedAt.isAcceptableOrUnknown(data['updated_at']!, _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')) { if (data.containsKey('thumbnail_id')) {
context.handle( context.handle(
_thumbnailIdMeta, _thumbnailIdMeta,
thumbnailId.isAcceptableOrUnknown( thumbnailId.isAcceptableOrUnknown(
data['thumbnail_id']!, _thumbnailIdMeta)); data['thumbnail_id']!, _thumbnailIdMeta));
} }
if (data.containsKey('is_all')) {
context.handle(
_isAllMeta, isAll.isAcceptableOrUnknown(data['is_all']!, _isAllMeta));
}
return context; return context;
} }
@ -463,15 +404,11 @@ class $LocalAlbumEntityTable extends i3.LocalAlbumEntity
.read(i0.DriftSqlType.string, data['${effectivePrefix}name'])!, .read(i0.DriftSqlType.string, data['${effectivePrefix}name'])!,
updatedAt: attachedDatabase.typeMapping.read( updatedAt: attachedDatabase.typeMapping.read(
i0.DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, i0.DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!,
assetCount: attachedDatabase.typeMapping
.read(i0.DriftSqlType.int, data['${effectivePrefix}asset_count'])!,
thumbnailId: attachedDatabase.typeMapping thumbnailId: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}thumbnail_id']), .read(i0.DriftSqlType.string, data['${effectivePrefix}thumbnail_id']),
backupSelection: i1.$LocalAlbumEntityTable.$converterbackupSelection backupSelection: i1.$LocalAlbumEntityTable.$converterbackupSelection
.fromSql(attachedDatabase.typeMapping.read(i0.DriftSqlType.int, .fromSql(attachedDatabase.typeMapping.read(i0.DriftSqlType.int,
data['${effectivePrefix}backup_selection'])!), 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 id;
final String name; final String name;
final DateTime updatedAt; final DateTime updatedAt;
final int assetCount;
final String? thumbnailId; final String? thumbnailId;
final i2.BackupSelection backupSelection; final i2.BackupSelection backupSelection;
final bool isAll;
const LocalAlbumEntityData( const LocalAlbumEntityData(
{required this.id, {required this.id,
required this.name, required this.name,
required this.updatedAt, required this.updatedAt,
required this.assetCount,
this.thumbnailId, this.thumbnailId,
required this.backupSelection, required this.backupSelection});
required this.isAll});
@override @override
Map<String, i0.Expression> toColumns(bool nullToAbsent) { Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{}; final map = <String, i0.Expression>{};
map['id'] = i0.Variable<String>(id); map['id'] = i0.Variable<String>(id);
map['name'] = i0.Variable<String>(name); map['name'] = i0.Variable<String>(name);
map['updated_at'] = i0.Variable<DateTime>(updatedAt); map['updated_at'] = i0.Variable<DateTime>(updatedAt);
map['asset_count'] = i0.Variable<int>(assetCount);
if (!nullToAbsent || thumbnailId != null) { if (!nullToAbsent || thumbnailId != null) {
map['thumbnail_id'] = i0.Variable<String>(thumbnailId); map['thumbnail_id'] = i0.Variable<String>(thumbnailId);
} }
@ -522,7 +454,6 @@ class LocalAlbumEntityData extends i0.DataClass
.$LocalAlbumEntityTable.$converterbackupSelection .$LocalAlbumEntityTable.$converterbackupSelection
.toSql(backupSelection)); .toSql(backupSelection));
} }
map['is_all'] = i0.Variable<bool>(isAll);
return map; return map;
} }
@ -533,11 +464,9 @@ class LocalAlbumEntityData extends i0.DataClass
id: serializer.fromJson<String>(json['id']), id: serializer.fromJson<String>(json['id']),
name: serializer.fromJson<String>(json['name']), name: serializer.fromJson<String>(json['name']),
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']), updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
assetCount: serializer.fromJson<int>(json['assetCount']),
thumbnailId: serializer.fromJson<String?>(json['thumbnailId']), thumbnailId: serializer.fromJson<String?>(json['thumbnailId']),
backupSelection: i1.$LocalAlbumEntityTable.$converterbackupSelection backupSelection: i1.$LocalAlbumEntityTable.$converterbackupSelection
.fromJson(serializer.fromJson<int>(json['backupSelection'])), .fromJson(serializer.fromJson<int>(json['backupSelection'])),
isAll: serializer.fromJson<bool>(json['isAll']),
); );
} }
@override @override
@ -547,12 +476,10 @@ class LocalAlbumEntityData extends i0.DataClass
'id': serializer.toJson<String>(id), 'id': serializer.toJson<String>(id),
'name': serializer.toJson<String>(name), 'name': serializer.toJson<String>(name),
'updatedAt': serializer.toJson<DateTime>(updatedAt), 'updatedAt': serializer.toJson<DateTime>(updatedAt),
'assetCount': serializer.toJson<int>(assetCount),
'thumbnailId': serializer.toJson<String?>(thumbnailId), 'thumbnailId': serializer.toJson<String?>(thumbnailId),
'backupSelection': serializer.toJson<int>(i1 'backupSelection': serializer.toJson<int>(i1
.$LocalAlbumEntityTable.$converterbackupSelection .$LocalAlbumEntityTable.$converterbackupSelection
.toJson(backupSelection)), .toJson(backupSelection)),
'isAll': serializer.toJson<bool>(isAll),
}; };
} }
@ -560,32 +487,25 @@ class LocalAlbumEntityData extends i0.DataClass
{String? id, {String? id,
String? name, String? name,
DateTime? updatedAt, DateTime? updatedAt,
int? assetCount,
i0.Value<String?> thumbnailId = const i0.Value.absent(), i0.Value<String?> thumbnailId = const i0.Value.absent(),
i2.BackupSelection? backupSelection, i2.BackupSelection? backupSelection}) =>
bool? isAll}) =>
i1.LocalAlbumEntityData( i1.LocalAlbumEntityData(
id: id ?? this.id, id: id ?? this.id,
name: name ?? this.name, name: name ?? this.name,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
assetCount: assetCount ?? this.assetCount,
thumbnailId: thumbnailId.present ? thumbnailId.value : this.thumbnailId, thumbnailId: thumbnailId.present ? thumbnailId.value : this.thumbnailId,
backupSelection: backupSelection ?? this.backupSelection, backupSelection: backupSelection ?? this.backupSelection,
isAll: isAll ?? this.isAll,
); );
LocalAlbumEntityData copyWithCompanion(i1.LocalAlbumEntityCompanion data) { LocalAlbumEntityData copyWithCompanion(i1.LocalAlbumEntityCompanion data) {
return LocalAlbumEntityData( return LocalAlbumEntityData(
id: data.id.present ? data.id.value : this.id, id: data.id.present ? data.id.value : this.id,
name: data.name.present ? data.name.value : this.name, name: data.name.present ? data.name.value : this.name,
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
assetCount:
data.assetCount.present ? data.assetCount.value : this.assetCount,
thumbnailId: thumbnailId:
data.thumbnailId.present ? data.thumbnailId.value : this.thumbnailId, data.thumbnailId.present ? data.thumbnailId.value : this.thumbnailId,
backupSelection: data.backupSelection.present backupSelection: data.backupSelection.present
? data.backupSelection.value ? data.backupSelection.value
: this.backupSelection, : this.backupSelection,
isAll: data.isAll.present ? data.isAll.value : this.isAll,
); );
} }
@ -595,17 +515,15 @@ class LocalAlbumEntityData extends i0.DataClass
..write('id: $id, ') ..write('id: $id, ')
..write('name: $name, ') ..write('name: $name, ')
..write('updatedAt: $updatedAt, ') ..write('updatedAt: $updatedAt, ')
..write('assetCount: $assetCount, ')
..write('thumbnailId: $thumbnailId, ') ..write('thumbnailId: $thumbnailId, ')
..write('backupSelection: $backupSelection, ') ..write('backupSelection: $backupSelection')
..write('isAll: $isAll')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@override @override
int get hashCode => Object.hash( int get hashCode =>
id, name, updatedAt, assetCount, thumbnailId, backupSelection, isAll); Object.hash(id, name, updatedAt, thumbnailId, backupSelection);
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
@ -613,10 +531,8 @@ class LocalAlbumEntityData extends i0.DataClass
other.id == this.id && other.id == this.id &&
other.name == this.name && other.name == this.name &&
other.updatedAt == this.updatedAt && other.updatedAt == this.updatedAt &&
other.assetCount == this.assetCount &&
other.thumbnailId == this.thumbnailId && other.thumbnailId == this.thumbnailId &&
other.backupSelection == this.backupSelection && other.backupSelection == this.backupSelection);
other.isAll == this.isAll);
} }
class LocalAlbumEntityCompanion class LocalAlbumEntityCompanion
@ -624,27 +540,21 @@ class LocalAlbumEntityCompanion
final i0.Value<String> id; final i0.Value<String> id;
final i0.Value<String> name; final i0.Value<String> name;
final i0.Value<DateTime> updatedAt; final i0.Value<DateTime> updatedAt;
final i0.Value<int> assetCount;
final i0.Value<String?> thumbnailId; final i0.Value<String?> thumbnailId;
final i0.Value<i2.BackupSelection> backupSelection; final i0.Value<i2.BackupSelection> backupSelection;
final i0.Value<bool> isAll;
const LocalAlbumEntityCompanion({ const LocalAlbumEntityCompanion({
this.id = const i0.Value.absent(), this.id = const i0.Value.absent(),
this.name = const i0.Value.absent(), this.name = const i0.Value.absent(),
this.updatedAt = const i0.Value.absent(), this.updatedAt = const i0.Value.absent(),
this.assetCount = const i0.Value.absent(),
this.thumbnailId = const i0.Value.absent(), this.thumbnailId = const i0.Value.absent(),
this.backupSelection = const i0.Value.absent(), this.backupSelection = const i0.Value.absent(),
this.isAll = const i0.Value.absent(),
}); });
LocalAlbumEntityCompanion.insert({ LocalAlbumEntityCompanion.insert({
required String id, required String id,
required String name, required String name,
this.updatedAt = const i0.Value.absent(), this.updatedAt = const i0.Value.absent(),
this.assetCount = const i0.Value.absent(),
this.thumbnailId = const i0.Value.absent(), this.thumbnailId = const i0.Value.absent(),
required i2.BackupSelection backupSelection, required i2.BackupSelection backupSelection,
this.isAll = const i0.Value.absent(),
}) : id = i0.Value(id), }) : id = i0.Value(id),
name = i0.Value(name), name = i0.Value(name),
backupSelection = i0.Value(backupSelection); backupSelection = i0.Value(backupSelection);
@ -652,19 +562,15 @@ class LocalAlbumEntityCompanion
i0.Expression<String>? id, i0.Expression<String>? id,
i0.Expression<String>? name, i0.Expression<String>? name,
i0.Expression<DateTime>? updatedAt, i0.Expression<DateTime>? updatedAt,
i0.Expression<int>? assetCount,
i0.Expression<String>? thumbnailId, i0.Expression<String>? thumbnailId,
i0.Expression<int>? backupSelection, i0.Expression<int>? backupSelection,
i0.Expression<bool>? isAll,
}) { }) {
return i0.RawValuesInsertable({ return i0.RawValuesInsertable({
if (id != null) 'id': id, if (id != null) 'id': id,
if (name != null) 'name': name, if (name != null) 'name': name,
if (updatedAt != null) 'updated_at': updatedAt, if (updatedAt != null) 'updated_at': updatedAt,
if (assetCount != null) 'asset_count': assetCount,
if (thumbnailId != null) 'thumbnail_id': thumbnailId, if (thumbnailId != null) 'thumbnail_id': thumbnailId,
if (backupSelection != null) 'backup_selection': backupSelection, 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>? id,
i0.Value<String>? name, i0.Value<String>? name,
i0.Value<DateTime>? updatedAt, i0.Value<DateTime>? updatedAt,
i0.Value<int>? assetCount,
i0.Value<String?>? thumbnailId, i0.Value<String?>? thumbnailId,
i0.Value<i2.BackupSelection>? backupSelection, i0.Value<i2.BackupSelection>? backupSelection}) {
i0.Value<bool>? isAll}) {
return i1.LocalAlbumEntityCompanion( return i1.LocalAlbumEntityCompanion(
id: id ?? this.id, id: id ?? this.id,
name: name ?? this.name, name: name ?? this.name,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
assetCount: assetCount ?? this.assetCount,
thumbnailId: thumbnailId ?? this.thumbnailId, thumbnailId: thumbnailId ?? this.thumbnailId,
backupSelection: backupSelection ?? this.backupSelection, backupSelection: backupSelection ?? this.backupSelection,
isAll: isAll ?? this.isAll,
); );
} }
@ -699,9 +601,6 @@ class LocalAlbumEntityCompanion
if (updatedAt.present) { if (updatedAt.present) {
map['updated_at'] = i0.Variable<DateTime>(updatedAt.value); map['updated_at'] = i0.Variable<DateTime>(updatedAt.value);
} }
if (assetCount.present) {
map['asset_count'] = i0.Variable<int>(assetCount.value);
}
if (thumbnailId.present) { if (thumbnailId.present) {
map['thumbnail_id'] = i0.Variable<String>(thumbnailId.value); map['thumbnail_id'] = i0.Variable<String>(thumbnailId.value);
} }
@ -710,9 +609,6 @@ class LocalAlbumEntityCompanion
.$LocalAlbumEntityTable.$converterbackupSelection .$LocalAlbumEntityTable.$converterbackupSelection
.toSql(backupSelection.value)); .toSql(backupSelection.value));
} }
if (isAll.present) {
map['is_all'] = i0.Variable<bool>(isAll.value);
}
return map; return map;
} }
@ -722,10 +618,8 @@ class LocalAlbumEntityCompanion
..write('id: $id, ') ..write('id: $id, ')
..write('name: $name, ') ..write('name: $name, ')
..write('updatedAt: $updatedAt, ') ..write('updatedAt: $updatedAt, ')
..write('assetCount: $assetCount, ')
..write('thumbnailId: $thumbnailId, ') ..write('thumbnailId: $thumbnailId, ')
..write('backupSelection: $backupSelection, ') ..write('backupSelection: $backupSelection')
..write('isAll: $isAll')
..write(')')) ..write(')'))
.toString(); .toString();
} }

View File

@ -1,5 +1,5 @@
import 'package:drift/drift.dart'; 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/entities/local_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart'; import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart';
import 'package:immich_mobile/infrastructure/utils/drift_default.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()(); 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 @override
Set<Column> get primaryKey => {localId}; Set<Column> get primaryKey => {localId};
} }
@ -19,7 +22,7 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin {
extension LocalAssetEntityX on LocalAssetEntityData { extension LocalAssetEntityX on LocalAssetEntityData {
LocalAsset toDto() { LocalAsset toDto() {
return LocalAsset( return LocalAsset(
localId: localId, id: localId,
name: name, name: name,
checksum: checksum, checksum: checksum,
type: type, type: type,
@ -28,6 +31,7 @@ extension LocalAssetEntityX on LocalAssetEntityData {
width: width, width: width,
height: height, height: height,
durationInSeconds: durationInSeconds, durationInSeconds: durationInSeconds,
isFavorite: isFavorite,
); );
} }
} }

View File

@ -3,7 +3,7 @@
import 'package:drift/drift.dart' as i0; import 'package:drift/drift.dart' as i0;
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart' import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart'
as i1; 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' import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'
as i3; as i3;
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4; import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
@ -19,6 +19,7 @@ typedef $$LocalAssetEntityTableCreateCompanionBuilder
i0.Value<int?> durationInSeconds, i0.Value<int?> durationInSeconds,
required String localId, required String localId,
i0.Value<String?> checksum, i0.Value<String?> checksum,
i0.Value<bool> isFavorite,
}); });
typedef $$LocalAssetEntityTableUpdateCompanionBuilder typedef $$LocalAssetEntityTableUpdateCompanionBuilder
= i1.LocalAssetEntityCompanion Function({ = i1.LocalAssetEntityCompanion Function({
@ -31,6 +32,7 @@ typedef $$LocalAssetEntityTableUpdateCompanionBuilder
i0.Value<int?> durationInSeconds, i0.Value<int?> durationInSeconds,
i0.Value<String> localId, i0.Value<String> localId,
i0.Value<String?> checksum, i0.Value<String?> checksum,
i0.Value<bool> isFavorite,
}); });
class $$LocalAssetEntityTableFilterComposer class $$LocalAssetEntityTableFilterComposer
@ -71,6 +73,9 @@ class $$LocalAssetEntityTableFilterComposer
i0.ColumnFilters<String> get checksum => $composableBuilder( i0.ColumnFilters<String> get checksum => $composableBuilder(
column: $table.checksum, builder: (column) => i0.ColumnFilters(column)); column: $table.checksum, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<bool> get isFavorite => $composableBuilder(
column: $table.isFavorite, builder: (column) => i0.ColumnFilters(column));
} }
class $$LocalAssetEntityTableOrderingComposer class $$LocalAssetEntityTableOrderingComposer
@ -111,6 +116,10 @@ class $$LocalAssetEntityTableOrderingComposer
i0.ColumnOrderings<String> get checksum => $composableBuilder( i0.ColumnOrderings<String> get checksum => $composableBuilder(
column: $table.checksum, builder: (column) => i0.ColumnOrderings(column)); column: $table.checksum, builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<bool> get isFavorite => $composableBuilder(
column: $table.isFavorite,
builder: (column) => i0.ColumnOrderings(column));
} }
class $$LocalAssetEntityTableAnnotationComposer class $$LocalAssetEntityTableAnnotationComposer
@ -148,6 +157,9 @@ class $$LocalAssetEntityTableAnnotationComposer
i0.GeneratedColumn<String> get checksum => i0.GeneratedColumn<String> get checksum =>
$composableBuilder(column: $table.checksum, builder: (column) => column); $composableBuilder(column: $table.checksum, builder: (column) => column);
i0.GeneratedColumn<bool> get isFavorite => $composableBuilder(
column: $table.isFavorite, builder: (column) => column);
} }
class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< class $$LocalAssetEntityTableTableManager extends i0.RootTableManager<
@ -188,6 +200,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager<
i0.Value<int?> durationInSeconds = const i0.Value.absent(), i0.Value<int?> durationInSeconds = const i0.Value.absent(),
i0.Value<String> localId = const i0.Value.absent(), i0.Value<String> localId = const i0.Value.absent(),
i0.Value<String?> checksum = const i0.Value.absent(), i0.Value<String?> checksum = const i0.Value.absent(),
i0.Value<bool> isFavorite = const i0.Value.absent(),
}) => }) =>
i1.LocalAssetEntityCompanion( i1.LocalAssetEntityCompanion(
name: name, name: name,
@ -199,6 +212,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager<
durationInSeconds: durationInSeconds, durationInSeconds: durationInSeconds,
localId: localId, localId: localId,
checksum: checksum, checksum: checksum,
isFavorite: isFavorite,
), ),
createCompanionCallback: ({ createCompanionCallback: ({
required String name, required String name,
@ -210,6 +224,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager<
i0.Value<int?> durationInSeconds = const i0.Value.absent(), i0.Value<int?> durationInSeconds = const i0.Value.absent(),
required String localId, required String localId,
i0.Value<String?> checksum = const i0.Value.absent(), i0.Value<String?> checksum = const i0.Value.absent(),
i0.Value<bool> isFavorite = const i0.Value.absent(),
}) => }) =>
i1.LocalAssetEntityCompanion.insert( i1.LocalAssetEntityCompanion.insert(
name: name, name: name,
@ -221,6 +236,7 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager<
durationInSeconds: durationInSeconds, durationInSeconds: durationInSeconds,
localId: localId, localId: localId,
checksum: checksum, checksum: checksum,
isFavorite: isFavorite,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper: (p0) => p0
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e))) .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>( late final i0.GeneratedColumn<String> checksum = i0.GeneratedColumn<String>(
'checksum', aliasedName, true, 'checksum', aliasedName, true,
type: i0.DriftSqlType.string, requiredDuringInsert: false); 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 @override
List<i0.GeneratedColumn> get $columns => [ List<i0.GeneratedColumn> get $columns => [
name, name,
@ -322,7 +348,8 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
height, height,
durationInSeconds, durationInSeconds,
localId, localId,
checksum checksum,
isFavorite
]; ];
@override @override
String get aliasedName => _alias ?? actualTableName; String get aliasedName => _alias ?? actualTableName;
@ -373,6 +400,12 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
context.handle(_checksumMeta, context.handle(_checksumMeta,
checksum.isAcceptableOrUnknown(data['checksum']!, _checksumMeta)); checksum.isAcceptableOrUnknown(data['checksum']!, _checksumMeta));
} }
if (data.containsKey('is_favorite')) {
context.handle(
_isFavoriteMeta,
isFavorite.isAcceptableOrUnknown(
data['is_favorite']!, _isFavoriteMeta));
}
return context; return context;
} }
@ -402,6 +435,8 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
.read(i0.DriftSqlType.string, data['${effectivePrefix}local_id'])!, .read(i0.DriftSqlType.string, data['${effectivePrefix}local_id'])!,
checksum: attachedDatabase.typeMapping checksum: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}checksum']), .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 int? durationInSeconds;
final String localId; final String localId;
final String? checksum; final String? checksum;
final bool isFavorite;
const LocalAssetEntityData( const LocalAssetEntityData(
{required this.name, {required this.name,
required this.type, required this.type,
@ -438,7 +474,8 @@ class LocalAssetEntityData extends i0.DataClass
this.height, this.height,
this.durationInSeconds, this.durationInSeconds,
required this.localId, required this.localId,
this.checksum}); this.checksum,
required this.isFavorite});
@override @override
Map<String, i0.Expression> toColumns(bool nullToAbsent) { Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{}; final map = <String, i0.Expression>{};
@ -462,6 +499,7 @@ class LocalAssetEntityData extends i0.DataClass
if (!nullToAbsent || checksum != null) { if (!nullToAbsent || checksum != null) {
map['checksum'] = i0.Variable<String>(checksum); map['checksum'] = i0.Variable<String>(checksum);
} }
map['is_favorite'] = i0.Variable<bool>(isFavorite);
return map; return map;
} }
@ -479,6 +517,7 @@ class LocalAssetEntityData extends i0.DataClass
durationInSeconds: serializer.fromJson<int?>(json['durationInSeconds']), durationInSeconds: serializer.fromJson<int?>(json['durationInSeconds']),
localId: serializer.fromJson<String>(json['localId']), localId: serializer.fromJson<String>(json['localId']),
checksum: serializer.fromJson<String?>(json['checksum']), checksum: serializer.fromJson<String?>(json['checksum']),
isFavorite: serializer.fromJson<bool>(json['isFavorite']),
); );
} }
@override @override
@ -495,6 +534,7 @@ class LocalAssetEntityData extends i0.DataClass
'durationInSeconds': serializer.toJson<int?>(durationInSeconds), 'durationInSeconds': serializer.toJson<int?>(durationInSeconds),
'localId': serializer.toJson<String>(localId), 'localId': serializer.toJson<String>(localId),
'checksum': serializer.toJson<String?>(checksum), '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?> height = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(), i0.Value<int?> durationInSeconds = const i0.Value.absent(),
String? localId, String? localId,
i0.Value<String?> checksum = const i0.Value.absent()}) => i0.Value<String?> checksum = const i0.Value.absent(),
bool? isFavorite}) =>
i1.LocalAssetEntityData( i1.LocalAssetEntityData(
name: name ?? this.name, name: name ?? this.name,
type: type ?? this.type, type: type ?? this.type,
@ -520,6 +561,7 @@ class LocalAssetEntityData extends i0.DataClass
: this.durationInSeconds, : this.durationInSeconds,
localId: localId ?? this.localId, localId: localId ?? this.localId,
checksum: checksum.present ? checksum.value : this.checksum, checksum: checksum.present ? checksum.value : this.checksum,
isFavorite: isFavorite ?? this.isFavorite,
); );
LocalAssetEntityData copyWithCompanion(i1.LocalAssetEntityCompanion data) { LocalAssetEntityData copyWithCompanion(i1.LocalAssetEntityCompanion data) {
return LocalAssetEntityData( return LocalAssetEntityData(
@ -534,6 +576,8 @@ class LocalAssetEntityData extends i0.DataClass
: this.durationInSeconds, : this.durationInSeconds,
localId: data.localId.present ? data.localId.value : this.localId, localId: data.localId.present ? data.localId.value : this.localId,
checksum: data.checksum.present ? data.checksum.value : this.checksum, 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('height: $height, ')
..write('durationInSeconds: $durationInSeconds, ') ..write('durationInSeconds: $durationInSeconds, ')
..write('localId: $localId, ') ..write('localId: $localId, ')
..write('checksum: $checksum') ..write('checksum: $checksum, ')
..write('isFavorite: $isFavorite')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@override @override
int get hashCode => Object.hash(name, type, createdAt, updatedAt, width, int get hashCode => Object.hash(name, type, createdAt, updatedAt, width,
height, durationInSeconds, localId, checksum); height, durationInSeconds, localId, checksum, isFavorite);
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
@ -568,7 +613,8 @@ class LocalAssetEntityData extends i0.DataClass
other.height == this.height && other.height == this.height &&
other.durationInSeconds == this.durationInSeconds && other.durationInSeconds == this.durationInSeconds &&
other.localId == this.localId && other.localId == this.localId &&
other.checksum == this.checksum); other.checksum == this.checksum &&
other.isFavorite == this.isFavorite);
} }
class LocalAssetEntityCompanion class LocalAssetEntityCompanion
@ -582,6 +628,7 @@ class LocalAssetEntityCompanion
final i0.Value<int?> durationInSeconds; final i0.Value<int?> durationInSeconds;
final i0.Value<String> localId; final i0.Value<String> localId;
final i0.Value<String?> checksum; final i0.Value<String?> checksum;
final i0.Value<bool> isFavorite;
const LocalAssetEntityCompanion({ const LocalAssetEntityCompanion({
this.name = const i0.Value.absent(), this.name = const i0.Value.absent(),
this.type = const i0.Value.absent(), this.type = const i0.Value.absent(),
@ -592,6 +639,7 @@ class LocalAssetEntityCompanion
this.durationInSeconds = const i0.Value.absent(), this.durationInSeconds = const i0.Value.absent(),
this.localId = const i0.Value.absent(), this.localId = const i0.Value.absent(),
this.checksum = const i0.Value.absent(), this.checksum = const i0.Value.absent(),
this.isFavorite = const i0.Value.absent(),
}); });
LocalAssetEntityCompanion.insert({ LocalAssetEntityCompanion.insert({
required String name, required String name,
@ -603,6 +651,7 @@ class LocalAssetEntityCompanion
this.durationInSeconds = const i0.Value.absent(), this.durationInSeconds = const i0.Value.absent(),
required String localId, required String localId,
this.checksum = const i0.Value.absent(), this.checksum = const i0.Value.absent(),
this.isFavorite = const i0.Value.absent(),
}) : name = i0.Value(name), }) : name = i0.Value(name),
type = i0.Value(type), type = i0.Value(type),
localId = i0.Value(localId); localId = i0.Value(localId);
@ -616,6 +665,7 @@ class LocalAssetEntityCompanion
i0.Expression<int>? durationInSeconds, i0.Expression<int>? durationInSeconds,
i0.Expression<String>? localId, i0.Expression<String>? localId,
i0.Expression<String>? checksum, i0.Expression<String>? checksum,
i0.Expression<bool>? isFavorite,
}) { }) {
return i0.RawValuesInsertable({ return i0.RawValuesInsertable({
if (name != null) 'name': name, if (name != null) 'name': name,
@ -627,6 +677,7 @@ class LocalAssetEntityCompanion
if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds,
if (localId != null) 'local_id': localId, if (localId != null) 'local_id': localId,
if (checksum != null) 'checksum': checksum, if (checksum != null) 'checksum': checksum,
if (isFavorite != null) 'is_favorite': isFavorite,
}); });
} }
@ -639,7 +690,8 @@ class LocalAssetEntityCompanion
i0.Value<int?>? height, i0.Value<int?>? height,
i0.Value<int?>? durationInSeconds, i0.Value<int?>? durationInSeconds,
i0.Value<String>? localId, i0.Value<String>? localId,
i0.Value<String?>? checksum}) { i0.Value<String?>? checksum,
i0.Value<bool>? isFavorite}) {
return i1.LocalAssetEntityCompanion( return i1.LocalAssetEntityCompanion(
name: name ?? this.name, name: name ?? this.name,
type: type ?? this.type, type: type ?? this.type,
@ -650,6 +702,7 @@ class LocalAssetEntityCompanion
durationInSeconds: durationInSeconds ?? this.durationInSeconds, durationInSeconds: durationInSeconds ?? this.durationInSeconds,
localId: localId ?? this.localId, localId: localId ?? this.localId,
checksum: checksum ?? this.checksum, checksum: checksum ?? this.checksum,
isFavorite: isFavorite ?? this.isFavorite,
); );
} }
@ -684,6 +737,9 @@ class LocalAssetEntityCompanion
if (checksum.present) { if (checksum.present) {
map['checksum'] = i0.Variable<String>(checksum.value); map['checksum'] = i0.Variable<String>(checksum.value);
} }
if (isFavorite.present) {
map['is_favorite'] = i0.Variable<bool>(isFavorite.value);
}
return map; return map;
} }
@ -698,7 +754,8 @@ class LocalAssetEntityCompanion
..write('height: $height, ') ..write('height: $height, ')
..write('durationInSeconds: $durationInSeconds, ') ..write('durationInSeconds: $durationInSeconds, ')
..write('localId: $localId, ') ..write('localId: $localId, ')
..write('checksum: $checksum') ..write('checksum: $checksum, ')
..write('isFavorite: $isFavorite')
..write(')')) ..write(')'))
.toString(); .toString();
} }

View File

@ -1,11 +1,15 @@
import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/constants/constants.dart';
import 'package:immich_mobile/domain/interfaces/album_media.interface.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:immich_mobile/domain/models/local_album.model.dart';
import 'package:photo_manager/photo_manager.dart'; import 'package:photo_manager/photo_manager.dart';
import 'package:platform/platform.dart';
class AlbumMediaRepository implements IAlbumMediaRepository { class AlbumMediaRepository implements IAlbumMediaRepository {
const AlbumMediaRepository(); final Platform _platform;
const AlbumMediaRepository({Platform platform = const LocalPlatform()})
: _platform = platform;
PMFilter _getAlbumFilter({ PMFilter _getAlbumFilter({
withAssetTitle = false, withAssetTitle = false,
@ -42,7 +46,12 @@ class AlbumMediaRepository implements IAlbumMediaRepository {
); );
return PhotoManager.getAssetPathList(hasAll: true, filterOption: filter) 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 @override
@ -85,7 +94,7 @@ class AlbumMediaRepository implements IAlbumMediaRepository {
extension on AssetEntity { extension on AssetEntity {
Future<asset.LocalAsset> toDto() async => asset.LocalAsset( Future<asset.LocalAsset> toDto() async => asset.LocalAsset(
localId: id, id: id,
name: title ?? await titleAsync, name: title ?? await titleAsync,
type: switch (type) { type: switch (type) {
AssetType.other => asset.AssetType.other, AssetType.other => asset.AssetType.other,
@ -114,7 +123,6 @@ extension on AssetPathEntity {
// the assetCountAsync call is expensive for larger albums with several thousand assets // the assetCountAsync call is expensive for larger albums with several thousand assets
assetCount: withAssetCount ? await assetCountAsync : 0, assetCount: withAssetCount ? await assetCountAsync : 0,
backupSelection: BackupSelection.none, backupSelection: BackupSelection.none,
isAll: isAll,
); );
} }

View File

@ -1,6 +1,6 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/interfaces/local_album.interface.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/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.dart';
import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.drift.dart';
@ -137,10 +137,8 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
id: localAlbum.id, id: localAlbum.id,
name: localAlbum.name, name: localAlbum.name,
updatedAt: Value(localAlbum.updatedAt), updatedAt: Value(localAlbum.updatedAt),
assetCount: Value(localAlbum.assetCount),
thumbnailId: Value.absentIfNull(localAlbum.thumbnailId), thumbnailId: Value.absentIfNull(localAlbum.thumbnailId),
backupSelection: localAlbum.backupSelection, backupSelection: localAlbum.backupSelection,
isAll: Value(localAlbum.isAll),
); );
return _db.localAlbumEntity return _db.localAlbumEntity
@ -160,7 +158,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
_db.localAlbumAssetEntity, _db.localAlbumAssetEntity,
assets.map( assets.map(
(a) => LocalAlbumAssetEntityCompanion.insert( (a) => LocalAlbumAssetEntityCompanion.insert(
assetId: a.localId, assetId: a.id,
albumId: albumId, albumId: albumId,
), ),
), ),
@ -223,7 +221,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository
width: Value.absentIfNull(a.width), width: Value.absentIfNull(a.width),
height: Value.absentIfNull(a.height), height: Value.absentIfNull(a.height),
durationInSeconds: Value.absentIfNull(a.durationInSeconds), durationInSeconds: Value.absentIfNull(a.durationInSeconds),
localId: a.localId, localId: a.id,
checksum: Value.absentIfNull(a.checksum), checksum: Value.absentIfNull(a.checksum),
), ),
), ),

View File

@ -1,5 +1,5 @@
import 'package:immich_mobile/domain/interfaces/local_asset.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/infrastructure/entities/local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';

View File

@ -1,5 +1,5 @@
import 'package:drift/drift.dart'; 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 { mixin AssetEntityMixin on Table {
TextColumn get name => text()(); TextColumn get name => text()();

View File

@ -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/album_media.interface.dart';
import 'package:immich_mobile/domain/interfaces/local_album.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/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/models/local_album.model.dart';
import 'package:immich_mobile/domain/services/device_sync.service.dart'; import 'package:immich_mobile/domain/services/device_sync.service.dart';
import 'package:immich_mobile/utils/nullable_value.dart'; import 'package:immich_mobile/utils/nullable_value.dart';
@ -257,9 +257,9 @@ void main() {
newAlbum.copyWith(updatedAt: DateTime(2024), assetCount: 2); newAlbum.copyWith(updatedAt: DateTime(2024), assetCount: 2);
final assets = [ final assets = [
LocalAssetStub.image1 LocalAssetStub.image1
.copyWith(localId: "asset1", createdAt: DateTime(2024, 1, 1)), .copyWith(id: "asset1", createdAt: DateTime(2024, 1, 1)),
LocalAssetStub.image2.copyWith( LocalAssetStub.image2.copyWith(
localId: "asset2", id: "asset2",
createdAt: DateTime(2024, 1, 2), createdAt: DateTime(2024, 1, 2),
), ),
]; ];
@ -284,7 +284,7 @@ void main() {
expect(capturedAlbum.id, newAlbum.id); expect(capturedAlbum.id, newAlbum.id);
expect(capturedAlbum.assetCount, refreshedAlbum.assetCount); expect(capturedAlbum.assetCount, refreshedAlbum.assetCount);
expect(capturedAlbum.updatedAt, refreshedAlbum.updatedAt); expect(capturedAlbum.updatedAt, refreshedAlbum.updatedAt);
expect(capturedAlbum.thumbnailId, assets.first.localId); expect(capturedAlbum.thumbnailId, assets.first.id);
expect(listEquals(capturedAssets, assets), isTrue); expect(listEquals(capturedAssets, assets), isTrue);
}, },
); );
@ -354,7 +354,7 @@ void main() {
when(() => mockAlbumMediaRepo.refresh(dbAlbum.id)) when(() => mockAlbumMediaRepo.refresh(dbAlbum.id))
.thenAnswer((_) async => refreshedAlbum); .thenAnswer((_) async => refreshedAlbum);
final newAsset = LocalAssetStub.image2.copyWith(localId: "new_asset"); final newAsset = LocalAssetStub.image2.copyWith(id: "new_asset");
when( when(
() => mockAlbumMediaRepo.getAssetsForAlbum( () => mockAlbumMediaRepo.getAssetsForAlbum(
dbAlbum.id, dbAlbum.id,
@ -387,7 +387,7 @@ void main() {
(a) => (a) =>
a.id == dbAlbum.id && a.id == dbAlbum.id &&
a.assetCount == 2 && a.assetCount == 2 &&
a.thumbnailId == newAsset.localId, a.thumbnailId == newAsset.id,
), ),
), ),
), ),
@ -446,7 +446,7 @@ void main() {
).called(1); ).called(1);
verify( verify(
() => mockLocalAlbumRepo () => mockLocalAlbumRepo
.removeAssets(dbAlbum.id, [LocalAssetStub.image1.localId]), .removeAssets(dbAlbum.id, [LocalAssetStub.image1.id]),
).called(1); ).called(1);
}, },
); );
@ -519,7 +519,7 @@ void main() {
test('returns true and updates assets/metadata on success', () async { test('returns true and updates assets/metadata on success', () async {
final newAsset = LocalAssetStub.image2.copyWith( final newAsset = LocalAssetStub.image2.copyWith(
localId: "asset2", id: "asset2",
createdAt: DateTime(2024, 1, 1, 10, 30, 0), createdAt: DateTime(2024, 1, 1, 10, 30, 0),
); );
when( when(
@ -531,7 +531,7 @@ void main() {
when(() => mockLocalAssetRepo.get("thumb1")).thenAnswer( when(() => mockLocalAssetRepo.get("thumb1")).thenAnswer(
(_) async => LocalAssetStub.image1.copyWith( (_) async => LocalAssetStub.image1.copyWith(
localId: "thumb1", id: "thumb1",
createdAt: DateTime(2024, 1, 1, 9, 0, 0), createdAt: DateTime(2024, 1, 1, 9, 0, 0),
), ),
); );
@ -556,7 +556,7 @@ void main() {
a.id == dbAlbum.id && a.id == dbAlbum.id &&
a.assetCount == 2 && a.assetCount == 2 &&
a.updatedAt == refreshedAlbum.updatedAt && 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 { test('returns true and keeps old thumbnail if newer', () async {
final newAsset = LocalAssetStub.image2.copyWith( final newAsset = LocalAssetStub.image2.copyWith(
localId: "asset2", id: "asset2",
createdAt: DateTime(2024, 1, 1, 8, 0, 0), createdAt: DateTime(2024, 1, 1, 8, 0, 0),
); );
when( when(
@ -579,7 +579,7 @@ void main() {
when(() => mockLocalAssetRepo.get("thumb1")).thenAnswer( when(() => mockLocalAssetRepo.get("thumb1")).thenAnswer(
(_) async => LocalAssetStub.image1.copyWith( (_) async => LocalAssetStub.image1.copyWith(
localId: "thumb1", id: "thumb1",
createdAt: DateTime(2024, 1, 1, 9, 0, 0), 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 { test('returns true and sets new thumbnail if db thumb is null', () async {
final dbAlbumNoThumb = dbAlbum.copyWith(thumbnailId: null); final dbAlbumNoThumb = dbAlbum.copyWith(thumbnailId: null);
final newAsset = LocalAssetStub.image2.copyWith( final newAsset = LocalAssetStub.image2.copyWith(
localId: "asset2", id: "asset2",
createdAt: DateTime(2024, 1, 1, 10, 30, 0), createdAt: DateTime(2024, 1, 1, 10, 30, 0),
); );
when( when(
@ -644,7 +644,7 @@ void main() {
a.id == dbAlbum.id && a.id == dbAlbum.id &&
a.assetCount == 2 && a.assetCount == 2 &&
a.updatedAt == refreshedAlbum.updatedAt && a.updatedAt == refreshedAlbum.updatedAt &&
a.thumbnailId == newAsset.localId, a.thumbnailId == newAsset.id,
), ),
), ),
), ),
@ -731,22 +731,22 @@ void main() {
); );
final dbAsset1 = LocalAssetStub.image1.copyWith( final dbAsset1 = LocalAssetStub.image1.copyWith(
localId: "asset1", id: "asset1",
createdAt: DateTime(2024), createdAt: DateTime(2024),
updatedAt: DateTime(2024), updatedAt: DateTime(2024),
); );
final dbAsset2 = LocalAssetStub.image2.copyWith( final dbAsset2 = LocalAssetStub.image2.copyWith(
localId: "asset2", id: "asset2",
createdAt: DateTime(2024), createdAt: DateTime(2024),
updatedAt: DateTime(2024), updatedAt: DateTime(2024),
); // To be deleted ); // To be deleted
final deviceAsset1 = LocalAssetStub.image1.copyWith( final deviceAsset1 = LocalAssetStub.image1.copyWith(
localId: "asset1", id: "asset1",
createdAt: DateTime(2024), createdAt: DateTime(2024),
updatedAt: DateTime(2025), updatedAt: DateTime(2025),
); // Updated ); // Updated
final deviceAsset3 = LocalAssetStub.video1.copyWith( final deviceAsset3 = LocalAssetStub.video1.copyWith(
localId: "asset3", id: "asset3",
createdAt: DateTime(2024), createdAt: DateTime(2024),
updatedAt: DateTime(2024), updatedAt: DateTime(2024),
); // Added ); // Added
@ -819,7 +819,7 @@ void main() {
a.id == emptyDbAlbum.id && a.id == emptyDbAlbum.id &&
a.assetCount == deviceAssets.length && a.assetCount == deviceAssets.length &&
a.updatedAt == refreshedWithAssets.updatedAt && a.updatedAt == refreshedWithAssets.updatedAt &&
a.thumbnailId == deviceAssets.first.localId, a.thumbnailId == deviceAssets.first.id,
), ),
), ),
), ),
@ -833,7 +833,7 @@ void main() {
final deviceAssets = [deviceAsset1, deviceAsset3]; final deviceAssets = [deviceAsset1, deviceAsset3];
deviceAssets.sort((a, b) => a.createdAt.compareTo(b.createdAt)); deviceAssets.sort((a, b) => a.createdAt.compareTo(b.createdAt));
final dbAssets = [dbAsset1, dbAsset2]; 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( when(() => mockAlbumMediaRepo.getAssetsForAlbum(dbAlbum.id)).thenAnswer(
(_) async => deviceAssets, (_) async => deviceAssets,
@ -857,10 +857,10 @@ void main() {
return list.length == 2 && return list.length == 2 &&
list.any( list.any(
(a) => (a) =>
a.localId == "asset1" && a.id == "asset1" &&
a.updatedAt == deviceAsset1.updatedAt, 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.id == dbAlbum.id &&
a.assetCount == 2 && a.assetCount == 2 &&
a.updatedAt == currentRefreshedAlbum.updatedAt && 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 dbAssets = [dbAsset1, dbAsset2];
final deviceAssets = [dbAsset1, dbAsset2]; final deviceAssets = [dbAsset1, dbAsset2];
deviceAssets.sort((a, b) => a.createdAt.compareTo(b.createdAt)); 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)) when(() => mockAlbumMediaRepo.getAssetsForAlbum(dbAlbum.id))
.thenAnswer((_) async => deviceAssets); .thenAnswer((_) async => deviceAssets);
@ -915,7 +915,7 @@ void main() {
a.id == dbAlbum.id && a.id == dbAlbum.id &&
a.assetCount == 2 && a.assetCount == 2 &&
a.updatedAt == currentRefreshedAlbum.updatedAt && a.updatedAt == currentRefreshedAlbum.updatedAt &&
a.thumbnailId == deviceAssets.first.localId, a.thumbnailId == deviceAssets.first.id,
), ),
), ),
), ),

View File

@ -10,7 +10,6 @@ abstract final class LocalAlbumStub {
assetCount: 1, assetCount: 1,
thumbnailId: null, thumbnailId: null,
backupSelection: BackupSelection.none, backupSelection: BackupSelection.none,
isAll: false,
); );
static LocalAlbum get album2 => LocalAlbum( static LocalAlbum get album2 => LocalAlbum(
@ -20,7 +19,6 @@ abstract final class LocalAlbumStub {
assetCount: 2, assetCount: 2,
thumbnailId: null, thumbnailId: null,
backupSelection: BackupSelection.selected, backupSelection: BackupSelection.selected,
isAll: true,
); );
static LocalAlbum get album3 => LocalAlbum( static LocalAlbum get album3 => LocalAlbum(
@ -30,6 +28,5 @@ abstract final class LocalAlbumStub {
assetCount: 20, assetCount: 20,
thumbnailId: "123", thumbnailId: "123",
backupSelection: BackupSelection.excluded, backupSelection: BackupSelection.excluded,
isAll: false,
); );
} }

View File

@ -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 { abstract final class LocalAssetStub {
const LocalAssetStub(); const LocalAssetStub();
static LocalAsset get image1 => LocalAsset( static LocalAsset get image1 => LocalAsset(
localId: "image1", id: "image1",
name: "image1.jpg", name: "image1.jpg",
checksum: "image1-checksum", checksum: "image1-checksum",
type: AssetType.image, type: AssetType.image,
@ -16,7 +16,7 @@ abstract final class LocalAssetStub {
); );
static LocalAsset get image2 => LocalAsset( static LocalAsset get image2 => LocalAsset(
localId: "image2", id: "image2",
name: "image2.jpg", name: "image2.jpg",
checksum: "image2-checksum", checksum: "image2-checksum",
type: AssetType.image, type: AssetType.image,
@ -28,7 +28,7 @@ abstract final class LocalAssetStub {
); );
static LocalAsset get video1 => LocalAsset( static LocalAsset get video1 => LocalAsset(
localId: "video1", id: "video1",
name: "video1.mov", name: "video1.mov",
checksum: "video1-checksum", checksum: "video1-checksum",
type: AssetType.video, type: AssetType.video,