refactor: yeet old timeline (#27666)

* refactor: yank old timeline

# Conflicts:
#	mobile/lib/presentation/pages/editing/drift_edit.page.dart
#	mobile/lib/providers/websocket.provider.dart
#	mobile/lib/routing/router.dart

* more cleanup

* remove native code

* chore: bump sqlite-data version

* remove old background tasks from BGTaskSchedulerPermittedIdentifiers

* rebase

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong
2026-04-15 23:00:27 +05:30
committed by GitHub
parent 6dd6053222
commit 79fccdbee0
367 changed files with 332 additions and 50870 deletions
@@ -1,25 +0,0 @@
import 'dart:typed_data';
import 'package:immich_mobile/domain/models/device_asset.model.dart';
import 'package:immich_mobile/utils/hash.dart';
import 'package:isar/isar.dart';
part 'device_asset.entity.g.dart';
@Collection(inheritance: false)
class DeviceAssetEntity {
Id get id => fastHash(assetId);
@Index(replace: true, unique: true, type: IndexType.hash)
final String assetId;
@Index(unique: false, type: IndexType.hash)
final List<byte> hash;
final DateTime modifiedTime;
const DeviceAssetEntity({required this.assetId, required this.hash, required this.modifiedTime});
DeviceAsset toModel() => DeviceAsset(assetId: assetId, hash: Uint8List.fromList(hash), modifiedTime: modifiedTime);
static DeviceAssetEntity fromDto(DeviceAsset dto) =>
DeviceAssetEntity(assetId: dto.assetId, hash: dto.hash, modifiedTime: dto.modifiedTime);
}
@@ -1,874 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'device_asset.entity.dart';
// **************************************************************************
// IsarCollectionGenerator
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetDeviceAssetEntityCollection on Isar {
IsarCollection<DeviceAssetEntity> get deviceAssetEntitys => this.collection();
}
const DeviceAssetEntitySchema = CollectionSchema(
name: r'DeviceAssetEntity',
id: 6967030785073446271,
properties: {
r'assetId': PropertySchema(id: 0, name: r'assetId', type: IsarType.string),
r'hash': PropertySchema(id: 1, name: r'hash', type: IsarType.byteList),
r'modifiedTime': PropertySchema(
id: 2,
name: r'modifiedTime',
type: IsarType.dateTime,
),
},
estimateSize: _deviceAssetEntityEstimateSize,
serialize: _deviceAssetEntitySerialize,
deserialize: _deviceAssetEntityDeserialize,
deserializeProp: _deviceAssetEntityDeserializeProp,
idName: r'id',
indexes: {
r'assetId': IndexSchema(
id: 174362542210192109,
name: r'assetId',
unique: true,
replace: true,
properties: [
IndexPropertySchema(
name: r'assetId',
type: IndexType.hash,
caseSensitive: true,
),
],
),
r'hash': IndexSchema(
id: -7973251393006690288,
name: r'hash',
unique: false,
replace: false,
properties: [
IndexPropertySchema(
name: r'hash',
type: IndexType.hash,
caseSensitive: false,
),
],
),
},
links: {},
embeddedSchemas: {},
getId: _deviceAssetEntityGetId,
getLinks: _deviceAssetEntityGetLinks,
attach: _deviceAssetEntityAttach,
version: '3.3.0-dev.3',
);
int _deviceAssetEntityEstimateSize(
DeviceAssetEntity object,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
var bytesCount = offsets.last;
bytesCount += 3 + object.assetId.length * 3;
bytesCount += 3 + object.hash.length;
return bytesCount;
}
void _deviceAssetEntitySerialize(
DeviceAssetEntity object,
IsarWriter writer,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
writer.writeString(offsets[0], object.assetId);
writer.writeByteList(offsets[1], object.hash);
writer.writeDateTime(offsets[2], object.modifiedTime);
}
DeviceAssetEntity _deviceAssetEntityDeserialize(
Id id,
IsarReader reader,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
final object = DeviceAssetEntity(
assetId: reader.readString(offsets[0]),
hash: reader.readByteList(offsets[1]) ?? [],
modifiedTime: reader.readDateTime(offsets[2]),
);
return object;
}
P _deviceAssetEntityDeserializeProp<P>(
IsarReader reader,
int propertyId,
int offset,
Map<Type, List<int>> allOffsets,
) {
switch (propertyId) {
case 0:
return (reader.readString(offset)) as P;
case 1:
return (reader.readByteList(offset) ?? []) as P;
case 2:
return (reader.readDateTime(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
}
}
Id _deviceAssetEntityGetId(DeviceAssetEntity object) {
return object.id;
}
List<IsarLinkBase<dynamic>> _deviceAssetEntityGetLinks(
DeviceAssetEntity object,
) {
return [];
}
void _deviceAssetEntityAttach(
IsarCollection<dynamic> col,
Id id,
DeviceAssetEntity object,
) {}
extension DeviceAssetEntityByIndex on IsarCollection<DeviceAssetEntity> {
Future<DeviceAssetEntity?> getByAssetId(String assetId) {
return getByIndex(r'assetId', [assetId]);
}
DeviceAssetEntity? getByAssetIdSync(String assetId) {
return getByIndexSync(r'assetId', [assetId]);
}
Future<bool> deleteByAssetId(String assetId) {
return deleteByIndex(r'assetId', [assetId]);
}
bool deleteByAssetIdSync(String assetId) {
return deleteByIndexSync(r'assetId', [assetId]);
}
Future<List<DeviceAssetEntity?>> getAllByAssetId(List<String> assetIdValues) {
final values = assetIdValues.map((e) => [e]).toList();
return getAllByIndex(r'assetId', values);
}
List<DeviceAssetEntity?> getAllByAssetIdSync(List<String> assetIdValues) {
final values = assetIdValues.map((e) => [e]).toList();
return getAllByIndexSync(r'assetId', values);
}
Future<int> deleteAllByAssetId(List<String> assetIdValues) {
final values = assetIdValues.map((e) => [e]).toList();
return deleteAllByIndex(r'assetId', values);
}
int deleteAllByAssetIdSync(List<String> assetIdValues) {
final values = assetIdValues.map((e) => [e]).toList();
return deleteAllByIndexSync(r'assetId', values);
}
Future<Id> putByAssetId(DeviceAssetEntity object) {
return putByIndex(r'assetId', object);
}
Id putByAssetIdSync(DeviceAssetEntity object, {bool saveLinks = true}) {
return putByIndexSync(r'assetId', object, saveLinks: saveLinks);
}
Future<List<Id>> putAllByAssetId(List<DeviceAssetEntity> objects) {
return putAllByIndex(r'assetId', objects);
}
List<Id> putAllByAssetIdSync(
List<DeviceAssetEntity> objects, {
bool saveLinks = true,
}) {
return putAllByIndexSync(r'assetId', objects, saveLinks: saveLinks);
}
}
extension DeviceAssetEntityQueryWhereSort
on QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QWhere> {
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterWhere> anyId() {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(const IdWhereClause.any());
});
}
}
extension DeviceAssetEntityQueryWhere
on QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QWhereClause> {
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterWhereClause>
idEqualTo(Id id) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterWhereClause>
idNotEqualTo(Id id) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
.addWhereClause(
IdWhereClause.lessThan(upper: id, includeUpper: false),
)
.addWhereClause(
IdWhereClause.greaterThan(lower: id, includeLower: false),
);
} else {
return query
.addWhereClause(
IdWhereClause.greaterThan(lower: id, includeLower: false),
)
.addWhereClause(
IdWhereClause.lessThan(upper: id, includeUpper: false),
);
}
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterWhereClause>
idGreaterThan(Id id, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.greaterThan(lower: id, includeLower: include),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterWhereClause>
idLessThan(Id id, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.lessThan(upper: id, includeUpper: include),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterWhereClause>
idBetween(
Id lowerId,
Id upperId, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.between(
lower: lowerId,
includeLower: includeLower,
upper: upperId,
includeUpper: includeUpper,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterWhereClause>
assetIdEqualTo(String assetId) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IndexWhereClause.equalTo(indexName: r'assetId', value: [assetId]),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterWhereClause>
assetIdNotEqualTo(String assetId) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
.addWhereClause(
IndexWhereClause.between(
indexName: r'assetId',
lower: [],
upper: [assetId],
includeUpper: false,
),
)
.addWhereClause(
IndexWhereClause.between(
indexName: r'assetId',
lower: [assetId],
includeLower: false,
upper: [],
),
);
} else {
return query
.addWhereClause(
IndexWhereClause.between(
indexName: r'assetId',
lower: [assetId],
includeLower: false,
upper: [],
),
)
.addWhereClause(
IndexWhereClause.between(
indexName: r'assetId',
lower: [],
upper: [assetId],
includeUpper: false,
),
);
}
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterWhereClause>
hashEqualTo(List<int> hash) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IndexWhereClause.equalTo(indexName: r'hash', value: [hash]),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterWhereClause>
hashNotEqualTo(List<int> hash) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
.addWhereClause(
IndexWhereClause.between(
indexName: r'hash',
lower: [],
upper: [hash],
includeUpper: false,
),
)
.addWhereClause(
IndexWhereClause.between(
indexName: r'hash',
lower: [hash],
includeLower: false,
upper: [],
),
);
} else {
return query
.addWhereClause(
IndexWhereClause.between(
indexName: r'hash',
lower: [hash],
includeLower: false,
upper: [],
),
)
.addWhereClause(
IndexWhereClause.between(
indexName: r'hash',
lower: [],
upper: [hash],
includeUpper: false,
),
);
}
});
}
}
extension DeviceAssetEntityQueryFilter
on QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QFilterCondition> {
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
assetIdEqualTo(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(
property: r'assetId',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
assetIdGreaterThan(
String value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'assetId',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
assetIdLessThan(
String value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'assetId',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
assetIdBetween(
String lower,
String upper, {
bool includeLower = true,
bool includeUpper = true,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'assetId',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
assetIdStartsWith(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.startsWith(
property: r'assetId',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
assetIdEndsWith(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.endsWith(
property: r'assetId',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
assetIdContains(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.contains(
property: r'assetId',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
assetIdMatches(String pattern, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.matches(
property: r'assetId',
wildcard: pattern,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
assetIdIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'assetId', value: ''),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
assetIdIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(property: r'assetId', value: ''),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
hashElementEqualTo(int value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'hash', value: value),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
hashElementGreaterThan(int value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'hash',
value: value,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
hashElementLessThan(int value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'hash',
value: value,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
hashElementBetween(
int lower,
int upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'hash',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
hashLengthEqualTo(int length) {
return QueryBuilder.apply(this, (query) {
return query.listLength(r'hash', length, true, length, true);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
hashIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.listLength(r'hash', 0, true, 0, true);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
hashIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.listLength(r'hash', 0, false, 999999, true);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
hashLengthLessThan(int length, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.listLength(r'hash', 0, true, length, include);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
hashLengthGreaterThan(int length, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.listLength(r'hash', length, include, 999999, true);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
hashLengthBetween(
int lower,
int upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.listLength(
r'hash',
lower,
includeLower,
upper,
includeUpper,
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
idEqualTo(Id value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'id', value: value),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
idGreaterThan(Id value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'id',
value: value,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
idLessThan(Id value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'id',
value: value,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
idBetween(
Id lower,
Id upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'id',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
modifiedTimeEqualTo(DateTime value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'modifiedTime', value: value),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
modifiedTimeGreaterThan(DateTime value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'modifiedTime',
value: value,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
modifiedTimeLessThan(DateTime value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'modifiedTime',
value: value,
),
);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterFilterCondition>
modifiedTimeBetween(
DateTime lower,
DateTime upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'modifiedTime',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
),
);
});
}
}
extension DeviceAssetEntityQueryObject
on QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QFilterCondition> {}
extension DeviceAssetEntityQueryLinks
on QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QFilterCondition> {}
extension DeviceAssetEntityQuerySortBy
on QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QSortBy> {
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterSortBy>
sortByAssetId() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'assetId', Sort.asc);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterSortBy>
sortByAssetIdDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'assetId', Sort.desc);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterSortBy>
sortByModifiedTime() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'modifiedTime', Sort.asc);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterSortBy>
sortByModifiedTimeDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'modifiedTime', Sort.desc);
});
}
}
extension DeviceAssetEntityQuerySortThenBy
on QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QSortThenBy> {
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterSortBy>
thenByAssetId() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'assetId', Sort.asc);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterSortBy>
thenByAssetIdDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'assetId', Sort.desc);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterSortBy> thenById() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'id', Sort.asc);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterSortBy>
thenByIdDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'id', Sort.desc);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterSortBy>
thenByModifiedTime() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'modifiedTime', Sort.asc);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QAfterSortBy>
thenByModifiedTimeDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'modifiedTime', Sort.desc);
});
}
}
extension DeviceAssetEntityQueryWhereDistinct
on QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QDistinct> {
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QDistinct>
distinctByAssetId({bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'assetId', caseSensitive: caseSensitive);
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QDistinct>
distinctByHash() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'hash');
});
}
QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QDistinct>
distinctByModifiedTime() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'modifiedTime');
});
}
}
extension DeviceAssetEntityQueryProperty
on QueryBuilder<DeviceAssetEntity, DeviceAssetEntity, QQueryProperty> {
QueryBuilder<DeviceAssetEntity, int, QQueryOperations> idProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'id');
});
}
QueryBuilder<DeviceAssetEntity, String, QQueryOperations> assetIdProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'assetId');
});
}
QueryBuilder<DeviceAssetEntity, List<int>, QQueryOperations> hashProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'hash');
});
}
QueryBuilder<DeviceAssetEntity, DateTime, QQueryOperations>
modifiedTimeProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'modifiedTime');
});
}
}
@@ -4,96 +4,6 @@ import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart';
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:isar/isar.dart';
part 'exif.entity.g.dart';
/// Exif information 1:1 relation with Asset
@Collection(inheritance: false)
class ExifInfo {
final Id? id;
final int? fileSize;
final DateTime? dateTimeOriginal;
final String? timeZone;
final String? make;
final String? model;
final String? lens;
final float? f;
final float? mm;
final short? iso;
final float? exposureSeconds;
final float? lat;
final float? long;
final String? city;
final String? state;
final String? country;
final String? description;
final String? orientation;
const ExifInfo({
this.id,
this.fileSize,
this.dateTimeOriginal,
this.timeZone,
this.make,
this.model,
this.lens,
this.f,
this.mm,
this.iso,
this.exposureSeconds,
this.lat,
this.long,
this.city,
this.state,
this.country,
this.description,
this.orientation,
});
static ExifInfo fromDto(domain.ExifInfo dto) => ExifInfo(
id: dto.assetId,
fileSize: dto.fileSize,
dateTimeOriginal: dto.dateTimeOriginal,
timeZone: dto.timeZone,
make: dto.make,
model: dto.model,
lens: dto.lens,
f: dto.f,
mm: dto.mm,
iso: dto.iso?.toInt(),
exposureSeconds: dto.exposureSeconds,
lat: dto.latitude,
long: dto.longitude,
city: dto.city,
state: dto.state,
country: dto.country,
description: dto.description,
orientation: dto.orientation,
);
domain.ExifInfo toDto() => domain.ExifInfo(
assetId: id,
fileSize: fileSize,
description: description,
orientation: orientation,
timeZone: timeZone,
dateTimeOriginal: dateTimeOriginal,
isFlipped: ExifDtoConverter.isOrientationFlipped(orientation),
latitude: lat,
longitude: long,
city: city,
state: state,
country: country,
make: make,
model: model,
lens: lens,
f: f,
mm: mm,
iso: iso?.toInt(),
exposureSeconds: exposureSeconds,
);
}
@TableIndex.sql('CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)')
class RemoteExifEntity extends Table with DriftDefaultsMixin {
File diff suppressed because it is too large Load Diff
@@ -1,18 +1,5 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
import 'package:isar/isar.dart';
part 'store.entity.g.dart';
/// Internal class for `Store`, do not use elsewhere.
@Collection(inheritance: false)
class StoreValue {
final Id id;
final int? intValue;
final String? strValue;
const StoreValue(this.id, {this.intValue, this.strValue});
}
class StoreEntity extends Table with DriftDefaultsMixin {
IntColumn get id => integer()();
-596
View File
@@ -1,596 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'store.entity.dart';
// **************************************************************************
// IsarCollectionGenerator
// **************************************************************************
// coverage:ignore-file
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
extension GetStoreValueCollection on Isar {
IsarCollection<StoreValue> get storeValues => this.collection();
}
const StoreValueSchema = CollectionSchema(
name: r'StoreValue',
id: 902899285492123510,
properties: {
r'intValue': PropertySchema(id: 0, name: r'intValue', type: IsarType.long),
r'strValue': PropertySchema(
id: 1,
name: r'strValue',
type: IsarType.string,
),
},
estimateSize: _storeValueEstimateSize,
serialize: _storeValueSerialize,
deserialize: _storeValueDeserialize,
deserializeProp: _storeValueDeserializeProp,
idName: r'id',
indexes: {},
links: {},
embeddedSchemas: {},
getId: _storeValueGetId,
getLinks: _storeValueGetLinks,
attach: _storeValueAttach,
version: '3.3.0-dev.3',
);
int _storeValueEstimateSize(
StoreValue object,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
var bytesCount = offsets.last;
{
final value = object.strValue;
if (value != null) {
bytesCount += 3 + value.length * 3;
}
}
return bytesCount;
}
void _storeValueSerialize(
StoreValue object,
IsarWriter writer,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
writer.writeLong(offsets[0], object.intValue);
writer.writeString(offsets[1], object.strValue);
}
StoreValue _storeValueDeserialize(
Id id,
IsarReader reader,
List<int> offsets,
Map<Type, List<int>> allOffsets,
) {
final object = StoreValue(
id,
intValue: reader.readLongOrNull(offsets[0]),
strValue: reader.readStringOrNull(offsets[1]),
);
return object;
}
P _storeValueDeserializeProp<P>(
IsarReader reader,
int propertyId,
int offset,
Map<Type, List<int>> allOffsets,
) {
switch (propertyId) {
case 0:
return (reader.readLongOrNull(offset)) as P;
case 1:
return (reader.readStringOrNull(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
}
}
Id _storeValueGetId(StoreValue object) {
return object.id;
}
List<IsarLinkBase<dynamic>> _storeValueGetLinks(StoreValue object) {
return [];
}
void _storeValueAttach(IsarCollection<dynamic> col, Id id, StoreValue object) {}
extension StoreValueQueryWhereSort
on QueryBuilder<StoreValue, StoreValue, QWhere> {
QueryBuilder<StoreValue, StoreValue, QAfterWhere> anyId() {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(const IdWhereClause.any());
});
}
}
extension StoreValueQueryWhere
on QueryBuilder<StoreValue, StoreValue, QWhereClause> {
QueryBuilder<StoreValue, StoreValue, QAfterWhereClause> idEqualTo(Id id) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
});
}
QueryBuilder<StoreValue, StoreValue, QAfterWhereClause> idNotEqualTo(Id id) {
return QueryBuilder.apply(this, (query) {
if (query.whereSort == Sort.asc) {
return query
.addWhereClause(
IdWhereClause.lessThan(upper: id, includeUpper: false),
)
.addWhereClause(
IdWhereClause.greaterThan(lower: id, includeLower: false),
);
} else {
return query
.addWhereClause(
IdWhereClause.greaterThan(lower: id, includeLower: false),
)
.addWhereClause(
IdWhereClause.lessThan(upper: id, includeUpper: false),
);
}
});
}
QueryBuilder<StoreValue, StoreValue, QAfterWhereClause> idGreaterThan(
Id id, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.greaterThan(lower: id, includeLower: include),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterWhereClause> idLessThan(
Id id, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.lessThan(upper: id, includeUpper: include),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterWhereClause> idBetween(
Id lowerId,
Id upperId, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addWhereClause(
IdWhereClause.between(
lower: lowerId,
includeLower: includeLower,
upper: upperId,
includeUpper: includeUpper,
),
);
});
}
}
extension StoreValueQueryFilter
on QueryBuilder<StoreValue, StoreValue, QFilterCondition> {
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> idEqualTo(
Id value,
) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'id', value: value),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> idGreaterThan(
Id value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'id',
value: value,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> idLessThan(
Id value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'id',
value: value,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> idBetween(
Id lower,
Id upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'id',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> intValueIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'intValue'),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition>
intValueIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'intValue'),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> intValueEqualTo(
int? value,
) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'intValue', value: value),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition>
intValueGreaterThan(int? value, {bool include = false}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'intValue',
value: value,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> intValueLessThan(
int? value, {
bool include = false,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'intValue',
value: value,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> intValueBetween(
int? lower,
int? upper, {
bool includeLower = true,
bool includeUpper = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'intValue',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> strValueIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNull(property: r'strValue'),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition>
strValueIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
const FilterCondition.isNotNull(property: r'strValue'),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> strValueEqualTo(
String? value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(
property: r'strValue',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition>
strValueGreaterThan(
String? value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(
include: include,
property: r'strValue',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> strValueLessThan(
String? value, {
bool include = false,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.lessThan(
include: include,
property: r'strValue',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> strValueBetween(
String? lower,
String? upper, {
bool includeLower = true,
bool includeUpper = true,
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.between(
property: r'strValue',
lower: lower,
includeLower: includeLower,
upper: upper,
includeUpper: includeUpper,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition>
strValueStartsWith(String value, {bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.startsWith(
property: r'strValue',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> strValueEndsWith(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.endsWith(
property: r'strValue',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> strValueContains(
String value, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.contains(
property: r'strValue',
value: value,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition> strValueMatches(
String pattern, {
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.matches(
property: r'strValue',
wildcard: pattern,
caseSensitive: caseSensitive,
),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition>
strValueIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.equalTo(property: r'strValue', value: ''),
);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterFilterCondition>
strValueIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(
FilterCondition.greaterThan(property: r'strValue', value: ''),
);
});
}
}
extension StoreValueQueryObject
on QueryBuilder<StoreValue, StoreValue, QFilterCondition> {}
extension StoreValueQueryLinks
on QueryBuilder<StoreValue, StoreValue, QFilterCondition> {}
extension StoreValueQuerySortBy
on QueryBuilder<StoreValue, StoreValue, QSortBy> {
QueryBuilder<StoreValue, StoreValue, QAfterSortBy> sortByIntValue() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'intValue', Sort.asc);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterSortBy> sortByIntValueDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'intValue', Sort.desc);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterSortBy> sortByStrValue() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'strValue', Sort.asc);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterSortBy> sortByStrValueDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'strValue', Sort.desc);
});
}
}
extension StoreValueQuerySortThenBy
on QueryBuilder<StoreValue, StoreValue, QSortThenBy> {
QueryBuilder<StoreValue, StoreValue, QAfterSortBy> thenById() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'id', Sort.asc);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterSortBy> thenByIdDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'id', Sort.desc);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterSortBy> thenByIntValue() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'intValue', Sort.asc);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterSortBy> thenByIntValueDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'intValue', Sort.desc);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterSortBy> thenByStrValue() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'strValue', Sort.asc);
});
}
QueryBuilder<StoreValue, StoreValue, QAfterSortBy> thenByStrValueDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'strValue', Sort.desc);
});
}
}
extension StoreValueQueryWhereDistinct
on QueryBuilder<StoreValue, StoreValue, QDistinct> {
QueryBuilder<StoreValue, StoreValue, QDistinct> distinctByIntValue() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'intValue');
});
}
QueryBuilder<StoreValue, StoreValue, QDistinct> distinctByStrValue({
bool caseSensitive = true,
}) {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'strValue', caseSensitive: caseSensitive);
});
}
}
extension StoreValueQueryProperty
on QueryBuilder<StoreValue, StoreValue, QQueryProperty> {
QueryBuilder<StoreValue, int, QQueryOperations> idProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'id');
});
}
QueryBuilder<StoreValue, int?, QQueryOperations> intValueProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'intValue');
});
}
QueryBuilder<StoreValue, String?, QQueryOperations> strValueProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'strValue');
});
}
}
@@ -1,79 +1,6 @@
import 'package:drift/drift.dart' hide Index;
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
import 'package:immich_mobile/utils/hash.dart';
import 'package:isar/isar.dart';
part 'user.entity.g.dart';
@Collection(inheritance: false)
class User {
Id get isarId => fastHash(id);
@Index(unique: true, replace: false, type: IndexType.hash)
final String id;
final DateTime updatedAt;
final String email;
final String name;
final bool isPartnerSharedBy;
final bool isPartnerSharedWith;
final bool isAdmin;
final String profileImagePath;
@Enumerated(EnumType.ordinal)
final AvatarColor avatarColor;
final bool memoryEnabled;
final bool inTimeline;
final int quotaUsageInBytes;
final int quotaSizeInBytes;
const User({
required this.id,
required this.updatedAt,
required this.email,
required this.name,
required this.isAdmin,
this.isPartnerSharedBy = false,
this.isPartnerSharedWith = false,
this.profileImagePath = '',
this.avatarColor = AvatarColor.primary,
this.memoryEnabled = true,
this.inTimeline = false,
this.quotaUsageInBytes = 0,
this.quotaSizeInBytes = 0,
});
static User fromDto(UserDto dto) => User(
id: dto.id,
updatedAt: dto.updatedAt ?? DateTime(2025),
email: dto.email,
name: dto.name,
isAdmin: dto.isAdmin,
isPartnerSharedBy: dto.isPartnerSharedBy,
isPartnerSharedWith: dto.isPartnerSharedWith,
profileImagePath: dto.hasProfileImage ? "HAS_PROFILE_IMAGE" : "",
avatarColor: dto.avatarColor,
memoryEnabled: dto.memoryEnabled,
inTimeline: dto.inTimeline,
quotaUsageInBytes: dto.quotaUsageInBytes,
quotaSizeInBytes: dto.quotaSizeInBytes,
);
UserDto toDto() => UserDto(
id: id,
email: email,
name: name,
isAdmin: isAdmin,
updatedAt: updatedAt,
avatarColor: avatarColor,
memoryEnabled: memoryEnabled,
inTimeline: inTimeline,
isPartnerSharedBy: isPartnerSharedBy,
isPartnerSharedWith: isPartnerSharedWith,
hasProfileImage: profileImagePath.isNotEmpty,
profileChangedAt: updatedAt,
quotaUsageInBytes: quotaUsageInBytes,
quotaSizeInBytes: quotaSizeInBytes,
);
}
class UserEntity extends Table with DriftDefaultsMixin {
const UserEntity();
File diff suppressed because it is too large Load Diff
@@ -3,7 +3,6 @@ import 'dart:async';
import 'package:drift/drift.dart';
import 'package:drift_flutter/drift_flutter.dart';
import 'package:flutter/foundation.dart';
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
import 'package:immich_mobile/infrastructure/entities/asset_edit.entity.dart';
import 'package:immich_mobile/infrastructure/entities/asset_face.entity.dart';
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.dart';
@@ -27,22 +26,6 @@ import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.steps.dart';
import 'package:isar/isar.dart' hide Index;
// #zoneTxn is the symbol used by Isar to mark a transaction within the current zone
// ref: isar/isar_common.dart
const Symbol _kzoneTxn = #zoneTxn;
class IsarDatabaseRepository implements IDatabaseRepository {
final Isar _db;
const IsarDatabaseRepository(Isar db) : _db = db;
// Isar do not support nested transactions. This is a workaround to prevent us from making nested transactions
// Reuse the current transaction if it is already active, else start a new transaction
@override
Future<T> transaction<T>(Future<T> Function() callback) =>
Zone.current[_kzoneTxn] == null ? _db.writeTxn(callback) : callback();
}
@DriftDatabase(
tables: [
@@ -70,7 +53,7 @@ class IsarDatabaseRepository implements IDatabaseRepository {
],
include: {'package:immich_mobile/infrastructure/entities/merged_asset.drift'},
)
class Drift extends $Drift implements IDatabaseRepository {
class Drift extends $Drift {
Drift([QueryExecutor? executor])
: super(executor ?? driftDatabase(name: 'immich', native: const DriftNativeOptions(shareAcrossIsolates: true)));
@@ -261,10 +244,9 @@ class Drift extends $Drift implements IDatabaseRepository {
);
}
class DriftDatabaseRepository implements IDatabaseRepository {
class DriftDatabaseRepository {
final Drift _db;
const DriftDatabaseRepository(this._db);
@override
Future<T> transaction<T>(Future<T> Function() callback) => _db.transaction(callback);
}
@@ -1,31 +0,0 @@
import 'package:immich_mobile/domain/models/device_asset.model.dart';
import 'package:immich_mobile/infrastructure/entities/device_asset.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:isar/isar.dart';
class IsarDeviceAssetRepository extends IsarDatabaseRepository {
final Isar _db;
const IsarDeviceAssetRepository(this._db) : super(_db);
Future<void> deleteIds(List<String> ids) {
return transaction(() async {
await _db.deviceAssetEntitys.deleteAllByAssetId(ids.toList());
});
}
Future<List<DeviceAsset>> getByIds(List<String> localIds) {
return _db.deviceAssetEntitys
.where()
.anyOf(localIds, (query, id) => query.assetIdEqualTo(id))
.findAll()
.then((value) => value.map((e) => e.toModel()).toList());
}
Future<bool> updateAll(List<DeviceAsset> assetHash) {
return transaction(() async {
await _db.deviceAssetEntitys.putAll(assetHash.map(DeviceAssetEntity.fromDto).toList());
return true;
});
}
}
@@ -1,40 +0,0 @@
import 'package:immich_mobile/domain/models/exif.model.dart';
import 'package:immich_mobile/infrastructure/entities/exif.entity.dart' as entity;
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:isar/isar.dart';
class IsarExifRepository extends IsarDatabaseRepository {
final Isar _db;
const IsarExifRepository(this._db) : super(_db);
Future<void> delete(int assetId) async {
await transaction(() async {
await _db.exifInfos.delete(assetId);
});
}
Future<void> deleteAll() async {
await transaction(() async {
await _db.exifInfos.clear();
});
}
Future<ExifInfo?> get(int assetId) async {
return (await _db.exifInfos.get(assetId))?.toDto();
}
Future<ExifInfo> update(ExifInfo exifInfo) {
return transaction(() async {
await _db.exifInfos.put(entity.ExifInfo.fromDto(exifInfo));
return exifInfo;
});
}
Future<List<ExifInfo>> updateAll(List<ExifInfo> exifInfos) {
return transaction(() async {
await _db.exifInfos.putAll(exifInfos.map(entity.ExifInfo.fromDto).toList());
return exifInfos;
});
}
}
@@ -1,11 +1,10 @@
import 'package:drift/drift.dart';
import 'package:drift_flutter/drift_flutter.dart';
import 'package:immich_mobile/domain/interfaces/db.interface.dart';
import 'package:immich_mobile/infrastructure/entities/log.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/logger_db.repository.drift.dart';
@DriftDatabase(tables: [LogMessageEntity])
class DriftLogger extends $DriftLogger implements IDatabaseRepository {
class DriftLogger extends $DriftLogger {
DriftLogger([QueryExecutor? executor])
: super(
executor ?? driftDatabase(name: 'immich_logs', native: const DriftNativeOptions(shareAcrossIsolates: true)),
@@ -4,7 +4,7 @@ import 'package:immich_mobile/domain/models/asset_edit.model.dart';
import 'package:immich_mobile/domain/models/exif.model.dart';
import 'package:immich_mobile/domain/models/stack.model.dart';
import 'package:immich_mobile/infrastructure/entities/asset_edit.entity.dart';
import 'package:immich_mobile/infrastructure/entities/exif.entity.dart' hide ExifInfo;
import 'package:immich_mobile/infrastructure/entities/exif.entity.dart';
import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart';
import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart';
@@ -1,150 +1,42 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/infrastructure/entities/store.entity.dart';
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
import 'package:isar/isar.dart';
// Temporary interface until Isar is removed to make the service work with both Isar and Sqlite
abstract class IStoreRepository {
Future<bool> deleteAll();
Stream<List<StoreDto<Object>>> watchAll();
Future<void> delete<T>(StoreKey<T> key);
Future<bool> upsert<T>(StoreKey<T> key, T value);
Future<T?> tryGet<T>(StoreKey<T> key);
Stream<T?> watch<T>(StoreKey<T> key);
Future<List<StoreDto<Object>>> getAll();
}
class IsarStoreRepository extends IsarDatabaseRepository implements IStoreRepository {
final Isar _db;
final validStoreKeys = StoreKey.values.map((e) => e.id).toSet();
IsarStoreRepository(super.db) : _db = db;
@override
Future<bool> deleteAll() async {
return await transaction(() async {
await _db.storeValues.clear();
return true;
});
}
@override
Stream<List<StoreDto<Object>>> watchAll() {
return _db.storeValues
.filter()
.anyOf(validStoreKeys, (query, id) => query.idEqualTo(id))
.watch(fireImmediately: true)
.asyncMap((entities) => Future.wait(entities.map((entity) => _toUpdateEvent(entity))));
}
@override
Future<void> delete<T>(StoreKey<T> key) async {
return await transaction(() async => await _db.storeValues.delete(key.id));
}
@override
Future<bool> upsert<T>(StoreKey<T> key, T value) async {
return await transaction(() async {
await _db.storeValues.put(await _fromValue(key, value));
return true;
});
}
@override
Future<T?> tryGet<T>(StoreKey<T> key) async {
final entity = (await _db.storeValues.get(key.id));
if (entity == null) {
return null;
}
return await _toValue(key, entity);
}
@override
Stream<T?> watch<T>(StoreKey<T> key) async* {
yield* _db.storeValues
.watchObject(key.id, fireImmediately: true)
.asyncMap((e) async => e == null ? null : await _toValue(key, e));
}
Future<StoreDto<Object>> _toUpdateEvent(StoreValue entity) async {
final key = StoreKey.values.firstWhere((e) => e.id == entity.id) as StoreKey<Object>;
final value = await _toValue(key, entity);
return StoreDto(key, value);
}
Future<T?> _toValue<T>(StoreKey<T> key, StoreValue entity) async =>
switch (key.type) {
const (int) => entity.intValue,
const (String) => entity.strValue,
const (bool) => entity.intValue == 1,
const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!),
const (UserDto) =>
entity.strValue == null ? null : await IsarUserRepository(_db).getByUserId(entity.strValue!),
_ => null,
}
as T?;
Future<StoreValue> _fromValue<T>(StoreKey<T> key, T value) async {
final (int? intValue, String? strValue) = switch (key.type) {
const (int) => (value as int, null),
const (String) => (null, value as String),
const (bool) => ((value as bool) ? 1 : 0, null),
const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null),
const (UserDto) => (null, (await IsarUserRepository(_db).update(value as UserDto)).id),
_ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"),
};
return StoreValue(key.id, intValue: intValue, strValue: strValue);
}
@override
Future<List<StoreDto<Object>>> getAll() async {
final entities = await _db.storeValues.filter().anyOf(validStoreKeys, (query, id) => query.idEqualTo(id)).findAll();
return Future.wait(entities.map((e) => _toUpdateEvent(e)).toList());
}
}
class DriftStoreRepository extends DriftDatabaseRepository implements IStoreRepository {
class DriftStoreRepository extends DriftDatabaseRepository {
final Drift _db;
final validStoreKeys = StoreKey.values.map((e) => e.id).toSet();
DriftStoreRepository(super.db) : _db = db;
@override
Future<bool> deleteAll() async {
await _db.storeEntity.deleteAll();
return true;
}
@override
Future<List<StoreDto<Object>>> getAll() async {
final query = _db.storeEntity.select()..where((entity) => entity.id.isIn(validStoreKeys));
return query.asyncMap((entity) => _toUpdateEvent(entity)).get();
}
@override
Stream<List<StoreDto<Object>>> watchAll() {
final query = _db.storeEntity.select()..where((entity) => entity.id.isIn(validStoreKeys));
return query.asyncMap((entity) => _toUpdateEvent(entity)).watch();
}
@override
Future<void> delete<T>(StoreKey<T> key) async {
await _db.storeEntity.deleteWhere((entity) => entity.id.equals(key.id));
return;
}
@override
Future<bool> upsert<T>(StoreKey<T> key, T value) async {
await _db.storeEntity.insertOnConflictUpdate(await _fromValue(key, value));
return true;
}
@override
Future<T?> tryGet<T>(StoreKey<T> key) async {
final entity = await _db.managers.storeEntity.filter((entity) => entity.id.equals(key.id)).getSingleOrNull();
if (entity == null) {
@@ -153,7 +45,6 @@ class DriftStoreRepository extends DriftDatabaseRepository implements IStoreRepo
return await _toValue(key, entity);
}
@override
Stream<T?> watch<T>(StoreKey<T> key) async* {
final query = _db.storeEntity.select()..where((entity) => entity.id.equals(key.id));
@@ -1,72 +1,9 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
import 'package:immich_mobile/domain/models/user_metadata.model.dart';
import 'package:immich_mobile/infrastructure/entities/auth_user.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/user.entity.dart' as entity;
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/user_metadata.repository.dart';
import 'package:isar/isar.dart';
class IsarUserRepository extends IsarDatabaseRepository {
final Isar _db;
const IsarUserRepository(super.db) : _db = db;
Future<void> delete(List<String> ids) async {
await transaction(() async {
await _db.users.deleteAllById(ids);
});
}
Future<void> deleteAll() async {
await transaction(() async {
await _db.users.clear();
});
}
Future<List<UserDto>> getAll({SortUserBy? sortBy}) async {
return (await _db.users
.where()
.optional(
sortBy != null,
(query) => switch (sortBy!) {
SortUserBy.id => query.sortById(),
},
)
.findAll())
.map((u) => u.toDto())
.toList();
}
Future<UserDto?> getByUserId(String id) async {
return (await _db.users.getById(id))?.toDto();
}
Future<List<UserDto?>> getByUserIds(List<String> ids) async {
return (await _db.users.getAllById(ids)).map((u) => u?.toDto()).toList();
}
Future<bool> insert(UserDto user) async {
await transaction(() async {
await _db.users.put(entity.User.fromDto(user));
});
return true;
}
Future<UserDto> update(UserDto user) async {
await transaction(() async {
await _db.users.put(entity.User.fromDto(user));
});
return user;
}
Future<bool> updateAll(List<UserDto> users) async {
await transaction(() async {
await _db.users.putAll(users.map(entity.User.fromDto).toList());
});
return true;
}
}
class DriftAuthUserRepository extends DriftDatabaseRepository {
final Drift _db;
@@ -117,6 +54,7 @@ extension on AuthUserEntityData {
id: id,
email: email,
name: name,
updatedAt: profileChangedAt,
profileChangedAt: profileChangedAt,
hasProfileImage: hasProfileImage,
avatarColor: avatarColor,