1
0
mirror of https://github.com/immich-app/immich.git synced 2025-07-07 06:16:05 +02:00

feat(mobile): remote asset & exif sync (#18756)

* feat(mobile): remote asset & exif sync

* add visibility and update constraints

* chore: generate drifts

* update ids to be strings

* clear remote entities on logout

* reset sqlite button

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong
2025-06-03 21:31:50 +05:30
committed by GitHub
parent edae9c2d3d
commit b4a798c39f
26 changed files with 3196 additions and 302 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,17 @@
part of 'base_asset.model.dart'; part of 'base_asset.model.dart';
enum AssetVisibility {
timeline,
hidden,
archive,
locked,
}
// Model for an asset stored in the server // Model for an asset stored in the server
class Asset extends BaseAsset { class Asset extends BaseAsset {
final String id; final String id;
final String? localId; final String? localId;
final AssetVisibility visibility;
const Asset({ const Asset({
required this.id, required this.id,
@ -17,6 +25,7 @@ class Asset extends BaseAsset {
super.height, super.height,
super.durationInSeconds, super.durationInSeconds,
super.isFavorite = false, super.isFavorite = false,
this.visibility = AssetVisibility.timeline,
}); });
@override @override
@ -32,6 +41,7 @@ class Asset extends BaseAsset {
durationInSeconds: ${durationInSeconds ?? "<NA>"}, durationInSeconds: ${durationInSeconds ?? "<NA>"},
localId: ${localId ?? "<NA>"}, localId: ${localId ?? "<NA>"},
isFavorite: $isFavorite, isFavorite: $isFavorite,
visibility: $visibility,
}'''; }''';
} }
@ -39,9 +49,13 @@ class Asset extends BaseAsset {
bool operator ==(Object other) { bool operator ==(Object other) {
if (other is! Asset) return false; if (other is! Asset) return false;
if (identical(this, other)) return true; if (identical(this, other)) return true;
return super == other && id == other.id && localId == other.localId; return super == other &&
id == other.id &&
localId == other.localId &&
visibility == other.visibility;
} }
@override @override
int get hashCode => super.hashCode ^ id.hashCode ^ localId.hashCode; int get hashCode =>
super.hashCode ^ id.hashCode ^ localId.hashCode ^ visibility.hashCode;
} }

View File

@ -63,7 +63,6 @@ class SyncStreamService {
Iterable<dynamic> data, Iterable<dynamic> data,
) async { ) async {
_logger.fine("Processing sync data for $type of length ${data.length}"); _logger.fine("Processing sync data for $type of length ${data.length}");
// ignore: prefer-switch-expression
switch (type) { switch (type) {
case SyncEntityType.userV1: case SyncEntityType.userV1:
return _syncStreamRepository.updateUsersV1(data.cast()); return _syncStreamRepository.updateUsersV1(data.cast());

View File

@ -1,7 +1,3 @@
import 'dart:typed_data';
import 'package:uuid/parsing.dart';
extension StringExtension on String { extension StringExtension on String {
String capitalize() { String capitalize() {
return split(" ") return split(" ")
@ -33,8 +29,3 @@ extension DurationExtension on String {
return int.parse(this); return int.parse(this);
} }
} }
extension UUIDExtension on String {
Uint8List toUuidByte({bool shouldValidate = false}) =>
UuidParsing.parseAsByteList(this, validate: shouldValidate);
}

View File

@ -1,4 +1,7 @@
import 'package:drift/drift.dart' hide Query;
import 'package:immich_mobile/domain/models/exif.model.dart' as domain; import 'package:immich_mobile/domain/models/exif.model.dart' as domain;
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart';
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
import 'package:immich_mobile/infrastructure/utils/exif.converter.dart'; import 'package:immich_mobile/infrastructure/utils/exif.converter.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
@ -90,3 +93,53 @@ class ExifInfo {
exposureSeconds: exposureSeconds, exposureSeconds: exposureSeconds,
); );
} }
class RemoteExifEntity extends Table with DriftDefaultsMixin {
const RemoteExifEntity();
TextColumn get assetId =>
text().references(RemoteAssetEntity, #id, onDelete: KeyAction.cascade)();
TextColumn get city => text().nullable()();
TextColumn get state => text().nullable()();
TextColumn get country => text().nullable()();
DateTimeColumn get dateTimeOriginal => dateTime().nullable()();
TextColumn get description => text().nullable()();
IntColumn get height => integer().nullable()();
IntColumn get width => integer().nullable()();
TextColumn get exposureTime => text().nullable()();
IntColumn get fNumber => integer().nullable()();
IntColumn get fileSize => integer().nullable()();
IntColumn get focalLength => integer().nullable()();
IntColumn get latitude => integer().nullable()();
IntColumn get longitude => integer().nullable()();
IntColumn get iso => integer().nullable()();
TextColumn get make => text().nullable()();
TextColumn get model => text().nullable()();
TextColumn get orientation => text().nullable()();
TextColumn get timeZone => text().nullable()();
IntColumn get rating => integer().nullable()();
TextColumn get projectionType => text().nullable()();
@override
Set<Column> get primaryKey => {assetId};
}

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@ import 'package:drift/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';
@TableIndex(name: 'local_asset_checksum', columns: {#checksum}) @TableIndex(name: 'idx_local_asset_checksum', columns: {#checksum})
class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin { class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin {
const LocalAssetEntity(); const LocalAssetEntity();

View File

@ -231,8 +231,8 @@ typedef $$LocalAssetEntityTableProcessedTableManager = i0.ProcessedTableManager<
), ),
i1.LocalAssetEntityData, i1.LocalAssetEntityData,
i0.PrefetchHooks Function()>; i0.PrefetchHooks Function()>;
i0.Index get localAssetChecksum => i0.Index('local_asset_checksum', i0.Index get idxLocalAssetChecksum => i0.Index('idx_local_asset_checksum',
'CREATE INDEX local_asset_checksum ON local_asset_entity (checksum)'); 'CREATE INDEX idx_local_asset_checksum ON local_asset_entity (checksum)');
class $LocalAssetEntityTable extends i3.LocalAssetEntity class $LocalAssetEntityTable extends i3.LocalAssetEntity
with i0.TableInfo<$LocalAssetEntityTable, i1.LocalAssetEntityData> { with i0.TableInfo<$LocalAssetEntityTable, i1.LocalAssetEntityData> {

View File

@ -5,11 +5,11 @@ import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
class PartnerEntity extends Table with DriftDefaultsMixin { class PartnerEntity extends Table with DriftDefaultsMixin {
const PartnerEntity(); const PartnerEntity();
BlobColumn get sharedById => TextColumn get sharedById =>
blob().references(UserEntity, #id, onDelete: KeyAction.cascade)(); text().references(UserEntity, #id, onDelete: KeyAction.cascade)();
BlobColumn get sharedWithId => TextColumn get sharedWithId =>
blob().references(UserEntity, #id, onDelete: KeyAction.cascade)(); text().references(UserEntity, #id, onDelete: KeyAction.cascade)();
BoolColumn get inTimeline => boolean().withDefault(const Constant(false))(); BoolColumn get inTimeline => boolean().withDefault(const Constant(false))();

View File

@ -3,24 +3,23 @@
import 'package:drift/drift.dart' as i0; import 'package:drift/drift.dart' as i0;
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart' import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'
as i1; as i1;
import 'dart:typed_data' as i2;
import 'package:immich_mobile/infrastructure/entities/partner.entity.dart' import 'package:immich_mobile/infrastructure/entities/partner.entity.dart'
as i3; as i2;
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4; import 'package:drift/src/runtime/query_builder/query_builder.dart' as i3;
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart' import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
as i5; as i4;
import 'package:drift/internal/modular.dart' as i6; import 'package:drift/internal/modular.dart' as i5;
typedef $$PartnerEntityTableCreateCompanionBuilder = i1.PartnerEntityCompanion typedef $$PartnerEntityTableCreateCompanionBuilder = i1.PartnerEntityCompanion
Function({ Function({
required i2.Uint8List sharedById, required String sharedById,
required i2.Uint8List sharedWithId, required String sharedWithId,
i0.Value<bool> inTimeline, i0.Value<bool> inTimeline,
}); });
typedef $$PartnerEntityTableUpdateCompanionBuilder = i1.PartnerEntityCompanion typedef $$PartnerEntityTableUpdateCompanionBuilder = i1.PartnerEntityCompanion
Function({ Function({
i0.Value<i2.Uint8List> sharedById, i0.Value<String> sharedById,
i0.Value<i2.Uint8List> sharedWithId, i0.Value<String> sharedWithId,
i0.Value<bool> inTimeline, i0.Value<bool> inTimeline,
}); });
@ -29,25 +28,25 @@ final class $$PartnerEntityTableReferences extends i0.BaseReferences<
$$PartnerEntityTableReferences( $$PartnerEntityTableReferences(
super.$_db, super.$_table, super.$_typedResult); super.$_db, super.$_table, super.$_typedResult);
static i5.$UserEntityTable _sharedByIdTable(i0.GeneratedDatabase db) => static i4.$UserEntityTable _sharedByIdTable(i0.GeneratedDatabase db) =>
i6.ReadDatabaseContainer(db) i5.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity') .resultSet<i4.$UserEntityTable>('user_entity')
.createAlias(i0.$_aliasNameGenerator( .createAlias(i0.$_aliasNameGenerator(
i6.ReadDatabaseContainer(db) i5.ReadDatabaseContainer(db)
.resultSet<i1.$PartnerEntityTable>('partner_entity') .resultSet<i1.$PartnerEntityTable>('partner_entity')
.sharedById, .sharedById,
i6.ReadDatabaseContainer(db) i5.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity') .resultSet<i4.$UserEntityTable>('user_entity')
.id)); .id));
i5.$$UserEntityTableProcessedTableManager get sharedById { i4.$$UserEntityTableProcessedTableManager get sharedById {
final $_column = $_itemColumn<i2.Uint8List>('shared_by_id')!; final $_column = $_itemColumn<String>('shared_by_id')!;
final manager = i5 final manager = i4
.$$UserEntityTableTableManager( .$$UserEntityTableTableManager(
$_db, $_db,
i6.ReadDatabaseContainer($_db) i5.ReadDatabaseContainer($_db)
.resultSet<i5.$UserEntityTable>('user_entity')) .resultSet<i4.$UserEntityTable>('user_entity'))
.filter((f) => f.id.sqlEquals($_column)); .filter((f) => f.id.sqlEquals($_column));
final item = $_typedResult.readTableOrNull(_sharedByIdTable($_db)); final item = $_typedResult.readTableOrNull(_sharedByIdTable($_db));
if (item == null) return manager; if (item == null) return manager;
@ -55,25 +54,25 @@ final class $$PartnerEntityTableReferences extends i0.BaseReferences<
manager.$state.copyWith(prefetchedData: [item])); manager.$state.copyWith(prefetchedData: [item]));
} }
static i5.$UserEntityTable _sharedWithIdTable(i0.GeneratedDatabase db) => static i4.$UserEntityTable _sharedWithIdTable(i0.GeneratedDatabase db) =>
i6.ReadDatabaseContainer(db) i5.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity') .resultSet<i4.$UserEntityTable>('user_entity')
.createAlias(i0.$_aliasNameGenerator( .createAlias(i0.$_aliasNameGenerator(
i6.ReadDatabaseContainer(db) i5.ReadDatabaseContainer(db)
.resultSet<i1.$PartnerEntityTable>('partner_entity') .resultSet<i1.$PartnerEntityTable>('partner_entity')
.sharedWithId, .sharedWithId,
i6.ReadDatabaseContainer(db) i5.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity') .resultSet<i4.$UserEntityTable>('user_entity')
.id)); .id));
i5.$$UserEntityTableProcessedTableManager get sharedWithId { i4.$$UserEntityTableProcessedTableManager get sharedWithId {
final $_column = $_itemColumn<i2.Uint8List>('shared_with_id')!; final $_column = $_itemColumn<String>('shared_with_id')!;
final manager = i5 final manager = i4
.$$UserEntityTableTableManager( .$$UserEntityTableTableManager(
$_db, $_db,
i6.ReadDatabaseContainer($_db) i5.ReadDatabaseContainer($_db)
.resultSet<i5.$UserEntityTable>('user_entity')) .resultSet<i4.$UserEntityTable>('user_entity'))
.filter((f) => f.id.sqlEquals($_column)); .filter((f) => f.id.sqlEquals($_column));
final item = $_typedResult.readTableOrNull(_sharedWithIdTable($_db)); final item = $_typedResult.readTableOrNull(_sharedWithIdTable($_db));
if (item == null) return manager; if (item == null) return manager;
@ -94,20 +93,20 @@ class $$PartnerEntityTableFilterComposer
i0.ColumnFilters<bool> get inTimeline => $composableBuilder( i0.ColumnFilters<bool> get inTimeline => $composableBuilder(
column: $table.inTimeline, builder: (column) => i0.ColumnFilters(column)); column: $table.inTimeline, builder: (column) => i0.ColumnFilters(column));
i5.$$UserEntityTableFilterComposer get sharedById { i4.$$UserEntityTableFilterComposer get sharedById {
final i5.$$UserEntityTableFilterComposer composer = $composerBuilder( final i4.$$UserEntityTableFilterComposer composer = $composerBuilder(
composer: this, composer: this,
getCurrentColumn: (t) => t.sharedById, getCurrentColumn: (t) => t.sharedById,
referencedTable: i6.ReadDatabaseContainer($db) referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id, getReferencedColumn: (t) => t.id,
builder: (joinBuilder, builder: (joinBuilder,
{$addJoinBuilderToRootComposer, {$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) => $removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableFilterComposer( i4.$$UserEntityTableFilterComposer(
$db: $db, $db: $db,
$table: i6.ReadDatabaseContainer($db) $table: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder, joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer:
@ -116,20 +115,20 @@ class $$PartnerEntityTableFilterComposer
return composer; return composer;
} }
i5.$$UserEntityTableFilterComposer get sharedWithId { i4.$$UserEntityTableFilterComposer get sharedWithId {
final i5.$$UserEntityTableFilterComposer composer = $composerBuilder( final i4.$$UserEntityTableFilterComposer composer = $composerBuilder(
composer: this, composer: this,
getCurrentColumn: (t) => t.sharedWithId, getCurrentColumn: (t) => t.sharedWithId,
referencedTable: i6.ReadDatabaseContainer($db) referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id, getReferencedColumn: (t) => t.id,
builder: (joinBuilder, builder: (joinBuilder,
{$addJoinBuilderToRootComposer, {$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) => $removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableFilterComposer( i4.$$UserEntityTableFilterComposer(
$db: $db, $db: $db,
$table: i6.ReadDatabaseContainer($db) $table: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder, joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer:
@ -152,20 +151,20 @@ class $$PartnerEntityTableOrderingComposer
column: $table.inTimeline, column: $table.inTimeline,
builder: (column) => i0.ColumnOrderings(column)); builder: (column) => i0.ColumnOrderings(column));
i5.$$UserEntityTableOrderingComposer get sharedById { i4.$$UserEntityTableOrderingComposer get sharedById {
final i5.$$UserEntityTableOrderingComposer composer = $composerBuilder( final i4.$$UserEntityTableOrderingComposer composer = $composerBuilder(
composer: this, composer: this,
getCurrentColumn: (t) => t.sharedById, getCurrentColumn: (t) => t.sharedById,
referencedTable: i6.ReadDatabaseContainer($db) referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id, getReferencedColumn: (t) => t.id,
builder: (joinBuilder, builder: (joinBuilder,
{$addJoinBuilderToRootComposer, {$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) => $removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableOrderingComposer( i4.$$UserEntityTableOrderingComposer(
$db: $db, $db: $db,
$table: i6.ReadDatabaseContainer($db) $table: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder, joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer:
@ -174,20 +173,20 @@ class $$PartnerEntityTableOrderingComposer
return composer; return composer;
} }
i5.$$UserEntityTableOrderingComposer get sharedWithId { i4.$$UserEntityTableOrderingComposer get sharedWithId {
final i5.$$UserEntityTableOrderingComposer composer = $composerBuilder( final i4.$$UserEntityTableOrderingComposer composer = $composerBuilder(
composer: this, composer: this,
getCurrentColumn: (t) => t.sharedWithId, getCurrentColumn: (t) => t.sharedWithId,
referencedTable: i6.ReadDatabaseContainer($db) referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id, getReferencedColumn: (t) => t.id,
builder: (joinBuilder, builder: (joinBuilder,
{$addJoinBuilderToRootComposer, {$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) => $removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableOrderingComposer( i4.$$UserEntityTableOrderingComposer(
$db: $db, $db: $db,
$table: i6.ReadDatabaseContainer($db) $table: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder, joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer:
@ -209,20 +208,20 @@ class $$PartnerEntityTableAnnotationComposer
i0.GeneratedColumn<bool> get inTimeline => $composableBuilder( i0.GeneratedColumn<bool> get inTimeline => $composableBuilder(
column: $table.inTimeline, builder: (column) => column); column: $table.inTimeline, builder: (column) => column);
i5.$$UserEntityTableAnnotationComposer get sharedById { i4.$$UserEntityTableAnnotationComposer get sharedById {
final i5.$$UserEntityTableAnnotationComposer composer = $composerBuilder( final i4.$$UserEntityTableAnnotationComposer composer = $composerBuilder(
composer: this, composer: this,
getCurrentColumn: (t) => t.sharedById, getCurrentColumn: (t) => t.sharedById,
referencedTable: i6.ReadDatabaseContainer($db) referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id, getReferencedColumn: (t) => t.id,
builder: (joinBuilder, builder: (joinBuilder,
{$addJoinBuilderToRootComposer, {$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) => $removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableAnnotationComposer( i4.$$UserEntityTableAnnotationComposer(
$db: $db, $db: $db,
$table: i6.ReadDatabaseContainer($db) $table: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder, joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer:
@ -231,20 +230,20 @@ class $$PartnerEntityTableAnnotationComposer
return composer; return composer;
} }
i5.$$UserEntityTableAnnotationComposer get sharedWithId { i4.$$UserEntityTableAnnotationComposer get sharedWithId {
final i5.$$UserEntityTableAnnotationComposer composer = $composerBuilder( final i4.$$UserEntityTableAnnotationComposer composer = $composerBuilder(
composer: this, composer: this,
getCurrentColumn: (t) => t.sharedWithId, getCurrentColumn: (t) => t.sharedWithId,
referencedTable: i6.ReadDatabaseContainer($db) referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id, getReferencedColumn: (t) => t.id,
builder: (joinBuilder, builder: (joinBuilder,
{$addJoinBuilderToRootComposer, {$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) => $removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableAnnotationComposer( i4.$$UserEntityTableAnnotationComposer(
$db: $db, $db: $db,
$table: i6.ReadDatabaseContainer($db) $table: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder, joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer:
@ -278,8 +277,8 @@ class $$PartnerEntityTableTableManager extends i0.RootTableManager<
createComputedFieldComposer: () => createComputedFieldComposer: () =>
i1.$$PartnerEntityTableAnnotationComposer($db: db, $table: table), i1.$$PartnerEntityTableAnnotationComposer($db: db, $table: table),
updateCompanionCallback: ({ updateCompanionCallback: ({
i0.Value<i2.Uint8List> sharedById = const i0.Value.absent(), i0.Value<String> sharedById = const i0.Value.absent(),
i0.Value<i2.Uint8List> sharedWithId = const i0.Value.absent(), i0.Value<String> sharedWithId = const i0.Value.absent(),
i0.Value<bool> inTimeline = const i0.Value.absent(), i0.Value<bool> inTimeline = const i0.Value.absent(),
}) => }) =>
i1.PartnerEntityCompanion( i1.PartnerEntityCompanion(
@ -288,8 +287,8 @@ class $$PartnerEntityTableTableManager extends i0.RootTableManager<
inTimeline: inTimeline, inTimeline: inTimeline,
), ),
createCompanionCallback: ({ createCompanionCallback: ({
required i2.Uint8List sharedById, required String sharedById,
required i2.Uint8List sharedWithId, required String sharedWithId,
i0.Value<bool> inTimeline = const i0.Value.absent(), i0.Value<bool> inTimeline = const i0.Value.absent(),
}) => }) =>
i1.PartnerEntityCompanion.insert( i1.PartnerEntityCompanion.insert(
@ -366,7 +365,7 @@ typedef $$PartnerEntityTableProcessedTableManager = i0.ProcessedTableManager<
i1.PartnerEntityData, i1.PartnerEntityData,
i0.PrefetchHooks Function({bool sharedById, bool sharedWithId})>; i0.PrefetchHooks Function({bool sharedById, bool sharedWithId})>;
class $PartnerEntityTable extends i3.PartnerEntity class $PartnerEntityTable extends i2.PartnerEntity
with i0.TableInfo<$PartnerEntityTable, i1.PartnerEntityData> { with i0.TableInfo<$PartnerEntityTable, i1.PartnerEntityData> {
@override @override
final i0.GeneratedDatabase attachedDatabase; final i0.GeneratedDatabase attachedDatabase;
@ -375,18 +374,18 @@ class $PartnerEntityTable extends i3.PartnerEntity
static const i0.VerificationMeta _sharedByIdMeta = static const i0.VerificationMeta _sharedByIdMeta =
const i0.VerificationMeta('sharedById'); const i0.VerificationMeta('sharedById');
@override @override
late final i0.GeneratedColumn<i2.Uint8List> sharedById = late final i0.GeneratedColumn<String> sharedById = i0.GeneratedColumn<String>(
i0.GeneratedColumn<i2.Uint8List>('shared_by_id', aliasedName, false, 'shared_by_id', aliasedName, false,
type: i0.DriftSqlType.blob, type: i0.DriftSqlType.string,
requiredDuringInsert: true, requiredDuringInsert: true,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways( defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'REFERENCES user_entity (id) ON DELETE CASCADE')); 'REFERENCES user_entity (id) ON DELETE CASCADE'));
static const i0.VerificationMeta _sharedWithIdMeta = static const i0.VerificationMeta _sharedWithIdMeta =
const i0.VerificationMeta('sharedWithId'); const i0.VerificationMeta('sharedWithId');
@override @override
late final i0.GeneratedColumn<i2.Uint8List> sharedWithId = late final i0.GeneratedColumn<String> sharedWithId =
i0.GeneratedColumn<i2.Uint8List>('shared_with_id', aliasedName, false, i0.GeneratedColumn<String>('shared_with_id', aliasedName, false,
type: i0.DriftSqlType.blob, type: i0.DriftSqlType.string,
requiredDuringInsert: true, requiredDuringInsert: true,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways( defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'REFERENCES user_entity (id) ON DELETE CASCADE')); 'REFERENCES user_entity (id) ON DELETE CASCADE'));
@ -399,7 +398,7 @@ class $PartnerEntityTable extends i3.PartnerEntity
requiredDuringInsert: false, requiredDuringInsert: false,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways( defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'CHECK ("in_timeline" IN (0, 1))'), 'CHECK ("in_timeline" IN (0, 1))'),
defaultValue: const i4.Constant(false)); defaultValue: const i3.Constant(false));
@override @override
List<i0.GeneratedColumn> get $columns => List<i0.GeneratedColumn> get $columns =>
[sharedById, sharedWithId, inTimeline]; [sharedById, sharedWithId, inTimeline];
@ -445,10 +444,10 @@ class $PartnerEntityTable extends i3.PartnerEntity
i1.PartnerEntityData map(Map<String, dynamic> data, {String? tablePrefix}) { i1.PartnerEntityData map(Map<String, dynamic> data, {String? tablePrefix}) {
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.PartnerEntityData( return i1.PartnerEntityData(
sharedById: attachedDatabase.typeMapping sharedById: attachedDatabase.typeMapping.read(
.read(i0.DriftSqlType.blob, data['${effectivePrefix}shared_by_id'])!, i0.DriftSqlType.string, data['${effectivePrefix}shared_by_id'])!,
sharedWithId: attachedDatabase.typeMapping.read( sharedWithId: attachedDatabase.typeMapping.read(
i0.DriftSqlType.blob, data['${effectivePrefix}shared_with_id'])!, i0.DriftSqlType.string, data['${effectivePrefix}shared_with_id'])!,
inTimeline: attachedDatabase.typeMapping inTimeline: attachedDatabase.typeMapping
.read(i0.DriftSqlType.bool, data['${effectivePrefix}in_timeline'])!, .read(i0.DriftSqlType.bool, data['${effectivePrefix}in_timeline'])!,
); );
@ -467,8 +466,8 @@ class $PartnerEntityTable extends i3.PartnerEntity
class PartnerEntityData extends i0.DataClass class PartnerEntityData extends i0.DataClass
implements i0.Insertable<i1.PartnerEntityData> { implements i0.Insertable<i1.PartnerEntityData> {
final i2.Uint8List sharedById; final String sharedById;
final i2.Uint8List sharedWithId; final String sharedWithId;
final bool inTimeline; final bool inTimeline;
const PartnerEntityData( const PartnerEntityData(
{required this.sharedById, {required this.sharedById,
@ -477,8 +476,8 @@ class PartnerEntityData extends i0.DataClass
@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['shared_by_id'] = i0.Variable<i2.Uint8List>(sharedById); map['shared_by_id'] = i0.Variable<String>(sharedById);
map['shared_with_id'] = i0.Variable<i2.Uint8List>(sharedWithId); map['shared_with_id'] = i0.Variable<String>(sharedWithId);
map['in_timeline'] = i0.Variable<bool>(inTimeline); map['in_timeline'] = i0.Variable<bool>(inTimeline);
return map; return map;
} }
@ -487,8 +486,8 @@ class PartnerEntityData extends i0.DataClass
{i0.ValueSerializer? serializer}) { {i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer; serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return PartnerEntityData( return PartnerEntityData(
sharedById: serializer.fromJson<i2.Uint8List>(json['sharedById']), sharedById: serializer.fromJson<String>(json['sharedById']),
sharedWithId: serializer.fromJson<i2.Uint8List>(json['sharedWithId']), sharedWithId: serializer.fromJson<String>(json['sharedWithId']),
inTimeline: serializer.fromJson<bool>(json['inTimeline']), inTimeline: serializer.fromJson<bool>(json['inTimeline']),
); );
} }
@ -496,16 +495,14 @@ class PartnerEntityData extends i0.DataClass
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) { Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer; serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{ return <String, dynamic>{
'sharedById': serializer.toJson<i2.Uint8List>(sharedById), 'sharedById': serializer.toJson<String>(sharedById),
'sharedWithId': serializer.toJson<i2.Uint8List>(sharedWithId), 'sharedWithId': serializer.toJson<String>(sharedWithId),
'inTimeline': serializer.toJson<bool>(inTimeline), 'inTimeline': serializer.toJson<bool>(inTimeline),
}; };
} }
i1.PartnerEntityData copyWith( i1.PartnerEntityData copyWith(
{i2.Uint8List? sharedById, {String? sharedById, String? sharedWithId, bool? inTimeline}) =>
i2.Uint8List? sharedWithId,
bool? inTimeline}) =>
i1.PartnerEntityData( i1.PartnerEntityData(
sharedById: sharedById ?? this.sharedById, sharedById: sharedById ?? this.sharedById,
sharedWithId: sharedWithId ?? this.sharedWithId, sharedWithId: sharedWithId ?? this.sharedWithId,
@ -534,20 +531,19 @@ class PartnerEntityData extends i0.DataClass
} }
@override @override
int get hashCode => Object.hash(i0.$driftBlobEquality.hash(sharedById), int get hashCode => Object.hash(sharedById, sharedWithId, inTimeline);
i0.$driftBlobEquality.hash(sharedWithId), inTimeline);
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
(other is i1.PartnerEntityData && (other is i1.PartnerEntityData &&
i0.$driftBlobEquality.equals(other.sharedById, this.sharedById) && other.sharedById == this.sharedById &&
i0.$driftBlobEquality.equals(other.sharedWithId, this.sharedWithId) && other.sharedWithId == this.sharedWithId &&
other.inTimeline == this.inTimeline); other.inTimeline == this.inTimeline);
} }
class PartnerEntityCompanion extends i0.UpdateCompanion<i1.PartnerEntityData> { class PartnerEntityCompanion extends i0.UpdateCompanion<i1.PartnerEntityData> {
final i0.Value<i2.Uint8List> sharedById; final i0.Value<String> sharedById;
final i0.Value<i2.Uint8List> sharedWithId; final i0.Value<String> sharedWithId;
final i0.Value<bool> inTimeline; final i0.Value<bool> inTimeline;
const PartnerEntityCompanion({ const PartnerEntityCompanion({
this.sharedById = const i0.Value.absent(), this.sharedById = const i0.Value.absent(),
@ -555,14 +551,14 @@ class PartnerEntityCompanion extends i0.UpdateCompanion<i1.PartnerEntityData> {
this.inTimeline = const i0.Value.absent(), this.inTimeline = const i0.Value.absent(),
}); });
PartnerEntityCompanion.insert({ PartnerEntityCompanion.insert({
required i2.Uint8List sharedById, required String sharedById,
required i2.Uint8List sharedWithId, required String sharedWithId,
this.inTimeline = const i0.Value.absent(), this.inTimeline = const i0.Value.absent(),
}) : sharedById = i0.Value(sharedById), }) : sharedById = i0.Value(sharedById),
sharedWithId = i0.Value(sharedWithId); sharedWithId = i0.Value(sharedWithId);
static i0.Insertable<i1.PartnerEntityData> custom({ static i0.Insertable<i1.PartnerEntityData> custom({
i0.Expression<i2.Uint8List>? sharedById, i0.Expression<String>? sharedById,
i0.Expression<i2.Uint8List>? sharedWithId, i0.Expression<String>? sharedWithId,
i0.Expression<bool>? inTimeline, i0.Expression<bool>? inTimeline,
}) { }) {
return i0.RawValuesInsertable({ return i0.RawValuesInsertable({
@ -573,8 +569,8 @@ class PartnerEntityCompanion extends i0.UpdateCompanion<i1.PartnerEntityData> {
} }
i1.PartnerEntityCompanion copyWith( i1.PartnerEntityCompanion copyWith(
{i0.Value<i2.Uint8List>? sharedById, {i0.Value<String>? sharedById,
i0.Value<i2.Uint8List>? sharedWithId, i0.Value<String>? sharedWithId,
i0.Value<bool>? inTimeline}) { i0.Value<bool>? inTimeline}) {
return i1.PartnerEntityCompanion( return i1.PartnerEntityCompanion(
sharedById: sharedById ?? this.sharedById, sharedById: sharedById ?? this.sharedById,
@ -587,10 +583,10 @@ class PartnerEntityCompanion extends i0.UpdateCompanion<i1.PartnerEntityData> {
Map<String, i0.Expression> toColumns(bool nullToAbsent) { Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{}; final map = <String, i0.Expression>{};
if (sharedById.present) { if (sharedById.present) {
map['shared_by_id'] = i0.Variable<i2.Uint8List>(sharedById.value); map['shared_by_id'] = i0.Variable<String>(sharedById.value);
} }
if (sharedWithId.present) { if (sharedWithId.present) {
map['shared_with_id'] = i0.Variable<i2.Uint8List>(sharedWithId.value); map['shared_with_id'] = i0.Variable<String>(sharedWithId.value);
} }
if (inTimeline.present) { if (inTimeline.present) {
map['in_timeline'] = i0.Variable<bool>(inTimeline.value); map['in_timeline'] = i0.Variable<bool>(inTimeline.value);

View File

@ -0,0 +1,35 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart';
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
@TableIndex(
name: 'UQ_remote_asset_owner_checksum',
columns: {#checksum, #ownerId},
unique: true,
)
class RemoteAssetEntity extends Table
with DriftDefaultsMixin, AssetEntityMixin {
const RemoteAssetEntity();
TextColumn get id => text()();
TextColumn get checksum => text()();
BoolColumn get isFavorite => boolean().withDefault(const Constant(false))();
TextColumn get ownerId =>
text().references(UserEntity, #id, onDelete: KeyAction.cascade)();
DateTimeColumn get localDateTime => dateTime().nullable()();
TextColumn get thumbHash => text().nullable()();
DateTimeColumn get deletedAt => dateTime().nullable()();
IntColumn get visibility => intEnum<AssetVisibility>()();
@override
Set<Column> get primaryKey => {id};
}

File diff suppressed because it is too large Load Diff

View File

@ -78,7 +78,7 @@ class User {
class UserEntity extends Table with DriftDefaultsMixin { class UserEntity extends Table with DriftDefaultsMixin {
const UserEntity(); const UserEntity();
BlobColumn get id => blob()(); TextColumn get id => text()();
TextColumn get name => text()(); TextColumn get name => text()();
BoolColumn get isAdmin => boolean().withDefault(const Constant(false))(); BoolColumn get isAdmin => boolean().withDefault(const Constant(false))();
TextColumn get email => text()(); TextColumn get email => text()();

View File

@ -3,13 +3,12 @@
import 'package:drift/drift.dart' as i0; import 'package:drift/drift.dart' as i0;
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart' import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
as i1; as i1;
import 'dart:typed_data' as i2; import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as i2;
import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as i3; import 'package:drift/src/runtime/query_builder/query_builder.dart' as i3;
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4;
typedef $$UserEntityTableCreateCompanionBuilder = i1.UserEntityCompanion typedef $$UserEntityTableCreateCompanionBuilder = i1.UserEntityCompanion
Function({ Function({
required i2.Uint8List id, required String id,
required String name, required String name,
i0.Value<bool> isAdmin, i0.Value<bool> isAdmin,
required String email, required String email,
@ -20,7 +19,7 @@ typedef $$UserEntityTableCreateCompanionBuilder = i1.UserEntityCompanion
}); });
typedef $$UserEntityTableUpdateCompanionBuilder = i1.UserEntityCompanion typedef $$UserEntityTableUpdateCompanionBuilder = i1.UserEntityCompanion
Function({ Function({
i0.Value<i2.Uint8List> id, i0.Value<String> id,
i0.Value<String> name, i0.Value<String> name,
i0.Value<bool> isAdmin, i0.Value<bool> isAdmin,
i0.Value<String> email, i0.Value<String> email,
@ -39,7 +38,7 @@ class $$UserEntityTableFilterComposer
super.$addJoinBuilderToRootComposer, super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
i0.ColumnFilters<i2.Uint8List> get id => $composableBuilder( i0.ColumnFilters<String> get id => $composableBuilder(
column: $table.id, builder: (column) => i0.ColumnFilters(column)); column: $table.id, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<String> get name => $composableBuilder( i0.ColumnFilters<String> get name => $composableBuilder(
@ -76,7 +75,7 @@ class $$UserEntityTableOrderingComposer
super.$addJoinBuilderToRootComposer, super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
i0.ColumnOrderings<i2.Uint8List> get id => $composableBuilder( i0.ColumnOrderings<String> get id => $composableBuilder(
column: $table.id, builder: (column) => i0.ColumnOrderings(column)); column: $table.id, builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<String> get name => $composableBuilder( i0.ColumnOrderings<String> get name => $composableBuilder(
@ -114,7 +113,7 @@ class $$UserEntityTableAnnotationComposer
super.$addJoinBuilderToRootComposer, super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
i0.GeneratedColumn<i2.Uint8List> get id => i0.GeneratedColumn<String> get id =>
$composableBuilder(column: $table.id, builder: (column) => column); $composableBuilder(column: $table.id, builder: (column) => column);
i0.GeneratedColumn<String> get name => i0.GeneratedColumn<String> get name =>
@ -167,7 +166,7 @@ class $$UserEntityTableTableManager extends i0.RootTableManager<
createComputedFieldComposer: () => createComputedFieldComposer: () =>
i1.$$UserEntityTableAnnotationComposer($db: db, $table: table), i1.$$UserEntityTableAnnotationComposer($db: db, $table: table),
updateCompanionCallback: ({ updateCompanionCallback: ({
i0.Value<i2.Uint8List> 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<bool> isAdmin = const i0.Value.absent(), i0.Value<bool> isAdmin = const i0.Value.absent(),
i0.Value<String> email = const i0.Value.absent(), i0.Value<String> email = const i0.Value.absent(),
@ -187,7 +186,7 @@ class $$UserEntityTableTableManager extends i0.RootTableManager<
quotaUsageInBytes: quotaUsageInBytes, quotaUsageInBytes: quotaUsageInBytes,
), ),
createCompanionCallback: ({ createCompanionCallback: ({
required i2.Uint8List id, required String id,
required String name, required String name,
i0.Value<bool> isAdmin = const i0.Value.absent(), i0.Value<bool> isAdmin = const i0.Value.absent(),
required String email, required String email,
@ -230,7 +229,7 @@ typedef $$UserEntityTableProcessedTableManager = i0.ProcessedTableManager<
i1.UserEntityData, i1.UserEntityData,
i0.PrefetchHooks Function()>; i0.PrefetchHooks Function()>;
class $UserEntityTable extends i3.UserEntity class $UserEntityTable extends i2.UserEntity
with i0.TableInfo<$UserEntityTable, i1.UserEntityData> { with i0.TableInfo<$UserEntityTable, i1.UserEntityData> {
@override @override
final i0.GeneratedDatabase attachedDatabase; final i0.GeneratedDatabase attachedDatabase;
@ -238,9 +237,9 @@ class $UserEntityTable extends i3.UserEntity
$UserEntityTable(this.attachedDatabase, [this._alias]); $UserEntityTable(this.attachedDatabase, [this._alias]);
static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id'); static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id');
@override @override
late final i0.GeneratedColumn<i2.Uint8List> id = late final i0.GeneratedColumn<String> id = i0.GeneratedColumn<String>(
i0.GeneratedColumn<i2.Uint8List>('id', aliasedName, false, 'id', aliasedName, false,
type: i0.DriftSqlType.blob, requiredDuringInsert: true); type: i0.DriftSqlType.string, requiredDuringInsert: true);
static const i0.VerificationMeta _nameMeta = static const i0.VerificationMeta _nameMeta =
const i0.VerificationMeta('name'); const i0.VerificationMeta('name');
@override @override
@ -256,7 +255,7 @@ class $UserEntityTable extends i3.UserEntity
requiredDuringInsert: false, requiredDuringInsert: false,
defaultConstraints: defaultConstraints:
i0.GeneratedColumn.constraintIsAlways('CHECK ("is_admin" IN (0, 1))'), i0.GeneratedColumn.constraintIsAlways('CHECK ("is_admin" IN (0, 1))'),
defaultValue: const i4.Constant(false)); defaultValue: const i3.Constant(false));
static const i0.VerificationMeta _emailMeta = static const i0.VerificationMeta _emailMeta =
const i0.VerificationMeta('email'); const i0.VerificationMeta('email');
@override @override
@ -276,7 +275,7 @@ class $UserEntityTable extends i3.UserEntity
i0.GeneratedColumn<DateTime>('updated_at', aliasedName, false, i0.GeneratedColumn<DateTime>('updated_at', aliasedName, false,
type: i0.DriftSqlType.dateTime, type: i0.DriftSqlType.dateTime,
requiredDuringInsert: false, requiredDuringInsert: false,
defaultValue: i4.currentDateAndTime); defaultValue: i3.currentDateAndTime);
static const i0.VerificationMeta _quotaSizeInBytesMeta = static const i0.VerificationMeta _quotaSizeInBytesMeta =
const i0.VerificationMeta('quotaSizeInBytes'); const i0.VerificationMeta('quotaSizeInBytes');
@override @override
@ -290,7 +289,7 @@ class $UserEntityTable extends i3.UserEntity
i0.GeneratedColumn<int>('quota_usage_in_bytes', aliasedName, false, i0.GeneratedColumn<int>('quota_usage_in_bytes', aliasedName, false,
type: i0.DriftSqlType.int, type: i0.DriftSqlType.int,
requiredDuringInsert: false, requiredDuringInsert: false,
defaultValue: const i4.Constant(0)); defaultValue: const i3.Constant(0));
@override @override
List<i0.GeneratedColumn> get $columns => [ List<i0.GeneratedColumn> get $columns => [
id, id,
@ -366,7 +365,7 @@ class $UserEntityTable extends i3.UserEntity
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.UserEntityData( return i1.UserEntityData(
id: attachedDatabase.typeMapping id: attachedDatabase.typeMapping
.read(i0.DriftSqlType.blob, data['${effectivePrefix}id'])!, .read(i0.DriftSqlType.string, data['${effectivePrefix}id'])!,
name: attachedDatabase.typeMapping name: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}name'])!, .read(i0.DriftSqlType.string, data['${effectivePrefix}name'])!,
isAdmin: attachedDatabase.typeMapping isAdmin: attachedDatabase.typeMapping
@ -397,7 +396,7 @@ class $UserEntityTable extends i3.UserEntity
class UserEntityData extends i0.DataClass class UserEntityData extends i0.DataClass
implements i0.Insertable<i1.UserEntityData> { implements i0.Insertable<i1.UserEntityData> {
final i2.Uint8List id; final String id;
final String name; final String name;
final bool isAdmin; final bool isAdmin;
final String email; final String email;
@ -417,7 +416,7 @@ class UserEntityData extends i0.DataClass
@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<i2.Uint8List>(id); map['id'] = i0.Variable<String>(id);
map['name'] = i0.Variable<String>(name); map['name'] = i0.Variable<String>(name);
map['is_admin'] = i0.Variable<bool>(isAdmin); map['is_admin'] = i0.Variable<bool>(isAdmin);
map['email'] = i0.Variable<String>(email); map['email'] = i0.Variable<String>(email);
@ -436,7 +435,7 @@ class UserEntityData extends i0.DataClass
{i0.ValueSerializer? serializer}) { {i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer; serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return UserEntityData( return UserEntityData(
id: serializer.fromJson<i2.Uint8List>(json['id']), id: serializer.fromJson<String>(json['id']),
name: serializer.fromJson<String>(json['name']), name: serializer.fromJson<String>(json['name']),
isAdmin: serializer.fromJson<bool>(json['isAdmin']), isAdmin: serializer.fromJson<bool>(json['isAdmin']),
email: serializer.fromJson<String>(json['email']), email: serializer.fromJson<String>(json['email']),
@ -450,7 +449,7 @@ class UserEntityData extends i0.DataClass
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) { Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer; serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{ return <String, dynamic>{
'id': serializer.toJson<i2.Uint8List>(id), 'id': serializer.toJson<String>(id),
'name': serializer.toJson<String>(name), 'name': serializer.toJson<String>(name),
'isAdmin': serializer.toJson<bool>(isAdmin), 'isAdmin': serializer.toJson<bool>(isAdmin),
'email': serializer.toJson<String>(email), 'email': serializer.toJson<String>(email),
@ -462,7 +461,7 @@ class UserEntityData extends i0.DataClass
} }
i1.UserEntityData copyWith( i1.UserEntityData copyWith(
{i2.Uint8List? id, {String? id,
String? name, String? name,
bool? isAdmin, bool? isAdmin,
String? email, String? email,
@ -519,13 +518,13 @@ class UserEntityData extends i0.DataClass
} }
@override @override
int get hashCode => Object.hash(i0.$driftBlobEquality.hash(id), name, isAdmin, int get hashCode => Object.hash(id, name, isAdmin, email, profileImagePath,
email, profileImagePath, updatedAt, quotaSizeInBytes, quotaUsageInBytes); updatedAt, quotaSizeInBytes, quotaUsageInBytes);
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
(other is i1.UserEntityData && (other is i1.UserEntityData &&
i0.$driftBlobEquality.equals(other.id, this.id) && other.id == this.id &&
other.name == this.name && other.name == this.name &&
other.isAdmin == this.isAdmin && other.isAdmin == this.isAdmin &&
other.email == this.email && other.email == this.email &&
@ -536,7 +535,7 @@ class UserEntityData extends i0.DataClass
} }
class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> { class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
final i0.Value<i2.Uint8List> id; final i0.Value<String> id;
final i0.Value<String> name; final i0.Value<String> name;
final i0.Value<bool> isAdmin; final i0.Value<bool> isAdmin;
final i0.Value<String> email; final i0.Value<String> email;
@ -555,7 +554,7 @@ class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
this.quotaUsageInBytes = const i0.Value.absent(), this.quotaUsageInBytes = const i0.Value.absent(),
}); });
UserEntityCompanion.insert({ UserEntityCompanion.insert({
required i2.Uint8List id, required String id,
required String name, required String name,
this.isAdmin = const i0.Value.absent(), this.isAdmin = const i0.Value.absent(),
required String email, required String email,
@ -567,7 +566,7 @@ class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
name = i0.Value(name), name = i0.Value(name),
email = i0.Value(email); email = i0.Value(email);
static i0.Insertable<i1.UserEntityData> custom({ static i0.Insertable<i1.UserEntityData> custom({
i0.Expression<i2.Uint8List>? id, i0.Expression<String>? id,
i0.Expression<String>? name, i0.Expression<String>? name,
i0.Expression<bool>? isAdmin, i0.Expression<bool>? isAdmin,
i0.Expression<String>? email, i0.Expression<String>? email,
@ -589,7 +588,7 @@ class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
} }
i1.UserEntityCompanion copyWith( i1.UserEntityCompanion copyWith(
{i0.Value<i2.Uint8List>? id, {i0.Value<String>? id,
i0.Value<String>? name, i0.Value<String>? name,
i0.Value<bool>? isAdmin, i0.Value<bool>? isAdmin,
i0.Value<String>? email, i0.Value<String>? email,
@ -613,7 +612,7 @@ class UserEntityCompanion extends i0.UpdateCompanion<i1.UserEntityData> {
Map<String, i0.Expression> toColumns(bool nullToAbsent) { Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{}; final map = <String, i0.Expression>{};
if (id.present) { if (id.present) {
map['id'] = i0.Variable<i2.Uint8List>(id.value); map['id'] = i0.Variable<String>(id.value);
} }
if (name.present) { if (name.present) {
map['name'] = i0.Variable<String>(name.value); map['name'] = i0.Variable<String>(name.value);

View File

@ -6,8 +6,8 @@ import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
class UserMetadataEntity extends Table with DriftDefaultsMixin { class UserMetadataEntity extends Table with DriftDefaultsMixin {
const UserMetadataEntity(); const UserMetadataEntity();
BlobColumn get userId => TextColumn get userId =>
blob().references(UserEntity, #id, onDelete: KeyAction.cascade)(); text().references(UserEntity, #id, onDelete: KeyAction.cascade)();
TextColumn get preferences => text().map(userPreferenceConverter)(); TextColumn get preferences => text().map(userPreferenceConverter)();
@override @override

View File

@ -3,23 +3,22 @@
import 'package:drift/drift.dart' as i0; import 'package:drift/drift.dart' as i0;
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart' import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift.dart'
as i1; as i1;
import 'dart:typed_data' as i2; import 'package:immich_mobile/domain/models/user_metadata.model.dart' as i2;
import 'package:immich_mobile/domain/models/user_metadata.model.dart' as i3;
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart' import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart'
as i4; as i3;
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart' import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'
as i5; as i4;
import 'package:drift/internal/modular.dart' as i6; import 'package:drift/internal/modular.dart' as i5;
typedef $$UserMetadataEntityTableCreateCompanionBuilder typedef $$UserMetadataEntityTableCreateCompanionBuilder
= i1.UserMetadataEntityCompanion Function({ = i1.UserMetadataEntityCompanion Function({
required i2.Uint8List userId, required String userId,
required i3.UserPreferences preferences, required i2.UserPreferences preferences,
}); });
typedef $$UserMetadataEntityTableUpdateCompanionBuilder typedef $$UserMetadataEntityTableUpdateCompanionBuilder
= i1.UserMetadataEntityCompanion Function({ = i1.UserMetadataEntityCompanion Function({
i0.Value<i2.Uint8List> userId, i0.Value<String> userId,
i0.Value<i3.UserPreferences> preferences, i0.Value<i2.UserPreferences> preferences,
}); });
final class $$UserMetadataEntityTableReferences extends i0.BaseReferences< final class $$UserMetadataEntityTableReferences extends i0.BaseReferences<
@ -29,26 +28,26 @@ final class $$UserMetadataEntityTableReferences extends i0.BaseReferences<
$$UserMetadataEntityTableReferences( $$UserMetadataEntityTableReferences(
super.$_db, super.$_table, super.$_typedResult); super.$_db, super.$_table, super.$_typedResult);
static i5.$UserEntityTable _userIdTable(i0.GeneratedDatabase db) => static i4.$UserEntityTable _userIdTable(i0.GeneratedDatabase db) =>
i6.ReadDatabaseContainer(db) i5.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity') .resultSet<i4.$UserEntityTable>('user_entity')
.createAlias(i0.$_aliasNameGenerator( .createAlias(i0.$_aliasNameGenerator(
i6.ReadDatabaseContainer(db) i5.ReadDatabaseContainer(db)
.resultSet<i1.$UserMetadataEntityTable>( .resultSet<i1.$UserMetadataEntityTable>(
'user_metadata_entity') 'user_metadata_entity')
.userId, .userId,
i6.ReadDatabaseContainer(db) i5.ReadDatabaseContainer(db)
.resultSet<i5.$UserEntityTable>('user_entity') .resultSet<i4.$UserEntityTable>('user_entity')
.id)); .id));
i5.$$UserEntityTableProcessedTableManager get userId { i4.$$UserEntityTableProcessedTableManager get userId {
final $_column = $_itemColumn<i2.Uint8List>('user_id')!; final $_column = $_itemColumn<String>('user_id')!;
final manager = i5 final manager = i4
.$$UserEntityTableTableManager( .$$UserEntityTableTableManager(
$_db, $_db,
i6.ReadDatabaseContainer($_db) i5.ReadDatabaseContainer($_db)
.resultSet<i5.$UserEntityTable>('user_entity')) .resultSet<i4.$UserEntityTable>('user_entity'))
.filter((f) => f.id.sqlEquals($_column)); .filter((f) => f.id.sqlEquals($_column));
final item = $_typedResult.readTableOrNull(_userIdTable($_db)); final item = $_typedResult.readTableOrNull(_userIdTable($_db));
if (item == null) return manager; if (item == null) return manager;
@ -66,26 +65,26 @@ class $$UserMetadataEntityTableFilterComposer
super.$addJoinBuilderToRootComposer, super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
i0.ColumnWithTypeConverterFilters<i3.UserPreferences, i3.UserPreferences, i0.ColumnWithTypeConverterFilters<i2.UserPreferences, i2.UserPreferences,
String> String>
get preferences => $composableBuilder( get preferences => $composableBuilder(
column: $table.preferences, column: $table.preferences,
builder: (column) => i0.ColumnWithTypeConverterFilters(column)); builder: (column) => i0.ColumnWithTypeConverterFilters(column));
i5.$$UserEntityTableFilterComposer get userId { i4.$$UserEntityTableFilterComposer get userId {
final i5.$$UserEntityTableFilterComposer composer = $composerBuilder( final i4.$$UserEntityTableFilterComposer composer = $composerBuilder(
composer: this, composer: this,
getCurrentColumn: (t) => t.userId, getCurrentColumn: (t) => t.userId,
referencedTable: i6.ReadDatabaseContainer($db) referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id, getReferencedColumn: (t) => t.id,
builder: (joinBuilder, builder: (joinBuilder,
{$addJoinBuilderToRootComposer, {$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) => $removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableFilterComposer( i4.$$UserEntityTableFilterComposer(
$db: $db, $db: $db,
$table: i6.ReadDatabaseContainer($db) $table: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder, joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer:
@ -108,20 +107,20 @@ class $$UserMetadataEntityTableOrderingComposer
column: $table.preferences, column: $table.preferences,
builder: (column) => i0.ColumnOrderings(column)); builder: (column) => i0.ColumnOrderings(column));
i5.$$UserEntityTableOrderingComposer get userId { i4.$$UserEntityTableOrderingComposer get userId {
final i5.$$UserEntityTableOrderingComposer composer = $composerBuilder( final i4.$$UserEntityTableOrderingComposer composer = $composerBuilder(
composer: this, composer: this,
getCurrentColumn: (t) => t.userId, getCurrentColumn: (t) => t.userId,
referencedTable: i6.ReadDatabaseContainer($db) referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id, getReferencedColumn: (t) => t.id,
builder: (joinBuilder, builder: (joinBuilder,
{$addJoinBuilderToRootComposer, {$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) => $removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableOrderingComposer( i4.$$UserEntityTableOrderingComposer(
$db: $db, $db: $db,
$table: i6.ReadDatabaseContainer($db) $table: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder, joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer:
@ -140,24 +139,24 @@ class $$UserMetadataEntityTableAnnotationComposer
super.$addJoinBuilderToRootComposer, super.$addJoinBuilderToRootComposer,
super.$removeJoinBuilderFromRootComposer, super.$removeJoinBuilderFromRootComposer,
}); });
i0.GeneratedColumnWithTypeConverter<i3.UserPreferences, String> i0.GeneratedColumnWithTypeConverter<i2.UserPreferences, String>
get preferences => $composableBuilder( get preferences => $composableBuilder(
column: $table.preferences, builder: (column) => column); column: $table.preferences, builder: (column) => column);
i5.$$UserEntityTableAnnotationComposer get userId { i4.$$UserEntityTableAnnotationComposer get userId {
final i5.$$UserEntityTableAnnotationComposer composer = $composerBuilder( final i4.$$UserEntityTableAnnotationComposer composer = $composerBuilder(
composer: this, composer: this,
getCurrentColumn: (t) => t.userId, getCurrentColumn: (t) => t.userId,
referencedTable: i6.ReadDatabaseContainer($db) referencedTable: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
getReferencedColumn: (t) => t.id, getReferencedColumn: (t) => t.id,
builder: (joinBuilder, builder: (joinBuilder,
{$addJoinBuilderToRootComposer, {$addJoinBuilderToRootComposer,
$removeJoinBuilderFromRootComposer}) => $removeJoinBuilderFromRootComposer}) =>
i5.$$UserEntityTableAnnotationComposer( i4.$$UserEntityTableAnnotationComposer(
$db: $db, $db: $db,
$table: i6.ReadDatabaseContainer($db) $table: i5.ReadDatabaseContainer($db)
.resultSet<i5.$UserEntityTable>('user_entity'), .resultSet<i4.$UserEntityTable>('user_entity'),
$addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer,
joinBuilder: joinBuilder, joinBuilder: joinBuilder,
$removeJoinBuilderFromRootComposer: $removeJoinBuilderFromRootComposer:
@ -193,16 +192,16 @@ class $$UserMetadataEntityTableTableManager extends i0.RootTableManager<
i1.$$UserMetadataEntityTableAnnotationComposer( i1.$$UserMetadataEntityTableAnnotationComposer(
$db: db, $table: table), $db: db, $table: table),
updateCompanionCallback: ({ updateCompanionCallback: ({
i0.Value<i2.Uint8List> userId = const i0.Value.absent(), i0.Value<String> userId = const i0.Value.absent(),
i0.Value<i3.UserPreferences> preferences = const i0.Value.absent(), i0.Value<i2.UserPreferences> preferences = const i0.Value.absent(),
}) => }) =>
i1.UserMetadataEntityCompanion( i1.UserMetadataEntityCompanion(
userId: userId, userId: userId,
preferences: preferences, preferences: preferences,
), ),
createCompanionCallback: ({ createCompanionCallback: ({
required i2.Uint8List userId, required String userId,
required i3.UserPreferences preferences, required i2.UserPreferences preferences,
}) => }) =>
i1.UserMetadataEntityCompanion.insert( i1.UserMetadataEntityCompanion.insert(
userId: userId, userId: userId,
@ -267,7 +266,7 @@ typedef $$UserMetadataEntityTableProcessedTableManager
i1.UserMetadataEntityData, i1.UserMetadataEntityData,
i0.PrefetchHooks Function({bool userId})>; i0.PrefetchHooks Function({bool userId})>;
class $UserMetadataEntityTable extends i4.UserMetadataEntity class $UserMetadataEntityTable extends i3.UserMetadataEntity
with i0.TableInfo<$UserMetadataEntityTable, i1.UserMetadataEntityData> { with i0.TableInfo<$UserMetadataEntityTable, i1.UserMetadataEntityData> {
@override @override
final i0.GeneratedDatabase attachedDatabase; final i0.GeneratedDatabase attachedDatabase;
@ -276,18 +275,18 @@ class $UserMetadataEntityTable extends i4.UserMetadataEntity
static const i0.VerificationMeta _userIdMeta = static const i0.VerificationMeta _userIdMeta =
const i0.VerificationMeta('userId'); const i0.VerificationMeta('userId');
@override @override
late final i0.GeneratedColumn<i2.Uint8List> userId = late final i0.GeneratedColumn<String> userId = i0.GeneratedColumn<String>(
i0.GeneratedColumn<i2.Uint8List>('user_id', aliasedName, false, 'user_id', aliasedName, false,
type: i0.DriftSqlType.blob, type: i0.DriftSqlType.string,
requiredDuringInsert: true, requiredDuringInsert: true,
defaultConstraints: i0.GeneratedColumn.constraintIsAlways( defaultConstraints: i0.GeneratedColumn.constraintIsAlways(
'REFERENCES user_entity (id) ON DELETE CASCADE')); 'REFERENCES user_entity (id) ON DELETE CASCADE'));
@override @override
late final i0.GeneratedColumnWithTypeConverter<i3.UserPreferences, String> late final i0.GeneratedColumnWithTypeConverter<i2.UserPreferences, String>
preferences = i0.GeneratedColumn<String>( preferences = i0.GeneratedColumn<String>(
'preferences', aliasedName, false, 'preferences', aliasedName, false,
type: i0.DriftSqlType.string, requiredDuringInsert: true) type: i0.DriftSqlType.string, requiredDuringInsert: true)
.withConverter<i3.UserPreferences>( .withConverter<i2.UserPreferences>(
i1.$UserMetadataEntityTable.$converterpreferences); i1.$UserMetadataEntityTable.$converterpreferences);
@override @override
List<i0.GeneratedColumn> get $columns => [userId, preferences]; List<i0.GeneratedColumn> get $columns => [userId, preferences];
@ -319,7 +318,7 @@ class $UserMetadataEntityTable extends i4.UserMetadataEntity
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
return i1.UserMetadataEntityData( return i1.UserMetadataEntityData(
userId: attachedDatabase.typeMapping userId: attachedDatabase.typeMapping
.read(i0.DriftSqlType.blob, data['${effectivePrefix}user_id'])!, .read(i0.DriftSqlType.string, data['${effectivePrefix}user_id'])!,
preferences: i1.$UserMetadataEntityTable.$converterpreferences.fromSql( preferences: i1.$UserMetadataEntityTable.$converterpreferences.fromSql(
attachedDatabase.typeMapping.read( attachedDatabase.typeMapping.read(
i0.DriftSqlType.string, data['${effectivePrefix}preferences'])!), i0.DriftSqlType.string, data['${effectivePrefix}preferences'])!),
@ -331,8 +330,8 @@ class $UserMetadataEntityTable extends i4.UserMetadataEntity
return $UserMetadataEntityTable(attachedDatabase, alias); return $UserMetadataEntityTable(attachedDatabase, alias);
} }
static i0.JsonTypeConverter2<i3.UserPreferences, String, Object?> static i0.JsonTypeConverter2<i2.UserPreferences, String, Object?>
$converterpreferences = i4.userPreferenceConverter; $converterpreferences = i3.userPreferenceConverter;
@override @override
bool get withoutRowId => true; bool get withoutRowId => true;
@override @override
@ -341,14 +340,14 @@ class $UserMetadataEntityTable extends i4.UserMetadataEntity
class UserMetadataEntityData extends i0.DataClass class UserMetadataEntityData extends i0.DataClass
implements i0.Insertable<i1.UserMetadataEntityData> { implements i0.Insertable<i1.UserMetadataEntityData> {
final i2.Uint8List userId; final String userId;
final i3.UserPreferences preferences; final i2.UserPreferences preferences;
const UserMetadataEntityData( const UserMetadataEntityData(
{required this.userId, required this.preferences}); {required this.userId, required this.preferences});
@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['user_id'] = i0.Variable<i2.Uint8List>(userId); map['user_id'] = i0.Variable<String>(userId);
{ {
map['preferences'] = i0.Variable<String>( map['preferences'] = i0.Variable<String>(
i1.$UserMetadataEntityTable.$converterpreferences.toSql(preferences)); i1.$UserMetadataEntityTable.$converterpreferences.toSql(preferences));
@ -360,7 +359,7 @@ class UserMetadataEntityData extends i0.DataClass
{i0.ValueSerializer? serializer}) { {i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer; serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return UserMetadataEntityData( return UserMetadataEntityData(
userId: serializer.fromJson<i2.Uint8List>(json['userId']), userId: serializer.fromJson<String>(json['userId']),
preferences: i1.$UserMetadataEntityTable.$converterpreferences preferences: i1.$UserMetadataEntityTable.$converterpreferences
.fromJson(serializer.fromJson<Object?>(json['preferences'])), .fromJson(serializer.fromJson<Object?>(json['preferences'])),
); );
@ -369,7 +368,7 @@ class UserMetadataEntityData extends i0.DataClass
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) { Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
serializer ??= i0.driftRuntimeOptions.defaultSerializer; serializer ??= i0.driftRuntimeOptions.defaultSerializer;
return <String, dynamic>{ return <String, dynamic>{
'userId': serializer.toJson<i2.Uint8List>(userId), 'userId': serializer.toJson<String>(userId),
'preferences': serializer.toJson<Object?>(i1 'preferences': serializer.toJson<Object?>(i1
.$UserMetadataEntityTable.$converterpreferences .$UserMetadataEntityTable.$converterpreferences
.toJson(preferences)), .toJson(preferences)),
@ -377,7 +376,7 @@ class UserMetadataEntityData extends i0.DataClass
} }
i1.UserMetadataEntityData copyWith( i1.UserMetadataEntityData copyWith(
{i2.Uint8List? userId, i3.UserPreferences? preferences}) => {String? userId, i2.UserPreferences? preferences}) =>
i1.UserMetadataEntityData( i1.UserMetadataEntityData(
userId: userId ?? this.userId, userId: userId ?? this.userId,
preferences: preferences ?? this.preferences, preferences: preferences ?? this.preferences,
@ -401,31 +400,30 @@ class UserMetadataEntityData extends i0.DataClass
} }
@override @override
int get hashCode => int get hashCode => Object.hash(userId, preferences);
Object.hash(i0.$driftBlobEquality.hash(userId), preferences);
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
(other is i1.UserMetadataEntityData && (other is i1.UserMetadataEntityData &&
i0.$driftBlobEquality.equals(other.userId, this.userId) && other.userId == this.userId &&
other.preferences == this.preferences); other.preferences == this.preferences);
} }
class UserMetadataEntityCompanion class UserMetadataEntityCompanion
extends i0.UpdateCompanion<i1.UserMetadataEntityData> { extends i0.UpdateCompanion<i1.UserMetadataEntityData> {
final i0.Value<i2.Uint8List> userId; final i0.Value<String> userId;
final i0.Value<i3.UserPreferences> preferences; final i0.Value<i2.UserPreferences> preferences;
const UserMetadataEntityCompanion({ const UserMetadataEntityCompanion({
this.userId = const i0.Value.absent(), this.userId = const i0.Value.absent(),
this.preferences = const i0.Value.absent(), this.preferences = const i0.Value.absent(),
}); });
UserMetadataEntityCompanion.insert({ UserMetadataEntityCompanion.insert({
required i2.Uint8List userId, required String userId,
required i3.UserPreferences preferences, required i2.UserPreferences preferences,
}) : userId = i0.Value(userId), }) : userId = i0.Value(userId),
preferences = i0.Value(preferences); preferences = i0.Value(preferences);
static i0.Insertable<i1.UserMetadataEntityData> custom({ static i0.Insertable<i1.UserMetadataEntityData> custom({
i0.Expression<i2.Uint8List>? userId, i0.Expression<String>? userId,
i0.Expression<String>? preferences, i0.Expression<String>? preferences,
}) { }) {
return i0.RawValuesInsertable({ return i0.RawValuesInsertable({
@ -435,8 +433,7 @@ class UserMetadataEntityCompanion
} }
i1.UserMetadataEntityCompanion copyWith( i1.UserMetadataEntityCompanion copyWith(
{i0.Value<i2.Uint8List>? userId, {i0.Value<String>? userId, i0.Value<i2.UserPreferences>? preferences}) {
i0.Value<i3.UserPreferences>? preferences}) {
return i1.UserMetadataEntityCompanion( return i1.UserMetadataEntityCompanion(
userId: userId ?? this.userId, userId: userId ?? this.userId,
preferences: preferences ?? this.preferences, preferences: preferences ?? this.preferences,
@ -447,7 +444,7 @@ class UserMetadataEntityCompanion
Map<String, i0.Expression> toColumns(bool nullToAbsent) { Map<String, i0.Expression> toColumns(bool nullToAbsent) {
final map = <String, i0.Expression>{}; final map = <String, i0.Expression>{};
if (userId.present) { if (userId.present) {
map['user_id'] = i0.Variable<i2.Uint8List>(userId.value); map['user_id'] = i0.Variable<String>(userId.value);
} }
if (preferences.present) { if (preferences.present) {
map['preferences'] = i0.Variable<String>(i1 map['preferences'] = i0.Variable<String>(i1

View File

@ -3,10 +3,12 @@ import 'dart:async';
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:drift_flutter/drift_flutter.dart'; import 'package:drift_flutter/drift_flutter.dart';
import 'package:immich_mobile/domain/interfaces/db.interface.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/local_album.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_album_asset.entity.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/entities/partner.entity.dart'; import 'package:immich_mobile/infrastructure/entities/partner.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart'; import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart';
import 'package:isar/isar.dart'; import 'package:isar/isar.dart';
@ -36,6 +38,8 @@ class IsarDatabaseRepository implements IDatabaseRepository {
LocalAlbumEntity, LocalAlbumEntity,
LocalAssetEntity, LocalAssetEntity,
LocalAlbumAssetEntity, LocalAlbumAssetEntity,
RemoteAssetEntity,
RemoteExifEntity,
], ],
) )
class Drift extends $Drift implements IDatabaseRepository { class Drift extends $Drift implements IDatabaseRepository {

View File

@ -13,6 +13,10 @@ import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.d
as i5; as i5;
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart' import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart'
as i6; as i6;
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'
as i7;
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart'
as i8;
abstract class $Drift extends i0.GeneratedDatabase { abstract class $Drift extends i0.GeneratedDatabase {
$Drift(i0.QueryExecutor e) : super(e); $Drift(i0.QueryExecutor e) : super(e);
@ -28,6 +32,10 @@ abstract class $Drift extends i0.GeneratedDatabase {
i5.$LocalAssetEntityTable(this); i5.$LocalAssetEntityTable(this);
late final i6.$LocalAlbumAssetEntityTable localAlbumAssetEntity = late final i6.$LocalAlbumAssetEntityTable localAlbumAssetEntity =
i6.$LocalAlbumAssetEntityTable(this); i6.$LocalAlbumAssetEntityTable(this);
late final i7.$RemoteAssetEntityTable remoteAssetEntity =
i7.$RemoteAssetEntityTable(this);
late final i8.$RemoteExifEntityTable remoteExifEntity =
i8.$RemoteExifEntityTable(this);
@override @override
Iterable<i0.TableInfo<i0.Table, Object?>> get allTables => Iterable<i0.TableInfo<i0.Table, Object?>> get allTables =>
allSchemaEntities.whereType<i0.TableInfo<i0.Table, Object?>>(); allSchemaEntities.whereType<i0.TableInfo<i0.Table, Object?>>();
@ -39,7 +47,10 @@ abstract class $Drift extends i0.GeneratedDatabase {
localAlbumEntity, localAlbumEntity,
localAssetEntity, localAssetEntity,
localAlbumAssetEntity, localAlbumAssetEntity,
i5.localAssetChecksum remoteAssetEntity,
remoteExifEntity,
i5.idxLocalAssetChecksum,
i7.uQRemoteAssetOwnerChecksum
]; ];
@override @override
i0.StreamQueryUpdateRules get streamUpdateRules => i0.StreamQueryUpdateRules get streamUpdateRules =>
@ -83,6 +94,20 @@ abstract class $Drift extends i0.GeneratedDatabase {
kind: i0.UpdateKind.delete), kind: i0.UpdateKind.delete),
], ],
), ),
i0.WritePropagation(
on: i0.TableUpdateQuery.onTableName('user_entity',
limitUpdateKind: i0.UpdateKind.delete),
result: [
i0.TableUpdate('remote_asset_entity', kind: i0.UpdateKind.delete),
],
),
i0.WritePropagation(
on: i0.TableUpdateQuery.onTableName('remote_asset_entity',
limitUpdateKind: i0.UpdateKind.delete),
result: [
i0.TableUpdate('remote_exif_entity', kind: i0.UpdateKind.delete),
],
),
], ],
); );
@override @override
@ -105,4 +130,8 @@ class $DriftManager {
i5.$$LocalAssetEntityTableTableManager(_db, _db.localAssetEntity); i5.$$LocalAssetEntityTableTableManager(_db, _db.localAssetEntity);
i6.$$LocalAlbumAssetEntityTableTableManager get localAlbumAssetEntity => i6 i6.$$LocalAlbumAssetEntityTableTableManager get localAlbumAssetEntity => i6
.$$LocalAlbumAssetEntityTableTableManager(_db, _db.localAlbumAssetEntity); .$$LocalAlbumAssetEntityTableTableManager(_db, _db.localAlbumAssetEntity);
i7.$$RemoteAssetEntityTableTableManager get remoteAssetEntity =>
i7.$$RemoteAssetEntityTableTableManager(_db, _db.remoteAssetEntity);
i8.$$RemoteExifEntityTableTableManager get remoteExifEntity =>
i8.$$RemoteExifEntityTableTableManager(_db, _db.remoteExifEntity);
} }

View File

@ -5,6 +5,7 @@ import 'package:http/http.dart' as http;
import 'package:immich_mobile/constants/constants.dart'; import 'package:immich_mobile/constants/constants.dart';
import 'package:immich_mobile/domain/interfaces/sync_api.interface.dart'; import 'package:immich_mobile/domain/interfaces/sync_api.interface.dart';
import 'package:immich_mobile/domain/models/sync_event.model.dart'; import 'package:immich_mobile/domain/models/sync_event.model.dart';
import 'package:immich_mobile/presentation/pages/dev/dev_logger.dart';
import 'package:immich_mobile/services/api.service.dart'; import 'package:immich_mobile/services/api.service.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:openapi/api.dart'; import 'package:openapi/api.dart';
@ -105,6 +106,7 @@ class SyncApiRepository implements ISyncApiRepository {
stopwatch.stop(); stopwatch.stop();
_logger _logger
.info("Remote Sync completed in ${stopwatch.elapsed.inMilliseconds}ms"); .info("Remote Sync completed in ${stopwatch.elapsed.inMilliseconds}ms");
DLog.log("Remote Sync completed in ${stopwatch.elapsed.inMilliseconds}ms");
} }
List<SyncEvent> _parseLines(List<String> lines) { List<SyncEvent> _parseLines(List<String> lines) {

View File

@ -1,12 +1,13 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:flutter/foundation.dart';
import 'package:immich_mobile/domain/interfaces/sync_stream.interface.dart'; import 'package:immich_mobile/domain/interfaces/sync_stream.interface.dart';
import 'package:immich_mobile/extensions/string_extensions.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:openapi/api.dart'; import 'package:openapi/api.dart' hide AssetVisibility;
class DriftSyncStreamRepository extends DriftDatabaseRepository class DriftSyncStreamRepository extends DriftDatabaseRepository
implements ISyncStreamRepository { implements ISyncStreamRepository {
@ -22,7 +23,7 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
for (final user in data) { for (final user in data) {
batch.delete( batch.delete(
_db.userEntity, _db.userEntity,
UserEntityCompanion(id: Value(user.userId.toUuidByte())), UserEntityCompanion(id: Value(user.userId)),
); );
} }
}); });
@ -44,7 +45,7 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
batch.insert( batch.insert(
_db.userEntity, _db.userEntity,
companion.copyWith(id: Value(user.id.toUuidByte())), companion.copyWith(id: Value(user.id)),
onConflict: DoUpdate((_) => companion), onConflict: DoUpdate((_) => companion),
); );
} }
@ -63,8 +64,8 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
batch.delete( batch.delete(
_db.partnerEntity, _db.partnerEntity,
PartnerEntityCompanion( PartnerEntityCompanion(
sharedById: Value(partner.sharedById.toUuidByte()), sharedById: Value(partner.sharedById),
sharedWithId: Value(partner.sharedWithId.toUuidByte()), sharedWithId: Value(partner.sharedWithId),
), ),
); );
} }
@ -86,8 +87,8 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
batch.insert( batch.insert(
_db.partnerEntity, _db.partnerEntity,
companion.copyWith( companion.copyWith(
sharedById: Value(partner.sharedById.toUuidByte()), sharedById: Value(partner.sharedById),
sharedWithId: Value(partner.sharedWithId.toUuidByte()), sharedWithId: Value(partner.sharedWithId),
), ),
onConflict: DoUpdate((_) => companion), onConflict: DoUpdate((_) => companion),
); );
@ -99,36 +100,153 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
} }
} }
// Assets
@override
Future<void> updateAssetsV1(Iterable<SyncAssetV1> data) async {
debugPrint("updateAssetsV1 - ${data.length}");
}
@override @override
Future<void> deleteAssetsV1(Iterable<SyncAssetDeleteV1> data) async { Future<void> deleteAssetsV1(Iterable<SyncAssetDeleteV1> data) async {
debugPrint("deleteAssetsV1 - ${data.length}"); try {
await _deleteAssetsV1(data);
} catch (e, s) {
_logger.severe('Error while processing deleteAssetsV1', e, s);
rethrow;
}
} }
// Partner Assets
@override @override
Future<void> updatePartnerAssetsV1(Iterable<SyncAssetV1> data) async { Future<void> updateAssetsV1(Iterable<SyncAssetV1> data) async {
debugPrint("updatePartnerAssetsV1 - ${data.length}"); try {
await _updateAssetsV1(data);
} catch (e, s) {
_logger.severe('Error while processing updateAssetsV1', e, s);
rethrow;
}
} }
@override @override
Future<void> deletePartnerAssetsV1(Iterable<SyncAssetDeleteV1> data) async { Future<void> deletePartnerAssetsV1(Iterable<SyncAssetDeleteV1> data) async {
debugPrint("deletePartnerAssetsV1 - ${data.length}"); try {
await _deleteAssetsV1(data);
} catch (e, s) {
_logger.severe('Error while processing deletePartnerAssetsV1', e, s);
rethrow;
}
}
@override
Future<void> updatePartnerAssetsV1(Iterable<SyncAssetV1> data) async {
try {
await _updateAssetsV1(data);
} catch (e, s) {
_logger.severe('Error while processing updatePartnerAssetsV1', e, s);
rethrow;
}
} }
// EXIF
@override @override
Future<void> updateAssetsExifV1(Iterable<SyncAssetExifV1> data) async { Future<void> updateAssetsExifV1(Iterable<SyncAssetExifV1> data) async {
debugPrint("updateAssetsExifV1 - ${data.length}"); try {
await _updateAssetExifV1(data);
} catch (e, s) {
_logger.severe('Error while processing updateAssetsExifV1', e, s);
rethrow;
}
} }
@override @override
Future<void> updatePartnerAssetsExifV1(Iterable<SyncAssetExifV1> data) async { Future<void> updatePartnerAssetsExifV1(Iterable<SyncAssetExifV1> data) async {
debugPrint("updatePartnerAssetsExifV1 - ${data.length}"); try {
await _updateAssetExifV1(data);
} catch (e, s) {
_logger.severe('Error while processing updatePartnerAssetsExifV1', e, s);
rethrow;
} }
}
Future<void> _updateAssetsV1(Iterable<SyncAssetV1> data) =>
_db.batch((batch) {
for (final asset in data) {
final companion = RemoteAssetEntityCompanion(
name: Value(asset.originalFileName),
type: Value(asset.type.toAssetType()),
createdAt: Value.absentIfNull(asset.fileCreatedAt),
updatedAt: Value.absentIfNull(asset.fileModifiedAt),
durationInSeconds: const Value(0),
checksum: Value(asset.checksum),
isFavorite: Value(asset.isFavorite),
ownerId: Value(asset.ownerId),
localDateTime: Value(asset.localDateTime),
thumbHash: Value(asset.thumbhash),
deletedAt: Value(asset.deletedAt),
visibility: Value(asset.visibility.toAssetVisibility()),
);
batch.insert(
_db.remoteAssetEntity,
companion.copyWith(id: Value(asset.id)),
onConflict: DoUpdate((_) => companion),
);
}
});
Future<void> _deleteAssetsV1(Iterable<SyncAssetDeleteV1> assets) =>
_db.batch((batch) {
for (final asset in assets) {
batch.delete(
_db.remoteAssetEntity,
RemoteAssetEntityCompanion(id: Value(asset.assetId)),
);
}
});
Future<void> _updateAssetExifV1(Iterable<SyncAssetExifV1> data) =>
_db.batch((batch) {
for (final exif in data) {
final companion = RemoteExifEntityCompanion(
city: Value(exif.city),
state: Value(exif.state),
country: Value(exif.country),
dateTimeOriginal: Value(exif.dateTimeOriginal),
description: Value(exif.description),
height: Value(exif.exifImageHeight),
width: Value(exif.exifImageWidth),
exposureTime: Value(exif.exposureTime),
fNumber: Value(exif.fNumber),
fileSize: Value(exif.fileSizeInByte),
focalLength: Value(exif.focalLength),
latitude: Value(exif.latitude),
longitude: Value(exif.longitude),
iso: Value(exif.iso),
make: Value(exif.make),
model: Value(exif.model),
orientation: Value(exif.orientation),
timeZone: Value(exif.timeZone),
rating: Value(exif.rating),
projectionType: Value(exif.projectionType),
);
batch.insert(
_db.remoteExifEntity,
companion.copyWith(assetId: Value(exif.assetId)),
onConflict: DoUpdate((_) => companion),
);
}
});
}
extension on SyncAssetV1TypeEnum {
AssetType toAssetType() => switch (this) {
SyncAssetV1TypeEnum.IMAGE => AssetType.image,
SyncAssetV1TypeEnum.VIDEO => AssetType.video,
SyncAssetV1TypeEnum.AUDIO => AssetType.audio,
SyncAssetV1TypeEnum.OTHER => AssetType.other,
_ => throw Exception('Unknown SyncAssetV1TypeEnum value: $this'),
};
}
extension on SyncAssetV1VisibilityEnum {
AssetVisibility toAssetVisibility() => switch (this) {
SyncAssetV1VisibilityEnum.timeline => AssetVisibility.timeline,
SyncAssetV1VisibilityEnum.hidden => AssetVisibility.hidden,
SyncAssetV1VisibilityEnum.archive => AssetVisibility.archive,
SyncAssetV1VisibilityEnum.locked => AssetVisibility.locked,
_ => throw Exception('Unknown SyncAssetV1VisibilityEnum value: $this'),
};
} }

View File

@ -53,11 +53,38 @@ final _features = [
await db.localAlbumAssetEntity.deleteAll(); await db.localAlbumAssetEntity.deleteAll();
}, },
), ),
_Feature(
name: 'Clear Remote Data',
icon: Icons.delete_sweep_rounded,
onTap: (_, ref) async {
final db = ref.read(driftProvider);
await db.remoteAssetEntity.deleteAll();
await db.remoteExifEntity.deleteAll();
},
),
_Feature( _Feature(
name: 'Local Media Summary', name: 'Local Media Summary',
icon: Icons.table_chart_rounded, icon: Icons.table_chart_rounded,
onTap: (ctx, _) => ctx.pushRoute(const LocalMediaSummaryRoute()), onTap: (ctx, _) => ctx.pushRoute(const LocalMediaSummaryRoute()),
), ),
_Feature(
name: 'Remote Media Summary',
icon: Icons.summarize_rounded,
onTap: (ctx, _) => ctx.pushRoute(const RemoteMediaSummaryRoute()),
),
_Feature(
name: 'Reset Sqlite',
icon: Icons.table_view_rounded,
onTap: (_, ref) async {
final drift = ref.read(driftProvider);
// ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member
final migrator = drift.createMigrator();
for (final entity in drift.allSchemaEntities) {
await migrator.drop(entity);
await migrator.create(entity);
}
},
),
]; ];
@RoutePage() @RoutePage()

View File

@ -1,3 +1,5 @@
// ignore_for_file: prefer-single-widget-per-file
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -8,7 +10,40 @@ import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
final _stats = [ class _Stat {
const _Stat({required this.name, required this.load});
final String name;
final Future<int> Function(Drift _) load;
}
class _Summary extends StatelessWidget {
final String name;
final Future<int> countFuture;
const _Summary({required this.name, required this.countFuture});
@override
Widget build(BuildContext context) {
return FutureBuilder<int>(
future: countFuture,
builder: (ctx, snapshot) {
final Widget subtitle;
if (snapshot.connectionState == ConnectionState.waiting) {
subtitle = const CircularProgressIndicator();
} else if (snapshot.hasError) {
subtitle = const Icon(Icons.error_rounded);
} else {
subtitle = Text('${snapshot.data ?? 0}');
}
return ListTile(title: Text(name), trailing: subtitle);
},
);
}
}
final _localStats = [
_Stat( _Stat(
name: 'Local Assets', name: 'Local Assets',
load: (db) => db.managers.localAssetEntity.count(), load: (db) => db.managers.localAssetEntity.count(),
@ -36,11 +71,11 @@ class LocalMediaSummaryPage extends StatelessWidget {
slivers: [ slivers: [
SliverList.builder( SliverList.builder(
itemBuilder: (_, index) { itemBuilder: (_, index) {
final stat = _stats[index]; final stat = _localStats[index];
final countFuture = stat.load(db); final countFuture = stat.load(db);
return _Summary(name: stat.name, countFuture: countFuture); return _Summary(name: stat.name, countFuture: countFuture);
}, },
itemCount: _stats.length, itemCount: _localStats.length,
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Column( child: Column(
@ -90,36 +125,43 @@ class LocalMediaSummaryPage extends StatelessWidget {
} }
} }
// ignore: prefer-single-widget-per-file final _remoteStats = [
class _Summary extends StatelessWidget { _Stat(
final String name; name: 'Remote Assets',
final Future<int> countFuture; load: (db) => db.managers.remoteAssetEntity.count(),
),
_Stat(
name: 'Exif Entities',
load: (db) => db.managers.remoteExifEntity.count(),
),
];
const _Summary({required this.name, required this.countFuture}); @RoutePage()
class RemoteMediaSummaryPage extends StatelessWidget {
const RemoteMediaSummaryPage({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FutureBuilder<int>( return Scaffold(
future: countFuture, appBar: AppBar(title: const Text('Remote Media Summary')),
builder: (ctx, snapshot) { body: Consumer(
final Widget subtitle; builder: (ctx, ref, __) {
final db = ref.watch(driftProvider);
if (snapshot.connectionState == ConnectionState.waiting) { return CustomScrollView(
subtitle = const CircularProgressIndicator(); slivers: [
} else if (snapshot.hasError) { SliverList.builder(
subtitle = const Icon(Icons.error_rounded); itemBuilder: (_, index) {
} else { final stat = _remoteStats[index];
subtitle = Text('${snapshot.data ?? 0}'); final countFuture = stat.load(db);
} return _Summary(name: stat.name, countFuture: countFuture);
return ListTile(title: Text(name), trailing: subtitle);
}, },
itemCount: _remoteStats.length,
),
],
);
},
),
); );
} }
} }
class _Stat {
const _Stat({required this.name, required this.load});
final String name;
final Future<int> Function(Drift _) load;
}

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'package:drift/drift.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/album.entity.dart'; import 'package:immich_mobile/entities/album.entity.dart';
@ -8,17 +9,22 @@ import 'package:immich_mobile/entities/etag.entity.dart';
import 'package:immich_mobile/entities/store.entity.dart'; import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/infrastructure/entities/exif.entity.dart'; import 'package:immich_mobile/infrastructure/entities/exif.entity.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/interfaces/auth.interface.dart'; import 'package:immich_mobile/interfaces/auth.interface.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart'; import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/providers/db.provider.dart'; import 'package:immich_mobile/providers/db.provider.dart';
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
import 'package:immich_mobile/repositories/database.repository.dart'; import 'package:immich_mobile/repositories/database.repository.dart';
final authRepositoryProvider = Provider<IAuthRepository>( final authRepositoryProvider = Provider<IAuthRepository>(
(ref) => AuthRepository(ref.watch(dbProvider)), (ref) =>
AuthRepository(ref.watch(dbProvider), drift: ref.watch(driftProvider)),
); );
class AuthRepository extends DatabaseRepository implements IAuthRepository { class AuthRepository extends DatabaseRepository implements IAuthRepository {
AuthRepository(super.db); final Drift _drift;
AuthRepository(super.db, {required Drift drift}) : _drift = drift;
@override @override
Future<void> clearLocalData() { Future<void> clearLocalData() {
@ -29,6 +35,8 @@ class AuthRepository extends DatabaseRepository implements IAuthRepository {
db.albums.clear(), db.albums.clear(),
db.eTags.clear(), db.eTags.clear(),
db.users.clear(), db.users.clear(),
_drift.remoteAssetEntity.deleteAll(),
_drift.remoteExifEntity.deleteAll(),
]); ]);
}); });
} }

View File

@ -64,7 +64,7 @@ import 'package:immich_mobile/pages/search/recently_taken.page.dart';
import 'package:immich_mobile/pages/search/search.page.dart'; import 'package:immich_mobile/pages/search/search.page.dart';
import 'package:immich_mobile/pages/share_intent/share_intent.page.dart'; import 'package:immich_mobile/pages/share_intent/share_intent.page.dart';
import 'package:immich_mobile/presentation/pages/dev/feat_in_development.page.dart'; import 'package:immich_mobile/presentation/pages/dev/feat_in_development.page.dart';
import 'package:immich_mobile/presentation/pages/dev/local_media_stat.page.dart'; import 'package:immich_mobile/presentation/pages/dev/media_stat.page.dart';
import 'package:immich_mobile/providers/api.provider.dart'; import 'package:immich_mobile/providers/api.provider.dart';
import 'package:immich_mobile/providers/gallery_permission.provider.dart'; import 'package:immich_mobile/providers/gallery_permission.provider.dart';
import 'package:immich_mobile/routing/auth_guard.dart'; import 'package:immich_mobile/routing/auth_guard.dart';
@ -326,5 +326,9 @@ class AppRouter extends RootStackRouter {
page: LocalMediaSummaryRoute.page, page: LocalMediaSummaryRoute.page,
guards: [_authGuard, _duplicateGuard], guards: [_authGuard, _duplicateGuard],
), ),
AutoRoute(
page: RemoteMediaSummaryRoute.page,
guards: [_authGuard, _duplicateGuard],
),
]; ];
} }

View File

@ -1356,6 +1356,22 @@ class RecentlyTakenRoute extends PageRouteInfo<void> {
); );
} }
/// generated route for
/// [RemoteMediaSummaryPage]
class RemoteMediaSummaryRoute extends PageRouteInfo<void> {
const RemoteMediaSummaryRoute({List<PageRouteInfo>? children})
: super(RemoteMediaSummaryRoute.name, initialChildren: children);
static const String name = 'RemoteMediaSummaryRoute';
static PageInfo page = PageInfo(
name,
builder: (data) {
return const RemoteMediaSummaryPage();
},
);
}
/// generated route for /// generated route for
/// [SearchPage] /// [SearchPage]
class SearchRoute extends PageRouteInfo<SearchRouteArgs> { class SearchRoute extends PageRouteInfo<SearchRouteArgs> {

View File

@ -21,7 +21,7 @@ create_splash:
build_release_android: build_release_android:
flutter build appbundle flutter build appbundle
migrations: migration:
dart run drift_dev make-migrations dart run drift_dev make-migrations
translation: translation: