review changes

This commit is contained in:
shenlong-tanwen
2026-04-30 08:08:22 +07:00
parent 8eb14555dc
commit 7386226235
4 changed files with 44 additions and 40 deletions
+3 -8
View File
@@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'package:immich_mobile/domain/models/log.model.dart';
enum MetadataDomain {
appConfig('app-config'),
systemConfig('system-config');
appConfig('config.app'),
systemConfig('config.system');
final String prefix;
const MetadataDomain(this.prefix);
@@ -22,10 +22,5 @@ enum MetadataKey<T extends Object> {
String get key => '${domain.prefix}.$name';
static MetadataKey<Object>? fromKey(String key) {
for (final m in MetadataKey.values) {
if (m.key == key) return m;
}
return null;
}
static Map<String, MetadataKey<Object>> asKeyMap() => {for (var value in MetadataKey.values) value.key: value};
}
+5 -3
View File
@@ -22,7 +22,6 @@ enum StoreKey<T> {
// user settings from [AppSettingsEnum] below:
loadPreview<bool>._(100),
loadOriginal<bool>._(101),
// id 102 (themeMode) moved to user_config.theme-mode
tilesPerRow<int>._(103),
dynamicLayout<bool>._(104),
groupAssetsBy<int>._(105),
@@ -35,7 +34,6 @@ enum StoreKey<T> {
albumThumbnailCacheSize<int>._(112),
selectedAlbumSortOrder<int>._(113),
advancedTroubleshooting<bool>._(114),
// id 115 (logLevel) moved to app_metadata.log-level
preferRemoteImage<bool>._(116),
loopVideo<bool>._(117),
// map related settings
@@ -94,7 +92,11 @@ enum StoreKey<T> {
cleanupCutoffDaysAgo<int>._(1011),
cleanupDefaultsInitialized<bool>._(1012),
syncMigrationStatus<String>._(1013);
syncMigrationStatus<String>._(1013),
// Legacy keys that have been migrated to the new metadata store
legacyThemeMode<String>._(102),
legacyLogLevel<int>._(115);
const StoreKey._(this.id);
final int id;
@@ -3,7 +3,6 @@ import 'package:drift/drift.dart';
import 'package:flutter/foundation.dart';
import 'package:immich_mobile/domain/models/config/app_config.dart';
import 'package:immich_mobile/domain/models/config/system_config.dart';
import 'package:immich_mobile/domain/models/config/theme_config.dart';
import 'package:immich_mobile/domain/models/metadata_key.dart';
import 'package:immich_mobile/infrastructure/entities/metadata.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
@@ -24,6 +23,12 @@ class MetadataRepository extends DriftDatabaseRepository {
return instance;
}
AppConfig _appConfig = const .new();
AppConfig get appConfig => _appConfig;
SystemConfig _systemConfig = const .new();
SystemConfig get systemConfig => _systemConfig;
static Future<MetadataRepository> ensureInitialized(Drift db) async {
if (_instance == null) {
final instance = MetadataRepository._(db);
@@ -35,16 +40,12 @@ class MetadataRepository extends DriftDatabaseRepository {
static Future<void> refresh() async {
instance._cache.clear();
instance._appConfig = const .new();
instance._systemConfig = const .new();
await instance._hydrate();
}
Future<void> _hydrate() async {
final rows = await _db.select(_db.metadataEntity).get();
for (final row in rows) {
final key = MetadataKey.fromKey(row.key);
if (key != null) _cache[key] = decode(key, row.value);
}
}
Future<void> _hydrate() async => _hydrateCache(await _db.select(_db.metadataEntity).get());
T _read<T extends Object>(MetadataKey<T> key) => (_cache[key] as T?) ?? key.defaultValue;
@@ -56,7 +57,7 @@ class MetadataRepository extends DriftDatabaseRepository {
.insertOnConflictUpdate(
MetadataEntityCompanion.insert(key: key.key, value: encode(value), updatedAt: Value(DateTime.now())),
);
_cache[key] = value;
_updateCache(key, value);
}
@visibleForTesting
@@ -79,27 +80,36 @@ class MetadataRepository extends DriftDatabaseRepository {
}
Future<void> delete<T extends Object>(MetadataKey<T> key) async {
_cache[key] = key.defaultValue;
await (_db.delete(_db.metadataEntity)..where((t) => t.key.equals(key.key))).go();
_updateCache(key, key.defaultValue);
}
AppConfig get appConfig => AppConfig(theme: ThemeConfig(mode: _read(MetadataKey.themeMode)));
Stream<AppConfig> watchAppConfig() => _watchDomain(.appConfig).map((_) => appConfig).distinct();
SystemConfig get systemConfig => SystemConfig(logLevel: _read(MetadataKey.logLevel));
Stream<AppConfig> watchAppConfig() => _watchDomain(MetadataDomain.appConfig).map((_) => appConfig).distinct();
Stream<SystemConfig> watchSystemConfig() =>
_watchDomain(MetadataDomain.systemConfig).map((_) => systemConfig).distinct();
Stream<SystemConfig> watchSystemConfig() => _watchDomain(.systemConfig).map((_) => systemConfig).distinct();
Stream<void> _watchDomain(MetadataDomain domain) {
final query = _db.select(_db.metadataEntity)..where((t) => t.key.like('${domain.prefix}.%'));
return query.watch().map((rows) => rows.forEach(_updateCacheForRow));
return query.watch().map(_hydrateCache);
}
void _updateCacheForRow(MetadataEntityData row) {
final key = MetadataKey.fromKey(row.key);
if (key == null) return;
_cache[key] = decode(key, row.value);
void _hydrateCache(List<MetadataEntityData> rows) {
final keyMap = MetadataKey.asKeyMap();
for (final row in rows) {
final key = keyMap[row.key];
if (key == null) continue;
_updateCache(key, decode(key, row.value));
}
}
void _updateCache<T extends Object>(MetadataKey<T> key, T value) {
if (_cache[key] == value) return;
_cache[key] = value;
switch (key.domain) {
case .appConfig:
_appConfig = .new(theme: .new(mode: _read(.themeMode)));
case .systemConfig:
_systemConfig = .new(logLevel: _read(.logLevel));
}
}
}
+4 -7
View File
@@ -40,24 +40,21 @@ Future<void> _migrateTo25() async {
}
Future<void> _migrateTo26(Drift drift) async {
const int themeModeKey = 102;
const int logLevelKey = 115;
final repo = MetadataRepository.instance;
final migrated = <int>[];
final themeMode = await _readLegacyStoreString(drift, themeModeKey);
final themeMode = await _readLegacyStoreString(drift, StoreKey.legacyThemeMode.id);
if (themeMode != null) {
final mode = ThemeMode.values.firstWhere((m) => m.name == themeMode, orElse: () => ThemeMode.system);
await repo.write(MetadataKey.themeMode, mode);
migrated.add(themeModeKey);
migrated.add(StoreKey.legacyThemeMode.id);
}
final logLevelIndex = await _readLegacyStoreInt(drift, logLevelKey);
final logLevelIndex = await _readLegacyStoreInt(drift, StoreKey.legacyLogLevel.id);
if (logLevelIndex != null) {
final logLevel = LogLevel.values.elementAtOrNull(logLevelIndex) ?? LogLevel.info;
await LogService.I.setLogLevel(logLevel);
migrated.add(logLevelKey);
migrated.add(StoreKey.legacyLogLevel.id);
}
await _deleteLegacyStoreRows(drift, migrated);