feat: sync stream repo impl for assets and exif

This commit is contained in:
shenlong-tanwen 2025-04-21 16:19:22 +05:30
parent 5fc1a63810
commit b44cfe5d1c
18 changed files with 2907 additions and 164 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,3 +1,5 @@
import 'package:immich_mobile/utils/nullable_value.dart';
part 'local_asset.model.dart'; part 'local_asset.model.dart';
part 'merged_asset.model.dart'; part 'merged_asset.model.dart';
part 'remote_asset.model.dart'; part 'remote_asset.model.dart';
@ -16,8 +18,6 @@ sealed class Asset {
final AssetType type; final AssetType type;
final DateTime createdAt; final DateTime createdAt;
final DateTime updatedAt; final DateTime updatedAt;
final int? width;
final int? height;
final int? durationInSeconds; final int? durationInSeconds;
const Asset({ const Asset({
@ -26,8 +26,6 @@ sealed class Asset {
required this.type, required this.type,
required this.createdAt, required this.createdAt,
required this.updatedAt, required this.updatedAt,
this.width,
this.height,
this.durationInSeconds, this.durationInSeconds,
}); });
@ -38,8 +36,6 @@ sealed class Asset {
type: $type, type: $type,
createdAt: $createdAt, createdAt: $createdAt,
updatedAt: $updatedAt, updatedAt: $updatedAt,
width: ${width ?? "<NA>"},
height: ${height ?? "<NA>"},
durationInSeconds: ${durationInSeconds ?? "<NA>"} durationInSeconds: ${durationInSeconds ?? "<NA>"}
}'''; }''';
} }
@ -52,8 +48,6 @@ sealed class Asset {
type == other.type && type == other.type &&
createdAt == other.createdAt && createdAt == other.createdAt &&
updatedAt == other.updatedAt && updatedAt == other.updatedAt &&
width == other.width &&
height == other.height &&
durationInSeconds == other.durationInSeconds; durationInSeconds == other.durationInSeconds;
} }
return false; return false;
@ -65,8 +59,6 @@ sealed class Asset {
type.hashCode ^ type.hashCode ^
createdAt.hashCode ^ createdAt.hashCode ^
updatedAt.hashCode ^ updatedAt.hashCode ^
width.hashCode ^
height.hashCode ^
durationInSeconds.hashCode; durationInSeconds.hashCode;
} }
} }

View file

@ -2,6 +2,8 @@ part of 'asset.model.dart';
class LocalAsset extends Asset { class LocalAsset extends Asset {
final String localId; final String localId;
final int? width;
final int? height;
const LocalAsset({ const LocalAsset({
required this.localId, required this.localId,
@ -10,8 +12,8 @@ class LocalAsset extends Asset {
required super.type, required super.type,
required super.createdAt, required super.createdAt,
required super.updatedAt, required super.updatedAt,
super.width, this.width,
super.height, this.height,
super.durationInSeconds, super.durationInSeconds,
}); });
@ -33,7 +35,10 @@ class LocalAsset extends Asset {
bool operator ==(Object other) { bool operator ==(Object other) {
if (other is! LocalAsset) return false; if (other is! LocalAsset) return false;
if (identical(this, other)) return true; if (identical(this, other)) return true;
return super == other && localId == other.localId; return super == other &&
localId == other.localId &&
width == other.width &&
height == other.height;
} }
@override @override
@ -48,9 +53,9 @@ class LocalAsset extends Asset {
AssetType? type, AssetType? type,
DateTime? createdAt, DateTime? createdAt,
DateTime? updatedAt, DateTime? updatedAt,
int? width, NullableValue<int> width = const NullableValue.absent(),
int? height, NullableValue<int> height = const NullableValue.absent(),
int? durationInSeconds, NullableValue<int> durationInSeconds = const NullableValue.absent(),
}) { }) {
return LocalAsset( return LocalAsset(
localId: localId ?? this.localId, localId: localId ?? this.localId,
@ -59,9 +64,9 @@ class LocalAsset extends Asset {
type: type ?? this.type, type: type ?? this.type,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
width: width ?? this.width, width: width.getOrDefault(this.width),
height: height ?? this.height, height: height.getOrDefault(this.height),
durationInSeconds: durationInSeconds ?? this.durationInSeconds, durationInSeconds: durationInSeconds.getOrDefault(this.durationInSeconds),
); );
} }
} }

View file

@ -12,8 +12,6 @@ class MergedAsset extends Asset {
required super.type, required super.type,
required super.createdAt, required super.createdAt,
required super.updatedAt, required super.updatedAt,
super.width,
super.height,
super.durationInSeconds, super.durationInSeconds,
}); });
@ -26,8 +24,6 @@ class MergedAsset extends Asset {
type: $type, type: $type,
createdAt: $createdAt, createdAt: $createdAt,
updatedAt: $updatedAt, updatedAt: $updatedAt,
width: ${width ?? "<NA>"},
height: ${height ?? "<NA>"},
durationInSeconds: ${durationInSeconds ?? "<NA>"} durationInSeconds: ${durationInSeconds ?? "<NA>"}
}'''; }''';
} }

View file

