diff --git a/mobile/lib/domain/models/metadata_key.dart b/mobile/lib/domain/models/metadata_key.dart index 0a8b210e63..062b0565d7 100644 --- a/mobile/lib/domain/models/metadata_key.dart +++ b/mobile/lib/domain/models/metadata_key.dart @@ -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 { String get key => '${domain.prefix}.$name'; - static MetadataKey? fromKey(String key) { - for (final m in MetadataKey.values) { - if (m.key == key) return m; - } - return null; - } + static Map> asKeyMap() => {for (var value in MetadataKey.values) value.key: value}; } diff --git a/mobile/lib/domain/models/store.model.dart b/mobile/lib/domain/models/store.model.dart index 45fec51cd8..481085c4c1 100644 --- a/mobile/lib/domain/models/store.model.dart +++ b/mobile/lib/domain/models/store.model.dart @@ -22,7 +22,6 @@ enum StoreKey { // user settings from [AppSettingsEnum] below: loadPreview._(100), loadOriginal._(101), - // id 102 (themeMode) moved to user_config.theme-mode tilesPerRow._(103), dynamicLayout._(104), groupAssetsBy._(105), @@ -35,7 +34,6 @@ enum StoreKey { albumThumbnailCacheSize._(112), selectedAlbumSortOrder._(113), advancedTroubleshooting._(114), - // id 115 (logLevel) moved to app_metadata.log-level preferRemoteImage._(116), loopVideo._(117), // map related settings @@ -94,7 +92,11 @@ enum StoreKey { cleanupCutoffDaysAgo._(1011), cleanupDefaultsInitialized._(1012), - syncMigrationStatus._(1013); + syncMigrationStatus._(1013), + + // Legacy keys that have been migrated to the new metadata store + legacyThemeMode._(102), + legacyLogLevel._(115); const StoreKey._(this.id); final int id; diff --git a/mobile/lib/infrastructure/repositories/metadata.repository.dart b/mobile/lib/infrastructure/repositories/metadata.repository.dart index 5f04063389..90cc59249d 100644 --- a/mobile/lib/infrastructure/repositories/metadata.repository.dart +++ b/mobile/lib/infrastructure/repositories/metadata.repository.dart @@ -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 ensureInitialized(Drift db) async { if (_instance == null) { final instance = MetadataRepository._(db); @@ -35,16 +40,12 @@ class MetadataRepository extends DriftDatabaseRepository { static Future refresh() async { instance._cache.clear(); + instance._appConfig = const .new(); + instance._systemConfig = const .new(); await instance._hydrate(); } - Future _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 _hydrate() async => _hydrateCache(await _db.select(_db.metadataEntity).get()); T _read(MetadataKey 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 delete(MetadataKey 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 watchAppConfig() => _watchDomain(.appConfig).map((_) => appConfig).distinct(); - SystemConfig get systemConfig => SystemConfig(logLevel: _read(MetadataKey.logLevel)); - - Stream watchAppConfig() => _watchDomain(MetadataDomain.appConfig).map((_) => appConfig).distinct(); - - Stream watchSystemConfig() => - _watchDomain(MetadataDomain.systemConfig).map((_) => systemConfig).distinct(); + Stream watchSystemConfig() => _watchDomain(.systemConfig).map((_) => systemConfig).distinct(); Stream _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 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(MetadataKey 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)); + } } } diff --git a/mobile/lib/utils/migration.dart b/mobile/lib/utils/migration.dart index c08a4e4353..dcb6f5a44c 100644 --- a/mobile/lib/utils/migration.dart +++ b/mobile/lib/utils/migration.dart @@ -40,24 +40,21 @@ Future _migrateTo25() async { } Future _migrateTo26(Drift drift) async { - const int themeModeKey = 102; - const int logLevelKey = 115; - final repo = MetadataRepository.instance; final migrated = []; - 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);