mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
migrate dynamic theme
This commit is contained in:
@@ -4,19 +4,27 @@ import 'package:immich_mobile/constants/colors.dart';
|
|||||||
class ThemeConfig {
|
class ThemeConfig {
|
||||||
final ThemeMode mode;
|
final ThemeMode mode;
|
||||||
final ImmichColorPreset primaryColor;
|
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}) =>
|
ThemeConfig copyWith({ThemeMode? mode, ImmichColorPreset? primaryColor, bool? dynamicTheme}) => .new(
|
||||||
.new(mode: mode ?? this.mode, primaryColor: primaryColor ?? this.primaryColor);
|
mode: mode ?? this.mode,
|
||||||
|
primaryColor: primaryColor ?? this.primaryColor,
|
||||||
|
dynamicTheme: dynamicTheme ?? this.dynamicTheme,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
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
|
@override
|
||||||
int get hashCode => Object.hash(mode, primaryColor);
|
int get hashCode => Object.hash(mode, primaryColor, dynamicTheme);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'ThemeConfig(mode: $mode, primaryColor: $primaryColor)';
|
String toString() => 'ThemeConfig(mode: $mode, primaryColor: $primaryColor, dynamicTheme: $dynamicTheme)';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ enum MetadataKey<T extends Object> {
|
|||||||
// Theme
|
// Theme
|
||||||
primaryColor<ImmichColorPreset>(.appConfig, 'theme.primaryColor', .indigo, _EnumCodec(ImmichColorPreset.values)),
|
primaryColor<ImmichColorPreset>(.appConfig, 'theme.primaryColor', .indigo, _EnumCodec(ImmichColorPreset.values)),
|
||||||
themeMode<ThemeMode>(.appConfig, 'theme.mode', .system, _EnumCodec(ThemeMode.values)),
|
themeMode<ThemeMode>(.appConfig, 'theme.mode', .system, _EnumCodec(ThemeMode.values)),
|
||||||
|
dynamicTheme<bool>(.appConfig, 'dynamicTheme', false),
|
||||||
|
|
||||||
// Log
|
// Log
|
||||||
logLevel<LogLevel>(.systemConfig, 'log.level', .info, _EnumCodec(LogLevel.values));
|
logLevel<LogLevel>(.systemConfig, 'log.level', .info, _EnumCodec(LogLevel.values));
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ enum StoreKey<T> {
|
|||||||
customHeaders<String>._(127),
|
customHeaders<String>._(127),
|
||||||
|
|
||||||
// theme settings
|
// theme settings
|
||||||
dynamicTheme<bool>._(129),
|
|
||||||
colorfulInterface<bool>._(130),
|
colorfulInterface<bool>._(130),
|
||||||
|
|
||||||
syncAlbums<bool>._(131),
|
syncAlbums<bool>._(131),
|
||||||
@@ -95,6 +94,7 @@ enum StoreKey<T> {
|
|||||||
|
|
||||||
// Legacy keys that have been migrated to the new metadata store
|
// Legacy keys that have been migrated to the new metadata store
|
||||||
legacyPrimaryColor<String>._(128),
|
legacyPrimaryColor<String>._(128),
|
||||||
|
legacyDynamicTheme<bool>._(129),
|
||||||
legacyThemeMode<String>._(102),
|
legacyThemeMode<String>._(102),
|
||||||
legacyLogLevel<int>._(115);
|
legacyLogLevel<int>._(115);
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,11 @@ extension<T extends Object> on MetadataDomain<T> {
|
|||||||
switch (this) {
|
switch (this) {
|
||||||
case .appConfig:
|
case .appConfig:
|
||||||
repo._appConfig = .new(
|
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:
|
case .systemConfig:
|
||||||
repo._systemConfig = .new(logLevel: repo._read(.logLevel));
|
repo._systemConfig = .new(logLevel: repo._read(.logLevel));
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ final immichThemePresetProvider = StateProvider<ImmichColorPreset>(
|
|||||||
(ref) => ref.watch(appConfigProvider.select((config) => config.theme.primaryColor)),
|
(ref) => ref.watch(appConfigProvider.select((config) => config.theme.primaryColor)),
|
||||||
);
|
);
|
||||||
|
|
||||||
final dynamicThemeSettingProvider = StateProvider<bool>((ref) {
|
final dynamicThemeSettingProvider = StateProvider<bool>(
|
||||||
return ref.watch(appSettingsServiceProvider).getSetting(AppSettingsEnum.dynamicTheme);
|
(ref) => ref.watch(appConfigProvider.select((config) => config.theme.dynamicTheme)),
|
||||||
});
|
);
|
||||||
|
|
||||||
final colorfulInterfaceSettingProvider = StateProvider<bool>((ref) {
|
final colorfulInterfaceSettingProvider = StateProvider<bool>((ref) {
|
||||||
return ref.watch(appSettingsServiceProvider).getSetting(AppSettingsEnum.colorfulInterface);
|
return ref.watch(appSettingsServiceProvider).getSetting(AppSettingsEnum.colorfulInterface);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import 'package:immich_mobile/entities/store.entity.dart';
|
|||||||
enum AppSettingsEnum<T> {
|
enum AppSettingsEnum<T> {
|
||||||
loadPreview<bool>(StoreKey.loadPreview, "loadPreview", true),
|
loadPreview<bool>(StoreKey.loadPreview, "loadPreview", true),
|
||||||
loadOriginal<bool>(StoreKey.loadOriginal, "loadOriginal", false),
|
loadOriginal<bool>(StoreKey.loadOriginal, "loadOriginal", false),
|
||||||
dynamicTheme<bool>(StoreKey.dynamicTheme, "dynamicTheme", false),
|
|
||||||
colorfulInterface<bool>(StoreKey.colorfulInterface, "colorfulInterface", true),
|
colorfulInterface<bool>(StoreKey.colorfulInterface, "colorfulInterface", true),
|
||||||
tilesPerRow<int>(StoreKey.tilesPerRow, "tilesPerRow", 4),
|
tilesPerRow<int>(StoreKey.tilesPerRow, "tilesPerRow", 4),
|
||||||
dynamicLayout<bool>(StoreKey.dynamicLayout, "dynamicLayout", false),
|
dynamicLayout<bool>(StoreKey.dynamicLayout, "dynamicLayout", false),
|
||||||
|
|||||||
@@ -65,6 +65,13 @@ Future<void> _migrateTo26(Drift drift) async {
|
|||||||
migrated.add(StoreKey.legacyPrimaryColor.id);
|
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);
|
await _deleteLegacyStoreRows(drift, migrated);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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/extensions/theme_extensions.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/metadata.provider.dart';
|
||||||
import 'package:immich_mobile/providers/theme.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/color_scheme.dart';
|
||||||
import 'package:immich_mobile/theme/dynamic_theme.dart';
|
import 'package:immich_mobile/theme/dynamic_theme.dart';
|
||||||
import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart';
|
|
||||||
|
|
||||||
class PrimaryColorSetting extends HookConsumerWidget {
|
class PrimaryColorSetting extends HookConsumerWidget {
|
||||||
const PrimaryColorSetting({super.key});
|
const PrimaryColorSetting({super.key});
|
||||||
@@ -18,9 +16,7 @@ class PrimaryColorSetting extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final themeProvider = ref.read(immichThemeProvider);
|
final themeProvider = ref.read(immichThemeProvider);
|
||||||
|
final themeConfig = ref.watch(appConfigProvider.select((config) => config.theme));
|
||||||
final currentPreset = ref.watch(appConfigProvider.select((config) => config.theme.primaryColor));
|
|
||||||
final systemPrimaryColorSetting = useAppSettingsState(AppSettingsEnum.dynamicTheme);
|
|
||||||
|
|
||||||
const tileSize = 55.0;
|
const tileSize = 55.0;
|
||||||
|
|
||||||
@@ -31,9 +27,7 @@ class PrimaryColorSetting extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onUseSystemColorChange(bool newValue) {
|
onUseSystemColorChange(bool newValue) {
|
||||||
systemPrimaryColorSetting.value = newValue;
|
ref.read(metadataProvider).write(MetadataKey.dynamicTheme, newValue);
|
||||||
ref.watch(dynamicThemeSettingProvider.notifier).state = newValue;
|
|
||||||
ref.invalidate(immichThemeProvider);
|
|
||||||
popBottomSheet();
|
popBottomSheet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,11 +35,10 @@ class PrimaryColorSetting extends HookConsumerWidget {
|
|||||||
ref.read(metadataProvider).write(MetadataKey.primaryColor, colorPreset);
|
ref.read(metadataProvider).write(MetadataKey.primaryColor, colorPreset);
|
||||||
|
|
||||||
//turn off system color setting
|
//turn off system color setting
|
||||||
if (systemPrimaryColorSetting.value) {
|
if (themeConfig.dynamicTheme) {
|
||||||
onUseSystemColorChange(false);
|
ref.read(metadataProvider).write(MetadataKey.dynamicTheme, false);
|
||||||
} else {
|
|
||||||
popBottomSheet();
|
|
||||||
}
|
}
|
||||||
|
popBottomSheet();
|
||||||
}
|
}
|
||||||
|
|
||||||
buildPrimaryColorTile({
|
buildPrimaryColorTile({
|
||||||
@@ -115,7 +108,7 @@ class PrimaryColorSetting extends HookConsumerWidget {
|
|||||||
'theme_setting_system_primary_color_title'.tr(),
|
'theme_setting_system_primary_color_title'.tr(),
|
||||||
style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500, height: 1.5),
|
style: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.w500, height: 1.5),
|
||||||
),
|
),
|
||||||
value: systemPrimaryColorSetting.value,
|
value: themeConfig.dynamicTheme,
|
||||||
onChanged: onUseSystemColorChange,
|
onChanged: onUseSystemColorChange,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -133,7 +126,7 @@ class PrimaryColorSetting extends HookConsumerWidget {
|
|||||||
topColor: theme.light.primary,
|
topColor: theme.light.primary,
|
||||||
bottomColor: theme.dark.primary,
|
bottomColor: theme.dark.primary,
|
||||||
tileSize: tileSize,
|
tileSize: tileSize,
|
||||||
showSelector: currentPreset == preset && !systemPrimaryColorSetting.value,
|
showSelector: themeConfig.primaryColor == preset && !themeConfig.dynamicTheme,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
|
|||||||
Reference in New Issue
Block a user