From 4c6c56e3f8a9040b82bece3920df14cb58c79a8c Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Tue, 19 Dec 2023 19:09:40 +0100 Subject: [PATCH] ui fixes --- lib/theme/themes.dart | 55 +++++++------------ lib/widgets/aves_app.dart | 16 ++---- lib/widgets/common/identity/aves_caption.dart | 2 +- .../identity/buttons/captioned_button.dart | 2 +- lib/widgets/dialogs/convert_entry_dialog.dart | 4 +- lib/widgets/navigation/drawer/app_drawer.dart | 40 +++++++++----- lib/widgets/stats/date/histogram.dart | 6 +- .../info/metadata/metadata_section.dart | 1 + .../viewer/info/metadata/xmp_card.dart | 2 +- plugins/aves_utils/lib/src/colors.dart | 5 ++ 10 files changed, 63 insertions(+), 70 deletions(-) diff --git a/lib/theme/themes.dart b/lib/theme/themes.dart index 953f059e0..f3d7fc06e 100644 --- a/lib/theme/themes.dart +++ b/lib/theme/themes.dart @@ -1,6 +1,7 @@ import 'dart:ui'; import 'package:aves/widgets/aves_app.dart'; +import 'package:aves_utils/aves_utils.dart'; import 'package:flutter/material.dart'; class Themes { @@ -136,19 +137,19 @@ class Themes { static final _lightThemeTypo = _typography.black; static final _lightTitleColor = _lightThemeTypo.titleMedium!.color!; - static final _lightBodyColor = _lightThemeTypo.bodyMedium!.color!; static final _lightLabelColor = _lightThemeTypo.labelMedium!.color!; static const _lightActionIconColor = Color(0xAA000000); static const _lightOnSurface = Colors.black; static ThemeData lightTheme(Color accentColor, bool deviceInitialized) { + final onAccent = ColorUtils.textColorOn(accentColor); final colors = ColorScheme.fromSeed( seedColor: accentColor, brightness: Brightness.light, primary: accentColor, - onPrimary: _lightBodyColor, + onPrimary: onAccent, secondary: accentColor, - onSecondary: _lightBodyColor, + onSecondary: onAccent, onSurface: _lightOnSurface, ); final textTheme = _lightThemeTypo; @@ -171,20 +172,6 @@ class Themes { ), popupMenuTheme: _popupMenuTheme(colors, textTheme), snackBarTheme: _snackBarTheme(colors), - switchTheme: SwitchThemeData( - thumbColor: MaterialStateProperty.resolveWith((states) { - final active = states.contains(MaterialState.selected); - return active ? Colors.white : Colors.grey.shade600; - }), - trackColor: MaterialStateProperty.resolveWith((states) { - final active = states.contains(MaterialState.selected); - return colors.primary.withOpacity(active ? 1 : .1); - }), - trackOutlineColor: MaterialStateProperty.resolveWith((states) { - final active = states.contains(MaterialState.selected); - return active ? colors.primary : colors.onPrimary.withOpacity(.5); - }), - ), textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom( foregroundColor: _lightLabelColor, @@ -201,6 +188,20 @@ class Themes { static final _darkLabelColor = _darkThemeTypo.labelMedium!.color!; static const _darkOnSurface = Colors.white; + static ColorScheme _darkColorScheme(Color accentColor) { + final onAccent = ColorUtils.textColorOn(accentColor); + final colors = ColorScheme.fromSeed( + seedColor: accentColor, + brightness: Brightness.dark, + primary: accentColor, + onPrimary: onAccent, + secondary: accentColor, + onSecondary: onAccent, + onSurface: _darkOnSurface, + ); + return colors; + } + static ThemeData _baseDarkTheme(ColorScheme colors, bool deviceInitialized) { final textTheme = _darkThemeTypo; return _baseTheme(colors, deviceInitialized).copyWith( @@ -234,30 +235,14 @@ class Themes { } static ThemeData darkTheme(Color accentColor, bool deviceInitialized) { - final colors = ColorScheme.fromSeed( - seedColor: accentColor, - brightness: Brightness.dark, - primary: accentColor, - onPrimary: _darkBodyColor, - secondary: accentColor, - onSecondary: _darkBodyColor, - onSurface: _darkOnSurface, - ); + final colors = _darkColorScheme(accentColor); return _baseDarkTheme(colors, deviceInitialized); } // black static ThemeData blackTheme(Color accentColor, bool deviceInitialized) { - final colors = ColorScheme.fromSeed( - seedColor: accentColor, - brightness: Brightness.dark, - primary: accentColor, - onPrimary: _darkBodyColor, - secondary: accentColor, - onSecondary: _darkBodyColor, - onSurface: _darkOnSurface, - ).copyWith( + final colors = _darkColorScheme(accentColor).copyWith( background: Colors.black, ); final baseTheme = _baseDarkTheme(colors, deviceInitialized); diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index 84a02fff5..847f92bcc 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -45,7 +45,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_localization_nn/flutter_localization_nn.dart'; -import 'package:material_color_utilities/material_color_utilities.dart'; import 'package:overlay_support/overlay_support.dart'; import 'package:provider/provider.dart'; import 'package:screen_brightness/screen_brightness.dart'; @@ -151,7 +150,6 @@ class _AvesAppState extends State with WidgetsBindingObserver { final List _subscriptions = []; late final Future _appSetup; late final Future _shouldUseBoldFontLoader; - late final Future _dynamicColorPaletteLoader; final TvRailController _tvRailController = TvRailController(); final CollectionSource _mediaStoreSource = MediaStoreSource(); final Debouncer _mediaStoreChangeDebouncer = Debouncer(delay: ADurations.mediaContentChangeDebounceDelay); @@ -183,7 +181,6 @@ class _AvesAppState extends State with WidgetsBindingObserver { EquatableConfig.stringify = true; _appSetup = _setup(); _shouldUseBoldFontLoader = AccessibilityService.shouldUseBoldFont(); - _dynamicColorPaletteLoader = DynamicColorPlugin.getCorePalette(); _subscriptions.add(_mediaStoreChangeChannel.receiveBroadcastStream().listen((event) => _onMediaStoreChanged(event as String?))); _subscriptions.add(_newIntentChannel.receiveBroadcastStream().listen((event) => _onNewIntent(event as Map?))); _subscriptions.add(_analysisCompletionChannel.receiveBroadcastStream().listen((event) => _onAnalysisCompletion())); @@ -246,18 +243,13 @@ class _AvesAppState extends State with WidgetsBindingObserver { AStyles.updateStylesForLocale(settings.appliedLocale); - return FutureBuilder( - future: _dynamicColorPaletteLoader, - builder: (context, snapshot) { + return DynamicColorBuilder( + builder: (lightScheme, darkScheme) { const defaultAccent = AvesColorsData.defaultAccent; Color lightAccent = defaultAccent, darkAccent = defaultAccent; if (enableDynamicColor) { - // `DynamicColorBuilder` from package `dynamic_color` provides light/dark - // palettes with a primary color from tones too dark/light (40/80), - // so we derive the color with adjusted tones (60/70) - final tonalPalette = snapshot.data?.primary; - lightAccent = Color(tonalPalette?.get(60) ?? defaultAccent.value); - darkAccent = Color(tonalPalette?.get(70) ?? defaultAccent.value); + lightAccent = lightScheme?.primary ?? lightAccent; + darkAccent = darkScheme?.primary ?? darkAccent; } final lightTheme = Themes.lightTheme(lightAccent, initialized); final darkTheme = themeBrightness == AvesThemeBrightness.black ? Themes.blackTheme(darkAccent, initialized) : Themes.darkTheme(darkAccent, initialized); diff --git a/lib/widgets/common/identity/aves_caption.dart b/lib/widgets/common/identity/aves_caption.dart index 68bf75e60..095caff9e 100644 --- a/lib/widgets/common/identity/aves_caption.dart +++ b/lib/widgets/common/identity/aves_caption.dart @@ -15,7 +15,7 @@ class AvesCaption extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); final subtitleStyle = theme.textTheme.bodySmall!; - final subtitleChangeShadowColor = theme.colorScheme.onPrimary; + final subtitleChangeShadowColor = theme.colorScheme.onBackground; return ChangeHighlightText( // provide key to refresh on theme brightness change key: ValueKey(subtitleChangeShadowColor), diff --git a/lib/widgets/common/identity/buttons/captioned_button.dart b/lib/widgets/common/identity/buttons/captioned_button.dart index 7417cd866..72d4fdebf 100644 --- a/lib/widgets/common/identity/buttons/captioned_button.dart +++ b/lib/widgets/common/identity/buttons/captioned_button.dart @@ -116,7 +116,7 @@ class _CaptionedButtonState extends State { return AnimatedDefaultTextStyle( style: focused ? style.copyWith( - color: Theme.of(context).colorScheme.onPrimary, + color: Theme.of(context).colorScheme.primary, ) : style, duration: const Duration(milliseconds: 200), diff --git a/lib/widgets/dialogs/convert_entry_dialog.dart b/lib/widgets/dialogs/convert_entry_dialog.dart index 10fd78821..ef9ffc8f8 100644 --- a/lib/widgets/dialogs/convert_entry_dialog.dart +++ b/lib/widgets/dialogs/convert_entry_dialog.dart @@ -99,12 +99,12 @@ class _ConvertEntryDialogState extends State { const contentHorizontalPadding = EdgeInsets.symmetric(horizontal: AvesDialog.defaultHorizontalContentPadding); final colorScheme = Theme.of(context).colorScheme; final trailingStyle = TextStyle(color: colorScheme.onSurfaceVariant); - final trailingChangeShadowColor = colorScheme.onPrimary; + final trailingChangeShadowColor = colorScheme.onBackground; // used by the drop down to match input decoration final textFieldDecorationBorder = Border( bottom: BorderSide( - color: colorScheme.onSurface.withOpacity(0.38), //Color(0xFFBDBDBD), + color: colorScheme.onSurface.withOpacity(0.38), width: 1.0, ), ); diff --git a/lib/widgets/navigation/drawer/app_drawer.dart b/lib/widgets/navigation/drawer/app_drawer.dart index e3c94d672..3139a5049 100644 --- a/lib/widgets/navigation/drawer/app_drawer.dart +++ b/lib/widgets/navigation/drawer/app_drawer.dart @@ -14,6 +14,7 @@ import 'package:aves/theme/icons.dart'; import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/utils/file_utils.dart'; import 'package:aves/widgets/about/about_page.dart'; +import 'package:aves/widgets/common/basic/text/outlined.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/extensions/media_query.dart'; import 'package:aves/widgets/common/identity/aves_logo.dart'; @@ -120,17 +121,21 @@ class _AppDrawerState extends State { )); } + final colorScheme = Theme.of(context).colorScheme; + final onPrimary = colorScheme.onPrimary; + final drawerButtonStyle = ButtonStyle( padding: MaterialStateProperty.all(const EdgeInsetsDirectional.only(start: 12, end: 16)), ); return Container( - padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), - color: Theme.of(context).colorScheme.primary, + padding: const EdgeInsets.symmetric(horizontal: 16), + color: colorScheme.primary, child: SafeArea( bottom: false, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + const SizedBox(height: 6), Align( alignment: AlignmentDirectional.centerStart, child: Wrap( @@ -138,15 +143,19 @@ class _AppDrawerState extends State { crossAxisAlignment: WrapCrossAlignment.center, children: [ const AvesLogo(size: 48), - Text( - context.l10n.appName, - style: const TextStyle( - color: Colors.white, - fontSize: 38, - fontWeight: FontWeight.w300, - letterSpacing: 1.0, - fontFeatures: [FontFeature.enable('smcp')], - ), + OutlinedText( + textSpans: [ + TextSpan( + text: context.l10n.appName, + style: const TextStyle( + color: Colors.white, + fontSize: 38, + fontWeight: FontWeight.w300, + letterSpacing: 1.0, + fontFeatures: [FontFeature.enable('smcp')], + ), + ), + ], ), ], ), @@ -155,9 +164,9 @@ class _AppDrawerState extends State { OutlinedButtonTheme( data: OutlinedButtonThemeData( style: ButtonStyle( - foregroundColor: MaterialStateProperty.all(Colors.white), - overlayColor: MaterialStateProperty.all(Colors.white24), - side: MaterialStateProperty.all(BorderSide(width: 1, color: Colors.white.withOpacity(0.12))), + foregroundColor: MaterialStateProperty.all(onPrimary), + overlayColor: MaterialStateProperty.all(onPrimary.withOpacity(.12)), + side: MaterialStateProperty.all(BorderSide(width: 1, color: onPrimary.withOpacity(.24))), ), ), child: Wrap( @@ -181,7 +190,8 @@ class _AppDrawerState extends State { ), ], ), - ) + ), + const SizedBox(height: 8), ], ), ), diff --git a/lib/widgets/stats/date/histogram.dart b/lib/widgets/stats/date/histogram.dart index 55cebcaa9..0debd691b 100644 --- a/lib/widgets/stats/date/histogram.dart +++ b/lib/widgets/stats/date/histogram.dart @@ -195,10 +195,10 @@ class _HistogramState extends State with AutomaticKeepAliveClientMixi final colorScheme = Theme.of(context).colorScheme; final accentColor = colorScheme.primary; - final axisColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onPrimary.withOpacity(.9) : Colors.transparent); - final measureLineColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onPrimary.withOpacity(.1) : Colors.transparent); + final axisColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onBackground : Colors.transparent); + final measureLineColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onBackground.withOpacity(.1) : Colors.transparent); final histogramLineColor = charts.ColorUtil.fromDartColor(drawLine ? accentColor : Colors.white); - final histogramPointStrikeColor = axisColor; + final histogramPointStrikeColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onSurface : Colors.transparent); final histogramPointFillColor = charts.ColorUtil.fromDartColor(colorScheme.background); final series = [ diff --git a/lib/widgets/viewer/info/metadata/metadata_section.dart b/lib/widgets/viewer/info/metadata/metadata_section.dart index c72588edc..bd0d34c34 100644 --- a/lib/widgets/viewer/info/metadata/metadata_section.dart +++ b/lib/widgets/viewer/info/metadata/metadata_section.dart @@ -98,6 +98,7 @@ class _MetadataSectionSliverState extends State { ), children: settings.useTvLayout ? [ + const SizedBox(height: 16), AvesOutlinedButton( label: MaterialLocalizations.of(context).moreButtonTooltip, onPressed: () { diff --git a/lib/widgets/viewer/info/metadata/xmp_card.dart b/lib/widgets/viewer/info/metadata/xmp_card.dart index 49ec41cf1..7df746d69 100644 --- a/lib/widgets/viewer/info/metadata/xmp_card.dart +++ b/lib/widgets/viewer/info/metadata/xmp_card.dart @@ -74,7 +74,7 @@ class _XmpCardState extends State { return Container( decoration: BoxDecoration( border: Border.all( - color: Theme.of(context).colorScheme.onPrimary.withOpacity(.2), + color: Theme.of(context).dividerColor, ), borderRadius: const BorderRadius.all(Radius.circular(4)), ), diff --git a/plugins/aves_utils/lib/src/colors.dart b/plugins/aves_utils/lib/src/colors.dart index d5e9768b4..6189f4131 100644 --- a/plugins/aves_utils/lib/src/colors.dart +++ b/plugins/aves_utils/lib/src/colors.dart @@ -5,4 +5,9 @@ class ColorUtils { // when used in gradients or lerping to it static const transparentWhite = Color(0x00FFFFFF); static const transparentBlack = Color(0x00000000); + + static Color textColorOn(Color background) { + final yiq = (background.red * 299 + background.green * 587 + background.blue * 114) / 1000; + return Color(yiq >= 128 ? 0xFF000000 : 0xFFFFFFFF); + } }