@ -2,16 +2,24 @@ part of 'asset.model.dart';
class RemoteAsset extends Asset { class RemoteAsset extends Asset {
final String remoteId; final String remoteId;
final bool isFavorite;
final String ownerId;
final DateTime localDateTime;
final String? thumbhash;
final DateTime? deletedAt;
const RemoteAsset({ const RemoteAsset({
required this.remoteId, required this.remoteId,
required this.ownerId,
required super.name, required super.name,
required super.checksum, required super.checksum,
required super.type, required super.type,
required this.isFavorite,
required this.localDateTime,
required super.createdAt, required super.createdAt,
required super.updatedAt, required super.updatedAt,
super.width, this.deletedAt,
super.height, this.thumbhash,
super.durationInSeconds, super.durationInSeconds,
}); });
@ -19,13 +27,15 @@ class RemoteAsset extends Asset {
String toString() { String toString() {
return '''RemoteAsset { return '''RemoteAsset {
remoteId: $remoteId, remoteId: $remoteId,
ownerId: $ownerId,
name: $name, name: $name,
type: $type, type: $type,
isFavorite: $isFavorite,
createdAt: $createdAt, createdAt: $createdAt,
updatedAt: $updatedAt, updatedAt: $updatedAt,
width: ${width ?? "<NA>"}, localDateTime: $localDateTime,
height: ${height ?? "<NA>"}, deletedAt: ${deletedAt ?? "<NA>"},
durationInSeconds: ${durationInSeconds ?? "<NA>"} durationInSeconds: ${durationInSeconds ?? "<NA>"},
}'''; }''';
} }
@ -33,11 +43,23 @@ class RemoteAsset extends Asset {
bool operator ==(Object other) { bool operator ==(Object other) {
if (other is! RemoteAsset) return false; if (other is! RemoteAsset) return false;
if (identical(this, other)) return true; if (identical(this, other)) return true;
return super == other && remoteId == other.remoteId; return super == other &&
remoteId == other.remoteId &&
isFavorite == other.isFavorite &&
ownerId == other.ownerId &&
localDateTime == other.localDateTime &&
deletedAt == other.deletedAt &&
thumbhash == other.thumbhash;
} }
@override @override
int get hashCode { int get hashCode {
return super.hashCode ^ remoteId.hashCode; return super.hashCode ^
remoteId.hashCode ^
isFavorite.hashCode ^
ownerId.hashCode ^
localDateTime.hashCode ^
deletedAt.hashCode ^
thumbhash.hashCode;
} }
} }

View file

@ -32,7 +32,7 @@ class LocalAlbum {
String? name, String? name,
DateTime? updatedAt, DateTime? updatedAt,
int? assetCount, int? assetCount,
NullableValue<String>? thumbnailId, NullableValue<String> thumbnailId = const NullableValue.absent(),
BackupSelection? backupSelection, BackupSelection? backupSelection,
bool? isAll, bool? isAll,
}) { }) {
@ -41,7 +41,7 @@ class LocalAlbum {
name: name ?? this.name, name: name ?? this.name,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
assetCount: assetCount ?? this.assetCount, assetCount: assetCount ?? this.assetCount,
thumbnailId: thumbnailId?.getOrDefault(this.thumbnailId), thumbnailId: thumbnailId.getOrDefault(this.thumbnailId),
backupSelection: backupSelection ?? this.backupSelection, backupSelection: backupSelection ?? this.backupSelection,
isAll: isAll ?? this.isAll, isAll: isAll ?? this.isAll,
); );

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 ExifEntity extends Table with DriftDefaultsMixin {
const ExifEntity();
BlobColumn get assetId => blob()
.references(RemoteAssetEntity, #remoteId, 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

@ -12,6 +12,10 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin {
TextColumn get checksum => text().nullable()(); TextColumn get checksum => text().nullable()();
IntColumn get width => integer().nullable()();
IntColumn get height => integer().nullable()();
@override @override
Set<Column> get primaryKey => {localId}; Set<Column> get primaryKey => {localId};
} }

View file

@ -14,11 +14,11 @@ typedef $$LocalAssetEntityTableCreateCompanionBuilder
required i2.AssetType type, required i2.AssetType type,
i0.Value<DateTime> createdAt, i0.Value<DateTime> createdAt,
i0.Value<DateTime> updatedAt, i0.Value<DateTime> updatedAt,
i0.Value<int?> width,
i0.Value<int?> height,
i0.Value<int?> durationInSeconds, i0.Value<int?> durationInSeconds,
required String localId, required String localId,
i0.Value<String?> checksum, i0.Value<String?> checksum,
i0.Value<int?> width,
i0.Value<int?> height,
}); });
typedef $$LocalAssetEntityTableUpdateCompanionBuilder typedef $$LocalAssetEntityTableUpdateCompanionBuilder
= i1.LocalAssetEntityCompanion Function({ = i1.LocalAssetEntityCompanion Function({
@ -26,11 +26,11 @@ typedef $$LocalAssetEntityTableUpdateCompanionBuilder
i0.Value<i2.AssetType> type, i0.Value<i2.AssetType> type,
i0.Value<DateTime> createdAt, i0.Value<DateTime> createdAt,
i0.Value<DateTime> updatedAt, i0.Value<DateTime> updatedAt,
i0.Value<int?> width,
i0.Value<int?> height,
i0.Value<int?> durationInSeconds, i0.Value<int?> durationInSeconds,
i0.Value<String> localId, i0.Value<String> localId,
i0.Value<String?> checksum, i0.Value<String?> checksum,
i0.Value<int?> width,
i0.Value<int?> height,
}); });
class $$LocalAssetEntityTableFilterComposer class $$LocalAssetEntityTableFilterComposer
@ -56,12 +56,6 @@ class $$LocalAssetEntityTableFilterComposer
i0.ColumnFilters<DateTime> get updatedAt => $composableBuilder( i0.ColumnFilters<DateTime> get updatedAt => $composableBuilder(
column: $table.updatedAt, builder: (column) => i0.ColumnFilters(column)); column: $table.updatedAt, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<int> get width => $composableBuilder(
column: $table.width, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<int> get height => $composableBuilder(
column: $table.height, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<int> get durationInSeconds => $composableBuilder( i0.ColumnFilters<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds, column: $table.durationInSeconds,
builder: (column) => i0.ColumnFilters(column)); builder: (column) => i0.ColumnFilters(column));
@ -71,6 +65,12 @@ class $$LocalAssetEntityTableFilterComposer
i0.ColumnFilters<String> get checksum => $composableBuilder( i0.ColumnFilters<String> get checksum => $composableBuilder(
column: $table.checksum, builder: (column) => i0.ColumnFilters(column)); column: $table.checksum, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<int> get width => $composableBuilder(
column: $table.width, builder: (column) => i0.ColumnFilters(column));
i0.ColumnFilters<int> get height => $composableBuilder(
column: $table.height, builder: (column) => i0.ColumnFilters(column));
} }
class $$LocalAssetEntityTableOrderingComposer class $$LocalAssetEntityTableOrderingComposer
@ -96,12 +96,6 @@ class $$LocalAssetEntityTableOrderingComposer
column: $table.updatedAt, column: $table.updatedAt,
builder: (column) => i0.ColumnOrderings(column)); builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<int> get width => $composableBuilder(
column: $table.width, builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<int> get height => $composableBuilder(
column: $table.height, builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<int> get durationInSeconds => $composableBuilder( i0.ColumnOrderings<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds, column: $table.durationInSeconds,
builder: (column) => i0.ColumnOrderings(column)); builder: (column) => i0.ColumnOrderings(column));
@ -111,6 +105,12 @@ class $$LocalAssetEntityTableOrderingComposer
i0.ColumnOrderings<String> get checksum => $composableBuilder( i0.ColumnOrderings<String> get checksum => $composableBuilder(
column: $table.checksum, builder: (column) => i0.ColumnOrderings(column)); column: $table.checksum, builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<int> get width => $composableBuilder(
column: $table.width, builder: (column) => i0.ColumnOrderings(column));
i0.ColumnOrderings<int> get height => $composableBuilder(
column: $table.height, builder: (column) => i0.ColumnOrderings(column));
} }
class $$LocalAssetEntityTableAnnotationComposer class $$LocalAssetEntityTableAnnotationComposer
@ -134,12 +134,6 @@ class $$LocalAssetEntityTableAnnotationComposer
i0.GeneratedColumn<DateTime> get updatedAt => i0.GeneratedColumn<DateTime> get updatedAt =>
$composableBuilder(column: $table.updatedAt, builder: (column) => column); $composableBuilder(column: $table.updatedAt, builder: (column) => column);
i0.GeneratedColumn<int> get width =>
$composableBuilder(column: $table.width, builder: (column) => column);
i0.GeneratedColumn<int> get height =>
$composableBuilder(column: $table.height, builder: (column) => column);
i0.GeneratedColumn<int> get durationInSeconds => $composableBuilder( i0.GeneratedColumn<int> get durationInSeconds => $composableBuilder(
column: $table.durationInSeconds, builder: (column) => column); column: $table.durationInSeconds, builder: (column) => column);
@ -148,6 +142,12 @@ class $$LocalAssetEntityTableAnnotationComposer
i0.GeneratedColumn<String> get checksum => i0.GeneratedColumn<String> get checksum =>
$composableBuilder(column: $table.checksum, builder: (column) => column); $composableBuilder(column: $table.checksum, builder: (column) => column);
i0.GeneratedColumn<int> get width =>
$composableBuilder(column: $table.width, builder: (column) => column);
i0.GeneratedColumn<int> get height =>
$composableBuilder(column: $table.height, builder: (column) => column);
} }
class $$LocalAssetEntityTableTableManager extends i0.RootTableManager< class $$LocalAssetEntityTableTableManager extends i0.RootTableManager<
@ -183,44 +183,44 @@ class $$LocalAssetEntityTableTableManager extends i0.RootTableManager<
i0.Value<i2.AssetType> type = const i0.Value.absent(), i0.Value<i2.AssetType> type = const i0.Value.absent(),
i0.Value<DateTime> createdAt = const i0.Value.absent(), i0.Value<DateTime> createdAt = const i0.Value.absent(),
i0.Value<DateTime> updatedAt = const i0.Value.absent(), i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(), i0.Value<int?> durationInSeconds = const i0.Value.absent(),
i0.Value<String> localId = const i0.Value.absent(), i0.Value<String> localId = const i0.Value.absent(),
i0.Value<String?> checksum = const i0.Value.absent(), i0.Value<String?> checksum = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
}) => }) =>
i1.LocalAssetEntityCompanion( i1.LocalAssetEntityCompanion(
name: name, name: name,
type: type, type: type,
createdAt: createdAt, createdAt: createdAt,
updatedAt: updatedAt, updatedAt: updatedAt,
width: width,
height: height,
durationInSeconds: durationInSeconds, durationInSeconds: durationInSeconds,
localId: localId, localId: localId,
checksum: checksum, checksum: checksum,
width: width,
height: height,
), ),
createCompanionCallback: ({ createCompanionCallback: ({
required String name, required String name,
required i2.AssetType type, required i2.AssetType type,
i0.Value<DateTime> createdAt = const i0.Value.absent(), i0.Value<DateTime> createdAt = const i0.Value.absent(),
i0.Value<DateTime> updatedAt = const i0.Value.absent(), i0.Value<DateTime> updatedAt = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(), i0.Value<int?> durationInSeconds = const i0.Value.absent(),
required String localId, required String localId,
i0.Value<String?> checksum = const i0.Value.absent(), i0.Value<String?> checksum = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
}) => }) =>
i1.LocalAssetEntityCompanion.insert( i1.LocalAssetEntityCompanion.insert(
name: name, name: name,
type: type, type: type,
createdAt: createdAt, createdAt: createdAt,
updatedAt: updatedAt, updatedAt: updatedAt,
width: width,
height: height,
durationInSeconds: durationInSeconds, durationInSeconds: durationInSeconds,
localId: localId, localId: localId,
checksum: checksum, checksum: checksum,
width: width,
height: height,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper: (p0) => p0
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e))) .map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
@ -282,18 +282,6 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
type: i0.DriftSqlType.dateTime, type: i0.DriftSqlType.dateTime,
requiredDuringInsert: false, requiredDuringInsert: false,
defaultValue: i4.currentDateAndTime); defaultValue: i4.currentDateAndTime);
static const i0.VerificationMeta _widthMeta =
const i0.VerificationMeta('width');
@override
late final i0.GeneratedColumn<int> width = i0.GeneratedColumn<int>(
'width', aliasedName, true,
type: i0.DriftSqlType.int, requiredDuringInsert: false);
static const i0.VerificationMeta _heightMeta =
const i0.VerificationMeta('height');
@override
late final i0.GeneratedColumn<int> height = i0.GeneratedColumn<int>(
'height', aliasedName, true,
type: i0.DriftSqlType.int, requiredDuringInsert: false);
static const i0.VerificationMeta _durationInSecondsMeta = static const i0.VerificationMeta _durationInSecondsMeta =
const i0.VerificationMeta('durationInSeconds'); const i0.VerificationMeta('durationInSeconds');
@override @override
@ -312,17 +300,29 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
late final i0.GeneratedColumn<String> checksum = i0.GeneratedColumn<String>( late final i0.GeneratedColumn<String> checksum = i0.GeneratedColumn<String>(
'checksum', aliasedName, true, 'checksum', aliasedName, true,
type: i0.DriftSqlType.string, requiredDuringInsert: false); type: i0.DriftSqlType.string, requiredDuringInsert: false);
static const i0.VerificationMeta _widthMeta =
const i0.VerificationMeta('width');
@override
late final i0.GeneratedColumn<int> width = i0.GeneratedColumn<int>(
'width', aliasedName, true,
type: i0.DriftSqlType.int, requiredDuringInsert: false);
static const i0.VerificationMeta _heightMeta =
const i0.VerificationMeta('height');
@override
late final i0.GeneratedColumn<int> height = i0.GeneratedColumn<int>(
'height', aliasedName, true,
type: i0.DriftSqlType.int, requiredDuringInsert: false);
@override @override
List<i0.GeneratedColumn> get $columns => [ List<i0.GeneratedColumn> get $columns => [
name, name,
type, type,
createdAt, createdAt,
updatedAt, updatedAt,
width,
height,
durationInSeconds, durationInSeconds,
localId, localId,
checksum checksum,
width,
height
]; ];
@override @override
String get aliasedName => _alias ?? actualTableName; String get aliasedName => _alias ?? actualTableName;
@ -349,14 +349,6 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
context.handle(_updatedAtMeta, context.handle(_updatedAtMeta,
updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta));
} }
if (data.containsKey('width')) {
context.handle(
_widthMeta, width.isAcceptableOrUnknown(data['width']!, _widthMeta));
}
if (data.containsKey('height')) {
context.handle(_heightMeta,
height.isAcceptableOrUnknown(data['height']!, _heightMeta));
}
if (data.containsKey('duration_in_seconds')) { if (data.containsKey('duration_in_seconds')) {
context.handle( context.handle(
_durationInSecondsMeta, _durationInSecondsMeta,
@ -373,6 +365,14 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
context.handle(_checksumMeta, context.handle(_checksumMeta,
checksum.isAcceptableOrUnknown(data['checksum']!, _checksumMeta)); checksum.isAcceptableOrUnknown(data['checksum']!, _checksumMeta));
} }
if (data.containsKey('width')) {
context.handle(
_widthMeta, width.isAcceptableOrUnknown(data['width']!, _widthMeta));
}
if (data.containsKey('height')) {
context.handle(_heightMeta,
height.isAcceptableOrUnknown(data['height']!, _heightMeta));
}
return context; return context;
} }
@ -392,16 +392,16 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity
i0.DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, i0.DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!,
updatedAt: attachedDatabase.typeMapping.read( updatedAt: attachedDatabase.typeMapping.read(
i0.DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, i0.DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!,
width: attachedDatabase.typeMapping
.read(i0.DriftSqlType.int, data['${effectivePrefix}width']),
height: attachedDatabase.typeMapping
.read(i0.DriftSqlType.int, data['${effectivePrefix}height']),
durationInSeconds: attachedDatabase.typeMapping.read( durationInSeconds: attachedDatabase.typeMapping.read(
i0.DriftSqlType.int, data['${effectivePrefix}duration_in_seconds']), i0.DriftSqlType.int, data['${effectivePrefix}duration_in_seconds']),
localId: attachedDatabase.typeMapping localId: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}local_id'])!, .read(i0.DriftSqlType.string, data['${effectivePrefix}local_id'])!,
checksum: attachedDatabase.typeMapping checksum: attachedDatabase.typeMapping
.read(i0.DriftSqlType.string, data['${effectivePrefix}checksum']), .read(i0.DriftSqlType.string, data['${effectivePrefix}checksum']),
width: attachedDatabase.typeMapping
.read(i0.DriftSqlType.int, data['${effectivePrefix}width']),
height: attachedDatabase.typeMapping
.read(i0.DriftSqlType.int, data['${effectivePrefix}height']),
); );
} }
@ -424,21 +424,21 @@ class LocalAssetEntityData extends i0.DataClass
final i2.AssetType type; final i2.AssetType type;
final DateTime createdAt; final DateTime createdAt;
final DateTime updatedAt; final DateTime updatedAt;
final int? width;
final int? height;
final int? durationInSeconds; final int? durationInSeconds;
final String localId; final String localId;
final String? checksum; final String? checksum;
final int? width;
final int? height;
const LocalAssetEntityData( const LocalAssetEntityData(
{required this.name, {required this.name,
required this.type, required this.type,
required this.createdAt, required this.createdAt,
required this.updatedAt, required this.updatedAt,
this.width,
this.height,
this.durationInSeconds, this.durationInSeconds,
required this.localId, required this.localId,
this.checksum}); this.checksum,
this.width,
this.height});
@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>{};
@ -449,12 +449,6 @@ class LocalAssetEntityData extends i0.DataClass
} }
map['created_at'] = i0.Variable<DateTime>(createdAt); map['created_at'] = i0.Variable<DateTime>(createdAt);
map['updated_at'] = i0.Variable<DateTime>(updatedAt); map['updated_at'] = i0.Variable<DateTime>(updatedAt);
if (!nullToAbsent || width != null) {
map['width'] = i0.Variable<int>(width);
}
if (!nullToAbsent || height != null) {
map['height'] = i0.Variable<int>(height);
}
if (!nullToAbsent || durationInSeconds != null) { if (!nullToAbsent || durationInSeconds != null) {
map['duration_in_seconds'] = i0.Variable<int>(durationInSeconds); map['duration_in_seconds'] = i0.Variable<int>(durationInSeconds);
} }
@ -462,6 +456,12 @@ class LocalAssetEntityData extends i0.DataClass
if (!nullToAbsent || checksum != null) { if (!nullToAbsent || checksum != null) {
map['checksum'] = i0.Variable<String>(checksum); map['checksum'] = i0.Variable<String>(checksum);
} }
if (!nullToAbsent || width != null) {
map['width'] = i0.Variable<int>(width);
}
if (!nullToAbsent || height != null) {
map['height'] = i0.Variable<int>(height);
}
return map; return map;
} }
@ -474,11 +474,11 @@ class LocalAssetEntityData extends i0.DataClass
.fromJson(serializer.fromJson<int>(json['type'])), .fromJson(serializer.fromJson<int>(json['type'])),
createdAt: serializer.fromJson<DateTime>(json['createdAt']), createdAt: serializer.fromJson<DateTime>(json['createdAt']),
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']), updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
width: serializer.fromJson<int?>(json['width']),
height: serializer.fromJson<int?>(json['height']),
durationInSeconds: serializer.fromJson<int?>(json['durationInSeconds']), durationInSeconds: serializer.fromJson<int?>(json['durationInSeconds']),
localId: serializer.fromJson<String>(json['localId']), localId: serializer.fromJson<String>(json['localId']),
checksum: serializer.fromJson<String?>(json['checksum']), checksum: serializer.fromJson<String?>(json['checksum']),
width: serializer.fromJson<int?>(json['width']),
height: serializer.fromJson<int?>(json['height']),
); );
} }
@override @override
@ -490,11 +490,11 @@ class LocalAssetEntityData extends i0.DataClass
.toJson<int>(i1.$LocalAssetEntityTable.$convertertype.toJson(type)), .toJson<int>(i1.$LocalAssetEntityTable.$convertertype.toJson(type)),
'createdAt': serializer.toJson<DateTime>(createdAt), 'createdAt': serializer.toJson<DateTime>(createdAt),
'updatedAt': serializer.toJson<DateTime>(updatedAt), 'updatedAt': serializer.toJson<DateTime>(updatedAt),
'width': serializer.toJson<int?>(width),
'height': serializer.toJson<int?>(height),
'durationInSeconds': serializer.toJson<int?>(durationInSeconds), 'durationInSeconds': serializer.toJson<int?>(durationInSeconds),
'localId': serializer.toJson<String>(localId), 'localId': serializer.toJson<String>(localId),
'checksum': serializer.toJson<String?>(checksum), 'checksum': serializer.toJson<String?>(checksum),
'width': serializer.toJson<int?>(width),
'height': serializer.toJson<int?>(height),
}; };
} }
@ -503,23 +503,23 @@ class LocalAssetEntityData extends i0.DataClass
i2.AssetType? type, i2.AssetType? type,
DateTime? createdAt, DateTime? createdAt,
DateTime? updatedAt, DateTime? updatedAt,
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent(),
i0.Value<int?> durationInSeconds = const i0.Value.absent(), i0.Value<int?> durationInSeconds = const i0.Value.absent(),
String? localId, String? localId,
i0.Value<String?> checksum = const i0.Value.absent()}) => i0.Value<String?> checksum = const i0.Value.absent(),
i0.Value<int?> width = const i0.Value.absent(),
i0.Value<int?> height = const i0.Value.absent()}) =>
i1.LocalAssetEntityData( i1.LocalAssetEntityData(
name: name ?? this.name, name: name ?? this.name,
type: type ?? this.type, type: type ?? this.type,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
width: width.present ? width.value : this.width,
height: height.present ? height.value : this.height,
durationInSeconds: durationInSeconds.present durationInSeconds: durationInSeconds.present
? durationInSeconds.value ? durationInSeconds.value
: this.durationInSeconds, : this.durationInSeconds,
localId: localId ?? this.localId, localId: localId ?? this.localId,
checksum: checksum.present ? checksum.value : this.checksum, checksum: checksum.present ? checksum.value : this.checksum,
width: width.present ? width.value : this.width,
height: height.present ? height.value : this.height,
); );
LocalAssetEntityData copyWithCompanion(i1.LocalAssetEntityCompanion data) { LocalAssetEntityData copyWithCompanion(i1.LocalAssetEntityCompanion data) {
return LocalAssetEntityData( return LocalAssetEntityData(
@ -527,13 +527,13 @@ class LocalAssetEntityData extends i0.DataClass
type: data.type.present ? data.type.value : this.type, type: data.type.present ? data.type.value : this.type,
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
width: data.width.present ? data.width.value : this.width,
height: data.height.present ? data.height.value : this.height,
durationInSeconds: data.durationInSeconds.present durationInSeconds: data.durationInSeconds.present
? data.durationInSeconds.value ? data.durationInSeconds.value
: this.durationInSeconds, : this.durationInSeconds,
localId: data.localId.present ? data.localId.value : this.localId, localId: data.localId.present ? data.localId.value : this.localId,
checksum: data.checksum.present ? data.checksum.value : this.checksum, checksum: data.checksum.present ? data.checksum.value : this.checksum,
width: data.width.present ? data.width.value : this.width,
height: data.height.present ? data.height.value : this.height,
); );
} }
@ -544,18 +544,18 @@ class LocalAssetEntityData extends i0.DataClass
..write('type: $type, ') ..write('type: $type, ')
..write('createdAt: $createdAt, ') ..write('createdAt: $createdAt, ')
..write('updatedAt: $updatedAt, ') ..write('updatedAt: $updatedAt, ')
..write('width: $width, ')
..write('height: $height, ')
..write('durationInSeconds: $durationInSeconds, ') ..write('durationInSeconds: $durationInSeconds, ')
..write('localId: $localId, ') ..write('localId: $localId, ')
..write('checksum: $checksum') ..write('checksum: $checksum, ')
..write('width: $width, ')
..write('height: $height')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@override @override
int get hashCode => Object.hash(name, type, createdAt, updatedAt, width, int get hashCode => Object.hash(name, type, createdAt, updatedAt,
height, durationInSeconds, localId, checksum); durationInSeconds, localId, checksum, width, height);
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
@ -564,11 +564,11 @@ class LocalAssetEntityData extends i0.DataClass
other.type == this.type && other.type == this.type &&
other.createdAt == this.createdAt && other.createdAt == this.createdAt &&
other.updatedAt == this.updatedAt && other.updatedAt == this.updatedAt &&
other.width == this.width &&
other.height == this.height &&
other.durationInSeconds == this.durationInSeconds && other.durationInSeconds == this.durationInSeconds &&
other.localId == this.localId && other.localId == this.localId &&
other.checksum == this.checksum); other.checksum == this.checksum &&
other.width == this.width &&
other.height == this.height);
} }
class LocalAssetEntityCompanion class LocalAssetEntityCompanion
@ -577,32 +577,32 @@ class LocalAssetEntityCompanion
final i0.Value<i2.AssetType> type; final i0.Value<i2.AssetType> type;
final i0.Value<DateTime> createdAt; final i0.Value<DateTime> createdAt;
final i0.Value<DateTime> updatedAt; final i0.Value<DateTime> updatedAt;
final i0.Value<int?> width;
final i0.Value<int?> height;
final i0.Value<int?> durationInSeconds; final i0.Value<int?> durationInSeconds;
final i0.Value<String> localId; final i0.Value<String> localId;
final i0.Value<String?> checksum; final i0.Value<String?> checksum;
final i0.Value<int?> width;
final i0.Value<int?> height;
const LocalAssetEntityCompanion({ const LocalAssetEntityCompanion({
this.name = const i0.Value.absent(), this.name = const i0.Value.absent(),
this.type = const i0.Value.absent(), this.type = const i0.Value.absent(),
this.createdAt = const i0.Value.absent(), this.createdAt = const i0.Value.absent(),
this.updatedAt = const i0.Value.absent(), this.updatedAt = const i0.Value.absent(),
this.width = const i0.Value.absent(),
this.height = const i0.Value.absent(),
this.durationInSeconds = const i0.Value.absent(), this.durationInSeconds = const i0.Value.absent(),
this.localId = const i0.Value.absent(), this.localId = const i0.Value.absent(),
this.checksum = const i0.Value.absent(), this.checksum = const i0.Value.absent(),
this.width = const i0.Value.absent(),
this.height = const i0.Value.absent(),
}); });
LocalAssetEntityCompanion.insert({ LocalAssetEntityCompanion.insert({
required String name, required String name,
required i2.AssetType type, required i2.AssetType type,
this.createdAt = const i0.Value.absent(), this.createdAt = const i0.Value.absent(),
this.updatedAt = const i0.Value.absent(), this.updatedAt = const i0.Value.absent(),
this.width = const i0.Value.absent(),
this.height = const i0.Value.absent(),
this.durationInSeconds = const i0.Value.absent(), this.durationInSeconds = const i0.Value.absent(),
required String localId, required String localId,
this.checksum = const i0.Value.absent(), this.checksum = const i0.Value.absent(),
this.width = const i0.Value.absent(),
this.height = const i0.Value.absent(),
}) : name = i0.Value(name), }) : name = i0.Value(name),
type = i0.Value(type), type = i0.Value(type),
localId = i0.Value(localId); localId = i0.Value(localId);
@ -611,22 +611,22 @@ class LocalAssetEntityCompanion
i0.Expression<int>? type, i0.Expression<int>? type,
i0.Expression<DateTime>? createdAt, i0.Expression<DateTime>? createdAt,
i0.Expression<DateTime>? updatedAt, i0.Expression<DateTime>? updatedAt,
i0.Expression<int>? width,
i0.Expression<int>? height,
i0.Expression<int>? durationInSeconds, i0.Expression<int>? durationInSeconds,
i0.Expression<String>? localId, i0.Expression<String>? localId,
i0.Expression<String>? checksum, i0.Expression<String>? checksum,
i0.Expression<int>? width,
i0.Expression<int>? height,
}) { }) {
return i0.RawValuesInsertable({ return i0.RawValuesInsertable({
if (name != null) 'name': name, if (name != null) 'name': name,
if (type != null) 'type': type, if (type != null) 'type': type,
if (createdAt != null) 'created_at': createdAt, if (createdAt != null) 'created_at': createdAt,
if (updatedAt != null) 'updated_at': updatedAt, if (updatedAt != null) 'updated_at': updatedAt,
if (width != null) 'width': width,
if (height != null) 'height': height,
if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds,
if (localId != null) 'local_id': localId, if (localId != null) 'local_id': localId,
if (checksum != null) 'checksum': checksum, if (checksum != null) 'checksum': checksum,
if (width != null) 'width': width,
if (height != null) 'height': height,
}); });
} }
@ -635,21 +635,21 @@ class LocalAssetEntityCompanion
i0.Value<i2.AssetType>? type, i0.Value<i2.AssetType>? type,
i0.Value<DateTime>? createdAt, i0.Value<DateTime>? createdAt,
i0.Value<DateTime>? updatedAt, i0.Value<DateTime>? updatedAt,
i0.Value<int?>? width,
i0.Value<int?>? height,
i0.Value<int?>? durationInSeconds, i0.Value<int?>? durationInSeconds,
i0.Value<String>? localId, i0.Value<String>? localId,
i0.Value<String?>? checksum}) { i0.Value<String?>? checksum,
i0.Value<int?>? width,
i0.Value<int?>? height}) {
return i1.LocalAssetEntityCompanion( return i1.LocalAssetEntityCompanion(
name: name ?? this.name, name: name ?? this.name,
type: type ?? this.type, type: type ?? this.type,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt, updatedAt: updatedAt ?? this.updatedAt,
width: width ?? this.width,
height: height ?? this.height,
durationInSeconds: durationInSeconds ?? this.durationInSeconds, durationInSeconds: durationInSeconds ?? this.durationInSeconds,
localId: localId ?? this.localId, localId: localId ?? this.localId,
checksum: checksum ?? this.checksum, checksum: checksum ?? this.checksum,
width: width ?? this.width,
height: height ?? this.height,
); );
} }
@ -669,12 +669,6 @@ class LocalAssetEntityCompanion
if (updatedAt.present) { if (updatedAt.present) {
map['updated_at'] = i0.Variable<DateTime>(updatedAt.value); map['updated_at'] = i0.Variable<DateTime>(updatedAt.value);
} }
if (width.present) {
map['width'] = i0.Variable<int>(width.value);
}
if (height.present) {
map['height'] = i0.Variable<int>(height.value);
}
if (durationInSeconds.present) { if (durationInSeconds.present) {
map['duration_in_seconds'] = i0.Variable<int>(durationInSeconds.value); map['duration_in_seconds'] = i0.Variable<int>(durationInSeconds.value);
} }
@ -684,6 +678,12 @@ class LocalAssetEntityCompanion
if (checksum.present) { if (checksum.present) {
map['checksum'] = i0.Variable<String>(checksum.value); map['checksum'] = i0.Variable<String>(checksum.value);
} }
if (width.present) {
map['width'] = i0.Variable<int>(width.value);
}
if (height.present) {
map['height'] = i0.Variable<int>(height.value);
}
return map; return map;
} }
@ -694,11 +694,11 @@ class LocalAssetEntityCompanion
..write('type: $type, ') ..write('type: $type, ')
..write('createdAt: $createdAt, ') ..write('createdAt: $createdAt, ')
..write('updatedAt: $updatedAt, ') ..write('updatedAt: $updatedAt, ')
..write('width: $width, ')
..write('height: $height, ')
..write('durationInSeconds: $durationInSeconds, ') ..write('durationInSeconds: $durationInSeconds, ')
..write('localId: $localId, ') ..write('localId: $localId, ')
..write('checksum: $checksum') ..write('checksum: $checksum, ')
..write('width: $width, ')
..write('height: $height')
..write(')')) ..write(')'))
.toString(); .toString();
} }

View file

@ -0,0 +1,28 @@
import 'package:drift/drift.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: 'remote_asset_checksum', columns: {#checksum})
class RemoteAssetEntity extends Table
with DriftDefaultsMixin, AssetEntityMixin {
const RemoteAssetEntity();
BlobColumn get remoteId => blob()();
TextColumn get checksum => text().unique()();
BoolColumn get isFavorite => boolean().withDefault(const Constant(false))();
BlobColumn get ownerId =>
blob().references(UserEntity, #id, onDelete: KeyAction.cascade)();
DateTimeColumn get localDateTime => dateTime().nullable()();
TextColumn get thumbhash => text().nullable()();
DateTimeColumn get deletedAt => dateTime().nullable()();
@override
Set<Column> get primaryKey => {remoteId};
}

File diff suppressed because it is too large Load diff

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,
ExifEntity,
], ],
) )
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_album.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,9 @@ abstract class $Drift extends i0.GeneratedDatabase {
i5.$LocalAlbumEntityTable(this); i5.$LocalAlbumEntityTable(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.$ExifEntityTable exifEntity = i8.$ExifEntityTable(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 +46,10 @@ abstract class $Drift extends i0.GeneratedDatabase {
localAssetEntity, localAssetEntity,
localAlbumEntity, localAlbumEntity,
localAlbumAssetEntity, localAlbumAssetEntity,
i4.localAssetChecksum remoteAssetEntity,
exifEntity,
i4.localAssetChecksum,
i7.remoteAssetChecksum
]; ];
@override @override
i0.StreamQueryUpdateRules get streamUpdateRules => i0.StreamQueryUpdateRules get streamUpdateRules =>
@ -90,6 +100,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('exif_entity', kind: i0.UpdateKind.delete),
],
),
], ],
); );
@override @override
@ -112,4 +136,8 @@ class $DriftManager {
i5.$$LocalAlbumEntityTableTableManager(_db, _db.localAlbumEntity); i5.$$LocalAlbumEntityTableTableManager(_db, _db.localAlbumEntity);
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.$$ExifEntityTableTableManager get exifEntity =>
i8.$$ExifEntityTableTableManager(_db, _db.exifEntity);
} }

View file

@ -1,8 +1,10 @@
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/domain/models/asset/asset.model.dart';
import 'package:immich_mobile/extensions/string_extensions.dart'; import 'package:immich_mobile/extensions/string_extensions.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';
@ -99,36 +101,144 @@ 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: const Value(''), // TODO: Needed from the server
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.toUuidByte()),
localDateTime: Value(asset.localDateTime),
thumbhash: Value(asset.thumbhash),
deletedAt: Value(asset.deletedAt),
);
batch.insert(
_db.remoteAssetEntity,
companion.copyWith(remoteId: Value(asset.id.toUuidByte())),
onConflict: DoUpdate((_) => companion),
);
}
});
Future<void> _deleteAssetsV1(Iterable<SyncAssetDeleteV1> assets) =>
_db.batch((batch) {
for (final asset in assets) {
batch.delete(
_db.remoteAssetEntity,
RemoteAssetEntityCompanion(
remoteId: Value(asset.assetId.toUuidByte()),
),
);
}
});
Future<void> _updateAssetExifV1(Iterable<SyncAssetExifV1> data) =>
_db.batch((batch) {
for (final exif in data) {
final companion = ExifEntityCompanion(
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.exifEntity,
companion.copyWith(assetId: Value(exif.assetId.toUuidByte())),
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'),
};
} }

View file

@ -6,7 +6,5 @@ mixin AssetEntityMixin on Table {
IntColumn get type => intEnum<AssetType>()(); IntColumn get type => intEnum<AssetType>()();
DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)();
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
IntColumn get width => integer().nullable()();
IntColumn get height => integer().nullable()();
IntColumn get durationInSeconds => integer().nullable()(); IntColumn get durationInSeconds => integer().nullable()();
} }

