mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 16:56:19 +01:00
Support system theme color (aka Material You)
This commit is contained in:
parent
2c50e06991
commit
cadf9c7410
13 changed files with 216 additions and 109 deletions
|
@ -251,8 +251,14 @@ extension PrefExtension on Pref {
|
|||
|
||||
int? getSeedColor() => provider.getInt(PrefKey.seedColor);
|
||||
int getSeedColorOr(int def) => getSeedColor() ?? def;
|
||||
Future<bool> setSeedColor(int value) => _set<int>(
|
||||
PrefKey.seedColor, value, (key, value) => provider.setInt(key, value));
|
||||
Future<bool> setSeedColor(int? value) {
|
||||
if (value == null) {
|
||||
return _remove(PrefKey.seedColor);
|
||||
} else {
|
||||
return _set<int>(PrefKey.seedColor, value,
|
||||
(key, value) => provider.setInt(key, value));
|
||||
}
|
||||
}
|
||||
|
||||
bool? isVideoPlayerMute() => provider.getBool(PrefKey.isVideoPlayerMute);
|
||||
bool isVideoPlayerMuteOr([bool def = false]) => isVideoPlayerMute() ?? def;
|
||||
|
|
|
@ -383,10 +383,18 @@
|
|||
"@settingsSeedColorDescription": {
|
||||
"description": "Customize the colors used in app"
|
||||
},
|
||||
"settingsSeedColorSystemColorDescription": "Use system color",
|
||||
"@settingsSeedColorSystemColorDescription": {
|
||||
"description": "Use color provided by the OS, i.e., Material You"
|
||||
},
|
||||
"settingsSeedColorPickerTitle": "Pick a color",
|
||||
"@settingsSeedColorPickerTitle": {
|
||||
"description": "Dialog to customize the colors used in app"
|
||||
},
|
||||
"settingsSeedColorPickerSystemColorButtonLabel": "USE SYSTEM COLOR",
|
||||
"@settingsSeedColorPickerSystemColorButtonLabel": {
|
||||
"description": "Use color provided by the OS, i.e., Material You"
|
||||
},
|
||||
"settingsUseBlackInDarkThemeTitle": "Darker theme",
|
||||
"@settingsUseBlackInDarkThemeTitle": {
|
||||
"description": "Make the dark theme darker"
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
"cs": [
|
||||
"nameInputInvalidEmpty",
|
||||
"settingsPersonProviderTitle",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsServerVersionTitle",
|
||||
"searchLandingPeopleListEmptyText2",
|
||||
"createCollectionFailureNotification",
|
||||
|
@ -49,7 +51,9 @@
|
|||
"settingsImageEditSaveResultsToServerFalseDescription",
|
||||
"settingsSeedColorTitle",
|
||||
"settingsSeedColorDescription",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerTitle",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsMiscellaneousTitle",
|
||||
"settingsDoubleTapExitTitle",
|
||||
"settingsPhotosTabSortByNameTitle",
|
||||
|
@ -242,7 +246,9 @@
|
|||
"settingsImageEditSaveResultsToServerFalseDescription",
|
||||
"settingsSeedColorTitle",
|
||||
"settingsSeedColorDescription",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerTitle",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsDoubleTapExitTitle",
|
||||
"settingsExpertTitle",
|
||||
"settingsExpertWarningText",
|
||||
|
@ -328,12 +334,16 @@
|
|||
|
||||
"es": [
|
||||
"settingsPersonProviderTitle",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"searchLandingPeopleListEmptyText2",
|
||||
"accountSettingsTooltip"
|
||||
],
|
||||
|
||||
"fi": [
|
||||
"settingsPersonProviderTitle",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"searchLandingPeopleListEmptyText2",
|
||||
"accountSettingsTooltip"
|
||||
],
|
||||
|
@ -362,7 +372,9 @@
|
|||
"settingsImageEditSaveResultsToServerFalseDescription",
|
||||
"settingsSeedColorTitle",
|
||||
"settingsSeedColorDescription",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerTitle",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsMiscellaneousTitle",
|
||||
"settingsDoubleTapExitTitle",
|
||||
"settingsPhotosTabSortByNameTitle",
|
||||
|
@ -495,7 +507,9 @@
|
|||
"settingsFollowSystemThemeTitle",
|
||||
"settingsSeedColorTitle",
|
||||
"settingsSeedColorDescription",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerTitle",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsUseBlackInDarkThemeTitle",
|
||||
"settingsUseBlackInDarkThemeTrueDescription",
|
||||
"settingsUseBlackInDarkThemeFalseDescription",
|
||||
|
@ -843,7 +857,9 @@
|
|||
"settingsFollowSystemThemeTitle",
|
||||
"settingsSeedColorTitle",
|
||||
"settingsSeedColorDescription",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerTitle",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsUseBlackInDarkThemeTitle",
|
||||
"settingsUseBlackInDarkThemeTrueDescription",
|
||||
"settingsUseBlackInDarkThemeFalseDescription",
|
||||
|
@ -1145,7 +1161,9 @@
|
|||
"settingsImageEditSaveResultsToServerFalseDescription",
|
||||
"settingsSeedColorTitle",
|
||||
"settingsSeedColorDescription",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerTitle",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsMiscellaneousTitle",
|
||||
"settingsDoubleTapExitTitle",
|
||||
"settingsPhotosTabSortByNameTitle",
|
||||
|
@ -1265,6 +1283,8 @@
|
|||
"pt": [
|
||||
"nameInputInvalidEmpty",
|
||||
"settingsPersonProviderTitle",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsServerVersionTitle",
|
||||
"searchLandingPeopleListEmptyText2",
|
||||
"createCollectionFailureNotification",
|
||||
|
@ -1302,7 +1322,9 @@
|
|||
"settingsImageEditSaveResultsToServerFalseDescription",
|
||||
"settingsSeedColorTitle",
|
||||
"settingsSeedColorDescription",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerTitle",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsMiscellaneousTitle",
|
||||
"settingsDoubleTapExitTitle",
|
||||
"settingsPhotosTabSortByNameTitle",
|
||||
|
@ -1424,7 +1446,9 @@
|
|||
"settingsImageEditSaveResultsToServerFalseDescription",
|
||||
"settingsSeedColorTitle",
|
||||
"settingsSeedColorDescription",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerTitle",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsMiscellaneousTitle",
|
||||
"settingsDoubleTapExitTitle",
|
||||
"settingsPhotosTabSortByNameTitle",
|
||||
|
@ -1546,7 +1570,9 @@
|
|||
"settingsImageEditSaveResultsToServerFalseDescription",
|
||||
"settingsSeedColorTitle",
|
||||
"settingsSeedColorDescription",
|
||||
"settingsSeedColorSystemColorDescription",
|
||||
"settingsSeedColorPickerTitle",
|
||||
"settingsSeedColorPickerSystemColorButtonLabel",
|
||||
"settingsMiscellaneousTitle",
|
||||
"settingsDoubleTapExitTitle",
|
||||
"settingsPhotosTabSortByNameTitle",
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
|||
|
||||
class M3 extends ThemeExtension<M3> {
|
||||
const M3({
|
||||
required this.seed,
|
||||
required this.checkbox,
|
||||
required this.filterChip,
|
||||
required this.listTile,
|
||||
|
@ -12,13 +11,11 @@ class M3 extends ThemeExtension<M3> {
|
|||
|
||||
@override
|
||||
M3 copyWith({
|
||||
Color? seed,
|
||||
M3Checkbox? checkbox,
|
||||
M3FilterChip? filterChip,
|
||||
M3ListTile? listTile,
|
||||
}) =>
|
||||
M3(
|
||||
seed: seed ?? this.seed,
|
||||
checkbox: checkbox ?? this.checkbox,
|
||||
filterChip: filterChip ?? this.filterChip,
|
||||
listTile: listTile ?? this.listTile,
|
||||
|
@ -30,14 +27,12 @@ class M3 extends ThemeExtension<M3> {
|
|||
return this;
|
||||
}
|
||||
return M3(
|
||||
seed: Color.lerp(seed, other.seed, t)!,
|
||||
checkbox: checkbox.lerp(other.checkbox, t),
|
||||
filterChip: filterChip.lerp(other.filterChip, t),
|
||||
listTile: listTile.lerp(other.listTile, t),
|
||||
);
|
||||
}
|
||||
|
||||
final Color seed;
|
||||
final M3Checkbox checkbox;
|
||||
final M3FilterChip filterChip;
|
||||
final M3ListTile listTile;
|
||||
|
|
|
@ -12,5 +12,8 @@ class SessionStorage {
|
|||
/// Whether the drag to rearrange notification has been shown
|
||||
bool hasShowDragRearrangeNotification = false;
|
||||
|
||||
/// Whether the dynamic_color library is supported in this platform
|
||||
bool isSupportDynamicColor = false;
|
||||
|
||||
static final _inst = SessionStorage._();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ import 'dart:ui';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:nc_photos/entity/pref.dart';
|
||||
import 'package:nc_photos/material3.dart';
|
||||
import 'package:nc_photos/object_extension.dart';
|
||||
|
||||
const defaultSeedColor = 0xFF2196F3;
|
||||
|
||||
extension ThemeExtension on ThemeData {
|
||||
double get widthLimitedContentMaxWidth => 550.0;
|
||||
|
@ -90,38 +93,43 @@ ThemeData buildTheme(Brightness brightness) {
|
|||
: buildDarkTheme();
|
||||
}
|
||||
|
||||
ThemeData buildLightTheme() {
|
||||
final seedColor = getSeedColor();
|
||||
final colorScheme = ColorScheme.fromSeed(
|
||||
seedColor: seedColor,
|
||||
);
|
||||
return _applyColorScheme(colorScheme, seedColor);
|
||||
ThemeData buildLightTheme([ColorScheme? dynamicScheme]) {
|
||||
final colorScheme = _getColorScheme(dynamicScheme, Brightness.light);
|
||||
return _applyColorScheme(colorScheme);
|
||||
}
|
||||
|
||||
ThemeData buildDarkTheme() {
|
||||
final seedColor = getSeedColor();
|
||||
final colorScheme = ColorScheme.fromSeed(
|
||||
seedColor: seedColor,
|
||||
brightness: Brightness.dark,
|
||||
);
|
||||
ThemeData buildDarkTheme([ColorScheme? dynamicScheme]) {
|
||||
final colorScheme = _getColorScheme(dynamicScheme, Brightness.dark);
|
||||
if (Pref().isUseBlackInDarkThemeOr(false)) {
|
||||
return _applyColorScheme(
|
||||
colorScheme.copyWith(
|
||||
background: Colors.black,
|
||||
surface: Colors.grey[900],
|
||||
),
|
||||
seedColor,
|
||||
);
|
||||
return _applyColorScheme(colorScheme.copyWith(
|
||||
background: Colors.black,
|
||||
surface: Colors.grey[900],
|
||||
));
|
||||
} else {
|
||||
return _applyColorScheme(colorScheme, seedColor);
|
||||
return _applyColorScheme(colorScheme);
|
||||
}
|
||||
}
|
||||
|
||||
Color getSeedColor() {
|
||||
return Color(Pref().getSeedColor() ?? 0xFF2196F3).withAlpha(0xFF);
|
||||
Color? getSeedColor() {
|
||||
return Pref().getSeedColor()?.run((c) => Color(c).withAlpha(0xFF));
|
||||
}
|
||||
|
||||
ThemeData _applyColorScheme(ColorScheme colorScheme, Color seedColor) {
|
||||
ColorScheme _getColorScheme(ColorScheme? dynamicScheme, Brightness brightness) {
|
||||
var seedColor = Pref().getSeedColor();
|
||||
if (seedColor == null) {
|
||||
if (dynamicScheme != null) {
|
||||
return dynamicScheme;
|
||||
} else {
|
||||
seedColor = defaultSeedColor;
|
||||
}
|
||||
}
|
||||
return ColorScheme.fromSeed(
|
||||
seedColor: Color(seedColor),
|
||||
brightness: brightness,
|
||||
);
|
||||
}
|
||||
|
||||
ThemeData _applyColorScheme(ColorScheme colorScheme) {
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: colorScheme.brightness,
|
||||
|
@ -212,7 +220,6 @@ ThemeData _applyColorScheme(ColorScheme colorScheme, Color seedColor) {
|
|||
),
|
||||
extensions: [
|
||||
M3(
|
||||
seed: seedColor,
|
||||
checkbox: M3Checkbox(
|
||||
disabled: M3CheckboxDisabled(
|
||||
container: colorScheme.onSurface.withOpacity(.38),
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:dynamic_color/dynamic_color.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
@ -13,6 +14,7 @@ import 'package:nc_photos/language_util.dart' as language_util;
|
|||
import 'package:nc_photos/legacy/connect.dart' as legacy;
|
||||
import 'package:nc_photos/legacy/sign_in.dart' as legacy;
|
||||
import 'package:nc_photos/navigation_manager.dart';
|
||||
import 'package:nc_photos/session_storage.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/stream_util.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
|
@ -97,7 +99,7 @@ class _WrappedAppState extends State<_WrappedApp>
|
|||
}
|
||||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeMode themeMode;
|
||||
if (Pref().isFollowSystemThemeOr(false)) {
|
||||
themeMode = ThemeMode.system;
|
||||
|
@ -108,42 +110,50 @@ class _WrappedAppState extends State<_WrappedApp>
|
|||
final prefController = context.read<PrefController>();
|
||||
return ValueStreamBuilder<language_util.AppLanguage>(
|
||||
stream: prefController.language,
|
||||
builder: (context, snapshot) => MaterialApp(
|
||||
onGenerateTitle: (context) => AppLocalizations.of(context)!.appTitle,
|
||||
theme: buildLightTheme(),
|
||||
darkTheme: buildDarkTheme(),
|
||||
themeMode: themeMode,
|
||||
initialRoute: Splash.routeName,
|
||||
onGenerateRoute: _onGenerateRoute,
|
||||
navigatorObservers: <NavigatorObserver>[MyApp.routeObserver],
|
||||
navigatorKey: _navigatorKey,
|
||||
scaffoldMessengerKey: _scaffoldMessengerKey,
|
||||
locale: snapshot.requireData.locale,
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: const <Locale>[
|
||||
// the order here doesn't matter, except for the first one, which must
|
||||
// be en
|
||||
Locale("en"),
|
||||
Locale("el"),
|
||||
Locale("es"),
|
||||
Locale("fr"),
|
||||
Locale("ru"),
|
||||
Locale("de"),
|
||||
Locale("cs"),
|
||||
Locale("fi"),
|
||||
Locale("pl"),
|
||||
Locale("pt"),
|
||||
Locale.fromSubtags(languageCode: "zh", scriptCode: "Hans"),
|
||||
Locale.fromSubtags(languageCode: "zh", scriptCode: "Hant"),
|
||||
Locale("it"),
|
||||
Locale("nl"),
|
||||
],
|
||||
builder: (context, child) {
|
||||
MyApp._globalContext = context;
|
||||
return child!;
|
||||
builder: (context, snapshot) => DynamicColorBuilder(
|
||||
builder: (lightDynamic, darkDynamic) {
|
||||
if (lightDynamic != null) {
|
||||
SessionStorage().isSupportDynamicColor = true;
|
||||
}
|
||||
return MaterialApp(
|
||||
onGenerateTitle: (context) =>
|
||||
AppLocalizations.of(context)!.appTitle,
|
||||
theme: buildLightTheme(lightDynamic),
|
||||
darkTheme: buildDarkTheme(darkDynamic),
|
||||
themeMode: themeMode,
|
||||
initialRoute: Splash.routeName,
|
||||
onGenerateRoute: _onGenerateRoute,
|
||||
navigatorObservers: <NavigatorObserver>[MyApp.routeObserver],
|
||||
navigatorKey: _navigatorKey,
|
||||
scaffoldMessengerKey: _scaffoldMessengerKey,
|
||||
locale: snapshot.requireData.locale,
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: const <Locale>[
|
||||
// the order here doesn't matter, except for the first one, which must
|
||||
// be en
|
||||
Locale("en"),
|
||||
Locale("el"),
|
||||
Locale("es"),
|
||||
Locale("fr"),
|
||||
Locale("ru"),
|
||||
Locale("de"),
|
||||
Locale("cs"),
|
||||
Locale("fi"),
|
||||
Locale("pl"),
|
||||
Locale("pt"),
|
||||
Locale.fromSubtags(languageCode: "zh", scriptCode: "Hans"),
|
||||
Locale.fromSubtags(languageCode: "zh", scriptCode: "Hant"),
|
||||
Locale("it"),
|
||||
Locale("nl"),
|
||||
],
|
||||
builder: (context, child) {
|
||||
MyApp._globalContext = context;
|
||||
return child!;
|
||||
},
|
||||
debugShowCheckedModeBanner: false,
|
||||
scrollBehavior: const _MyScrollBehavior(),
|
||||
);
|
||||
},
|
||||
debugShowCheckedModeBanner: false,
|
||||
scrollBehavior: const _MyScrollBehavior(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ class _Bloc extends Bloc<_Event, _State> {
|
|||
super(_State(
|
||||
isFollowSystemTheme: c.pref.isFollowSystemThemeOr(false),
|
||||
isUseBlackInDarkTheme: c.pref.isUseBlackInDarkThemeOr(false),
|
||||
seedColor: getSeedColor(),
|
||||
seedColor: getSeedColor()?.value,
|
||||
)) {
|
||||
on<_SetFollowSystemTheme>(_onSetFollowSystemTheme);
|
||||
on<_SetUseBlackInDarkTheme>(_onSetUseBlackInDarkTheme);
|
||||
|
@ -27,6 +27,7 @@ class _Bloc extends Bloc<_Event, _State> {
|
|||
|
||||
Future<void> _onSetFollowSystemTheme(
|
||||
_SetFollowSystemTheme ev, Emitter<_State> emit) async {
|
||||
_log.info(ev);
|
||||
final oldValue = state.isFollowSystemTheme;
|
||||
emit(state.copyWith(isFollowSystemTheme: ev.value));
|
||||
if (await _c.pref.setFollowSystemTheme(ev.value)) {
|
||||
|
@ -40,6 +41,7 @@ class _Bloc extends Bloc<_Event, _State> {
|
|||
|
||||
Future<void> _onSetUseBlackInDarkTheme(
|
||||
_SetUseBlackInDarkTheme ev, Emitter<_State> emit) async {
|
||||
_log.info(ev);
|
||||
final oldValue = state.isUseBlackInDarkTheme;
|
||||
emit(state.copyWith(isUseBlackInDarkTheme: ev.value));
|
||||
if (await _c.pref.setUseBlackInDarkTheme(ev.value)) {
|
||||
|
@ -54,9 +56,10 @@ class _Bloc extends Bloc<_Event, _State> {
|
|||
}
|
||||
|
||||
Future<void> _onSetSeedColor(_SetSeedColor ev, Emitter<_State> emit) async {
|
||||
_log.info(ev);
|
||||
final oldValue = state.seedColor;
|
||||
emit(state.copyWith(seedColor: ev.value));
|
||||
if (await _c.pref.setSeedColor(ev.value.withAlpha(0xFF).value)) {
|
||||
emit(state.copyWith(seedColor: ev.value?.value));
|
||||
if (await _c.pref.setSeedColor(ev.value?.withAlpha(0xFF).value)) {
|
||||
KiwiContainer().resolve<EventBus>().fire(ThemeChangedEvent());
|
||||
} else {
|
||||
_log.severe("[_onSetSeedColor] Failed writing pref");
|
||||
|
|
|
@ -14,7 +14,8 @@ class _State {
|
|||
|
||||
final bool isFollowSystemTheme;
|
||||
final bool isUseBlackInDarkTheme;
|
||||
final Color seedColor;
|
||||
// workaround analyzer bug where Color type can't be recognized
|
||||
final int? seedColor;
|
||||
}
|
||||
|
||||
abstract class _Event {
|
||||
|
@ -49,5 +50,5 @@ class _SetSeedColor extends _Event {
|
|||
@override
|
||||
String toString() => _$toString();
|
||||
|
||||
final Color value;
|
||||
final Color? value;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import 'package:nc_photos/event/event.dart';
|
|||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/mobile/android/android_info.dart';
|
||||
import 'package:nc_photos/platform/k.dart' as platform_k;
|
||||
import 'package:nc_photos/session_storage.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:np_codegen/np_codegen.dart';
|
||||
|
@ -23,6 +24,8 @@ part 'theme/bloc.dart';
|
|||
part 'theme/state_event.dart';
|
||||
part 'theme_settings.g.dart';
|
||||
|
||||
typedef _BlocBuilder = BlocBuilder<_Bloc, _State>;
|
||||
|
||||
class ThemeSettings extends StatelessWidget {
|
||||
const ThemeSettings({super.key});
|
||||
|
||||
|
@ -47,7 +50,7 @@ class _WrappedThemeSettingsState extends State<_WrappedThemeSettings> {
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_errorSubscription = context.read<_Bloc>().errorStream().listen((_) {
|
||||
_errorSubscription = _bloc.errorStream().listen((_) {
|
||||
SnackBarManager().showSnackBar(SnackBar(
|
||||
content: Text(L10n.global().writePreferenceFailureNotification),
|
||||
duration: k.snackBarDurationNormal,
|
||||
|
@ -80,25 +83,10 @@ class _WrappedThemeSettingsState extends State<_WrappedThemeSettings> {
|
|||
SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
BlocBuilder<_Bloc, _State>(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.seedColor != current.seedColor,
|
||||
builder: (context, state) {
|
||||
return ListTile(
|
||||
title: Text(L10n.global().settingsSeedColorTitle),
|
||||
subtitle: Text(L10n.global().settingsSeedColorDescription),
|
||||
trailing: Icon(
|
||||
Icons.circle,
|
||||
size: 32,
|
||||
color: state.seedColor,
|
||||
),
|
||||
onTap: () => _onSeedColorPressed(context),
|
||||
);
|
||||
},
|
||||
),
|
||||
const _SeedColorOption(),
|
||||
if (platform_k.isAndroid &&
|
||||
AndroidInfo().sdkInt >= AndroidVersion.Q)
|
||||
BlocBuilder<_Bloc, _State>(
|
||||
_BlocBuilder(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.isFollowSystemTheme !=
|
||||
current.isFollowSystemTheme,
|
||||
|
@ -107,12 +95,12 @@ class _WrappedThemeSettingsState extends State<_WrappedThemeSettings> {
|
|||
title: Text(L10n.global().settingsFollowSystemThemeTitle),
|
||||
value: state.isFollowSystemTheme,
|
||||
onChanged: (value) {
|
||||
context.read<_Bloc>().add(_SetFollowSystemTheme(value));
|
||||
_bloc.add(_SetFollowSystemTheme(value));
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
BlocBuilder<_Bloc, _State>(
|
||||
_BlocBuilder(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.isUseBlackInDarkTheme !=
|
||||
current.isUseBlackInDarkTheme,
|
||||
|
@ -126,7 +114,7 @@ class _WrappedThemeSettingsState extends State<_WrappedThemeSettings> {
|
|||
.settingsUseBlackInDarkThemeFalseDescription),
|
||||
value: state.isUseBlackInDarkTheme,
|
||||
onChanged: (value) {
|
||||
context.read<_Bloc>().add(
|
||||
_bloc.add(
|
||||
_SetUseBlackInDarkTheme(value, Theme.of(context)));
|
||||
},
|
||||
);
|
||||
|
@ -139,20 +127,63 @@ class _WrappedThemeSettingsState extends State<_WrappedThemeSettings> {
|
|||
);
|
||||
}
|
||||
|
||||
late final _bloc = context.read<_Bloc>();
|
||||
late final StreamSubscription _errorSubscription;
|
||||
}
|
||||
|
||||
class _SeedColorOption extends StatelessWidget {
|
||||
const _SeedColorOption();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _BlocBuilder(
|
||||
buildWhen: (previous, current) => previous.seedColor != current.seedColor,
|
||||
builder: (context, state) {
|
||||
if (SessionStorage().isSupportDynamicColor) {
|
||||
return ListTile(
|
||||
title: Text(L10n.global().settingsSeedColorTitle),
|
||||
subtitle: Text(state.seedColor == null
|
||||
? L10n.global().settingsSeedColorSystemColorDescription
|
||||
: L10n.global().settingsSeedColorDescription),
|
||||
trailing: state.seedColor == null
|
||||
? null
|
||||
: Icon(
|
||||
Icons.circle,
|
||||
size: 32,
|
||||
color: Color(state.seedColor!),
|
||||
),
|
||||
onTap: () => _onSeedColorPressed(context),
|
||||
);
|
||||
} else {
|
||||
return ListTile(
|
||||
title: Text(L10n.global().settingsSeedColorTitle),
|
||||
subtitle: Text(L10n.global().settingsSeedColorDescription),
|
||||
trailing: Icon(
|
||||
Icons.circle,
|
||||
size: 32,
|
||||
color: Color(state.seedColor ?? defaultSeedColor),
|
||||
),
|
||||
onTap: () => _onSeedColorPressed(context),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onSeedColorPressed(BuildContext context) async {
|
||||
final result = await showDialog<Color>(
|
||||
final result = await showDialog<int>(
|
||||
context: context,
|
||||
builder: (context) => const _SeedColorPicker(),
|
||||
);
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
if (mounted) {
|
||||
context.read<_Bloc>().add(_SetSeedColor(result));
|
||||
if (context.mounted) {
|
||||
context
|
||||
.read<_Bloc>()
|
||||
.add(_SetSeedColor(result == -1 ? null : Color(result)));
|
||||
}
|
||||
}
|
||||
|
||||
late final StreamSubscription _errorSubscription;
|
||||
}
|
||||
|
||||
class _SeedColorPicker extends StatefulWidget {
|
||||
|
@ -180,15 +211,24 @@ class _SeedColorPickerState extends State<_SeedColorPicker> {
|
|||
]
|
||||
.map((c) => _SeedColorPickerItem(
|
||||
seedColor: c,
|
||||
onSelected: () => _onItemSelected(context, c),
|
||||
onSelected: () => _onItemSelected(context, c?.value),
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
actions: SessionStorage().isSupportDynamicColor
|
||||
? [
|
||||
TextButton(
|
||||
onPressed: () => _onItemSelected(context, -1),
|
||||
child: Text(L10n.global()
|
||||
.settingsSeedColorPickerSystemColorButtonLabel),
|
||||
),
|
||||
]
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onItemSelected(BuildContext context, Color? seedColor) async {
|
||||
Future<void> _onItemSelected(BuildContext context, int? seedColor) async {
|
||||
if (seedColor != null) {
|
||||
Navigator.of(context).pop(seedColor);
|
||||
return;
|
||||
|
@ -198,10 +238,10 @@ class _SeedColorPickerState extends State<_SeedColorPicker> {
|
|||
});
|
||||
final color = await showDialog<Color>(
|
||||
context: context,
|
||||
builder: (context) => const _SeedColorCustomPicker(),
|
||||
builder: (_) => const _SeedColorCustomPicker(),
|
||||
barrierColor: Colors.transparent,
|
||||
);
|
||||
Navigator.of(context).pop(color);
|
||||
Navigator.of(context).pop(color?.value);
|
||||
}
|
||||
|
||||
var _isVisible = true;
|
||||
|
@ -240,7 +280,7 @@ class _SeedColorCustomPickerState extends State<_SeedColorCustomPicker> {
|
|||
);
|
||||
}
|
||||
|
||||
late Color _customColor = getSeedColor();
|
||||
late Color _customColor = getSeedColor() ?? const Color(defaultSeedColor);
|
||||
}
|
||||
|
||||
class _SeedColorPickerItem extends StatelessWidget {
|
||||
|
|
|
@ -14,9 +14,7 @@ part of 'theme_settings.dart';
|
|||
|
||||
abstract class $_StateCopyWithWorker {
|
||||
_State call(
|
||||
{bool? isFollowSystemTheme,
|
||||
bool? isUseBlackInDarkTheme,
|
||||
Color? seedColor});
|
||||
{bool? isFollowSystemTheme, bool? isUseBlackInDarkTheme, int? seedColor});
|
||||
}
|
||||
|
||||
class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
|
||||
|
@ -26,13 +24,14 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
|
|||
_State call(
|
||||
{dynamic isFollowSystemTheme,
|
||||
dynamic isUseBlackInDarkTheme,
|
||||
dynamic seedColor}) {
|
||||
dynamic seedColor = copyWithNull}) {
|
||||
return _State(
|
||||
isFollowSystemTheme:
|
||||
isFollowSystemTheme as bool? ?? that.isFollowSystemTheme,
|
||||
isUseBlackInDarkTheme:
|
||||
isUseBlackInDarkTheme as bool? ?? that.isUseBlackInDarkTheme,
|
||||
seedColor: seedColor as Color? ?? that.seedColor);
|
||||
seedColor:
|
||||
seedColor == copyWithNull ? that.seedColor : seedColor as int?);
|
||||
}
|
||||
|
||||
final _State that;
|
||||
|
|
|
@ -413,6 +413,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.8.0"
|
||||
dynamic_color:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dynamic_color
|
||||
sha256: de4798a7069121aee12d5895315680258415de9b00e717723a1bd73d58f0126d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.6.6"
|
||||
equatable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1779,4 +1787,4 @@ packages:
|
|||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=2.19.0 <3.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
flutter: ">=3.4.0-17.0.pre"
|
||||
|
|
|
@ -53,6 +53,7 @@ dependencies:
|
|||
url: https://gitlab.com/nc-photos/flutter-draggable-scrollbar
|
||||
ref: v0.1.0-nc-photos-6
|
||||
drift: 2.8.0
|
||||
dynamic_color: ^1.6.6
|
||||
equatable: ^2.0.5
|
||||
event_bus: ^2.0.0
|
||||
exifdart:
|
||||
|
|
Loading…
Reference in a new issue