refactor: proper layer archtecture

This commit is contained in:
idubnori
2025-12-10 01:06:07 +09:00
parent f874c12bee
commit 7473b959dc
12 changed files with 392 additions and 176 deletions

View File

@@ -0,0 +1,76 @@
import 'dart:convert';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/utils/action_button.utils.dart';
/// Repository for managing quick action button order persistence.
/// Handles serialization, deserialization, and storage operations.
class ActionButtonOrderRepository {
const ActionButtonOrderRepository();
/// Default order for quick actions
static const List<ActionButtonType> defaultOrder = [
ActionButtonType.share,
ActionButtonType.upload,
ActionButtonType.edit,
ActionButtonType.add,
ActionButtonType.archive,
ActionButtonType.delete,
ActionButtonType.removeFromAlbum,
ActionButtonType.likeActivity,
];
/// Get the current quick action order from storage
List<ActionButtonType> get() {
final json = Store.tryGet(StoreKey.viewerQuickActionOrder);
if (json == null || json.isEmpty) {
return defaultOrder;
}
final deserialized = _deserialize(json);
return deserialized.isEmpty ? defaultOrder : deserialized;
}
/// Save quick action order to storage
Future<void> set(List<ActionButtonType> order) async {
final json = _serialize(order);
await Store.put(StoreKey.viewerQuickActionOrder, json);
}
/// Watch for changes to quick action order
Stream<List<ActionButtonType>> watch() {
return Store.watch(StoreKey.viewerQuickActionOrder).map((json) {
if (json == null || json.isEmpty) {
return defaultOrder;
}
final deserialized = _deserialize(json);
return deserialized.isEmpty ? defaultOrder : deserialized;
});
}
/// Serialize a list of ActionButtonType to JSON string
String _serialize(List<ActionButtonType> order) {
return jsonEncode(order.map((type) => type.name).toList());
}
/// Deserialize a JSON string to a list of ActionButtonType
List<ActionButtonType> _deserialize(String json) {
try {
final list = jsonDecode(json) as List<dynamic>;
return list
.whereType<String>()
.map((name) {
try {
return ActionButtonType.values.byName(name);
} catch (e) {
return null;
}
})
.whereType<ActionButtonType>()
.toList();
} catch (e) {
return [];
}
}
}

View File

@@ -1,4 +1,3 @@
import 'dart:convert';
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/domain/models/user.model.dart';
@@ -6,7 +5,6 @@ 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:immich_mobile/utils/action_button.utils.dart';
import 'package:isar/isar.dart';
// Temporary interface until Isar is removed to make the service work with both Isar and Sqlite
@@ -86,11 +84,6 @@ class IsarStoreRepository extends IsarDatabaseRepository implements IStoreReposi
const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!),
const (UserDto) =>
entity.strValue == null ? null : await IsarUserRepository(_db).getByUserId(entity.strValue!),
const (List<ActionButtonType>) =>
(jsonDecode(entity.strValue ?? '[]') as List<dynamic>)
.map<ActionButtonType>((d) => ActionButtonType.values.byName(d))
.toList()
as T,
_ => null,
}
as T?;
@@ -102,7 +95,6 @@ class IsarStoreRepository extends IsarDatabaseRepository implements IStoreReposi
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),
const (List<ActionButtonType>) => (null, jsonEncode(value)),
_ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"),
};
return StoreValue(key.id, intValue: intValue, strValue: strValue);
@@ -182,11 +174,6 @@ class DriftStoreRepository extends DriftDatabaseRepository implements IStoreRepo
const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!),
const (UserDto) =>
entity.stringValue == null ? null : await DriftAuthUserRepository(_db).get(entity.stringValue!),
const (List<ActionButtonType>) =>
(jsonDecode(entity.stringValue ?? '[]') as List<dynamic>)
.map<ActionButtonType>((d) => ActionButtonType.values.byName(d))
.toList()
as T,
_ => null,
}
as T?;
@@ -198,7 +185,6 @@ class DriftStoreRepository extends DriftDatabaseRepository implements IStoreRepo
const (bool) => ((value as bool) ? 1 : 0, null),
const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null),
const (UserDto) => (null, (await DriftAuthUserRepository(_db).upsert(value as UserDto)).id),
const (List<ActionButtonType>) => (null, jsonEncode(value)),
_ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"),
};
return StoreEntityCompanion(id: Value(key.id), intValue: Value(intValue), stringValue: Value(strValue));