View file

@ -8,6 +8,9 @@ class NullableValue<T> {
const NullableValue._(this._value, {bool present = false}) const NullableValue._(this._value, {bool present = false})
: _present = present; : _present = present;
/// Creates an instance without value
const NullableValue.absent() : this._(null, present: false);
/// Forces the value to be null /// Forces the value to be null
const NullableValue.empty() : this._(null, present: true); const NullableValue.empty() : this._(null, present: true);

View file

@ -361,7 +361,8 @@ void main() {
updateTimeCond: any(named: 'updateTimeCond'), updateTimeCond: any(named: 'updateTimeCond'),
), ),
).thenAnswer((_) async => [newAsset]); ).thenAnswer((_) async => [newAsset]);
final dbAlbumNoThumb = dbAlbum.copyWith(thumbnailId: null); final dbAlbumNoThumb =
dbAlbum.copyWith(thumbnailId: const NullableValue.absent());
final result = final result =
await sut.updateAlbum(dbAlbumNoThumb, LocalAlbumStub.album1); await sut.updateAlbum(dbAlbumNoThumb, LocalAlbumStub.album1);
@ -612,7 +613,8 @@ void main() {
}); });
test('returns true and sets new thumbnail if db thumb is null', () async { test('returns true and sets new thumbnail if db thumb is null', () async {
final dbAlbumNoThumb = dbAlbum.copyWith(thumbnailId: null); final dbAlbumNoThumb =
dbAlbum.copyWith(thumbnailId: const NullableValue.empty());
final newAsset = LocalAssetStub.image2.copyWith( final newAsset = LocalAssetStub.image2.copyWith(
localId: "asset2", localId: "asset2",
createdAt: DateTime(2024, 1, 1, 10, 30, 0), createdAt: DateTime(2024, 1, 1, 10, 30, 0),