import 'package:immich_mobile/domain/interfaces/store.interface.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/repositories/db.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/user.repository.dart'; import 'package:isar/isar.dart'; 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 deleteAll() async { return await transaction(() async { await _db.storeValues.clear(); return true; }); } @override Stream watchAll() { return _db.storeValues .filter() .anyOf(validStoreKeys, (query, id) => query.idEqualTo(id)) .watch(fireImmediately: true) .asyncExpand( (entities) => Stream.fromFutures( entities.map((e) async => _toUpdateEvent(e)), ), ); } @override Future delete(StoreKey key) async { return await transaction(() async => await _db.storeValues.delete(key.id)); } @override Future insert(StoreKey key, T value) async { return await transaction(() async { await _db.storeValues.put(await _fromValue(key, value)); return true; }); } @override Future tryGet(StoreKey key) async { final entity = (await _db.storeValues.get(key.id)); if (entity == null) { return null; } return await _toValue(key, entity); } @override Future update(StoreKey key, T value) async { return await transaction(() async { await _db.storeValues.put(await _fromValue(key, value)); return true; }); } @override Stream watch(StoreKey key) async* { yield* _db.storeValues .watchObject(key.id, fireImmediately: true) .asyncMap((e) async => e == null ? null : await _toValue(key, e)); } Future _toUpdateEvent(StoreValue entity) async { final key = StoreKey.values.firstWhere((e) => e.id == entity.id); final value = await _toValue(key, entity); return StoreUpdateEvent(key, value); } Future _toValue(StoreKey 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 _fromValue(StoreKey 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); } }