diff --git a/mobile/lib/domain/models/config/theme_config.dart b/mobile/lib/domain/models/config/theme_config.dart index df090e9dc7..fd83defdd6 100644 --- a/mobile/lib/domain/models/config/theme_config.dart +++ b/mobile/lib/domain/models/config/theme_config.dart @@ -4,19 +4,27 @@ import 'package:immich_mobile/constants/colors.dart'; class ThemeConfig { final ThemeMode mode; final ImmichColorPreset primaryColor; + final bool dynamicTheme; - const ThemeConfig({this.mode = .system, this.primaryColor = .indigo}); + const ThemeConfig({this.mode = .system, this.primaryColor = .indigo, this.dynamicTheme = false}); - ThemeConfig copyWith({ThemeMode? mode, ImmichColorPreset? primaryColor}) => - .new(mode: mode ?? this.mode, primaryColor: primaryColor ?? this.primaryColor); + ThemeConfig copyWith({ThemeMode? mode, ImmichColorPreset? primaryColor, bool? dynamicTheme}) => .new( + mode: mode ?? this.mode, + primaryColor: primaryColor ?? this.primaryColor, + dynamicTheme: dynamicTheme ?? this.dynamicTheme, + ); @override bool operator ==(Object other) => - identical(this, other) || (other is ThemeConfig && other.mode == mode && other.primaryColor == primaryColor); + identical(this, other) || + (other is ThemeConfig && + other.mode == mode && + other.primaryColor == primaryColor && + other.dynamicTheme == dynamicTheme); @override - int get hashCode => Object.hash(mode, primaryColor); + int get hashCode => Object.hash(mode, primaryColor, dynamicTheme); @override - String toString() => 'ThemeConfig(mode: $mode, primaryColor: $primaryColor)'; + String toString() => 'ThemeConfig(mode: $mode, primaryColor: $primaryColor, dynamicTheme: $dynamicTheme)'; } diff --git a/mobile/lib/domain/models/metadata_key.dart b/mobile/lib/domain/models/metadata_key.dart index 943a86a3b5..6d510413da 100644 --- a/mobile/lib/domain/models/metadata_key.dart +++ b/mobile/lib/domain/models/metadata_key.dart @@ -17,6 +17,7 @@ enum MetadataKey { // Theme primaryColor(.appConfig, 'theme.primaryColor', .indigo, _EnumCodec(ImmichColorPreset.values)), themeMode(.appConfig, 'theme.mode', .system, _EnumCodec(ThemeMode.values)), + dynamicTheme(.appConfig, 'dynamicTheme', false), // Log logLevel(.systemConfig, 'log.level', .info, _EnumCodec(LogLevel.values)); diff --git a/mobile/lib/domain/models/store.model.dart b/mobile/lib/domain/models/store.model.dart index 5d47c05f8f..413549d021 100644 --- a/mobile/lib/domain/models/store.model.dart +++ b/mobile/lib/domain/models/store.model.dart @@ -49,7 +49,6 @@ enum StoreKey { customHeaders._(127), // theme settings - dynamicTheme._(129), colorfulInterface._(130), syncAlbums._(131), @@ -95,6 +94,7 @@ enum StoreKey { // Legacy keys that have been migrated to the new metadata store legacyPrimaryColor._(128), + legacyDynamicTheme._(129), legacyThemeMode._(102), legacyLogLevel._(115); diff --git a/mobile/lib/infrastructure/repositories/metadata.repository.dart b/mobile/lib/infrastructure/repositories/metadata.repository.dart index 2b0704e35b..825e8e664e 100644 --- a/mobile/lib/infrastructure/repositories/metadata.repository.dart +++ b/mobile/lib/infrastructure/repositories/metadata.repository.dart @@ -101,7 +101,11 @@ extension on MetadataDomain { switch (this) { case .appConfig: repo._appConfig = .new( - theme: .new(mode: repo._read(.themeMode), primaryColor: repo._read(.primaryColor)), + theme: .new( + mode: repo._read(.themeMode), + primaryColor: repo._read(.primaryColor), + dynamicTheme: repo._read(.dynamicTheme), + ), ); case .systemConfig: repo._systemConfig = .new(logLevel: repo._read(.logLevel)); diff --git a/mobile/lib/providers/theme.provider.dart b/mobile/lib/providers/theme.provider.dart index df6a24e902..f6497bfa0a 100644 --- a/mobile/lib/providers/theme.provider.dart +++ b/mobile/lib/providers/theme.provider.dart @@ -14,9 +14,9 @@ final immichThemePresetProvider = StateProvider( (ref) => ref.watch(appConfigProvider.select((config) => config.theme.primaryColor)), ); -final dynamicThemeSettingProvider = StateProvider((ref) { - return ref.watch(appSettingsServiceProvider).getSetting(AppSettingsEnum.dynamicTheme); -}); +final dynamicThemeSettingProvider = StateProvider( + (ref) => ref.watch(appConfigProvider.select((config) => config.theme.dynamicTheme)), +); final colorfulInterfaceSettingProvider = StateProvider((ref) { return ref.watch(appSettingsServiceProvider).getSetting(AppSettingsEnum.colorfulInterface); diff --git a/mobile/lib/services/app_settings.service.dart b/mobile/lib/services/app_settings.service.dart index 1f3bf9c719..d2363a72eb 100644 --- a/mobile/lib/services/app_settings.service.dart +++ b/mobile/lib/services/app_settings.service.dart @@ -4,7 +4,6 @@ import 'package:immich_mobile/entities/store.entity.dart'; enum AppSettingsEnum { loadPreview(StoreKey.loadPreview, "loadPreview", true), loadOriginal(StoreKey.loadOriginal, "loadOriginal", false), - dynamicTheme(StoreKey.dynamicTheme, "dynamicTheme", false), colorfulInterface(StoreKey.colorfulInterface, "colorfulInterface", true), tilesPerRow(StoreKey.tilesPerRow, "tilesPerRow", 4), dynamicLayout(StoreKey.dynamicLayout, "dynamicLayout", false), diff --git a/mobile/lib/utils/migration.dart b/mobile/lib/utils/migration.dart index 377a92e21e..4a5429e7e5 100644 --- a/mobile/lib/utils/migration.dart +++ b/mobile/lib/utils/migration.dart @@ -65,6 +65,13 @@ Future _migrateTo26(Drift drift) async { migrated.add(StoreKey.legacyPrimaryColor.id); } + final dynamicTheme = await _readLegacyStoreInt(drift, StoreKey.legacyDynamicTheme.id); + if (dynamicTheme != null) { + final dynamicThemeValue = dynamicTheme != 0; + await repo.write(MetadataKey.dynamicTheme, dynamicThemeValue); + migrated.add(StoreKey.legacyDynamicTheme.id); + } + await _deleteLegacyStoreRows(drift, migrated); } diff --git a/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart b/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart index 67a723591a..617a9a0758 100644 --- a/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart @@ -7,10 +7,8 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart'; import 'package:immich_mobile/providers/theme.provider.dart'; -import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/theme/color_scheme.dart'; import 'package:immich_mobile/theme/dynamic_theme.dart'; -import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; class PrimaryColorSetting extends HookConsumerWidget { const PrimaryColorSetting({super.key}); @@ -18,9 +16,7 @@ class PrimaryColorSetting extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final themeProvider = ref.read(immichThemeProvider); - - final currentPreset = ref.watch(appConfigProvider.select((config) => config.theme.primaryColor)); - final systemPrimaryColorSetting = useAppSettingsState(AppSettingsEnum.dynamicTheme); + final themeConfig = ref.watch(appConfigProvider.select((config) => config.theme)); const tileSize = 55.0; @@ -31,9 +27,7 @@ class PrimaryColorSetting extends HookConsumerWidget { } onUseSystemColorChange(bool newValue) { - systemPrimaryColorSetting.value = newValue; - ref.watch(dynamicThemeSettingProvider.notifier).state = newValue; - ref.invalidate(immichThemeProvider); + ref.read(metadataProvider).write(MetadataKey.dynamicTheme, newValue); popBottomSheet(); } @@ -41,11 +35,10 @@ class PrimaryColorSetting extends HookConsumerWidget { ref.read(metadataProvider).write(MetadataKey.primaryColor, colorPreset); //turn off system color setting - if (systemPrimaryColorSetting.value) { - onUseSystemColorChange(false); - } else { - popBottomSheet(); + if (themeConfig.dynamicTheme) { + ref.read(metadataProvider).write(MetadataKey.dynamicTheme, false); } + popBottomSheet(); } buildPrimaryColorTile({ @@ -115,7 +108,7 @@ class PrimaryColorSetting extends HookConsumerWidget { 'theme_setting_system_primary_color_title'.tr(), style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500, height: 1.5), ), - value: systemPrimaryColorSetting.value, + value: themeConfig.dynamicTheme, onChanged: onUseSystemColorChange, ), ), @@ -133,7 +126,7 @@ class PrimaryColorSetting extends HookConsumerWidget { topColor: theme.light.primary, bottomColor: theme.dark.primary, tileSize: tileSize, - showSelector: currentPreset == preset && !systemPrimaryColorSetting.value, + showSelector: themeConfig.primaryColor == preset && !themeConfig.dynamicTheme, ), ); }).toList(),