Vaani/lib/theme/providers/system_theme_provider.dart

157 lines
4.8 KiB
Dart
Raw Normal View History

import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
2025-03-25 22:01:16 +05:30
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:logging/logging.dart';
import 'package:material_color_utilities/material_color_utilities.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
2026-01-08 17:49:30 +08:00
import 'package:vaani/features/settings/app_settings_provider.dart';
import 'package:vaani/theme/providers/theme_from_cover_provider.dart';
import 'package:vaani/theme/theme.dart';
part 'system_theme_provider.g.dart';
final _logger = Logger('SystemThemeProvider');
/// copied from [DynamicColorBuilder]
@Riverpod(keepAlive: true)
FutureOr<(ColorScheme light, ColorScheme dark)?> systemTheme(
2025-03-25 22:01:16 +05:30
Ref ref, {
bool highContrast = false,
}) async {
_logger.fine('Generating system theme');
ColorScheme? schemeLight;
ColorScheme? schemeDark;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
CorePalette? corePalette = await DynamicColorPlugin.getCorePalette();
if (corePalette != null) {
_logger.fine('dynamic_color: Core palette detected.');
schemeLight = corePalette.toColorScheme(brightness: Brightness.light);
schemeDark = corePalette.toColorScheme(brightness: Brightness.dark);
}
} on PlatformException {
_logger.warning('dynamic_color: Failed to obtain core palette.');
}
if (schemeLight == null || schemeDark == null) {
try {
final Color? accentColor = await DynamicColorPlugin.getAccentColor();
if (accentColor != null) {
_logger.fine('dynamic_color: Accent color detected.');
schemeLight = ColorScheme.fromSeed(
seedColor: accentColor,
brightness: Brightness.light,
);
schemeDark = ColorScheme.fromSeed(
seedColor: accentColor,
brightness: Brightness.dark,
);
}
} on PlatformException {
_logger.warning('dynamic_color: Failed to obtain accent color.');
}
}
if (schemeLight == null || schemeDark == null) {
_logger
.warning('dynamic_color: Dynamic color not detected on this device.');
return null;
}
// set high contrast theme
if (highContrast) {
schemeLight = schemeLight
.copyWith(
surface: Colors.white,
)
.harmonized();
schemeDark = schemeDark
.copyWith(
surface: Colors.black,
)
.harmonized();
}
return (schemeLight, schemeDark);
}
2026-01-08 17:49:30 +08:00
@riverpod
(ThemeData light, ThemeData dark) currentTheme(
Ref ref, {
bool highContrast = false,
String? id,
}) {
final themeSettings =
ref.watch(appSettingsProvider.select((v) => v.themeSettings));
ColorScheme lightColorScheme = brandLightColorScheme;
ColorScheme darkColorScheme = brandDarkColorScheme;
final shouldUseHighContrast = themeSettings.highContrast || highContrast;
if (shouldUseHighContrast) {
lightColorScheme = lightColorScheme.copyWith(
surface: Colors.white,
);
darkColorScheme = darkColorScheme.copyWith(
surface: Colors.black,
);
}
if (themeSettings.useMaterialThemeFromSystem) {
var themes =
ref.watch(systemThemeProvider(highContrast: shouldUseHighContrast));
if (themes.valueOrNull != null) {
lightColorScheme = themes.valueOrNull!.$1;
darkColorScheme = themes.valueOrNull!.$2;
}
}
if (themeSettings.useCurrentPlayerThemeThroughoutApp) {
try {
if (id != null) {
final themeLight = ref.watch(
themeOfLibraryItemProvider(
id,
highContrast: shouldUseHighContrast,
brightness: Brightness.light,
),
);
final themeDark = ref.watch(
themeOfLibraryItemProvider(
id,
highContrast: shouldUseHighContrast,
brightness: Brightness.dark,
),
);
if (themeLight.valueOrNull != null && themeDark.valueOrNull != null) {
lightColorScheme = themeLight.valueOrNull!;
darkColorScheme = themeDark.valueOrNull!;
}
}
} catch (e) {
debugPrintStack(stackTrace: StackTrace.current, label: e.toString());
_logger.severe('not building with player theme');
_logger.severe(e.toString());
}
}
final appThemeLight = ThemeData(
useMaterial3: true,
colorScheme: lightColorScheme.harmonized(),
fontFamily: fontFamilyPlatform,
textTheme: textTheme,
);
final appThemeDark = ThemeData(
useMaterial3: true,
colorScheme: darkColorScheme.harmonized(),
fontFamily: fontFamilyPlatform,
textTheme: textTheme,
brightness: Brightness.dark,
// TODO bottom sheet theme is not working
bottomSheetTheme: BottomSheetThemeData(
backgroundColor: darkColorScheme.surface,
),
);
return (appThemeLight, appThemeDark);
}