refactor repositories

This commit is contained in:
shenlong-tanwen 2024-09-21 20:04:05 +05:30
parent d6495f014d
commit e810512285
23 changed files with 142 additions and 127 deletions

View File

@ -9,7 +9,7 @@ class Asset extends Table {
IntColumn get id => integer().autoIncrement()(); IntColumn get id => integer().autoIncrement()();
TextColumn get name => text()(); TextColumn get name => text()();
TextColumn get checksum => text().unique()(); TextColumn get hash => text().unique()();
IntColumn get height => integer().nullable()(); IntColumn get height => integer().nullable()();
IntColumn get width => integer().nullable()(); IntColumn get width => integer().nullable()();
IntColumn get type => intEnum<AssetType>()(); IntColumn get type => intEnum<AssetType>()();

View File

@ -1,27 +1,23 @@
import 'dart:async'; import 'dart:async';
import 'package:immich_mobile/domain/models/asset.model.dart'; import 'package:immich_mobile/domain/models/asset.model.dart';
import 'package:immich_mobile/domain/models/render_list.model.dart';
abstract class IAssetRepository { abstract interface class IAssetRepository {
/// Batch insert asset /// Batch upsert asset
FutureOr<bool> addAll(Iterable<Asset> assets); FutureOr<bool> upsertAll(Iterable<Asset> assets);
/// Removes assets with the [localIds] /// Removes assets with the [localIds]
FutureOr<List<Asset>> fetchLocalAssetsForIds(List<String> localIds); FutureOr<List<Asset>> getForLocalIds(List<String> localIds);
/// Removes assets with the [remoteIds] /// Removes assets with the [remoteIds]
FutureOr<List<Asset>> fetchRemoteAssetsForIds(List<String> remoteIds); FutureOr<List<Asset>> getForRemoteIds(List<String> remoteIds);
/// Removes assets with the given [ids]
FutureOr<void> deleteAssetsForIds(List<int> ids);
/// Removes all assets
FutureOr<bool> clearAll();
/// Fetch assets from the [offset] with the [limit] /// Fetch assets from the [offset] with the [limit]
FutureOr<List<Asset>> fetchAssets({int? offset, int? limit}); FutureOr<List<Asset>> getAll({int? offset, int? limit});
/// Streams assets as groups grouped by the group type passed /// Removes assets with the given [ids]
Stream<RenderList> watchRenderList(); FutureOr<void> deleteIds(List<int> ids);
/// Removes all assets
FutureOr<bool> deleteAll();
} }

View File

@ -2,19 +2,19 @@ import 'dart:async';
import 'package:immich_mobile/domain/models/log.model.dart'; import 'package:immich_mobile/domain/models/log.model.dart';
abstract class ILogRepository { abstract interface class ILogRepository {
/// Fetches all logs
FutureOr<List<LogMessage>> fetchAll();
/// Inserts a new log into the DB /// Inserts a new log into the DB
FutureOr<bool> add(LogMessage log); FutureOr<bool> create(LogMessage log);
/// Bulk insert logs into DB /// Bulk insert logs into DB
FutureOr<bool> addAll(List<LogMessage> log); FutureOr<bool> createAll(List<LogMessage> log);
/// Fetches all logs
FutureOr<List<LogMessage>> getAll();
/// Clears all logs /// Clears all logs
FutureOr<bool> clear(); FutureOr<bool> deleteAll();
/// Truncates the logs to the most recent [limit]. Defaults to recent 250 logs /// Truncates the logs to the most recent [limit]. Defaults to recent 250 logs
FutureOr<void> truncateLogs({int limit = 250}); FutureOr<void> truncate({int limit = 250});
} }

View File

@ -0,0 +1,6 @@
import 'package:immich_mobile/domain/models/render_list.model.dart';
abstract interface class IRenderListRepository {
/// Streams the [RenderList] for the main timeline
Stream<RenderList> watchAll();
}

View File

@ -12,16 +12,16 @@ abstract class IStoreConverter<T, U> {
FutureOr<T?> fromPrimitive(U value); FutureOr<T?> fromPrimitive(U value);
} }
abstract class IStoreRepository { abstract interface class IStoreRepository {
FutureOr<T?> tryGet<T, U>(StoreKey<T, U> key); FutureOr<bool> upsert<T, U>(StoreKey<T, U> key, T value);
FutureOr<T> get<T, U>(StoreKey<T, U> key); FutureOr<T> get<T, U>(StoreKey<T, U> key);
FutureOr<bool> set<T, U>(StoreKey<T, U> key, T value); FutureOr<T?> tryGet<T, U>(StoreKey<T, U> key);
FutureOr<void> delete(StoreKey key);
Stream<T?> watch<T, U>(StoreKey<T, U> key); Stream<T?> watch<T, U>(StoreKey<T, U> key);
FutureOr<void> clearStore(); FutureOr<void> delete(StoreKey key);
FutureOr<void> deleteAll();
} }

