Material You theming support

This commit is contained in:
Miroslav Mazel
2023-08-25 21:30:53 +02:00
parent 8d3d9e25a0
commit 50807362a1
11 changed files with 155 additions and 59 deletions

View File

@ -14,10 +14,8 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:timecop/data_providers/settings/settings_provider.dart';
import 'package:timecop/models/theme_type.dart';
import 'package:timecop/themes.dart';
part 'theme_event.dart';
part 'theme_state.dart';

View File

@ -19,19 +19,4 @@ class ThemeState extends Equatable {
const ThemeState(this.theme);
@override
List<Object?> get props => [theme];
ThemeData? get themeData {
switch (theme) {
case ThemeType.auto:
return null;
case ThemeType.light:
return ThemeUtil.lightTheme;
case ThemeType.dark:
return ThemeUtil.darkTheme;
case ThemeType.black:
return ThemeUtil.blackTheme;
default:
return null;
}
}
}

View File

@ -15,6 +15,7 @@
import 'dart:async';
import 'dart:io';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
@ -33,6 +34,7 @@ import 'package:timecop/data_providers/notifications/notifications_provider.dart
import 'package:timecop/data_providers/settings/settings_provider.dart';
import 'package:timecop/fontlicenses.dart';
import 'package:timecop/l10n.dart';
import 'package:timecop/models/theme_type.dart';
import 'package:timecop/screens/dashboard/DashboardScreen.dart';
import 'package:timecop/themes.dart';
import 'package:flutter_app_badger/flutter_app_badger.dart';
@ -195,6 +197,46 @@ class _TimeCopAppState extends State<TimeCopApp> with WidgetsBindingObserver {
() => brightness = WidgetsBinding.instance.window.platformBrightness);
}
ThemeData getTheme(
ThemeType? type, ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
if (type == ThemeType.autoMaterialYou) {
if (brightness == Brightness.dark) {
type = ThemeType.darkMaterialYou;
} else {
type = ThemeType.lightMaterialYou;
}
}
switch (type) {
case ThemeType.light:
return ThemeUtil.lightTheme;
case ThemeType.dark:
return ThemeUtil.darkTheme;
case ThemeType.black:
return ThemeUtil.blackTheme;
case ThemeType.lightMaterialYou:
return ThemeUtil.getThemeFromColors(
brightness: Brightness.light,
colors: lightDynamic ?? ThemeUtil.lightColors,
appBarBackground:
lightDynamic?.background ?? ThemeUtil.lightColors.background,
appBarForeground: lightDynamic?.onBackground ??
ThemeUtil.lightColors.onBackground);
case ThemeType.darkMaterialYou:
return ThemeUtil.getThemeFromColors(
brightness: Brightness.dark,
colors: darkDynamic ?? ThemeUtil.darkColors,
appBarBackground:
darkDynamic?.background ?? ThemeUtil.darkColors.background,
appBarForeground:
darkDynamic?.onBackground ?? ThemeUtil.darkColors.onBackground);
case ThemeType.auto:
default:
return brightness == Brightness.dark
? ThemeUtil.darkTheme
: ThemeUtil.lightTheme;
}
}
@override
Widget build(BuildContext context) {
return MultiRepositoryProvider(
@ -205,13 +247,14 @@ class _TimeCopAppState extends State<TimeCopApp> with WidgetsBindingObserver {
builder: (BuildContext context, ThemeState themeState) =>
BlocBuilder<LocaleBloc, LocaleState>(
builder: (BuildContext context, LocaleState localeState) =>
DynamicColorBuilder(
builder: (ColorScheme? lightDynamic,
ColorScheme? darkDynamic) =>
MaterialApp(
title: 'Time Cop',
home: const DashboardScreen(),
theme: themeState.themeData ??
(brightness == Brightness.dark
? ThemeUtil.darkTheme
: ThemeUtil.lightTheme),
theme: getTheme(
themeState.theme, lightDynamic, darkDynamic),
localizationsDelegates: const [
L10N.delegate,
GlobalMaterialLocalizations.delegate,
@ -240,6 +283,6 @@ class _TimeCopAppState extends State<TimeCopApp> with WidgetsBindingObserver {
Locale('zh', 'TW'),
],
),
)));
))));
}
}

View File

