From 91978a6cc80662716657b2d09c0a8f0a959d099a Mon Sep 17 00:00:00 2001 From: Ming Ming Date: Sat, 26 Nov 2022 17:51:54 +0800 Subject: [PATCH] Allow picking theme color from color wheel --- app/assets/2.0x/ic_custom_color_56dp.png | Bin 0 -> 10184 bytes app/assets/3.0x/ic_custom_color_56dp.png | Bin 0 -> 18945 bytes app/assets/ic_custom_color_56dp.png | Bin 0 -> 3646 bytes app/lib/widget/settings.dart | 215 +---------- app/lib/widget/settings/theme_settings.dart | 377 ++++++++++++++++++++ app/pubspec.lock | 7 + app/pubspec.yaml | 1 + 7 files changed, 387 insertions(+), 213 deletions(-) create mode 100644 app/assets/2.0x/ic_custom_color_56dp.png create mode 100644 app/assets/3.0x/ic_custom_color_56dp.png create mode 100644 app/assets/ic_custom_color_56dp.png create mode 100644 app/lib/widget/settings/theme_settings.dart diff --git a/app/assets/2.0x/ic_custom_color_56dp.png b/app/assets/2.0x/ic_custom_color_56dp.png new file mode 100644 index 0000000000000000000000000000000000000000..9e98aad3e705b546a5e6132fe12850ae32b36a89 GIT binary patch literal 10184 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 literal 0 HcmV?d00001 diff --git a/app/assets/3.0x/ic_custom_color_56dp.png b/app/assets/3.0x/ic_custom_color_56dp.png new file mode 100644 index 0000000000000000000000000000000000000000..6b38c827952dfb4f56095ea9d0a233f2dc39b868 GIT binary patch literal 18945 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 literal 0 HcmV?d00001 diff --git a/app/assets/ic_custom_color_56dp.png b/app/assets/ic_custom_color_56dp.png new file mode 100644 index 0000000000000000000000000000000000000000..8ee8bc48ee3317b4a45ae4df091f224c597e88a1 GIT binary patch literal 3646 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 { leading: const Icon(Icons.palette_outlined), label: L10n.global().settingsThemeTitle, description: L10n.global().settingsThemeDescription, - builder: () => _ThemeSettings(), + builder: () => const ThemeSettings(), ), _buildSubSettings( context, @@ -1463,216 +1462,6 @@ class _EnhanceResolutionSliderState extends State<_EnhanceResolutionSlider> { late int _height; } -class _ThemeSettings extends StatefulWidget { - @override - createState() => _ThemeSettingsState(); -} - -class _ThemeSettingsState extends State<_ThemeSettings> { - @override - initState() { - super.initState(); - _isFollowSystemTheme = Pref().isFollowSystemThemeOr(false); - _isUseBlackInDarkTheme = Pref().isUseBlackInDarkThemeOr(false); - _seedColor = getSeedColor(); - } - - @override - build(BuildContext context) { - return Scaffold( - body: Builder( - builder: (context) => _buildContent(context), - ), - ); - } - - Widget _buildContent(BuildContext context) { - return CustomScrollView( - slivers: [ - SliverAppBar( - pinned: true, - title: Text(L10n.global().settingsThemeTitle), - ), - SliverList( - delegate: SliverChildListDelegate( - [ - ListTile( - title: Text(L10n.global().settingsSeedColorTitle), - trailing: Icon( - Icons.circle, - size: 32, - color: _seedColor, - ), - onTap: () => _onSeedColorPressed(context), - ), - if (platform_k.isAndroid && - AndroidInfo().sdkInt >= AndroidVersion.Q) - SwitchListTile( - title: Text(L10n.global().settingsFollowSystemThemeTitle), - value: _isFollowSystemTheme, - onChanged: (value) => _onFollowSystemThemeChanged(value), - ), - SwitchListTile( - title: Text(L10n.global().settingsUseBlackInDarkThemeTitle), - subtitle: Text(_isUseBlackInDarkTheme - ? L10n.global().settingsUseBlackInDarkThemeTrueDescription - : L10n.global() - .settingsUseBlackInDarkThemeFalseDescription), - value: _isUseBlackInDarkTheme, - onChanged: (value) => - _onUseBlackInDarkThemeChanged(context, value), - ), - ], - ), - ), - ], - ); - } - - Future _onFollowSystemThemeChanged(bool value) async { - final oldValue = _isFollowSystemTheme; - setState(() { - _isFollowSystemTheme = value; - }); - if (await Pref().setFollowSystemTheme(value)) { - KiwiContainer().resolve().fire(ThemeChangedEvent()); - } else { - _log.severe("[_onFollowSystemThemeChanged] Failed writing pref"); - SnackBarManager().showSnackBar(SnackBar( - content: Text(L10n.global().writePreferenceFailureNotification), - duration: k.snackBarDurationNormal, - )); - setState(() { - _isFollowSystemTheme = oldValue; - }); - } - } - - Future _onUseBlackInDarkThemeChanged( - BuildContext context, bool value) async { - final oldValue = _isUseBlackInDarkTheme; - setState(() { - _isUseBlackInDarkTheme = value; - }); - if (await Pref().setUseBlackInDarkTheme(value)) { - if (Theme.of(context).brightness == Brightness.dark) { - KiwiContainer().resolve().fire(ThemeChangedEvent()); - } - } else { - _log.severe("[_onUseBlackInDarkThemeChanged] Failed writing pref"); - SnackBarManager().showSnackBar(SnackBar( - content: Text(L10n.global().writePreferenceFailureNotification), - duration: k.snackBarDurationNormal, - )); - setState(() { - _isUseBlackInDarkTheme = oldValue; - }); - } - } - - Future _onSeedColorPressed(BuildContext context) async { - final result = await showDialog( - context: context, - builder: (context) => const _SeedColorPicker(), - ); - if (result == null) { - return; - } - - final oldValue = _seedColor; - setState(() { - _seedColor = result; - }); - if (await Pref().setSeedColor(result.withAlpha(0xFF).value)) { - KiwiContainer().resolve().fire(ThemeChangedEvent()); - } else { - _log.severe("[_onSeedColorPressed] Failed writing pref"); - SnackBarManager().showSnackBar(SnackBar( - content: Text(L10n.global().writePreferenceFailureNotification), - duration: k.snackBarDurationNormal, - )); - setState(() { - _seedColor = oldValue; - }); - } - } - - late bool _isFollowSystemTheme; - late bool _isUseBlackInDarkTheme; - late Color _seedColor; - - static final _log = Logger("widget.settings._ThemeSettingsState"); -} - -class _SeedColorPicker extends StatefulWidget { - const _SeedColorPicker(); - - @override - State createState() => _SeedColorPickerState(); -} - -class _SeedColorPickerState extends State<_SeedColorPicker> { - @override - Widget build(BuildContext context) { - return AlertDialog( - title: Text(L10n.global().settingsSeedColorPickerTitle), - content: Wrap( - children: const [ - Color(0xFFF44336), - Color(0xFF9C27B0), - Color(0xFF2196F3), - Color(0xFF4CAF50), - Color(0xFFFFC107), - ] - .map((c) => _SeedColorPickerItem( - seedColor: c, - onSelected: () => _onItemSelected(context, c), - )) - .toList(), - ), - ); - } - - void _onItemSelected(BuildContext context, Color seedColor) { - Navigator.of(context).pop(seedColor); - } -} - -class _SeedColorPickerItem extends StatelessWidget { - const _SeedColorPickerItem({ - required this.seedColor, - this.onSelected, - }); - - @override - Widget build(BuildContext context) { - final content = SizedBox.square( - dimension: _size, - child: Center( - child: Icon( - Icons.circle, - size: _size - _size * .1, - color: seedColor, - ), - ), - ); - if (onSelected != null) { - return InkWell( - customBorder: const CircleBorder(), - onTap: onSelected, - child: content, - ); - } else { - return content; - } - } - - final Color seedColor; - final VoidCallback? onSelected; - - static const _size = 56.0; -} - class _MiscSettings extends StatefulWidget { const _MiscSettings({Key? key}) : super(key: key); diff --git a/app/lib/widget/settings/theme_settings.dart b/app/lib/widget/settings/theme_settings.dart new file mode 100644 index 00000000..105cd01b --- /dev/null +++ b/app/lib/widget/settings/theme_settings.dart @@ -0,0 +1,377 @@ +import 'package:event_bus/event_bus.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_colorpicker/flutter_colorpicker.dart'; +import 'package:kiwi/kiwi.dart'; +import 'package:logging/logging.dart'; +import 'package:nc_photos/app_localizations.dart'; +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/pref.dart'; +import 'package:nc_photos/snack_bar_manager.dart'; +import 'package:nc_photos/theme.dart'; + +class ThemeSettings extends StatefulWidget { + const ThemeSettings({super.key}); + + @override + createState() => _ThemeSettingsState(); +} + +class _ThemeSettingsState extends State { + @override + initState() { + super.initState(); + _isFollowSystemTheme = Pref().isFollowSystemThemeOr(false); + _isUseBlackInDarkTheme = Pref().isUseBlackInDarkThemeOr(false); + _seedColor = getSeedColor(); + } + + @override + build(BuildContext context) { + return Scaffold( + body: Builder( + builder: (context) => _buildContent(context), + ), + ); + } + + Widget _buildContent(BuildContext context) { + return CustomScrollView( + slivers: [ + SliverAppBar( + pinned: true, + title: Text(L10n.global().settingsThemeTitle), + ), + SliverList( + delegate: SliverChildListDelegate( + [ + ListTile( + title: Text(L10n.global().settingsSeedColorTitle), + trailing: Icon( + Icons.circle, + size: 32, + color: _seedColor, + ), + onTap: () => _onSeedColorPressed(context), + ), + if (platform_k.isAndroid && + AndroidInfo().sdkInt >= AndroidVersion.Q) + SwitchListTile( + title: Text(L10n.global().settingsFollowSystemThemeTitle), + value: _isFollowSystemTheme, + onChanged: (value) => _onFollowSystemThemeChanged(value), + ), + SwitchListTile( + title: Text(L10n.global().settingsUseBlackInDarkThemeTitle), + subtitle: Text(_isUseBlackInDarkTheme + ? L10n.global().settingsUseBlackInDarkThemeTrueDescription + : L10n.global() + .settingsUseBlackInDarkThemeFalseDescription), + value: _isUseBlackInDarkTheme, + onChanged: (value) => + _onUseBlackInDarkThemeChanged(context, value), + ), + ], + ), + ), + ], + ); + } + + Future _onFollowSystemThemeChanged(bool value) async { + final oldValue = _isFollowSystemTheme; + setState(() { + _isFollowSystemTheme = value; + }); + if (await Pref().setFollowSystemTheme(value)) { + KiwiContainer().resolve().fire(ThemeChangedEvent()); + } else { + _log.severe("[_onFollowSystemThemeChanged] Failed writing pref"); + SnackBarManager().showSnackBar(SnackBar( + content: Text(L10n.global().writePreferenceFailureNotification), + duration: k.snackBarDurationNormal, + )); + setState(() { + _isFollowSystemTheme = oldValue; + }); + } + } + + Future _onUseBlackInDarkThemeChanged( + BuildContext context, bool value) async { + final oldValue = _isUseBlackInDarkTheme; + setState(() { + _isUseBlackInDarkTheme = value; + }); + if (await Pref().setUseBlackInDarkTheme(value)) { + if (Theme.of(context).brightness == Brightness.dark) { + KiwiContainer().resolve().fire(ThemeChangedEvent()); + } + } else { + _log.severe("[_onUseBlackInDarkThemeChanged] Failed writing pref"); + SnackBarManager().showSnackBar(SnackBar( + content: Text(L10n.global().writePreferenceFailureNotification), + duration: k.snackBarDurationNormal, + )); + setState(() { + _isUseBlackInDarkTheme = oldValue; + }); + } + } + + Future _onSeedColorPressed(BuildContext context) async { + final result = await showDialog( + context: context, + builder: (context) => const _SeedColorPicker(), + ); + if (result == null) { + return; + } + + final oldValue = _seedColor; + setState(() { + _seedColor = result; + }); + if (await Pref().setSeedColor(result.withAlpha(0xFF).value)) { + KiwiContainer().resolve().fire(ThemeChangedEvent()); + } else { + _log.severe("[_onSeedColorPressed] Failed writing pref"); + SnackBarManager().showSnackBar(SnackBar( + content: Text(L10n.global().writePreferenceFailureNotification), + duration: k.snackBarDurationNormal, + )); + setState(() { + _seedColor = oldValue; + }); + } + } + + late bool _isFollowSystemTheme; + late bool _isUseBlackInDarkTheme; + late Color _seedColor; + + static final _log = + Logger("widget.settings.theme_settings._ThemeSettingsState"); +} + +class _SeedColorPicker extends StatefulWidget { + const _SeedColorPicker(); + + @override + State createState() => _SeedColorPickerState(); +} + +class _SeedColorPickerState extends State<_SeedColorPicker> { + @override + Widget build(BuildContext context) { + return Visibility( + visible: _isVisible, + child: AlertDialog( + title: Text(L10n.global().settingsSeedColorPickerTitle), + content: Wrap( + children: const [ + Color(0xFFF44336), + Color(0xFF9C27B0), + Color(0xFF2196F3), + Color(0xFF4CAF50), + Color(0xFFFFC107), + null, + ] + .map((c) => _SeedColorPickerItem( + seedColor: c, + onSelected: () => _onItemSelected(context, c), + )) + .toList(), + ), + ), + ); + } + + Future _onItemSelected(BuildContext context, Color? seedColor) async { + if (seedColor != null) { + Navigator.of(context).pop(seedColor); + return; + } + setState(() { + _isVisible = false; + }); + final color = await showDialog( + context: context, + builder: (context) => const _SeedColorCustomPicker(), + barrierColor: Colors.transparent, + ); + Navigator.of(context).pop(color); + } + + var _isVisible = true; +} + +class _SeedColorCustomPicker extends StatefulWidget { + const _SeedColorCustomPicker(); + + @override + State createState() => _SeedColorCustomPickerState(); +} + +class _SeedColorCustomPickerState extends State<_SeedColorCustomPicker> { + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(L10n.global().settingsSeedColorPickerTitle), + content: SingleChildScrollView( + child: _HueRingPicker( + pickerColor: _customColor, + onColorChanged: (value) { + setState(() { + _customColor = value; + }); + }, + ), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(_customColor); + }, + child: Text(L10n.global().applyButtonLabel), + ), + ], + ); + } + + late Color _customColor = getSeedColor(); +} + +class _SeedColorPickerItem extends StatelessWidget { + const _SeedColorPickerItem({ + required this.seedColor, + this.onSelected, + }); + + @override + Widget build(BuildContext context) { + final content = SizedBox.square( + dimension: _size, + child: Center( + child: seedColor != null + ? Icon( + Icons.circle, + size: _size * .9, + color: seedColor, + ) + : Transform.scale( + scale: .9, + child: Stack( + alignment: Alignment.center, + children: [ + Image.asset("assets/ic_custom_color_56dp.png"), + const Icon( + Icons.colorize_outlined, + size: _size * .5, + color: Colors.black87, + ), + ], + ), + ), + ), + ); + if (onSelected != null) { + return InkWell( + customBorder: const CircleBorder(), + onTap: onSelected, + child: content, + ); + } else { + return content; + } + } + + final Color? seedColor; + final VoidCallback? onSelected; + + static const _size = 56.0; +} + +/// Based on the original HueRingPicker +class _HueRingPicker extends StatefulWidget { + const _HueRingPicker({ + Key? key, + required this.pickerColor, + required this.onColorChanged, + // ignore: unused_element + this.colorPickerHeight = 250.0, + // ignore: unused_element + this.hueRingStrokeWidth = 20.0, + // ignore: unused_element + this.displayThumbColor = true, + // ignore: unused_element + this.pickerAreaBorderRadius = const BorderRadius.all(Radius.zero), + }) : super(key: key); + + final Color pickerColor; + final ValueChanged onColorChanged; + final double colorPickerHeight; + final double hueRingStrokeWidth; + final bool displayThumbColor; + final BorderRadius pickerAreaBorderRadius; + + @override + _HueRingPickerState createState() => _HueRingPickerState(); +} + +class _HueRingPickerState extends State<_HueRingPicker> { + HSVColor currentHsvColor = const HSVColor.fromAHSV(0.0, 0.0, 0.0, 0.0); + + @override + void initState() { + currentHsvColor = HSVColor.fromColor(widget.pickerColor); + super.initState(); + } + + @override + void didUpdateWidget(_HueRingPicker oldWidget) { + super.didUpdateWidget(oldWidget); + currentHsvColor = HSVColor.fromColor(widget.pickerColor); + } + + void onColorChanging(HSVColor color) { + setState(() => currentHsvColor = color.withSaturation(1).withValue(1)); + widget.onColorChanged(currentHsvColor.toColor()); + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + ClipRRect( + borderRadius: widget.pickerAreaBorderRadius, + child: Padding( + padding: const EdgeInsets.all(18), + child: Stack( + alignment: AlignmentDirectional.center, + children: [ + ColorIndicator( + currentHsvColor, + width: 128, + height: 128, + ), + SizedBox( + width: widget.colorPickerHeight, + height: widget.colorPickerHeight, + child: ColorPickerHueRing( + currentHsvColor, + onColorChanging, + displayThumbColor: widget.displayThumbColor, + strokeWidth: 26, + ), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/app/pubspec.lock b/app/pubspec.lock index 5efe07c9..1eb05b06 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -497,6 +497,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.3.0" + flutter_colorpicker: + dependency: "direct main" + description: + name: flutter_colorpicker + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" flutter_isolate: dependency: "direct main" description: diff --git a/app/pubspec.yaml b/app/pubspec.yaml index f8743d59..dd0e51dd 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -58,6 +58,7 @@ dependencies: url: https://gitlab.com/nc-photos/flutter_background_service.git ref: v0.2.6-nc-photos-2 flutter_bloc: ^8.0.0 + flutter_colorpicker: ^1.0.3 flutter_isolate: git: url: https://gitlab.com/nc-photos/flutter_isolate.git