View File

@ -2,10 +2,10 @@ import 'dart:async';
import 'package:immich_mobile/domain/models/user.model.dart'; import 'package:immich_mobile/domain/models/user.model.dart';
abstract class IUserRepository { abstract interface class IUserRepository {
/// Fetches user
FutureOr<User?> fetch(String userId);
/// Insert user /// Insert user
FutureOr<bool> add(User user); FutureOr<bool> upsert(User user);
/// Fetches user
FutureOr<User?> getForId(String userId);
} }

View File

@ -14,7 +14,7 @@ enum AssetType {
class Asset { class Asset {
final int id; final int id;
final String name; final String name;
final String checksum; final String hash;
final int? height; final int? height;
final int? width; final int? width;
final AssetType type; final AssetType type;
@ -36,7 +36,7 @@ class Asset {
const Asset({ const Asset({
required this.id, required this.id,
required this.name, required this.name,
required this.checksum, required this.hash,
this.height, this.height,
this.width, this.width,
required this.type, required this.type,
@ -55,7 +55,7 @@ class Asset {
duration: dto.duration.tryParseInt() ?? 0, duration: dto.duration.tryParseInt() ?? 0,
height: dto.exifInfo?.exifImageHeight?.toInt(), height: dto.exifInfo?.exifImageHeight?.toInt(),
width: dto.exifInfo?.exifImageWidth?.toInt(), width: dto.exifInfo?.exifImageWidth?.toInt(),
checksum: dto.checksum, hash: dto.checksum,
name: dto.originalFileName, name: dto.originalFileName,
livePhotoVideoId: dto.livePhotoVideoId, livePhotoVideoId: dto.livePhotoVideoId,
modifiedTime: dto.fileModifiedAt, modifiedTime: dto.fileModifiedAt,
@ -65,7 +65,7 @@ class Asset {
Asset copyWith({ Asset copyWith({
int? id, int? id,
String? name, String? name,
String? checksum, String? hash,
int? height, int? height,
int? width, int? width,
AssetType? type, AssetType? type,
@ -79,7 +79,7 @@ class Asset {
return Asset( return Asset(
id: id ?? this.id, id: id ?? this.id,
name: name ?? this.name, name: name ?? this.name,
checksum: checksum ?? this.checksum, hash: hash ?? this.hash,
height: height ?? this.height, height: height ?? this.height,
width: width ?? this.width, width: width ?? this.width,
type: type ?? this.type, type: type ?? this.type,
@ -119,7 +119,7 @@ class Asset {
"remoteId": "${remoteId ?? "-"}", "remoteId": "${remoteId ?? "-"}",
"localId": "${localId ?? "-"}", "localId": "${localId ?? "-"}",
"name": "$name", "name": "$name",
"checksum": "$checksum", "hash": "$hash",
"height": ${height ?? "-"}, "height": ${height ?? "-"},
"width": ${width ?? "-"}, "width": ${width ?? "-"},
"type": "$type", "type": "$type",
@ -135,7 +135,7 @@ class Asset {
return other.id == id && return other.id == id &&
other.name == name && other.name == name &&
other.checksum == checksum && other.hash == hash &&
other.height == height && other.height == height &&
other.width == width && other.width == width &&
other.type == type && other.type == type &&
@ -151,7 +151,7 @@ class Asset {
int get hashCode { int get hashCode {
return id.hashCode ^ return id.hashCode ^
name.hashCode ^ name.hashCode ^
checksum.hashCode ^ hash.hashCode ^
height.hashCode ^ height.hashCode ^
width.hashCode ^ width.hashCode ^
type.hashCode ^ type.hashCode ^

View File

@ -4,19 +4,16 @@ import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/entities/asset.entity.drift.dart'; import 'package:immich_mobile/domain/entities/asset.entity.drift.dart';
import 'package:immich_mobile/domain/interfaces/asset.interface.dart'; import 'package:immich_mobile/domain/interfaces/asset.interface.dart';
import 'package:immich_mobile/domain/models/asset.model.dart'; import 'package:immich_mobile/domain/models/asset.model.dart';
import 'package:immich_mobile/domain/models/render_list.model.dart';
import 'package:immich_mobile/domain/models/render_list_element.model.dart';
import 'package:immich_mobile/domain/repositories/database.repository.dart'; import 'package:immich_mobile/domain/repositories/database.repository.dart';
import 'package:immich_mobile/utils/extensions/drift.extension.dart';
import 'package:immich_mobile/utils/mixins/log.mixin.dart'; import 'package:immich_mobile/utils/mixins/log.mixin.dart';
class RemoteAssetDriftRepository with LogMixin implements IAssetRepository { class AssetDriftRepository with LogMixin implements IAssetRepository {
final DriftDatabaseRepository _db; final DriftDatabaseRepository _db;
const RemoteAssetDriftRepository(this._db); const AssetDriftRepository(this._db);
@override @override
Future<bool> addAll(Iterable<Asset> assets) async { Future<bool> upsertAll(Iterable<Asset> assets) async {
try { try {
await _db.batch((batch) => batch.insertAllOnConflictUpdate( await _db.batch((batch) => batch.insertAllOnConflictUpdate(
_db.asset, _db.asset,
@ -31,7 +28,7 @@ class RemoteAssetDriftRepository with LogMixin implements IAssetRepository {
} }
@override @override
Future<bool> clearAll() async { Future<bool> deleteAll() async {
try { try {
await _db.asset.deleteAll(); await _db.asset.deleteAll();
return true; return true;
@ -42,7 +39,7 @@ class RemoteAssetDriftRepository with LogMixin implements IAssetRepository {
} }
@override @override
Future<List<Asset>> fetchAssets({int? offset, int? limit}) async { Future<List<Asset>> getAll({int? offset, int? limit}) async {
final query = _db.asset.select() final query = _db.asset.select()
..orderBy([(asset) => OrderingTerm.desc(asset.createdTime)]); ..orderBy([(asset) => OrderingTerm.desc(asset.createdTime)]);
@ -54,40 +51,7 @@ class RemoteAssetDriftRepository with LogMixin implements IAssetRepository {
} }
@override @override
Stream<RenderList> watchRenderList() { Future<List<Asset>> getForLocalIds(List<String> localIds) async {
final assetCountExp = _db.asset.id.count();
final createdTimeExp = _db.asset.createdTime;
final monthYearExp = _db.asset.createdTime.strftime('%m-%Y');
final query = _db.asset.selectOnly()
..addColumns([assetCountExp, createdTimeExp])
..groupBy([monthYearExp])
..orderBy([OrderingTerm.desc(createdTimeExp)]);
int lastAssetOffset = 0;
return query
.expand((row) {
final createdTime = row.read<DateTime>(createdTimeExp)!;
final assetCount = row.read(assetCountExp)!;
final assetOffset = lastAssetOffset;
lastAssetOffset += assetCount;
return [
RenderListMonthHeaderElement(date: createdTime),
RenderListAssetElement(
date: createdTime,
assetCount: assetCount,
assetOffset: assetOffset,
),
];
})
.watch()
.map((elements) => RenderList(elements: elements));
}
@override
Future<List<Asset>> fetchLocalAssetsForIds(List<String> localIds) async {
final query = _db.asset.select() final query = _db.asset.select()
..where((row) => row.localId.isIn(localIds)) ..where((row) => row.localId.isIn(localIds))
..orderBy([(asset) => OrderingTerm.asc(asset.localId)]); ..orderBy([(asset) => OrderingTerm.asc(asset.localId)]);
@ -96,7 +60,7 @@ class RemoteAssetDriftRepository with LogMixin implements IAssetRepository {
} }
@override @override
Future<List<Asset>> fetchRemoteAssetsForIds(List<String> remoteIds) async { Future<List<Asset>> getForRemoteIds(List<String> remoteIds) async {
final query = _db.asset.select() final query = _db.asset.select()
..where((row) => row.remoteId.isIn(remoteIds)) ..where((row) => row.remoteId.isIn(remoteIds))
..orderBy([(asset) => OrderingTerm.asc(asset.remoteId)]); ..orderBy([(asset) => OrderingTerm.asc(asset.remoteId)]);
@ -105,7 +69,7 @@ class RemoteAssetDriftRepository with LogMixin implements IAssetRepository {
} }
@override @override
FutureOr<void> deleteAssetsForIds(List<int> ids) async { FutureOr<void> deleteIds(List<int> ids) async {
await _db.asset.deleteWhere((row) => row.id.isIn(ids)); await _db.asset.deleteWhere((row) => row.id.isIn(ids));
} }
} }
@ -115,7 +79,7 @@ AssetCompanion _toEntity(Asset asset) {
localId: Value(asset.localId), localId: Value(asset.localId),
remoteId: Value(asset.remoteId), remoteId: Value(asset.remoteId),
name: asset.name, name: asset.name,
checksum: asset.checksum, hash: asset.hash,
height: Value(asset.height), height: Value(asset.height),
width: Value(asset.width), width: Value(asset.width),
type: asset.type, type: asset.type,
@ -133,7 +97,7 @@ Asset _toModel(AssetData asset) {
remoteId: asset.remoteId, remoteId: asset.remoteId,
name: asset.name, name: asset.name,
type: asset.type, type: asset.type,
checksum: asset.checksum, hash: asset.hash,
createdTime: asset.createdTime, createdTime: asset.createdTime,
modifiedTime: asset.modifiedTime, modifiedTime: asset.modifiedTime,
height: asset.height, height: asset.height,

View File

@ -13,12 +13,12 @@ class LogDriftRepository implements ILogRepository {
const LogDriftRepository(this._db); const LogDriftRepository(this._db);
@override @override
Future<List<LogMessage>> fetchAll() async { Future<List<LogMessage>> getAll() async {
return await _db.managers.logs.map(_toModel).get(); return await _db.managers.logs.map(_toModel).get();
} }
@override @override
Future<void> truncateLogs({int limit = 250}) async { Future<void> truncate({int limit = 250}) async {
final totalCount = await _db.managers.logs.count(); final totalCount = await _db.managers.logs.count();
if (totalCount > limit) { if (totalCount > limit) {
final rowsToDelete = totalCount - limit; final rowsToDelete = totalCount - limit;
@ -30,7 +30,7 @@ class LogDriftRepository implements ILogRepository {
} }
@override @override
FutureOr<bool> add(LogMessage log) async { FutureOr<bool> create(LogMessage log) async {
try { try {
await _db.into(_db.logs).insert(LogsCompanion.insert( await _db.into(_db.logs).insert(LogsCompanion.insert(
content: log.content, content: log.content,
@ -48,7 +48,7 @@ class LogDriftRepository implements ILogRepository {
} }
@override @override
FutureOr<bool> addAll(List<LogMessage> logs) async { FutureOr<bool> createAll(List<LogMessage> logs) async {
try { try {
await _db.batch((b) { await _db.batch((b) {
b.insertAll( b.insertAll(
@ -71,7 +71,7 @@ class LogDriftRepository implements ILogRepository {
} }
@override @override
FutureOr<bool> clear() async { FutureOr<bool> deleteAll() async {
try { try {
await _db.managers.logs.delete(); await _db.managers.logs.delete();
return true; return true;

View File

@ -0,0 +1,46 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/interfaces/renderlist.interface.dart';
import 'package:immich_mobile/domain/models/render_list.model.dart';
import 'package:immich_mobile/domain/models/render_list_element.model.dart';
import 'package:immich_mobile/domain/repositories/database.repository.dart';
import 'package:immich_mobile/utils/extensions/drift.extension.dart';
import 'package:immich_mobile/utils/mixins/log.mixin.dart';
class RenderListDriftRepository with LogMixin implements IRenderListRepository {
final DriftDatabaseRepository _db;
const RenderListDriftRepository(this._db);
@override
Stream<RenderList> watchAll() {
final assetCountExp = _db.asset.id.count();
final createdTimeExp = _db.asset.createdTime;
final monthYearExp = _db.asset.createdTime.strftime('%m-%Y');
final query = _db.asset.selectOnly()
..addColumns([assetCountExp, createdTimeExp])
..groupBy([monthYearExp])
..orderBy([OrderingTerm.desc(createdTimeExp)]);
int lastAssetOffset = 0;
return query
.expand((row) {
final createdTime = row.read<DateTime>(createdTimeExp)!;
final assetCount = row.read(assetCountExp)!;
final assetOffset = lastAssetOffset;
lastAssetOffset += assetCount;
return [
RenderListMonthHeaderElement(date: createdTime),
RenderListAssetElement(
date: createdTime,
assetCount: assetCount,
assetOffset: assetOffset,
),
];
})
.watch()
.map((elements) => RenderList(elements: elements));
}
}

View File

@ -30,7 +30,7 @@ class StoreDriftRepository with LogMixin implements IStoreRepository {
} }
@override @override
FutureOr<bool> set<T, U>(StoreKey<T, U> key, T value) async { FutureOr<bool> upsert<T, U>(StoreKey<T, U> key, T value) async {
try { try {
final storeValue = key.converter.toPrimitive(value); final storeValue = key.converter.toPrimitive(value);
final intValue = (key.type == int) ? storeValue as int : null; final intValue = (key.type == int) ? storeValue as int : null;
@ -61,7 +61,7 @@ class StoreDriftRepository with LogMixin implements IStoreRepository {
} }
@override @override
FutureOr<void> clearStore() async { FutureOr<void> deleteAll() async {
await _db.managers.store.delete(); await _db.managers.store.delete();
} }

View File

@ -13,7 +13,7 @@ class UserDriftRepository with LogMixin implements IUserRepository {
const UserDriftRepository(this._db); const UserDriftRepository(this._db);
@override @override
FutureOr<User?> fetch(String userId) async { FutureOr<User?> getForId(String userId) async {
return await _db.managers.user return await _db.managers.user
.filter((f) => f.id.equals(userId)) .filter((f) => f.id.equals(userId))
.map(_toModel) .map(_toModel)
@ -21,7 +21,7 @@ class UserDriftRepository with LogMixin implements IUserRepository {
} }
@override @override
FutureOr<bool> add(User user) async { FutureOr<bool> upsert(User user) async {
try { try {
await _db.into(_db.user).insertOnConflictUpdate( await _db.into(_db.user).insertOnConflictUpdate(
UserCompanion.insert( UserCompanion.insert(

View File

@ -6,16 +6,16 @@ class AppSettingService {
const AppSettingService(this._store); const AppSettingService(this._store);
Future<T> getSetting<T>(AppSetting<T> setting) async { Future<T> get<T>(AppSetting<T> setting) async {
final value = await _store.tryGet(setting.storeKey); final value = await _store.tryGet(setting.storeKey);
return value ?? setting.defaultValue; return value ?? setting.defaultValue;
} }
Future<bool> setSetting<T>(AppSetting<T> setting, T value) async { Future<bool> upsert<T>(AppSetting<T> setting, T value) async {
return await _store.set(setting.storeKey, value); return await _store.upsert(setting.storeKey, value);
} }
Stream<T> watchSetting<T>(AppSetting<T> setting) { Stream<T> watch<T>(AppSetting<T> setting) {
return _store return _store
.watch(setting.storeKey) .watch(setting.storeKey)
.map((value) => value ?? setting.defaultValue); .map((value) => value ?? setting.defaultValue);

View File

@ -16,7 +16,7 @@ import 'package:openapi/api.dart';
class AssetSyncService with LogMixin { class AssetSyncService with LogMixin {
const AssetSyncService(); const AssetSyncService();
Future<bool> doFullRemoteSyncForUserDrift( Future<bool> performFullRemoteSyncForUser(
User user, { User user, {
DateTime? updatedUtil, DateTime? updatedUtil,
int? limit, int? limit,
@ -49,12 +49,11 @@ class AssetSyncService with LogMixin {
final assetsFromServer = final assetsFromServer =
assets.map(Asset.remote).sorted(Asset.compareByRemoteId); assets.map(Asset.remote).sorted(Asset.compareByRemoteId);
final assetsInDb = final assetsInDb = await di<IAssetRepository>().getForRemoteIds(
await di<IAssetRepository>().fetchRemoteAssetsForIds(
assetsFromServer.map((a) => a.remoteId!).toList(), assetsFromServer.map((a) => a.remoteId!).toList(),
); );
await _syncAssetsToDbDrift( await _syncAssetsToDb(
assetsFromServer, assetsFromServer,
assetsInDb, assetsInDb,
Asset.compareByRemoteId, Asset.compareByRemoteId,
@ -73,7 +72,7 @@ class AssetSyncService with LogMixin {
}); });
} }
Future<void> _syncAssetsToDbDrift( Future<void> _syncAssetsToDb(
List<Asset> newAssets, List<Asset> newAssets,
List<Asset> existingAssets, List<Asset> existingAssets,
Comparator<Asset> compare, { Comparator<Asset> compare, {
@ -88,9 +87,9 @@ class AssetSyncService with LogMixin {
final assetsToAdd = toAdd.followedBy(toUpdate); final assetsToAdd = toAdd.followedBy(toUpdate);
await di<IAssetRepository>().addAll(assetsToAdd); await di<IAssetRepository>().upsertAll(assetsToAdd);
await di<IAssetRepository>() await di<IAssetRepository>()
.deleteAssetsForIds(assetsToRemove.map((a) => a.id).toList()); .deleteIds(assetsToRemove.map((a) => a.id).toList());
} }
/// Returns a triple (toAdd, toUpdate, toRemove) /// Returns a triple (toAdd, toUpdate, toRemove)

View File

@ -107,7 +107,7 @@ class LoginService with LogMixin {
return null; return null;
} }
Future<bool> tryLoginFromSplash() async { Future<bool> tryAutoLogin() async {
final serverEndpoint = final serverEndpoint =
await di<IStoreRepository>().tryGet(StoreKey.serverEndpoint); await di<IStoreRepository>().tryGet(StoreKey.serverEndpoint);
if (serverEndpoint == null) { if (serverEndpoint == null) {

View File

@ -50,7 +50,7 @@ class StoreUserConverter extends IStoreConverter<User, String> {
@override @override
Future<User?> fromPrimitive(String value) async { Future<User?> fromPrimitive(String value) async {
return await di<IUserRepository>().fetch(value); return await di<IUserRepository>().getForId(value);
} }
@override @override

View File

@ -37,7 +37,7 @@ class _ImSwitchListTileState<T> extends State<ImSwitchListTile<T>> {
final value = T != bool ? widget.toAppSetting!(enabled) : enabled as T; final value = T != bool ? widget.toAppSetting!(enabled) : enabled as T;
if (value != null && if (value != null &&
await _appSettingService.setSetting(widget.setting, value) && await _appSettingService.upsert(widget.setting, value) &&
context.mounted) { context.mounted) {
setState(() { setState(() {
isEnabled = enabled; isEnabled = enabled;
@ -48,7 +48,7 @@ class _ImSwitchListTileState<T> extends State<ImSwitchListTile<T>> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_appSettingService.getSetting(widget.setting).then((value) { _appSettingService.get(widget.setting).then((value) {
if (context.mounted) { if (context.mounted) {
setState(() { setState(() {
isEnabled = T != bool ? widget.fromAppSetting!(value) : value as bool; isEnabled = T != bool ? widget.fromAppSetting!(value) : value as bool;

View File

@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:immich_mobile/domain/interfaces/asset.interface.dart'; import 'package:immich_mobile/domain/interfaces/asset.interface.dart';
import 'package:immich_mobile/domain/interfaces/renderlist.interface.dart';
import 'package:immich_mobile/presentation/components/grid/immich_asset_grid.state.dart'; import 'package:immich_mobile/presentation/components/grid/immich_asset_grid.state.dart';
import 'package:immich_mobile/presentation/components/grid/immich_asset_grid.widget.dart'; import 'package:immich_mobile/presentation/components/grid/immich_asset_grid.widget.dart';
import 'package:immich_mobile/service_locator.dart'; import 'package:immich_mobile/service_locator.dart';
@ -15,8 +16,8 @@ class HomePage extends StatelessWidget {
return Scaffold( return Scaffold(
body: BlocProvider( body: BlocProvider(
create: (_) => ImmichAssetGridCubit( create: (_) => ImmichAssetGridCubit(
renderStream: di<IAssetRepository>().watchRenderList(), renderStream: di<IRenderListRepository>().watchAll(),
assetProvider: di<IAssetRepository>().fetchAssets, assetProvider: di<IAssetRepository>().getAll,
), ),
child: const ImAssetGrid(), child: const ImAssetGrid(),
), ),

View File

@ -65,7 +65,7 @@ class LoginPageCubit extends Cubit<LoginPageState> with LogMixin {
// Check for /.well-known/immich // Check for /.well-known/immich
url = await loginService.resolveEndpoint(uri); url = await loginService.resolveEndpoint(uri);
di<IStoreRepository>().set(StoreKey.serverEndpoint, url); di<IStoreRepository>().upsert(StoreKey.serverEndpoint, url);
ServiceLocator.registerApiClient(url); ServiceLocator.registerApiClient(url);
ServiceLocator.registerPostValidationServices(); ServiceLocator.registerPostValidationServices();
ServiceLocator.registerPostGlobalStates(); ServiceLocator.registerPostGlobalStates();
@ -123,7 +123,7 @@ class LoginPageCubit extends Cubit<LoginPageState> with LogMixin {
} }
Future<void> _postLogin(String accessToken) async { Future<void> _postLogin(String accessToken) async {
await di<IStoreRepository>().set(StoreKey.accessToken, accessToken); await di<IStoreRepository>().upsert(StoreKey.accessToken, accessToken);
/// Set token to interceptor /// Set token to interceptor
await di<ImmichApiClient>().init(accessToken: accessToken); await di<ImmichApiClient>().init(accessToken: accessToken);
@ -136,10 +136,10 @@ class LoginPageCubit extends Cubit<LoginPageState> with LogMixin {
// Register user // Register user
ServiceLocator.registerCurrentUser(user); ServiceLocator.registerCurrentUser(user);
await di<IUserRepository>().add(user); await di<IUserRepository>().upsert(user);
// Remove and Sync assets in background // Remove and Sync assets in background
await di<IAssetRepository>().clearAll(); await di<IAssetRepository>().deleteAll();
unawaited(di<AssetSyncService>().doFullRemoteSyncForUserDrift(user)); unawaited(di<AssetSyncService>().performFullRemoteSyncForUser(user));
emit(state.copyWith( emit(state.copyWith(
isValidationInProgress: false, isValidationInProgress: false,

View File

@ -10,9 +10,8 @@ class AppThemeCubit extends Cubit<AppTheme> {
late final StreamSubscription _appSettingSubscription; late final StreamSubscription _appSettingSubscription;
AppThemeCubit(this._appSettings) : super(AppTheme.blue) { AppThemeCubit(this._appSettings) : super(AppTheme.blue) {
_appSettingSubscription = _appSettings _appSettingSubscription =
.watchSetting(AppSetting.appTheme) _appSettings.watch(AppSetting.appTheme).listen((theme) => emit(theme));
.listen((theme) => emit(theme));
} }
@override @override

View File

@ -3,8 +3,10 @@ import 'dart:async';
import 'package:auto_route/auto_route.dart'; import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:immich_mobile/domain/services/asset_sync.service.dart';
import 'package:immich_mobile/domain/services/login.service.dart'; import 'package:immich_mobile/domain/services/login.service.dart';
import 'package:immich_mobile/presentation/components/image/immich_logo.widget.dart'; import 'package:immich_mobile/presentation/components/image/immich_logo.widget.dart';
import 'package:immich_mobile/presentation/modules/common/states/current_user.state.dart';
import 'package:immich_mobile/presentation/modules/login/states/login_page.state.dart'; import 'package:immich_mobile/presentation/modules/login/states/login_page.state.dart';
import 'package:immich_mobile/presentation/router/router.dart'; import 'package:immich_mobile/presentation/router/router.dart';
import 'package:immich_mobile/service_locator.dart'; import 'package:immich_mobile/service_locator.dart';
@ -49,7 +51,9 @@ class _SplashScreenState extends State<SplashScreenPage>
} }
Future<void> _tryLogin() async { Future<void> _tryLogin() async {
if (await di<LoginService>().tryLoginFromSplash() && mounted) { if (await di<LoginService>().tryAutoLogin() && mounted) {
unawaited(di<AssetSyncService>()
.performFullRemoteSyncForUser(di<CurrentUserCubit>().state));
unawaited(context.replaceRoute(const TabControllerRoute())); unawaited(context.replaceRoute(const TabControllerRoute()));
} else { } else {
unawaited(context.replaceRoute(const LoginRoute())); unawaited(context.replaceRoute(const LoginRoute()));

View File

@ -69,7 +69,7 @@ class ServiceLocator {
_registerFactory<AppSettingService>(() => AppSettingService(di())); _registerFactory<AppSettingService>(() => AppSettingService(di()));
_registerFactory<IUserRepository>(() => UserDriftRepository(di())); _registerFactory<IUserRepository>(() => UserDriftRepository(di()));
_registerFactory<IAssetRepository>( _registerFactory<IAssetRepository>(
() => RemoteAssetDriftRepository(di()), () => AssetDriftRepository(di()),
); );
/// Services /// Services

View File

@ -53,7 +53,7 @@ class LogManager {
_timer = null; _timer = null;
final buffer = _msgBuffer; final buffer = _msgBuffer;
_msgBuffer = []; _msgBuffer = [];
di<ILogRepository>().addAll(buffer); di<ILogRepository>().createAll(buffer);
} }
void init() { void init() {
@ -78,7 +78,7 @@ class LogManager {
_timer?.cancel(); _timer?.cancel();
_timer = null; _timer = null;
_msgBuffer.clear(); _msgBuffer.clear();
di<ILogRepository>().clear(); di<ILogRepository>().deleteAll();
} }
static void setGlobalErrorCallbacks() { static void setGlobalErrorCallbacks() {