#260 optional dynamic accent color
This commit is contained in:
parent
cbc958289c
commit
21f3df8003
22 changed files with 297 additions and 183 deletions
|
@ -32,6 +32,7 @@ class DeviceHandler(private val context: Context) : MethodCallHandler {
|
|||
"canPinShortcut" to ShortcutManagerCompat.isRequestPinShortcutSupported(context),
|
||||
"canPrint" to (sdkInt >= Build.VERSION_CODES.KITKAT),
|
||||
"canRenderFlagEmojis" to (sdkInt >= Build.VERSION_CODES.LOLLIPOP),
|
||||
"isDynamicColorAvailable" to (sdkInt >= Build.VERSION_CODES.S),
|
||||
"showPinShortcutFeedback" to (sdkInt >= Build.VERSION_CODES.O),
|
||||
"supportEdgeToEdgeUIMode" to (sdkInt >= Build.VERSION_CODES.Q),
|
||||
)
|
||||
|
|
|
@ -723,6 +723,7 @@
|
|||
"settingsSectionDisplay": "Display",
|
||||
"settingsThemeBrightness": "Theme",
|
||||
"settingsThemeColorHighlights": "Color highlights",
|
||||
"settingsThemeEnableDynamicColor": "Dynamic color",
|
||||
"settingsDisplayRefreshRateModeTile": "Display refresh rate",
|
||||
"settingsDisplayRefreshRateModeTitle": "Refresh Rate",
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ final Device device = Device._private();
|
|||
class Device {
|
||||
late final String _userAgent;
|
||||
late final bool _canGrantDirectoryAccess, _canPinShortcut, _canPrint, _canRenderFlagEmojis;
|
||||
late final bool _showPinShortcutFeedback, _supportEdgeToEdgeUIMode;
|
||||
late final bool _isDynamicColorAvailable, _showPinShortcutFeedback, _supportEdgeToEdgeUIMode;
|
||||
|
||||
String get userAgent => _userAgent;
|
||||
|
||||
|
@ -18,6 +18,8 @@ class Device {
|
|||
|
||||
bool get canRenderFlagEmojis => _canRenderFlagEmojis;
|
||||
|
||||
bool get isDynamicColorAvailable => _isDynamicColorAvailable;
|
||||
|
||||
bool get showPinShortcutFeedback => _showPinShortcutFeedback;
|
||||
|
||||
bool get supportEdgeToEdgeUIMode => _supportEdgeToEdgeUIMode;
|
||||
|
@ -33,6 +35,7 @@ class Device {
|
|||
_canPinShortcut = capabilities['canPinShortcut'] ?? false;
|
||||
_canPrint = capabilities['canPrint'] ?? false;
|
||||
_canRenderFlagEmojis = capabilities['canRenderFlagEmojis'] ?? false;
|
||||
_isDynamicColorAvailable = capabilities['isDynamicColorAvailable'] ?? false;
|
||||
_showPinShortcutFeedback = capabilities['showPinShortcutFeedback'] ?? false;
|
||||
_supportEdgeToEdgeUIMode = capabilities['supportEdgeToEdgeUIMode'] ?? false;
|
||||
}
|
||||
|
|
|
@ -17,11 +17,15 @@ class SettingsDefaults {
|
|||
static const canUseAnalysisService = true;
|
||||
static const isInstalledAppAccessAllowed = false;
|
||||
static const isErrorReportingAllowed = false;
|
||||
static const tileLayout = TileLayout.grid;
|
||||
static const entryRenamingPattern = '<${DateNamingProcessor.key}, yyyyMMdd-HHmmss> <${NameNamingProcessor.key}>';
|
||||
|
||||
// display
|
||||
static const displayRefreshRateMode = DisplayRefreshRateMode.auto;
|
||||
static const themeBrightness = AvesThemeBrightness.system;
|
||||
static const themeColorMode = AvesThemeColorMode.polychrome;
|
||||
static const tileLayout = TileLayout.grid;
|
||||
static const entryRenamingPattern = '<${DateNamingProcessor.key}, yyyyMMdd-HHmmss> <${NameNamingProcessor.key}>';
|
||||
static const enableDynamicColor = false;
|
||||
static const enableBlurEffect = true; // `enableBlurEffect` has a contextual default value
|
||||
|
||||
// navigation
|
||||
static const mustBackTwiceToExit = true;
|
||||
|
@ -79,7 +83,6 @@ class SettingsDefaults {
|
|||
static const showOverlayInfo = true;
|
||||
static const showOverlayShootingDetails = false;
|
||||
static const showOverlayThumbnailPreview = false;
|
||||
static const enableOverlayBlurEffect = true; // `enableOverlayBlurEffect` has a contextual default value
|
||||
static const viewerUseCutout = true;
|
||||
static const viewerMaxBrightness = false;
|
||||
static const enableMotionPhotoAutoPlay = false;
|
||||
|
|
|
@ -42,15 +42,19 @@ class Settings extends ChangeNotifier {
|
|||
static const isInstalledAppAccessAllowedKey = 'is_installed_app_access_allowed';
|
||||
static const isErrorReportingAllowedKey = 'is_crashlytics_enabled';
|
||||
static const localeKey = 'locale';
|
||||
static const displayRefreshRateModeKey = 'display_refresh_rate_mode';
|
||||
static const themeBrightnessKey = 'theme_brightness';
|
||||
static const themeColorModeKey = 'theme_color_mode';
|
||||
static const catalogTimeZoneKey = 'catalog_time_zone';
|
||||
static const tileExtentPrefixKey = 'tile_extent_';
|
||||
static const tileLayoutPrefixKey = 'tile_layout_';
|
||||
static const entryRenamingPatternKey = 'entry_renaming_pattern';
|
||||
static const topEntryIdsKey = 'top_entry_ids';
|
||||
|
||||
// display
|
||||
static const displayRefreshRateModeKey = 'display_refresh_rate_mode';
|
||||
static const themeBrightnessKey = 'theme_brightness';
|
||||
static const themeColorModeKey = 'theme_color_mode';
|
||||
static const enableDynamicColorKey = 'dynamic_color';
|
||||
static const enableBlurEffectKey = 'enable_overlay_blur_effect';
|
||||
|
||||
// navigation
|
||||
static const mustBackTwiceToExitKey = 'must_back_twice_to_exit';
|
||||
static const keepScreenOnKey = 'keep_screen_on';
|
||||
|
@ -92,7 +96,6 @@ class Settings extends ChangeNotifier {
|
|||
static const showOverlayInfoKey = 'show_overlay_info';
|
||||
static const showOverlayShootingDetailsKey = 'show_overlay_shooting_details';
|
||||
static const showOverlayThumbnailPreviewKey = 'show_overlay_thumbnail_preview';
|
||||
static const enableOverlayBlurEffectKey = 'enable_overlay_blur_effect';
|
||||
static const viewerUseCutoutKey = 'viewer_use_cutout';
|
||||
static const viewerMaxBrightnessKey = 'viewer_max_brightness';
|
||||
static const enableMotionPhotoAutoPlayKey = 'motion_photo_auto_play';
|
||||
|
@ -161,7 +164,7 @@ class Settings extends ChangeNotifier {
|
|||
Future<void> setContextualDefaults() async {
|
||||
// performance
|
||||
final performanceClass = await deviceService.getPerformanceClass();
|
||||
enableOverlayBlurEffect = performanceClass >= 29;
|
||||
enableBlurEffect = performanceClass >= 29;
|
||||
|
||||
// availability
|
||||
final defaultMapStyle = mobileServices.defaultMapStyle;
|
||||
|
@ -249,18 +252,6 @@ class Settings extends ChangeNotifier {
|
|||
return _appliedLocale!;
|
||||
}
|
||||
|
||||
DisplayRefreshRateMode get displayRefreshRateMode => getEnumOrDefault(displayRefreshRateModeKey, SettingsDefaults.displayRefreshRateMode, DisplayRefreshRateMode.values);
|
||||
|
||||
set displayRefreshRateMode(DisplayRefreshRateMode newValue) => setAndNotify(displayRefreshRateModeKey, newValue.toString());
|
||||
|
||||
AvesThemeBrightness get themeBrightness => getEnumOrDefault(themeBrightnessKey, SettingsDefaults.themeBrightness, AvesThemeBrightness.values);
|
||||
|
||||
set themeBrightness(AvesThemeBrightness newValue) => setAndNotify(themeBrightnessKey, newValue.toString());
|
||||
|
||||
AvesThemeColorMode get themeColorMode => getEnumOrDefault(themeColorModeKey, SettingsDefaults.themeColorMode, AvesThemeColorMode.values);
|
||||
|
||||
set themeColorMode(AvesThemeColorMode newValue) => setAndNotify(themeColorModeKey, newValue.toString());
|
||||
|
||||
String get catalogTimeZone => getString(catalogTimeZoneKey) ?? '';
|
||||
|
||||
set catalogTimeZone(String newValue) => setAndNotify(catalogTimeZoneKey, newValue);
|
||||
|
@ -281,6 +272,28 @@ class Settings extends ChangeNotifier {
|
|||
|
||||
set topEntryIds(List<int>? newValue) => setAndNotify(topEntryIdsKey, newValue?.map((id) => id.toString()).whereNotNull().toList());
|
||||
|
||||
// display
|
||||
|
||||
DisplayRefreshRateMode get displayRefreshRateMode => getEnumOrDefault(displayRefreshRateModeKey, SettingsDefaults.displayRefreshRateMode, DisplayRefreshRateMode.values);
|
||||
|
||||
set displayRefreshRateMode(DisplayRefreshRateMode newValue) => setAndNotify(displayRefreshRateModeKey, newValue.toString());
|
||||
|
||||
AvesThemeBrightness get themeBrightness => getEnumOrDefault(themeBrightnessKey, SettingsDefaults.themeBrightness, AvesThemeBrightness.values);
|
||||
|
||||
set themeBrightness(AvesThemeBrightness newValue) => setAndNotify(themeBrightnessKey, newValue.toString());
|
||||
|
||||
AvesThemeColorMode get themeColorMode => getEnumOrDefault(themeColorModeKey, SettingsDefaults.themeColorMode, AvesThemeColorMode.values);
|
||||
|
||||
set themeColorMode(AvesThemeColorMode newValue) => setAndNotify(themeColorModeKey, newValue.toString());
|
||||
|
||||
bool get enableDynamicColor => getBoolOrDefault(enableDynamicColorKey, SettingsDefaults.enableDynamicColor);
|
||||
|
||||
set enableDynamicColor(bool newValue) => setAndNotify(enableDynamicColorKey, newValue);
|
||||
|
||||
bool get enableBlurEffect => getBoolOrDefault(enableBlurEffectKey, SettingsDefaults.enableBlurEffect);
|
||||
|
||||
set enableBlurEffect(bool newValue) => setAndNotify(enableBlurEffectKey, newValue);
|
||||
|
||||
// navigation
|
||||
|
||||
bool get mustBackTwiceToExit => getBoolOrDefault(mustBackTwiceToExitKey, SettingsDefaults.mustBackTwiceToExit);
|
||||
|
@ -441,10 +454,6 @@ class Settings extends ChangeNotifier {
|
|||
|
||||
set showOverlayThumbnailPreview(bool newValue) => setAndNotify(showOverlayThumbnailPreviewKey, newValue);
|
||||
|
||||
bool get enableOverlayBlurEffect => getBoolOrDefault(enableOverlayBlurEffectKey, SettingsDefaults.enableOverlayBlurEffect);
|
||||
|
||||
set enableOverlayBlurEffect(bool newValue) => setAndNotify(enableOverlayBlurEffectKey, newValue);
|
||||
|
||||
bool get viewerUseCutout => getBoolOrDefault(viewerUseCutoutKey, SettingsDefaults.viewerUseCutout);
|
||||
|
||||
set viewerUseCutout(bool newValue) => setAndNotify(viewerUseCutoutKey, newValue);
|
||||
|
@ -695,6 +704,8 @@ class Settings extends ChangeNotifier {
|
|||
break;
|
||||
case isInstalledAppAccessAllowedKey:
|
||||
case isErrorReportingAllowedKey:
|
||||
case enableDynamicColorKey:
|
||||
case enableBlurEffectKey:
|
||||
case showBottomNavigationBarKey:
|
||||
case mustBackTwiceToExitKey:
|
||||
case confirmDeleteForeverKey:
|
||||
|
@ -713,7 +724,6 @@ class Settings extends ChangeNotifier {
|
|||
case showOverlayInfoKey:
|
||||
case showOverlayShootingDetailsKey:
|
||||
case showOverlayThumbnailPreviewKey:
|
||||
case enableOverlayBlurEffectKey:
|
||||
case viewerUseCutoutKey:
|
||||
case viewerMaxBrightnessKey:
|
||||
case enableMotionPhotoAutoPlayKey:
|
||||
|
|
|
@ -7,7 +7,7 @@ import 'package:flutter/services.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
|
||||
class Themes {
|
||||
static const _accentColor = Colors.indigoAccent;
|
||||
static const defaultAccent = Colors.indigoAccent;
|
||||
|
||||
static const _tooltipTheme = TooltipThemeData(
|
||||
verticalOffset: 32,
|
||||
|
@ -19,8 +19,8 @@ class Themes {
|
|||
fontFeatures: [FontFeature.enable('smcp')],
|
||||
);
|
||||
|
||||
static const _snackBarTheme = SnackBarThemeData(
|
||||
actionTextColor: _accentColor,
|
||||
static SnackBarThemeData _snackBarTheme(Color accentColor) => SnackBarThemeData(
|
||||
actionTextColor: accentColor,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
);
|
||||
|
||||
|
@ -35,10 +35,10 @@ class Themes {
|
|||
static const _lightSecondLayer = Color(0xFFF5F5F5); // aka `Colors.grey[100]`
|
||||
static const _lightThirdLayer = Color(0xFFEEEEEE); // aka `Colors.grey[200]`
|
||||
|
||||
static final lightTheme = ThemeData(
|
||||
static ThemeData lightTheme(Color accentColor) => ThemeData(
|
||||
colorScheme: ColorScheme.light(
|
||||
primary: _accentColor,
|
||||
secondary: _accentColor,
|
||||
primary: accentColor,
|
||||
secondary: accentColor,
|
||||
onPrimary: _lightBodyColor,
|
||||
onSecondary: _lightBodyColor,
|
||||
),
|
||||
|
@ -49,8 +49,8 @@ class Themes {
|
|||
// `cardColor` is used by `ExpansionPanel`
|
||||
cardColor: _lightSecondLayer,
|
||||
dialogBackgroundColor: _lightSecondLayer,
|
||||
indicatorColor: _accentColor,
|
||||
toggleableActiveColor: _accentColor,
|
||||
indicatorColor: accentColor,
|
||||
toggleableActiveColor: accentColor,
|
||||
typography: _typography,
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: _lightFirstLayer,
|
||||
|
@ -66,7 +66,7 @@ class Themes {
|
|||
popupMenuTheme: const PopupMenuThemeData(
|
||||
color: _lightSecondLayer,
|
||||
),
|
||||
snackBarTheme: _snackBarTheme,
|
||||
snackBarTheme: _snackBarTheme(accentColor),
|
||||
tabBarTheme: TabBarTheme(
|
||||
labelColor: _lightTitleColor,
|
||||
unselectedLabelColor: Colors.black54,
|
||||
|
@ -87,10 +87,10 @@ class Themes {
|
|||
static const _darkSecondLayer = Color(0xFF363636);
|
||||
static const _darkThirdLayer = Color(0xFF424242); // aka `Colors.grey[800]`
|
||||
|
||||
static final darkTheme = ThemeData(
|
||||
static ThemeData darkTheme(Color accentColor) => ThemeData(
|
||||
colorScheme: ColorScheme.dark(
|
||||
primary: _accentColor,
|
||||
secondary: _accentColor,
|
||||
primary: accentColor,
|
||||
secondary: accentColor,
|
||||
// surface color is used by the date/time pickers
|
||||
surface: Colors.grey.shade800,
|
||||
onPrimary: _darkBodyColor,
|
||||
|
@ -103,8 +103,8 @@ class Themes {
|
|||
// `cardColor` is used by `ExpansionPanel`
|
||||
cardColor: _darkSecondLayer,
|
||||
dialogBackgroundColor: _darkSecondLayer,
|
||||
indicatorColor: _accentColor,
|
||||
toggleableActiveColor: _accentColor,
|
||||
indicatorColor: accentColor,
|
||||
toggleableActiveColor: accentColor,
|
||||
typography: _typography,
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: _darkFirstLayer,
|
||||
|
@ -117,7 +117,7 @@ class Themes {
|
|||
popupMenuTheme: const PopupMenuThemeData(
|
||||
color: _darkSecondLayer,
|
||||
),
|
||||
snackBarTheme: _snackBarTheme.copyWith(
|
||||
snackBarTheme: _snackBarTheme(accentColor).copyWith(
|
||||
backgroundColor: Colors.grey.shade800,
|
||||
contentTextStyle: TextStyle(
|
||||
color: _darkBodyColor,
|
||||
|
@ -138,20 +138,23 @@ class Themes {
|
|||
static const _blackSecondLayer = Color(0xFF212121); // aka `Colors.grey[900]`
|
||||
static const _blackThirdLayer = Color(0xFF303030); // aka `Colors.grey[850]`
|
||||
|
||||
static final blackTheme = darkTheme.copyWith(
|
||||
static ThemeData blackTheme(Color accentColor) {
|
||||
final baseTheme = darkTheme(accentColor);
|
||||
return baseTheme.copyWith(
|
||||
// `canvasColor` is used by `Drawer`, `DropdownButton` and `ExpansionTileCard`
|
||||
canvasColor: _blackSecondLayer,
|
||||
scaffoldBackgroundColor: _blackFirstLayer,
|
||||
// `cardColor` is used by `ExpansionPanel`
|
||||
cardColor: _blackSecondLayer,
|
||||
dialogBackgroundColor: _blackSecondLayer,
|
||||
appBarTheme: darkTheme.appBarTheme.copyWith(
|
||||
appBarTheme: baseTheme.appBarTheme.copyWith(
|
||||
backgroundColor: _blackFirstLayer,
|
||||
),
|
||||
popupMenuTheme: darkTheme.popupMenuTheme.copyWith(
|
||||
popupMenuTheme: baseTheme.popupMenuTheme.copyWith(
|
||||
color: _blackSecondLayer,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Color overlayBackgroundColor({
|
||||
required Brightness brightness,
|
||||
|
|
|
@ -108,6 +108,11 @@ class Constants {
|
|||
licenseUrl: 'https://github.com/fluttercommunity/plus_plugins/blob/main/packages/device_info_plus/device_info_plus/LICENSE',
|
||||
sourceUrl: 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/device_info_plus',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Dynamic Color',
|
||||
license: 'BSD 3-Clause',
|
||||
sourceUrl: 'https://github.com/material-foundation/material-dynamic-color-flutter',
|
||||
),
|
||||
Dependency(
|
||||
name: 'fijkplayer (Aves fork)',
|
||||
license: 'MIT',
|
||||
|
@ -337,6 +342,12 @@ class Constants {
|
|||
license: 'Apache 2.0',
|
||||
sourceUrl: 'https://github.com/jifalops/dart-latlong',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Material Color Utilities',
|
||||
license: 'Apache 2.0',
|
||||
licenseUrl: 'https://github.com/material-foundation/material-color-utilities/tree/main/dart/LICENSE',
|
||||
sourceUrl: 'https://github.com/material-foundation/material-color-utilities/tree/main/dart',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Path',
|
||||
license: 'BSD 3-Clause',
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:aves/app_flavor.dart';
|
|||
import 'package:aves/app_mode.dart';
|
||||
import 'package:aves/l10n/l10n.dart';
|
||||
import 'package:aves/model/device.dart';
|
||||
import 'package:aves/model/settings/defaults.dart';
|
||||
import 'package:aves/model/settings/enums/accessibility_animations.dart';
|
||||
import 'package:aves/model/settings/enums/display_refresh_rate_mode.dart';
|
||||
import 'package:aves/model/settings/enums/enums.dart';
|
||||
|
@ -30,11 +31,13 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
|
|||
import 'package:aves/widgets/common/providers/highlight_info_provider.dart';
|
||||
import 'package:aves/widgets/home_page.dart';
|
||||
import 'package:aves/widgets/welcome_page.dart';
|
||||
import 'package:dynamic_color/dynamic_color.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:fijkplayer/fijkplayer.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:material_color_utilities/material_color_utilities.dart';
|
||||
import 'package:overlay_support/overlay_support.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
@ -70,6 +73,7 @@ class AvesApp extends StatefulWidget {
|
|||
class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
||||
final ValueNotifier<AppMode> appModeNotifier = ValueNotifier(AppMode.main);
|
||||
late Future<void> _appSetup;
|
||||
late Future<CorePalette?> _dynamicColorPaletteLoader;
|
||||
final _mediaStoreSource = MediaStoreSource();
|
||||
final Debouncer _mediaStoreChangeDebouncer = Debouncer(delay: Durations.mediaContentChangeDebounceDelay);
|
||||
final Set<String> changedUris = {};
|
||||
|
@ -89,6 +93,7 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
|||
super.initState();
|
||||
EquatableConfig.stringify = true;
|
||||
_appSetup = _setup();
|
||||
_dynamicColorPaletteLoader = DynamicColorPlugin.getCorePalette();
|
||||
_mediaStoreChangeChannel.receiveBroadcastStream().listen((event) => _onMediaStoreChange(event as String?));
|
||||
_newIntentChannel.receiveBroadcastStream().listen((event) => _onNewIntent(event as Map?));
|
||||
_analysisCompletionChannel.receiveBroadcastStream().listen((event) => _onAnalysisCompletion());
|
||||
|
@ -120,16 +125,18 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
|||
: Scaffold(
|
||||
body: snapshot.hasError ? _buildError(snapshot.error!) : const SizedBox(),
|
||||
);
|
||||
return Selector<Settings, Tuple3<Locale?, bool, AvesThemeBrightness>>(
|
||||
selector: (context, s) => Tuple3(
|
||||
return Selector<Settings, Tuple4<Locale?, bool, AvesThemeBrightness, bool>>(
|
||||
selector: (context, s) => Tuple4(
|
||||
s.locale,
|
||||
s.initialized ? s.accessibilityAnimations.animate : true,
|
||||
s.initialized ? s.themeBrightness : AvesThemeBrightness.system,
|
||||
s.initialized ? s.themeBrightness : SettingsDefaults.themeBrightness,
|
||||
s.initialized ? s.enableDynamicColor : SettingsDefaults.enableDynamicColor,
|
||||
),
|
||||
builder: (context, s, child) {
|
||||
final settingsLocale = s.item1;
|
||||
final areAnimationsEnabled = s.item2;
|
||||
final themeBrightness = s.item3;
|
||||
final enableDynamicColor = s.item4;
|
||||
|
||||
final pageTransitionsTheme = areAnimationsEnabled
|
||||
// Flutter has various page transition implementations for Android:
|
||||
|
@ -144,6 +151,19 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
|||
// strip page transitions used by `MaterialPageRoute`
|
||||
: const DirectPageTransitionsTheme();
|
||||
|
||||
return FutureBuilder<CorePalette?>(
|
||||
future: _dynamicColorPaletteLoader,
|
||||
builder: (context, snapshot) {
|
||||
const defaultAccent = Themes.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);
|
||||
}
|
||||
return MaterialApp(
|
||||
navigatorKey: AvesApp.navigatorKey,
|
||||
home: home,
|
||||
|
@ -157,8 +177,8 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
|||
),
|
||||
),
|
||||
onGenerateTitle: (context) => context.l10n.appName,
|
||||
theme: Themes.lightTheme,
|
||||
darkTheme: themeBrightness == AvesThemeBrightness.black ? Themes.blackTheme : Themes.darkTheme,
|
||||
theme: Themes.lightTheme(lightAccent),
|
||||
darkTheme: themeBrightness == AvesThemeBrightness.black ? Themes.blackTheme(darkAccent) : Themes.darkTheme(darkAccent),
|
||||
themeMode: themeBrightness.appThemeMode,
|
||||
locale: settingsLocale,
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
|
@ -169,6 +189,8 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
|
|||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -206,7 +206,7 @@ class _AvesFloatingBarState extends State<AvesFloatingBar> with RouteAware {
|
|||
return ValueListenableBuilder<bool>(
|
||||
valueListenable: _isBlurAllowedNotifier,
|
||||
builder: (context, isBlurAllowed, child) {
|
||||
final blurred = isBlurAllowed && context.select<Settings, bool>((s) => s.enableOverlayBlurEffect);
|
||||
final blurred = isBlurAllowed && context.select<Settings, bool>((s) => s.enableBlurEffect);
|
||||
return Container(
|
||||
foregroundDecoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
|
|
|
@ -20,7 +20,7 @@ class EmptyContent extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const color = Colors.blueGrey;
|
||||
final color = Theme.of(context).colorScheme.secondary.withOpacity(.5);
|
||||
return Padding(
|
||||
padding: safeBottom
|
||||
? EdgeInsets.only(
|
||||
|
|
|
@ -20,7 +20,7 @@ class MapOverlayButton extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final blurred = settings.enableOverlayBlurEffect;
|
||||
final blurred = settings.enableBlurEffect;
|
||||
return Selector<MapThemeData, Animation<double>>(
|
||||
selector: (context, v) => v.scale,
|
||||
builder: (context, scale, child) => ScaleTransition(
|
||||
|
|
|
@ -57,7 +57,7 @@ class _OverlayCoordinateFilterChipState extends State<OverlayCoordinateFilterChi
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final blurred = settings.enableOverlayBlurEffect;
|
||||
final blurred = settings.enableBlurEffect;
|
||||
final theme = Theme.of(context);
|
||||
return Theme(
|
||||
data: theme.copyWith(
|
||||
|
|
|
@ -129,7 +129,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
spacing: 16,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
const AvesLogo(size: 64),
|
||||
const AvesLogo(size: 56),
|
||||
Text(
|
||||
context.l10n.appName,
|
||||
style: const TextStyle(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:aves/model/device.dart';
|
||||
import 'package:aves/model/settings/enums/display_refresh_rate_mode.dart';
|
||||
import 'package:aves/model/settings/enums/enums.dart';
|
||||
import 'package:aves/model/settings/enums/theme_brightness.dart';
|
||||
|
@ -30,8 +31,9 @@ class DisplaySection extends SettingsSection {
|
|||
FutureOr<List<SettingsTile>> tiles(BuildContext context) => [
|
||||
SettingsTileDisplayThemeBrightness(),
|
||||
SettingsTileDisplayThemeColorMode(),
|
||||
SettingsTileDisplayDisplayRefreshRateMode(),
|
||||
if (device.isDynamicColorAvailable) SettingsTileDisplayEnableDynamicColor(),
|
||||
SettingsTileDisplayEnableBlurEffect(),
|
||||
SettingsTileDisplayDisplayRefreshRateMode(),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -62,6 +64,30 @@ class SettingsTileDisplayThemeColorMode extends SettingsTile {
|
|||
);
|
||||
}
|
||||
|
||||
class SettingsTileDisplayEnableDynamicColor extends SettingsTile {
|
||||
@override
|
||||
String title(BuildContext context) => context.l10n.settingsThemeEnableDynamicColor;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SettingsSwitchListTile(
|
||||
selector: (context, s) => s.enableDynamicColor,
|
||||
onChanged: (v) => settings.enableDynamicColor = v,
|
||||
title: title(context),
|
||||
);
|
||||
}
|
||||
|
||||
class SettingsTileDisplayEnableBlurEffect extends SettingsTile {
|
||||
@override
|
||||
String title(BuildContext context) => context.l10n.settingsViewerEnableOverlayBlurEffect;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SettingsSwitchListTile(
|
||||
selector: (context, s) => s.enableBlurEffect,
|
||||
onChanged: (v) => settings.enableBlurEffect = v,
|
||||
title: title(context),
|
||||
);
|
||||
}
|
||||
|
||||
class SettingsTileDisplayDisplayRefreshRateMode extends SettingsTile {
|
||||
@override
|
||||
String title(BuildContext context) => context.l10n.settingsDisplayRefreshRateModeTile;
|
||||
|
@ -76,15 +102,3 @@ class SettingsTileDisplayDisplayRefreshRateMode extends SettingsTile {
|
|||
dialogTitle: context.l10n.settingsDisplayRefreshRateModeTitle,
|
||||
);
|
||||
}
|
||||
|
||||
class SettingsTileDisplayEnableBlurEffect extends SettingsTile {
|
||||
@override
|
||||
String title(BuildContext context) => context.l10n.settingsViewerEnableOverlayBlurEffect;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SettingsSwitchListTile(
|
||||
selector: (context, s) => s.enableOverlayBlurEffect,
|
||||
onChanged: (v) => settings.enableOverlayBlurEffect = v,
|
||||
title: title(context),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class OverlayButton extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final brightness = Theme.of(context).brightness;
|
||||
final blurred = settings.enableOverlayBlurEffect;
|
||||
final blurred = settings.enableBlurEffect;
|
||||
return ScaleTransition(
|
||||
scale: scale,
|
||||
child: borderRadius != null
|
||||
|
@ -77,7 +77,7 @@ class OverlayTextButton extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final blurred = settings.enableOverlayBlurEffect;
|
||||
final blurred = settings.enableBlurEffect;
|
||||
final theme = Theme.of(context);
|
||||
return SizeTransition(
|
||||
sizeFactor: scale,
|
||||
|
|
|
@ -42,7 +42,7 @@ class ViewerTopOverlay extends StatelessWidget {
|
|||
final viewStateConductor = context.read<ViewStateConductor>();
|
||||
final viewStateNotifier = viewStateConductor.getOrCreateController(pageEntry);
|
||||
|
||||
final blurred = settings.enableOverlayBlurEffect;
|
||||
final blurred = settings.enableBlurEffect;
|
||||
final viewInsetsPadding = (viewInsets ?? EdgeInsets.zero) + (viewPadding ?? EdgeInsets.zero);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
|
|
|
@ -39,7 +39,7 @@ class _VideoProgressBarState extends State<VideoProgressBar> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final blurred = settings.enableOverlayBlurEffect;
|
||||
final blurred = settings.enableBlurEffect;
|
||||
final brightness = Theme.of(context).brightness;
|
||||
final textStyle = TextStyle(
|
||||
shadows: brightness == Brightness.dark ? Constants.embossShadows : null,
|
||||
|
|
|
@ -260,6 +260,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
dynamic_color:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dynamic_color
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
equatable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -589,7 +596,7 @@ packages:
|
|||
source: hosted
|
||||
version: "0.12.11"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
|
|
|
@ -37,6 +37,7 @@ dependencies:
|
|||
country_code:
|
||||
decorated_icon:
|
||||
device_info_plus:
|
||||
dynamic_color:
|
||||
equatable:
|
||||
event_bus:
|
||||
expansion_tile_card:
|
||||
|
@ -56,6 +57,7 @@ dependencies:
|
|||
get_it:
|
||||
intl:
|
||||
latlong2:
|
||||
material_color_utilities:
|
||||
material_design_icons_flutter:
|
||||
overlay_support:
|
||||
package_info_plus:
|
||||
|
|
|
@ -41,7 +41,7 @@ Future<void> configureAndLaunch() async {
|
|||
..showOverlayInfo = true
|
||||
..showOverlayShootingDetails = false
|
||||
..showOverlayThumbnailPreview = false
|
||||
..enableOverlayBlurEffect = true
|
||||
..enableBlurEffect = true
|
||||
..viewerUseCutout = true
|
||||
// info
|
||||
..infoMapStyle = EntryMapStyle.stamenWatercolor
|
||||
|
|
|
@ -29,7 +29,7 @@ Future<void> configureAndLaunch() async {
|
|||
..showOverlayInfo = true
|
||||
..showOverlayShootingDetails = true
|
||||
..showOverlayThumbnailPreview = true
|
||||
..enableOverlayBlurEffect = true
|
||||
..enableBlurEffect = true
|
||||
..imageBackground = EntryBackground.checkered
|
||||
// info
|
||||
..infoMapStyle = EntryMapStyle.googleNormal;
|
||||
|
|
|
@ -1,6 +1,43 @@
|
|||
{
|
||||
"de": [
|
||||
"settingsThemeEnableDynamicColor"
|
||||
],
|
||||
|
||||
"es": [
|
||||
"settingsShowBottomNavigationBar",
|
||||
"settingsThumbnailShowTagIcon"
|
||||
"settingsThumbnailShowTagIcon",
|
||||
"settingsThemeEnableDynamicColor"
|
||||
],
|
||||
|
||||
"fr": [
|
||||
"settingsThemeEnableDynamicColor"
|
||||
],
|
||||
|
||||
"id": [
|
||||
"settingsThemeEnableDynamicColor"
|
||||
],
|
||||
|
||||
"it": [
|
||||
"settingsThemeEnableDynamicColor"
|
||||
],
|
||||
|
||||
"ja": [
|
||||
"settingsThemeEnableDynamicColor"
|
||||
],
|
||||
|
||||
"ko": [
|
||||
"settingsThemeEnableDynamicColor"
|
||||
],
|
||||
|
||||
"pt": [
|
||||
"settingsThemeEnableDynamicColor"
|
||||
],
|
||||
|
||||
"ru": [
|
||||
"settingsThemeEnableDynamicColor"
|
||||
],
|
||||
|
||||
"zh": [
|
||||
"settingsThemeEnableDynamicColor"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue