diff --git a/lib/main.dart b/lib/main.dart index 73bc71fd..63632057 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -118,6 +118,8 @@ class MyApp extends StatelessWidget { Box get setting => GStorage.setting; + static ThemeData? darkThemeData; + @override Widget build(BuildContext context) { // 主题色 @@ -183,12 +185,12 @@ class MyApp extends StatelessWidget { return GetMaterialApp( // showSemanticsDebugger: true, title: 'PiliPlus', - theme: _getThemeData( + theme: Utils.getThemeData( colorScheme: lightColorScheme, isDynamic: lightDynamic != null && isDynamicColor, variant: variant, ), - darkTheme: _getThemeData( + darkTheme: Utils.getThemeData( colorScheme: darkColorScheme, isDynamic: darkDynamic != null && isDynamicColor, isDark: true, @@ -224,71 +226,6 @@ class MyApp extends StatelessWidget { }), ); } - - ThemeData _getThemeData({ - required ColorScheme colorScheme, - required bool isDynamic, - bool isDark = false, - required FlexSchemeVariant variant, - }) { - ThemeData themeData = ThemeData( - colorScheme: colorScheme, - useMaterial3: true, - appBarTheme: AppBarTheme( - elevation: 0, - titleSpacing: 0, - centerTitle: false, - scrolledUnderElevation: 0, - backgroundColor: isDynamic ? null : colorScheme.surface, - titleTextStyle: TextStyle(fontSize: 16, color: colorScheme.onSurface), - ), - navigationBarTheme: NavigationBarThemeData( - surfaceTintColor: isDynamic ? colorScheme.onSurfaceVariant : null, - ), - snackBarTheme: SnackBarThemeData( - actionTextColor: colorScheme.primary, - backgroundColor: colorScheme.secondaryContainer, - closeIconColor: colorScheme.secondary, - contentTextStyle: TextStyle(color: colorScheme.secondary), - elevation: 20, - ), - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: ZoomPageTransitionsBuilder( - allowEnterRouteSnapshotting: false, - ), - }, - ), - popupMenuTheme: PopupMenuThemeData( - surfaceTintColor: isDynamic ? colorScheme.onSurfaceVariant : null, - ), - cardTheme: CardTheme( - elevation: 1, - surfaceTintColor: isDynamic - ? colorScheme.onSurfaceVariant - : isDark - ? colorScheme.onSurfaceVariant - : null, - shadowColor: Colors.transparent, - ), - // dialogTheme: DialogTheme( - // surfaceTintColor: isDark ? colorScheme.onSurfaceVariant : null, - // ), - progressIndicatorTheme: ProgressIndicatorThemeData( - refreshBackgroundColor: colorScheme.onSecondary, - ), - dialogTheme: DialogTheme( - titleTextStyle: TextStyle( - fontSize: 18, - color: colorScheme.onSurface, - ), - ), - ); - if (isDark && GStorage.isPureBlackTheme) { - themeData = Utils.darkenTheme(themeData); - } - return themeData; - } } class _CustomHttpOverrides extends HttpOverrides { diff --git a/lib/pages/setting/widgets/model.dart b/lib/pages/setting/widgets/model.dart index 1f3e8cb5..143f2e0a 100644 --- a/lib/pages/setting/widgets/model.dart +++ b/lib/pages/setting/widgets/model.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/common/widgets/refresh_indicator.dart' import 'package:PiliPlus/http/interceptor.dart'; import 'package:PiliPlus/http/reply.dart'; import 'package:PiliPlus/http/video.dart'; +import 'package:PiliPlus/main.dart'; import 'package:PiliPlus/models/common/audio_normalization.dart'; import 'package:PiliPlus/models/common/dynamic_badge_mode.dart'; import 'package:PiliPlus/models/common/dynamics_type.dart'; @@ -206,6 +207,18 @@ List get styleSettings => [ getSubtitle: () => '当前:${GStorage.mediumCardWidth.toInt()}dp,屏幕宽度:${MediaQuery.of(Get.context!).size.width.toPrecision(2)}dp。宽度越小列数越多。', ), + SettingsModel( + settingsType: SettingsType.sw1tch, + title: '视频播放页使用深色主题', + leading: Icon(Icons.dark_mode_outlined), + setKey: SettingBoxKey.darkVideoPage, + defaultVal: false, + onChanged: (value) { + if (value && MyApp.darkThemeData == null) { + Get.forceAppUpdate(); + } + }, + ), SettingsModel( settingsType: SettingsType.sw1tch, title: '播放页移除安全边距', @@ -496,7 +509,8 @@ List get styleSettings => [ setKey: SettingBoxKey.isPureBlackTheme, defaultVal: false, onChanged: (value) { - if (Theme.of(Get.context!).brightness == Brightness.dark) { + if (Theme.of(Get.context!).brightness == Brightness.dark || + GStorage.darkVideoPage) { Get.forceAppUpdate(); } }, diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index b5a0a58f..948757d2 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -944,6 +944,7 @@ class VideoDetailController extends GetxController savedDanmaku = null; plPlayerController.danmakuController?.addDanmaku(danmakuModel); }, + darkVideoPage: plPlayerController.darkVideoPage, ); }, transitionDuration: const Duration(milliseconds: 500), diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 1b657326..d51f68ee 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -60,6 +60,7 @@ class ReplyItem extends StatelessWidget { @override Widget build(BuildContext context) { return Material( + color: Colors.transparent, child: InkWell( // 点击整个评论区 评论详情/回复 onTap: () { diff --git a/lib/pages/video/detail/reply_new/reply_page.dart b/lib/pages/video/detail/reply_new/reply_page.dart index 48109cbf..6c57a063 100644 --- a/lib/pages/video/detail/reply_new/reply_page.dart +++ b/lib/pages/video/detail/reply_new/reply_page.dart @@ -1,10 +1,12 @@ import 'dart:async'; import 'package:PiliPlus/http/video.dart'; +import 'package:PiliPlus/main.dart'; import 'package:PiliPlus/pages/common/common_publish_page.dart'; import 'package:PiliPlus/pages/emote/view.dart'; import 'package:PiliPlus/pages/video/detail/reply_new/toolbar_icon_button.dart'; import 'package:PiliPlus/utils/global_data.dart'; +import 'package:PiliPlus/utils/storage.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -36,39 +38,47 @@ class ReplyPage extends CommonPublishPage { class _ReplyPageState extends CommonPublishPageState { final RxBool _syncToDynamic = false.obs; - @override - Widget build(BuildContext context) { - return MediaQuery.removePadding( - removeTop: true, - context: context, - child: GestureDetector( - onTap: Get.back, - child: LayoutBuilder( - builder: (context, constraints) { - bool isH = constraints.maxWidth > constraints.maxHeight; - late double padding = constraints.maxWidth * 0.12; - return Padding( - padding: EdgeInsets.symmetric(horizontal: isH ? padding : 0), - child: Scaffold( - resizeToAvoidBottomInset: false, - backgroundColor: Colors.transparent, - body: GestureDetector( - onTap: () {}, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - buildInputView(), - buildImagePreview(), - buildPanelContainer(), - ], + Widget get child => MediaQuery.removePadding( + removeTop: true, + context: context, + child: GestureDetector( + onTap: Get.back, + child: LayoutBuilder( + builder: (context, constraints) { + bool isH = constraints.maxWidth > constraints.maxHeight; + late double padding = constraints.maxWidth * 0.12; + return Padding( + padding: EdgeInsets.symmetric(horizontal: isH ? padding : 0), + child: Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: Colors.transparent, + body: GestureDetector( + onTap: () {}, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + buildInputView(), + buildImagePreview(), + buildPanelContainer(themeData.colorScheme.surface), + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), - ), - ); + ); + + late final darkVideoPage = + Get.currentRoute.startsWith('/video') && GStorage.darkVideoPage; + late final ThemeData themeData = darkVideoPage + ? MyApp.darkThemeData ?? Theme.of(context) + : Theme.of(context); + + @override + Widget build(BuildContext context) { + return darkVideoPage ? Theme(data: themeData, child: child) : child; } @override @@ -83,7 +93,7 @@ class _ReplyPageState extends CommonPublishPageState { if (pathList.isNotEmpty) { return Container( height: 85, - color: Theme.of(context).colorScheme.surface, + color: themeData.colorScheme.surface, padding: const EdgeInsets.only(bottom: 10), child: ListView.separated( scrollDirection: Axis.horizontal, @@ -112,7 +122,7 @@ class _ReplyPageState extends CommonPublishPageState { topLeft: Radius.circular(12), topRight: Radius.circular(12), ), - color: Theme.of(context).colorScheme.surface, + color: themeData.colorScheme.surface, ), child: Column( mainAxisSize: MainAxisSize.min, @@ -150,7 +160,7 @@ class _ReplyPageState extends CommonPublishPageState { hintText: "输入回复内容", border: InputBorder.none, hintStyle: TextStyle(fontSize: 14)), - style: Theme.of(context).textTheme.bodyLarge, + style: themeData.textTheme.bodyLarge, ), ), ), @@ -158,7 +168,7 @@ class _ReplyPageState extends CommonPublishPageState { ), Divider( height: 1, - color: Theme.of(context).dividerColor.withOpacity(0.1), + color: themeData.dividerColor.withOpacity(0.1), ), Container( height: 52, @@ -213,8 +223,8 @@ class _ReplyPageState extends CommonPublishPageState { vertical: -2, ), foregroundColor: _syncToDynamic.value - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.outline, + ? themeData.colorScheme.secondary + : themeData.colorScheme.outline, ), onPressed: () { _syncToDynamic.value = !_syncToDynamic.value; diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 14412029..1d2990ef 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -5,6 +5,7 @@ import 'dart:math'; import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/list_sheet.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/main.dart'; import 'package:PiliPlus/models/bangumi/info.dart'; import 'package:PiliPlus/models/common/reply_type.dart'; import 'package:PiliPlus/pages/bangumi/introduction/widgets/intro_detail.dart' @@ -797,7 +798,7 @@ class _VideoDetailPageState extends State // child: Divider( // indent: 12, // endIndent: 12, - // color: Theme.of(context).dividerColor.withOpacity(0.06), + // color: themeData.dividerColor.withOpacity(0.06), // ), // ), // const RelatedVideoPanel(), @@ -1153,8 +1154,12 @@ class _VideoDetailPageState extends State return childWhenDisabled; } - @override - Widget build(BuildContext context) { + late final ThemeData themeData = + videoDetailController.plPlayerController.darkVideoPage + ? MyApp.darkThemeData ?? Theme.of(context) + : Theme.of(context); + + Widget get child { if (!horizontalScreen) { return autoChoose(childWhenDisabled); } @@ -1162,7 +1167,7 @@ class _VideoDetailPageState extends State return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { // if (!isShowing) { - // return ColoredBox(color: Theme.of(context).colorScheme.surface); + // return ColoredBox(color: themeData.colorScheme.surface); // } if (constraints.maxWidth > constraints.maxHeight * 1.25) { // hideStatusBar(); @@ -1212,6 +1217,13 @@ class _VideoDetailPageState extends State ); } + @override + Widget build(BuildContext context) { + return videoDetailController.plPlayerController.darkVideoPage + ? Theme(data: themeData, child: child) + : child; + } + Widget buildTabbar({ bool needIndicator = true, String introText = '简介', @@ -1234,7 +1246,7 @@ class _VideoDetailPageState extends State Widget tabbar() => TabBar( labelColor: needIndicator.not || tabs.length == 1 - ? Theme.of(context).colorScheme.onSurface + ? themeData.colorScheme.onSurface : null, indicator: needIndicator.not || tabs.length == 1 ? const BoxDecoration() @@ -1281,7 +1293,7 @@ class _VideoDetailPageState extends State border: Border( bottom: BorderSide( width: 1, - color: Theme.of(context).dividerColor.withOpacity(0.1), + color: themeData.dividerColor.withOpacity(0.1), ), ), ), @@ -1311,7 +1323,7 @@ class _VideoDetailPageState extends State '发弹幕', style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.onSurfaceVariant, + color: themeData.colorScheme.onSurfaceVariant, ), ), ), @@ -1339,8 +1351,8 @@ class _VideoDetailPageState extends State // ignore: deprecated_member_use color: videoDetailController .plPlayerController.isOpenDanmu.value - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.outline, + ? themeData.colorScheme.secondary + : themeData.colorScheme.outline, ), ), ), @@ -1463,9 +1475,8 @@ class _VideoDetailPageState extends State shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(6), ), - backgroundColor: Theme.of(context) - .colorScheme - .secondaryContainer + backgroundColor: themeData + .colorScheme.secondaryContainer .withOpacity(0.8), padding: const EdgeInsets.symmetric( horizontal: 15, @@ -1524,10 +1535,7 @@ class _VideoDetailPageState extends State height: 1, indent: 12, endIndent: 12, - color: Theme.of(context) - .colorScheme - .outline - .withOpacity(0.08), + color: themeData.colorScheme.outline.withOpacity(0.08), ), ), ), @@ -1578,9 +1586,7 @@ class _VideoDetailPageState extends State height: 54, padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer + color: themeData.colorScheme.secondaryContainer .withOpacity(0.95), borderRadius: const BorderRadius.all(Radius.circular(14)), ), @@ -1591,9 +1597,7 @@ class _VideoDetailPageState extends State Text( videoDetailController.watchLaterTitle, style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + color: themeData.colorScheme.onSecondaryContainer, fontWeight: FontWeight.bold, letterSpacing: 0.2, ), @@ -1660,7 +1664,7 @@ class _VideoDetailPageState extends State const SizedBox(height: 8), Divider( height: 1, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), + color: themeData.colorScheme.outline.withOpacity(0.1), ), ], Padding( @@ -1780,7 +1784,7 @@ class _VideoDetailPageState extends State showIntroDetail(videoDetail, videoTags) { videoDetailController.childKey.currentState?.showBottomSheet( shape: const RoundedRectangleBorder(), - backgroundColor: Theme.of(context).colorScheme.surface, + backgroundColor: themeData.colorScheme.surface, (context) => videoDetail is BangumiInfoModel ? bangumi.IntroDetail( bangumiDetail: videoDetail, @@ -1945,7 +1949,7 @@ class _VideoDetailPageState extends State void onShowMemberPage(mid) { videoDetailController.childKey.currentState?.showBottomSheet( shape: const RoundedRectangleBorder(), - backgroundColor: Theme.of(context).colorScheme.surface, + backgroundColor: themeData.colorScheme.surface, (context) { return HorizontalMemberPage( mid: mid, diff --git a/lib/pages/video/detail/view_v.dart b/lib/pages/video/detail/view_v.dart index f0dc58de..ca0257f4 100644 --- a/lib/pages/video/detail/view_v.dart +++ b/lib/pages/video/detail/view_v.dart @@ -6,6 +6,7 @@ import 'dart:ui'; import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/list_sheet.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/main.dart'; import 'package:PiliPlus/models/bangumi/info.dart'; import 'package:PiliPlus/models/common/reply_type.dart'; import 'package:PiliPlus/pages/bangumi/introduction/widgets/intro_detail.dart' @@ -652,26 +653,22 @@ class _VideoDetailPageVState extends State statusBarIconBrightness: Brightness.light, systemNavigationBarIconBrightness: - Theme.of(context) - .brightness - .reverse, + themeData.brightness.reverse, ) : null, ), if (shouldShow) AppBar( - backgroundColor: Theme.of(context) - .colorScheme - .surface + backgroundColor: themeData.colorScheme.surface .withOpacity( videoDetailController.scrollRatio.value), toolbarHeight: 0, systemOverlayStyle: Platform.isAndroid ? SystemUiOverlayStyle( statusBarIconBrightness: - Theme.of(context).brightness.reverse, + themeData.brightness.reverse, systemNavigationBarIconBrightness: - Theme.of(context).brightness.reverse, + themeData.brightness.reverse, ) : null, ), @@ -797,7 +794,7 @@ class _VideoDetailPageVState extends State opacity: videoDetailController.scrollRatio.value, child: Container( - color: Theme.of(context).colorScheme.surface, + color: themeData.colorScheme.surface, alignment: Alignment.topCenter, child: SizedBox( height: kToolbarHeight, @@ -816,9 +813,8 @@ class _VideoDetailPageVState extends State icon: Icon( FontAwesomeIcons.arrowLeft, size: 15, - color: Theme.of(context) - .colorScheme - .onSurface, + color: themeData + .colorScheme.onSurface, ), onPressed: Get.back, ), @@ -831,9 +827,8 @@ class _VideoDetailPageVState extends State icon: Icon( FontAwesomeIcons.house, size: 15, - color: Theme.of(context) - .colorScheme - .onSurface, + color: themeData + .colorScheme.onSurface, ), onPressed: () { videoDetailController @@ -853,16 +848,14 @@ class _VideoDetailPageVState extends State children: [ Icon( Icons.play_arrow_rounded, - color: Theme.of(context) - .colorScheme - .primary, + color: themeData + .colorScheme.primary, ), Text( '${videoDetailController.playedTime == null ? '立即' : plPlayerController!.playerStatus.status.value == PlayerStatus.completed ? '重新' : '继续'}播放', style: TextStyle( - color: Theme.of(context) - .colorScheme - .primary, + color: themeData + .colorScheme.primary, ), ), ], @@ -875,9 +868,8 @@ class _VideoDetailPageVState extends State child: PopupMenuButton( icon: Icon( Icons.more_vert, - color: Theme.of(context) - .colorScheme - .onSurface, + color: themeData + .colorScheme.onSurface, ), onSelected: (String type) async { switch (type) { @@ -1184,7 +1176,7 @@ class _VideoDetailPageVState extends State // child: Divider( // indent: 12, // endIndent: 12, - // color: Theme.of(context).dividerColor.withOpacity(0.06), + // color: themeData.dividerColor.withOpacity(0.06), // ), // ), // const RelatedVideoPanel(), @@ -1541,8 +1533,12 @@ class _VideoDetailPageVState extends State return childWhenDisabled; } - @override - Widget build(BuildContext context) { + late final ThemeData themeData = + videoDetailController.plPlayerController.darkVideoPage + ? MyApp.darkThemeData ?? Theme.of(context) + : Theme.of(context); + + Widget get child { if (!horizontalScreen) { return autoChoose(childWhenDisabled); } @@ -1550,7 +1546,7 @@ class _VideoDetailPageVState extends State return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { // if (!isShowing) { - // return ColoredBox(color: Theme.of(context).colorScheme.surface); + // return ColoredBox(color: themeData.colorScheme.surface); // } if (constraints.maxWidth > constraints.maxHeight * 1.25) { // hideStatusBar(); @@ -1600,6 +1596,13 @@ class _VideoDetailPageVState extends State ); } + @override + Widget build(BuildContext context) { + return videoDetailController.plPlayerController.darkVideoPage + ? Theme(data: themeData, child: child) + : child; + } + Widget buildTabbar({ bool needIndicator = true, String introText = '简介', @@ -1623,7 +1626,7 @@ class _VideoDetailPageVState extends State Widget tabbar() => TabBar( labelColor: needIndicator.not || tabs.length == 1 - ? Theme.of(context).colorScheme.onSurface + ? themeData.colorScheme.onSurface : null, indicator: needIndicator.not || tabs.length == 1 ? const BoxDecoration() @@ -1674,7 +1677,7 @@ class _VideoDetailPageVState extends State border: Border( bottom: BorderSide( width: 1, - color: Theme.of(context).dividerColor.withOpacity(0.1), + color: themeData.dividerColor.withOpacity(0.1), ), ), ), @@ -1704,7 +1707,7 @@ class _VideoDetailPageVState extends State '发弹幕', style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.onSurfaceVariant, + color: themeData.colorScheme.onSurfaceVariant, ), ), ), @@ -1732,8 +1735,8 @@ class _VideoDetailPageVState extends State // ignore: deprecated_member_use color: videoDetailController .plPlayerController.isOpenDanmu.value - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.outline, + ? themeData.colorScheme.secondary + : themeData.colorScheme.outline, ), ), ), @@ -1866,9 +1869,8 @@ class _VideoDetailPageVState extends State shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(6), ), - backgroundColor: Theme.of(context) - .colorScheme - .secondaryContainer + backgroundColor: themeData + .colorScheme.secondaryContainer .withOpacity(0.8), padding: const EdgeInsets.symmetric( horizontal: 15, @@ -1936,10 +1938,7 @@ class _VideoDetailPageVState extends State height: 1, indent: 12, endIndent: 12, - color: Theme.of(context) - .colorScheme - .outline - .withOpacity(0.08), + color: themeData.colorScheme.outline.withOpacity(0.08), ), ), ), @@ -1992,9 +1991,7 @@ class _VideoDetailPageVState extends State height: 54, padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer + color: themeData.colorScheme.secondaryContainer .withOpacity(0.95), borderRadius: const BorderRadius.all(Radius.circular(14)), ), @@ -2005,9 +2002,7 @@ class _VideoDetailPageVState extends State Text( videoDetailController.watchLaterTitle, style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + color: themeData.colorScheme.onSecondaryContainer, fontWeight: FontWeight.bold, letterSpacing: 0.2, ), @@ -2074,7 +2069,7 @@ class _VideoDetailPageVState extends State const SizedBox(height: 8), Divider( height: 1, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), + color: themeData.colorScheme.outline.withOpacity(0.1), ), ], Padding( @@ -2359,7 +2354,7 @@ class _VideoDetailPageVState extends State void onShowMemberPage(mid) { videoDetailController.childKey.currentState?.showBottomSheet( shape: const RoundedRectangleBorder(), - backgroundColor: Theme.of(context).colorScheme.surface, + backgroundColor: themeData.colorScheme.surface, (context) { return HorizontalMemberPage( mid: mid, diff --git a/lib/pages/video/detail/widgets/send_danmaku_panel.dart b/lib/pages/video/detail/widgets/send_danmaku_panel.dart index 92e5c72f..9e0542e2 100644 --- a/lib/pages/video/detail/widgets/send_danmaku_panel.dart +++ b/lib/pages/video/detail/widgets/send_danmaku_panel.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:PiliPlus/common/widgets/icon_button.dart'; import 'package:PiliPlus/http/danmaku.dart'; +import 'package:PiliPlus/main.dart'; import 'package:PiliPlus/pages/common/common_publish_page.dart'; import 'package:PiliPlus/pages/setting/slide_color_picker.dart'; import 'package:PiliPlus/utils/extension.dart'; @@ -16,6 +17,7 @@ class SendDanmakuPanel extends CommonPublishPage { final dynamic bvid; final dynamic progress; final ValueChanged callback; + final bool darkVideoPage; const SendDanmakuPanel({ super.key, @@ -25,6 +27,7 @@ class SendDanmakuPanel extends CommonPublishPage { required this.bvid, required this.progress, required this.callback, + required this.darkVideoPage, }); @override @@ -81,8 +84,7 @@ class _SendDanmakuPanelState extends CommonPublishPageState { width: 40, height: 40, decoration: BoxDecoration( - color: - Theme.of(context).colorScheme.secondaryContainer, + color: themeData.colorScheme.secondaryContainer, borderRadius: BorderRadius.circular(8), ), alignment: Alignment.center, @@ -90,9 +92,7 @@ class _SendDanmakuPanelState extends CommonPublishPageState { child: Icon( size: 22, Icons.edit, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + color: themeData.colorScheme.onSecondaryContainer, ), ), ); @@ -107,38 +107,44 @@ class _SendDanmakuPanelState extends CommonPublishPageState { ), ); - @override - Widget build(BuildContext context) { - return MediaQuery.removePadding( - removeTop: true, - context: context, - child: GestureDetector( - onTap: Get.back, - child: LayoutBuilder( - builder: (context, constraints) { - bool isH = constraints.maxWidth > constraints.maxHeight; - late double padding = constraints.maxWidth * 0.12; - return Padding( - padding: EdgeInsets.symmetric(horizontal: isH ? padding : 0), - child: Scaffold( - resizeToAvoidBottomInset: false, - backgroundColor: Colors.transparent, - body: GestureDetector( - onTap: () {}, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - _buildInputView(), - buildPanelContainer(), - ], + Widget get child => MediaQuery.removePadding( + removeTop: true, + context: context, + child: GestureDetector( + onTap: Get.back, + child: LayoutBuilder( + builder: (context, constraints) { + bool isH = constraints.maxWidth > constraints.maxHeight; + late double padding = constraints.maxWidth * 0.12; + return Padding( + padding: EdgeInsets.symmetric(horizontal: isH ? padding : 0), + child: Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: Colors.transparent, + body: GestureDetector( + onTap: () {}, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + _buildInputView(), + buildPanelContainer(themeData.colorScheme.surface), + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), - ), - ); + ); + + late final ThemeData themeData = widget.darkVideoPage + ? MyApp.darkThemeData ?? Theme.of(context) + : Theme.of(context); + + @override + Widget build(BuildContext context) { + return widget.darkVideoPage ? Theme(data: themeData, child: child) : child; } @override @@ -148,7 +154,7 @@ class _SendDanmakuPanelState extends CommonPublishPageState { decoration: BoxDecoration( border: Border( top: BorderSide( - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), + color: themeData.colorScheme.outline.withOpacity(0.1), ), ), ), @@ -209,7 +215,7 @@ class _SendDanmakuPanelState extends CommonPublishPageState { ? null : Border.all( width: 2, - color: Theme.of(context).colorScheme.primary, + color: themeData.colorScheme.primary, ), ), child: Container( @@ -236,8 +242,8 @@ class _SendDanmakuPanelState extends CommonPublishPageState { alignment: Alignment.center, decoration: BoxDecoration( color: _mode.value == mode - ? Theme.of(context).colorScheme.secondaryContainer - : Theme.of(context).colorScheme.onInverseSurface, + ? themeData.colorScheme.secondaryContainer + : themeData.colorScheme.onInverseSurface, borderRadius: BorderRadius.circular(8), ), padding: const EdgeInsets.symmetric(vertical: 5), @@ -245,8 +251,8 @@ class _SendDanmakuPanelState extends CommonPublishPageState { title, style: TextStyle( color: _mode.value == mode - ? Theme.of(context).colorScheme.onSecondaryContainer - : Theme.of(context).colorScheme.outline, + ? themeData.colorScheme.onSecondaryContainer + : themeData.colorScheme.outline, ), ), ), @@ -268,8 +274,8 @@ class _SendDanmakuPanelState extends CommonPublishPageState { alignment: Alignment.center, decoration: BoxDecoration( color: _fontsize.value == fontsize - ? Theme.of(context).colorScheme.secondaryContainer - : Theme.of(context).colorScheme.onInverseSurface, + ? themeData.colorScheme.secondaryContainer + : themeData.colorScheme.onInverseSurface, borderRadius: BorderRadius.circular(8), ), padding: const EdgeInsets.symmetric(vertical: 5), @@ -277,8 +283,8 @@ class _SendDanmakuPanelState extends CommonPublishPageState { title, style: TextStyle( color: _fontsize.value == fontsize - ? Theme.of(context).colorScheme.onSecondaryContainer - : Theme.of(context).colorScheme.outline, + ? themeData.colorScheme.onSecondaryContainer + : themeData.colorScheme.outline, ), ), ), @@ -297,7 +303,7 @@ class _SendDanmakuPanelState extends CommonPublishPageState { topLeft: Radius.circular(12), topRight: Radius.circular(12), ), - color: Theme.of(context).colorScheme.surface, + color: themeData.colorScheme.surface, ), child: Row( children: [ @@ -318,8 +324,8 @@ class _SendDanmakuPanelState extends CommonPublishPageState { iconSize: 24, icon: Icons.text_format, iconColor: selectKeyboard.value.not - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurfaceVariant, + ? themeData.colorScheme.primary + : themeData.colorScheme.onSurfaceVariant, ), ), const SizedBox(width: 12), @@ -362,10 +368,10 @@ class _SendDanmakuPanelState extends CommonPublishPageState { border: InputBorder.none, hintStyle: TextStyle( fontSize: 15, - color: Theme.of(context).colorScheme.outline, + color: themeData.colorScheme.outline, ), ), - style: Theme.of(context).textTheme.bodyLarge, + style: themeData.textTheme.bodyLarge, ), ), ), @@ -379,8 +385,8 @@ class _SendDanmakuPanelState extends CommonPublishPageState { bgColor: Colors.transparent, iconSize: 22, iconColor: enablePublish.value - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, + ? themeData.colorScheme.primary + : themeData.colorScheme.outline, onPressed: enablePublish.value ? onPublish : null, icon: Icons.send, ), diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 2698ea6e..b840fe9b 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -256,6 +256,7 @@ class PlPlayerController { late final showFSActionItem = GStorage.showFSActionItem; late final enableShrinkVideoSize = GStorage.enableShrinkVideoSize; + late final darkVideoPage = GStorage.darkVideoPage; /// 弹幕权重 int danmakuWeight = 0; diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index cbad10f6..304baa1a 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -403,6 +403,9 @@ class GStorage { static bool get showDynActionBar => GStorage.setting.get(SettingBoxKey.showDynActionBar, defaultValue: true); + static bool get darkVideoPage => + GStorage.setting.get(SettingBoxKey.darkVideoPage, defaultValue: false); + static List get dynamicDetailRatio => List.from(setting .get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0])); @@ -661,6 +664,7 @@ class SettingBoxKey { showFSActionItem = 'showFSActionItem', enableShrinkVideoSize = 'enableShrinkVideoSize', showDynActionBar = 'showDynActionBar', + darkVideoPage = 'darkVideoPage', // Sponsor Block enableSponsorBlock = 'enableSponsorBlock', diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 3fcc5ee6..3cd9f9b0 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -14,6 +14,7 @@ import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/member.dart'; import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/http/video.dart'; +import 'package:PiliPlus/main.dart'; import 'package:PiliPlus/models/bangumi/info.dart'; import 'package:PiliPlus/models/common/search_type.dart'; import 'package:PiliPlus/models/dynamics/result.dart'; @@ -33,6 +34,7 @@ import 'package:PiliPlus/utils/url_utils.dart'; import 'package:crypto/crypto.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:dio/dio.dart'; +import 'package:flex_seed_scheme/flex_seed_scheme.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -50,6 +52,74 @@ class Utils { static const channel = MethodChannel("PiliPlus"); + static ThemeData getThemeData({ + required ColorScheme colorScheme, + required bool isDynamic, + bool isDark = false, + required FlexSchemeVariant variant, + }) { + ThemeData themeData = ThemeData( + colorScheme: colorScheme, + useMaterial3: true, + appBarTheme: AppBarTheme( + elevation: 0, + titleSpacing: 0, + centerTitle: false, + scrolledUnderElevation: 0, + backgroundColor: isDynamic ? null : colorScheme.surface, + titleTextStyle: TextStyle(fontSize: 16, color: colorScheme.onSurface), + ), + navigationBarTheme: NavigationBarThemeData( + surfaceTintColor: isDynamic ? colorScheme.onSurfaceVariant : null, + ), + snackBarTheme: SnackBarThemeData( + actionTextColor: colorScheme.primary, + backgroundColor: colorScheme.secondaryContainer, + closeIconColor: colorScheme.secondary, + contentTextStyle: TextStyle(color: colorScheme.secondary), + elevation: 20, + ), + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: ZoomPageTransitionsBuilder( + allowEnterRouteSnapshotting: false, + ), + }, + ), + popupMenuTheme: PopupMenuThemeData( + surfaceTintColor: isDynamic ? colorScheme.onSurfaceVariant : null, + ), + cardTheme: CardTheme( + elevation: 1, + surfaceTintColor: isDynamic + ? colorScheme.onSurfaceVariant + : isDark + ? colorScheme.onSurfaceVariant + : null, + shadowColor: Colors.transparent, + ), + // dialogTheme: DialogTheme( + // surfaceTintColor: isDark ? colorScheme.onSurfaceVariant : null, + // ), + progressIndicatorTheme: ProgressIndicatorThemeData( + refreshBackgroundColor: colorScheme.onSecondary, + ), + dialogTheme: DialogTheme( + titleTextStyle: TextStyle( + fontSize: 18, + color: colorScheme.onSurface, + ), + ), + ); + if (isDark && GStorage.isPureBlackTheme) { + themeData = Utils.darkenTheme(themeData); + } + if (isDark && GStorage.darkVideoPage) { + MyApp.darkThemeData = themeData; + } + return themeData; + } + static final regExp = RegExp(r'(@(\d+[a-z]_?)*)(\..*)?$', caseSensitive: false);