This commit is contained in:
Thibault Deckers 2023-12-19 19:09:40 +01:00
parent 4dcfc7568f
commit 4c6c56e3f8
10 changed files with 63 additions and 70 deletions

View file

@ -1,6 +1,7 @@
import 'dart:ui'; import 'dart:ui';
import 'package:aves/widgets/aves_app.dart'; import 'package:aves/widgets/aves_app.dart';
import 'package:aves_utils/aves_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class Themes { class Themes {
@ -136,19 +137,19 @@ class Themes {
static final _lightThemeTypo = _typography.black; static final _lightThemeTypo = _typography.black;
static final _lightTitleColor = _lightThemeTypo.titleMedium!.color!; static final _lightTitleColor = _lightThemeTypo.titleMedium!.color!;
static final _lightBodyColor = _lightThemeTypo.bodyMedium!.color!;
static final _lightLabelColor = _lightThemeTypo.labelMedium!.color!; static final _lightLabelColor = _lightThemeTypo.labelMedium!.color!;
static const _lightActionIconColor = Color(0xAA000000); static const _lightActionIconColor = Color(0xAA000000);
static const _lightOnSurface = Colors.black; static const _lightOnSurface = Colors.black;
static ThemeData lightTheme(Color accentColor, bool deviceInitialized) { static ThemeData lightTheme(Color accentColor, bool deviceInitialized) {
final onAccent = ColorUtils.textColorOn(accentColor);
final colors = ColorScheme.fromSeed( final colors = ColorScheme.fromSeed(
seedColor: accentColor, seedColor: accentColor,
brightness: Brightness.light, brightness: Brightness.light,
primary: accentColor, primary: accentColor,
onPrimary: _lightBodyColor, onPrimary: onAccent,
secondary: accentColor, secondary: accentColor,
onSecondary: _lightBodyColor, onSecondary: onAccent,
onSurface: _lightOnSurface, onSurface: _lightOnSurface,
); );
final textTheme = _lightThemeTypo; final textTheme = _lightThemeTypo;
@ -171,20 +172,6 @@ class Themes {
), ),
popupMenuTheme: _popupMenuTheme(colors, textTheme), popupMenuTheme: _popupMenuTheme(colors, textTheme),
snackBarTheme: _snackBarTheme(colors), snackBarTheme: _snackBarTheme(colors),
switchTheme: SwitchThemeData(
thumbColor: MaterialStateProperty.resolveWith<Color>((states) {
final active = states.contains(MaterialState.selected);
return active ? Colors.white : Colors.grey.shade600;
}),
trackColor: MaterialStateProperty.resolveWith<Color>((states) {
final active = states.contains(MaterialState.selected);
return colors.primary.withOpacity(active ? 1 : .1);
}),
trackOutlineColor: MaterialStateProperty.resolveWith<Color>((states) {
final active = states.contains(MaterialState.selected);
return active ? colors.primary : colors.onPrimary.withOpacity(.5);
}),
),
textButtonTheme: TextButtonThemeData( textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: _lightLabelColor, foregroundColor: _lightLabelColor,
@ -201,6 +188,20 @@ class Themes {
static final _darkLabelColor = _darkThemeTypo.labelMedium!.color!; static final _darkLabelColor = _darkThemeTypo.labelMedium!.color!;
static const _darkOnSurface = Colors.white; 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) { static ThemeData _baseDarkTheme(ColorScheme colors, bool deviceInitialized) {
final textTheme = _darkThemeTypo; final textTheme = _darkThemeTypo;
return _baseTheme(colors, deviceInitialized).copyWith( return _baseTheme(colors, deviceInitialized).copyWith(
@ -234,30 +235,14 @@ class Themes {
} }
static ThemeData darkTheme(Color accentColor, bool deviceInitialized) { static ThemeData darkTheme(Color accentColor, bool deviceInitialized) {
final colors = ColorScheme.fromSeed( final colors = _darkColorScheme(accentColor);
seedColor: accentColor,
brightness: Brightness.dark,
primary: accentColor,
onPrimary: _darkBodyColor,
secondary: accentColor,
onSecondary: _darkBodyColor,
onSurface: _darkOnSurface,
);
return _baseDarkTheme(colors, deviceInitialized); return _baseDarkTheme(colors, deviceInitialized);
} }
// black // black
static ThemeData blackTheme(Color accentColor, bool deviceInitialized) { static ThemeData blackTheme(Color accentColor, bool deviceInitialized) {
final colors = ColorScheme.fromSeed( final colors = _darkColorScheme(accentColor).copyWith(
seedColor: accentColor,
brightness: Brightness.dark,
primary: accentColor,
onPrimary: _darkBodyColor,
secondary: accentColor,
onSecondary: _darkBodyColor,
onSurface: _darkOnSurface,
).copyWith(
background: Colors.black, background: Colors.black,
); );
final baseTheme = _baseDarkTheme(colors, deviceInitialized); final baseTheme = _baseDarkTheme(colors, deviceInitialized);

View file

@ -45,7 +45,6 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_localization_nn/flutter_localization_nn.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:overlay_support/overlay_support.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:screen_brightness/screen_brightness.dart'; import 'package:screen_brightness/screen_brightness.dart';
@ -151,7 +150,6 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
final List<StreamSubscription> _subscriptions = []; final List<StreamSubscription> _subscriptions = [];
late final Future<void> _appSetup; late final Future<void> _appSetup;
late final Future<bool> _shouldUseBoldFontLoader; late final Future<bool> _shouldUseBoldFontLoader;
late final Future<CorePalette?> _dynamicColorPaletteLoader;
final TvRailController _tvRailController = TvRailController(); final TvRailController _tvRailController = TvRailController();
final CollectionSource _mediaStoreSource = MediaStoreSource(); final CollectionSource _mediaStoreSource = MediaStoreSource();
final Debouncer _mediaStoreChangeDebouncer = Debouncer(delay: ADurations.mediaContentChangeDebounceDelay); final Debouncer _mediaStoreChangeDebouncer = Debouncer(delay: ADurations.mediaContentChangeDebounceDelay);
@ -183,7 +181,6 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
EquatableConfig.stringify = true; EquatableConfig.stringify = true;
_appSetup = _setup(); _appSetup = _setup();
_shouldUseBoldFontLoader = AccessibilityService.shouldUseBoldFont(); _shouldUseBoldFontLoader = AccessibilityService.shouldUseBoldFont();
_dynamicColorPaletteLoader = DynamicColorPlugin.getCorePalette();
_subscriptions.add(_mediaStoreChangeChannel.receiveBroadcastStream().listen((event) => _onMediaStoreChanged(event as String?))); _subscriptions.add(_mediaStoreChangeChannel.receiveBroadcastStream().listen((event) => _onMediaStoreChanged(event as String?)));
_subscriptions.add(_newIntentChannel.receiveBroadcastStream().listen((event) => _onNewIntent(event as Map?))); _subscriptions.add(_newIntentChannel.receiveBroadcastStream().listen((event) => _onNewIntent(event as Map?)));
_subscriptions.add(_analysisCompletionChannel.receiveBroadcastStream().listen((event) => _onAnalysisCompletion())); _subscriptions.add(_analysisCompletionChannel.receiveBroadcastStream().listen((event) => _onAnalysisCompletion()));
@ -246,18 +243,13 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
AStyles.updateStylesForLocale(settings.appliedLocale); AStyles.updateStylesForLocale(settings.appliedLocale);
return FutureBuilder<CorePalette?>( return DynamicColorBuilder(
future: _dynamicColorPaletteLoader, builder: (lightScheme, darkScheme) {
builder: (context, snapshot) {
const defaultAccent = AvesColorsData.defaultAccent; const defaultAccent = AvesColorsData.defaultAccent;
Color lightAccent = defaultAccent, darkAccent = defaultAccent; Color lightAccent = defaultAccent, darkAccent = defaultAccent;
if (enableDynamicColor) { if (enableDynamicColor) {
// `DynamicColorBuilder` from package `dynamic_color` provides light/dark lightAccent = lightScheme?.primary ?? lightAccent;
// palettes with a primary color from tones too dark/light (40/80), darkAccent = darkScheme?.primary ?? darkAccent;
// 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);
} }
final lightTheme = Themes.lightTheme(lightAccent, initialized); final lightTheme = Themes.lightTheme(lightAccent, initialized);
final darkTheme = themeBrightness == AvesThemeBrightness.black ? Themes.blackTheme(darkAccent, initialized) : Themes.darkTheme(darkAccent, initialized); final darkTheme = themeBrightness == AvesThemeBrightness.black ? Themes.blackTheme(darkAccent, initialized) : Themes.darkTheme(darkAccent, initialized);

View file

@ -15,7 +15,7 @@ class AvesCaption extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context); final theme = Theme.of(context);
final subtitleStyle = theme.textTheme.bodySmall!; final subtitleStyle = theme.textTheme.bodySmall!;
final subtitleChangeShadowColor = theme.colorScheme.onPrimary; final subtitleChangeShadowColor = theme.colorScheme.onBackground;
return ChangeHighlightText( return ChangeHighlightText(
// provide key to refresh on theme brightness change // provide key to refresh on theme brightness change
key: ValueKey(subtitleChangeShadowColor), key: ValueKey(subtitleChangeShadowColor),

View file

@ -116,7 +116,7 @@ class _CaptionedButtonState extends State<CaptionedButton> {
return AnimatedDefaultTextStyle( return AnimatedDefaultTextStyle(
style: focused style: focused
? style.copyWith( ? style.copyWith(
color: Theme.of(context).colorScheme.onPrimary, color: Theme.of(context).colorScheme.primary,
) )
: style, : style,
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),

View file

@ -99,12 +99,12 @@ class _ConvertEntryDialogState extends State<ConvertEntryDialog> {
const contentHorizontalPadding = EdgeInsets.symmetric(horizontal: AvesDialog.defaultHorizontalContentPadding); const contentHorizontalPadding = EdgeInsets.symmetric(horizontal: AvesDialog.defaultHorizontalContentPadding);
final colorScheme = Theme.of(context).colorScheme; final colorScheme = Theme.of(context).colorScheme;
final trailingStyle = TextStyle(color: colorScheme.onSurfaceVariant); final trailingStyle = TextStyle(color: colorScheme.onSurfaceVariant);
final trailingChangeShadowColor = colorScheme.onPrimary; final trailingChangeShadowColor = colorScheme.onBackground;
// used by the drop down to match input decoration // used by the drop down to match input decoration
final textFieldDecorationBorder = Border( final textFieldDecorationBorder = Border(
bottom: BorderSide( bottom: BorderSide(
color: colorScheme.onSurface.withOpacity(0.38), //Color(0xFFBDBDBD), color: colorScheme.onSurface.withOpacity(0.38),
width: 1.0, width: 1.0,
), ),
); );

View file

@ -14,6 +14,7 @@ import 'package:aves/theme/icons.dart';
import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/utils/file_utils.dart'; import 'package:aves/utils/file_utils.dart';
import 'package:aves/widgets/about/about_page.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/build_context.dart';
import 'package:aves/widgets/common/extensions/media_query.dart'; import 'package:aves/widgets/common/extensions/media_query.dart';
import 'package:aves/widgets/common/identity/aves_logo.dart'; import 'package:aves/widgets/common/identity/aves_logo.dart';
@ -120,17 +121,21 @@ class _AppDrawerState extends State<AppDrawer> {
)); ));
} }
final colorScheme = Theme.of(context).colorScheme;
final onPrimary = colorScheme.onPrimary;
final drawerButtonStyle = ButtonStyle( final drawerButtonStyle = ButtonStyle(
padding: MaterialStateProperty.all(const EdgeInsetsDirectional.only(start: 12, end: 16)), padding: MaterialStateProperty.all(const EdgeInsetsDirectional.only(start: 12, end: 16)),
); );
return Container( return Container(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), padding: const EdgeInsets.symmetric(horizontal: 16),
color: Theme.of(context).colorScheme.primary, color: colorScheme.primary,
child: SafeArea( child: SafeArea(
bottom: false, bottom: false,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(height: 6),
Align( Align(
alignment: AlignmentDirectional.centerStart, alignment: AlignmentDirectional.centerStart,
child: Wrap( child: Wrap(
@ -138,8 +143,10 @@ class _AppDrawerState extends State<AppDrawer> {
crossAxisAlignment: WrapCrossAlignment.center, crossAxisAlignment: WrapCrossAlignment.center,
children: [ children: [
const AvesLogo(size: 48), const AvesLogo(size: 48),
Text( OutlinedText(
context.l10n.appName, textSpans: [
TextSpan(
text: context.l10n.appName,
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 38, fontSize: 38,
@ -150,14 +157,16 @@ class _AppDrawerState extends State<AppDrawer> {
), ),
], ],
), ),
],
),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
OutlinedButtonTheme( OutlinedButtonTheme(
data: OutlinedButtonThemeData( data: OutlinedButtonThemeData(
style: ButtonStyle( style: ButtonStyle(
foregroundColor: MaterialStateProperty.all<Color>(Colors.white), foregroundColor: MaterialStateProperty.all<Color>(onPrimary),
overlayColor: MaterialStateProperty.all<Color>(Colors.white24), overlayColor: MaterialStateProperty.all<Color>(onPrimary.withOpacity(.12)),
side: MaterialStateProperty.all<BorderSide>(BorderSide(width: 1, color: Colors.white.withOpacity(0.12))), side: MaterialStateProperty.all<BorderSide>(BorderSide(width: 1, color: onPrimary.withOpacity(.24))),
), ),
), ),
child: Wrap( child: Wrap(
@ -181,7 +190,8 @@ class _AppDrawerState extends State<AppDrawer> {
), ),
], ],
), ),
) ),
const SizedBox(height: 8),
], ],
), ),
), ),

View file

@ -195,10 +195,10 @@ class _HistogramState extends State<Histogram> with AutomaticKeepAliveClientMixi
final colorScheme = Theme.of(context).colorScheme; final colorScheme = Theme.of(context).colorScheme;
final accentColor = colorScheme.primary; final accentColor = colorScheme.primary;
final axisColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onPrimary.withOpacity(.9) : Colors.transparent); final axisColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onBackground : Colors.transparent);
final measureLineColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onPrimary.withOpacity(.1) : Colors.transparent); final measureLineColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onBackground.withOpacity(.1) : Colors.transparent);
final histogramLineColor = charts.ColorUtil.fromDartColor(drawLine ? accentColor : Colors.white); 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 histogramPointFillColor = charts.ColorUtil.fromDartColor(colorScheme.background);
final series = [ final series = [

View file

@ -98,6 +98,7 @@ class _MetadataSectionSliverState extends State<MetadataSectionSliver> {
), ),
children: settings.useTvLayout children: settings.useTvLayout
? [ ? [
const SizedBox(height: 16),
AvesOutlinedButton( AvesOutlinedButton(
label: MaterialLocalizations.of(context).moreButtonTooltip, label: MaterialLocalizations.of(context).moreButtonTooltip,
onPressed: () { onPressed: () {

View file

@ -74,7 +74,7 @@ class _XmpCardState extends State<XmpCard> {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all( border: Border.all(
color: Theme.of(context).colorScheme.onPrimary.withOpacity(.2), color: Theme.of(context).dividerColor,
), ),
borderRadius: const BorderRadius.all(Radius.circular(4)), borderRadius: const BorderRadius.all(Radius.circular(4)),
), ),

View file

@ -5,4 +5,9 @@ class ColorUtils {
// when used in gradients or lerping to it // when used in gradients or lerping to it
static const transparentWhite = Color(0x00FFFFFF); static const transparentWhite = Color(0x00FFFFFF);
static const transparentBlack = Color(0x00000000); 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);
}
} }