@ -15,7 +15,15 @@
import 'package:flutter/cupertino.dart';
import 'package:timecop/l10n.dart';
enum ThemeType { auto, light, dark, black }
enum ThemeType {
auto,
light,
dark,
black,
autoMaterialYou,
lightMaterialYou,
darkMaterialYou
}
ThemeType themeFromString(String? type) {
if (type == null) return ThemeType.auto;
@ -28,12 +36,18 @@ ThemeType themeFromString(String? type) {
return ThemeType.dark;
case "black":
return ThemeType.black;
case "autoMaterialYou":
return ThemeType.autoMaterialYou;
case "lightMaterialYou":
return ThemeType.lightMaterialYou;
case "darkMaterialYou":
return ThemeType.darkMaterialYou;
default:
return ThemeType.auto;
}
}
extension ThemeTypeStr on ThemeType? {
extension ThemeTypeStr on ThemeType {
String? get stringify {
switch (this) {
case ThemeType.auto:
@ -44,8 +58,12 @@ extension ThemeTypeStr on ThemeType? {
return "dark";
case ThemeType.black:
return "black";
default:
return null;
case ThemeType.autoMaterialYou:
return "autoMaterialYou";
case ThemeType.lightMaterialYou:
return "lightMaterialYou";
case ThemeType.darkMaterialYou:
return "darkMaterialYou";
}
}
@ -59,6 +77,12 @@ extension ThemeTypeStr on ThemeType? {
return L10N.of(context).tr.dark;
case ThemeType.black:
return L10N.of(context).tr.black;
case ThemeType.autoMaterialYou:
return L10N.of(context).tr.autoMaterialYou;
case ThemeType.lightMaterialYou:
return L10N.of(context).tr.lightMaterialYou;
case ThemeType.darkMaterialYou:
return L10N.of(context).tr.darkMaterialYou;
default:
return null;
}

View File

@ -31,7 +31,7 @@ class ThemeOptions extends StatelessWidget {
return ListTile(
key: const Key("themeOption"),
title: Text(L10N.of(context).tr.theme),
subtitle: Text(state.theme.display(context)!),
subtitle: Text(state.theme?.display(context) ?? ""),
trailing: Icon(L10N.of(context).rtl
? FontAwesomeIcons.chevronLeft
: FontAwesomeIcons.chevronRight),
@ -75,6 +75,30 @@ class ThemeOptions extends StatelessWidget {
onChanged: (ThemeType? type) =>
Navigator.pop(context, type),
),
RadioListTile<ThemeType>(
key: const Key("themeAutoMaterialYou"),
title: Text(L10N.of(context).tr.autoMaterialYou),
value: ThemeType.autoMaterialYou,
groupValue: state.theme,
onChanged: (ThemeType? type) =>
Navigator.pop(context, type),
),
RadioListTile<ThemeType>(
key: const Key("themeLightMaterialYou"),
title: Text(L10N.of(context).tr.lightMaterialYou),
value: ThemeType.lightMaterialYou,
groupValue: state.theme,
onChanged: (ThemeType? type) =>
Navigator.pop(context, type),
),
RadioListTile<ThemeType>(
key: const Key("themeDarkMaterialYou"),
title: Text(L10N.of(context).tr.darkMaterialYou),
value: ThemeType.darkMaterialYou,
groupValue: state.theme,
onChanged: (ThemeType? type) =>
Navigator.pop(context, type),
),
],
));

View File

@ -6,9 +6,13 @@
#include "generated_plugin_registrant.h"
#include <dynamic_color/dynamic_color_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) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);

View File

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

View File

@ -5,6 +5,7 @@
import FlutterMacOS
import Foundation
import dynamic_color
import flutter_app_badger
import flutter_local_notifications
import package_info_plus
@ -15,6 +16,7 @@ import sqflite
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
FlutterAppBadgerPlugin.register(with: registry.registrar(forPlugin: "FlutterAppBadgerPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))

View File

@ -1,4 +1,6 @@
PODS:
- dynamic_color (0.0.2):
- FlutterMacOS
- flutter_app_badger (1.3.0):
- FlutterMacOS
- flutter_local_notifications (0.0.1):
@ -24,6 +26,7 @@ PODS:
- FlutterMacOS
DEPENDENCIES:
- dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
- flutter_app_badger (from `Flutter/ephemeral/.symlinks/plugins/flutter_app_badger/macos`)
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
@ -39,6 +42,8 @@ SPEC REPOS:
- FMDB
EXTERNAL SOURCES:
dynamic_color:
:path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos
flutter_app_badger:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_app_badger/macos
flutter_local_notifications:
@ -59,6 +64,7 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
SPEC CHECKSUMS:
dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f
flutter_app_badger: 55a64b179f8438e89d574320c77b306e327a1730
flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24

View File

@ -161,6 +161,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.8"
dynamic_color:
dependency: "direct main"
description:
name: dynamic_color
sha256: de4798a7069121aee12d5895315680258415de9b00e717723a1bd73d58f0126d
url: "https://pub.dev"
source: hosted
version: "1.6.6"
effective_dart:
dependency: "direct dev"
description:

View File

@ -44,6 +44,7 @@ dependencies:
xdg_directories: ^1.0.0
fluent: ^2.0.1
permission_handler: ^10.2.0
dynamic_color: ^1.6.6
dependency_overrides:
intl: 0.18.1