mirror of
https://github.com/immich-app/immich.git
synced 2025-07-31 15:08:44 -04:00
feat(mobile): asset face sync (#20022)
* feat(mobile): asset face sync * fix: lint --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
parent
ab61bcfcc8
commit
ac44f6d1e0
1
mobile/drift_schemas/main/drift_schema_v4.json
generated
Normal file
1
mobile/drift_schemas/main/drift_schema_v4.json
generated
Normal file
File diff suppressed because one or more lines are too long
98
mobile/lib/domain/models/asset_face.model.dart
Normal file
98
mobile/lib/domain/models/asset_face.model.dart
Normal file
@ -0,0 +1,98 @@
|
||||
// Model for an asset face stored in the server
|
||||
class AssetFace {
|
||||
final String id;
|
||||
final String assetId;
|
||||
final String? personId;
|
||||
final int imageWidth;
|
||||
final int imageHeight;
|
||||
final int boundingBoxX1;
|
||||
final int boundingBoxY1;
|
||||
final int boundingBoxX2;
|
||||
final int boundingBoxY2;
|
||||
final String sourceType;
|
||||
|
||||
const AssetFace({
|
||||
required this.id,
|
||||
required this.assetId,
|
||||
this.personId,
|
||||
required this.imageWidth,
|
||||
required this.imageHeight,
|
||||
required this.boundingBoxX1,
|
||||
required this.boundingBoxY1,
|
||||
required this.boundingBoxX2,
|
||||
required this.boundingBoxY2,
|
||||
required this.sourceType,
|
||||
});
|
||||
|
||||
AssetFace copyWith({
|
||||
String? id,
|
||||
String? assetId,
|
||||
String? personId,
|
||||
int? imageWidth,
|
||||
int? imageHeight,
|
||||
int? boundingBoxX1,
|
||||
int? boundingBoxY1,
|
||||
int? boundingBoxX2,
|
||||
int? boundingBoxY2,
|
||||
String? sourceType,
|
||||
}) {
|
||||
return AssetFace(
|
||||
id: id ?? this.id,
|
||||
assetId: assetId ?? this.assetId,
|
||||
personId: personId ?? this.personId,
|
||||
imageWidth: imageWidth ?? this.imageWidth,
|
||||
imageHeight: imageHeight ?? this.imageHeight,
|
||||
boundingBoxX1: boundingBoxX1 ?? this.boundingBoxX1,
|
||||
boundingBoxY1: boundingBoxY1 ?? this.boundingBoxY1,
|
||||
boundingBoxX2: boundingBoxX2 ?? this.boundingBoxX2,
|
||||
boundingBoxY2: boundingBoxY2 ?? this.boundingBoxY2,
|
||||
sourceType: sourceType ?? this.sourceType,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''AssetFace {
|
||||
id: $id,
|
||||
assetId: $assetId,
|
||||
personId: ${personId ?? "<NA>"},
|
||||
imageWidth: $imageWidth,
|
||||
imageHeight: $imageHeight,
|
||||
boundingBoxX1: $boundingBoxX1,
|
||||
boundingBoxY1: $boundingBoxY1,
|
||||
boundingBoxX2: $boundingBoxX2,
|
||||
boundingBoxY2: $boundingBoxY2,
|
||||
sourceType: $sourceType,
|
||||
}''';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(covariant AssetFace other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other.id == id &&
|
||||
other.assetId == assetId &&
|
||||
other.personId == personId &&
|
||||
other.imageWidth == imageWidth &&
|
||||
other.imageHeight == imageHeight &&
|
||||
other.boundingBoxX1 == boundingBoxX1 &&
|
||||
other.boundingBoxY1 == boundingBoxY1 &&
|
||||
other.boundingBoxX2 == boundingBoxX2 &&
|
||||
other.boundingBoxY2 == boundingBoxY2 &&
|
||||
other.sourceType == sourceType;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return id.hashCode ^
|
||||
assetId.hashCode ^
|
||||
personId.hashCode ^
|
||||
imageWidth.hashCode ^
|
||||
imageHeight.hashCode ^
|
||||
boundingBoxX1.hashCode ^
|
||||
boundingBoxY1.hashCode ^
|
||||
boundingBoxX2.hashCode ^
|
||||
boundingBoxY2.hashCode ^
|
||||
sourceType.hashCode;
|
||||
}
|
||||
}
|
@ -103,7 +103,6 @@ class Person {
|
||||
final String ownerId;
|
||||
final String name;
|
||||
final String? faceAssetId;
|
||||
final String thumbnailPath;
|
||||
final bool isFavorite;
|
||||
final bool isHidden;
|
||||
final String? color;
|
||||
@ -116,7 +115,6 @@ class Person {
|
||||
required this.ownerId,
|
||||
required this.name,
|
||||
this.faceAssetId,
|
||||
required this.thumbnailPath,
|
||||
required this.isFavorite,
|
||||
required this.isHidden,
|
||||
required this.color,
|
||||
@ -130,7 +128,6 @@ class Person {
|
||||
String? ownerId,
|
||||
String? name,
|
||||
String? faceAssetId,
|
||||
String? thumbnailPath,
|
||||
bool? isFavorite,
|
||||
bool? isHidden,
|
||||
String? color,
|
||||
@ -143,7 +140,6 @@ class Person {
|
||||
ownerId: ownerId ?? this.ownerId,
|
||||
name: name ?? this.name,
|
||||
faceAssetId: faceAssetId ?? this.faceAssetId,
|
||||
thumbnailPath: thumbnailPath ?? this.thumbnailPath,
|
||||
isFavorite: isFavorite ?? this.isFavorite,
|
||||
isHidden: isHidden ?? this.isHidden,
|
||||
color: color ?? this.color,
|
||||
@ -160,7 +156,6 @@ class Person {
|
||||
ownerId: $ownerId,
|
||||
name: $name,
|
||||
faceAssetId: ${faceAssetId ?? "<NA>"},
|
||||
thumbnailPath: $thumbnailPath,
|
||||
isFavorite: $isFavorite,
|
||||
isHidden: $isHidden,
|
||||
color: ${color ?? "<NA>"},
|
||||
@ -178,7 +173,6 @@ class Person {
|
||||
other.ownerId == ownerId &&
|
||||
other.name == name &&
|
||||
other.faceAssetId == faceAssetId &&
|
||||
other.thumbnailPath == thumbnailPath &&
|
||||
other.isFavorite == isFavorite &&
|
||||
other.isHidden == isHidden &&
|
||||
other.color == color &&
|
||||
@ -193,7 +187,6 @@ class Person {
|
||||
ownerId.hashCode ^
|
||||
name.hashCode ^
|
||||
faceAssetId.hashCode ^
|
||||
thumbnailPath.hashCode ^
|
||||
isFavorite.hashCode ^
|
||||
isHidden.hashCode ^
|
||||
color.hashCode ^
|
||||
|
@ -244,6 +244,10 @@ class SyncStreamService {
|
||||
return _syncStreamRepository.updatePeopleV1(data.cast());
|
||||
case SyncEntityType.personDeleteV1:
|
||||
return _syncStreamRepository.deletePeopleV1(data.cast());
|
||||
case SyncEntityType.assetFaceV1:
|
||||
return _syncStreamRepository.updateAssetFacesV1(data.cast());
|
||||
case SyncEntityType.assetFaceDeleteV1:
|
||||
return _syncStreamRepository.deleteAssetFacesV1(data.cast());
|
||||
default:
|
||||
_logger.warning("Unknown sync data type: $type");
|
||||
}
|
||||
|
34
mobile/lib/infrastructure/entities/asset_face.entity.dart
Normal file
34
mobile/lib/infrastructure/entities/asset_face.entity.dart
Normal file
@ -0,0 +1,34 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/person.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||
|
||||
class AssetFaceEntity extends Table with DriftDefaultsMixin {
|
||||
const AssetFaceEntity();
|
||||
|
||||
TextColumn get id => text()();
|
||||
|
||||
TextColumn get assetId =>
|
||||
text().references(RemoteAssetEntity, #id, onDelete: KeyAction.cascade)();
|
||||
|
||||
TextColumn get personId => text()
|
||||
.nullable()
|
||||
.references(PersonEntity, #id, onDelete: KeyAction.setNull)();
|
||||
|
||||
IntColumn get imageWidth => integer()();
|
||||
|
||||
IntColumn get imageHeight => integer()();
|
||||
|
||||
IntColumn get boundingBoxX1 => integer()();
|
||||
|
||||
IntColumn get boundingBoxY1 => integer()();
|
||||
|
||||
IntColumn get boundingBoxX2 => integer()();
|
||||
|
||||
IntColumn get boundingBoxY2 => integer()();
|
||||
|
||||
TextColumn get sourceType => text()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
}
|
1013
mobile/lib/infrastructure/entities/asset_face.entity.drift.dart
generated
Normal file
1013
mobile/lib/infrastructure/entities/asset_face.entity.drift.dart
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,11 +16,8 @@ class PersonEntity extends Table with DriftDefaultsMixin {
|
||||
|
||||
TextColumn get name => text()();
|
||||
|
||||
// TODO: foreign key refering to asset faces
|
||||
TextColumn get faceAssetId => text().nullable()();
|
||||
|
||||
TextColumn get thumbnailPath => text()();
|
||||
|
||||
BoolColumn get isFavorite => boolean()();
|
||||
|
||||
BoolColumn get isHidden => boolean()();
|
||||
|
@ -17,7 +17,6 @@ typedef $$PersonEntityTableCreateCompanionBuilder = i1.PersonEntityCompanion
|
||||
required String ownerId,
|
||||
required String name,
|
||||
i0.Value<String?> faceAssetId,
|
||||
required String thumbnailPath,
|
||||
required bool isFavorite,
|
||||
required bool isHidden,
|
||||
i0.Value<String?> color,
|
||||
@ -31,7 +30,6 @@ typedef $$PersonEntityTableUpdateCompanionBuilder = i1.PersonEntityCompanion
|
||||
i0.Value<String> ownerId,
|
||||
i0.Value<String> name,
|
||||
i0.Value<String?> faceAssetId,
|
||||
i0.Value<String> thumbnailPath,
|
||||
i0.Value<bool> isFavorite,
|
||||
i0.Value<bool> isHidden,
|
||||
i0.Value<String?> color,
|
||||
@ -94,10 +92,6 @@ class $$PersonEntityTableFilterComposer
|
||||
column: $table.faceAssetId,
|
||||
builder: (column) => i0.ColumnFilters(column));
|
||||
|
||||
i0.ColumnFilters<String> get thumbnailPath => $composableBuilder(
|
||||
column: $table.thumbnailPath,
|
||||
builder: (column) => i0.ColumnFilters(column));
|
||||
|
||||
i0.ColumnFilters<bool> get isFavorite => $composableBuilder(
|
||||
column: $table.isFavorite, builder: (column) => i0.ColumnFilters(column));
|
||||
|
||||
@ -160,10 +154,6 @@ class $$PersonEntityTableOrderingComposer
|
||||
column: $table.faceAssetId,
|
||||
builder: (column) => i0.ColumnOrderings(column));
|
||||
|
||||
i0.ColumnOrderings<String> get thumbnailPath => $composableBuilder(
|
||||
column: $table.thumbnailPath,
|
||||
builder: (column) => i0.ColumnOrderings(column));
|
||||
|
||||
i0.ColumnOrderings<bool> get isFavorite => $composableBuilder(
|
||||
column: $table.isFavorite,
|
||||
builder: (column) => i0.ColumnOrderings(column));
|
||||
@ -225,9 +215,6 @@ class $$PersonEntityTableAnnotationComposer
|
||||
i0.GeneratedColumn<String> get faceAssetId => $composableBuilder(
|
||||
column: $table.faceAssetId, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumn<String> get thumbnailPath => $composableBuilder(
|
||||
column: $table.thumbnailPath, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumn<bool> get isFavorite => $composableBuilder(
|
||||
column: $table.isFavorite, builder: (column) => column);
|
||||
|
||||
@ -293,7 +280,6 @@ class $$PersonEntityTableTableManager extends i0.RootTableManager<
|
||||
i0.Value<String> ownerId = const i0.Value.absent(),
|
||||
i0.Value<String> name = const i0.Value.absent(),
|
||||
i0.Value<String?> faceAssetId = const i0.Value.absent(),
|
||||
i0.Value<String> thumbnailPath = const i0.Value.absent(),
|
||||
i0.Value<bool> isFavorite = const i0.Value.absent(),
|
||||
i0.Value<bool> isHidden = const i0.Value.absent(),
|
||||
i0.Value<String?> color = const i0.Value.absent(),
|
||||
@ -306,7 +292,6 @@ class $$PersonEntityTableTableManager extends i0.RootTableManager<
|
||||
ownerId: ownerId,
|
||||
name: name,
|
||||
faceAssetId: faceAssetId,
|
||||
thumbnailPath: thumbnailPath,
|
||||
isFavorite: isFavorite,
|
||||
isHidden: isHidden,
|
||||
color: color,
|
||||
@ -319,7 +304,6 @@ class $$PersonEntityTableTableManager extends i0.RootTableManager<
|
||||
required String ownerId,
|
||||
required String name,
|
||||
i0.Value<String?> faceAssetId = const i0.Value.absent(),
|
||||
required String thumbnailPath,
|
||||
required bool isFavorite,
|
||||
required bool isHidden,
|
||||
i0.Value<String?> color = const i0.Value.absent(),
|
||||
@ -332,7 +316,6 @@ class $$PersonEntityTableTableManager extends i0.RootTableManager<
|
||||
ownerId: ownerId,
|
||||
name: name,
|
||||
faceAssetId: faceAssetId,
|
||||
thumbnailPath: thumbnailPath,
|
||||
isFavorite: isFavorite,
|
||||
isHidden: isHidden,
|
||||
color: color,
|
||||
@ -443,12 +426,6 @@ class $PersonEntityTable extends i2.PersonEntity
|
||||
late final i0.GeneratedColumn<String> faceAssetId =
|
||||
i0.GeneratedColumn<String>('face_asset_id', aliasedName, true,
|
||||
type: i0.DriftSqlType.string, requiredDuringInsert: false);
|
||||
static const i0.VerificationMeta _thumbnailPathMeta =
|
||||
const i0.VerificationMeta('thumbnailPath');
|
||||
@override
|
||||
late final i0.GeneratedColumn<String> thumbnailPath =
|
||||
i0.GeneratedColumn<String>('thumbnail_path', aliasedName, false,
|
||||
type: i0.DriftSqlType.string, requiredDuringInsert: true);
|
||||
static const i0.VerificationMeta _isFavoriteMeta =
|
||||
const i0.VerificationMeta('isFavorite');
|
||||
@override
|
||||
@ -487,7 +464,6 @@ class $PersonEntityTable extends i2.PersonEntity
|
||||
ownerId,
|
||||
name,
|
||||
faceAssetId,
|
||||
thumbnailPath,
|
||||
isFavorite,
|
||||
isHidden,
|
||||
color,
|
||||
@ -535,14 +511,6 @@ class $PersonEntityTable extends i2.PersonEntity
|
||||
faceAssetId.isAcceptableOrUnknown(
|
||||
data['face_asset_id']!, _faceAssetIdMeta));
|
||||
}
|
||||
if (data.containsKey('thumbnail_path')) {
|
||||
context.handle(
|
||||
_thumbnailPathMeta,
|
||||
thumbnailPath.isAcceptableOrUnknown(
|
||||
data['thumbnail_path']!, _thumbnailPathMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_thumbnailPathMeta);
|
||||
}
|
||||
if (data.containsKey('is_favorite')) {
|
||||
context.handle(
|
||||
_isFavoriteMeta,
|
||||
@ -586,8 +554,6 @@ class $PersonEntityTable extends i2.PersonEntity
|
||||
.read(i0.DriftSqlType.string, data['${effectivePrefix}name'])!,
|
||||
faceAssetId: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string, data['${effectivePrefix}face_asset_id']),
|
||||
thumbnailPath: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string, data['${effectivePrefix}thumbnail_path'])!,
|
||||
isFavorite: attachedDatabase.typeMapping
|
||||
.read(i0.DriftSqlType.bool, data['${effectivePrefix}is_favorite'])!,
|
||||
isHidden: attachedDatabase.typeMapping
|
||||
@ -618,7 +584,6 @@ class PersonEntityData extends i0.DataClass
|
||||
final String ownerId;
|
||||
final String name;
|
||||
final String? faceAssetId;
|
||||
final String thumbnailPath;
|
||||
final bool isFavorite;
|
||||
final bool isHidden;
|
||||
final String? color;
|
||||
@ -630,7 +595,6 @@ class PersonEntityData extends i0.DataClass
|
||||
required this.ownerId,
|
||||
required this.name,
|
||||
this.faceAssetId,
|
||||
required this.thumbnailPath,
|
||||
required this.isFavorite,
|
||||
required this.isHidden,
|
||||
this.color,
|
||||
@ -646,7 +610,6 @@ class PersonEntityData extends i0.DataClass
|
||||
if (!nullToAbsent || faceAssetId != null) {
|
||||
map['face_asset_id'] = i0.Variable<String>(faceAssetId);
|
||||
}
|
||||
map['thumbnail_path'] = i0.Variable<String>(thumbnailPath);
|
||||
map['is_favorite'] = i0.Variable<bool>(isFavorite);
|
||||
map['is_hidden'] = i0.Variable<bool>(isHidden);
|
||||
if (!nullToAbsent || color != null) {
|
||||
@ -668,7 +631,6 @@ class PersonEntityData extends i0.DataClass
|
||||
ownerId: serializer.fromJson<String>(json['ownerId']),
|
||||
name: serializer.fromJson<String>(json['name']),
|
||||
faceAssetId: serializer.fromJson<String?>(json['faceAssetId']),
|
||||
thumbnailPath: serializer.fromJson<String>(json['thumbnailPath']),
|
||||
isFavorite: serializer.fromJson<bool>(json['isFavorite']),
|
||||
isHidden: serializer.fromJson<bool>(json['isHidden']),
|
||||
color: serializer.fromJson<String?>(json['color']),
|
||||
@ -685,7 +647,6 @@ class PersonEntityData extends i0.DataClass
|
||||
'ownerId': serializer.toJson<String>(ownerId),
|
||||
'name': serializer.toJson<String>(name),
|
||||
'faceAssetId': serializer.toJson<String?>(faceAssetId),
|
||||
'thumbnailPath': serializer.toJson<String>(thumbnailPath),
|
||||
'isFavorite': serializer.toJson<bool>(isFavorite),
|
||||
'isHidden': serializer.toJson<bool>(isHidden),
|
||||
'color': serializer.toJson<String?>(color),
|
||||
@ -700,7 +661,6 @@ class PersonEntityData extends i0.DataClass
|
||||
String? ownerId,
|
||||
String? name,
|
||||
i0.Value<String?> faceAssetId = const i0.Value.absent(),
|
||||
String? thumbnailPath,
|
||||
bool? isFavorite,
|
||||
bool? isHidden,
|
||||
i0.Value<String?> color = const i0.Value.absent(),
|
||||
@ -712,7 +672,6 @@ class PersonEntityData extends i0.DataClass
|
||||
ownerId: ownerId ?? this.ownerId,
|
||||
name: name ?? this.name,
|
||||
faceAssetId: faceAssetId.present ? faceAssetId.value : this.faceAssetId,
|
||||
thumbnailPath: thumbnailPath ?? this.thumbnailPath,
|
||||
isFavorite: isFavorite ?? this.isFavorite,
|
||||
isHidden: isHidden ?? this.isHidden,
|
||||
color: color.present ? color.value : this.color,
|
||||
@ -727,9 +686,6 @@ class PersonEntityData extends i0.DataClass
|
||||
name: data.name.present ? data.name.value : this.name,
|
||||
faceAssetId:
|
||||
data.faceAssetId.present ? data.faceAssetId.value : this.faceAssetId,
|
||||
thumbnailPath: data.thumbnailPath.present
|
||||
? data.thumbnailPath.value
|
||||
: this.thumbnailPath,
|
||||
isFavorite:
|
||||
data.isFavorite.present ? data.isFavorite.value : this.isFavorite,
|
||||
isHidden: data.isHidden.present ? data.isHidden.value : this.isHidden,
|
||||
@ -747,7 +703,6 @@ class PersonEntityData extends i0.DataClass
|
||||
..write('ownerId: $ownerId, ')
|
||||
..write('name: $name, ')
|
||||
..write('faceAssetId: $faceAssetId, ')
|
||||
..write('thumbnailPath: $thumbnailPath, ')
|
||||
..write('isFavorite: $isFavorite, ')
|
||||
..write('isHidden: $isHidden, ')
|
||||
..write('color: $color, ')
|
||||
@ -758,7 +713,7 @@ class PersonEntityData extends i0.DataClass
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, createdAt, updatedAt, ownerId, name,
|
||||
faceAssetId, thumbnailPath, isFavorite, isHidden, color, birthDate);
|
||||
faceAssetId, isFavorite, isHidden, color, birthDate);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
@ -769,7 +724,6 @@ class PersonEntityData extends i0.DataClass
|
||||
other.ownerId == this.ownerId &&
|
||||
other.name == this.name &&
|
||||
other.faceAssetId == this.faceAssetId &&
|
||||
other.thumbnailPath == this.thumbnailPath &&
|
||||
other.isFavorite == this.isFavorite &&
|
||||
other.isHidden == this.isHidden &&
|
||||
other.color == this.color &&
|
||||
@ -783,7 +737,6 @@ class PersonEntityCompanion extends i0.UpdateCompanion<i1.PersonEntityData> {
|
||||
final i0.Value<String> ownerId;
|
||||
final i0.Value<String> name;
|
||||
final i0.Value<String?> faceAssetId;
|
||||
final i0.Value<String> thumbnailPath;
|
||||
final i0.Value<bool> isFavorite;
|
||||
final i0.Value<bool> isHidden;
|
||||
final i0.Value<String?> color;
|
||||
@ -795,7 +748,6 @@ class PersonEntityCompanion extends i0.UpdateCompanion<i1.PersonEntityData> {
|
||||
this.ownerId = const i0.Value.absent(),
|
||||
this.name = const i0.Value.absent(),
|
||||
this.faceAssetId = const i0.Value.absent(),
|
||||
this.thumbnailPath = const i0.Value.absent(),
|
||||
this.isFavorite = const i0.Value.absent(),
|
||||
this.isHidden = const i0.Value.absent(),
|
||||
this.color = const i0.Value.absent(),
|
||||
@ -808,7 +760,6 @@ class PersonEntityCompanion extends i0.UpdateCompanion<i1.PersonEntityData> {
|
||||
required String ownerId,
|
||||
required String name,
|
||||
this.faceAssetId = const i0.Value.absent(),
|
||||
required String thumbnailPath,
|
||||
required bool isFavorite,
|
||||
required bool isHidden,
|
||||
this.color = const i0.Value.absent(),
|
||||
@ -816,7 +767,6 @@ class PersonEntityCompanion extends i0.UpdateCompanion<i1.PersonEntityData> {
|
||||
}) : id = i0.Value(id),
|
||||
ownerId = i0.Value(ownerId),
|
||||
name = i0.Value(name),
|
||||
thumbnailPath = i0.Value(thumbnailPath),
|
||||
isFavorite = i0.Value(isFavorite),
|
||||
isHidden = i0.Value(isHidden);
|
||||
static i0.Insertable<i1.PersonEntityData> custom({
|
||||
@ -826,7 +776,6 @@ class PersonEntityCompanion extends i0.UpdateCompanion<i1.PersonEntityData> {
|
||||
i0.Expression<String>? ownerId,
|
||||
i0.Expression<String>? name,
|
||||
i0.Expression<String>? faceAssetId,
|
||||
i0.Expression<String>? thumbnailPath,
|
||||
i0.Expression<bool>? isFavorite,
|
||||
i0.Expression<bool>? isHidden,
|
||||
i0.Expression<String>? color,
|
||||
@ -839,7 +788,6 @@ class PersonEntityCompanion extends i0.UpdateCompanion<i1.PersonEntityData> {
|
||||
if (ownerId != null) 'owner_id': ownerId,
|
||||
if (name != null) 'name': name,
|
||||
if (faceAssetId != null) 'face_asset_id': faceAssetId,
|
||||
if (thumbnailPath != null) 'thumbnail_path': thumbnailPath,
|
||||
if (isFavorite != null) 'is_favorite': isFavorite,
|
||||
if (isHidden != null) 'is_hidden': isHidden,
|
||||
if (color != null) 'color': color,
|
||||
@ -854,7 +802,6 @@ class PersonEntityCompanion extends i0.UpdateCompanion<i1.PersonEntityData> {
|
||||
i0.Value<String>? ownerId,
|
||||
i0.Value<String>? name,
|
||||
i0.Value<String?>? faceAssetId,
|
||||
i0.Value<String>? thumbnailPath,
|
||||
i0.Value<bool>? isFavorite,
|
||||
i0.Value<bool>? isHidden,
|
||||
i0.Value<String?>? color,
|
||||
@ -866,7 +813,6 @@ class PersonEntityCompanion extends i0.UpdateCompanion<i1.PersonEntityData> {
|
||||
ownerId: ownerId ?? this.ownerId,
|
||||
name: name ?? this.name,
|
||||
faceAssetId: faceAssetId ?? this.faceAssetId,
|
||||
thumbnailPath: thumbnailPath ?? this.thumbnailPath,
|
||||
isFavorite: isFavorite ?? this.isFavorite,
|
||||
isHidden: isHidden ?? this.isHidden,
|
||||
color: color ?? this.color,
|
||||
@ -895,9 +841,6 @@ class PersonEntityCompanion extends i0.UpdateCompanion<i1.PersonEntityData> {
|
||||
if (faceAssetId.present) {
|
||||
map['face_asset_id'] = i0.Variable<String>(faceAssetId.value);
|
||||
}
|
||||
if (thumbnailPath.present) {
|
||||
map['thumbnail_path'] = i0.Variable<String>(thumbnailPath.value);
|
||||
}
|
||||
if (isFavorite.present) {
|
||||
map['is_favorite'] = i0.Variable<bool>(isFavorite.value);
|
||||
}
|
||||
@ -922,7 +865,6 @@ class PersonEntityCompanion extends i0.UpdateCompanion<i1.PersonEntityData> {
|
||||
..write('ownerId: $ownerId, ')
|
||||
..write('name: $name, ')
|
||||
..write('faceAssetId: $faceAssetId, ')
|
||||
..write('thumbnailPath: $thumbnailPath, ')
|
||||
..write('isFavorite: $isFavorite, ')
|
||||
..write('isHidden: $isHidden, ')
|
||||
..write('color: $color, ')
|
||||
|
@ -0,0 +1,33 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:immich_mobile/domain/models/asset_face.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
|
||||
class DriftAssetFaceRepository extends DriftDatabaseRepository {
|
||||
final Drift _db;
|
||||
const DriftAssetFaceRepository(this._db) : super(_db);
|
||||
|
||||
Future<List<AssetFace>> getAll() {
|
||||
return _db.assetFaceEntity
|
||||
.select()
|
||||
.map((assetFace) => assetFace.toDto())
|
||||
.get();
|
||||
}
|
||||
}
|
||||
|
||||
extension on AssetFaceEntityData {
|
||||
AssetFace toDto() {
|
||||
return AssetFace(
|
||||
id: id,
|
||||
assetId: assetId,
|
||||
personId: personId,
|
||||
imageWidth: imageWidth,
|
||||
imageHeight: imageHeight,
|
||||
boundingBoxX1: boundingBoxX1,
|
||||
boundingBoxY1: boundingBoxY1,
|
||||
boundingBoxX2: boundingBoxX2,
|
||||
boundingBoxY2: boundingBoxY2,
|
||||
sourceType: sourceType,
|
||||
);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import 'package:drift_flutter/drift_flutter.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/exif.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
||||
@ -56,6 +57,7 @@ class IsarDatabaseRepository implements IDatabaseRepository {
|
||||
MemoryAssetEntity,
|
||||
StackEntity,
|
||||
PersonEntity,
|
||||
AssetFaceEntity,
|
||||
],
|
||||
include: {
|
||||
'package:immich_mobile/infrastructure/entities/merged_asset.drift',
|
||||
@ -72,7 +74,7 @@ class Drift extends $Drift implements IDatabaseRepository {
|
||||
);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 3;
|
||||
int get schemaVersion => 4;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy(
|
||||
@ -94,6 +96,10 @@ class Drift extends $Drift implements IDatabaseRepository {
|
||||
// Removed foreign key constraint on stack.primaryAssetId
|
||||
await m.alterTable(TableMigration(v3.stackEntity));
|
||||
},
|
||||
from3To4: (m, v4) async {
|
||||
await m.alterTable(TableMigration(v4.personEntity));
|
||||
await m.create(v4.assetFaceEntity);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -31,9 +31,11 @@ import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.
|
||||
as i14;
|
||||
import 'package:immich_mobile/infrastructure/entities/person.entity.drift.dart'
|
||||
as i15;
|
||||
import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart'
|
||||
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart'
|
||||
as i16;
|
||||
import 'package:drift/internal/modular.dart' as i17;
|
||||
import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart'
|
||||
as i17;
|
||||
import 'package:drift/internal/modular.dart' as i18;
|
||||
|
||||
abstract class $Drift extends i0.GeneratedDatabase {
|
||||
$Drift(i0.QueryExecutor e) : super(e);
|
||||
@ -64,8 +66,10 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
||||
late final i14.$MemoryAssetEntityTable memoryAssetEntity =
|
||||
i14.$MemoryAssetEntityTable(this);
|
||||
late final i15.$PersonEntityTable personEntity = i15.$PersonEntityTable(this);
|
||||
i16.MergedAssetDrift get mergedAssetDrift => i17.ReadDatabaseContainer(this)
|
||||
.accessor<i16.MergedAssetDrift>(i16.MergedAssetDrift.new);
|
||||
late final i16.$AssetFaceEntityTable assetFaceEntity =
|
||||
i16.$AssetFaceEntityTable(this);
|
||||
i17.MergedAssetDrift get mergedAssetDrift => i18.ReadDatabaseContainer(this)
|
||||
.accessor<i17.MergedAssetDrift>(i17.MergedAssetDrift.new);
|
||||
@override
|
||||
Iterable<i0.TableInfo<i0.Table, Object?>> get allTables =>
|
||||
allSchemaEntities.whereType<i0.TableInfo<i0.Table, Object?>>();
|
||||
@ -88,7 +92,8 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
||||
remoteAlbumUserEntity,
|
||||
memoryEntity,
|
||||
memoryAssetEntity,
|
||||
personEntity
|
||||
personEntity,
|
||||
assetFaceEntity
|
||||
];
|
||||
@override
|
||||
i0.StreamQueryUpdateRules get streamUpdateRules =>
|
||||
@ -227,6 +232,20 @@ abstract class $Drift extends i0.GeneratedDatabase {
|
||||
i0.TableUpdate('person_entity', kind: i0.UpdateKind.delete),
|
||||
],
|
||||
),
|
||||
i0.WritePropagation(
|
||||
on: i0.TableUpdateQuery.onTableName('remote_asset_entity',
|
||||
limitUpdateKind: i0.UpdateKind.delete),
|
||||
result: [
|
||||
i0.TableUpdate('asset_face_entity', kind: i0.UpdateKind.delete),
|
||||
],
|
||||
),
|
||||
i0.WritePropagation(
|
||||
on: i0.TableUpdateQuery.onTableName('person_entity',
|
||||
limitUpdateKind: i0.UpdateKind.delete),
|
||||
result: [
|
||||
i0.TableUpdate('asset_face_entity', kind: i0.UpdateKind.update),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
@override
|
||||
@ -268,4 +287,6 @@ class $DriftManager {
|
||||
i14.$$MemoryAssetEntityTableTableManager(_db, _db.memoryAssetEntity);
|
||||
i15.$$PersonEntityTableTableManager get personEntity =>
|
||||
i15.$$PersonEntityTableTableManager(_db, _db.personEntity);
|
||||
i16.$$AssetFaceEntityTableTableManager get assetFaceEntity =>
|
||||
i16.$$AssetFaceEntityTableTableManager(_db, _db.assetFaceEntity);
|
||||
}
|
||||
|
@ -1266,9 +1266,451 @@ final class Schema3 extends i0.VersionedSchema {
|
||||
i1.GeneratedColumn<String> _column_75(String aliasedName) =>
|
||||
i1.GeneratedColumn<String>('primary_asset_id', aliasedName, false,
|
||||
type: i1.DriftSqlType.string);
|
||||
|
||||
final class Schema4 extends i0.VersionedSchema {
|
||||
Schema4({required super.database}) : super(version: 4);
|
||||
@override
|
||||
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||
userEntity,
|
||||
remoteAssetEntity,
|
||||
localAssetEntity,
|
||||
stackEntity,
|
||||
idxLocalAssetChecksum,
|
||||
uQRemoteAssetOwnerChecksum,
|
||||
idxRemoteAssetChecksum,
|
||||
userMetadataEntity,
|
||||
partnerEntity,
|
||||
localAlbumEntity,
|
||||
localAlbumAssetEntity,
|
||||
remoteExifEntity,
|
||||
remoteAlbumEntity,
|
||||
remoteAlbumAssetEntity,
|
||||
remoteAlbumUserEntity,
|
||||
memoryEntity,
|
||||
memoryAssetEntity,
|
||||
personEntity,
|
||||
assetFaceEntity,
|
||||
];
|
||||
late final Shape0 userEntity = Shape0(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'user_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(id)',
|
||||
],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_1,
|
||||
_column_2,
|
||||
_column_3,
|
||||
_column_4,
|
||||
_column_5,
|
||||
_column_6,
|
||||
_column_7,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape1 remoteAssetEntity = Shape1(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(id)',
|
||||
],
|
||||
columns: [
|
||||
_column_1,
|
||||
_column_8,
|
||||
_column_9,
|
||||
_column_5,
|
||||
_column_10,
|
||||
_column_11,
|
||||
_column_12,
|
||||
_column_0,
|
||||
_column_13,
|
||||
_column_14,
|
||||
_column_15,
|
||||
_column_16,
|
||||
_column_17,
|
||||
_column_18,
|
||||
_column_19,
|
||||
_column_20,
|
||||
_column_21,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape2 localAssetEntity = Shape2(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'local_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(id)',
|
||||
],
|
||||
columns: [
|
||||
_column_1,
|
||||
_column_8,
|
||||
_column_9,
|
||||
_column_5,
|
||||
_column_10,
|
||||
_column_11,
|
||||
_column_12,
|
||||
_column_0,
|
||||
_column_22,
|
||||
_column_14,
|
||||
_column_23,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape3 stackEntity = Shape3(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'stack_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(id)',
|
||||
],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_9,
|
||||
_column_5,
|
||||
_column_15,
|
||||
_column_75,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
final i1.Index idxLocalAssetChecksum = i1.Index('idx_local_asset_checksum',
|
||||
'CREATE INDEX idx_local_asset_checksum ON local_asset_entity (checksum)');
|
||||
final i1.Index uQRemoteAssetOwnerChecksum = i1.Index(
|
||||
'UQ_remote_asset_owner_checksum',
|
||||
'CREATE UNIQUE INDEX UQ_remote_asset_owner_checksum ON remote_asset_entity (checksum, owner_id)');
|
||||
final i1.Index idxRemoteAssetChecksum = i1.Index('idx_remote_asset_checksum',
|
||||
'CREATE INDEX idx_remote_asset_checksum ON remote_asset_entity (checksum)');
|
||||
late final Shape4 userMetadataEntity = Shape4(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'user_metadata_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(user_id, "key")',
|
||||
],
|
||||
columns: [
|
||||
_column_25,
|
||||
_column_26,
|
||||
_column_27,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape5 partnerEntity = Shape5(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'partner_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(shared_by_id, shared_with_id)',
|
||||
],
|
||||
columns: [
|
||||
_column_28,
|
||||
_column_29,
|
||||
_column_30,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape6 localAlbumEntity = Shape6(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'local_album_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(id)',
|
||||
],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_1,
|
||||
_column_5,
|
||||
_column_31,
|
||||
_column_32,
|
||||
_column_33,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape7 localAlbumAssetEntity = Shape7(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'local_album_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(asset_id, album_id)',
|
||||
],
|
||||
columns: [
|
||||
_column_34,
|
||||
_column_35,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape8 remoteExifEntity = Shape8(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_exif_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(asset_id)',
|
||||
],
|
||||
columns: [
|
||||
_column_36,
|
||||
_column_37,
|
||||
_column_38,
|
||||
_column_39,
|
||||
_column_40,
|
||||
_column_41,
|
||||
_column_11,
|
||||
_column_10,
|
||||
_column_42,
|
||||
_column_43,
|
||||
_column_44,
|
||||
_column_45,
|
||||
_column_46,
|
||||
_column_47,
|
||||
_column_48,
|
||||
_column_49,
|
||||
_column_50,
|
||||
_column_51,
|
||||
_column_52,
|
||||
_column_53,
|
||||
_column_54,
|
||||
_column_55,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape9 remoteAlbumEntity = Shape9(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_album_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(id)',
|
||||
],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_1,
|
||||
_column_56,
|
||||
_column_9,
|
||||
_column_5,
|
||||
_column_15,
|
||||
_column_57,
|
||||
_column_58,
|
||||
_column_59,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape7 remoteAlbumAssetEntity = Shape7(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_album_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(asset_id, album_id)',
|
||||
],
|
||||
columns: [
|
||||
_column_36,
|
||||
_column_60,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape10 remoteAlbumUserEntity = Shape10(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'remote_album_user_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(album_id, user_id)',
|
||||
],
|
||||
columns: [
|
||||
_column_60,
|
||||
_column_25,
|
||||
_column_61,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape11 memoryEntity = Shape11(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'memory_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(id)',
|
||||
],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_9,
|
||||
_column_5,
|
||||
_column_18,
|
||||
_column_15,
|
||||
_column_8,
|
||||
_column_62,
|
||||
_column_63,
|
||||
_column_64,
|
||||
_column_65,
|
||||
_column_66,
|
||||
_column_67,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape12 memoryAssetEntity = Shape12(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'memory_asset_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(asset_id, memory_id)',
|
||||
],
|
||||
columns: [
|
||||
_column_36,
|
||||
_column_68,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape14 personEntity = Shape14(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'person_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(id)',
|
||||
],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_9,
|
||||
_column_5,
|
||||
_column_15,
|
||||
_column_1,
|
||||
_column_69,
|
||||
_column_71,
|
||||
_column_72,
|
||||
_column_73,
|
||||
_column_74,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape15 assetFaceEntity = Shape15(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'asset_face_entity',
|
||||
withoutRowId: true,
|
||||
isStrict: true,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(id)',
|
||||
],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_36,
|
||||
_column_76,
|
||||
_column_77,
|
||||
_column_78,
|
||||
_column_79,
|
||||
_column_80,
|
||||
_column_81,
|
||||
_column_82,
|
||||
_column_83,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
}
|
||||
|
||||
class Shape14 extends i0.VersionedTable {
|
||||
Shape14({required super.source, required super.alias}) : super.aliased();
|
||||
i1.GeneratedColumn<String> get id =>
|
||||
columnsByName['id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<DateTime> get createdAt =>
|
||||
columnsByName['created_at']! as i1.GeneratedColumn<DateTime>;
|
||||
i1.GeneratedColumn<DateTime> get updatedAt =>
|
||||
columnsByName['updated_at']! as i1.GeneratedColumn<DateTime>;
|
||||
i1.GeneratedColumn<String> get ownerId =>
|
||||
columnsByName['owner_id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get name =>
|
||||
columnsByName['name']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get faceAssetId =>
|
||||
columnsByName['face_asset_id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<bool> get isFavorite =>
|
||||
columnsByName['is_favorite']! as i1.GeneratedColumn<bool>;
|
||||
i1.GeneratedColumn<bool> get isHidden =>
|
||||
columnsByName['is_hidden']! as i1.GeneratedColumn<bool>;
|
||||
i1.GeneratedColumn<String> get color =>
|
||||
columnsByName['color']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<DateTime> get birthDate =>
|
||||
columnsByName['birth_date']! as i1.GeneratedColumn<DateTime>;
|
||||
}
|
||||
|
||||
class Shape15 extends i0.VersionedTable {
|
||||
Shape15({required super.source, required super.alias}) : super.aliased();
|
||||
i1.GeneratedColumn<String> get id =>
|
||||
columnsByName['id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get assetId =>
|
||||
columnsByName['asset_id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<String> get personId =>
|
||||
columnsByName['person_id']! as i1.GeneratedColumn<String>;
|
||||
i1.GeneratedColumn<int> get imageWidth =>
|
||||
columnsByName['image_width']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<int> get imageHeight =>
|
||||
columnsByName['image_height']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<int> get boundingBoxX1 =>
|
||||
columnsByName['bounding_box_x1']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<int> get boundingBoxY1 =>
|
||||
columnsByName['bounding_box_y1']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<int> get boundingBoxX2 =>
|
||||
columnsByName['bounding_box_x2']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<int> get boundingBoxY2 =>
|
||||
columnsByName['bounding_box_y2']! as i1.GeneratedColumn<int>;
|
||||
i1.GeneratedColumn<String> get sourceType =>
|
||||
columnsByName['source_type']! as i1.GeneratedColumn<String>;
|
||||
}
|
||||
|
||||
i1.GeneratedColumn<String> _column_76(String aliasedName) =>
|
||||
i1.GeneratedColumn<String>('person_id', aliasedName, true,
|
||||
type: i1.DriftSqlType.string,
|
||||
defaultConstraints: i1.GeneratedColumn.constraintIsAlways(
|
||||
'REFERENCES person_entity (id) ON DELETE SET NULL'));
|
||||
i1.GeneratedColumn<int> _column_77(String aliasedName) =>
|
||||
i1.GeneratedColumn<int>('image_width', aliasedName, false,
|
||||
type: i1.DriftSqlType.int);
|
||||
i1.GeneratedColumn<int> _column_78(String aliasedName) =>
|
||||
i1.GeneratedColumn<int>('image_height', aliasedName, false,
|
||||
type: i1.DriftSqlType.int);
|
||||
i1.GeneratedColumn<int> _column_79(String aliasedName) =>
|
||||
i1.GeneratedColumn<int>('bounding_box_x1', aliasedName, false,
|
||||
type: i1.DriftSqlType.int);
|
||||
i1.GeneratedColumn<int> _column_80(String aliasedName) =>
|
||||
i1.GeneratedColumn<int>('bounding_box_y1', aliasedName, false,
|
||||
type: i1.DriftSqlType.int);
|
||||
i1.GeneratedColumn<int> _column_81(String aliasedName) =>
|
||||
i1.GeneratedColumn<int>('bounding_box_x2', aliasedName, false,
|
||||
type: i1.DriftSqlType.int);
|
||||
i1.GeneratedColumn<int> _column_82(String aliasedName) =>
|
||||
i1.GeneratedColumn<int>('bounding_box_y2', aliasedName, false,
|
||||
type: i1.DriftSqlType.int);
|
||||
i1.GeneratedColumn<String> _column_83(String aliasedName) =>
|
||||
i1.GeneratedColumn<String>('source_type', aliasedName, false,
|
||||
type: i1.DriftSqlType.string);
|
||||
i0.MigrationStepWithVersion migrationSteps({
|
||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
||||
}) {
|
||||
return (currentVersion, database) async {
|
||||
switch (currentVersion) {
|
||||
@ -1282,6 +1724,11 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||
final migrator = i1.Migrator(database, schema);
|
||||
await from2To3(migrator, schema);
|
||||
return 3;
|
||||
case 3:
|
||||
final schema = Schema4(database: database);
|
||||
final migrator = i1.Migrator(database, schema);
|
||||
await from3To4(migrator, schema);
|
||||
return 4;
|
||||
default:
|
||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||
}
|
||||
@ -1291,9 +1738,11 @@ i0.MigrationStepWithVersion migrationSteps({
|
||||
i1.OnUpgrade stepByStep({
|
||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||
required Future<void> Function(i1.Migrator m, Schema4 schema) from3To4,
|
||||
}) =>
|
||||
i0.VersionedSchema.stepByStepHelper(
|
||||
step: migrationSteps(
|
||||
from1To2: from1To2,
|
||||
from2To3: from2To3,
|
||||
from3To4: from3To4,
|
||||
));
|
||||
|
@ -26,7 +26,6 @@ extension on PersonEntityData {
|
||||
ownerId: ownerId,
|
||||
name: name,
|
||||
faceAssetId: faceAssetId,
|
||||
thumbnailPath: thumbnailPath,
|
||||
isFavorite: isFavorite,
|
||||
isHidden: isHidden,
|
||||
color: color,
|
||||
|
@ -58,6 +58,7 @@ class SyncApiRepository {
|
||||
SyncRequestType.partnerStacksV1,
|
||||
SyncRequestType.userMetadataV1,
|
||||
SyncRequestType.peopleV1,
|
||||
SyncRequestType.assetFacesV1,
|
||||
],
|
||||
).toJson(),
|
||||
);
|
||||
@ -176,6 +177,8 @@ const _kResponseMap = <SyncEntityType, Function(Object)>{
|
||||
SyncEntityType.userMetadataDeleteV1: SyncUserMetadataDeleteV1.fromJson,
|
||||
SyncEntityType.personV1: SyncPersonV1.fromJson,
|
||||
SyncEntityType.personDeleteV1: SyncPersonDeleteV1.fromJson,
|
||||
SyncEntityType.assetFaceV1: SyncAssetFaceV1.fromJson,
|
||||
SyncEntityType.assetFaceDeleteV1: SyncAssetFaceDeleteV1.fromJson,
|
||||
};
|
||||
|
||||
class _SyncAckV1 {
|
||||
|
@ -5,6 +5,7 @@ import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/memory.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart';
|
||||
@ -546,11 +547,62 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||
Iterable<SyncPersonDeleteV1> data,
|
||||
) async {
|
||||
try {
|
||||
await _db.personEntity.deleteWhere(
|
||||
(row) => row.id.isIn(data.map((e) => e.personId)),
|
||||
await _db.batch((batch) {
|
||||
for (final person in data) {
|
||||
batch.deleteWhere(
|
||||
_db.personEntity,
|
||||
(row) => row.id.equals(person.personId),
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch (error, stack) {
|
||||
_logger.severe('Error: deletePeopleV1', error, stack);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateAssetFacesV1(Iterable<SyncAssetFaceV1> data) async {
|
||||
try {
|
||||
await _db.batch((batch) {
|
||||
for (final assetFace in data) {
|
||||
final companion = AssetFaceEntityCompanion(
|
||||
assetId: Value(assetFace.assetId),
|
||||
personId: Value(assetFace.personId),
|
||||
imageWidth: Value(assetFace.imageWidth),
|
||||
imageHeight: Value(assetFace.imageHeight),
|
||||
boundingBoxX1: Value(assetFace.boundingBoxX1),
|
||||
boundingBoxY1: Value(assetFace.boundingBoxY1),
|
||||
boundingBoxX2: Value(assetFace.boundingBoxX2),
|
||||
boundingBoxY2: Value(assetFace.boundingBoxY2),
|
||||
sourceType: Value(assetFace.sourceType),
|
||||
);
|
||||
|
||||
batch.insert(
|
||||
_db.assetFaceEntity,
|
||||
companion.copyWith(id: Value(assetFace.id)),
|
||||
onConflict: DoUpdate((_) => companion),
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch (error, stack) {
|
||||
_logger.severe('Error: updateAssetFacesV1', error, stack);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteAssetFacesV1(Iterable<SyncAssetFaceDeleteV1> data) async {
|
||||
try {
|
||||
await _db.batch((batch) {
|
||||
for (final assetFace in data) {
|
||||
batch.deleteWhere(
|
||||
_db.assetFaceEntity,
|
||||
(row) => row.id.equals(assetFace.assetFaceId),
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch (error, stack) {
|
||||
_logger.severe('Error: deleteAssetFacesV1', error, stack);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +121,7 @@ final _features = [
|
||||
await db.memoryAssetEntity.deleteAll();
|
||||
await db.stackEntity.deleteAll();
|
||||
await db.personEntity.deleteAll();
|
||||
await db.assetFaceEntity.deleteAll();
|
||||
},
|
||||
),
|
||||
_Feature(
|
||||
|
@ -170,6 +170,10 @@ final _remoteStats = [
|
||||
name: 'People',
|
||||
load: (db) => db.managers.personEntity.count(),
|
||||
),
|
||||
_Stat(
|
||||
name: 'AssetFaces',
|
||||
load: (db) => db.managers.assetFaceEntity.count(),
|
||||
),
|
||||
];
|
||||
|
||||
@RoutePage()
|
||||
|
@ -0,0 +1,7 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/asset_face.repository.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
|
||||
final driftAssetFaceProvider = Provider<DriftAssetFaceRepository>(
|
||||
(ref) => DriftAssetFaceRepository(ref.watch(driftProvider)),
|
||||
);
|
@ -34,11 +34,12 @@ class AuthRepository extends DatabaseRepository {
|
||||
_drift.userMetadataEntity.deleteAll(),
|
||||
_drift.partnerEntity.deleteAll(),
|
||||
_drift.stackEntity.deleteAll(),
|
||||
_drift.personEntity.deleteAll(),
|
||||
_drift.assetFaceEntity.deleteAll(),
|
||||
]);
|
||||
// Drift deletions - parent entities
|
||||
await Future.wait([
|
||||
_drift.memoryEntity.deleteAll(),
|
||||
_drift.personEntity.deleteAll(),
|
||||
_drift.remoteAlbumEntity.deleteAll(),
|
||||
_drift.remoteAssetEntity.deleteAll(),
|
||||
_drift.userEntity.deleteAll(),
|
||||
|
@ -109,6 +109,10 @@ void main() {
|
||||
.thenAnswer(successHandler);
|
||||
when(() => mockSyncStreamRepo.deletePeopleV1(any()))
|
||||
.thenAnswer(successHandler);
|
||||
when(() => mockSyncStreamRepo.updateAssetFacesV1(any()))
|
||||
.thenAnswer(successHandler);
|
||||
when(() => mockSyncStreamRepo.deleteAssetFacesV1(any()))
|
||||
.thenAnswer(successHandler);
|
||||
|
||||
sut = SyncStreamService(
|
||||
syncApiRepository: mockSyncApiRepo,
|
||||
|
5
mobile/test/drift/main/generated/schema.dart
generated
5
mobile/test/drift/main/generated/schema.dart
generated
@ -6,6 +6,7 @@ import 'package:drift/internal/migrations.dart';
|
||||
import 'schema_v1.dart' as v1;
|
||||
import 'schema_v2.dart' as v2;
|
||||
import 'schema_v3.dart' as v3;
|
||||
import 'schema_v4.dart' as v4;
|
||||
|
||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
@override
|
||||
@ -17,10 +18,12 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
return v2.DatabaseAtV2(db);
|
||||
case 3:
|
||||
return v3.DatabaseAtV3(db);
|
||||
case 4:
|
||||
return v4.DatabaseAtV4(db);
|
||||
default:
|
||||
throw MissingSchemaException(version, versions);
|
||||
}
|
||||
}
|
||||
|
||||
static const versions = const [1, 2, 3];
|
||||
static const versions = const [1, 2, 3, 4];
|
||||
}
|
||||
|
5524
mobile/test/drift/main/generated/schema_v4.dart
generated
Normal file
5524
mobile/test/drift/main/generated/schema_v4.dart
generated
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user