1
0
mirror of https://github.com/immich-app/immich.git synced 2025-08-07 23:03:36 +02:00

feat(mobile): drift user metadata sync (#19894)

* feat(mobile): drift user metadata sync

* change text to jsonb

* update primary key

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Daimolean
2025-07-15 22:17:35 +08:00
committed by GitHub
parent daea57f7d2
commit 0acbf1199a
10 changed files with 495 additions and 106 deletions

View File

@ -8,14 +8,16 @@ class UserMetadataEntity extends Table with DriftDefaultsMixin {
TextColumn get userId =>
text().references(UserEntity, #id, onDelete: KeyAction.cascade)();
TextColumn get preferences => text().map(userPreferenceConverter)();
IntColumn get key => intEnum<UserMetadataKey>()();
BlobColumn get value => blob().map(userMetadataConverter)();
@override
Set<Column> get primaryKey => {userId};
Set<Column> get primaryKey => {userId, key};
}
final JsonTypeConverter2<UserPreferences, String, Object?>
userPreferenceConverter = TypeConverter.json2(
fromJson: (json) => UserPreferences.fromMap(json as Map<String, Object?>),
toJson: (pref) => pref.toMap(),
final JsonTypeConverter2<Map<String, Object?>, Uint8List, Object?>
userMetadataConverter = TypeConverter.jsonb(
fromJson: (json) => json as Map<String, Object?>,
);

View File

@ -4,21 +4,24 @@ import 'package:drift/drift.dart' as i0;
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart'
as i1;
import 'package:immich_mobile/domain/models/user_metadata.model.dart' as i2;
import 'dart:typed_data' as i3;
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart'
as i3;
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
as i4;
import 'package:drift/internal/modular.dart' as i5;
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
as i5;
import 'package:drift/internal/modular.dart' as i6;
typedef $$UserMetadataEntityTableCreateCompanionBuilder
= i1.UserMetadataEntityCompanion Function({
required String userId,
required i2.UserPreferences preferences,
required i2.UserMetadataKey key,
required Map<String, Object?> value,
});
typedef $$UserMetadataEntityTableUpdateCompanionBuilder
= i1.UserMetadataEntityCompanion Function({
i0.Value<String> userId,
i0.Value<i2.UserPreferences> preferences,
i0.Value<i2.UserMetadataKey> key,
i0.Value<Map<String, Object?>> value,
});
final class $$UserMetadataEntityTableReferences extends i0.BaseReferences<
@ -28,26 +31,26 @@ final class $$UserMetadataEntityTableReferences extends i0.BaseReferences<
$$UserMetadataEntityTableReferences(
super.$_db, super.$_table, super.$_typedResult);
static i4.$UserEntityTable _userIdTable(i0.GeneratedDatabase db) =>
i5.ReadDatabaseContainer(db)
.resultSet<i4.$UserEntityTable>('user_entity')
static i5.$UserEntityTable _userIdTable(i0.GeneratedDatabase db) =>
i6.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity')
.createAlias(i0.$_aliasNameGenerator(
i5.ReadDatabaseContainer(db)
i6.ReadDatabaseContainer(db)
.resultSet<i1.$UserMetadataEntityTable>(
'user_metadata_entity')
.userId,
i5.ReadDatabaseContainer(db)
.resultSet<i4.$UserEntityTable>('user_entity')
i6.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity')
.id));
i4.$$UserEntityTableProcessedTableManager get userId {
i5.$$UserEntityTableProcessedTableManager get userId {
final $_column = $_itemColumn<String>('user_id')!;
final manager = i4
final manager = i5
.$$UserEntityTableTableManager(
$_db,
i5.ReadDatabaseContainer($_db)
.resultSet<i4.$UserEntityTable>('user_entity'))
i6.ReadDatabaseContainer($_db)
.resultSet<i5.$UserEntityTable>('user_entity'))
.filter((f) => f.id.sqlEquals($_column));
final item = $_typedResult.readTableOrNull(_userIdTable($_db));
if (item == null) return manager;
@ -65,26 +68,31 @@ class $$UserMetadataEntityTableFilterComposer
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnWithTypeConverterFilters<i2.UserPreferences, i2.UserPreferences,
String>
get preferences => $composableBuilder(
column: $table.preferences,
i0.ColumnWithTypeConverterFilters<i2.UserMetadataKey, i2.UserMetadataKey, int>
get key => $composableBuilder(
column: $table.key,
builder: (column) => i0.ColumnWithTypeConverterFilters(column));
i4.$$UserEntityTableFilterComposer get userId {
final i4.$$UserEntityTableFilterComposer composer = $composerBuilder(
i0.ColumnWithTypeConverterFilters<Map<String, Object?>, Map<String, Object>,
i3.Uint8List>
get value => $composableBuilder(
column: $table.value,
builder: (column) => i0.ColumnWithTypeConverterFilters(column));
i5.$$UserEntityTableFilterComposer get userId {
final i5.$$UserEntityTableFilterComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.userId,
referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i4.$UserEntityTable>('user_entity'),
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i4.$$UserEntityTableFilterComposer(
i5.$$UserEntityTableFilterComposer(
$db: $db,
$table: i5.ReadDatabaseContainer($db)
.resultSet<i4.$UserEntityTable>('user_entity'),
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
@ -103,24 +111,26 @@ class $$UserMetadataEntityTableOrderingComposer
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.ColumnOrderings<String> get preferences => $composableBuilder(
column: $table.preferences,
builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<int> get key => $composableBuilder(
column: $table.key, builder: (column) => i0.ColumnOrderings(column));
i4.$$UserEntityTableOrderingComposer get userId {
final i4.$$UserEntityTableOrderingComposer composer = $composerBuilder(
i0.ColumnOrderings<i3.Uint8List> get value => $composableBuilder(
column: $table.value, builder: (column) => i0.ColumnOrderings(column));
i5.$$UserEntityTableOrderingComposer get userId {
final i5.$$UserEntityTableOrderingComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.userId,
referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i4.$UserEntityTable>('user_entity'),
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i4.$$UserEntityTableOrderingComposer(
i5.$$UserEntityTableOrderingComposer(
$db: $db,
$table: i5.ReadDatabaseContainer($db)
.resultSet<i4.$UserEntityTable>('user_entity'),
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
@ -139,24 +149,27 @@ class $$UserMetadataEntityTableAnnotationComposer
super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer,
});
i0.GeneratedColumnWithTypeConverter<i2.UserPreferences, String>
get preferences => $composableBuilder(
column: $table.preferences, builder: (column) => column);
i0.GeneratedColumnWithTypeConverter<i2.UserMetadataKey, int> get key =>
$composableBuilder(column: $table.key, builder: (column) => column);
i4.$$UserEntityTableAnnotationComposer get userId {
final i4.$$UserEntityTableAnnotationComposer composer = $composerBuilder(
i0.GeneratedColumnWithTypeConverter<Map<String, Object?>, i3.Uint8List>
get value =>
$composableBuilder(column: $table.value, builder: (column) => column);
i5.$$UserEntityTableAnnotationComposer get userId {
final i5.$$UserEntityTableAnnotationComposer composer = $composerBuilder(
composer: this,
getCurrentColumn: (t) => t.userId,
referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i4.$UserEntityTable>('user_entity'),
referencedTable: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id,
builder: (joinBuilder,
{$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) =>
i4.$$UserEntityTableAnnotationComposer(
i5.$$UserEntityTableAnnotationComposer(
$db: $db,
$table: i5.ReadDatabaseContainer($db)
.resultSet<i4.$UserEntityTable>('user_entity'),
$table: i6.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer:
@ -193,19 +206,23 @@ class $$UserMetadataEntityTableTableManager extends i0.RootTableManager<
$db: db, $table: table),
updateCompanionCallback: ({
i0.Value<String> userId = const i0.Value.absent(),
i0.Value<i2.UserPreferences> preferences = const i0.Value.absent(),
i0.Value<i2.UserMetadataKey> key = const i0.Value.absent(),
i0.Value<Map<String, Object?>> value = const i0.Value.absent(),
}) =>
i1.UserMetadataEntityCompanion(
userId: userId,
preferences: preferences,
key: key,
value: value,
),
createCompanionCallback: ({
required String userId,
required i2.UserPreferences preferences,
required i2.UserMetadataKey key,
required Map<String, Object?> value,
}) =>
i1.UserMetadataEntityCompanion.insert(
userId: userId,
preferences: preferences,
key: key,
value: value,
),
withReferenceMapper: (p0) => p0
.map((e) => (
@ -266,7 +283,7 @@ typedef $$UserMetadataEntityTableProcessedTableManager
i1.UserMetadataEntityData,
i0.PrefetchHooks Function({bool userId})>;
class $UserMetadataEntityTable extends i3.UserMetadataEntity
class $UserMetadataEntityTable extends i4.UserMetadataEntity
with i0.TableInfo<$UserMetadataEntityTable, i1.UserMetadataEntityData> {
@override
final i0.GeneratedDatabase attachedDatabase;
@ -282,14 +299,20 @@ class $UserMetadataEntityTable extends i3.UserMetadataEntity
defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'REFERENCES user_entity (id) ON DELETE CASCADE'));
@override
late final i0.GeneratedColumnWithTypeConverter<i2.UserPreferences, String>
preferences = i0.GeneratedColumn<String>(
'preferences', aliasedName, false,
type: i0.DriftSqlType.string, requiredDuringInsert: true)
.withConverter<i2.UserPreferences>(
i1.$UserMetadataEntityTable.$converterpreferences);
late final i0.GeneratedColumnWithTypeConverter<i2.UserMetadataKey, int> key =
i0.GeneratedColumn<int>('key', aliasedName, false,
type: i0.DriftSqlType.int, requiredDuringInsert: true)
.withConverter<i2.UserMetadataKey>(
i1.$UserMetadataEntityTable.$converterkey);
@override
List<i0.GeneratedColumn> get $columns => [userId, preferences];
late final i0
.GeneratedColumnWithTypeConverter<Map<String, Object?>, i3.Uint8List>
value = i0.GeneratedColumn<i3.Uint8List>('value', aliasedName, false,
type: i0.DriftSqlType.blob, requiredDuringInsert: true)
.withConverter<Map<String, Object?>>(
i1.$UserMetadataEntityTable.$convertervalue);
@override
List<i0.GeneratedColumn> get $columns => [userId, key, value];
@override
String get aliasedName => _alias ?? actualTableName;
@override
@ -311,7 +334,7 @@ class $UserMetadataEntityTable extends i3.UserMetadataEntity
}
@override
Set<i0.GeneratedColumn> get $primaryKey => {userId};
Set<i0.GeneratedColumn> get $primaryKey => {userId, key};
@override
i1.UserMetadataEntityData map(Map<String, dynamic> data,
{String? tablePrefix}) {
@ -319,9 +342,12 @@ class $UserMetadataEntityTable extends i3.UserMetadataEntity
return i1.UserMetadataEntityData(
userId: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}user_id'])!,
preferences: i1.$UserMetadataEntityTable.$converterpreferences.fromSql(
attachedDatabase.typeMapping.read(
i0.DriftSqlType.string, data['${effectivePrefix}preferences'])!),
key: i1.$UserMetadataEntityTable.$converterkey.fromSql(attachedDatabase
.typeMapping
.read(i0.DriftSqlType.int, data['${effectivePrefix}key'])!),
value: i1.$UserMetadataEntityTable.$convertervalue.fromSql(
attachedDatabase.typeMapping
.read(i0.DriftSqlType.blob, data['${effectivePrefix}value'])!),
);
}
@ -330,8 +356,11 @@ class $UserMetadataEntityTable extends i3.UserMetadataEntity
return $UserMetadataEntityTable(attachedDatabase, alias);
}
static i0.JsonTypeConverter2<i2.UserPreferences, String, Object?>
$converterpreferences = i3.userPreferenceConverter;
static i0.JsonTypeConverter2<i2.UserMetadataKey, int, int> $converterkey =
const i0.EnumIndexConverter<i2.UserMetadataKey>(
i2.UserMetadataKey.values);
static i0.JsonTypeConverter2<Map<String, Object?>, i3.Uint8List, Object?>
$convertervalue = i4.userMetadataConverter;
@override
bool get withoutRowId => true;
@override
@ -341,16 +370,21 @@ class $UserMetadataEntityTable extends i3.UserMetadataEntity
class UserMetadataEntityData extends i0.DataClass
implements i0.Insertable<i1.UserMetadataEntityData> {
final String userId;
final i2.UserPreferences preferences;
final i2.UserMetadataKey key;
final Map<String, Object?> value;
const UserMetadataEntityData(
{required this.userId, required this.preferences});
{required this.userId, required this.key, required this.value});
@override
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{};
map['user_id'] = i0.Variable<String>(userId);
{
map['preferences'] = i0.Variable<String>(
i1.$UserMetadataEntityTable.$converterpreferences.toSql(preferences));
map['key'] = i0.Variable<int>(
i1.$UserMetadataEntityTable.$converterkey.toSql(key));
}
{
map['value'] = i0.Variable<i3.Uint8List>(
i1.$UserMetadataEntityTable.$convertervalue.toSql(value));
}
return map;
}
@ -360,8 +394,10 @@ class UserMetadataEntityData extends i0.DataClass
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return UserMetadataEntityData(
userId: serializer.fromJson<String>(json['userId']),
preferences: i1.$UserMetadataEntityTable.$converterpreferences
.fromJson(serializer.fromJson<Object?>(json['preferences'])),
key: i1.$UserMetadataEntityTable.$converterkey
.fromJson(serializer.fromJson<int>(json['key'])),
value: i1.$UserMetadataEntityTable.$convertervalue
.fromJson(serializer.fromJson<Object?>(json['value'])),
);
}
@override
@ -369,24 +405,28 @@ class UserMetadataEntityData extends i0.DataClass
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{
'userId': serializer.toJson<String>(userId),
'preferences': serializer.toJson<Object?>(i1
.$UserMetadataEntityTable.$converterpreferences
.toJson(preferences)),
'key': serializer
.toJson<int>(i1.$UserMetadataEntityTable.$converterkey.toJson(key)),
'value': serializer.toJson<Object?>(
i1.$UserMetadataEntityTable.$convertervalue.toJson(value)),
};
}
i1.UserMetadataEntityData copyWith(
{String? userId, i2.UserPreferences? preferences}) =>
{String? userId,
i2.UserMetadataKey? key,
Map<String, Object?>? value}) =>
i1.UserMetadataEntityData(
userId: userId ?? this.userId,
preferences: preferences ?? this.preferences,
key: key ?? this.key,
value: value ?? this.value,
);
UserMetadataEntityData copyWithCompanion(
i1.UserMetadataEntityCompanion data) {
return UserMetadataEntityData(
userId: data.userId.present ? data.userId.value : this.userId,
preferences:
data.preferences.present ? data.preferences.value : this.preferences,
key: data.key.present ? data.key.value : this.key,
value: data.value.present ? data.value.value : this.value,
);
}
@ -394,49 +434,60 @@ class UserMetadataEntityData extends i0.DataClass
String toString() {
return (StringBuffer('UserMetadataEntityData(')
..write('userId: $userId, ')
..write('preferences: $preferences')
..write('key: $key, ')
..write('value: $value')
..write(')'))
.toString();
}
@override
int get hashCode => Object.hash(userId, preferences);
int get hashCode => Object.hash(userId, key, value);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is i1.UserMetadataEntityData &&
other.userId == this.userId &&
other.preferences == this.preferences);
other.key == this.key &&
other.value == this.value);
}
class UserMetadataEntityCompanion
extends i0.UpdateCompanion<i1.UserMetadataEntityData> {
final i0.Value<String> userId;
final i0.Value<i2.UserPreferences> preferences;
final i0.Value<i2.UserMetadataKey> key;
final i0.Value<Map<String, Object?>> value;
const UserMetadataEntityCompanion({
this.userId = const i0.Value.absent(),
this.preferences = const i0.Value.absent(),
this.key = const i0.Value.absent(),
this.value = const i0.Value.absent(),
});
UserMetadataEntityCompanion.insert({
required String userId,
required i2.UserPreferences preferences,
required i2.UserMetadataKey key,
required Map<String, Object?> value,
}) : userId = i0.Value(userId),
preferences = i0.Value(preferences);
key = i0.Value(key),
value = i0.Value(value);
static i0.Insertable<i1.UserMetadataEntityData> custom({
i0.Expression<String>? userId,
i0.Expression<String>? preferences,
i0.Expression<int>? key,
i0.Expression<i3.Uint8List>? value,
}) {
return i0.RawValuesInsertable({
if (userId != null) 'user_id': userId,
if (preferences != null) 'preferences': preferences,
if (key != null) 'key': key,
if (value != null) 'value': value,
});
}
i1.UserMetadataEntityCompanion copyWith(
{i0.Value<String>? userId, i0.Value<i2.UserPreferences>? preferences}) {
{i0.Value<String>? userId,
i0.Value<i2.UserMetadataKey>? key,
i0.Value<Map<String, Object?>>? value}) {
return i1.UserMetadataEntityCompanion(
userId: userId ?? this.userId,
preferences: preferences ?? this.preferences,
key: key ?? this.key,
value: value ?? this.value,
);
}
@ -446,10 +497,13 @@ class UserMetadataEntityCompanion
if (userId.present) {
map['user_id'] = i0.Variable<String>(userId.value);
}
if (preferences.present) {
map['preferences'] = i0.Variable<String>(i1
.$UserMetadataEntityTable.$converterpreferences
.toSql(preferences.value));
if (key.present) {
map['key'] = i0.Variable<int>(
i1.$UserMetadataEntityTable.$converterkey.toSql(key.value));
}
if (value.present) {
map['value'] = i0.Variable<i3.Uint8List>(
i1.$UserMetadataEntityTable.$convertervalue.toSql(value.value));
}
return map;
}
@ -458,7 +512,8 @@ class UserMetadataEntityCompanion
String toString() {
return (StringBuffer('UserMetadataEntityCompanion(')
..write('userId: $userId, ')
..write('preferences: $preferences')
..write('key: $key, ')
..write('value: $value')
..write(')'))
.toString();
}

View File

@ -56,6 +56,7 @@ class SyncApiRepository {
SyncRequestType.memoryToAssetsV1,
SyncRequestType.stacksV1,
SyncRequestType.partnerStacksV1,
SyncRequestType.userMetadataV1,
],
).toJson(),
);
@ -170,6 +171,8 @@ const _kResponseMap = <SyncEntityType, Function(Object)>{
SyncEntityType.partnerStackV1: SyncStackV1.fromJson,
SyncEntityType.partnerStackBackfillV1: SyncStackV1.fromJson,
SyncEntityType.partnerStackDeleteV1: SyncStackDeleteV1.fromJson,
SyncEntityType.userMetadataV1: SyncUserMetadataV1.fromJson,
SyncEntityType.userMetadataDeleteV1: SyncUserMetadataDeleteV1.fromJson,
};
class _SyncAckV1 {

View File

@ -4,6 +4,7 @@ import 'package:drift/drift.dart';
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/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';
@ -14,6 +15,7 @@ import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.d
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/stack.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:logging/logging.dart';
import 'package:openapi/api.dart' as api show AssetVisibility, AlbumUserRole;
@ -461,6 +463,53 @@ class SyncStreamRepository extends DriftDatabaseRepository {
rethrow;
}
}
Future<void> updateUserMetadatasV1(
Iterable<SyncUserMetadataV1> data,
) async {
try {
await _db.batch((batch) {
for (final userMetadata in data) {
final companion = UserMetadataEntityCompanion(
value: Value(userMetadata.value as Map<String, Object?>),
);
batch.insert(
_db.userMetadataEntity,
companion.copyWith(
userId: Value(userMetadata.userId),
key: Value(userMetadata.key.toUserMetadataKey()),
),
onConflict: DoUpdate((_) => companion),
);
}
});
} catch (error, stack) {
_logger.severe('Error: deleteUserMetadatasV1', error, stack);
rethrow;
}
}
Future<void> deleteUserMetadatasV1(
Iterable<SyncUserMetadataDeleteV1> data,
) async {
try {
await _db.batch((batch) {
for (final userMetadata in data) {
batch.delete(
_db.userMetadataEntity,
UserMetadataEntityCompanion(
userId: Value(userMetadata.userId),
key: Value(userMetadata.key.toUserMetadataKey()),
),
);
}
});
} catch (error, stack) {
_logger.severe('Error: deleteUserMetadatasV1', error, stack);
rethrow;
}
}
}
extension on AssetTypeEnum {
@ -506,6 +555,15 @@ extension on api.AssetVisibility {
};
}
extension on String {
UserMetadataKey toUserMetadataKey() => switch (this) {
"onboarding" => UserMetadataKey.onboarding,
"preferences" => UserMetadataKey.preferences,
"license" => UserMetadataKey.license,
_ => throw Exception('Unknown UserMetadataKey value: $this'),
};
}
extension on String {
Duration? toDuration() {
try {

View File

@ -0,0 +1,38 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
class DriftUserMetadataRepository extends DriftDatabaseRepository {
final Drift _db;
const DriftUserMetadataRepository(this._db) : super(_db);
Future<List<UserMetadata>> getUserMetadata(String userId) {
final query = _db.userMetadataEntity.select()
..where((e) => e.userId.equals(userId));
return query.map((userMetadata) {
return userMetadata.toDto();
}).get();
}
}
extension on UserMetadataEntityData {
UserMetadata toDto() => switch (key) {
UserMetadataKey.onboarding => UserMetadata(
userId: userId,
key: key,
onboarding: Onboarding.fromMap(value),
),
UserMetadataKey.preferences => UserMetadata(
userId: userId,
key: key,
preferences: Preferences.fromMap(value),
),
UserMetadataKey.license => UserMetadata(
userId: userId,
key: key,
license: License.fromMap(value),
),
};
}