This commit is contained in:
rang 2026-01-08 17:49:30 +08:00
parent edd5a01482
commit eef72c6aa6
13 changed files with 1341 additions and 1012 deletions

View file

@ -1,6 +1,5 @@
import 'dart:math';
import 'package:animated_theme_switcher/animated_theme_switcher.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
@ -8,9 +7,11 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/api/library_item_provider.dart';
import 'package:vaani/features/item_viewer/view/library_item_sliver_app_bar.dart';
import 'package:vaani/features/player/view/mini_player_bottom_padding.dart';
import 'package:vaani/features/settings/app_settings_provider.dart';
import 'package:vaani/generated/l10n.dart';
import 'package:vaani/router/models/library_item_extras.dart';
import 'package:vaani/shared/widgets/expandable_description.dart';
import 'package:vaani/theme/providers/system_theme_provider.dart';
import 'library_item_actions.dart';
import 'library_item_hero_section.dart';
@ -32,6 +33,23 @@ class LibraryItemPage extends HookConsumerWidget {
extra is LibraryItemExtras ? extra as LibraryItemExtras : null;
final scrollController = useScrollController();
final showFab = useState(false);
final themeSettings =
ref.watch(appSettingsProvider.select((v) => v.themeSettings));
var currentTheme = Theme.of(context);
if (themeSettings.useMaterialThemeOnItemPage) {
final theme = ref.watch(
CurrentThemeProvider(
highContrast: MediaQuery.of(context).highContrast,
id: itemId,
),
);
if (currentTheme.brightness == Brightness.dark) {
currentTheme = theme.$2;
} else {
currentTheme = theme.$1;
}
}
// Effect to listen to scroll changes and update FAB visibility
useEffect(
@ -72,10 +90,8 @@ class LibraryItemPage extends HookConsumerWidget {
}
}
return ThemeProvider(
initTheme: Theme.of(context),
duration: 200.ms,
child: ThemeSwitchingArea(
return Theme(
data: currentTheme,
child: Scaffold(
floatingActionButton: AnimatedSwitcher(
duration: 250.ms,
@ -132,7 +148,6 @@ class LibraryItemPage extends HookConsumerWidget {
],
),
),
),
);
}
}

View file

@ -2,6 +2,7 @@ import 'dart:math';
import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shelfsdk/audiobookshelf_api.dart';
import 'package:vaani/constants/sizes.dart';
@ -29,6 +30,7 @@ class PlayerExpandedDesktop extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// final textTheme = Theme.of(context).textTheme;
final book = ref.watch(currentBookProvider);
if (book == null) {
return SizedBox.shrink();
@ -116,7 +118,16 @@ class PlayerExpandedDesktop extends HookConsumerWidget {
timeLabelLocation: TimeLabelLocation.sides,
),
),
Container(child: _buildBottom()),
MouseRegion(
cursor: SystemMouseCursors.click, //
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
context.pop();
},
child: _buildBottom(),
),
),
],
),
],
@ -125,11 +136,15 @@ class PlayerExpandedDesktop extends HookConsumerWidget {
Widget _buildBottom() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
// mainAxisAlignment: MainAxisAlignment.center,
children: [
Spacer(),
Expanded(
flex: 1,
child: Row(),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const AudiobookPlayerSeekChapterButton(isForward: false),
const AudiobookPlayerSeekButton(isForward: false),
@ -141,6 +156,7 @@ class PlayerExpandedDesktop extends HookConsumerWidget {
),
),
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [

View file

@ -6,12 +6,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_settings_ui/flutter_settings_ui.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/generated/l10n.dart';
import 'package:vaani/features/settings/app_settings_provider.dart';
import 'package:vaani/features/settings/view/buttons.dart';
import 'package:vaani/features/settings/view/simple_settings_page.dart';
import 'package:vaani/generated/l10n.dart';
import 'package:vaani/globals.dart';
import 'package:vaani/shared/extensions/duration_format.dart';
class DownloadSettingsPage extends HookConsumerWidget {
const DownloadSettingsPage({
@ -22,7 +21,7 @@ class DownloadSettingsPage extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final appSettings = ref.watch(appSettingsProvider);
final downloadSettings = appSettings.downloadSettings;
final primaryColor = Theme.of(context).colorScheme.primary;
// final primaryColor = Theme.of(context).colorScheme.primary;
return SimpleSettingsPage(
title: Text(S.of(context).playerSettings),

View file

@ -91,7 +91,7 @@ class PlayerSettingsPage extends HookConsumerWidget {
if (newSpeedOptions != null) {
ref.read(appSettingsProvider.notifier).update(
appSettings.copyWith.playerSettings(
speedOptions: newSpeedOptions..sort(),
speedOptions: [...newSpeedOptions]..sort(),
),
);
}

View file

@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_settings_ui/flutter_settings_ui.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:vaani/features/player/view/mini_player_bottom_padding.dart';
class SimpleSettingsPage extends HookConsumerWidget {
const SimpleSettingsPage({
@ -15,30 +14,43 @@ class SimpleSettingsPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final colorScheme = Theme.of(context).colorScheme;
return Scaffold(
// appBar: AppBar(
// title: title,
// ),
appBar: AppBar(
title: title,
),
// body: body,
// an app bar which is bigger than the default app bar but on scroll shrinks to the default app bar with the title being animated
body: CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: 200.0,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
title: title,
// background: Theme.of(context).primaryColor,
),
),
// SliverAppBar(
// expandedHeight: 100.0,
// floating: false,
// pinned: true,
// flexibleSpace: FlexibleSpaceBar(
// title: title,
// // background: Theme.of(context).primaryColor,
// ),
// ),
if (sections != null)
SliverList(
delegate: SliverChildListDelegate(
[
ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(20)),
// borderRadius: const BorderRadius.all(Radius.circular(20)),
child: SettingsList(
lightTheme: SettingsThemeData(
settingsListBackground: colorScheme.surface,
settingsSectionBackground: colorScheme.surfaceContainer,
// inactiveTitleColor:
// trailingTextColor: colorScheme.primary,
// settingsTileTextColor:
),
darkTheme: SettingsThemeData(
settingsListBackground: colorScheme.surface,
settingsSectionBackground: colorScheme.surfaceContainer,
),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
sections: sections!,
@ -48,7 +60,7 @@ class SimpleSettingsPage extends HookConsumerWidget {
),
),
// some padding at the bottom
const SliverPadding(padding: EdgeInsets.only(bottom: 20)),
// const SliverPadding(padding: EdgeInsets.only(bottom: 20)),
// SliverToBoxAdapter(child: MiniPlayerBottomPadding()),
],
),

View file

@ -54,10 +54,8 @@ class MessageLookup extends MessageLookupByLibrary {
"accountDeleteServer": MessageLookupByLibrary.simpleMessage(
"Delete Server",
),
"accountInvalidURL":
MessageLookupByLibrary.simpleMessage("Invalid URL"),
"accountManage":
MessageLookupByLibrary.simpleMessage("Manage Accounts"),
"accountInvalidURL": MessageLookupByLibrary.simpleMessage("Invalid URL"),
"accountManage": MessageLookupByLibrary.simpleMessage("Manage Accounts"),
"accountRegisteredServers": MessageLookupByLibrary.simpleMessage(
"Registered Servers",
),
@ -96,8 +94,7 @@ class MessageLookup extends MessageLookupByLibrary {
"autoTurnOnTimerAlways": MessageLookupByLibrary.simpleMessage(
"Always Auto Turn On Timer",
),
"autoTurnOnTimerAlwaysDescription":
MessageLookupByLibrary.simpleMessage(
"autoTurnOnTimerAlwaysDescription": MessageLookupByLibrary.simpleMessage(
"Always turn on the sleep timer, no matter what",
),
"autoTurnOnTimerDescription": MessageLookupByLibrary.simpleMessage(
@ -125,11 +122,9 @@ class MessageLookup extends MessageLookupByLibrary {
"bookAuthors": MessageLookupByLibrary.simpleMessage("Authors"),
"bookDownloads": MessageLookupByLibrary.simpleMessage("Downloads"),
"bookGenres": MessageLookupByLibrary.simpleMessage("Genres"),
"bookMetadataAbridged":
MessageLookupByLibrary.simpleMessage("Abridged"),
"bookMetadataAbridged": MessageLookupByLibrary.simpleMessage("Abridged"),
"bookMetadataLength": MessageLookupByLibrary.simpleMessage("Length"),
"bookMetadataPublished":
MessageLookupByLibrary.simpleMessage("Published"),
"bookMetadataPublished": MessageLookupByLibrary.simpleMessage("Published"),
"bookMetadataUnabridged": MessageLookupByLibrary.simpleMessage(
"Unabridged",
),
@ -173,12 +168,10 @@ class MessageLookup extends MessageLookupByLibrary {
"erDragText": MessageLookupByLibrary.simpleMessage("Pull to refresh"),
"erDragTextUp": MessageLookupByLibrary.simpleMessage("Pull to refresh"),
"erFailedText": MessageLookupByLibrary.simpleMessage("Failed"),
"erMessageText":
MessageLookupByLibrary.simpleMessage("Last updated at %T"),
"erMessageText": MessageLookupByLibrary.simpleMessage("Last updated at %T"),
"erNoMoreText": MessageLookupByLibrary.simpleMessage("No more"),
"erProcessedText": MessageLookupByLibrary.simpleMessage("Succeeded"),
"erProcessingText":
MessageLookupByLibrary.simpleMessage("Refreshing..."),
"erProcessingText": MessageLookupByLibrary.simpleMessage("Refreshing..."),
"erReadyText": MessageLookupByLibrary.simpleMessage("Refreshing..."),
"explore": MessageLookupByLibrary.simpleMessage("explore"),
"exploreHint": MessageLookupByLibrary.simpleMessage(
@ -200,13 +193,11 @@ class MessageLookup extends MessageLookupByLibrary {
"homeBookContinueSeries": MessageLookupByLibrary.simpleMessage(
"Continue Series",
),
"homeBookContinueSeriesDescription":
MessageLookupByLibrary.simpleMessage(
"homeBookContinueSeriesDescription": MessageLookupByLibrary.simpleMessage(
"Show play button for books in continue series shelf",
),
"homeBookDiscover": MessageLookupByLibrary.simpleMessage("Discover"),
"homeBookListenAgain":
MessageLookupByLibrary.simpleMessage("Listen Again"),
"homeBookListenAgain": MessageLookupByLibrary.simpleMessage("Listen Again"),
"homeBookListenAgainDescription": MessageLookupByLibrary.simpleMessage(
"Show play button for all books in listen again shelf",
),
@ -216,8 +207,7 @@ class MessageLookup extends MessageLookupByLibrary {
"homeBookRecentlyAdded": MessageLookupByLibrary.simpleMessage(
"Recently Added",
),
"homeBookRecommended":
MessageLookupByLibrary.simpleMessage("Recommended"),
"homeBookRecommended": MessageLookupByLibrary.simpleMessage("Recommended"),
"homeContinueListening": MessageLookupByLibrary.simpleMessage(
"Continue Listening",
),
@ -290,8 +280,7 @@ class MessageLookup extends MessageLookupByLibrary {
"nmpSettingsMediaControls": MessageLookupByLibrary.simpleMessage(
"Media Controls",
),
"nmpSettingsMediaControlsDescription":
MessageLookupByLibrary.simpleMessage(
"nmpSettingsMediaControlsDescription": MessageLookupByLibrary.simpleMessage(
"Select the media controls to display",
),
"nmpSettingsSelectOne": MessageLookupByLibrary.simpleMessage(
@ -310,32 +299,27 @@ class MessageLookup extends MessageLookupByLibrary {
"nmpSettingsSubTitleDescription": MessageLookupByLibrary.simpleMessage(
"The subtitle of the notification\n",
),
"nmpSettingsTitle":
MessageLookupByLibrary.simpleMessage("Primary Title"),
"nmpSettingsTitle": MessageLookupByLibrary.simpleMessage("Primary Title"),
"nmpSettingsTitleDescription": MessageLookupByLibrary.simpleMessage(
"The title of the notification\n",
),
"no": MessageLookupByLibrary.simpleMessage("No"),
"notImplemented":
MessageLookupByLibrary.simpleMessage("Not implemented"),
"notImplemented": MessageLookupByLibrary.simpleMessage("Not implemented"),
"notificationMediaPlayer": MessageLookupByLibrary.simpleMessage(
"Notification Media Player",
),
"notificationMediaPlayerDescription":
MessageLookupByLibrary.simpleMessage(
"notificationMediaPlayerDescription": MessageLookupByLibrary.simpleMessage(
"Customize the media player in notifications",
),
"ok": MessageLookupByLibrary.simpleMessage("OK"),
"pause": MessageLookupByLibrary.simpleMessage("Pause"),
"play": MessageLookupByLibrary.simpleMessage("Play"),
"playerSettings":
MessageLookupByLibrary.simpleMessage("Player Settings"),
"playerSettings": MessageLookupByLibrary.simpleMessage("Player Settings"),
"playerSettingsCompleteTime": MessageLookupByLibrary.simpleMessage(
"Mark Complete When Time Left",
),
"playerSettingsCompleteTimeDescriptionHead":
MessageLookupByLibrary.simpleMessage(
"Mark complete when less than "),
MessageLookupByLibrary.simpleMessage("Mark complete when less than "),
"playerSettingsCompleteTimeDescriptionTail":
MessageLookupByLibrary.simpleMessage(" left in the book"),
"playerSettingsDescription": MessageLookupByLibrary.simpleMessage(
@ -350,8 +334,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage(
"Show the progress of the current chapter in the player",
),
"playerSettingsDisplayTotalProgress":
MessageLookupByLibrary.simpleMessage(
"playerSettingsDisplayTotalProgress": MessageLookupByLibrary.simpleMessage(
"Show Total Progress",
),
"playerSettingsDisplayTotalProgressDescription":
@ -380,8 +363,7 @@ class MessageLookup extends MessageLookupByLibrary {
),
"playerSettingsPlaybackReportingMinimumDescriptionTail":
MessageLookupByLibrary.simpleMessage("of the book"),
"playerSettingsRememberForEveryBook":
MessageLookupByLibrary.simpleMessage(
"playerSettingsRememberForEveryBook": MessageLookupByLibrary.simpleMessage(
"Remember Player Settings for Every Book",
),
"playerSettingsRememberForEveryBookDescription":
@ -395,17 +377,14 @@ class MessageLookup extends MessageLookupByLibrary {
"playerSettingsSpeedOptions": MessageLookupByLibrary.simpleMessage(
"Speed Options",
),
"playerSettingsSpeedOptionsSelect":
MessageLookupByLibrary.simpleMessage(
"playerSettingsSpeedOptionsSelect": MessageLookupByLibrary.simpleMessage(
"Select Speed Options",
),
"playerSettingsSpeedOptionsSelectAdd":
MessageLookupByLibrary.simpleMessage(
"playerSettingsSpeedOptionsSelectAdd": MessageLookupByLibrary.simpleMessage(
"Add Speed Option",
),
"playerSettingsSpeedOptionsSelectAddHelper":
MessageLookupByLibrary.simpleMessage(
"Enter a new speed option to add"),
MessageLookupByLibrary.simpleMessage("Enter a new speed option to add"),
"playerSettingsSpeedSelect": MessageLookupByLibrary.simpleMessage(
"Select Speed",
),
@ -453,8 +432,7 @@ class MessageLookup extends MessageLookupByLibrary {
"shakeActivationThreshold": MessageLookupByLibrary.simpleMessage(
"Shake Activation Threshold",
),
"shakeActivationThresholdDescription":
MessageLookupByLibrary.simpleMessage(
"shakeActivationThresholdDescription": MessageLookupByLibrary.simpleMessage(
"The higher the threshold, the harder you need to shake",
),
"shakeDetector": MessageLookupByLibrary.simpleMessage("Shake Detector"),
@ -492,8 +470,7 @@ class MessageLookup extends MessageLookupByLibrary {
"themeModeHighContrast": MessageLookupByLibrary.simpleMessage(
"High Contrast Mode",
),
"themeModeHighContrastDescription":
MessageLookupByLibrary.simpleMessage(
"themeModeHighContrastDescription": MessageLookupByLibrary.simpleMessage(
"Increase the contrast between the background and the text",
),
"themeModeLight": MessageLookupByLibrary.simpleMessage("Light"),
@ -508,8 +485,7 @@ class MessageLookup extends MessageLookupByLibrary {
"themeSettingsColorsBook": MessageLookupByLibrary.simpleMessage(
"Adaptive Theme on Item Page",
),
"themeSettingsColorsBookDescription":
MessageLookupByLibrary.simpleMessage(
"themeSettingsColorsBookDescription": MessageLookupByLibrary.simpleMessage(
"Get fancy with the colors on the item page at the cost of some performance",
),
"themeSettingsColorsCurrent": MessageLookupByLibrary.simpleMessage(

View file

@ -50,8 +50,7 @@ class MessageLookup extends MessageLookupByLibrary {
"accountDeleteServer": MessageLookupByLibrary.simpleMessage("删除服务器"),
"accountInvalidURL": MessageLookupByLibrary.simpleMessage("无效网址"),
"accountManage": MessageLookupByLibrary.simpleMessage("帐户管理"),
"accountRegisteredServers":
MessageLookupByLibrary.simpleMessage("已注册服务器"),
"accountRegisteredServers": MessageLookupByLibrary.simpleMessage("已注册服务器"),
"accountRemoveServerAndUsers": MessageLookupByLibrary.simpleMessage(
"删除服务器和用户",
),
@ -61,8 +60,7 @@ class MessageLookup extends MessageLookupByLibrary {
"accountRemoveServerAndUsersTail": MessageLookupByLibrary.simpleMessage(
" 以及该应用程序中所有用户的登录信息。",
),
"accountRemoveUserLogin":
MessageLookupByLibrary.simpleMessage("删除用户登录"),
"accountRemoveUserLogin": MessageLookupByLibrary.simpleMessage("删除用户登录"),
"accountRemoveUserLoginHead": MessageLookupByLibrary.simpleMessage(
"这将删除用户 ",
),
@ -74,15 +72,11 @@ class MessageLookup extends MessageLookupByLibrary {
"accountUsersCount": m1,
"appSettings": MessageLookupByLibrary.simpleMessage("应用设置"),
"appearance": MessageLookupByLibrary.simpleMessage("外观"),
"autoSleepTimerSettings":
MessageLookupByLibrary.simpleMessage("自动睡眠定时器设置"),
"autoTurnOnSleepTimer":
MessageLookupByLibrary.simpleMessage("自动开启睡眠定时器"),
"autoSleepTimerSettings": MessageLookupByLibrary.simpleMessage("自动睡眠定时器设置"),
"autoTurnOnSleepTimer": MessageLookupByLibrary.simpleMessage("自动开启睡眠定时器"),
"autoTurnOnTimer": MessageLookupByLibrary.simpleMessage("自动开启定时器"),
"autoTurnOnTimerAlways":
MessageLookupByLibrary.simpleMessage("始终自动开启定时器"),
"autoTurnOnTimerAlwaysDescription":
MessageLookupByLibrary.simpleMessage(
"autoTurnOnTimerAlways": MessageLookupByLibrary.simpleMessage("始终自动开启定时器"),
"autoTurnOnTimerAlwaysDescription": MessageLookupByLibrary.simpleMessage(
"总是打开睡眠定时器",
),
"autoTurnOnTimerDescription": MessageLookupByLibrary.simpleMessage(
@ -124,8 +118,7 @@ class MessageLookup extends MessageLookupByLibrary {
"copyToClipboardDescription": MessageLookupByLibrary.simpleMessage(
"将应用程序设置复制到剪贴板",
),
"copyToClipboardToast":
MessageLookupByLibrary.simpleMessage("设置已复制到剪贴板"),
"copyToClipboardToast": MessageLookupByLibrary.simpleMessage("设置已复制到剪贴板"),
"delete": MessageLookupByLibrary.simpleMessage("删除"),
"deleteDialog": m2,
"deleted": m3,
@ -148,13 +141,11 @@ class MessageLookup extends MessageLookupByLibrary {
"general": MessageLookupByLibrary.simpleMessage("通用"),
"help": MessageLookupByLibrary.simpleMessage("Help"),
"home": MessageLookupByLibrary.simpleMessage("首页"),
"homeBookContinueListening":
MessageLookupByLibrary.simpleMessage("继续收听"),
"homeBookContinueListening": MessageLookupByLibrary.simpleMessage("继续收听"),
"homeBookContinueListeningDescription":
MessageLookupByLibrary.simpleMessage("继续收听书架上显示播放按钮"),
"homeBookContinueSeries": MessageLookupByLibrary.simpleMessage("继续系列"),
"homeBookContinueSeriesDescription":
MessageLookupByLibrary.simpleMessage(
"homeBookContinueSeriesDescription": MessageLookupByLibrary.simpleMessage(
"继续系列书架上显示播放按钮",
),
"homeBookDiscover": MessageLookupByLibrary.simpleMessage("发现"),
@ -176,8 +167,7 @@ class MessageLookup extends MessageLookupByLibrary {
),
"homePageSettingsOtherShelvesDescription":
MessageLookupByLibrary.simpleMessage("显示所有剩余书架上所有书籍的播放按钮"),
"homePageSettingsQuickPlay":
MessageLookupByLibrary.simpleMessage("继续播放"),
"homePageSettingsQuickPlay": MessageLookupByLibrary.simpleMessage("继续播放"),
"homeStartListening": MessageLookupByLibrary.simpleMessage("开始收听"),
"language": MessageLookupByLibrary.simpleMessage("语言"),
"languageDescription": MessageLookupByLibrary.simpleMessage("语言切换"),
@ -194,8 +184,7 @@ class MessageLookup extends MessageLookupByLibrary {
"loginOpenID": MessageLookupByLibrary.simpleMessage("OpenID"),
"loginPassword": MessageLookupByLibrary.simpleMessage("密码"),
"loginServerClick": MessageLookupByLibrary.simpleMessage("单击此处"),
"loginServerConnected":
MessageLookupByLibrary.simpleMessage("服务器已连接,请登录"),
"loginServerConnected": MessageLookupByLibrary.simpleMessage("服务器已连接,请登录"),
"loginServerNo": MessageLookupByLibrary.simpleMessage("没有服务器? "),
"loginServerNoConnected": MessageLookupByLibrary.simpleMessage(
"请输入您的AudiobookShelf服务器的URL",
@ -208,10 +197,8 @@ class MessageLookup extends MessageLookupByLibrary {
"logs": MessageLookupByLibrary.simpleMessage("日志"),
"nmpSettingsBackward": MessageLookupByLibrary.simpleMessage("快退间隔"),
"nmpSettingsForward": MessageLookupByLibrary.simpleMessage("快进间隔"),
"nmpSettingsMediaControls":
MessageLookupByLibrary.simpleMessage("媒体控制"),
"nmpSettingsMediaControlsDescription":
MessageLookupByLibrary.simpleMessage(
"nmpSettingsMediaControls": MessageLookupByLibrary.simpleMessage("媒体控制"),
"nmpSettingsMediaControlsDescription": MessageLookupByLibrary.simpleMessage(
"选择要显示的媒体控件",
),
"nmpSettingsSelectOne": MessageLookupByLibrary.simpleMessage(
@ -232,10 +219,8 @@ class MessageLookup extends MessageLookupByLibrary {
),
"no": MessageLookupByLibrary.simpleMessage(""),
"notImplemented": MessageLookupByLibrary.simpleMessage("未实现"),
"notificationMediaPlayer":
MessageLookupByLibrary.simpleMessage("通知媒体播放器"),
"notificationMediaPlayerDescription":
MessageLookupByLibrary.simpleMessage(
"notificationMediaPlayer": MessageLookupByLibrary.simpleMessage("通知媒体播放器"),
"notificationMediaPlayerDescription": MessageLookupByLibrary.simpleMessage(
"在通知中自定义媒体播放器",
),
"ok": MessageLookupByLibrary.simpleMessage("确定"),
@ -257,8 +242,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("显示章节进度"),
"playerSettingsDisplayChapterProgressDescription":
MessageLookupByLibrary.simpleMessage("在播放器中显示当前章节的进度"),
"playerSettingsDisplayTotalProgress":
MessageLookupByLibrary.simpleMessage(
"playerSettingsDisplayTotalProgress": MessageLookupByLibrary.simpleMessage(
"显示总进度",
),
"playerSettingsDisplayTotalProgressDescription":
@ -281,8 +265,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("不要报告本书前 "),
"playerSettingsPlaybackReportingMinimumDescriptionTail":
MessageLookupByLibrary.simpleMessage(" 的播放"),
"playerSettingsRememberForEveryBook":
MessageLookupByLibrary.simpleMessage(
"playerSettingsRememberForEveryBook": MessageLookupByLibrary.simpleMessage(
"记住每本书的播放器设置",
),
"playerSettingsRememberForEveryBookDescription":
@ -294,18 +277,15 @@ class MessageLookup extends MessageLookupByLibrary {
"playerSettingsSpeedOptions": MessageLookupByLibrary.simpleMessage(
"播放速度选项",
),
"playerSettingsSpeedOptionsSelect":
MessageLookupByLibrary.simpleMessage(
"playerSettingsSpeedOptionsSelect": MessageLookupByLibrary.simpleMessage(
"播放速度选项",
),
"playerSettingsSpeedOptionsSelectAdd":
MessageLookupByLibrary.simpleMessage(
"playerSettingsSpeedOptionsSelectAdd": MessageLookupByLibrary.simpleMessage(
"添加一个速度选项",
),
"playerSettingsSpeedOptionsSelectAddHelper":
MessageLookupByLibrary.simpleMessage("输入一个新的速度选项"),
"playerSettingsSpeedSelect":
MessageLookupByLibrary.simpleMessage("选择播放速度"),
"playerSettingsSpeedSelect": MessageLookupByLibrary.simpleMessage("选择播放速度"),
"playerSettingsSpeedSelectHelper": MessageLookupByLibrary.simpleMessage(
"输入默认的播放速度",
),
@ -326,10 +306,8 @@ class MessageLookup extends MessageLookupByLibrary {
"restoreBackupHint": MessageLookupByLibrary.simpleMessage("将备份粘贴到此处"),
"restoreBackupInvalid": MessageLookupByLibrary.simpleMessage("无效备份"),
"restoreBackupSuccess": MessageLookupByLibrary.simpleMessage("设置已恢复"),
"restoreBackupValidator":
MessageLookupByLibrary.simpleMessage("请将备份粘贴到此处"),
"restoreDescription":
MessageLookupByLibrary.simpleMessage("从备份中还原应用程序设置"),
"restoreBackupValidator": MessageLookupByLibrary.simpleMessage("请将备份粘贴到此处"),
"restoreDescription": MessageLookupByLibrary.simpleMessage("从备份中还原应用程序设置"),
"resume": MessageLookupByLibrary.simpleMessage("继续"),
"retry": MessageLookupByLibrary.simpleMessage("重试"),
"settings": MessageLookupByLibrary.simpleMessage("设置"),
@ -337,10 +315,8 @@ class MessageLookup extends MessageLookupByLibrary {
"shakeActionDescription": MessageLookupByLibrary.simpleMessage(
"检测到抖动时要执行的操作",
),
"shakeActivationThreshold":
MessageLookupByLibrary.simpleMessage("抖动激活阈值"),
"shakeActivationThresholdDescription":
MessageLookupByLibrary.simpleMessage(
"shakeActivationThreshold": MessageLookupByLibrary.simpleMessage("抖动激活阈值"),
"shakeActivationThresholdDescription": MessageLookupByLibrary.simpleMessage(
"门槛越高,你就越难摇晃",
),
"shakeDetector": MessageLookupByLibrary.simpleMessage("抖动检测器"),
@ -351,8 +327,7 @@ class MessageLookup extends MessageLookupByLibrary {
"shakeDetectorEnableDescription": MessageLookupByLibrary.simpleMessage(
"启用抖动检测以执行各种操作",
),
"shakeDetectorSettings":
MessageLookupByLibrary.simpleMessage("抖动检测器设置"),
"shakeDetectorSettings": MessageLookupByLibrary.simpleMessage("抖动检测器设置"),
"shakeFeedback": MessageLookupByLibrary.simpleMessage("抖动反馈"),
"shakeFeedbackDescription": MessageLookupByLibrary.simpleMessage(
"检测到抖动时给出的反馈",
@ -367,21 +342,18 @@ class MessageLookup extends MessageLookupByLibrary {
"themeMode": MessageLookupByLibrary.simpleMessage("主题模式"),
"themeModeDark": MessageLookupByLibrary.simpleMessage("深色"),
"themeModeHighContrast": MessageLookupByLibrary.simpleMessage("高对比度模式"),
"themeModeHighContrastDescription":
MessageLookupByLibrary.simpleMessage(
"themeModeHighContrastDescription": MessageLookupByLibrary.simpleMessage(
"增加背景和文本之间的对比度",
),
"themeModeLight": MessageLookupByLibrary.simpleMessage("浅色"),
"themeModeSystem": MessageLookupByLibrary.simpleMessage("跟随系统"),
"themeSettings": MessageLookupByLibrary.simpleMessage("主题设置"),
"themeSettingsColors": MessageLookupByLibrary.simpleMessage("主题色"),
"themeSettingsColorsAndroid":
MessageLookupByLibrary.simpleMessage("主题色"),
"themeSettingsColorsAndroid": MessageLookupByLibrary.simpleMessage("主题色"),
"themeSettingsColorsBook": MessageLookupByLibrary.simpleMessage(
"书籍详情页自适应主题",
),
"themeSettingsColorsBookDescription":
MessageLookupByLibrary.simpleMessage(
"themeSettingsColorsBookDescription": MessageLookupByLibrary.simpleMessage(
"以牺牲一些性能为代价,对书籍详情页的颜色进行美化",
),
"themeSettingsColorsCurrent": MessageLookupByLibrary.simpleMessage(
@ -392,8 +364,7 @@ class MessageLookup extends MessageLookupByLibrary {
"themeSettingsColorsDescription": MessageLookupByLibrary.simpleMessage(
"使用应用程序的系统主题色",
),
"themeSettingsDescription":
MessageLookupByLibrary.simpleMessage("自定义应用主题"),
"themeSettingsDescription": MessageLookupByLibrary.simpleMessage("自定义应用主题"),
"timeSecond": m7,
"unknown": MessageLookupByLibrary.simpleMessage("未知"),
"webVersion": MessageLookupByLibrary.simpleMessage("Web版本"),

View file

@ -1,6 +1,5 @@
import 'dart:io';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
@ -17,8 +16,6 @@ import 'package:vaani/generated/l10n.dart';
import 'package:vaani/globals.dart';
import 'package:vaani/router/router.dart';
import 'package:vaani/theme/providers/system_theme_provider.dart';
import 'package:vaani/theme/providers/theme_from_cover_provider.dart';
import 'package:vaani/theme/theme.dart';
import 'package:window_manager/window_manager.dart';
void main() async {
@ -90,80 +87,19 @@ class AbsApp extends ConsumerWidget {
if (needOnboarding) {
routerConfig.goNamed(Routes.onboarding.name);
}
final appSettings = ref.watch(appSettingsProvider);
final themeSettings = appSettings.themeSettings;
ColorScheme lightColorScheme = brandLightColorScheme;
ColorScheme darkColorScheme = brandDarkColorScheme;
final shouldUseHighContrast =
themeSettings.highContrast || MediaQuery.of(context).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 {
final language = ref.watch(appSettingsProvider.select((v) => v.language));
final themeSettings =
ref.watch(appSettingsProvider.select((v) => v.themeSettings));
final currentBook = ref.watch(currentBookProvider);
if (currentBook != null) {
final themeLight = ref.watch(
themeOfLibraryItemProvider(
currentBook.libraryItemId,
highContrast: shouldUseHighContrast,
brightness: Brightness.light,
),
);
final themeDark = ref.watch(
themeOfLibraryItemProvider(
currentBook.libraryItemId,
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());
appLogger.severe('not building with player theme');
appLogger.severe(e.toString());
}
}
final appThemeLight = ThemeData(
useMaterial3: true,
colorScheme: lightColorScheme.harmonized(),
fontFamily: fontFamilyPlatform,
);
final appThemeDark = ThemeData(
useMaterial3: true,
colorScheme: darkColorScheme.harmonized(),
fontFamily: fontFamilyPlatform,
brightness: Brightness.dark,
// TODO bottom sheet theme is not working
bottomSheetTheme: BottomSheetThemeData(
backgroundColor: darkColorScheme.surface,
final currentTheme = ref.watch(
CurrentThemeProvider(
highContrast: MediaQuery.of(context).highContrast,
id: currentBook?.libraryItemId,
),
);
try {
return MaterialApp.router(
locale: Locale(appSettings.language),
locale: Locale(language),
localizationsDelegates: [
//
S.delegate, //String
@ -172,8 +108,8 @@ class AbsApp extends ConsumerWidget {
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: S.delegate.supportedLocales,
theme: appThemeLight,
darkTheme: appThemeDark,
theme: currentTheme.$1,
darkTheme: currentTheme.$2,
themeMode: themeSettings.themeMode,
routerConfig: routerConfig,
themeAnimationCurve: Curves.easeInOut,

View file

@ -5,6 +5,9 @@ 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';
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';
@ -72,3 +75,82 @@ FutureOr<(ColorScheme light, ColorScheme dark)?> systemTheme(
}
return (schemeLight, schemeDark);
}
@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);
}

View file

@ -175,5 +175,156 @@ class _SystemThemeProviderElement
@override
bool get highContrast => (origin as SystemThemeProvider).highContrast;
}
String _$currentThemeHash() => r'0e62a7f1b62c6ad73a3769909607407d41eb0338';
/// See also [currentTheme].
@ProviderFor(currentTheme)
const currentThemeProvider = CurrentThemeFamily();
/// See also [currentTheme].
class CurrentThemeFamily extends Family<(ThemeData light, ThemeData dark)> {
/// See also [currentTheme].
const CurrentThemeFamily();
/// See also [currentTheme].
CurrentThemeProvider call({
bool highContrast = false,
String? id,
}) {
return CurrentThemeProvider(
highContrast: highContrast,
id: id,
);
}
@override
CurrentThemeProvider getProviderOverride(
covariant CurrentThemeProvider provider,
) {
return call(
highContrast: provider.highContrast,
id: provider.id,
);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'currentThemeProvider';
}
/// See also [currentTheme].
class CurrentThemeProvider
extends AutoDisposeProvider<(ThemeData light, ThemeData dark)> {
/// See also [currentTheme].
CurrentThemeProvider({
bool highContrast = false,
String? id,
}) : this._internal(
(ref) => currentTheme(
ref as CurrentThemeRef,
highContrast: highContrast,
id: id,
),
from: currentThemeProvider,
name: r'currentThemeProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$currentThemeHash,
dependencies: CurrentThemeFamily._dependencies,
allTransitiveDependencies:
CurrentThemeFamily._allTransitiveDependencies,
highContrast: highContrast,
id: id,
);
CurrentThemeProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.highContrast,
required this.id,
}) : super.internal();
final bool highContrast;
final String? id;
@override
Override overrideWith(
(ThemeData light, ThemeData dark) Function(CurrentThemeRef provider) create,
) {
return ProviderOverride(
origin: this,
override: CurrentThemeProvider._internal(
(ref) => create(ref as CurrentThemeRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
highContrast: highContrast,
id: id,
),
);
}
@override
AutoDisposeProviderElement<(ThemeData light, ThemeData dark)>
createElement() {
return _CurrentThemeProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is CurrentThemeProvider &&
other.highContrast == highContrast &&
other.id == id;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, highContrast.hashCode);
hash = _SystemHash.combine(hash, id.hashCode);
return _SystemHash.finish(hash);
}
}
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
mixin CurrentThemeRef
on AutoDisposeProviderRef<(ThemeData light, ThemeData dark)> {
/// The parameter `highContrast` of this provider.
bool get highContrast;
/// The parameter `id` of this provider.
String? get id;
}
class _CurrentThemeProviderElement
extends AutoDisposeProviderElement<(ThemeData light, ThemeData dark)>
with CurrentThemeRef {
_CurrentThemeProviderElement(super.provider);
@override
bool get highContrast => (origin as CurrentThemeProvider).highContrast;
@override
String? get id => (origin as CurrentThemeProvider).id;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

View file

@ -30,3 +30,190 @@ String get fontFamilyPlatform {
return 'Arial'; // 退
}
}
// letterSpacing
const defaultTextTheme = TextTheme(
displayLarge: TextStyle(
fontSize: 57.0,
fontWeight: FontWeight.w400,
height: 1.12,
letterSpacing: -0.25,
),
displayMedium: TextStyle(
fontSize: 45.0,
fontWeight: FontWeight.w400,
height: 1.16,
letterSpacing: 0.0,
),
displaySmall: TextStyle(
fontSize: 36.0,
fontWeight: FontWeight.w400,
height: 1.22,
letterSpacing: 0.0,
),
headlineLarge: TextStyle(
fontSize: 32.0,
fontWeight: FontWeight.w400,
height: 1.25,
letterSpacing: 0.0,
),
headlineMedium: TextStyle(
fontSize: 28.0,
fontWeight: FontWeight.w400,
height: 1.29,
letterSpacing: 0.0,
),
headlineSmall: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.w400,
height: 1.33,
letterSpacing: 0.0,
),
titleLarge: TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.w400,
height: 1.27,
letterSpacing: 0.0,
),
titleMedium: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w500,
height: 1.5,
letterSpacing: 0.15,
),
titleSmall: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w500,
height: 1.43,
letterSpacing: 0.1,
),
bodyLarge: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.w400,
height: 1.5,
letterSpacing: 0.5,
),
bodyMedium: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w400,
height: 1.43,
letterSpacing: 0.25,
),
bodySmall: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
height: 1.33,
letterSpacing: 0.4,
),
labelLarge: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w500,
height: 1.43,
letterSpacing: 0.1,
),
labelMedium: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w500,
height: 1.33,
letterSpacing: 0.5,
),
labelSmall: TextStyle(
fontSize: 11.0,
fontWeight: FontWeight.w500,
height: 1.45,
letterSpacing: 0.5,
),
);
const textTheme = TextTheme(
displayLarge: TextStyle(
fontSize: 44, //
fontWeight: FontWeight.w400,
height: 1.12,
letterSpacing: -0.25,
),
displayMedium: TextStyle(
fontSize: 36,
fontWeight: FontWeight.w400,
height: 1.16,
letterSpacing: 0.0,
),
displaySmall: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w400,
height: 1.22,
letterSpacing: 0.0,
),
headlineLarge: TextStyle(
fontSize: 28,
fontWeight: FontWeight.w400,
height: 1.25,
letterSpacing: 0.0,
),
headlineMedium: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w400,
height: 1.29,
letterSpacing: 0.0,
),
headlineSmall: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w400,
height: 1.33,
letterSpacing: 0.0,
),
titleLarge: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w400,
height: 1.27,
letterSpacing: 0.0,
),
titleMedium: TextStyle(
fontSize: 15, //
fontWeight: FontWeight.w500,
height: 1.5,
letterSpacing: 0.15,
),
titleSmall: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
height: 1.43,
letterSpacing: 0.1,
),
bodyLarge: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w400,
height: 1.5,
letterSpacing: 0.5,
),
bodyMedium: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w400,
height: 1.43,
letterSpacing: 0.25,
),
bodySmall: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w400,
height: 1.33,
letterSpacing: 0.4,
),
labelLarge: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
height: 1.43,
letterSpacing: 0.1,
),
labelMedium: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w500,
height: 1.33,
letterSpacing: 0.5,
),
labelSmall: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w500,
height: 1.45,
letterSpacing: 0.5,
),
);

View file

@ -30,22 +30,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.11.3"
animated_list_plus:
dependency: "direct main"
description:
name: animated_list_plus
sha256: fb3d7f1fbaf5af84907f3c739236bacda8bf32cbe1f118dd51510752883ff50c
url: "https://pub.dev"
source: hosted
version: "0.5.2"
animated_theme_switcher:
dependency: "direct main"
description:
name: animated_theme_switcher
sha256: "24ccd74437b8db78f6d1ec701804702817bced5f925b1b3419c7a93071e3d3e9"
url: "https://pub.dev"
source: hosted
version: "2.0.10"
archive:
dependency: "direct main"
description:

View file

@ -133,8 +133,8 @@ dependencies:
# 动画
flutter_animate: ^4.5.0
lottie: ^3.1.0
animated_list_plus: ^0.5.2
animated_theme_switcher: ^2.0.10
# animated_list_plus: ^0.5.2
# animated_theme_switcher: ^2.0.10
# Material Design 3色彩系统的算法和工具
material_color_utilities: ^0.11.1