Refactor: move theme prefs to PrefController

This commit is contained in:
Ming Ming 2023-08-20 00:47:56 +08:00
parent 9d7d97b924
commit f50d7fbf26
26 changed files with 528 additions and 216 deletions

View file

@ -1,3 +1,5 @@
import 'package:flutter_bloc/flutter_bloc.dart';
mixin BlocLogger { mixin BlocLogger {
String? get tag => null; String? get tag => null;
@ -11,3 +13,15 @@ class StateMessage {
final String value; final String value;
} }
extension EmitterExtension<State> on Emitter<State> {
Future<void> forEachIgnoreError<T>(
Stream<T> stream, {
required State Function(T data) onData,
}) =>
onEach<T>(
stream,
onData: (data) => call(onData(data)),
onError: (_, __) {},
);
}

View file

@ -1,3 +1,6 @@
// ignore_for_file: deprecated_member_use_from_same_package
import 'package:flutter/material.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/pref.dart'; import 'package:nc_photos/entity/pref.dart';
@ -141,6 +144,41 @@ class PrefController {
value: value, value: value,
); );
ValueStream<bool> get isDarkTheme => _isDarkThemeController.stream;
Future<void> setDarkTheme(bool value) => _set<bool>(
controller: _isDarkThemeController,
setter: (pref, value) => pref.setDarkTheme(value),
value: value,
);
ValueStream<bool> get isFollowSystemTheme =>
_isFollowSystemThemeController.stream;
Future<void> setFollowSystemTheme(bool value) => _set<bool>(
controller: _isFollowSystemThemeController,
setter: (pref, value) => pref.setFollowSystemTheme(value),
value: value,
);
ValueStream<bool> get isUseBlackInDarkTheme =>
_isUseBlackInDarkThemeController.stream;
Future<void> setUseBlackInDarkTheme(bool value) => _set<bool>(
controller: _isUseBlackInDarkThemeController,
setter: (pref, value) => pref.setUseBlackInDarkTheme(value),
value: value,
);
ValueStream<Color?> get seedColor => _seedColorController.stream;
Future<void> setSeedColor(Color? value) => _setOrRemove<Color>(
controller: _seedColorController,
setter: (pref, value) => pref.setSeedColor(value.withAlpha(0xFF).value),
remover: (pref) => pref.setSeedColor(null),
value: value,
);
Future<void> _set<T>({ Future<void> _set<T>({
required BehaviorSubject<T> controller, required BehaviorSubject<T> controller,
required Future<bool> Function(Pref pref, T value) setter, required Future<bool> Function(Pref pref, T value) setter,
@ -160,6 +198,33 @@ class PrefController {
} }
} }
Future<void> _setOrRemove<T>({
required BehaviorSubject<T?> controller,
required Future<bool> Function(Pref pref, T value) setter,
required Future<bool> Function(Pref pref) remover,
required T? value,
T? defaultValue,
}) async {
final backup = controller.value;
controller.add(value ?? defaultValue);
try {
if (value == null) {
if (!await remover(_c.pref)) {
throw StateError("Unknown error");
}
} else {
if (!await setter(_c.pref, value)) {
throw StateError("Unknown error");
}
}
} catch (e, stackTrace) {
_log.severe("[_set] Failed setting preference", e, stackTrace);
controller
..addError(e, stackTrace)
..add(backup);
}
}
static language_util.AppLanguage _langIdToAppLanguage(int langId) { static language_util.AppLanguage _langIdToAppLanguage(int langId) {
try { try {
return language_util.supportedLanguages[langId]!; return language_util.supportedLanguages[langId]!;
@ -168,6 +233,8 @@ class PrefController {
} }
} }
static const _seedColorDef = 0xFF2196F3;
final DiContainer _c; final DiContainer _c;
late final _languageController = late final _languageController =
BehaviorSubject.seeded(_langIdToAppLanguage(_c.pref.getLanguageOr(0))); BehaviorSubject.seeded(_langIdToAppLanguage(_c.pref.getLanguageOr(0)));
@ -197,4 +264,12 @@ class PrefController {
BehaviorSubject.seeded(_c.pref.isSaveEditResultToServerOr(true)); BehaviorSubject.seeded(_c.pref.isSaveEditResultToServerOr(true));
late final _enhanceMaxSizeController = BehaviorSubject.seeded( late final _enhanceMaxSizeController = BehaviorSubject.seeded(
SizeInt(_c.pref.getEnhanceMaxWidthOr(), _c.pref.getEnhanceMaxHeightOr())); SizeInt(_c.pref.getEnhanceMaxWidthOr(), _c.pref.getEnhanceMaxHeightOr()));
late final _isDarkThemeController =
BehaviorSubject.seeded(_c.pref.isDarkThemeOr(false));
late final _isFollowSystemThemeController =
BehaviorSubject.seeded(_c.pref.isFollowSystemThemeOr(false));
late final _isUseBlackInDarkThemeController =
BehaviorSubject.seeded(_c.pref.isUseBlackInDarkThemeOr(false));
late final _seedColorController = BehaviorSubject<Color?>.seeded(
Color(_c.pref.getSeedColorOr(_seedColorDef)));
} }

View file

@ -101,21 +101,30 @@ extension PrefExtension on Pref {
Future<bool> setLastVersion(int value) => _set<int>( Future<bool> setLastVersion(int value) => _set<int>(
PrefKey.lastVersion, value, (key, value) => provider.setInt(key, value)); PrefKey.lastVersion, value, (key, value) => provider.setInt(key, value));
@Deprecated("Use PrefController")
bool? isDarkTheme() => provider.getBool(PrefKey.darkTheme); bool? isDarkTheme() => provider.getBool(PrefKey.darkTheme);
@Deprecated("Use PrefController")
bool isDarkThemeOr(bool def) => isDarkTheme() ?? def; bool isDarkThemeOr(bool def) => isDarkTheme() ?? def;
@Deprecated("Use PrefController")
Future<bool> setDarkTheme(bool value) => _set<bool>( Future<bool> setDarkTheme(bool value) => _set<bool>(
PrefKey.darkTheme, value, (key, value) => provider.setBool(key, value)); PrefKey.darkTheme, value, (key, value) => provider.setBool(key, value));
@Deprecated("Use PrefController")
bool? isFollowSystemTheme() => provider.getBool(PrefKey.followSystemTheme); bool? isFollowSystemTheme() => provider.getBool(PrefKey.followSystemTheme);
@Deprecated("Use PrefController")
bool isFollowSystemThemeOr(bool def) => isFollowSystemTheme() ?? def; bool isFollowSystemThemeOr(bool def) => isFollowSystemTheme() ?? def;
@Deprecated("Use PrefController")
Future<bool> setFollowSystemTheme(bool value) => _set<bool>( Future<bool> setFollowSystemTheme(bool value) => _set<bool>(
PrefKey.followSystemTheme, PrefKey.followSystemTheme,
value, value,
(key, value) => provider.setBool(key, value)); (key, value) => provider.setBool(key, value));
@Deprecated("Use PrefController")
bool? isUseBlackInDarkTheme() => bool? isUseBlackInDarkTheme() =>
provider.getBool(PrefKey.useBlackInDarkTheme); provider.getBool(PrefKey.useBlackInDarkTheme);
@Deprecated("Use PrefController")
bool isUseBlackInDarkThemeOr(bool def) => isUseBlackInDarkTheme() ?? def; bool isUseBlackInDarkThemeOr(bool def) => isUseBlackInDarkTheme() ?? def;
@Deprecated("Use PrefController")
Future<bool> setUseBlackInDarkTheme(bool value) => _set<bool>( Future<bool> setUseBlackInDarkTheme(bool value) => _set<bool>(
PrefKey.useBlackInDarkTheme, PrefKey.useBlackInDarkTheme,
value, value,
@ -249,8 +258,11 @@ extension PrefExtension on Pref {
value, value,
(key, value) => provider.setBool(key, value)); (key, value) => provider.setBool(key, value));
@Deprecated("Use PrefController")
int? getSeedColor() => provider.getInt(PrefKey.seedColor); int? getSeedColor() => provider.getInt(PrefKey.seedColor);
@Deprecated("Use PrefController")
int getSeedColorOr(int def) => getSeedColor() ?? def; int getSeedColorOr(int def) => getSeedColor() ?? def;
@Deprecated("Use PrefController")
Future<bool> setSeedColor(int? value) { Future<bool> setSeedColor(int? value) {
if (value == null) { if (value == null) {
return _remove(PrefKey.seedColor); return _remove(PrefKey.seedColor);

View file

@ -117,8 +117,6 @@ class FavoriteResyncedEvent {
final Account account; final Account account;
} }
class ThemeChangedEvent {}
enum MetadataTaskState { enum MetadataTaskState {
/// No work is being done /// No work is being done
idle, idle,

View file

@ -1,12 +1,12 @@
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:nc_photos/entity/pref.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:nc_photos/object_extension.dart'; import 'package:nc_photos/controller/pref_controller.dart';
import 'package:nc_photos/theme/dimension.dart'; import 'package:nc_photos/theme/dimension.dart';
import 'package:nc_photos/theme/material3.dart'; import 'package:nc_photos/theme/material3.dart';
const defaultSeedColor = 0xFF2196F3; const defaultSeedColor = Color(0xFF2196F3);
extension ThemeExtension on ThemeData { extension ThemeExtension on ThemeData {
double get widthLimitedContentMaxWidth => 550.0; double get widthLimitedContentMaxWidth => 550.0;
@ -88,20 +88,20 @@ class DarkModeSwitchTheme extends StatelessWidget {
final Widget child; final Widget child;
} }
ThemeData buildTheme(Brightness brightness) { ThemeData buildTheme(BuildContext context, Brightness brightness) {
return (brightness == Brightness.light) return (brightness == Brightness.light)
? buildLightTheme() ? buildLightTheme(context)
: buildDarkTheme(); : buildDarkTheme(context);
} }
ThemeData buildLightTheme([ColorScheme? dynamicScheme]) { ThemeData buildLightTheme(BuildContext context, [ColorScheme? dynamicScheme]) {
final colorScheme = _getColorScheme(dynamicScheme, Brightness.light); final colorScheme = _getColorScheme(context, dynamicScheme, Brightness.light);
return _applyColorScheme(colorScheme); return _applyColorScheme(colorScheme);
} }
ThemeData buildDarkTheme([ColorScheme? dynamicScheme]) { ThemeData buildDarkTheme(BuildContext context, [ColorScheme? dynamicScheme]) {
final colorScheme = _getColorScheme(dynamicScheme, Brightness.dark); final colorScheme = _getColorScheme(context, dynamicScheme, Brightness.dark);
if (Pref().isUseBlackInDarkThemeOr(false)) { if (context.read<PrefController>().isUseBlackInDarkTheme.value) {
return _applyColorScheme(colorScheme.copyWith( return _applyColorScheme(colorScheme.copyWith(
background: Colors.black, background: Colors.black,
surface: Colors.grey[900], surface: Colors.grey[900],
@ -111,12 +111,13 @@ ThemeData buildDarkTheme([ColorScheme? dynamicScheme]) {
} }
} }
Color? getSeedColor() { Color? getSeedColor(BuildContext context) {
return Pref().getSeedColor()?.run((c) => Color(c).withAlpha(0xFF)); return context.read<PrefController>().seedColor.value;
} }
ColorScheme _getColorScheme(ColorScheme? dynamicScheme, Brightness brightness) { ColorScheme _getColorScheme(
var seedColor = Pref().getSeedColor(); BuildContext context, ColorScheme? dynamicScheme, Brightness brightness) {
var seedColor = getSeedColor(context);
if (seedColor == null) { if (seedColor == null) {
if (dynamicScheme != null) { if (dynamicScheme != null) {
return dynamicScheme; return dynamicScheme;
@ -125,7 +126,7 @@ ColorScheme _getColorScheme(ColorScheme? dynamicScheme, Brightness brightness) {
} }
} }
return ColorScheme.fromSeed( return ColorScheme.fromSeed(
seedColor: Color(seedColor), seedColor: seedColor,
brightness: brightness, brightness: brightness,
); );
} }

View file

@ -4,7 +4,6 @@ import 'dart:math';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:clock/clock.dart'; import 'package:clock/clock.dart';
import 'package:copy_with/copy_with.dart'; import 'package:copy_with/copy_with.dart';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:kiwi/kiwi.dart'; import 'package:kiwi/kiwi.dart';
@ -15,15 +14,16 @@ import 'package:nc_photos/api/api_util.dart' as api_util;
import 'package:nc_photos/app_localizations.dart'; import 'package:nc_photos/app_localizations.dart';
import 'package:nc_photos/bloc_util.dart'; import 'package:nc_photos/bloc_util.dart';
import 'package:nc_photos/controller/account_controller.dart'; import 'package:nc_photos/controller/account_controller.dart';
import 'package:nc_photos/controller/pref_controller.dart';
import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/pref.dart'; import 'package:nc_photos/entity/pref.dart';
import 'package:nc_photos/entity/server_status.dart'; import 'package:nc_photos/entity/server_status.dart';
import 'package:nc_photos/entity/sqlite/database.dart' as sql; import 'package:nc_photos/entity/sqlite/database.dart' as sql;
import 'package:nc_photos/event/event.dart';
import 'package:nc_photos/exception_event.dart'; import 'package:nc_photos/exception_event.dart';
import 'package:nc_photos/exception_util.dart' as exception_util; import 'package:nc_photos/exception_util.dart' as exception_util;
import 'package:nc_photos/help_utils.dart' as help_util; import 'package:nc_photos/help_utils.dart' as help_util;
import 'package:nc_photos/k.dart' as k; import 'package:nc_photos/k.dart' as k;
import 'package:nc_photos/stream_util.dart';
import 'package:nc_photos/theme.dart'; import 'package:nc_photos/theme.dart';
import 'package:nc_photos/toast.dart'; import 'package:nc_photos/toast.dart';
import 'package:nc_photos/url_launcher_util.dart'; import 'package:nc_photos/url_launcher_util.dart';
@ -50,6 +50,7 @@ class AccountPickerDialog extends StatelessWidget {
create: (context) => _Bloc( create: (context) => _Bloc(
container: KiwiContainer().resolve(), container: KiwiContainer().resolve(),
accountController: context.read(), accountController: context.read(),
prefController: context.read(),
), ),
child: const _WrappedAccountPickerDialog(), child: const _WrappedAccountPickerDialog(),
); );
@ -112,13 +113,27 @@ class _WrappedAccountPickerDialog extends StatelessWidget {
style: Theme.of(context).textTheme.titleLarge, style: Theme.of(context).textTheme.titleLarge,
), ),
), ),
if (!Pref().isFollowSystemThemeOr(false)) ValueStreamBuilder<bool>(
Align( stream: context
alignment: AlignmentDirectional.centerEnd, .read<PrefController>()
child: _DarkModeSwitch( .isFollowSystemTheme,
onChanged: _onDarkModeChanged, builder: (_, isFollowSystemTheme) {
), if (!isFollowSystemTheme.requireData) {
), return Align(
alignment: AlignmentDirectional.centerEnd,
child: _DarkModeSwitch(
onChanged: (value) {
context
.read<_Bloc>()
.add(_SetDarkTheme(value));
},
),
);
} else {
return const SizedBox.shrink();
}
},
),
], ],
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
@ -192,12 +207,6 @@ class _WrappedAccountPickerDialog extends StatelessWidget {
), ),
); );
} }
void _onDarkModeChanged(bool value) {
Pref().setDarkTheme(value).then((_) {
KiwiContainer().resolve<EventBus>().fire(ThemeChangedEvent());
});
}
} }
class _DarkModeSwitch extends StatelessWidget { class _DarkModeSwitch extends StatelessWidget {

View file

@ -89,6 +89,13 @@ extension _$_DeleteAccountToString on _DeleteAccount {
} }
} }
extension _$_SetDarkThemeToString on _SetDarkTheme {
String _$toString() {
// ignore: unnecessary_string_interpolations
return "_SetDarkTheme {value: $value}";
}
}
extension _$_SetErrorToString on _SetError { extension _$_SetErrorToString on _SetError {
String _$toString() { String _$toString() {
// ignore: unnecessary_string_interpolations // ignore: unnecessary_string_interpolations

View file

@ -5,6 +5,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc({ _Bloc({
required DiContainer container, required DiContainer container,
required this.accountController, required this.accountController,
required this.prefController,
}) : _c = container, }) : _c = container,
super(_State.init( super(_State.init(
accounts: container.pref.getAccounts3Or([]), accounts: container.pref.getAccounts3Or([]),
@ -12,6 +13,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
on<_ToggleDropdown>(_onToggleDropdown); on<_ToggleDropdown>(_onToggleDropdown);
on<_SwitchAccount>(_onSwitchAccount); on<_SwitchAccount>(_onSwitchAccount);
on<_DeleteAccount>(_onDeleteAccount); on<_DeleteAccount>(_onDeleteAccount);
on<_SetDarkTheme>(_onSetDarkTheme);
on<_SetError>(_onSetError); on<_SetError>(_onSetError);
} }
@ -86,6 +88,11 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
} }
} }
void _onSetDarkTheme(_SetDarkTheme ev, Emitter<_State> emit) {
_log.info(ev);
prefController.setDarkTheme(ev.value);
}
void _onSetError(_SetError ev, Emitter<_State> emit) { void _onSetError(_SetError ev, Emitter<_State> emit) {
_log.info(ev); _log.info(ev);
emit(state.copyWith(error: ExceptionEvent(ev.error, ev.stackTrace))); emit(state.copyWith(error: ExceptionEvent(ev.error, ev.stackTrace)));
@ -104,6 +111,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
final DiContainer _c; final DiContainer _c;
final AccountController accountController; final AccountController accountController;
final PrefController prefController;
late final Account activeAccount = accountController.account; late final Account activeAccount = accountController.account;
final _prefLock = Mutex(); final _prefLock = Mutex();

View file

@ -60,6 +60,16 @@ class _DeleteAccount implements _Event {
final Account account; final Account account;
} }
@toString
class _SetDarkTheme implements _Event {
const _SetDarkTheme(this.value);
@override
String toString() => _$toString();
final bool value;
}
@toString @toString
class _SetError implements _Event { class _SetError implements _Event {
const _SetError(this.error, [this.stackTrace]); const _SetError(this.error, [this.stackTrace]);

View file

@ -73,7 +73,7 @@ class _ConnectState extends State<Connect> {
@override @override
build(BuildContext context) { build(BuildContext context) {
return Theme( return Theme(
data: buildDarkTheme().copyWith( data: buildDarkTheme(context).copyWith(
scaffoldBackgroundColor: Theme.of(context).nextcloudBlue, scaffoldBackgroundColor: Theme.of(context).nextcloudBlue,
progressIndicatorTheme: const ProgressIndicatorThemeData( progressIndicatorTheme: const ProgressIndicatorThemeData(
color: Colors.white, color: Colors.white,

View file

@ -87,7 +87,7 @@ class _ImageEditorState extends State<ImageEditor> {
@override @override
build(BuildContext context) => Theme( build(BuildContext context) => Theme(
data: buildDarkTheme(), data: buildDarkTheme(context),
child: Scaffold( child: Scaffold(
body: Builder( body: Builder(
builder: _buildContent, builder: _buildContent,

View file

@ -88,7 +88,7 @@ class _ImageEnhancerState extends State<ImageEnhancer> {
@override @override
build(BuildContext context) => Theme( build(BuildContext context) => Theme(
data: buildDarkTheme(), data: buildDarkTheme(context),
child: Scaffold( child: Scaffold(
body: Builder( body: Builder(
builder: _buildContent, builder: _buildContent,

View file

@ -53,7 +53,7 @@ class _LocalFileViewerState extends State<LocalFileViewer> {
@override @override
build(BuildContext context) { build(BuildContext context) {
return Theme( return Theme(
data: buildDarkTheme(), data: buildDarkTheme(context),
child: Scaffold( child: Scaffold(
body: Builder( body: Builder(
builder: _buildContent, builder: _buildContent,

View file

@ -1,3 +1,4 @@
import 'package:copy_with/copy_with.dart';
import 'package:dynamic_color/dynamic_color.dart'; import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -6,18 +7,16 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:kiwi/kiwi.dart'; import 'package:kiwi/kiwi.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:nc_photos/bloc_util.dart';
import 'package:nc_photos/controller/account_controller.dart'; import 'package:nc_photos/controller/account_controller.dart';
import 'package:nc_photos/controller/pref_controller.dart'; import 'package:nc_photos/controller/pref_controller.dart';
import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/pref.dart';
import 'package:nc_photos/event/event.dart';
import 'package:nc_photos/language_util.dart' as language_util; import 'package:nc_photos/language_util.dart' as language_util;
import 'package:nc_photos/legacy/connect.dart' as legacy; import 'package:nc_photos/legacy/connect.dart' as legacy;
import 'package:nc_photos/legacy/sign_in.dart' as legacy; import 'package:nc_photos/legacy/sign_in.dart' as legacy;
import 'package:nc_photos/navigation_manager.dart'; import 'package:nc_photos/navigation_manager.dart';
import 'package:nc_photos/session_storage.dart'; import 'package:nc_photos/session_storage.dart';
import 'package:nc_photos/snack_bar_manager.dart'; import 'package:nc_photos/snack_bar_manager.dart';
import 'package:nc_photos/stream_util.dart';
import 'package:nc_photos/theme.dart'; import 'package:nc_photos/theme.dart';
import 'package:nc_photos/widget/album_dir_picker.dart'; import 'package:nc_photos/widget/album_dir_picker.dart';
import 'package:nc_photos/widget/album_importer.dart'; import 'package:nc_photos/widget/album_importer.dart';
@ -51,8 +50,15 @@ import 'package:nc_photos/widget/trashbin_browser.dart';
import 'package:nc_photos/widget/trashbin_viewer.dart'; import 'package:nc_photos/widget/trashbin_viewer.dart';
import 'package:nc_photos/widget/viewer.dart'; import 'package:nc_photos/widget/viewer.dart';
import 'package:np_codegen/np_codegen.dart'; import 'package:np_codegen/np_codegen.dart';
import 'package:to_string/to_string.dart';
part 'my_app.g.dart'; part 'my_app.g.dart';
part 'my_app/bloc.dart';
part 'my_app/state_event.dart';
typedef _BlocBuilder = BlocBuilder<_Bloc, _State>;
// typedef _BlocListener = BlocListener<_Bloc, _State>;
// typedef _BlocSelector<T> = BlocSelector<_Bloc, _State, T>;
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
const MyApp({super.key}); const MyApp({super.key});
@ -69,7 +75,12 @@ class MyApp extends StatelessWidget {
create: (_) => PrefController(_c), create: (_) => PrefController(_c),
), ),
], ],
child: const _WrappedApp(), child: BlocProvider(
create: (context) => _Bloc(
prefController: context.read(),
),
child: const _WrappedApp(),
),
); );
} }
@ -96,43 +107,48 @@ class _WrappedAppState extends State<_WrappedApp>
super.initState(); super.initState();
SnackBarManager().registerHandler(this); SnackBarManager().registerHandler(this);
NavigationManager().setHandler(this); NavigationManager().setHandler(this);
_themeChangedListener =
AppEventListener<ThemeChangedEvent>(_onThemeChangedEvent)..begin(); _bloc.add(const _Init());
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ThemeMode themeMode; return _BlocBuilder(
if (Pref().isFollowSystemThemeOr(false)) { buildWhen: (previous, current) =>
themeMode = ThemeMode.system; previous.language != current.language ||
} else { previous.isDarkTheme != current.isDarkTheme ||
themeMode = previous.isFollowSystemTheme != current.isFollowSystemTheme ||
Pref().isDarkThemeOr(false) ? ThemeMode.dark : ThemeMode.light; previous.isUseBlackInDarkTheme != current.isUseBlackInDarkTheme ||
} previous.seedColor != current.seedColor,
final prefController = context.read<PrefController>(); builder: (context, state) => DynamicColorBuilder(
return ValueStreamBuilder<language_util.AppLanguage>(
stream: prefController.language,
builder: (context, snapshot) => DynamicColorBuilder(
builder: (lightDynamic, darkDynamic) { builder: (lightDynamic, darkDynamic) {
if (lightDynamic != null) { if (lightDynamic != null) {
SessionStorage().isSupportDynamicColor = true; SessionStorage().isSupportDynamicColor = true;
} }
final ThemeMode themeMode;
if (state.isFollowSystemTheme) {
themeMode = ThemeMode.system;
} else {
themeMode = state.isDarkTheme ? ThemeMode.dark : ThemeMode.light;
}
return MaterialApp( return MaterialApp(
onGenerateTitle: (context) => onGenerateTitle: (context) =>
AppLocalizations.of(context)!.appTitle, AppLocalizations.of(context)!.appTitle,
theme: buildLightTheme(lightDynamic), theme: buildLightTheme(context, lightDynamic),
darkTheme: buildDarkTheme(darkDynamic), darkTheme: buildDarkTheme(context, darkDynamic),
themeMode: themeMode, themeMode: themeMode,
initialRoute: Splash.routeName, initialRoute: Splash.routeName,
onGenerateRoute: _onGenerateRoute, onGenerateRoute: _onGenerateRoute,
navigatorObservers: <NavigatorObserver>[MyApp.routeObserver], navigatorObservers: [
MyApp.routeObserver,
],
navigatorKey: _navigatorKey, navigatorKey: _navigatorKey,
scaffoldMessengerKey: _scaffoldMessengerKey, scaffoldMessengerKey: _scaffoldMessengerKey,
locale: snapshot.requireData.locale, locale: state.language.locale,
localizationsDelegates: AppLocalizations.localizationsDelegates, localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: const <Locale>[ supportedLocales: const [
// the order here doesn't matter, except for the first one, which must // the order here doesn't matter, except for the first one, which
// be en // must be en
Locale("en"), Locale("en"),
Locale("el"), Locale("el"),
Locale("es"), Locale("es"),
@ -166,7 +182,6 @@ class _WrappedAppState extends State<_WrappedApp>
super.dispose(); super.dispose();
SnackBarManager().unregisterHandler(this); SnackBarManager().unregisterHandler(this);
NavigationManager().unsetHandler(this); NavigationManager().unsetHandler(this);
_themeChangedListener.end();
} }
@override @override
@ -227,10 +242,6 @@ class _WrappedAppState extends State<_WrappedApp>
return route; return route;
} }
void _onThemeChangedEvent(ThemeChangedEvent ev) {
setState(() {});
}
Route<dynamic>? _handleBasicRoute(RouteSettings settings) { Route<dynamic>? _handleBasicRoute(RouteSettings settings) {
for (final e in _getRouter().entries) { for (final e in _getRouter().entries) {
if (e.key == settings.name) { if (e.key == settings.name) {
@ -578,10 +589,9 @@ class _WrappedAppState extends State<_WrappedApp>
return null; return null;
} }
late final _bloc = context.read<_Bloc>();
final _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>(); final _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
final _navigatorKey = GlobalKey<NavigatorState>(); final _navigatorKey = GlobalKey<NavigatorState>();
late AppEventListener<ThemeChangedEvent> _themeChangedListener;
} }
class _ThemedMyApp extends StatelessWidget { class _ThemedMyApp extends StatelessWidget {

View file

@ -2,6 +2,54 @@
part of 'my_app.dart'; part of 'my_app.dart';
// **************************************************************************
// CopyWithLintRuleGenerator
// **************************************************************************
// ignore_for_file: library_private_types_in_public_api, duplicate_ignore
// **************************************************************************
// CopyWithGenerator
// **************************************************************************
abstract class $_StateCopyWithWorker {
_State call(
{language_util.AppLanguage? language,
bool? isDarkTheme,
bool? isFollowSystemTheme,
bool? isUseBlackInDarkTheme,
int? seedColor});
}
class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
_$_StateCopyWithWorkerImpl(this.that);
@override
_State call(
{dynamic language,
dynamic isDarkTheme,
dynamic isFollowSystemTheme,
dynamic isUseBlackInDarkTheme,
dynamic seedColor = copyWithNull}) {
return _State(
language: language as language_util.AppLanguage? ?? that.language,
isDarkTheme: isDarkTheme as bool? ?? that.isDarkTheme,
isFollowSystemTheme:
isFollowSystemTheme as bool? ?? that.isFollowSystemTheme,
isUseBlackInDarkTheme:
isUseBlackInDarkTheme as bool? ?? that.isUseBlackInDarkTheme,
seedColor:
seedColor == copyWithNull ? that.seedColor : seedColor as int?);
}
final _State that;
}
extension $_StateCopyWith on _State {
$_StateCopyWithWorker get copyWith => _$copyWith;
$_StateCopyWithWorker get _$copyWith => _$_StateCopyWithWorkerImpl(this);
}
// ************************************************************************** // **************************************************************************
// NpLogGenerator // NpLogGenerator
// ************************************************************************** // **************************************************************************
@ -12,3 +60,28 @@ extension _$_WrappedAppStateNpLog on _WrappedAppState {
static final log = Logger("widget.my_app._WrappedAppState"); static final log = Logger("widget.my_app._WrappedAppState");
} }
extension _$_BlocNpLog on _Bloc {
// ignore: unused_element
Logger get _log => log;
static final log = Logger("widget.my_app._Bloc");
}
// **************************************************************************
// ToStringGenerator
// **************************************************************************
extension _$_StateToString on _State {
String _$toString() {
// ignore: unnecessary_string_interpolations
return "_State {language: $language, isDarkTheme: $isDarkTheme, isFollowSystemTheme: $isFollowSystemTheme, isUseBlackInDarkTheme: $isUseBlackInDarkTheme, seedColor: $seedColor}";
}
}
extension _$_InitToString on _Init {
String _$toString() {
// ignore: unnecessary_string_interpolations
return "_Init {}";
}
}

View file

@ -0,0 +1,47 @@
part of '../my_app.dart';
@npLog
class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc({
required this.prefController,
}) : super(_State(
language: prefController.language.value,
isDarkTheme: prefController.isDarkTheme.value,
isFollowSystemTheme: prefController.isFollowSystemTheme.value,
isUseBlackInDarkTheme: prefController.isUseBlackInDarkTheme.value,
seedColor: prefController.seedColor.value?.value,
)) {
on<_Init>(_onInit);
}
@override
String get tag => _log.fullName;
Future<void> _onInit(_Init ev, Emitter<_State> emit) async {
_log.info(ev);
await Future.wait([
emit.forEachIgnoreError<language_util.AppLanguage>(
prefController.language,
onData: (data) => state.copyWith(language: data),
),
emit.forEachIgnoreError<bool>(
prefController.isDarkTheme,
onData: (data) => state.copyWith(isDarkTheme: data),
),
emit.forEachIgnoreError<bool>(
prefController.isFollowSystemTheme,
onData: (data) => state.copyWith(isFollowSystemTheme: data),
),
emit.forEachIgnoreError<bool>(
prefController.isUseBlackInDarkTheme,
onData: (data) => state.copyWith(isUseBlackInDarkTheme: data),
),
emit.forEachIgnoreError<Color?>(
prefController.seedColor,
onData: (data) => state.copyWith(seedColor: data?.value),
),
]);
}
final PrefController prefController;
}

View file

@ -0,0 +1,32 @@
part of '../my_app.dart';
@genCopyWith
@toString
class _State {
const _State({
required this.language,
required this.isDarkTheme,
required this.isFollowSystemTheme,
required this.isUseBlackInDarkTheme,
required this.seedColor,
});
@override
String toString() => _$toString();
final language_util.AppLanguage language;
final bool isDarkTheme;
final bool isFollowSystemTheme;
final bool isUseBlackInDarkTheme;
final int? seedColor;
}
abstract class _Event {}
@toString
class _Init implements _Event {
const _Init();
@override
String toString() => _$toString();
}

View file

@ -61,7 +61,7 @@ class _ResultViewerState extends State<ResultViewer> {
build(BuildContext context) { build(BuildContext context) {
if (_file == null) { if (_file == null) {
return Theme( return Theme(
data: buildDarkTheme(), data: buildDarkTheme(context),
child: Scaffold( child: Scaffold(
appBar: AppBar( appBar: AppBar(
backgroundColor: Colors.black, backgroundColor: Colors.black,

View file

@ -1,76 +1,68 @@
part of '../theme_settings.dart'; part of '../theme_settings.dart';
class _Error {
const _Error(this.ev);
final _Event ev;
}
@npLog @npLog
class _Bloc extends Bloc<_Event, _State> with BlocLogger { class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc(DiContainer c) _Bloc({
: assert(require(c)), required this.prefController,
_c = c, }) : super(_State(
super(_State( isFollowSystemTheme: prefController.isFollowSystemTheme.value,
isFollowSystemTheme: c.pref.isFollowSystemThemeOr(false), isUseBlackInDarkTheme: prefController.isUseBlackInDarkTheme.value,
isUseBlackInDarkTheme: c.pref.isUseBlackInDarkThemeOr(false), seedColor: prefController.seedColor.value?.value,
seedColor: getSeedColor()?.value,
)) { )) {
on<_Init>(_onInit);
on<_SetFollowSystemTheme>(_onSetFollowSystemTheme); on<_SetFollowSystemTheme>(_onSetFollowSystemTheme);
on<_SetUseBlackInDarkTheme>(_onSetUseBlackInDarkTheme); on<_SetUseBlackInDarkTheme>(_onSetUseBlackInDarkTheme);
on<_SetSeedColor>(_onSetSeedColor); on<_SetSeedColor>(_onSetSeedColor);
} }
static bool require(DiContainer c) => DiContainer.has(c, DiType.pref);
@override @override
String get tag => _log.fullName; String get tag => _log.fullName;
Stream<_Error> errorStream() => _errorStream.stream; Future<void> _onInit(_Init ev, Emitter<_State> emit) async {
Future<void> _onSetFollowSystemTheme(
_SetFollowSystemTheme ev, Emitter<_State> emit) async {
_log.info(ev); _log.info(ev);
final oldValue = state.isFollowSystemTheme; await Future.wait([
emit(state.copyWith(isFollowSystemTheme: ev.value)); emit.forEach<bool>(
if (await _c.pref.setFollowSystemTheme(ev.value)) { prefController.isFollowSystemTheme,
KiwiContainer().resolve<EventBus>().fire(ThemeChangedEvent()); onData: (data) => state.copyWith(isFollowSystemTheme: data),
} else { onError: (e, stackTrace) {
_log.severe("[_onSetFollowSystemTheme] Failed writing pref"); _log.severe("[_onInit] Uncaught exception", e, stackTrace);
_errorStream.add(_Error(ev)); return state.copyWith(error: ExceptionEvent(e, stackTrace));
emit(state.copyWith(isFollowSystemTheme: oldValue)); },
} ),
emit.forEach<bool>(
prefController.isUseBlackInDarkTheme,
onData: (data) => state.copyWith(isUseBlackInDarkTheme: data),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
return state.copyWith(error: ExceptionEvent(e, stackTrace));
},
),
emit.forEach<Color?>(
prefController.seedColor,
onData: (data) => state.copyWith(seedColor: data?.value),
onError: (e, stackTrace) {
_log.severe("[_onInit] Uncaught exception", e, stackTrace);
return state.copyWith(error: ExceptionEvent(e, stackTrace));
},
),
]);
} }
Future<void> _onSetUseBlackInDarkTheme( void _onSetFollowSystemTheme(_SetFollowSystemTheme ev, Emitter<_State> emit) {
_SetUseBlackInDarkTheme ev, Emitter<_State> emit) async {
_log.info(ev); _log.info(ev);
final oldValue = state.isUseBlackInDarkTheme; prefController.setFollowSystemTheme(ev.value);
emit(state.copyWith(isUseBlackInDarkTheme: ev.value));
if (await _c.pref.setUseBlackInDarkTheme(ev.value)) {
if (ev.theme.brightness == Brightness.dark) {
KiwiContainer().resolve<EventBus>().fire(ThemeChangedEvent());
}
} else {
_log.severe("[_onSetUseBlackInDarkTheme] Failed writing pref");
_errorStream.add(_Error(ev));
emit(state.copyWith(isUseBlackInDarkTheme: oldValue));
}
} }
Future<void> _onSetSeedColor(_SetSeedColor ev, Emitter<_State> emit) async { void _onSetUseBlackInDarkTheme(
_SetUseBlackInDarkTheme ev, Emitter<_State> emit) {
_log.info(ev); _log.info(ev);
final oldValue = state.seedColor; prefController.setUseBlackInDarkTheme(ev.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");
_errorStream.add(_Error(ev));
emit(state.copyWith(seedColor: oldValue));
}
} }
final DiContainer _c; void _onSetSeedColor(_SetSeedColor ev, Emitter<_State> emit) {
final _errorStream = StreamController<_Error>.broadcast(); _log.info(ev);
prefController.setSeedColor(ev.value);
}
final PrefController prefController;
} }

View file

@ -7,6 +7,7 @@ class _State {
required this.isFollowSystemTheme, required this.isFollowSystemTheme,
required this.isUseBlackInDarkTheme, required this.isUseBlackInDarkTheme,
required this.seedColor, required this.seedColor,
this.error,
}); });
@override @override
@ -16,12 +17,22 @@ class _State {
final bool isUseBlackInDarkTheme; final bool isUseBlackInDarkTheme;
// workaround analyzer bug where Color type can't be recognized // workaround analyzer bug where Color type can't be recognized
final int? seedColor; final int? seedColor;
final ExceptionEvent? error;
} }
abstract class _Event { abstract class _Event {
const _Event(); const _Event();
} }
@toString
class _Init implements _Event {
const _Init();
@override
String toString() => _$toString();
}
@toString @toString
class _SetFollowSystemTheme extends _Event { class _SetFollowSystemTheme extends _Event {
const _SetFollowSystemTheme(this.value); const _SetFollowSystemTheme(this.value);

View file

@ -1,23 +1,23 @@
import 'dart:async'; import 'dart:async';
import 'package:copy_with/copy_with.dart'; import 'package:copy_with/copy_with.dart';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:kiwi/kiwi.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:nc_photos/app_localizations.dart'; import 'package:nc_photos/app_localizations.dart';
import 'package:nc_photos/bloc_util.dart'; import 'package:nc_photos/bloc_util.dart';
import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/controller/pref_controller.dart';
import 'package:nc_photos/entity/pref.dart'; import 'package:nc_photos/exception_event.dart';
import 'package:nc_photos/event/event.dart'; import 'package:nc_photos/exception_util.dart' as exception_util;
import 'package:nc_photos/k.dart' as k; import 'package:nc_photos/k.dart' as k;
import 'package:nc_photos/mobile/android/android_info.dart'; import 'package:nc_photos/mobile/android/android_info.dart';
import 'package:nc_photos/object_extension.dart';
import 'package:nc_photos/platform/k.dart' as platform_k; import 'package:nc_photos/platform/k.dart' as platform_k;
import 'package:nc_photos/session_storage.dart'; import 'package:nc_photos/session_storage.dart';
import 'package:nc_photos/snack_bar_manager.dart'; import 'package:nc_photos/snack_bar_manager.dart';
import 'package:nc_photos/theme.dart'; import 'package:nc_photos/theme.dart';
import 'package:nc_photos/widget/page_visibility_mixin.dart';
import 'package:np_codegen/np_codegen.dart'; import 'package:np_codegen/np_codegen.dart';
import 'package:to_string/to_string.dart'; import 'package:to_string/to_string.dart';
@ -25,7 +25,9 @@ part 'theme/bloc.dart';
part 'theme/state_event.dart'; part 'theme/state_event.dart';
part 'theme_settings.g.dart'; part 'theme_settings.g.dart';
typedef _BlocBuilder = BlocBuilder<_Bloc, _State>; // typedef _BlocBuilder = BlocBuilder<_Bloc, _State>;
typedef _BlocListener = BlocListener<_Bloc, _State>;
typedef _BlocSelector<T> = BlocSelector<_Bloc, _State, T>;
class ThemeSettings extends StatelessWidget { class ThemeSettings extends StatelessWidget {
const ThemeSettings({super.key}); const ThemeSettings({super.key});
@ -33,7 +35,9 @@ class ThemeSettings extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (_) => _Bloc(KiwiContainer().resolve<DiContainer>()), create: (_) => _Bloc(
prefController: context.read(),
),
child: const _WrappedThemeSettings(), child: const _WrappedThemeSettings(),
); );
} }
@ -47,89 +51,86 @@ class _WrappedThemeSettings extends StatefulWidget {
} }
@npLog @npLog
class _WrappedThemeSettingsState extends State<_WrappedThemeSettings> { class _WrappedThemeSettingsState extends State<_WrappedThemeSettings>
with RouteAware, PageVisibilityMixin {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_errorSubscription = _bloc.errorStream().listen((_) { _bloc.add(const _Init());
SnackBarManager().showSnackBar(SnackBar(
content: Text(L10n.global().writePreferenceFailureNotification),
duration: k.snackBarDurationNormal,
));
});
}
@override
void dispose() {
_errorSubscription.cancel();
super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: Builder( body: MultiBlocListener(
builder: (context) => _buildContent(context), listeners: [
_BlocListener(
listenWhen: (previous, current) => previous.error != current.error,
listener: (context, state) {
if (state.error != null && isPageVisible()) {
SnackBarManager().showSnackBar(SnackBar(
content:
Text(exception_util.toUserString(state.error!.error)),
duration: k.snackBarDurationNormal,
));
}
},
),
],
child: CustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
title: Text(L10n.global().settingsThemeTitle),
),
SliverList(
delegate: SliverChildListDelegate(
[
const _SeedColorOption(),
if (platform_k.isAndroid &&
AndroidInfo().sdkInt >= AndroidVersion.Q)
_BlocSelector<bool>(
selector: (state) => state.isFollowSystemTheme,
builder: (_, isFollowSystemTheme) {
return SwitchListTile(
title: Text(
L10n.global().settingsFollowSystemThemeTitle),
value: isFollowSystemTheme,
onChanged: (value) {
_bloc.add(_SetFollowSystemTheme(value));
},
);
},
),
_BlocSelector<bool>(
selector: (state) => state.isUseBlackInDarkTheme,
builder: (context, isUseBlackInDarkTheme) {
return SwitchListTile(
title: Text(
L10n.global().settingsUseBlackInDarkThemeTitle),
subtitle: Text(isUseBlackInDarkTheme
? L10n.global()
.settingsUseBlackInDarkThemeTrueDescription
: L10n.global()
.settingsUseBlackInDarkThemeFalseDescription),
value: isUseBlackInDarkTheme,
onChanged: (value) {
_bloc.add(_SetUseBlackInDarkTheme(
value, Theme.of(context)));
},
);
},
),
],
),
),
],
),
), ),
); );
} }
Widget _buildContent(BuildContext context) {
return CustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
title: Text(L10n.global().settingsThemeTitle),
),
SliverList(
delegate: SliverChildListDelegate(
[
const _SeedColorOption(),
if (platform_k.isAndroid &&
AndroidInfo().sdkInt >= AndroidVersion.Q)
_BlocBuilder(
buildWhen: (previous, current) =>
previous.isFollowSystemTheme !=
current.isFollowSystemTheme,
builder: (context, state) {
return SwitchListTile(
title: Text(L10n.global().settingsFollowSystemThemeTitle),
value: state.isFollowSystemTheme,
onChanged: (value) {
_bloc.add(_SetFollowSystemTheme(value));
},
);
},
),
_BlocBuilder(
buildWhen: (previous, current) =>
previous.isUseBlackInDarkTheme !=
current.isUseBlackInDarkTheme,
builder: (context, state) {
return SwitchListTile(
title: Text(L10n.global().settingsUseBlackInDarkThemeTitle),
subtitle: Text(state.isUseBlackInDarkTheme
? L10n.global()
.settingsUseBlackInDarkThemeTrueDescription
: L10n.global()
.settingsUseBlackInDarkThemeFalseDescription),
value: state.isUseBlackInDarkTheme,
onChanged: (value) {
_bloc.add(
_SetUseBlackInDarkTheme(value, Theme.of(context)));
},
);
},
),
],
),
),
],
);
}
late final _bloc = context.read<_Bloc>(); late final _bloc = context.read<_Bloc>();
late final StreamSubscription _errorSubscription;
} }
class _SeedColorOption extends StatelessWidget { class _SeedColorOption extends StatelessWidget {
@ -137,21 +138,21 @@ class _SeedColorOption extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return _BlocBuilder( return _BlocSelector<int?>(
buildWhen: (previous, current) => previous.seedColor != current.seedColor, selector: (state) => state.seedColor,
builder: (context, state) { builder: (context, seedColor) {
if (SessionStorage().isSupportDynamicColor) { if (SessionStorage().isSupportDynamicColor) {
return ListTile( return ListTile(
title: Text(L10n.global().settingsSeedColorTitle), title: Text(L10n.global().settingsSeedColorTitle),
subtitle: Text(state.seedColor == null subtitle: Text(seedColor == null
? L10n.global().settingsSeedColorSystemColorDescription ? L10n.global().settingsSeedColorSystemColorDescription
: L10n.global().settingsSeedColorDescription), : L10n.global().settingsSeedColorDescription),
trailing: state.seedColor == null trailing: seedColor == null
? null ? null
: Icon( : Icon(
Icons.circle, Icons.circle,
size: 32, size: 32,
color: Color(state.seedColor!), color: Color(seedColor),
), ),
onTap: () => _onSeedColorPressed(context), onTap: () => _onSeedColorPressed(context),
); );
@ -162,7 +163,7 @@ class _SeedColorOption extends StatelessWidget {
trailing: Icon( trailing: Icon(
Icons.circle, Icons.circle,
size: 32, size: 32,
color: Color(state.seedColor ?? defaultSeedColor), color: seedColor?.run(Color.new) ?? defaultSeedColor,
), ),
onTap: () => _onSeedColorPressed(context), onTap: () => _onSeedColorPressed(context),
); );
@ -281,7 +282,7 @@ class _SeedColorCustomPickerState extends State<_SeedColorCustomPicker> {
); );
} }
late Color _customColor = getSeedColor() ?? const Color(defaultSeedColor); late var _customColor = getSeedColor(context) ?? defaultSeedColor;
} }
class _SeedColorPickerItem extends StatelessWidget { class _SeedColorPickerItem extends StatelessWidget {

View file

@ -14,7 +14,10 @@ part of 'theme_settings.dart';
abstract class $_StateCopyWithWorker { abstract class $_StateCopyWithWorker {
_State call( _State call(
{bool? isFollowSystemTheme, bool? isUseBlackInDarkTheme, int? seedColor}); {bool? isFollowSystemTheme,
bool? isUseBlackInDarkTheme,
int? seedColor,
ExceptionEvent? error});
} }
class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker { class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
@ -24,14 +27,16 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
_State call( _State call(
{dynamic isFollowSystemTheme, {dynamic isFollowSystemTheme,
dynamic isUseBlackInDarkTheme, dynamic isUseBlackInDarkTheme,
dynamic seedColor = copyWithNull}) { dynamic seedColor = copyWithNull,
dynamic error = copyWithNull}) {
return _State( return _State(
isFollowSystemTheme: isFollowSystemTheme:
isFollowSystemTheme as bool? ?? that.isFollowSystemTheme, isFollowSystemTheme as bool? ?? that.isFollowSystemTheme,
isUseBlackInDarkTheme: isUseBlackInDarkTheme:
isUseBlackInDarkTheme as bool? ?? that.isUseBlackInDarkTheme, isUseBlackInDarkTheme as bool? ?? that.isUseBlackInDarkTheme,
seedColor: seedColor:
seedColor == copyWithNull ? that.seedColor : seedColor as int?); seedColor == copyWithNull ? that.seedColor : seedColor as int?,
error: error == copyWithNull ? that.error : error as ExceptionEvent?);
} }
final _State that; final _State that;
@ -68,7 +73,14 @@ extension _$_BlocNpLog on _Bloc {
extension _$_StateToString on _State { extension _$_StateToString on _State {
String _$toString() { String _$toString() {
// ignore: unnecessary_string_interpolations // ignore: unnecessary_string_interpolations
return "_State {isFollowSystemTheme: $isFollowSystemTheme, isUseBlackInDarkTheme: $isUseBlackInDarkTheme, seedColor: $seedColor}"; return "_State {isFollowSystemTheme: $isFollowSystemTheme, isUseBlackInDarkTheme: $isUseBlackInDarkTheme, seedColor: $seedColor, error: $error}";
}
}
extension _$_InitToString on _Init {
String _$toString() {
// ignore: unnecessary_string_interpolations
return "_Init {}";
} }
} }

View file

@ -37,7 +37,7 @@ class _SignInState extends State<SignIn> {
@override @override
build(BuildContext context) { build(BuildContext context) {
return Theme( return Theme(
data: buildDarkTheme().copyWith( data: buildDarkTheme(context).copyWith(
scaffoldBackgroundColor: Colors.transparent, scaffoldBackgroundColor: Colors.transparent,
progressIndicatorTheme: const ProgressIndicatorThemeData( progressIndicatorTheme: const ProgressIndicatorThemeData(
color: Colors.white, color: Colors.white,

View file

@ -100,7 +100,7 @@ class _SlideshowViewerState extends State<SlideshowViewer>
@override @override
build(BuildContext context) { build(BuildContext context) {
return Theme( return Theme(
data: buildDarkTheme(), data: buildDarkTheme(context),
child: Scaffold( child: Scaffold(
body: Builder( body: Builder(
builder: _buildContent, builder: _buildContent,

View file

@ -65,7 +65,7 @@ class _TrashbinViewerState extends State<TrashbinViewer> {
@override @override
build(BuildContext context) { build(BuildContext context) {
return Theme( return Theme(
data: buildDarkTheme(), data: buildDarkTheme(context),
child: Scaffold( child: Scaffold(
body: Builder( body: Builder(
builder: _buildContent, builder: _buildContent,

View file

@ -120,7 +120,7 @@ class _ViewerState extends State<Viewer>
build(BuildContext context) { build(BuildContext context) {
final originalBrightness = Theme.of(context).brightness; final originalBrightness = Theme.of(context).brightness;
return Theme( return Theme(
data: buildDarkTheme(), data: buildDarkTheme(context),
child: AnnotatedRegion<SystemUiOverlayStyle>( child: AnnotatedRegion<SystemUiOverlayStyle>(
value: const SystemUiOverlayStyle( value: const SystemUiOverlayStyle(
systemNavigationBarColor: Colors.black, systemNavigationBarColor: Colors.black,
@ -299,7 +299,7 @@ class _ViewerState extends State<Viewer>
} }
}, },
child: Theme( child: Theme(
data: buildTheme(originalBrightness), data: buildTheme(context, originalBrightness),
child: Builder( child: Builder(
builder: (context) { builder: (context) {
return Container( return Container(