feat: integrate dynamic color support and enhance theme settings management

This commit is contained in:
Dr-Blank 2024-10-05 06:05:05 -04:00
parent dc263267be
commit 0437ca110c
No known key found for this signature in database
GPG key ID: 7452CC63F210A266
11 changed files with 225 additions and 30 deletions

View file

@ -1,3 +1,4 @@
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:logging/logging.dart';
@ -51,24 +52,58 @@ class MyApp extends ConsumerWidget {
if (needOnboarding) {
routerConfig.goNamed(Routes.onboarding.name);
}
final appSettings = ref.watch(appSettingsProvider);
try {
return MaterialApp.router(
// debugShowCheckedModeBanner: false,
theme: brandLightTheme,
darkTheme: brandDarkTheme,
themeMode: ref.watch(appSettingsProvider).themeSettings.isDarkMode
? ThemeMode.dark
: ThemeMode.light,
routerConfig: routerConfig,
);
} catch (e) {
debugPrintStack(stackTrace: StackTrace.current, label: e.toString());
if (needOnboarding) {
routerConfig.goNamed(Routes.onboarding.name);
}
return const SizedBox.shrink();
}
final themeSettings = appSettings.themeSettings;
return DynamicColorBuilder(
builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
// Decide on a colour/brightness scheme based on OS and user settings
ColorScheme lightColorScheme;
ColorScheme darkColorScheme;
if (lightDynamic != null &&
darkDynamic != null &&
themeSettings.useMaterialThemeFromSystem) {
lightColorScheme = lightDynamic.harmonized();
darkColorScheme = darkDynamic.harmonized();
} else {
lightColorScheme = brandLightColorScheme;
darkColorScheme = brandDarkColorScheme;
}
// set the background and surface colors to pure black in the amoled theme
if (themeSettings.highContrast) {
darkColorScheme =
darkColorScheme.copyWith(surface: Colors.black).harmonized();
}
final themeLight = ThemeData(
useMaterial3: true,
colorScheme: lightColorScheme,
);
final themeDark = ThemeData(
useMaterial3: true,
colorScheme: darkColorScheme,
brightness: Brightness.dark,
);
try {
return MaterialApp.router(
// debugShowCheckedModeBanner: false,
theme: themeLight,
darkTheme: themeDark,
themeMode:
themeSettings.isDarkMode ? ThemeMode.dark : ThemeMode.light,
routerConfig: routerConfig,
);
} catch (e) {
debugPrintStack(stackTrace: StackTrace.current, label: e.toString());
if (needOnboarding) {
routerConfig.goNamed(Routes.onboarding.name);
}
return const SizedBox.shrink();
}
},
);
}
}

View file

@ -25,10 +25,17 @@ class AppSettings with _$AppSettings {
_$AppSettingsFromJson(json);
}
enum ThemeType { light, dark, system }
@freezed
class ThemeSettings with _$ThemeSettings {
const factory ThemeSettings({
@Default(true) bool isDarkMode,
@Default(ThemeType.system) ThemeType themeType,
@Default(false) bool highContrast,
@Default(true) bool useMaterialThemeFromSystem,
@Default('#FF311B92') String customThemeColor,
@Default(true) bool useMaterialThemeOfPlayingItem,
@Default(true) bool useMaterialThemeOnItemPage,
@Default(true) bool useCurrentPlayerThemeThroughoutApp,
}) = _ThemeSettings;

View file

@ -379,6 +379,11 @@ ThemeSettings _$ThemeSettingsFromJson(Map<String, dynamic> json) {
/// @nodoc
mixin _$ThemeSettings {
bool get isDarkMode => throw _privateConstructorUsedError;
ThemeType get themeType => throw _privateConstructorUsedError;
bool get highContrast => throw _privateConstructorUsedError;
bool get useMaterialThemeFromSystem => throw _privateConstructorUsedError;
String get customThemeColor => throw _privateConstructorUsedError;
bool get useMaterialThemeOfPlayingItem => throw _privateConstructorUsedError;
bool get useMaterialThemeOnItemPage => throw _privateConstructorUsedError;
bool get useCurrentPlayerThemeThroughoutApp =>
throw _privateConstructorUsedError;
@ -401,6 +406,11 @@ abstract class $ThemeSettingsCopyWith<$Res> {
@useResult
$Res call(
{bool isDarkMode,
ThemeType themeType,
bool highContrast,
bool useMaterialThemeFromSystem,
String customThemeColor,
bool useMaterialThemeOfPlayingItem,
bool useMaterialThemeOnItemPage,
bool useCurrentPlayerThemeThroughoutApp});
}
@ -421,6 +431,11 @@ class _$ThemeSettingsCopyWithImpl<$Res, $Val extends ThemeSettings>
@override
$Res call({
Object? isDarkMode = null,
Object? themeType = null,
Object? highContrast = null,
Object? useMaterialThemeFromSystem = null,
Object? customThemeColor = null,
Object? useMaterialThemeOfPlayingItem = null,
Object? useMaterialThemeOnItemPage = null,
Object? useCurrentPlayerThemeThroughoutApp = null,
}) {
@ -429,6 +444,26 @@ class _$ThemeSettingsCopyWithImpl<$Res, $Val extends ThemeSettings>
? _value.isDarkMode
: isDarkMode // ignore: cast_nullable_to_non_nullable
as bool,
themeType: null == themeType
? _value.themeType
: themeType // ignore: cast_nullable_to_non_nullable
as ThemeType,
highContrast: null == highContrast
? _value.highContrast
: highContrast // ignore: cast_nullable_to_non_nullable
as bool,
useMaterialThemeFromSystem: null == useMaterialThemeFromSystem
? _value.useMaterialThemeFromSystem
: useMaterialThemeFromSystem // ignore: cast_nullable_to_non_nullable
as bool,
customThemeColor: null == customThemeColor
? _value.customThemeColor
: customThemeColor // ignore: cast_nullable_to_non_nullable
as String,
useMaterialThemeOfPlayingItem: null == useMaterialThemeOfPlayingItem
? _value.useMaterialThemeOfPlayingItem
: useMaterialThemeOfPlayingItem // ignore: cast_nullable_to_non_nullable
as bool,
useMaterialThemeOnItemPage: null == useMaterialThemeOnItemPage
? _value.useMaterialThemeOnItemPage
: useMaterialThemeOnItemPage // ignore: cast_nullable_to_non_nullable
@ -452,6 +487,11 @@ abstract class _$$ThemeSettingsImplCopyWith<$Res>
@useResult
$Res call(
{bool isDarkMode,
ThemeType themeType,
bool highContrast,
bool useMaterialThemeFromSystem,
String customThemeColor,
bool useMaterialThemeOfPlayingItem,
bool useMaterialThemeOnItemPage,
bool useCurrentPlayerThemeThroughoutApp});
}
@ -470,6 +510,11 @@ class __$$ThemeSettingsImplCopyWithImpl<$Res>
@override
$Res call({
Object? isDarkMode = null,
Object? themeType = null,
Object? highContrast = null,
Object? useMaterialThemeFromSystem = null,
Object? customThemeColor = null,
Object? useMaterialThemeOfPlayingItem = null,
Object? useMaterialThemeOnItemPage = null,
Object? useCurrentPlayerThemeThroughoutApp = null,
}) {
@ -478,6 +523,26 @@ class __$$ThemeSettingsImplCopyWithImpl<$Res>
? _value.isDarkMode
: isDarkMode // ignore: cast_nullable_to_non_nullable
as bool,
themeType: null == themeType
? _value.themeType
: themeType // ignore: cast_nullable_to_non_nullable
as ThemeType,
highContrast: null == highContrast
? _value.highContrast
: highContrast // ignore: cast_nullable_to_non_nullable
as bool,
useMaterialThemeFromSystem: null == useMaterialThemeFromSystem
? _value.useMaterialThemeFromSystem
: useMaterialThemeFromSystem // ignore: cast_nullable_to_non_nullable
as bool,
customThemeColor: null == customThemeColor
? _value.customThemeColor
: customThemeColor // ignore: cast_nullable_to_non_nullable
as String,
useMaterialThemeOfPlayingItem: null == useMaterialThemeOfPlayingItem
? _value.useMaterialThemeOfPlayingItem
: useMaterialThemeOfPlayingItem // ignore: cast_nullable_to_non_nullable
as bool,
useMaterialThemeOnItemPage: null == useMaterialThemeOnItemPage
? _value.useMaterialThemeOnItemPage
: useMaterialThemeOnItemPage // ignore: cast_nullable_to_non_nullable
@ -496,6 +561,11 @@ class __$$ThemeSettingsImplCopyWithImpl<$Res>
class _$ThemeSettingsImpl implements _ThemeSettings {
const _$ThemeSettingsImpl(
{this.isDarkMode = true,
this.themeType = ThemeType.system,
this.highContrast = false,
this.useMaterialThemeFromSystem = true,
this.customThemeColor = '#FF311B92',
this.useMaterialThemeOfPlayingItem = true,
this.useMaterialThemeOnItemPage = true,
this.useCurrentPlayerThemeThroughoutApp = true});
@ -507,6 +577,21 @@ class _$ThemeSettingsImpl implements _ThemeSettings {
final bool isDarkMode;
@override
@JsonKey()
final ThemeType themeType;
@override
@JsonKey()
final bool highContrast;
@override
@JsonKey()
final bool useMaterialThemeFromSystem;
@override
@JsonKey()
final String customThemeColor;
@override
@JsonKey()
final bool useMaterialThemeOfPlayingItem;
@override
@JsonKey()
final bool useMaterialThemeOnItemPage;
@override
@JsonKey()
@ -514,7 +599,7 @@ class _$ThemeSettingsImpl implements _ThemeSettings {
@override
String toString() {
return 'ThemeSettings(isDarkMode: $isDarkMode, useMaterialThemeOnItemPage: $useMaterialThemeOnItemPage, useCurrentPlayerThemeThroughoutApp: $useCurrentPlayerThemeThroughoutApp)';
return 'ThemeSettings(isDarkMode: $isDarkMode, themeType: $themeType, highContrast: $highContrast, useMaterialThemeFromSystem: $useMaterialThemeFromSystem, customThemeColor: $customThemeColor, useMaterialThemeOfPlayingItem: $useMaterialThemeOfPlayingItem, useMaterialThemeOnItemPage: $useMaterialThemeOnItemPage, useCurrentPlayerThemeThroughoutApp: $useCurrentPlayerThemeThroughoutApp)';
}
@override
@ -524,6 +609,20 @@ class _$ThemeSettingsImpl implements _ThemeSettings {
other is _$ThemeSettingsImpl &&
(identical(other.isDarkMode, isDarkMode) ||
other.isDarkMode == isDarkMode) &&
(identical(other.themeType, themeType) ||
other.themeType == themeType) &&
(identical(other.highContrast, highContrast) ||
other.highContrast == highContrast) &&
(identical(other.useMaterialThemeFromSystem,
useMaterialThemeFromSystem) ||
other.useMaterialThemeFromSystem ==
useMaterialThemeFromSystem) &&
(identical(other.customThemeColor, customThemeColor) ||
other.customThemeColor == customThemeColor) &&
(identical(other.useMaterialThemeOfPlayingItem,
useMaterialThemeOfPlayingItem) ||
other.useMaterialThemeOfPlayingItem ==
useMaterialThemeOfPlayingItem) &&
(identical(other.useMaterialThemeOnItemPage,
useMaterialThemeOnItemPage) ||
other.useMaterialThemeOnItemPage ==
@ -536,8 +635,16 @@ class _$ThemeSettingsImpl implements _ThemeSettings {
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, isDarkMode,
useMaterialThemeOnItemPage, useCurrentPlayerThemeThroughoutApp);
int get hashCode => Object.hash(
runtimeType,
isDarkMode,
themeType,
highContrast,
useMaterialThemeFromSystem,
customThemeColor,
useMaterialThemeOfPlayingItem,
useMaterialThemeOnItemPage,
useCurrentPlayerThemeThroughoutApp);
/// Create a copy of ThemeSettings
/// with the given fields replaced by the non-null parameter values.
@ -558,6 +665,11 @@ class _$ThemeSettingsImpl implements _ThemeSettings {
abstract class _ThemeSettings implements ThemeSettings {
const factory _ThemeSettings(
{final bool isDarkMode,
final ThemeType themeType,
final bool highContrast,
final bool useMaterialThemeFromSystem,
final String customThemeColor,
final bool useMaterialThemeOfPlayingItem,
final bool useMaterialThemeOnItemPage,
final bool useCurrentPlayerThemeThroughoutApp}) = _$ThemeSettingsImpl;
@ -567,6 +679,16 @@ abstract class _ThemeSettings implements ThemeSettings {
@override
bool get isDarkMode;
@override
ThemeType get themeType;
@override
bool get highContrast;
@override
bool get useMaterialThemeFromSystem;
@override
String get customThemeColor;
@override
bool get useMaterialThemeOfPlayingItem;
@override
bool get useMaterialThemeOnItemPage;
@override
bool get useCurrentPlayerThemeThroughoutApp;

View file

@ -47,6 +47,14 @@ Map<String, dynamic> _$$AppSettingsImplToJson(_$AppSettingsImpl instance) =>
_$ThemeSettingsImpl _$$ThemeSettingsImplFromJson(Map<String, dynamic> json) =>
_$ThemeSettingsImpl(
isDarkMode: json['isDarkMode'] as bool? ?? true,
themeType: $enumDecodeNullable(_$ThemeTypeEnumMap, json['themeType']) ??
ThemeType.system,
highContrast: json['highContrast'] as bool? ?? false,
useMaterialThemeFromSystem:
json['useMaterialThemeFromSystem'] as bool? ?? true,
customThemeColor: json['customThemeColor'] as String? ?? '#FF311B92',
useMaterialThemeOfPlayingItem:
json['useMaterialThemeOfPlayingItem'] as bool? ?? true,
useMaterialThemeOnItemPage:
json['useMaterialThemeOnItemPage'] as bool? ?? true,
useCurrentPlayerThemeThroughoutApp:
@ -56,11 +64,22 @@ _$ThemeSettingsImpl _$$ThemeSettingsImplFromJson(Map<String, dynamic> json) =>
Map<String, dynamic> _$$ThemeSettingsImplToJson(_$ThemeSettingsImpl instance) =>
<String, dynamic>{
'isDarkMode': instance.isDarkMode,
'themeType': _$ThemeTypeEnumMap[instance.themeType]!,
'highContrast': instance.highContrast,
'useMaterialThemeFromSystem': instance.useMaterialThemeFromSystem,
'customThemeColor': instance.customThemeColor,
'useMaterialThemeOfPlayingItem': instance.useMaterialThemeOfPlayingItem,
'useMaterialThemeOnItemPage': instance.useMaterialThemeOnItemPage,
'useCurrentPlayerThemeThroughoutApp':
instance.useCurrentPlayerThemeThroughoutApp,
};
const _$ThemeTypeEnumMap = {
ThemeType.light: 'light',
ThemeType.dark: 'dark',
ThemeType.system: 'system',
};
_$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map<String, dynamic> json) =>
_$PlayerSettingsImpl(
miniPlayerSettings: json['miniPlayerSettings'] == null

View file

@ -4,18 +4,12 @@ import 'package:flutter/material.dart';
const brandColor = Color(0xFF311B92);
const brandColorLight = Color(0xFF604CEC);
final ThemeData brandLightTheme = ThemeData(
final brandLightColorScheme = ColorScheme.fromSeed(
seedColor: brandColor,
brightness: Brightness.light,
colorScheme: ColorScheme.fromSeed(
seedColor: brandColor,
brightness: Brightness.light,
),
);
final ThemeData brandDarkTheme = ThemeData(
final brandDarkColorScheme = ColorScheme.fromSeed(
seedColor: brandColor,
brightness: Brightness.dark,
colorScheme: ColorScheme.fromSeed(
seedColor: brandColor,
brightness: Brightness.dark,
),
);

View file

@ -6,11 +6,15 @@
#include "generated_plugin_registrant.h"
#include <dynamic_color/dynamic_color_plugin.h>
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) dynamic_color_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin");
dynamic_color_plugin_register_with_registrar(dynamic_color_registrar);
g_autoptr(FlPluginRegistrar) isar_flutter_libs_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin");
isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar);

View file

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
dynamic_color
isar_flutter_libs
media_kit_libs_linux
url_launcher_linux

View file

@ -390,6 +390,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.0"
dynamic_color:
dependency: "direct main"
description:
name: dynamic_color
sha256: eae98052fa6e2826bdac3dd2e921c6ce2903be15c6b7f8b6d8a5d49b5086298d
url: "https://pub.dev"
source: hosted
version: "1.7.0"
easy_stepper:
dependency: "direct main"
description:

View file

@ -44,6 +44,7 @@ dependencies:
cupertino_icons: ^1.0.6
device_info_plus: ^10.1.0
duration_picker: ^1.2.0
dynamic_color: ^1.7.0
easy_stepper: ^0.8.4
file_picker: ^8.1.2
flutter:

View file

@ -6,6 +6,7 @@
#include "generated_plugin_registrant.h"
#include <dynamic_color/dynamic_color_plugin_c_api.h>
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
#include <media_kit_libs_windows_audio/media_kit_libs_windows_audio_plugin_c_api.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
@ -13,6 +14,8 @@
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
DynamicColorPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
IsarFlutterLibsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("IsarFlutterLibsPlugin"));
MediaKitLibsWindowsAudioPluginCApiRegisterWithRegistrar(

View file

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
dynamic_color
isar_flutter_libs
media_kit_libs_windows_audio
permission_handler_windows