diff --git a/lib/common/skeleton/dynamic_card.dart b/lib/common/skeleton/dynamic_card.dart index 6279bf78..1d94e91b 100644 --- a/lib/common/skeleton/dynamic_card.dart +++ b/lib/common/skeleton/dynamic_card.dart @@ -6,7 +6,8 @@ class DynamicCardSkeleton extends StatelessWidget { @override Widget build(BuildContext context) { - final color = Theme.of(context).colorScheme.onInverseSurface; + final ThemeData theme = Theme.of(context); + final color = theme.colorScheme.onInverseSurface; return Skeleton( child: Container( padding: const EdgeInsets.only(left: 12, right: 12, top: 12), @@ -14,7 +15,7 @@ class DynamicCardSkeleton extends StatelessWidget { border: Border( bottom: BorderSide( width: 8, - color: Theme.of(context).dividerColor.withOpacity(0.05), + color: theme.dividerColor.withOpacity(0.05), ), ), ), @@ -101,10 +102,8 @@ class DynamicCardSkeleton extends StatelessWidget { ), style: TextButton.styleFrom( padding: const EdgeInsets.fromLTRB(15, 0, 15, 0), - foregroundColor: Theme.of(context) - .colorScheme - .outline - .withOpacity(0.2), + foregroundColor: + theme.colorScheme.outline.withOpacity(0.2), ), label: Text( i == 0 diff --git a/lib/common/skeleton/media_bangumi.dart b/lib/common/skeleton/media_bangumi.dart index c8070602..e43f0faa 100644 --- a/lib/common/skeleton/media_bangumi.dart +++ b/lib/common/skeleton/media_bangumi.dart @@ -35,25 +35,25 @@ class _MediaBangumiSkeletonState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - color: Theme.of(context).colorScheme.onInverseSurface, + color: bgColor, width: 200, height: 20, margin: const EdgeInsets.only(bottom: 15), ), Container( - color: Theme.of(context).colorScheme.onInverseSurface, + color: bgColor, width: 150, height: 13, margin: const EdgeInsets.only(bottom: 5), ), Container( - color: Theme.of(context).colorScheme.onInverseSurface, + color: bgColor, width: 150, height: 13, margin: const EdgeInsets.only(bottom: 5), ), Container( - color: Theme.of(context).colorScheme.onInverseSurface, + color: bgColor, width: 150, height: 13, ), @@ -64,7 +64,7 @@ class _MediaBangumiSkeletonState extends State { decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(20)), - color: Theme.of(context).colorScheme.onInverseSurface, + color: bgColor, ), ), ], diff --git a/lib/common/skeleton/skeleton.dart b/lib/common/skeleton/skeleton.dart index b208bf70..40f6560f 100644 --- a/lib/common/skeleton/skeleton.dart +++ b/lib/common/skeleton/skeleton.dart @@ -10,11 +10,12 @@ class Skeleton extends StatelessWidget { @override Widget build(BuildContext context) { + final color = Theme.of(context).colorScheme.surface.withAlpha(10); var shimmerGradient = LinearGradient( colors: [ Colors.transparent, - Theme.of(context).colorScheme.surface.withAlpha(10), - Theme.of(context).colorScheme.surface.withAlpha(10), + color, + color, Colors.transparent, ], stops: const [ diff --git a/lib/common/widgets/badge.dart b/lib/common/widgets/badge.dart index c23863e2..1ca2d260 100644 --- a/lib/common/widgets/badge.dart +++ b/lib/common/widgets/badge.dart @@ -39,26 +39,26 @@ class PBadge extends StatelessWidget { return const SizedBox.shrink(); } - ColorScheme t = Theme.of(context).colorScheme; + ColorScheme theme = Theme.of(context).colorScheme; // 背景色 - Color bgColor = t.primary; + Color bgColor = theme.primary; // 前景色 - Color color = t.onPrimary; + Color color = theme.onPrimary; // 边框色 Color borderColor = Colors.transparent; if (type == 'gray') { bgColor = Colors.black45; color = Colors.white; } else if (type == 'color') { - bgColor = t.secondaryContainer.withOpacity(0.5); - color = t.onSecondaryContainer; + bgColor = theme.secondaryContainer.withOpacity(0.5); + color = theme.onSecondaryContainer; } else if (type == 'line') { bgColor = Colors.transparent; - color = t.primary; - borderColor = t.primary; + color = theme.primary; + borderColor = theme.primary; } else if (type == 'error') { - bgColor = t.error; - color = t.onError; + bgColor = theme.error; + color = theme.onError; } late EdgeInsets paddingStyle = diff --git a/lib/common/widgets/custom_toast.dart b/lib/common/widgets/custom_toast.dart index 73204b84..9b99a9c2 100644 --- a/lib/common/widgets/custom_toast.dart +++ b/lib/common/widgets/custom_toast.dart @@ -8,6 +8,7 @@ class CustomToast extends StatelessWidget { @override Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); final double toastOpacity = GStorage.setting .get(SettingBoxKey.defaultToastOp, defaultValue: 1.0) as double; return Container( @@ -15,17 +16,14 @@ class CustomToast extends StatelessWidget { EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom + 30), padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 10), decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .primaryContainer - .withOpacity(toastOpacity), + color: theme.colorScheme.primaryContainer.withOpacity(toastOpacity), borderRadius: BorderRadius.circular(20), ), child: Text( msg, style: TextStyle( fontSize: 13, - color: Theme.of(context).colorScheme.onPrimaryContainer, + color: theme.colorScheme.onPrimaryContainer, ), ), ); @@ -40,26 +38,25 @@ class LoadingWidget extends StatelessWidget { @override Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); + final onSurfaceVariant = theme.colorScheme.onSurfaceVariant; return Container( padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 20), decoration: BoxDecoration( - color: Theme.of(context).dialogBackgroundColor, + color: theme.dialogBackgroundColor, borderRadius: BorderRadius.circular(15), ), child: Column(mainAxisSize: MainAxisSize.min, children: [ //loading animation CircularProgressIndicator( strokeWidth: 3, - valueColor: AlwaysStoppedAnimation( - Theme.of(context).colorScheme.onSurfaceVariant), + valueColor: AlwaysStoppedAnimation(onSurfaceVariant), ), //msg Container( margin: const EdgeInsets.only(top: 20), - child: Text(msg, - style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant)), + child: Text(msg, style: TextStyle(color: onSurfaceVariant)), ), ]), ); diff --git a/lib/common/widgets/episode_panel.dart b/lib/common/widgets/episode_panel.dart index a940b7d9..2bbfbbfc 100644 --- a/lib/common/widgets/episode_panel.dart +++ b/lib/common/widgets/episode_panel.dart @@ -198,53 +198,57 @@ class _EpisodePanelState extends CommonSlidePageState } @override - Widget get buildPage => Material( - color: widget.showTitle == false - ? Colors.transparent - : Theme.of(context).colorScheme.surface, - child: Column( - children: [ - _buildToolbar, - if (widget.type == EpisodeType.season && - widget.list.length > 1) ...[ - TabBar( - controller: _tabController, - padding: const EdgeInsets.only(right: 60), - isScrollable: true, - tabs: widget.list.map((item) => Tab(text: item.title)).toList(), - dividerHeight: 1, - dividerColor: Theme.of(context).dividerColor.withOpacity(0.1), - ), - Expanded( - child: Material( - color: Colors.transparent, - child: tabBarView( - controller: _tabController, - children: List.generate( - widget.list.length, - (index) => _buildBody( - index, - widget.list[index].episodes, - ), + Widget buildPage(ThemeData theme) { + return Material( + color: widget.showTitle == false + ? Colors.transparent + : theme.colorScheme.surface, + child: Column( + children: [ + _buildToolbar(theme), + if (widget.type == EpisodeType.season && widget.list.length > 1) ...[ + TabBar( + controller: _tabController, + padding: const EdgeInsets.only(right: 60), + isScrollable: true, + tabs: widget.list.map((item) => Tab(text: item.title)).toList(), + dividerHeight: 1, + dividerColor: theme.dividerColor.withOpacity(0.1), + ), + Expanded( + child: Material( + color: Colors.transparent, + child: tabBarView( + controller: _tabController, + children: List.generate( + widget.list.length, + (index) => _buildBody( + theme, + index, + widget.list[index].episodes, ), ), ), ), - ] else - Expanded( - child: enableSlide ? slideList() : buildList, - ), - ], - ), - ); + ), + ] else + Expanded( + child: enableSlide ? slideList(theme) : buildList(theme), + ), + ], + ), + ); + } @override - Widget get buildList => Material( - color: Colors.transparent, - child: _buildBody(0, _getCurrEpisodes), - ); + Widget buildList(ThemeData theme) { + return Material( + color: Colors.transparent, + child: _buildBody(theme, 0, _getCurrEpisodes), + ); + } - Widget _buildBody(int index, episodes) { + Widget _buildBody(ThemeData theme, int index, episodes) { return KeepAliveWrapper( builder: (context) => ScrollablePositionedList.separated( padding: EdgeInsets.only( @@ -265,6 +269,7 @@ class _EpisodePanelState extends CommonSlidePageState children: [ Obx( () => _buildEpisodeItem( + theme: theme, episode: episode, index: index, length: episodes.length, @@ -293,6 +298,7 @@ class _EpisodePanelState extends CommonSlidePageState ) : Obx( () => _buildEpisodeItem( + theme: theme, episode: episode, index: index, length: episodes.length, @@ -310,6 +316,7 @@ class _EpisodePanelState extends CommonSlidePageState } Widget _buildEpisodeItem({ + required ThemeData theme, required dynamic episode, required int index, required int length, @@ -351,7 +358,7 @@ class _EpisodePanelState extends CommonSlidePageState pubdate = episode.pubTime; break; } - late final Color primary = Theme.of(context).colorScheme.primary; + late final Color primary = theme.colorScheme.primary; return Material( color: Colors.transparent, @@ -396,7 +403,7 @@ class _EpisodePanelState extends CommonSlidePageState }, onLongPress: () { if (cover?.isNotEmpty == true) { - imageSaveDialog(context: context, title: title, cover: cover); + imageSaveDialog(title: title, cover: cover); } }, child: Padding( @@ -450,10 +457,7 @@ class _EpisodePanelState extends CommonSlidePageState title, textAlign: TextAlign.start, style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .bodyMedium! - .fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, height: 1.42, letterSpacing: 0.3, fontWeight: isCurrentIndex ? FontWeight.bold : null, @@ -470,7 +474,7 @@ class _EpisodePanelState extends CommonSlidePageState style: TextStyle( fontSize: 12, height: 1, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, overflow: TextOverflow.clip, ), ), @@ -550,14 +554,14 @@ class _EpisodePanelState extends CommonSlidePageState }, ); - Widget get _buildToolbar => Container( + Widget _buildToolbar(ThemeData theme) => Container( height: 45, padding: EdgeInsets.symmetric( horizontal: widget.showTitle != false ? 14 : 6), decoration: BoxDecoration( border: Border( bottom: BorderSide( - color: Theme.of(context).dividerColor.withOpacity(0.1), + color: theme.dividerColor.withOpacity(0.1), ), ), ), @@ -566,7 +570,7 @@ class _EpisodePanelState extends CommonSlidePageState if (widget.showTitle != false) Text( widget.type.title, - style: Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, ), if (_favState != null) Obx(() => _buildFavBtn(_favState!.value)), mediumButton( diff --git a/lib/common/widgets/http_error.dart b/lib/common/widgets/http_error.dart index d369f00f..fd78ec9c 100644 --- a/lib/common/widgets/http_error.dart +++ b/lib/common/widgets/http_error.dart @@ -25,40 +25,43 @@ class HttpError extends StatelessWidget { ); } - Widget content(BuildContext context) => Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox(height: 40), - SvgPicture.asset( - "assets/images/error.svg", - height: 200, + Widget content(BuildContext context) { + final theme = Theme.of(context); + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const SizedBox(height: 40), + SvgPicture.asset( + "assets/images/error.svg", + height: 200, + ), + const SizedBox(height: 30), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), + child: SelectableText( + errMsg ?? '没有数据', + textAlign: TextAlign.center, + style: theme.textTheme.titleSmall, + scrollPhysics: const NeverScrollableScrollPhysics(), ), - const SizedBox(height: 30), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5), - child: SelectableText( - errMsg ?? '没有数据', - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.titleSmall, - scrollPhysics: const NeverScrollableScrollPhysics(), + ), + if (onReload != null) + FilledButton.tonal( + onPressed: onReload, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.resolveWith((states) { + return theme.colorScheme.primary.withAlpha(20); + }), + ), + child: Text( + btnText ?? '点击重试', + style: TextStyle(color: theme.colorScheme.primary), ), ), - if (onReload != null) - FilledButton.tonal( - onPressed: onReload, - style: ButtonStyle( - backgroundColor: WidgetStateProperty.resolveWith((states) { - return Theme.of(context).colorScheme.primary.withAlpha(20); - }), - ), - child: Text( - btnText ?? '点击重试', - style: TextStyle(color: Theme.of(context).colorScheme.primary), - ), - ), - SizedBox(height: 40 + MediaQuery.paddingOf(context).bottom), - ], - ); + SizedBox(height: 40 + MediaQuery.paddingOf(context).bottom), + ], + ); + } } diff --git a/lib/common/widgets/icon_button.dart b/lib/common/widgets/icon_button.dart index 92046344..94689ef7 100644 --- a/lib/common/widgets/icon_button.dart +++ b/lib/common/widgets/icon_button.dart @@ -10,6 +10,7 @@ Widget iconButton({ Color? bgColor, Color? iconColor, }) { + late final theme = Theme.of(context); return SizedBox( width: size, height: size, @@ -19,12 +20,11 @@ Widget iconButton({ icon: Icon( icon, size: iconSize ?? size / 2, - color: iconColor ?? Theme.of(context).colorScheme.onSecondaryContainer, + color: iconColor ?? theme.colorScheme.onSecondaryContainer, ), style: IconButton.styleFrom( padding: EdgeInsets.zero, - backgroundColor: - bgColor ?? Theme.of(context).colorScheme.secondaryContainer, + backgroundColor: bgColor ?? theme.colorScheme.secondaryContainer, ), ), ); diff --git a/lib/common/widgets/image_save.dart b/lib/common/widgets/image_save.dart index ab836097..7881f347 100644 --- a/lib/common/widgets/image_save.dart +++ b/lib/common/widgets/image_save.dart @@ -9,104 +9,108 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; void imageSaveDialog({ - required BuildContext context, required String? title, required String? cover, }) { final double imgWidth = min(Get.width, Get.height) - 8 * 2; SmartDialog.show( animationType: SmartAnimationType.centerScale_otherSlide, - builder: (_) => Container( - width: imgWidth, - margin: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, - borderRadius: BorderRadius.circular(10.0), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Stack( - children: [ - GestureDetector( - onTap: SmartDialog.dismiss, - child: NetworkImgLayer( - width: imgWidth, - height: imgWidth / StyleString.aspectRatio, - src: cover, - quality: 100, - ), - ), - Positioned( - right: 8, - top: 8, - child: Container( - width: 30, - height: 30, - decoration: BoxDecoration( - color: Colors.black.withOpacity(0.3), - shape: BoxShape.circle, - ), - child: IconButton( - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: SmartDialog.dismiss, - icon: const Icon( - Icons.close, - size: 18, - color: Colors.white, - ), - ), - ), - ), - ], - ), - Padding( - padding: const EdgeInsets.fromLTRB(12, 10, 8, 10), - child: Row( + builder: (context) { + final theme = Theme.of(context); + return Container( + width: imgWidth, + margin: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + decoration: BoxDecoration( + color: theme.colorScheme.surface, + borderRadius: BorderRadius.circular(10.0), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Stack( children: [ - Expanded( - child: SelectableText( - title ?? '', - style: Theme.of(context).textTheme.titleSmall, + GestureDetector( + onTap: SmartDialog.dismiss, + child: NetworkImgLayer( + width: imgWidth, + height: imgWidth / StyleString.aspectRatio, + src: cover, + quality: 100, ), ), - if (cover?.isNotEmpty == true) ...[ - const SizedBox(width: 4), - iconButton( - context: context, - tooltip: '分享', - onPressed: () { - SmartDialog.dismiss(); - DownloadUtils.onShareImg(cover!); - }, - iconSize: 20, - icon: Icons.share, - bgColor: Colors.transparent, - iconColor: Theme.of(context).colorScheme.onSurfaceVariant, + Positioned( + right: 8, + top: 8, + child: Container( + width: 30, + height: 30, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.3), + shape: BoxShape.circle, + ), + child: IconButton( + style: ButtonStyle( + padding: WidgetStateProperty.all(EdgeInsets.zero), + ), + onPressed: SmartDialog.dismiss, + icon: const Icon( + Icons.close, + size: 18, + color: Colors.white, + ), + ), ), - iconButton( - context: context, - tooltip: '保存封面图', - onPressed: () async { - bool saveStatus = - await DownloadUtils.downloadImg(context, [cover!]); - if (saveStatus) { - SmartDialog.dismiss(); - } - }, - iconSize: 20, - icon: Icons.download, - bgColor: Colors.transparent, - iconColor: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ], + ), ], ), - ), - ], - ), - ), + Padding( + padding: const EdgeInsets.fromLTRB(12, 10, 8, 10), + child: Row( + children: [ + Expanded( + child: SelectableText( + title ?? '', + style: theme.textTheme.titleSmall, + ), + ), + if (cover?.isNotEmpty == true) ...[ + const SizedBox(width: 4), + iconButton( + context: context, + tooltip: '分享', + onPressed: () { + SmartDialog.dismiss(); + DownloadUtils.onShareImg(cover!); + }, + iconSize: 20, + icon: Icons.share, + bgColor: Colors.transparent, + iconColor: theme.colorScheme.onSurfaceVariant, + ), + iconButton( + context: context, + tooltip: '保存封面图', + onPressed: () async { + bool saveStatus = await DownloadUtils.downloadImg( + context, + [cover!], + ); + if (saveStatus) { + SmartDialog.dismiss(); + } + }, + iconSize: 20, + icon: Icons.download, + bgColor: Colors.transparent, + iconColor: theme.colorScheme.onSurfaceVariant, + ), + ], + ], + ), + ), + ], + ), + ); + }, ); } diff --git a/lib/common/widgets/report.dart b/lib/common/widgets/report.dart index 9dcb139c..cd4f3326 100644 --- a/lib/common/widgets/report.dart +++ b/lib/common/widgets/report.dart @@ -159,6 +159,7 @@ class _BanUserCheckboxState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return GestureDetector( onTap: () { setState(() => _banUid = !_banUid); @@ -174,13 +175,13 @@ class _BanUserCheckboxState extends State { ? Icons.check_box_outlined : Icons.check_box_outline_blank, color: _banUid - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurfaceVariant, + ? theme.colorScheme.primary + : theme.colorScheme.onSurfaceVariant, ), Text( ' 拉黑该用户', style: TextStyle( - color: _banUid ? Theme.of(context).colorScheme.primary : null, + color: _banUid ? theme.colorScheme.primary : null, ), ), ], diff --git a/lib/common/widgets/save_panel.dart b/lib/common/widgets/save_panel.dart index 100e547a..c64c83ac 100644 --- a/lib/common/widgets/save_panel.dart +++ b/lib/common/widgets/save_panel.dart @@ -275,6 +275,7 @@ class _SavePanelState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return GestureDetector( behavior: HitTestBehavior.opaque, onTap: Get.back, @@ -295,7 +296,7 @@ class _SavePanelState extends State { child: Container( clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, borderRadius: BorderRadius.circular(12), ), child: AnimatedSize( @@ -332,9 +333,7 @@ class _SavePanelState extends State { const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.all(8), decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .onInverseSurface, + color: theme.colorScheme.onInverseSurface, borderRadius: BorderRadius.circular(8), ), child: Row( @@ -369,9 +368,8 @@ class _SavePanelState extends State { .toString() .substring(0, 19), style: TextStyle( - color: Theme.of(context) - .colorScheme - .outline, + color: + theme.colorScheme.outline, ), ), ], @@ -405,10 +403,9 @@ class _SavePanelState extends State { overflow: TextOverflow .ellipsis, style: TextStyle( - color: - Theme.of(context) - .colorScheme - .primary, + color: theme + .colorScheme + .primary, ), ), const SizedBox(height: 4), @@ -417,8 +414,7 @@ class _SavePanelState extends State { '识别二维码,$viewType$itemType', textAlign: TextAlign.end, style: TextStyle( - color: Theme.of(context) - .colorScheme + color: theme.colorScheme .onSurfaceVariant, ), ), @@ -431,8 +427,7 @@ class _SavePanelState extends State { textAlign: TextAlign.end, style: TextStyle( fontSize: 13, - color: Theme.of(context) - .colorScheme + color: theme.colorScheme .outline, ), ), @@ -447,9 +442,8 @@ class _SavePanelState extends State { child: Container( color: Get.isDarkMode ? Colors.white - : Theme.of(context) - .colorScheme - .surface, + : theme + .colorScheme.surface, padding: const EdgeInsets.all(3), child: PrettyQrView.data( @@ -473,9 +467,8 @@ class _SavePanelState extends State { child: Image.asset( 'assets/images/logo/logo_2.png', width: 100, - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, + color: theme + .colorScheme.onSurfaceVariant, ), ), ], @@ -517,8 +510,8 @@ class _SavePanelState extends State { context: context, icon: Icons.clear, onPressed: Get.back, - bgColor: Theme.of(context).colorScheme.onInverseSurface, - iconColor: Theme.of(context).colorScheme.onSurfaceVariant, + bgColor: theme.colorScheme.onInverseSurface, + iconColor: theme.colorScheme.onSurfaceVariant, ), const SizedBox(width: 40), iconButton( diff --git a/lib/common/widgets/video_card_h.dart b/lib/common/widgets/video_card_h.dart index bcdddbd4..731f0549 100644 --- a/lib/common/widgets/video_card_h.dart +++ b/lib/common/widgets/video_card_h.dart @@ -64,7 +64,6 @@ class VideoCardH extends StatelessWidget { onLongPress!(); } else { imageSaveDialog( - context: context, title: videoItem.title, cover: videoItem.pic, ); @@ -213,6 +212,7 @@ class VideoCardH extends StatelessWidget { } Widget videoContent(BuildContext context) { + final theme = Theme.of(context); String pubdate = showPubdate ? Utils.dateFormat(videoItem.pubdate!, formatType: 'day') : ''; @@ -234,13 +234,12 @@ class VideoCardH extends StatelessWidget { TextSpan( text: i['text'], style: TextStyle( - fontSize: - Theme.of(context).textTheme.bodyMedium!.fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, height: 1.42, letterSpacing: 0.3, color: i['type'] == 'em' - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurface, + ? theme.colorScheme.primary + : theme.colorScheme.onSurface, ), ), ], @@ -253,7 +252,7 @@ class VideoCardH extends StatelessWidget { videoItem.title, textAlign: TextAlign.start, style: TextStyle( - fontSize: Theme.of(context).textTheme.bodyMedium!.fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, height: 1.42, letterSpacing: 0.3, ), @@ -268,7 +267,7 @@ class VideoCardH extends StatelessWidget { style: TextStyle( fontSize: 12, height: 1, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, overflow: TextOverflow.clip, ), ), diff --git a/lib/common/widgets/video_card_h_grpc.dart b/lib/common/widgets/video_card_h_grpc.dart index 3b41d3a3..1652863e 100644 --- a/lib/common/widgets/video_card_h_grpc.dart +++ b/lib/common/widgets/video_card_h_grpc.dart @@ -38,7 +38,6 @@ class VideoCardHGrpc extends StatelessWidget { child: InkWell( borderRadius: BorderRadius.circular(12), onLongPress: () => imageSaveDialog( - context: context, title: videoItem.smallCoverV5.base.title, cover: videoItem.smallCoverV5.base.cover, ), @@ -110,6 +109,7 @@ class VideoCardHGrpc extends StatelessWidget { } Widget videoContent(context) { + final theme = Theme.of(context); return Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -119,7 +119,7 @@ class VideoCardHGrpc extends StatelessWidget { videoItem.smallCoverV5.base.title, textAlign: TextAlign.start, style: TextStyle( - fontSize: Theme.of(context).textTheme.bodyMedium!.fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, height: 1.42, letterSpacing: 0.3, ), @@ -132,9 +132,9 @@ class VideoCardHGrpc extends StatelessWidget { videoItem.smallCoverV5.rightDesc1, maxLines: 1, style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, + fontSize: theme.textTheme.labelMedium!.fontSize, height: 1, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, overflow: TextOverflow.clip, ), ), @@ -143,9 +143,9 @@ class VideoCardHGrpc extends StatelessWidget { videoItem.smallCoverV5.rightDesc2, maxLines: 1, style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, + fontSize: theme.textTheme.labelMedium!.fontSize, height: 1, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, overflow: TextOverflow.clip, ), ), diff --git a/lib/common/widgets/video_card_h_member_video.dart b/lib/common/widgets/video_card_h_member_video.dart index 19b336d6..0e621b51 100644 --- a/lib/common/widgets/video_card_h_member_video.dart +++ b/lib/common/widgets/video_card_h_member_video.dart @@ -31,7 +31,6 @@ class VideoCardHMemberVideo extends StatelessWidget { children: [ InkWell( onLongPress: () => imageSaveDialog( - context: context, title: videoItem.title, cover: videoItem.cover, ), @@ -185,6 +184,7 @@ class VideoCardHMemberVideo extends StatelessWidget { } Widget videoContent(context) { + final theme = Theme.of(context); return Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -197,11 +197,11 @@ class VideoCardHMemberVideo extends StatelessWidget { fontWeight: videoItem.bvid != null && videoItem.bvid == bvid ? FontWeight.bold : null, - fontSize: Theme.of(context).textTheme.bodyMedium!.fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, height: 1.42, letterSpacing: 0.3, color: videoItem.bvid != null && videoItem.bvid == bvid - ? Theme.of(context).colorScheme.primary + ? theme.colorScheme.primary : null, ), maxLines: 2, @@ -216,7 +216,7 @@ class VideoCardHMemberVideo extends StatelessWidget { style: TextStyle( fontSize: 12, height: 1, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, overflow: TextOverflow.clip, ), ), diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index 9b8ce3eb..86efdf3b 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -38,8 +38,8 @@ class VideoCardV extends StatelessWidget { break; case 'av': String bvid = videoItem.bvid ?? IdUtils.av2bv(videoItem.aid!); - int cid = videoItem.cid!; - if (cid == -1) { + int? cid = videoItem.cid; + if (cid == null || cid == 0 || cid == -1) { cid = await SearchHttp.ab2c(aid: videoItem.aid, bvid: bvid); } PageUtils.toVideoPage( @@ -100,7 +100,6 @@ class VideoCardV extends StatelessWidget { child: InkWell( onTap: () => onPushDetail(Utils.makeHeroTag(videoItem.aid)), onLongPress: () => imageSaveDialog( - context: context, title: videoItem.title, cover: videoItem.pic, ), @@ -152,6 +151,7 @@ class VideoCardV extends StatelessWidget { } Widget videoContent(context) { + final theme = Theme.of(context); return Expanded( child: Padding( padding: const EdgeInsets.fromLTRB(6, 5, 6, 5), @@ -168,7 +168,7 @@ class VideoCardV extends StatelessWidget { ), ), ), - videoStat(context), + videoStat(context, theme), Row( children: [ if (videoItem.goto == 'bangumi') ...[ @@ -217,9 +217,8 @@ class VideoCardV extends StatelessWidget { overflow: TextOverflow.clip, style: TextStyle( height: 1.5, - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), ), ), @@ -232,7 +231,7 @@ class VideoCardV extends StatelessWidget { ); } - Widget videoStat(context) { + Widget videoStat(BuildContext context, ThemeData theme) { return Row( children: [ StatView( @@ -254,8 +253,8 @@ class VideoCardV extends StatelessWidget { maxLines: 1, TextSpan( style: TextStyle( - fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, - color: Theme.of(context).colorScheme.outline.withOpacity(0.8), + fontSize: theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline.withOpacity(0.8), ), text: Utils.formatTimestampToRelativeTime(videoItem.pubdate)), ), @@ -268,8 +267,8 @@ class VideoCardV extends StatelessWidget { maxLines: 1, TextSpan( style: TextStyle( - fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, - color: Theme.of(context).colorScheme.outline.withOpacity(0.8), + fontSize: theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline.withOpacity(0.8), ), text: Utils.shortenChineseDateString( videoItem.desc!.split(' · ').last)), diff --git a/lib/common/widgets/video_card_v_member_home.dart b/lib/common/widgets/video_card_v_member_home.dart index ad8c323b..96312664 100644 --- a/lib/common/widgets/video_card_v_member_home.dart +++ b/lib/common/widgets/video_card_v_member_home.dart @@ -64,7 +64,6 @@ class VideoCardVMemberHome extends StatelessWidget { child: InkWell( onTap: () => onPushDetail(Utils.makeHeroTag(videoItem.bvid)), onLongPress: () => imageSaveDialog( - context: context, title: videoItem.title, cover: videoItem.cover, ), diff --git a/lib/pages/about/view.dart b/lib/pages/about/view.dart index a425c857..7df72d7a 100644 --- a/lib/pages/about/view.dart +++ b/lib/pages/about/view.dart @@ -35,9 +35,6 @@ class _AboutPageState extends State { late int _pressCount = 0; - late Color outline; - late TextStyle subTitleStyle; - @override void initState() { super.initState(); @@ -56,16 +53,11 @@ class _AboutPageState extends State { currentVersion.value = "${currentInfo.version}+$buildNumber"; } - @override - void didChangeDependencies() { - super.didChangeDependencies(); - outline = Theme.of(context).colorScheme.outline; - subTitleStyle = - TextStyle(fontSize: 13, color: Theme.of(context).colorScheme.outline); - } - @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final outline = theme.colorScheme.outline; + final subTitleStyle = TextStyle(fontSize: 13, color: outline); return Scaffold( appBar: widget.showAppBar == false ? null : AppBar(title: const Text('关于')), @@ -107,8 +99,7 @@ class _AboutPageState extends State { title: Text( 'PiliPlus', textAlign: TextAlign.center, - style: - Theme.of(context).textTheme.titleMedium!.copyWith(height: 2), + style: theme.textTheme.titleMedium!.copyWith(height: 2), ), subtitle: Row( mainAxisAlignment: MainAxisAlignment.center, @@ -153,7 +144,7 @@ Commit Hash: ${BuildConfig.commitHash}''', Divider( thickness: 1, height: 30, - color: Theme.of(context).colorScheme.outlineVariant, + color: theme.colorScheme.outlineVariant, ), ListTile( onTap: () => PageUtils.launchURL(_sourceCodeUrl), diff --git a/lib/pages/article/view.dart b/lib/pages/article/view.dart index c1ecbf8e..d6ef37a5 100644 --- a/lib/pages/article/view.dart +++ b/lib/pages/article/view.dart @@ -227,6 +227,7 @@ class _ArticlePageState extends State @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( resizeToAvoidBottomInset: false, appBar: _buildAppBar, @@ -249,18 +250,16 @@ class _ArticlePageState extends State controller: _articleCtr.scrollController, physics: const AlwaysScrollableScrollPhysics(), slivers: [ - _buildContent(maxWidth), + _buildContent(theme, maxWidth), SliverToBoxAdapter( child: Divider( thickness: 8, - color: Theme.of(context) - .dividerColor - .withOpacity(0.05), + color: theme.dividerColor.withOpacity(0.05), ), ), _buildReplyHeader, - Obx(() => - _buildReplyList(_articleCtr.loadingState.value)), + Obx(() => _buildReplyList( + theme, _articleCtr.loadingState.value)), ], ), ); @@ -286,7 +285,7 @@ class _ArticlePageState extends State MediaQuery.paddingOf(context).bottom + 80, ), - sliver: _buildContent(maxWidth), + sliver: _buildContent(theme, maxWidth), ), ], ); @@ -295,7 +294,7 @@ class _ArticlePageState extends State ), VerticalDivider( thickness: 8, - color: Theme.of(context).dividerColor.withOpacity(0.05), + color: theme.dividerColor.withOpacity(0.05), ), Expanded( flex: _ratio[1].toInt(), @@ -314,7 +313,7 @@ class _ArticlePageState extends State slivers: [ _buildReplyHeader, Obx(() => _buildReplyList( - _articleCtr.loadingState.value)), + theme, _articleCtr.loadingState.value)), ], ), ), @@ -327,13 +326,13 @@ class _ArticlePageState extends State }, ), ), - _buildBottom, + _buildBottom(theme), ], ), ); } - Widget _buildContent(double maxWidth) => SliverPadding( + Widget _buildContent(ThemeData theme, double maxWidth) => SliverPadding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), sliver: Obx( () { @@ -401,22 +400,17 @@ class _ArticlePageState extends State Text( _articleCtr.summary.author?.name ?? '', style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .titleSmall! - .fontSize, + fontSize: + theme.textTheme.titleSmall!.fontSize, ), ), if (pubTime != null) Text( Utils.dateFormat(pubTime), style: TextStyle( - color: - Theme.of(context).colorScheme.outline, - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, + color: theme.colorScheme.outline, + fontSize: + theme.textTheme.labelSmall!.fontSize, ), ), ], @@ -436,7 +430,8 @@ class _ArticlePageState extends State ), ); - Widget _buildReplyList(LoadingState?> loadingState) { + Widget _buildReplyList( + ThemeData theme, LoadingState?> loadingState) { return switch (loadingState) { Loading() => SliverList.builder( itemCount: 12, @@ -463,7 +458,7 @@ class _ArticlePageState extends State : '没有更多了', style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ); @@ -663,7 +658,7 @@ class _ArticlePageState extends State ], ); - Widget get _buildBottom => Positioned( + Widget _buildBottom(ThemeData theme) => Positioned( left: 0, bottom: 0, right: 0, @@ -711,8 +706,8 @@ class _ArticlePageState extends State }) { final show = stat?.status == true; final color = show - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline; + ? theme.colorScheme.primary + : theme.colorScheme.outline; return TextButton.icon( onPressed: callback, icon: Icon( @@ -723,8 +718,7 @@ class _ArticlePageState extends State ), style: TextButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 15), - foregroundColor: - Theme.of(context).colorScheme.outline, + foregroundColor: theme.colorScheme.outline, ), label: Text(stat?.count != null ? Utils.numFormat(stat!.count) @@ -749,13 +743,10 @@ class _ArticlePageState extends State _articleCtr.stats.value != null ? Container( decoration: BoxDecoration( - color: - Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, border: Border( top: BorderSide( - color: Theme.of(context) - .colorScheme - .outline + color: theme.colorScheme.outline .withOpacity(0.08), ), ), @@ -858,12 +849,8 @@ class _ArticlePageState extends State color: _articleCtr.stats.value ?.like?.status == true - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .outline, + ? theme.colorScheme.primary + : theme.colorScheme.outline, semanticLabel: _articleCtr .stats .value @@ -877,9 +864,8 @@ class _ArticlePageState extends State padding: const EdgeInsets.symmetric( horizontal: 15), - foregroundColor: Theme.of(context) - .colorScheme - .outline, + foregroundColor: + theme.colorScheme.outline, ), label: AnimatedSwitcher( duration: const Duration( @@ -902,12 +888,10 @@ class _ArticlePageState extends State color: _articleCtr.stats.value ?.like?.status == true - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .outline, + ? theme + .colorScheme.primary + : theme + .colorScheme.outline, ), ), ), diff --git a/lib/pages/bangumi/introduction/view.dart b/lib/pages/bangumi/introduction/view.dart index caa3fc51..fe8576f8 100644 --- a/lib/pages/bangumi/introduction/view.dart +++ b/lib/pages/bangumi/introduction/view.dart @@ -179,7 +179,7 @@ class _BangumiInfoState extends State { @override Widget build(BuildContext context) { - final ThemeData t = Theme.of(context); + final ThemeData theme = Theme.of(context); bool isLandscape = MediaQuery.of(context).orientation == Orientation.landscape; return SliverPadding( @@ -282,12 +282,12 @@ class _BangumiInfoState extends State { foregroundColor: bangumiIntroController .isFollowed.value - ? t.colorScheme.outline + ? theme.colorScheme.outline : null, backgroundColor: bangumiIntroController .isFollowed.value - ? t.colorScheme + ? theme.colorScheme .onInverseSurface : null, ), @@ -353,28 +353,32 @@ class _BangumiInfoState extends State { if (isLandscape) ...[ const SizedBox(width: 6), AreasAndPubTime( - widget: widget, - bangumiItem: bangumiItem, - t: t), + widget: widget, + bangumiItem: bangumiItem, + theme: theme, + ), const SizedBox(width: 6), NewEpDesc( - widget: widget, - bangumiItem: bangumiItem, - t: t), + widget: widget, + bangumiItem: bangumiItem, + theme: theme, + ), ] ], ), SizedBox(height: isLandscape ? 2 : 6), if (!isLandscape) AreasAndPubTime( - widget: widget, - bangumiItem: bangumiItem, - t: t), + widget: widget, + bangumiItem: bangumiItem, + theme: theme, + ), if (!isLandscape) NewEpDesc( - widget: widget, - bangumiItem: bangumiItem, - t: t), + widget: widget, + bangumiItem: bangumiItem, + theme: theme, + ), const Spacer(), Text( '简介:${!widget.isLoading ? widget.bangumiDetail!.evaluate! : bangumiItem!.evaluate!}', @@ -382,7 +386,7 @@ class _BangumiInfoState extends State { overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 13, - color: t.colorScheme.outline, + color: theme.colorScheme.outline, ), ), ], @@ -394,7 +398,7 @@ class _BangumiInfoState extends State { ), const SizedBox(height: 6), // 点赞收藏转发 布局样式2 - actionGrid(context, bangumiIntroController), + actionGrid(theme, bangumiIntroController), // 番剧分p if ((!widget.isLoading && widget.bangumiDetail!.episodes!.isNotEmpty) || @@ -427,115 +431,111 @@ class _BangumiInfoState extends State { } Widget actionGrid( - BuildContext context, BangumiIntroController bangumiIntroController) { - return LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - return Material( - color: Theme.of(context).colorScheme.surface, - child: Padding( - padding: const EdgeInsets.only(top: 1), - child: SizedBox( - height: 48, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Obx( - () => ActionItem( - icon: const Icon(FontAwesomeIcons.thumbsUp), - selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), - onTap: () => - handleState(bangumiIntroController.actionLikeVideo), - onLongPress: bangumiIntroController.actionOneThree, - selectStatus: bangumiIntroController.hasLike.value, - loadingStatus: false, - semanticsLabel: '点赞', - text: !widget.isLoading - ? Utils.numFormat(widget.bangumiDetail!.stat!['likes']!) - : Utils.numFormat( - bangumiItem!.stat!['likes']!, - ), - needAnim: true, - hasTriple: bangumiIntroController.hasLike.value && - bangumiIntroController.hasCoin && - bangumiIntroController.hasFav.value, - callBack: (start) { - if (start) { - HapticFeedback.lightImpact(); - _coinKey.currentState?.controller?.forward(); - _favKey.currentState?.controller?.forward(); - } else { - _coinKey.currentState?.controller?.reverse(); - _favKey.currentState?.controller?.reverse(); - } - }, - ), + ThemeData theme, BangumiIntroController bangumiIntroController) { + return Material( + color: theme.colorScheme.surface, + child: Padding( + padding: const EdgeInsets.only(top: 1), + child: SizedBox( + height: 48, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Obx( + () => ActionItem( + icon: const Icon(FontAwesomeIcons.thumbsUp), + selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp), + onTap: () => + handleState(bangumiIntroController.actionLikeVideo), + onLongPress: bangumiIntroController.actionOneThree, + selectStatus: bangumiIntroController.hasLike.value, + loadingStatus: false, + semanticsLabel: '点赞', + text: !widget.isLoading + ? Utils.numFormat(widget.bangumiDetail!.stat!['likes']!) + : Utils.numFormat( + bangumiItem!.stat!['likes']!, + ), + needAnim: true, + hasTriple: bangumiIntroController.hasLike.value && + bangumiIntroController.hasCoin && + bangumiIntroController.hasFav.value, + callBack: (start) { + if (start) { + HapticFeedback.lightImpact(); + _coinKey.currentState?.controller?.forward(); + _favKey.currentState?.controller?.forward(); + } else { + _coinKey.currentState?.controller?.reverse(); + _favKey.currentState?.controller?.reverse(); + } + }, ), - Obx( - () => ActionItem( - key: _coinKey, - icon: const Icon(FontAwesomeIcons.b), - selectIcon: const Icon(FontAwesomeIcons.b), - onTap: () => - handleState(bangumiIntroController.actionCoinVideo), - selectStatus: bangumiIntroController.hasCoin, - loadingStatus: false, - semanticsLabel: '投币', - text: !widget.isLoading - ? Utils.numFormat(widget.bangumiDetail!.stat!['coins']!) - : Utils.numFormat( - bangumiItem!.stat!['coins']!, - ), - needAnim: true, - ), + ), + Obx( + () => ActionItem( + key: _coinKey, + icon: const Icon(FontAwesomeIcons.b), + selectIcon: const Icon(FontAwesomeIcons.b), + onTap: () => + handleState(bangumiIntroController.actionCoinVideo), + selectStatus: bangumiIntroController.hasCoin, + loadingStatus: false, + semanticsLabel: '投币', + text: !widget.isLoading + ? Utils.numFormat(widget.bangumiDetail!.stat!['coins']!) + : Utils.numFormat( + bangumiItem!.stat!['coins']!, + ), + needAnim: true, ), - Obx( - () => ActionItem( - key: _favKey, - icon: const Icon(FontAwesomeIcons.star), - selectIcon: const Icon(FontAwesomeIcons.solidStar), - onTap: () => - bangumiIntroController.showFavBottomSheet(context), - onLongPress: () => bangumiIntroController - .showFavBottomSheet(context, type: 'longPress'), - selectStatus: bangumiIntroController.hasFav.value, - loadingStatus: false, - semanticsLabel: '收藏', - text: !widget.isLoading - ? Utils.numFormat( - widget.bangumiDetail!.stat!['favorite']!) - : Utils.numFormat( - bangumiItem!.stat!['favorite']!, - ), - needAnim: true, - ), + ), + Obx( + () => ActionItem( + key: _favKey, + icon: const Icon(FontAwesomeIcons.star), + selectIcon: const Icon(FontAwesomeIcons.solidStar), + onTap: () => + bangumiIntroController.showFavBottomSheet(context), + onLongPress: () => bangumiIntroController + .showFavBottomSheet(context, type: 'longPress'), + selectStatus: bangumiIntroController.hasFav.value, + loadingStatus: false, + semanticsLabel: '收藏', + text: !widget.isLoading + ? Utils.numFormat( + widget.bangumiDetail!.stat!['favorite']!) + : Utils.numFormat( + bangumiItem!.stat!['favorite']!, + ), + needAnim: true, ), - ActionItem( - icon: const Icon(FontAwesomeIcons.comment), - selectIcon: const Icon(FontAwesomeIcons.reply), - onTap: () => videoDetailCtr.tabCtr.animateTo(1), + ), + ActionItem( + icon: const Icon(FontAwesomeIcons.comment), + selectIcon: const Icon(FontAwesomeIcons.reply), + onTap: () => videoDetailCtr.tabCtr.animateTo(1), + selectStatus: false, + loadingStatus: false, + semanticsLabel: '评论', + text: !widget.isLoading + ? Utils.numFormat(widget.bangumiDetail!.stat!['reply']!) + : Utils.numFormat(bangumiItem!.stat!['reply']!), + ), + ActionItem( + icon: const Icon(FontAwesomeIcons.shareFromSquare), + onTap: () => bangumiIntroController.actionShareVideo(context), selectStatus: false, loadingStatus: false, - semanticsLabel: '评论', + semanticsLabel: '转发', text: !widget.isLoading - ? Utils.numFormat(widget.bangumiDetail!.stat!['reply']!) - : Utils.numFormat(bangumiItem!.stat!['reply']!), - ), - ActionItem( - icon: const Icon(FontAwesomeIcons.shareFromSquare), - onTap: () => - bangumiIntroController.actionShareVideo(context), - selectStatus: false, - loadingStatus: false, - semanticsLabel: '转发', - text: !widget.isLoading - ? Utils.numFormat(widget.bangumiDetail!.stat!['share']!) - : Utils.numFormat(bangumiItem!.stat!['share']!)), - ], - ), + ? Utils.numFormat(widget.bangumiDetail!.stat!['share']!) + : Utils.numFormat(bangumiItem!.stat!['share']!)), + ], ), ), - ); - }); + ), + ); } Widget actionRow( @@ -609,12 +609,12 @@ class AreasAndPubTime extends StatelessWidget { super.key, required this.widget, required this.bangumiItem, - required this.t, + required this.theme, }); final BangumiInfo widget; final BangumiInfoModel? bangumiItem; - final ThemeData t; + final ThemeData theme; @override Widget build(BuildContext context) { @@ -630,7 +630,7 @@ class AreasAndPubTime extends StatelessWidget { : ''), style: TextStyle( fontSize: 12, - color: t.colorScheme.outline, + color: theme.colorScheme.outline, ), ), const SizedBox(width: 6), @@ -640,7 +640,7 @@ class AreasAndPubTime extends StatelessWidget { : bangumiItem!.publish!['pub_time_show'], style: TextStyle( fontSize: 12, - color: t.colorScheme.outline, + color: theme.colorScheme.outline, ), ), ], @@ -653,12 +653,12 @@ class NewEpDesc extends StatelessWidget { super.key, required this.widget, required this.bangumiItem, - required this.t, + required this.theme, }); final BangumiInfo widget; final BangumiInfoModel? bangumiItem; - final ThemeData t; + final ThemeData theme; @override Widget build(BuildContext context) { @@ -668,7 +668,7 @@ class NewEpDesc extends StatelessWidget { : bangumiItem!.newEp!['desc'], style: TextStyle( fontSize: 12, - color: t.colorScheme.outline, + color: theme.colorScheme.outline, ), ); } diff --git a/lib/pages/bangumi/introduction/widgets/intro_detail.dart b/lib/pages/bangumi/introduction/widgets/intro_detail.dart index 07afd5ce..0c826006 100644 --- a/lib/pages/bangumi/introduction/widgets/intro_detail.dart +++ b/lib/pages/bangumi/introduction/widgets/intro_detail.dart @@ -22,15 +22,10 @@ class IntroDetail extends CommonCollapseSlidePage { } class _IntroDetailState extends CommonCollapseSlidePageState { - late final TextStyle smallTitle = TextStyle( - fontSize: 12, - color: Theme.of(context).colorScheme.onSurface, - ); - @override - Widget get buildPage { + Widget buildPage(ThemeData theme) { return Material( - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, child: Column( children: [ GestureDetector( @@ -44,16 +39,14 @@ class _IntroDetailState extends CommonCollapseSlidePageState { width: 32, height: 3, decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .onSecondaryContainer - .withOpacity(0.5), + color: + theme.colorScheme.onSecondaryContainer.withOpacity(0.5), borderRadius: const BorderRadius.all(Radius.circular(3))), ), ), ), Expanded( - child: enableSlide ? slideList() : buildList, + child: enableSlide ? slideList(theme) : buildList(theme), ) ], ), @@ -61,98 +54,104 @@ class _IntroDetailState extends CommonCollapseSlidePageState { } @override - Widget get buildList => ListView( - controller: ScrollController(), - physics: const AlwaysScrollableScrollPhysics(), - padding: EdgeInsets.only( - left: 14, - right: 14, - bottom: MediaQuery.paddingOf(context).bottom + 80, + Widget buildList(ThemeData theme) { + final TextStyle smallTitle = TextStyle( + fontSize: 12, + color: theme.colorScheme.onSurface, + ); + return ListView( + controller: ScrollController(), + physics: const AlwaysScrollableScrollPhysics(), + padding: EdgeInsets.only( + left: 14, + right: 14, + bottom: MediaQuery.paddingOf(context).bottom + 80, + ), + children: [ + SelectableText( + widget.bangumiDetail.title!, + style: const TextStyle( + fontSize: 16, + ), ), - children: [ - SelectableText( - widget.bangumiDetail.title!, - style: const TextStyle( - fontSize: 16, + const SizedBox(height: 4), + Row( + children: [ + StatView( + context: context, + theme: 'gray', + value: Utils.numFormat(widget.bangumiDetail.stat!['views']), + ), + const SizedBox(width: 6), + StatDanMu( + context: context, + theme: 'gray', + value: Utils.numFormat(widget.bangumiDetail.stat!['danmakus']), ), - ), - const SizedBox(height: 4), - Row( - children: [ - StatView( - context: context, - theme: 'gray', - value: Utils.numFormat(widget.bangumiDetail.stat!['views']), - ), - const SizedBox(width: 6), - StatDanMu( - context: context, - theme: 'gray', - value: Utils.numFormat(widget.bangumiDetail.stat!['danmakus']), - ), - ], - ), - const SizedBox(height: 4), - Row( - children: [ - Text( - widget.bangumiDetail.areas!.first['name'], - style: smallTitle, - ), - const SizedBox(width: 6), - Text( - widget.bangumiDetail.publish!['pub_time_show'], - style: smallTitle, - ), - const SizedBox(width: 6), - Text( - widget.bangumiDetail.newEp!['desc'], - style: smallTitle, - ), - ], - ), - const SizedBox(height: 20), - Text( - '简介:', - style: Theme.of(context).textTheme.titleMedium, - ), - const SizedBox(height: 4), - SelectableText( - widget.bangumiDetail.evaluate!, - style: smallTitle.copyWith(fontSize: 14), - ), - const SizedBox(height: 20), - Text( - '声优:', - style: Theme.of(context).textTheme.titleMedium, - ), - const SizedBox(height: 4), - SelectableText( - widget.bangumiDetail.actors!, - style: smallTitle.copyWith(fontSize: 14), - ), - if (widget.videoTags is List && widget.videoTags.isNotEmpty) ...[ - const SizedBox(height: 10), - Wrap( - spacing: 8, - runSpacing: 8, - children: (widget.videoTags as List) - .map( - (item) => SearchText( - fontSize: 13, - text: item['tag_name'], - onTap: (_) => Get.toNamed( - '/searchResult', - parameters: { - 'keyword': item['tag_name'], - }, - ), - onLongPress: (_) => Utils.copyText(item['tag_name']), - ), - ) - .toList(), - ) ], + ), + const SizedBox(height: 4), + Row( + children: [ + Text( + widget.bangumiDetail.areas!.first['name'], + style: smallTitle, + ), + const SizedBox(width: 6), + Text( + widget.bangumiDetail.publish!['pub_time_show'], + style: smallTitle, + ), + const SizedBox(width: 6), + Text( + widget.bangumiDetail.newEp!['desc'], + style: smallTitle, + ), + ], + ), + const SizedBox(height: 20), + Text( + '简介:', + style: theme.textTheme.titleMedium, + ), + const SizedBox(height: 4), + SelectableText( + widget.bangumiDetail.evaluate!, + style: smallTitle.copyWith(fontSize: 14), + ), + const SizedBox(height: 20), + Text( + '声优:', + style: theme.textTheme.titleMedium, + ), + const SizedBox(height: 4), + SelectableText( + widget.bangumiDetail.actors!, + style: smallTitle.copyWith(fontSize: 14), + ), + if (widget.videoTags is List && widget.videoTags.isNotEmpty) ...[ + const SizedBox(height: 10), + Wrap( + spacing: 8, + runSpacing: 8, + children: (widget.videoTags as List) + .map( + (item) => SearchText( + fontSize: 13, + text: item['tag_name'], + onTap: (_) => Get.toNamed( + '/searchResult', + parameters: { + 'keyword': item['tag_name'], + }, + ), + onLongPress: (_) => Utils.copyText(item['tag_name']), + ), + ) + .toList(), + ) ], - ); + ], + ); + } } diff --git a/lib/pages/bangumi/pgc_index/pgc_index_page.dart b/lib/pages/bangumi/pgc_index/pgc_index_page.dart index 5423cbfe..3faf1b7a 100644 --- a/lib/pages/bangumi/pgc_index/pgc_index_page.dart +++ b/lib/pages/bangumi/pgc_index/pgc_index_page.dart @@ -35,15 +35,16 @@ class _PgcIndexPageState extends State @override Widget build(BuildContext context) { super.build(context); + final theme = Theme.of(context); return widget.indexType == null ? Scaffold( appBar: AppBar(title: const Text('索引')), - body: Obx(() => _buildBody(_ctr.conditionState.value)), + body: Obx(() => _buildBody(theme, _ctr.conditionState.value)), ) - : Obx(() => _buildBody(_ctr.conditionState.value)); + : Obx(() => _buildBody(theme, _ctr.conditionState.value)); } - Widget _buildBody(LoadingState loadingState) { + Widget _buildBody(ThemeData theme, LoadingState loadingState) { return switch (loadingState) { Loading() => loadingWidget, Success() => Builder(builder: (context) { @@ -63,8 +64,8 @@ class _PgcIndexPageState extends State alignment: Alignment.topCenter, duration: const Duration(milliseconds: 200), child: count > 5 - ? Obx(() => _buildSortWidget(count, data)) - : _buildSortWidget(count, data), + ? Obx(() => _buildSortWidget(theme, count, data)) + : _buildSortWidget(theme, count, data), ), ), SliverPadding( @@ -90,7 +91,7 @@ class _PgcIndexPageState extends State }; } - Widget _buildSortWidget(count, data) => Column( + Widget _buildSortWidget(ThemeData theme, count, data) => Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -129,9 +130,7 @@ class _PgcIndexPageState extends State (item[childIndex] is Order ? item[childIndex].field : item[childIndex].keyword) - ? Theme.of(context) - .colorScheme - .secondaryContainer + ? theme.colorScheme.secondaryContainer : Colors.transparent, textColor: (item[childIndex] is Order ? _ctr.indexParams['order'] @@ -144,12 +143,8 @@ class _PgcIndexPageState extends State (item[childIndex] is Order ? item[childIndex].field : item[childIndex].keyword) - ? Theme.of(context) - .colorScheme - .onSecondaryContainer - : Theme.of(context) - .colorScheme - .onSurfaceVariant, + ? theme.colorScheme.onSecondaryContainer + : theme.colorScheme.onSurfaceVariant, text: item[childIndex].name, padding: const EdgeInsets.symmetric( horizontal: 6, @@ -192,14 +187,14 @@ class _PgcIndexPageState extends State Text( _ctr.isExpand.value ? '收起' : '展开', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), Icon( _ctr.isExpand.value ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ], ), diff --git a/lib/pages/bangumi/view.dart b/lib/pages/bangumi/view.dart index b0dbadd0..79a5a567 100644 --- a/lib/pages/bangumi/view.dart +++ b/lib/pages/bangumi/view.dart @@ -46,6 +46,7 @@ class _BangumiPageState extends CommonPageState @override Widget build(BuildContext context) { super.build(context); + final ThemeData theme = Theme.of(context); return refreshIndicator( onRefresh: () async { await controller.onRefresh(); @@ -54,17 +55,17 @@ class _BangumiPageState extends CommonPageState controller: controller.scrollController, physics: const AlwaysScrollableScrollPhysics(), slivers: [ - _buildFollow, + _buildFollow(theme), if (controller.showPgcTimeline) SliverToBoxAdapter( child: SizedBox( height: Grid.smallCardWidth / 2 / 0.75 + MediaQuery.textScalerOf(context).scale(96), - child: - Obx(() => _buildTimeline(controller.timelineState.value)), + child: Obx(() => + _buildTimeline(theme, controller.timelineState.value)), ), ), - ..._buildRcmd, + ..._buildRcmd(theme), ], ), ); @@ -80,7 +81,8 @@ class _BangumiPageState extends CommonPageState '日', ]; - Widget _buildTimeline(LoadingState?> loadingState) => + Widget _buildTimeline( + ThemeData theme, LoadingState?> loadingState) => switch (loadingState) { Loading() => loadingWidget, Success() => loadingState.response?.isNotEmpty == true @@ -99,7 +101,7 @@ class _BangumiPageState extends CommonPageState const SizedBox(width: 16), Text( '追番时间表', - style: Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, ), const SizedBox(width: 16), Expanded( @@ -118,16 +120,13 @@ class _BangumiPageState extends CommonPageState vertical: 10, ), indicator: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer, + color: theme.colorScheme.secondaryContainer, borderRadius: const BorderRadius.all( Radius.circular(20)), ), indicatorSize: TabBarIndicatorSize.tab, - labelColor: Theme.of(context) - .colorScheme - .onSecondaryContainer, + labelColor: + theme.colorScheme.onSecondaryContainer, labelStyle: TabBarTheme.of(context) .labelStyle ?.copyWith(fontSize: 14) ?? @@ -200,8 +199,8 @@ class _BangumiPageState extends CommonPageState ), }; - List get _buildRcmd => [ - _buildRcmdTitle, + List _buildRcmd(ThemeData theme) => [ + _buildRcmdTitle(theme), SliverPadding( padding: const EdgeInsets.fromLTRB( StyleString.safeSpace, 0, StyleString.safeSpace, 0), @@ -211,7 +210,7 @@ class _BangumiPageState extends CommonPageState ), ]; - Widget get _buildRcmdTitle => SliverToBoxAdapter( + Widget _buildRcmdTitle(ThemeData theme) => SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only( top: 10, @@ -224,7 +223,7 @@ class _BangumiPageState extends CommonPageState children: [ Text( '推荐', - style: Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, ), GestureDetector( behavior: HitTestBehavior.opaque, @@ -279,12 +278,12 @@ class _BangumiPageState extends CommonPageState strutStyle: StrutStyle(leading: 0, height: 1), style: TextStyle( height: 1, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), Icon( Icons.chevron_right, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ], ), @@ -332,12 +331,12 @@ class _BangumiPageState extends CommonPageState }; } - Widget get _buildFollow => SliverToBoxAdapter( + Widget _buildFollow(ThemeData theme) => SliverToBoxAdapter( child: Obx( () => controller.isLogin.value ? Column( children: [ - _buildFollowTitle, + _buildFollowTitle(theme), SizedBox( height: Grid.smallCardWidth / 2 / 0.75 + MediaQuery.textScalerOf(context).scale(50), @@ -351,14 +350,14 @@ class _BangumiPageState extends CommonPageState ), ); - Widget get _buildFollowTitle => Padding( + Widget _buildFollowTitle(ThemeData theme) => Padding( padding: const EdgeInsets.only(left: 16), child: Row( children: [ Obx( () => Text( '最近${widget.tabType == TabType.bangumi ? '追番' : '追剧'}${controller.followCount.value == -1 ? '' : ' ${controller.followCount.value}'}', - style: Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, ), ), const Spacer(), @@ -398,13 +397,12 @@ class _BangumiPageState extends CommonPageState strutStyle: StrutStyle(leading: 0, height: 1), style: TextStyle( height: 1, - color: - Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), Icon( Icons.chevron_right, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ], ), diff --git a/lib/pages/bangumi/widgets/bangumi_card_v.dart b/lib/pages/bangumi/widgets/bangumi_card_v.dart index c139f445..1550ee30 100644 --- a/lib/pages/bangumi/widgets/bangumi_card_v.dart +++ b/lib/pages/bangumi/widgets/bangumi_card_v.dart @@ -23,7 +23,6 @@ class BangumiCardV extends StatelessWidget { margin: EdgeInsets.zero, child: InkWell( onLongPress: () => imageSaveDialog( - context: context, title: bangumiItem.title, cover: bangumiItem.cover, ), @@ -88,6 +87,11 @@ class BangumiCardV extends StatelessWidget { } Widget bagumiContent(context) { + final theme = Theme.of(context); + final style = TextStyle( + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, + ); return Expanded( child: Padding( padding: const EdgeInsets.fromLTRB(4, 5, 0, 3), @@ -108,19 +112,13 @@ class BangumiCardV extends StatelessWidget { Text( bangumiItem.indexShow, maxLines: 1, - style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), + style: style, ), if (bangumiItem.progress != null) Text( bangumiItem.progress, maxLines: 1, - style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, - ), + style: style, ), ], ), diff --git a/lib/pages/bangumi/widgets/bangumi_card_v_member_home.dart b/lib/pages/bangumi/widgets/bangumi_card_v_member_home.dart index 1d36a6da..af9e9880 100644 --- a/lib/pages/bangumi/widgets/bangumi_card_v_member_home.dart +++ b/lib/pages/bangumi/widgets/bangumi_card_v_member_home.dart @@ -27,7 +27,6 @@ class BangumiCardVMemberHome extends StatelessWidget { PageUtils.viewBangumi(seasonId: seasonId); }, onLongPress: () => imageSaveDialog( - context: context, title: bangumiItem.title, cover: bangumiItem.cover, ), diff --git a/lib/pages/bangumi/widgets/bangumi_card_v_pgc_index.dart b/lib/pages/bangumi/widgets/bangumi_card_v_pgc_index.dart index dcfbb613..8474b435 100644 --- a/lib/pages/bangumi/widgets/bangumi_card_v_pgc_index.dart +++ b/lib/pages/bangumi/widgets/bangumi_card_v_pgc_index.dart @@ -21,7 +21,6 @@ class BangumiCardVPgcIndex extends StatelessWidget { margin: EdgeInsets.zero, child: InkWell( onLongPress: () => imageSaveDialog( - context: context, title: bangumiItem['title'], cover: bangumiItem['cover'], ), @@ -73,6 +72,7 @@ class BangumiCardVPgcIndex extends StatelessWidget { } Widget bagumiContent(context) { + final theme = Theme.of(context); return Expanded( child: Padding( padding: const EdgeInsets.fromLTRB(4, 5, 0, 3), @@ -94,8 +94,8 @@ class BangumiCardVPgcIndex extends StatelessWidget { bangumiItem['index_show'], maxLines: 1, style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), ), ], diff --git a/lib/pages/bangumi/widgets/bangumi_card_v_search.dart b/lib/pages/bangumi/widgets/bangumi_card_v_search.dart index e36f60de..d1e9e718 100644 --- a/lib/pages/bangumi/widgets/bangumi_card_v_search.dart +++ b/lib/pages/bangumi/widgets/bangumi_card_v_search.dart @@ -22,7 +22,6 @@ class BangumiCardVSearch extends StatelessWidget { margin: EdgeInsets.zero, child: InkWell( onLongPress: () => imageSaveDialog( - context: context, title: item.title?.map((e) => e['text']).join(), cover: item.cover, ), diff --git a/lib/pages/bangumi/widgets/bangumi_card_v_timeline.dart b/lib/pages/bangumi/widgets/bangumi_card_v_timeline.dart index 8d1f338a..01f8b3b0 100644 --- a/lib/pages/bangumi/widgets/bangumi_card_v_timeline.dart +++ b/lib/pages/bangumi/widgets/bangumi_card_v_timeline.dart @@ -22,7 +22,6 @@ class BangumiCardVTimeline extends StatelessWidget { margin: EdgeInsets.zero, child: InkWell( onLongPress: () => imageSaveDialog( - context: context, title: item.title, cover: item.cover, ), @@ -71,6 +70,7 @@ class BangumiCardVTimeline extends StatelessWidget { } Widget bagumiContent(context) { + final theme = Theme.of(context); return Expanded( child: Padding( padding: const EdgeInsets.fromLTRB(4, 5, 0, 3), @@ -90,8 +90,8 @@ class BangumiCardVTimeline extends StatelessWidget { item.pubIndex ?? '', maxLines: 1, style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), ), ], diff --git a/lib/pages/bangumi/widgets/bangumi_panel.dart b/lib/pages/bangumi/widgets/bangumi_panel.dart index 863abec7..5c333c0a 100644 --- a/lib/pages/bangumi/widgets/bangumi_panel.dart +++ b/lib/pages/bangumi/widgets/bangumi_panel.dart @@ -81,6 +81,7 @@ class _BangumiPanelState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Column( children: [ Padding( @@ -95,7 +96,7 @@ class _BangumiPanelState extends State { overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -140,7 +141,7 @@ class _BangumiPanelState extends State { right: index == widget.pages.length - 1 ? 0 : 10, ), child: Material( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, borderRadius: BorderRadius.circular(6), clipBehavior: Clip.hardEdge, child: InkWell( @@ -169,7 +170,7 @@ class _BangumiPanelState extends State { if (index == currentIndex) ...[ Image.asset( 'assets/images/live.png', - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, height: 12, semanticLabel: "正在播放:", ), @@ -185,10 +186,8 @@ class _BangumiPanelState extends State { style: TextStyle( fontSize: 13, color: index == currentIndex - ? Theme.of(context).colorScheme.primary - : Theme.of(context) - .colorScheme - .onSurface), + ? theme.colorScheme.primary + : theme.colorScheme.onSurface), )), const SizedBox(width: 2), if (item.badge != null) ...[ @@ -205,8 +204,7 @@ class _BangumiPanelState extends State { item.badge!, style: TextStyle( fontSize: 11, - color: - Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ], @@ -222,10 +220,8 @@ class _BangumiPanelState extends State { style: TextStyle( fontSize: 13, color: index == currentIndex - ? Theme.of(context).colorScheme.primary - : Theme.of(context) - .colorScheme - .onSurface), + ? theme.colorScheme.primary + : theme.colorScheme.onSurface), overflow: TextOverflow.ellipsis, ) ] diff --git a/lib/pages/common/common_publish_page.dart b/lib/pages/common/common_publish_page.dart index 989af2ef..7034c4cc 100644 --- a/lib/pages/common/common_publish_page.dart +++ b/lib/pages/common/common_publish_page.dart @@ -275,6 +275,9 @@ abstract class CommonPublishPageState } Widget buildImage(int index, double height) { + final color = + Theme.of(context).colorScheme.secondaryContainer.withOpacity(0.5); + void onClear() { pathList.removeAt(index); if (pathList.isEmpty && editController.text.trim().isEmpty) { @@ -319,10 +322,7 @@ abstract class CommonPublishPageState }, size: 24, iconSize: 14, - bgColor: Theme.of(context) - .colorScheme - .secondaryContainer - .withOpacity(0.5), + bgColor: color, ), ), Positioned( @@ -334,10 +334,7 @@ abstract class CommonPublishPageState onPressed: onClear, size: 24, iconSize: 14, - bgColor: Theme.of(context) - .colorScheme - .secondaryContainer - .withOpacity(0.5), + bgColor: color, ), ), ], @@ -345,14 +342,14 @@ abstract class CommonPublishPageState } void onCropImage(int index) async { + final theme = Theme.of(context); CroppedFile? croppedFile = await ImageCropper().cropImage( sourcePath: pathList[index], uiSettings: [ AndroidUiSettings( toolbarTitle: '裁剪', - toolbarColor: Theme.of(context).colorScheme.secondaryContainer, - toolbarWidgetColor: - Theme.of(context).colorScheme.onSecondaryContainer, + toolbarColor: theme.colorScheme.secondaryContainer, + toolbarWidgetColor: theme.colorScheme.onSecondaryContainer, ), IOSUiSettings( title: '裁剪', diff --git a/lib/pages/common/common_slide_page.dart b/lib/pages/common/common_slide_page.dart index e748663c..9b94b8f5 100644 --- a/lib/pages/common/common_slide_page.dart +++ b/lib/pages/common/common_slide_page.dart @@ -19,19 +19,20 @@ abstract class CommonSlidePageState @override Widget build(BuildContext context) { + final theme = Theme.of(context); return enableSlide ? Padding( padding: EdgeInsets.only(top: padding), - child: buildPage, + child: buildPage(theme), ) - : buildPage; + : buildPage(theme); } - Widget get buildPage; + Widget buildPage(ThemeData theme); - Widget get buildList => throw UnimplementedError(); + Widget buildList(ThemeData theme) => throw UnimplementedError(); - Widget slideList([Widget? buildList]) => GestureDetector( + Widget slideList(ThemeData theme, [Widget? buildList]) => GestureDetector( onPanDown: (event) { if (event.localPosition.dx > 30) { isSliding = false; @@ -86,6 +87,6 @@ abstract class CommonSlidePageState downPos = null; isSliding = null; }, - child: buildList ?? this.buildList, + child: buildList ?? this.buildList(theme), ); } diff --git a/lib/pages/dynamics/create_dyn_panel.dart b/lib/pages/dynamics/create_dyn_panel.dart index 0d24326e..c7997db7 100644 --- a/lib/pages/dynamics/create_dyn_panel.dart +++ b/lib/pages/dynamics/create_dyn_panel.dart @@ -36,10 +36,11 @@ class _CreateDynPanelState extends CommonPublishPageState { @override Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); return Scaffold( backgroundColor: Colors.transparent, resizeToAvoidBottomInset: false, - appBar: _buildAppBar, + appBar: _buildAppBar(theme), body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -65,16 +66,16 @@ class _CreateDynPanelState extends CommonPublishPageState { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildReplyOptionWidget, + _buildReplyOptionWidget(theme), const SizedBox(height: 5), - _buildPrivateWidget, + _buildPrivateWidget(theme), ], ), ], ), ), const SizedBox(height: 10), - _buildImageList, + _buildImageList(theme), const SizedBox(height: 2), ], ), @@ -86,7 +87,7 @@ class _CreateDynPanelState extends CommonPublishPageState { ); } - Widget get _buildImageList => Obx( + Widget _buildImageList(ThemeData theme) => Obx( () => SizedBox( height: 100, child: ListView.separated( @@ -114,7 +115,7 @@ class _CreateDynPanelState extends CommonPublishPageState { height: 100, decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), - color: Theme.of(context).colorScheme.secondaryContainer, + color: theme.colorScheme.secondaryContainer, ), child: Center(child: Icon(Icons.add, size: 35)), ), @@ -129,7 +130,7 @@ class _CreateDynPanelState extends CommonPublishPageState { ), ); - PreferredSizeWidget get _buildAppBar => PreferredSize( + PreferredSizeWidget _buildAppBar(ThemeData theme) => PreferredSize( preferredSize: Size.fromHeight(66), child: Padding( padding: const EdgeInsets.all(16), @@ -147,9 +148,7 @@ class _CreateDynPanelState extends CommonPublishPageState { padding: WidgetStateProperty.all(EdgeInsets.zero), backgroundColor: WidgetStateProperty.resolveWith( (states) { - return Theme.of(context) - .colorScheme - .secondaryContainer; + return theme.colorScheme.secondaryContainer; }, ), ), @@ -157,7 +156,7 @@ class _CreateDynPanelState extends CommonPublishPageState { icon: Icon( Icons.arrow_back_outlined, size: 18, - color: Theme.of(context).colorScheme.onSecondaryContainer, + color: theme.colorScheme.onSecondaryContainer, ), ), ), @@ -193,127 +192,124 @@ class _CreateDynPanelState extends CommonPublishPageState { ), ); - Widget get _buildPrivateWidget => PopupMenuButton( - initialValue: _isPrivate, - onOpened: controller.keepChatPanel, - onSelected: (value) { - setState(() { - _isPrivate = value; - }); - }, - itemBuilder: (context) => List.generate( - 2, - (index) => PopupMenuItem( - enabled: _publishTime != null && index == 1 ? false : true, - value: index == 0 ? false : true, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - size: 19, - index == 0 ? Icons.visibility : Icons.visibility_off, - ), - const SizedBox(width: 4), - Text(index == 0 ? '所有人可见' : '仅自己可见'), - ], + Widget _buildPrivateWidget(ThemeData theme) { + final color = + _isPrivate ? theme.colorScheme.error : theme.colorScheme.secondary; + return PopupMenuButton( + initialValue: _isPrivate, + onOpened: controller.keepChatPanel, + onSelected: (value) { + setState(() { + _isPrivate = value; + }); + }, + itemBuilder: (context) => List.generate( + 2, + (index) => PopupMenuItem( + enabled: _publishTime != null && index == 1 ? false : true, + value: index == 0 ? false : true, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + size: 19, + index == 0 ? Icons.visibility : Icons.visibility_off, + ), + const SizedBox(width: 4), + Text(index == 0 ? '所有人可见' : '仅自己可见'), + ], + ), + ), + ), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 2), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + size: 19, + _isPrivate ? Icons.visibility_off : Icons.visibility, + color: color, ), - ), + const SizedBox(width: 4), + Text( + _isPrivate ? '仅自己可见' : '所有人可见', + style: TextStyle( + height: 1, + color: color, + ), + strutStyle: StrutStyle(leading: 0, height: 1), + ), + Icon( + size: 20, + Icons.keyboard_arrow_right, + color: color, + ), + ], ), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 2), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - size: 19, - _isPrivate ? Icons.visibility_off : Icons.visibility, - color: _isPrivate - ? Theme.of(context).colorScheme.error - : Theme.of(context).colorScheme.secondary, - ), - const SizedBox(width: 4), - Text( - _isPrivate ? '仅自己可见' : '所有人可见', - style: TextStyle( - height: 1, - color: _isPrivate - ? Theme.of(context).colorScheme.error - : Theme.of(context).colorScheme.secondary, - ), - strutStyle: StrutStyle(leading: 0, height: 1), - ), - Icon( - size: 20, - Icons.keyboard_arrow_right, - color: _isPrivate - ? Theme.of(context).colorScheme.error - : Theme.of(context).colorScheme.secondary, - ), - ], - ), - ), - ); + ), + ); + } - Widget get _buildReplyOptionWidget => PopupMenuButton( - initialValue: _replyOption, - onOpened: controller.keepChatPanel, - onSelected: (item) { - setState(() { - _replyOption = item; - }); - }, - itemBuilder: (context) => ReplyOption.values - .map( - (item) => PopupMenuItem( - value: item, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - size: 19, - item.iconData, - ), - const SizedBox(width: 4), - Text(item.title), - ], - ), + Widget _buildReplyOptionWidget(ThemeData theme) { + final color = _replyOption == ReplyOption.close + ? theme.colorScheme.error + : theme.colorScheme.secondary; + return PopupMenuButton( + initialValue: _replyOption, + onOpened: controller.keepChatPanel, + onSelected: (item) { + setState(() { + _replyOption = item; + }); + }, + itemBuilder: (context) => ReplyOption.values + .map( + (item) => PopupMenuItem( + value: item, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + size: 19, + item.iconData, + ), + const SizedBox(width: 4), + Text(item.title), + ], ), - ) - .toList(), - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 2), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - size: 19, - _replyOption.iconData, - color: _replyOption == ReplyOption.close - ? Theme.of(context).colorScheme.error - : Theme.of(context).colorScheme.secondary, + ), + ) + .toList(), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 2), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + size: 19, + _replyOption.iconData, + color: color, + ), + const SizedBox(width: 4), + Text( + _replyOption.title, + style: TextStyle( + height: 1, + color: color, ), - const SizedBox(width: 4), - Text( - _replyOption.title, - style: TextStyle( - height: 1, - color: _replyOption == ReplyOption.close - ? Theme.of(context).colorScheme.error - : Theme.of(context).colorScheme.secondary, - ), - strutStyle: StrutStyle(leading: 0, height: 1), - ), - Icon( - size: 20, - Icons.keyboard_arrow_right, - color: _replyOption == ReplyOption.close - ? Theme.of(context).colorScheme.error - : Theme.of(context).colorScheme.secondary, - ), - ], - ), + strutStyle: StrutStyle(leading: 0, height: 1), + ), + Icon( + size: 20, + Icons.keyboard_arrow_right, + color: color, + ), + ], ), - ); + ), + ); + } Widget get _buildPubtimeWidget => _publishTime == null ? FilledButton.tonal( diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index b70627fc..9b0669cc 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -282,6 +282,7 @@ class _DynamicDetailPageState extends State @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( resizeToAvoidBottomInset: false, appBar: AppBar( @@ -353,14 +354,14 @@ class _DynamicDetailPageState extends State onRefresh: () async { await _dynamicDetailController.onRefresh(); }, - child: _buildBody(context.orientation), + child: _buildBody(context.orientation, theme), ) - : _buildBody(context.orientation), + : _buildBody(context.orientation, theme), ), ); } - Widget _buildBody(Orientation orientation) => Stack( + Widget _buildBody(Orientation orientation, ThemeData theme) => Stack( children: [ Builder( builder: (context) { @@ -377,10 +378,10 @@ class _DynamicDetailPageState extends State callback: _getImageCallback, ), ), - replyPersistentHeader(context), + replyPersistentHeader(theme), Obx( () => replyList( - _dynamicDetailController.loadingState.value), + theme, _dynamicDetailController.loadingState.value), ), ] .map((e) => SliverPadding( @@ -429,13 +430,15 @@ class _DynamicDetailPageState extends State slivers: [ SliverPadding( padding: EdgeInsets.only(right: padding / 4), - sliver: replyPersistentHeader(context), + sliver: replyPersistentHeader(theme), ), SliverPadding( padding: EdgeInsets.only(right: padding / 4), sliver: Obx( - () => replyList(_dynamicDetailController - .loadingState.value), + () => replyList( + theme, + _dynamicDetailController + .loadingState.value), ), ), ], @@ -499,12 +502,10 @@ class _DynamicDetailPageState extends State ), Container( decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, border: Border( top: BorderSide( - color: Theme.of(context) - .colorScheme - .outline + color: theme.colorScheme.outline .withOpacity(0.08), ), ), @@ -565,17 +566,14 @@ class _DynamicDetailPageState extends State icon: Icon( FontAwesomeIcons.shareFromSquare, size: 16, - color: Theme.of(context) - .colorScheme - .outline, + color: theme.colorScheme.outline, semanticLabel: "转发", ), style: TextButton.styleFrom( padding: const EdgeInsets.fromLTRB( 15, 0, 15, 0), - foregroundColor: Theme.of(context) - .colorScheme - .outline, + foregroundColor: + theme.colorScheme.outline, ), label: Text( _dynamicDetailController @@ -606,17 +604,14 @@ class _DynamicDetailPageState extends State icon: Icon( FontAwesomeIcons.shareNodes, size: 16, - color: Theme.of(context) - .colorScheme - .outline, + color: theme.colorScheme.outline, semanticLabel: "分享", ), style: TextButton.styleFrom( padding: const EdgeInsets.fromLTRB( 15, 0, 15, 0), - foregroundColor: Theme.of(context) - .colorScheme - .outline, + foregroundColor: + theme.colorScheme.outline, ), label: const Text('分享'), ), @@ -652,12 +647,8 @@ class _DynamicDetailPageState extends State ?.like ?.status == true - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .outline, + ? theme.colorScheme.primary + : theme.colorScheme.outline, semanticLabel: _dynamicDetailController .item @@ -672,9 +663,8 @@ class _DynamicDetailPageState extends State style: TextButton.styleFrom( padding: const EdgeInsets.fromLTRB( 15, 0, 15, 0), - foregroundColor: Theme.of(context) - .colorScheme - .outline, + foregroundColor: + theme.colorScheme.outline, ), label: AnimatedSwitcher( duration: const Duration( @@ -709,12 +699,8 @@ class _DynamicDetailPageState extends State ?.like ?.status == true - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .outline, + ? theme.colorScheme.primary + : theme.colorScheme.outline, ), ), ), @@ -733,10 +719,10 @@ class _DynamicDetailPageState extends State ], ); - SliverPersistentHeader replyPersistentHeader(BuildContext context) { + SliverPersistentHeader replyPersistentHeader(ThemeData theme) { return SliverPersistentHeader( delegate: CustomSliverPersistentHeaderDelegate( - bgColor: Theme.of(context).colorScheme.surface, + bgColor: theme.colorScheme.surface, child: Container( height: 45, padding: const EdgeInsets.only(left: 12, right: 6), @@ -763,13 +749,13 @@ class _DynamicDetailPageState extends State icon: Icon( Icons.sort, size: 16, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), label: Obx(() => Text( _dynamicDetailController.sortType.value.label, style: TextStyle( fontSize: 13, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), )), ), @@ -782,7 +768,8 @@ class _DynamicDetailPageState extends State ); } - Widget replyList(LoadingState?> loadingState) { + Widget replyList( + ThemeData theme, LoadingState?> loadingState) { return switch (loadingState) { Loading() => SliverList.builder( itemBuilder: (context, index) { @@ -808,7 +795,7 @@ class _DynamicDetailPageState extends State : '没有更多了', style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ); diff --git a/lib/pages/dynamics/repost_dyn_panel.dart b/lib/pages/dynamics/repost_dyn_panel.dart index 20bb1881..9bf0770e 100644 --- a/lib/pages/dynamics/repost_dyn_panel.dart +++ b/lib/pages/dynamics/repost_dyn_panel.dart @@ -70,6 +70,7 @@ class _RepostPanelState extends CommonPublishPageState { @override Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); return AnimatedSize( alignment: Alignment.topCenter, curve: Curves.ease, @@ -79,10 +80,13 @@ class _RepostPanelState extends CommonPublishPageState { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: _isMax ? 16 : 10), - _buildAppBar, - if (_isMax) Expanded(child: _buildEditPanel) else _buildEditPanel, + _buildAppBar(theme), + if (_isMax) + Expanded(child: _buildEditPanel(theme)) + else + _buildEditPanel(theme), if (_isMax.not) - ..._biuldDismiss + ..._biuldDismiss(theme) else ...[ _buildToolbar, buildPanelContainer(Colors.transparent), @@ -92,7 +96,7 @@ class _RepostPanelState extends CommonPublishPageState { ); } - Widget get _buildEditPanel => Column( + Widget _buildEditPanel(ThemeData theme) => Column( mainAxisSize: _isMax ? MainAxisSize.max : MainAxisSize.min, children: [ Flexible( @@ -105,28 +109,30 @@ class _RepostPanelState extends CommonPublishPageState { border: Border( left: BorderSide( width: 2, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ) : null, - child: _isMax.not ? _buildEditPlaceHolder : _buildEditWidget, + child: _isMax.not + ? _buildEditPlaceHolder(theme) + : _buildEditWidget, ), ), ), const SizedBox(height: 10), - _buildRefWidget, + _buildRefWidget(theme), ], ); - Widget get _buildRefWidget => Container( + Widget _buildRefWidget(ThemeData theme) => Container( padding: const EdgeInsets.all(10), margin: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHigh == - Theme.of(context).colorScheme.surface - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.surfaceContainerHighest, + color: theme.colorScheme.surfaceContainerHigh == + theme.colorScheme.surface + ? theme.colorScheme.onInverseSurface + : theme.colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(12), ), child: Row( @@ -149,7 +155,7 @@ class _RepostPanelState extends CommonPublishPageState { Text( '@$_uname', style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, fontSize: 13, ), ), @@ -165,7 +171,7 @@ class _RepostPanelState extends CommonPublishPageState { ), ); - Widget get _buildEditPlaceHolder => GestureDetector( + Widget _buildEditPlaceHolder(ThemeData theme) => GestureDetector( onTap: () async { setState(() => _isMax = true); await Future.delayed(const Duration(milliseconds: 300)); @@ -178,7 +184,7 @@ class _RepostPanelState extends CommonPublishPageState { style: TextStyle( height: 1.75, fontSize: 15, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ); @@ -212,7 +218,7 @@ class _RepostPanelState extends CommonPublishPageState { ), ); - Widget get _buildAppBar => _isMax.not + Widget _buildAppBar(ThemeData theme) => _isMax.not ? Row( children: [ const SizedBox(width: 16), @@ -253,14 +259,14 @@ class _RepostPanelState extends CommonPublishPageState { padding: WidgetStateProperty.all(EdgeInsets.zero), backgroundColor: WidgetStateProperty.resolveWith((states) { - return Theme.of(context).colorScheme.secondaryContainer; + return theme.colorScheme.secondaryContainer; }), ), onPressed: Get.back, icon: Icon( Icons.arrow_back_outlined, size: 18, - color: Theme.of(context).colorScheme.onSecondaryContainer, + color: theme.colorScheme.onSecondaryContainer, ), ), ), @@ -316,11 +322,11 @@ class _RepostPanelState extends CommonPublishPageState { ), ); - List get _biuldDismiss => [ + List _biuldDismiss(ThemeData theme) => [ const SizedBox(height: 10), Divider( height: 1, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), + color: theme.colorScheme.outline.withOpacity(0.1), ), ListTile( dense: true, @@ -328,7 +334,7 @@ class _RepostPanelState extends CommonPublishPageState { title: Center( child: Text( '取消', - style: TextStyle(color: Theme.of(context).colorScheme.outline), + style: TextStyle(color: theme.colorScheme.outline), ), ), ), diff --git a/lib/pages/dynamics/view.dart b/lib/pages/dynamics/view.dart index 92a6a8c6..e95e6151 100644 --- a/lib/pages/dynamics/view.dart +++ b/lib/pages/dynamics/view.dart @@ -35,6 +35,14 @@ class _DynamicsPageState extends State final DynamicsController _dynamicsController = Get.put(DynamicsController()); late UpPanelPosition upPanelPosition; + late ThemeData theme; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + theme = Theme.of(context); + } + @override bool get wantKeepAlive => true; @@ -49,7 +57,7 @@ class _DynamicsPageState extends State style: ButtonStyle( padding: WidgetStateProperty.all(EdgeInsets.zero), backgroundColor: WidgetStateProperty.resolveWith((states) { - return Theme.of(context).colorScheme.secondaryContainer; + return theme.colorScheme.secondaryContainer; }), ), onPressed: () { @@ -65,7 +73,7 @@ class _DynamicsPageState extends State icon: Icon( Icons.add, size: 18, - color: Theme.of(context).colorScheme.onSecondaryContainer, + color: theme.colorScheme.onSecondaryContainer, ), ), ), @@ -103,7 +111,7 @@ class _DynamicsPageState extends State return Container( //抽屉模式增加底色 color: upPanelPosition.index > 1 - ? Theme.of(context).colorScheme.surface + ? theme.colorScheme.surface : Colors.transparent, width: 64, child: Obx( @@ -149,9 +157,9 @@ class _DynamicsPageState extends State dividerColor: Colors.transparent, dividerHeight: 0, tabAlignment: TabAlignment.center, - indicatorColor: Theme.of(context).colorScheme.primary, - labelColor: Theme.of(context).colorScheme.primary, - unselectedLabelColor: Theme.of(context).colorScheme.onSurface, + indicatorColor: theme.colorScheme.primary, + labelColor: theme.colorScheme.primary, + unselectedLabelColor: theme.colorScheme.onSurface, labelStyle: TabBarTheme.of(context).labelStyle?.copyWith(fontSize: 13) ?? const TextStyle(fontSize: 13), diff --git a/lib/pages/dynamics/widgets/action_panel.dart b/lib/pages/dynamics/widgets/action_panel.dart index b0e2b589..9d80d80c 100644 --- a/lib/pages/dynamics/widgets/action_panel.dart +++ b/lib/pages/dynamics/widgets/action_panel.dart @@ -58,8 +58,10 @@ class _ActionPanelState extends State { @override Widget build(BuildContext context) { - var color = Theme.of(context).colorScheme.outline; - var primary = Theme.of(context).colorScheme.primary; + final theme = Theme.of(context); + final color = theme.colorScheme.outline; + final primary = theme.colorScheme.primary; + final outline = theme.colorScheme.outline; return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ @@ -90,7 +92,7 @@ class _ActionPanelState extends State { ), style: TextButton.styleFrom( padding: const EdgeInsets.fromLTRB(15, 0, 15, 0), - foregroundColor: Theme.of(context).colorScheme.outline, + foregroundColor: outline, ), label: Text( widget.item.modules.moduleStat!.forward!.count != null @@ -113,7 +115,7 @@ class _ActionPanelState extends State { ), style: TextButton.styleFrom( padding: const EdgeInsets.fromLTRB(15, 0, 15, 0), - foregroundColor: Theme.of(context).colorScheme.outline, + foregroundColor: outline, ), label: Text( widget.item.modules.moduleStat!.comment!.count != null @@ -140,7 +142,7 @@ class _ActionPanelState extends State { ), style: TextButton.styleFrom( padding: const EdgeInsets.fromLTRB(15, 0, 15, 0), - foregroundColor: Theme.of(context).colorScheme.outline, + foregroundColor: outline, ), label: AnimatedSwitcher( duration: const Duration(milliseconds: 400), diff --git a/lib/pages/dynamics/widgets/additional_panel.dart b/lib/pages/dynamics/widgets/additional_panel.dart index 6e0ee4d4..b289b5b6 100644 --- a/lib/pages/dynamics/widgets/additional_panel.dart +++ b/lib/pages/dynamics/widgets/additional_panel.dart @@ -1,3 +1,4 @@ +import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; @@ -6,33 +7,36 @@ import 'package:PiliPlus/common/widgets/network_img_layer.dart'; import 'package:PiliPlus/http/search.dart'; /// TODO 点击跳转 -Widget addWidget(item, context, type, {floor = 1}) { +Widget addWidget( + ThemeData theme, DynamicItemModel item, BuildContext context, type, + {floor = 1}) { Map dynamicProperty = { - 'ADDITIONAL_TYPE_UGC': item.modules.moduleDynamic.additional.ugc, + 'ADDITIONAL_TYPE_UGC': item.modules.moduleDynamic!.additional!.ugc, // 直播预约 - 'ADDITIONAL_TYPE_RESERVE': item.modules.moduleDynamic.additional.reserve, + 'ADDITIONAL_TYPE_RESERVE': item.modules.moduleDynamic!.additional!.reserve, // 商品 - 'ADDITIONAL_TYPE_GOODS': item.modules.moduleDynamic.additional.goods, + 'ADDITIONAL_TYPE_GOODS': item.modules.moduleDynamic!.additional!.goods, // 比赛信息 - 'ADDITIONAL_TYPE_MATCH': item.modules.moduleDynamic.additional.match, + 'ADDITIONAL_TYPE_MATCH': item.modules.moduleDynamic!.additional!.match, // 游戏信息 - 'ADDITIONAL_TYPE_COMMON': item.modules.moduleDynamic.additional.common, + 'ADDITIONAL_TYPE_COMMON': item.modules.moduleDynamic!.additional!.common, }; + dynamic content = dynamicProperty[type]; Color bgColor = floor == 1 - ? Theme.of(context).dividerColor.withOpacity(0.08) - : Theme.of(context).colorScheme.surface; + ? theme.dividerColor.withOpacity(0.08) + : theme.colorScheme.surface; switch (type) { case 'ADDITIONAL_TYPE_UGC': // 转发的投稿 return InkWell( onTap: () async { - String text = dynamicProperty[type].jumpUrl; + String text = content.jumpUrl; RegExp bvRegex = RegExp(r'BV[0-9A-Za-z]{10}', caseSensitive: false); Iterable matches = bvRegex.allMatches(text); if (matches.isNotEmpty) { Match match = matches.first; String bvid = match.group(0)!; - String cover = dynamicProperty[type].cover; + String cover = content.cover; try { int cid = await SearchHttp.ab2c(bvid: bvid); PageUtils.toVideoPage( @@ -58,7 +62,7 @@ Widget addWidget(item, context, type, {floor = 1}) { NetworkImgLayer( width: 120, height: 75, - src: dynamicProperty[type].cover, + src: content.cover, ), const SizedBox(width: 10), Expanded( @@ -67,17 +71,16 @@ Widget addWidget(item, context, type, {floor = 1}) { mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - dynamicProperty[type].title, + content.title, maxLines: 2, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 4), Text( - dynamicProperty[type].descSecond, + content.descSecond, style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, ), ) ], @@ -88,22 +91,22 @@ Widget addWidget(item, context, type, {floor = 1}) { ), ); case 'ADDITIONAL_TYPE_RESERVE': - return dynamicProperty[type].state != -1 - ? dynamicProperty[type].title != null + return content.state != -1 + ? content.title != null ? Padding( padding: const EdgeInsets.only(top: 8), child: InkWell( onTap: () {}, child: Container( width: double.infinity, - padding: const EdgeInsets.only( - left: 12, top: 10, right: 12, bottom: 10), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 10), color: bgColor, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - dynamicProperty[type].title, + content.title, maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -111,21 +114,15 @@ Widget addWidget(item, context, type, {floor = 1}) { Text.rich( TextSpan( style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: Theme.of(context) - .textTheme - .labelMedium! - .fontSize), + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + ), children: [ - if (dynamicProperty[type].desc1 != null) - TextSpan( - text: - dynamicProperty[type].desc1['text']), + if (content.desc1 != null) + TextSpan(text: content.desc1['text']), const TextSpan(text: ' '), - if (dynamicProperty[type].desc2 != null) - TextSpan( - text: - dynamicProperty[type].desc2['text']), + if (content.desc2 != null) + TextSpan(text: content.desc2['text']), ], ), ) @@ -146,6 +143,6 @@ Widget addWidget(item, context, type, {floor = 1}) { case 'ADDITIONAL_TYPE_VOTE': return const SizedBox.shrink(); default: - return const Text('11'); + return const SizedBox.shrink(); } } diff --git a/lib/pages/dynamics/widgets/article_panel.dart b/lib/pages/dynamics/widgets/article_panel.dart index 69c7ce7b..03b6df28 100644 --- a/lib/pages/dynamics/widgets/article_panel.dart +++ b/lib/pages/dynamics/widgets/article_panel.dart @@ -1,12 +1,18 @@ +import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:flutter/material.dart'; import 'package:PiliPlus/utils/utils.dart'; import '../../../common/constants.dart'; import 'pic_panel.dart'; -Widget articlePanel(source, item, context, callback, {floor = 1}) { - TextStyle authorStyle = - TextStyle(color: Theme.of(context).colorScheme.primary); +Widget articlePanel( + ThemeData theme, + String? source, + DynamicItemModel item, + BuildContext context, + callback, { + floor = 1, +}) { return Padding( padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), child: Column( @@ -15,37 +21,32 @@ Widget articlePanel(source, item, context, callback, {floor = 1}) { if (floor == 2) ...[ Row( children: [ - GestureDetector( - onTap: () {}, - child: Text( - '@${item.modules.moduleAuthor.name}', - style: authorStyle, - ), + Text( + '@${item.modules.moduleAuthor!.name}', + style: TextStyle(color: theme.colorScheme.primary), ), const SizedBox(width: 6), Text( - Utils.dateFormat(item.modules.moduleAuthor.pubTs), + Utils.dateFormat(item.modules.moduleAuthor!.pubTs), style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: Theme.of(context).textTheme.labelSmall!.fontSize), + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize), ), ], ), const SizedBox(height: 8), ], Text( - item.modules.moduleDynamic.major.opus.title, - style: Theme.of(context) - .textTheme - .titleMedium! + item.modules.moduleDynamic!.major!.opus!.title!, + style: theme.textTheme.titleMedium! .copyWith(fontWeight: FontWeight.bold), ), const SizedBox(height: 2), - if (item.modules.moduleDynamic.major.opus.summary.text != + if (item.modules.moduleDynamic?.major?.opus?.summary?.text != 'undefined') ...[ Text( - item.modules.moduleDynamic.major.opus.summary.richTextNodes.first - .text, + item.modules.moduleDynamic!.major!.opus!.summary!.richTextNodes! + .first.text!, maxLines: source == 'detail' ? null : 4, style: const TextStyle(height: 1.55), overflow: source == 'detail' ? null : TextOverflow.ellipsis, diff --git a/lib/pages/dynamics/widgets/author_panel.dart b/lib/pages/dynamics/widgets/author_panel.dart index 1eb1f359..b4703e6d 100644 --- a/lib/pages/dynamics/widgets/author_panel.dart +++ b/lib/pages/dynamics/widgets/author_panel.dart @@ -241,6 +241,7 @@ class AuthorPanel extends StatelessWidget { maxWidth: min(640, min(Get.width, Get.height)), ), builder: (context1) { + final theme = Theme.of(context); return Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context1).padding.bottom), @@ -261,7 +262,7 @@ class AuthorPanel extends StatelessWidget { width: 32, height: 3, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, borderRadius: const BorderRadius.all(Radius.circular(3))), ), @@ -283,7 +284,7 @@ class AuthorPanel extends StatelessWidget { leading: const Icon(Icons.watch_later_outlined, size: 19), title: Text( '稍后再看', - style: Theme.of(context).textTheme.titleSmall, + style: theme.textTheme.titleSmall, ), ), ListTile( @@ -293,13 +294,12 @@ class AuthorPanel extends StatelessWidget { }, minLeadingWidth: 0, leading: const Icon(Icons.save_alt, size: 19), - title: Text('保存动态', - style: Theme.of(context).textTheme.titleSmall!), + title: Text('保存动态', style: theme.textTheme.titleSmall!), ), ListTile( title: Text( '分享动态', - style: Theme.of(context).textTheme.titleSmall, + style: theme.textTheme.titleSmall, ), leading: const Icon(Icons.share_outlined, size: 19), onTap: () { @@ -314,7 +314,7 @@ class AuthorPanel extends StatelessWidget { ListTile( title: Text( '分享至消息', - style: Theme.of(context).textTheme.titleSmall, + style: theme.textTheme.titleSmall, ), leading: const Icon(Icons.forward_to_inbox, size: 19), onTap: () { @@ -359,7 +359,7 @@ class AuthorPanel extends StatelessWidget { ListTile( title: Text( '临时屏蔽:${item.modules.moduleAuthor?.name}', - style: Theme.of(context).textTheme.titleSmall, + style: theme.textTheme.titleSmall, ), leading: const Icon(Icons.visibility_off_outlined, size: 19), onTap: () { @@ -387,8 +387,7 @@ class AuthorPanel extends StatelessWidget { Icon(Icons.published_with_changes_sharp, size: 12), ], ), - title: Text('检查动态', - style: Theme.of(context).textTheme.titleSmall!), + title: Text('检查动态', style: theme.textTheme.titleSmall!), ), if (onSetTop != null) ListTile( @@ -401,7 +400,7 @@ class AuthorPanel extends StatelessWidget { leading: const Icon(Icons.vertical_align_top, size: 19), title: Text( '${item.modules.moduleTag?.text != null ? '取消' : ''}置顶', - style: Theme.of(context).textTheme.titleSmall!), + style: theme.textTheme.titleSmall!), ), if (onRemove != null) ListTile( @@ -417,7 +416,7 @@ class AuthorPanel extends StatelessWidget { child: Text( '取消', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -434,24 +433,24 @@ class AuthorPanel extends StatelessWidget { }, minLeadingWidth: 0, leading: Icon(Icons.delete_outline, - color: Theme.of(context).colorScheme.error, size: 19), + color: theme.colorScheme.error, size: 19), title: Text('删除', - style: Theme.of(context).textTheme.titleSmall!.copyWith( - color: Theme.of(context).colorScheme.error)), + style: theme.textTheme.titleSmall! + .copyWith(color: theme.colorScheme.error)), ), ], if (Accounts.main.isLogin) ListTile( title: Text( '举报', - style: Theme.of(context).textTheme.titleSmall!.copyWith( - color: Theme.of(context).colorScheme.error, - ), + style: theme.textTheme.titleSmall!.copyWith( + color: theme.colorScheme.error, + ), ), leading: Icon( Icons.error_outline_outlined, size: 19, - color: Theme.of(context).colorScheme.error, + color: theme.colorScheme.error, ), onTap: () { Get.back(); @@ -483,8 +482,7 @@ class AuthorPanel extends StatelessWidget { dense: true, title: Text( '取消', - style: - TextStyle(color: Theme.of(context).colorScheme.outline), + style: TextStyle(color: theme.colorScheme.outline), textAlign: TextAlign.center, ), ), diff --git a/lib/pages/dynamics/widgets/content_panel.dart b/lib/pages/dynamics/widgets/content_panel.dart index e9a5ae95..7def3c39 100644 --- a/lib/pages/dynamics/widgets/content_panel.dart +++ b/lib/pages/dynamics/widgets/content_panel.dart @@ -1,16 +1,24 @@ // 内容 import 'package:PiliPlus/common/widgets/image_view.dart'; +import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:flutter/material.dart'; import 'rich_node_panel.dart'; -Widget content(bool isSave, BuildContext context, item, source, callback) { +Widget content( + ThemeData theme, + bool isSave, + BuildContext context, + DynamicItemModel item, + String? source, + Function(List, int)? callback, +) { InlineSpan picsNodes() { return WidgetSpan( child: LayoutBuilder( builder: (context, constraints) => imageView( constraints.maxWidth, - (item.modules.moduleDynamic.major.opus.pics as List) + (item.modules.moduleDynamic!.major!.opus!.pics as List) .map( (item) => ImageModel( width: item.width, @@ -26,9 +34,7 @@ Widget content(bool isSave, BuildContext context, item, source, callback) { ); } - TextStyle authorStyle = - TextStyle(color: Theme.of(context).colorScheme.primary); - InlineSpan? richNodes = richNode(item, context); + TextSpan? richNodes = richNode(theme, item, context); return Container( width: double.infinity, @@ -36,24 +42,17 @@ Widget content(bool isSave, BuildContext context, item, source, callback) { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (item.modules.moduleDynamic.topic != null) ...[ - GestureDetector( - child: Text( - '#${item.modules.moduleDynamic.topic.name}', - style: authorStyle, - ), + if (item.modules.moduleDynamic?.topic != null) ...[ + Text( + '#${item.modules.moduleDynamic!.topic!.name}', + style: TextStyle(color: theme.colorScheme.primary), ), ], if (richNodes != null) source == 'detail' - ? SelectableRegion( - magnifierConfiguration: const TextMagnifierConfiguration(), - focusNode: FocusNode(), - selectionControls: MaterialTextSelectionControls(), - child: Text.rich( - style: TextStyle(fontSize: !isSave ? 16 : 15), - richNodes, - ), + ? SelectableText.rich( + richNodes, + style: TextStyle(fontSize: !isSave ? 16 : 15), ) : Text.rich( style: const TextStyle(fontSize: 15), @@ -61,12 +60,8 @@ Widget content(bool isSave, BuildContext context, item, source, callback) { maxLines: 6, overflow: TextOverflow.ellipsis, ), - if (item.modules.moduleDynamic.major != null && - item.modules.moduleDynamic.major.opus != null && - item.modules.moduleDynamic.major.opus.pics.isNotEmpty) - Text.rich( - picsNodes(), - ), + if (item.modules.moduleDynamic?.major?.opus?.pics?.isNotEmpty == true) + Text.rich(picsNodes()), ], ), ); diff --git a/lib/pages/dynamics/widgets/dynamic_panel.dart b/lib/pages/dynamics/widgets/dynamic_panel.dart index 077742c5..9faea17e 100644 --- a/lib/pages/dynamics/widgets/dynamic_panel.dart +++ b/lib/pages/dynamics/widgets/dynamic_panel.dart @@ -29,6 +29,7 @@ class DynamicPanel extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); final authorWidget = AuthorPanel( item: item, source: source, @@ -45,7 +46,7 @@ class DynamicPanel extends StatelessWidget { border: Border( bottom: BorderSide( width: 8, - color: Theme.of(context).dividerColor.withOpacity(0.05), + color: theme.dividerColor.withOpacity(0.05), ), ), ), @@ -76,8 +77,8 @@ class DynamicPanel extends StatelessWidget { ), if (item.modules.moduleDynamic!.desc != null || item.modules.moduleDynamic!.major != null) - content(isSave, context, item, source, callback), - forWard(isSave, item, context, source, callback), + content(theme, isSave, context, item, source, callback), + forWard(theme, isSave, item, context, source, callback), const SizedBox(height: 2), if (source == null) ActionPanel(item: item), if (source == 'detail' && !isSave) const SizedBox(height: 12), @@ -121,7 +122,6 @@ class DynamicPanel extends StatelessWidget { return; } imageSaveDialog( - context: context, title: title, cover: cover, ); diff --git a/lib/pages/dynamics/widgets/forward_panel.dart b/lib/pages/dynamics/widgets/forward_panel.dart index bc73db5a..944eeb5e 100644 --- a/lib/pages/dynamics/widgets/forward_panel.dart +++ b/lib/pages/dynamics/widgets/forward_panel.dart @@ -19,7 +19,10 @@ import 'pic_panel.dart'; import 'rich_node_panel.dart'; import 'video_panel.dart'; -InlineSpan picsNodes(List pics, callback) { +InlineSpan picsNodes( + List pics, + Function(List, int)? callback, +) { return WidgetSpan( child: LayoutBuilder( builder: (context, constraints) => imageView( @@ -40,7 +43,7 @@ InlineSpan picsNodes(List pics, callback) { ); } -Widget _blockedItem(BuildContext context, DynamicItemModel item, source) { +Widget _blockedItem(ThemeData theme, DynamicItemModel item, String? source) { return Container( width: double.infinity, padding: EdgeInsets.only( @@ -53,7 +56,7 @@ Widget _blockedItem(BuildContext context, DynamicItemModel item, source) { Text( item.modules.moduleDynamic!.major!.blocked!['title'], style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), if (item.modules.moduleDynamic!.major!.blocked!['hint_message'] != null) @@ -61,7 +64,7 @@ Widget _blockedItem(BuildContext context, DynamicItemModel item, source) { item.modules.moduleDynamic!.major!.blocked!['hint_message'], style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ], @@ -70,15 +73,21 @@ Widget _blockedItem(BuildContext context, DynamicItemModel item, source) { } Widget forWard( - bool isSave, DynamicItemModel item, BuildContext context, source, callback, - {floor = 1}) { + ThemeData theme, + bool isSave, + DynamicItemModel item, + BuildContext context, + source, + callback, { + floor = 1, +}) { switch (item.type) { // 图文 case 'DYNAMIC_TYPE_DRAW': bool hasPics = item.modules.moduleDynamic?.major?.opus?.pics?.isNotEmpty == true; - InlineSpan? richNodes = richNode(item, context); + TextSpan? richNodes = richNode(theme, item, context); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -91,17 +100,15 @@ Widget forWard( arguments: {'face': item.modules.moduleAuthor!.face}), child: Text( '@${item.modules.moduleAuthor!.name}', - style: - TextStyle(color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), ), ), const SizedBox(width: 6), Text( Utils.dateFormat(item.modules.moduleAuthor!.pubTs), style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: - Theme.of(context).textTheme.labelSmall!.fontSize), + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize), ), ], ), @@ -139,22 +146,24 @@ Widget forWard( /// 附加内容 商品信息、直播预约等等 if (item.modules.moduleDynamic?.additional != null) addWidget( + theme, item, context, item.modules.moduleDynamic?.additional?.type, floor: floor, ), if (item.modules.moduleDynamic?.major?.blocked != null) - _blockedItem(context, item, source), + _blockedItem(theme, item, source), ], ); // 视频 case 'DYNAMIC_TYPE_AV': - return videoSeasonWidget(source, item, context, 'archive', floor: floor); + return videoSeasonWidget(theme, source, item, context, 'archive', + floor: floor); // 文章 case 'DYNAMIC_TYPE_ARTICLE': return item.isForwarded == true - ? articlePanel(source, item, context, callback, floor: floor) + ? articlePanel(theme, source, item, context, callback, floor: floor) : item.modules.moduleDynamic?.major?.blocked != null ? Padding( padding: const EdgeInsets.symmetric(horizontal: 12), @@ -168,7 +177,7 @@ Widget forWard( Text( item.modules.moduleDynamic!.major!.blocked!['title'], style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), if (item.modules.moduleDynamic?.major @@ -179,7 +188,7 @@ Widget forWard( .blocked!['hint_message'], style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ) ], @@ -225,29 +234,28 @@ Widget forWard( return; } imageSaveDialog( - context: context, title: title, cover: cover, ); }, child: Container( padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8), - color: Theme.of(context).dividerColor.withOpacity(0.08), - child: forWard(isSave, item.orig!, context, source, callback, + color: theme.dividerColor.withOpacity(0.08), + child: forWard(theme, isSave, item.orig!, context, source, callback, floor: floor + 1), ), ); // 直播 case 'DYNAMIC_TYPE_LIVE_RCMD': - return liveRcmdPanel(source, item, context, floor: floor); + return liveRcmdPanel(theme, source, item, context, floor: floor); // 直播 case 'DYNAMIC_TYPE_LIVE': - return livePanel(source, item, context, floor: floor); + return livePanel(theme, source, item, context, floor: floor); // 合集 case 'DYNAMIC_TYPE_UGC_SEASON': - return videoSeasonWidget(source, item, context, 'ugcSeason'); + return videoSeasonWidget(theme, source, item, context, 'ugcSeason'); case 'DYNAMIC_TYPE_WORD': - InlineSpan? richNodes = richNode(item, context); + late TextSpan? richNodes = richNode(theme, item, context); return floor == 2 ? Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -260,17 +268,15 @@ Widget forWard( arguments: {'face': item.modules.moduleAuthor?.face}), child: Text( '@${item.modules.moduleAuthor?.name}', - style: TextStyle( - color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), ), ), const SizedBox(width: 6), Text( Utils.dateFormat(item.modules.moduleAuthor?.pubTs), style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: - Theme.of(context).textTheme.labelSmall!.fontSize), + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize), ), ], ), @@ -294,18 +300,21 @@ Widget forWard( ) : item.modules.moduleDynamic?.additional != null ? addWidget( + theme, item, context, item.modules.moduleDynamic!.additional!.type, floor: floor, ) : item.modules.moduleDynamic?.major?.blocked != null - ? _blockedItem(context, item, source) + ? _blockedItem(theme, item, source) : const SizedBox(height: 0); case 'DYNAMIC_TYPE_PGC': - return videoSeasonWidget(source, item, context, 'pgc', floor: floor); + return videoSeasonWidget(theme, source, item, context, 'pgc', + floor: floor); case 'DYNAMIC_TYPE_PGC_UNION': - return videoSeasonWidget(source, item, context, 'pgc', floor: floor); + return videoSeasonWidget(theme, source, item, context, 'pgc', + floor: floor); // 直播结束 case 'DYNAMIC_TYPE_NONE': return Row( @@ -347,7 +356,7 @@ Widget forWard( width: double.infinity, padding: const EdgeInsets.only(left: 12, top: 10, right: 12, bottom: 10), - color: Theme.of(context).dividerColor.withOpacity(0.08), + color: theme.dividerColor.withOpacity(0.08), child: Row( children: [ NetworkImgLayer( @@ -365,7 +374,7 @@ Widget forWard( Text( item.modules.moduleDynamic!.major!.common!['title'], style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), maxLines: 1, overflow: TextOverflow.ellipsis, @@ -374,9 +383,8 @@ Widget forWard( Text( item.modules.moduleDynamic!.major!.common!['desc'], style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, ), maxLines: 1, overflow: TextOverflow.ellipsis, @@ -398,7 +406,7 @@ Widget forWard( width: double.infinity, padding: const EdgeInsets.only(left: 12, top: 10, right: 12, bottom: 10), - color: Theme.of(context).dividerColor.withOpacity(0.08), + color: theme.dividerColor.withOpacity(0.08), child: Row( children: [ NetworkImgLayer( @@ -415,7 +423,7 @@ Widget forWard( Text( music['title'], style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), maxLines: 1, overflow: TextOverflow.ellipsis, @@ -424,9 +432,8 @@ Widget forWard( Text( music['label'], style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, ), maxLines: 1, overflow: TextOverflow.ellipsis, @@ -464,9 +471,8 @@ Widget forWard( item.modules.moduleAuthor!.vip!['status'] > 0 && item.modules.moduleAuthor!.vip!['type'] == 2 ? context.vipColor - : Theme.of(context).colorScheme.onSurface, - fontSize: - Theme.of(context).textTheme.titleMedium!.fontSize, + : theme.colorScheme.onSurface, + fontSize: theme.textTheme.titleMedium!.fontSize, ), ), ], @@ -510,10 +516,7 @@ Widget forWard( Text( item.modules.moduleDynamic!.major!.medialist!['title'], style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .titleMedium! - .fontSize, + fontSize: theme.textTheme.titleMedium!.fontSize, fontWeight: FontWeight.bold), ), if (item.modules.moduleDynamic?.major @@ -524,11 +527,8 @@ Widget forWard( item.modules.moduleDynamic!.major! .medialist!['sub_title'], style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelLarge! - .fontSize, - color: Theme.of(context).colorScheme.outline), + fontSize: theme.textTheme.labelLarge!.fontSize, + color: theme.colorScheme.outline), ), ], ], diff --git a/lib/pages/dynamics/widgets/live_panel.dart b/lib/pages/dynamics/widgets/live_panel.dart index 387205be..fef08a5f 100644 --- a/lib/pages/dynamics/widgets/live_panel.dart +++ b/lib/pages/dynamics/widgets/live_panel.dart @@ -1,4 +1,5 @@ import 'package:PiliPlus/common/widgets/image_save.dart'; +import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:PiliPlus/common/widgets/network_img_layer.dart'; @@ -6,11 +7,19 @@ import 'package:PiliPlus/utils/utils.dart'; import 'rich_node_panel.dart'; -Widget livePanel(source, item, context, {floor = 1}) { - dynamic content = item.modules.moduleDynamic.major; - late final TextStyle authorStyle = - TextStyle(color: Theme.of(context).colorScheme.primary); - InlineSpan? richNodes = richNode(item, context); +Widget livePanel( + ThemeData theme, + String? source, + DynamicItemModel item, + BuildContext context, { + int floor = 1, +}) { + DynamicMajorModel? content = item.modules.moduleDynamic!.major; + if (content == null) { + return const SizedBox.shrink(); + } + late final authorStyle = TextStyle(color: theme.colorScheme.primary); + TextSpan? richNodes = richNode(theme, item, context); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -19,40 +28,41 @@ Widget livePanel(source, item, context, {floor = 1}) { children: [ GestureDetector( onTap: () => Get.toNamed( - '/member?mid=${item.modules.moduleAuthor.mid}', - arguments: {'face': item.modules.moduleAuthor.face}), + '/member?mid=${item.modules.moduleAuthor!.mid}', + arguments: {'face': item.modules.moduleAuthor!.face}), child: Text( - '@${item.modules.moduleAuthor.name}', + '@${item.modules.moduleAuthor!.name}', style: authorStyle, ), ), const SizedBox(width: 6), Text( - Utils.dateFormat(item.modules.moduleAuthor.pubTs), + Utils.dateFormat(item.modules.moduleAuthor?.pubTs), style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: Theme.of(context).textTheme.labelSmall!.fontSize), + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize, + ), ), ], ), ], const SizedBox(height: 4), - if (item.modules.moduleDynamic.topic != null) ...[ + if (item.modules.moduleDynamic?.topic != null) ...[ Padding( padding: floor == 2 ? EdgeInsets.zero : const EdgeInsets.only(left: 12, right: 12), - child: GestureDetector( - child: Text( - '#${item.modules.moduleDynamic.topic.name}', - style: authorStyle, - ), + child: Text( + '#${item.modules.moduleDynamic!.topic!.name}', + style: authorStyle, ), ), const SizedBox(height: 6), ], - if (floor == 2 && item.modules.moduleDynamic.desc != null) ...[ - if (richNodes != null) Text.rich(richNodes), + if (floor == 2 && + item.modules.moduleDynamic?.desc != null && + richNodes != null) ...[ + Text.rich(richNodes), const SizedBox(height: 6), ], GestureDetector( @@ -63,9 +73,8 @@ Widget livePanel(source, item, context, {floor = 1}) { onLongPress: () { Feedback.forLongPress(context); imageSaveDialog( - context: context, - title: content.live.title, - cover: content.live.cover, + title: content.live!.title, + cover: content.live!.cover, ); }, child: Row( @@ -75,7 +84,7 @@ Widget livePanel(source, item, context, {floor = 1}) { NetworkImgLayer( width: 120, height: 75, - src: content.live.cover, + src: content.live!.cover, ), const SizedBox(width: 10), Expanded( @@ -84,26 +93,26 @@ Widget livePanel(source, item, context, {floor = 1}) { mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - content.live.title, + content.live!.title!, maxLines: source == 'detail' ? null : 2, overflow: source == 'detail' ? null : TextOverflow.ellipsis, ), const SizedBox(height: 4), - Text( - content.live.descFirst, - style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - ), - ) + if (content.live?.descFirst != null) + Text( + content.live!.descFirst!, + style: TextStyle( + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + ), + ) ], ), ), Text( - content.live.badge['text'], + content.live!.badge!['text'], style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, + fontSize: theme.textTheme.labelMedium!.fontSize, ), ) ], diff --git a/lib/pages/dynamics/widgets/live_rcmd_panel.dart b/lib/pages/dynamics/widgets/live_rcmd_panel.dart index 09021ec0..13e2f267 100644 --- a/lib/pages/dynamics/widgets/live_rcmd_panel.dart +++ b/lib/pages/dynamics/widgets/live_rcmd_panel.dart @@ -9,13 +9,21 @@ import 'package:PiliPlus/utils/utils.dart'; import 'rich_node_panel.dart'; -Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) { - TextStyle authorStyle = - TextStyle(color: Theme.of(context).colorScheme.primary); - DynamicLiveModel liveRcmd = item.modules.moduleDynamic!.major!.liveRcmd!; - int liveStatus = liveRcmd.liveStatus!; - Map watchedShow = liveRcmd.watchedShow!; - InlineSpan? richNodes = richNode(item, context); +Widget liveRcmdPanel( + ThemeData theme, + String? source, + DynamicItemModel item, + BuildContext context, { + int floor = 1, +}) { + DynamicLiveModel? liveRcmd = item.modules.moduleDynamic?.major?.liveRcmd; + if (liveRcmd == null) { + return const SizedBox.shrink(); + } + int? liveStatus = liveRcmd.liveStatus; + Map? watchedShow = liveRcmd.watchedShow; + TextSpan? richNodes = richNode(theme, item, context); + late final authorStyle = TextStyle(color: theme.colorScheme.primary); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -24,8 +32,9 @@ Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) { children: [ GestureDetector( onTap: () => Get.toNamed( - '/member?mid=${item.modules.moduleAuthor?.mid}', - arguments: {'face': item.modules.moduleAuthor?.face}), + '/member?mid=${item.modules.moduleAuthor?.mid}', + arguments: {'face': item.modules.moduleAuthor?.face}, + ), child: Text( '@${item.modules.moduleAuthor?.name}', style: authorStyle, @@ -35,8 +44,9 @@ Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) { Text( Utils.dateFormat(item.modules.moduleAuthor?.pubTs), style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: Theme.of(context).textTheme.labelSmall!.fontSize), + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize, + ), ), ], ), @@ -46,27 +56,27 @@ Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) { Padding( padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), - child: GestureDetector( - child: Text( - '#${item.modules.moduleDynamic!.topic!.name}', - style: authorStyle, - ), + child: Text( + '#${item.modules.moduleDynamic!.topic!.name}', + style: authorStyle, ), ), const SizedBox(height: 6), ], - if (floor == 2 && item.modules.moduleDynamic?.desc != null) ...[ - if (richNodes != null) Text.rich(richNodes), + if (floor == 2 && + item.modules.moduleDynamic?.desc != null && + richNodes != null) ...[ + Text.rich(richNodes), const SizedBox(height: 6), ], Padding( - padding: - const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), - child: GestureDetector( - onTap: () { - PageUtils.pushDynDetail(item, floor); - }, - child: LayoutBuilder(builder: (context, box) { + padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + child: GestureDetector( + onTap: () { + PageUtils.pushDynDetail(item, floor); + }, + child: LayoutBuilder( + builder: (context, box) { double width = box.maxWidth; return Stack( children: [ @@ -75,33 +85,31 @@ Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) { child: NetworkImgLayer( width: width, height: width / StyleString.aspectRatio, - src: item.modules.moduleDynamic?.major?.liveRcmd?.cover, + src: liveRcmd.cover, ), ), PBadge( - text: watchedShow['text_large'], + text: watchedShow?['text_large'], top: 6, right: 56, - bottom: null, - left: null, type: 'gray', ), PBadge( text: liveStatus == 1 ? '直播中' : '直播结束', top: 6, right: 6, - bottom: null, - left: null, ), - Positioned( - left: 0, - right: 0, - bottom: 0, - child: Container( - height: 80, - padding: const EdgeInsets.fromLTRB(12, 0, 10, 10), - clipBehavior: Clip.hardEdge, - decoration: BoxDecoration( + if (liveRcmd.areaName != null) + Positioned( + left: 0, + right: 0, + bottom: 0, + child: Container( + height: 80, + alignment: Alignment.bottomLeft, + padding: const EdgeInsets.fromLTRB(12, 0, 10, 10), + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, @@ -111,45 +119,42 @@ Widget liveRcmdPanel(source, DynamicItemModel item, context, {floor = 1}) { ], ), borderRadius: floor == 1 - ? StyleString.mdRadius - : const BorderRadius.all(Radius.circular(6))), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - DefaultTextStyle.merge( - style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelMedium! - .fontSize, - color: Colors.white), - child: Row( - children: [ - Text(item.modules.moduleDynamic?.major?.liveRcmd - ?.areaName ?? - ''), - ], - ), + ? const BorderRadius.only( + bottomLeft: StyleString.imgRadius, + bottomRight: StyleString.imgRadius, + ) + : const BorderRadius.only( + bottomLeft: Radius.circular(6), + bottomRight: Radius.circular(6), + ), + ), + child: Text( + liveRcmd.areaName!, + style: TextStyle( + fontSize: theme.textTheme.labelMedium!.fontSize, + color: Colors.white, ), - ], + ), ), ), - ), ], ); - }), - )), - const SizedBox(height: 6), - Padding( - padding: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), - child: Text( - item.modules.moduleDynamic!.major!.liveRcmd!.title!, - maxLines: source == 'detail' ? null : 1, - style: const TextStyle(fontWeight: FontWeight.bold), - overflow: source == 'detail' ? null : TextOverflow.ellipsis, + }, + ), ), ), + const SizedBox(height: 6), + if (liveRcmd.title != null) + Padding( + padding: + const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + child: Text( + liveRcmd.title!, + maxLines: source == 'detail' ? null : 1, + style: const TextStyle(fontWeight: FontWeight.bold), + overflow: source == 'detail' ? null : TextOverflow.ellipsis, + ), + ), const SizedBox(height: 2), ], ); diff --git a/lib/pages/dynamics/widgets/pic_panel.dart b/lib/pages/dynamics/widgets/pic_panel.dart index eda77a37..0daaba87 100644 --- a/lib/pages/dynamics/widgets/pic_panel.dart +++ b/lib/pages/dynamics/widgets/pic_panel.dart @@ -1,9 +1,14 @@ import 'package:PiliPlus/common/widgets/image_view.dart'; +import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:flutter/material.dart'; -Widget picWidget(item, context, callback) { - if (item.modules.moduleDynamic.major?.draw?.items == null || - item.modules.moduleDynamic.major.type == 'MAJOR_TYPE_OPUS') { +Widget picWidget( + DynamicItemModel item, + BuildContext context, + Function(List, int)? callback, +) { + if (item.modules.moduleDynamic?.major?.draw?.items == null || + item.modules.moduleDynamic?.major?.type == 'MAJOR_TYPE_OPUS') { /// fix 图片跟rich_node_panel重复 // pictures = item.modules.moduleDynamic.major.opus.pics; return const SizedBox.shrink(); @@ -11,7 +16,7 @@ Widget picWidget(item, context, callback) { return LayoutBuilder( builder: (context, constraints) => imageView( constraints.maxWidth, - (item.modules.moduleDynamic.major.draw.items as List) + (item.modules.moduleDynamic!.major!.draw!.items as List) .map( (item) => ImageModel( width: item.width, diff --git a/lib/pages/dynamics/widgets/rich_node_panel.dart b/lib/pages/dynamics/widgets/rich_node_panel.dart index e4c4b010..75140096 100644 --- a/lib/pages/dynamics/widgets/rich_node_panel.dart +++ b/lib/pages/dynamics/widgets/rich_node_panel.dart @@ -10,27 +10,27 @@ import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/utils/app_scheme.dart'; // 富文本 -InlineSpan? richNode(item, BuildContext context) { - final spacer = _VerticalSpaceSpan(0.0); +TextSpan? richNode( + ThemeData theme, + DynamicItemModel item, + BuildContext context, +) { try { - TextStyle authorStyle = - TextStyle(color: Theme.of(context).colorScheme.primary); + late final authorStyle = TextStyle(color: theme.colorScheme.primary); List spanChildren = []; List? richTextNodes; - if (item.modules.moduleDynamic.desc != null) { - richTextNodes = item.modules.moduleDynamic.desc.richTextNodes; - } else if (item.modules.moduleDynamic.major != null) { + if (item.modules.moduleDynamic?.desc != null) { + richTextNodes = item.modules.moduleDynamic!.desc!.richTextNodes; + } else if (item.modules.moduleDynamic?.major != null) { // 动态页面 richTextNodes 层级可能与主页动态层级不同 richTextNodes = - item.modules.moduleDynamic.major.opus?.summary?.richTextNodes; - if (item.modules.moduleDynamic.major.opus?.title != null) { + item.modules.moduleDynamic!.major!.opus?.summary?.richTextNodes; + if (item.modules.moduleDynamic?.major?.opus?.title != null) { spanChildren.add( TextSpan( - text: item.modules.moduleDynamic.major.opus.title + '\n', - style: Theme.of(context) - .textTheme - .titleMedium! + text: '${item.modules.moduleDynamic!.major!.opus!.title!}\n', + style: theme.textTheme.titleMedium! .copyWith(fontWeight: FontWeight.bold), ), ); @@ -42,7 +42,8 @@ InlineSpan? richNode(item, BuildContext context) { for (var i in richTextNodes) { if (i.type == 'RICH_TEXT_NODE_TYPE_TEXT') { spanChildren.add( - TextSpan(text: i.origText, style: const TextStyle(height: 1.65))); + TextSpan(text: i.origText, style: const TextStyle(height: 1.65)), + ); } // @用户 else if (i.type == 'RICH_TEXT_NODE_TYPE_AT') { @@ -53,8 +54,7 @@ InlineSpan? richNode(item, BuildContext context) { mainAxisSize: MainAxisSize.min, children: [ GestureDetector( - onTap: () => Get.toNamed('/member?mid=${i.rid}', - arguments: {'face': null}), + onTap: () => Get.toNamed('/member?mid=${i.rid}'), child: Text( ' ${i.text}', style: authorStyle, @@ -88,7 +88,7 @@ InlineSpan? richNode(item, BuildContext context) { child: Icon( Icons.link, size: 20, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ); @@ -120,14 +120,12 @@ InlineSpan? richNode(item, BuildContext context) { child: GestureDetector( onTap: () { try { - String dynamicId = item.basic.commentIdStr; + String dynamicId = item.basic!.commentIdStr!; Get.toNamed( '/webview', parameters: { 'url': 'https://t.bilibili.com/vote/h5/index/#/result?vote_id=${i.rid}&dynamic_id=$dynamicId&isWeb=1', - 'type': 'vote', - 'pageTitle': '投票' }, ); } catch (_) {} @@ -161,7 +159,7 @@ InlineSpan? richNode(item, BuildContext context) { child: Icon( Icons.redeem_rounded, size: 16, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ); @@ -195,7 +193,7 @@ InlineSpan? richNode(item, BuildContext context) { child: Icon( Icons.shopping_bag_outlined, size: 16, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ); @@ -220,7 +218,7 @@ InlineSpan? richNode(item, BuildContext context) { child: Icon( Icons.play_circle_outline_outlined, size: 16, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ); @@ -234,7 +232,6 @@ InlineSpan? richNode(item, BuildContext context) { PageUtils.toVideoPage( 'bvid=${i.rid}&cid=$cid', arguments: { - 'pic': null, 'heroTag': Utils.makeHeroTag(i.rid), }, ); @@ -285,11 +282,6 @@ InlineSpan? richNode(item, BuildContext context) { } } catch (err) { debugPrint('❌rich_node_panel err: $err'); - return spacer; + return null; } } - -class _VerticalSpaceSpan extends WidgetSpan { - _VerticalSpaceSpan(double height) - : super(child: SizedBox(height: height, width: double.infinity)); -} diff --git a/lib/pages/dynamics/widgets/up_panel.dart b/lib/pages/dynamics/widgets/up_panel.dart index f4a40c07..bc579720 100644 --- a/lib/pages/dynamics/widgets/up_panel.dart +++ b/lib/pages/dynamics/widgets/up_panel.dart @@ -27,6 +27,7 @@ class _UpPanelState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); if (widget.dynamicsController.isLogin.value.not) { return const SizedBox.shrink(); } @@ -74,14 +75,15 @@ class _UpPanelState extends State { SliverList.builder( itemCount: liveList.length, itemBuilder: (context, index) { - return upItemBuild(liveList[index]); + return upItemBuild(theme, liveList[index]); }, ), SliverToBoxAdapter( - child: upItemBuild(UpItem(face: '', uname: '全部动态', mid: -1)), + child: upItemBuild(theme, UpItem(face: '', uname: '全部动态', mid: -1)), ), SliverToBoxAdapter( child: upItemBuild( + theme, UpItem( uname: '我', face: widget.dynamicsController.face, @@ -93,7 +95,7 @@ class _UpPanelState extends State { SliverList.builder( itemCount: upList.length, itemBuilder: (context, index) { - return upItemBuild(upList[index]); + return upItemBuild(theme, upList[index]); }, ), const SliverToBoxAdapter(child: SizedBox(height: 200)), @@ -101,7 +103,7 @@ class _UpPanelState extends State { ); } - Widget upItemBuild(data) { + Widget upItemBuild(theme, data) { bool isCurrent = widget.dynamicsController.currentMid == data.mid || widget.dynamicsController.currentMid == -1; return SizedBox( @@ -163,17 +165,14 @@ class _UpPanelState extends State { child: Badge( smallSize: 8, label: data.type == 'live' ? const Text(' Live ') : null, - textColor: - Theme.of(context).colorScheme.onSecondaryContainer, + textColor: theme.colorScheme.onSecondaryContainer, alignment: AlignmentDirectional.topStart, isLabelVisible: data.type == 'live' || (data.type == 'up' && (data.hasUpdate ?? false)), backgroundColor: data.type == 'live' - ? Theme.of(context) - .colorScheme - .secondaryContainer + ? theme.colorScheme.secondaryContainer .withOpacity(0.75) - : Theme.of(context).colorScheme.primary, + : theme.colorScheme.primary, ), ), ], @@ -189,8 +188,8 @@ class _UpPanelState extends State { textAlign: TextAlign.center, style: TextStyle( color: widget.dynamicsController.currentMid == data.mid - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, + ? theme.colorScheme.primary + : theme.colorScheme.outline, height: 1.1, fontSize: 12.5, ), @@ -203,31 +202,3 @@ class _UpPanelState extends State { ); } } - -class UpPanelSkeleton extends StatelessWidget { - const UpPanelSkeleton({super.key}); - - @override - Widget build(BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 50, - height: 50, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onInverseSurface, - borderRadius: BorderRadius.circular(50), - ), - ), - Container( - margin: const EdgeInsets.only(top: 6), - width: 45, - height: 12, - color: Theme.of(context).colorScheme.onInverseSurface, - ), - ], - ); - } -} diff --git a/lib/pages/dynamics/widgets/video_panel.dart b/lib/pages/dynamics/widgets/video_panel.dart index 56bbb040..a4bbfeb6 100644 --- a/lib/pages/dynamics/widgets/video_panel.dart +++ b/lib/pages/dynamics/widgets/video_panel.dart @@ -1,4 +1,5 @@ // 视频or合集 +import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:PiliPlus/common/constants.dart'; @@ -8,21 +9,28 @@ import 'package:PiliPlus/utils/utils.dart'; import 'rich_node_panel.dart'; -Widget videoSeasonWidget(source, item, context, type, {floor = 1}) { - if (item.modules.moduleDynamic.major?.type == 'MAJOR_TYPE_NONE') { - return item.modules.moduleDynamic.major?.none?.tips != null +Widget videoSeasonWidget( + ThemeData theme, + String? source, + DynamicItemModel item, + BuildContext context, + String type, { + floor = 1, +}) { + if (item.modules.moduleDynamic?.major?.type == 'MAJOR_TYPE_NONE') { + return item.modules.moduleDynamic?.major?.none?.tips != null ? Row( children: [ Icon( Icons.error, size: 18, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), const SizedBox(width: 5), Text( - '${item.modules.moduleDynamic.major.none.tips}', + item.modules.moduleDynamic!.major!.none!.tips!, style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ], @@ -30,8 +38,6 @@ Widget videoSeasonWidget(source, item, context, type, {floor = 1}) { : const SizedBox.shrink(); } - TextStyle authorStyle = - TextStyle(color: Theme.of(context).colorScheme.primary); // type archive ugcSeason // archive 视频/显示发布人 // ugcSeason 合集/不显示发布人 @@ -39,93 +45,97 @@ Widget videoSeasonWidget(source, item, context, type, {floor = 1}) { // floor 1 2 // 1 投稿视频 铺满 borderRadius 0 // 2 转发视频 铺满 borderRadius 6 - Map dynamicProperty = { - 'ugcSeason': item.modules.moduleDynamic.major.ugcSeason, - 'archive': item.modules.moduleDynamic.major.archive, - 'pgc': item.modules.moduleDynamic.major.pgc + + DynamicArchiveModel? content = switch (type) { + 'ugcSeason' => item.modules.moduleDynamic?.major?.ugcSeason, + 'archive' => item.modules.moduleDynamic?.major?.archive, + 'pgc' => item.modules.moduleDynamic?.major?.pgc, + _ => null, }; - dynamic content = dynamicProperty[type]; - InlineSpan? richNodes = richNode(item, context); + + if (content == null) { + return const SizedBox.shrink(); + } + + TextSpan? richNodes = richNode(theme, item, context); Widget buildCover() { - if (content?.cover == null) { - return const SizedBox.shrink(); - } - return LayoutBuilder(builder: (context, box) { - double width = box.maxWidth; - return Stack( - children: [ - NetworkImgLayer( - width: width, - height: width / StyleString.aspectRatio, - src: content.cover, - semanticsLabel: content.title, - ), - if (content?.badge?['text'] != null) - PBadge( - text: content.badge['text'], - top: 8.0, - right: 10.0, - bottom: null, - left: null, - type: content.badge['text'] == '充电专属' ? 'error' : 'primary', + return LayoutBuilder( + builder: (context, box) { + double width = box.maxWidth; + return Stack( + children: [ + NetworkImgLayer( + width: width, + height: width / StyleString.aspectRatio, + src: content.cover, ), - Positioned( - left: 0, - right: 0, - bottom: 0, - child: Container( - height: 70, - padding: const EdgeInsets.fromLTRB(10, 0, 8, 8), - clipBehavior: Clip.hardEdge, - decoration: BoxDecoration( - gradient: const LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Colors.transparent, - Colors.black54, - ], + if (content.badge?['text'] != null) + PBadge( + text: content.badge!['text'], + top: 8.0, + right: 10.0, + bottom: null, + left: null, + type: content.badge!['text'] == '充电专属' ? 'error' : 'primary', + ), + Positioned( + left: 0, + right: 0, + bottom: 0, + child: Container( + height: 70, + alignment: Alignment.bottomLeft, + padding: const EdgeInsets.fromLTRB(10, 0, 8, 8), + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + gradient: const LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.transparent, + Colors.black54, + ], + ), + borderRadius: const BorderRadius.only( + bottomLeft: StyleString.imgRadius, + bottomRight: StyleString.imgRadius, + ), ), - borderRadius: StyleString.mdRadius, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - DefaultTextStyle.merge( - style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Colors.white), - child: Row( - children: [ - if (content.durationText != null) - Text( - content.durationText, - semanticsLabel: - '时长${Utils.durationReadFormat(content.durationText)}', - ), - if (content.durationText != null) - const SizedBox(width: 6), - Text(content.stat.play + '次围观'), + child: DefaultTextStyle.merge( + style: TextStyle( + fontSize: theme.textTheme.labelMedium!.fontSize, + color: Colors.white, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + if (content.durationText != null) ...[ + Text( + content.durationText!, + semanticsLabel: + '时长${Utils.durationReadFormat(content.durationText!)}', + ), const SizedBox(width: 6), - Text(content.stat.danmu + '条弹幕') ], - ), + Text('${content.stat?.play}次围观'), + const SizedBox(width: 6), + Text('${content.stat?.danmu}条弹幕'), + const Spacer(), + Image.asset( + 'assets/images/play.png', + width: 50, + height: 50, + ), + ], ), - Image.asset( - 'assets/images/play.png', - width: 50, - height: 50, - ), - ], + ), ), ), - ), - ], - ); - }); + ], + ); + }, + ); } return Column( @@ -137,45 +147,50 @@ Widget videoSeasonWidget(source, item, context, type, {floor = 1}) { children: [ GestureDetector( onTap: () => Get.toNamed( - '/member?mid=${item.modules.moduleAuthor.mid}', - arguments: {'face': item.modules.moduleAuthor.face}), + '/member?mid=${item.modules.moduleAuthor!.mid}', + arguments: {'face': item.modules.moduleAuthor!.face}, + ), child: Text( - item.modules.moduleAuthor.type == null - ? '@${item.modules.moduleAuthor.name}' - : item.modules.moduleAuthor.name, - style: authorStyle, + item.modules.moduleAuthor?.type == null + ? '@${item.modules.moduleAuthor!.name}' + : item.modules.moduleAuthor!.name!, + style: TextStyle(color: theme.colorScheme.primary), ), ), const SizedBox(width: 6), - Text( - Utils.dateFormat(item.modules.moduleAuthor.pubTs), - style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: Theme.of(context).textTheme.labelSmall!.fontSize), - ), + if (item.modules.moduleAuthor?.pubTs != null) + Text( + Utils.dateFormat(item.modules.moduleAuthor!.pubTs), + style: TextStyle( + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize, + ), + ), ], ), const SizedBox(height: 6), ], - if (floor == 2 && item.modules.moduleDynamic.desc != null) ...[ - if (richNodes != null) Text.rich(richNodes), + if (floor == 2 && content.desc != null && richNodes != null) ...[ + Text.rich(richNodes), const SizedBox(height: 6), ], - if (item.isForwarded == true) - buildCover() - else - Padding( - padding: EdgeInsets.symmetric(horizontal: StyleString.safeSpace), - child: buildCover(), - ), + if (content.cover != null) + if (item.isForwarded == true) + buildCover() + else + Padding( + padding: + const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + child: buildCover(), + ), const SizedBox(height: 6), - if (content?.title != null) + if (content.title != null) Padding( padding: floor == 1 ? const EdgeInsets.only(left: 12, right: 12) : EdgeInsets.zero, child: Text( - content.title, + content.title!, maxLines: source == 'detail' ? null : 1, style: const TextStyle(fontWeight: FontWeight.bold), overflow: source == 'detail' ? null : TextOverflow.ellipsis, diff --git a/lib/pages/fav/article/widget/item.dart b/lib/pages/fav/article/widget/item.dart index 416da2d6..4b7d05b8 100644 --- a/lib/pages/fav/article/widget/item.dart +++ b/lib/pages/fav/article/widget/item.dart @@ -17,6 +17,7 @@ class FavArticleItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Material( color: Colors.transparent, child: Stack( @@ -66,10 +67,7 @@ class FavArticleItem extends StatelessWidget { child: Text( item['content'], style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .bodyMedium! - .fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, height: 1.42, letterSpacing: 0.3, ), @@ -83,7 +81,7 @@ class FavArticleItem extends StatelessWidget { // context: context, // value: item['stat']['view'], // goto: 'picture', - // textColor: Theme.of(context).colorScheme.outline, + // textColor: theme.colorScheme.outline, // ), // const SizedBox(width: 16), StatView( @@ -92,7 +90,7 @@ class FavArticleItem extends StatelessWidget { value: item['stat']['like'] == '' ? 0 : item['stat']['like'], - textColor: Theme.of(context).colorScheme.outline, + textColor: theme.colorScheme.outline, ), ], ), @@ -103,7 +101,7 @@ class FavArticleItem extends StatelessWidget { style: TextStyle( fontSize: 13, height: 1, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, overflow: TextOverflow.clip, ), ), @@ -122,7 +120,7 @@ class FavArticleItem extends StatelessWidget { context: context, onPressed: onDelete, icon: Icons.clear, - iconColor: Theme.of(context).colorScheme.outline, + iconColor: theme.colorScheme.outline, bgColor: Colors.transparent, ), ), diff --git a/lib/pages/fav/note/child_view.dart b/lib/pages/fav/note/child_view.dart index 76670e16..bd1f8b2f 100644 --- a/lib/pages/fav/note/child_view.dart +++ b/lib/pages/fav/note/child_view.dart @@ -28,6 +28,7 @@ class _FavNoteChildPageState extends State @override Widget build(BuildContext context) { super.build(context); + final theme = Theme.of(context); return LayoutBuilder( builder: (context, constraints) => Stack( clipBehavior: Clip.none, @@ -55,14 +56,11 @@ class _FavNoteChildPageState extends State child: Container( padding: MediaQuery.paddingOf(context), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, border: Border( top: BorderSide( width: 0.5, - color: Theme.of(context) - .colorScheme - .outline - .withOpacity(0.5), + color: theme.colorScheme.outline.withOpacity(0.5), ), ), ), diff --git a/lib/pages/fav/note/view.dart b/lib/pages/fav/note/view.dart index 3886635d..93d28fed 100644 --- a/lib/pages/fav/note/view.dart +++ b/lib/pages/fav/note/view.dart @@ -25,6 +25,7 @@ class _FavNotePageState extends State @override Widget build(BuildContext context) { super.build(context); + final theme = Theme.of(context); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -43,7 +44,7 @@ class _FavNotePageState extends State indicatorPadding: const EdgeInsets.symmetric(horizontal: 3, vertical: 8), indicator: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, + color: theme.colorScheme.secondaryContainer, borderRadius: BorderRadius.circular(20), ), indicatorSize: TabBarIndicatorSize.tab, @@ -51,8 +52,8 @@ class _FavNotePageState extends State .labelStyle ?.copyWith(fontSize: 14) ?? const TextStyle(fontSize: 14), - labelColor: Theme.of(context).colorScheme.onSecondaryContainer, - unselectedLabelColor: Theme.of(context).colorScheme.outline, + labelColor: theme.colorScheme.onSecondaryContainer, + unselectedLabelColor: theme.colorScheme.outline, tabs: [ Tab(text: '未发布笔记'), Tab(text: '公开笔记'), @@ -61,7 +62,7 @@ class _FavNotePageState extends State ), // TextButton( // style: TextButton.styleFrom( - // foregroundColor: Theme.of(context).colorScheme.onSurfaceVariant, + // foregroundColor: theme.colorScheme.onSurfaceVariant, // visualDensity: VisualDensity(horizontal: -2, vertical: -2), // tapTargetSize: MaterialTapTargetSize.shrinkWrap, // ), diff --git a/lib/pages/fav/note/widget/item.dart b/lib/pages/fav/note/widget/item.dart index 655c367d..4c71e498 100644 --- a/lib/pages/fav/note/widget/item.dart +++ b/lib/pages/fav/note/widget/item.dart @@ -19,6 +19,7 @@ class FavNoteItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Material( color: Colors.transparent, child: InkWell( @@ -72,7 +73,7 @@ class FavNoteItem extends StatelessWidget { style: TextStyle( fontSize: 13, height: 1, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, overflow: TextOverflow.clip, ), ), @@ -83,7 +84,7 @@ class FavNoteItem extends StatelessWidget { style: TextStyle( fontSize: 13, height: 1, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, overflow: TextOverflow.clip, ), ), @@ -137,9 +138,7 @@ class FavNoteItem extends StatelessWidget { backgroundColor: WidgetStateProperty.resolveWith( (states) { - return Theme.of(context) - .colorScheme - .surface + return theme.colorScheme.surface .withOpacity(0.8); }, ), @@ -147,9 +146,7 @@ class FavNoteItem extends StatelessWidget { onPressed: null, icon: Icon( Icons.done_all_outlined, - color: Theme.of(context) - .colorScheme - .primary, + color: theme.colorScheme.primary, ), ), ), diff --git a/lib/pages/fav/pgc/child_view.dart b/lib/pages/fav/pgc/child_view.dart index 5b928475..159b3475 100644 --- a/lib/pages/fav/pgc/child_view.dart +++ b/lib/pages/fav/pgc/child_view.dart @@ -35,6 +35,7 @@ class _FavPgcChildPageState extends State @override Widget build(BuildContext context) { super.build(context); + final theme = Theme.of(context); return LayoutBuilder( builder: (context, constraints) => Stack( clipBehavior: Clip.none, @@ -62,14 +63,11 @@ class _FavPgcChildPageState extends State child: Container( padding: MediaQuery.paddingOf(context), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, border: Border( top: BorderSide( width: 0.5, - color: Theme.of(context) - .colorScheme - .outline - .withOpacity(0.5), + color: theme.colorScheme.outline.withOpacity(0.5), ), ), ), @@ -135,9 +133,7 @@ class _FavPgcChildPageState extends State child: Text( '标记为${item['title']}', style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, ), ), ), diff --git a/lib/pages/fav/pgc/view.dart b/lib/pages/fav/pgc/view.dart index c6feb6d5..b515d8a1 100644 --- a/lib/pages/fav/pgc/view.dart +++ b/lib/pages/fav/pgc/view.dart @@ -27,6 +27,7 @@ class _FavPgcPageState extends State @override Widget build(BuildContext context) { super.build(context); + final theme = Theme.of(context); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -45,7 +46,7 @@ class _FavPgcPageState extends State indicatorPadding: const EdgeInsets.symmetric(horizontal: 3, vertical: 8), indicator: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, + color: theme.colorScheme.secondaryContainer, borderRadius: BorderRadius.circular(20), ), indicatorSize: TabBarIndicatorSize.tab, @@ -53,8 +54,8 @@ class _FavPgcPageState extends State .labelStyle ?.copyWith(fontSize: 14) ?? const TextStyle(fontSize: 14), - labelColor: Theme.of(context).colorScheme.onSecondaryContainer, - unselectedLabelColor: Theme.of(context).colorScheme.outline, + labelColor: theme.colorScheme.onSecondaryContainer, + unselectedLabelColor: theme.colorScheme.outline, tabs: const [ Tab(text: '想看'), Tab(text: '在看'), @@ -64,7 +65,7 @@ class _FavPgcPageState extends State ), // TextButton( // style: TextButton.styleFrom( - // foregroundColor: Theme.of(context).colorScheme.onSurfaceVariant, + // foregroundColor: theme.colorScheme.onSurfaceVariant, // visualDensity: VisualDensity(horizontal: -2, vertical: -2), // tapTargetSize: MaterialTapTargetSize.shrinkWrap, // ), diff --git a/lib/pages/fav/pgc/widget/item.dart b/lib/pages/fav/pgc/widget/item.dart index b3a4434b..e65c7a04 100644 --- a/lib/pages/fav/pgc/widget/item.dart +++ b/lib/pages/fav/pgc/widget/item.dart @@ -23,6 +23,7 @@ class FavPgcItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Material( color: Colors.transparent, child: Stack( @@ -108,9 +109,8 @@ class FavPgcItem extends StatelessWidget { WidgetStateProperty .resolveWith( (states) { - return Theme.of(context) - .colorScheme - .surface + return theme + .colorScheme.surface .withOpacity(0.8); }, ), @@ -118,9 +118,7 @@ class FavPgcItem extends StatelessWidget { onPressed: null, icon: Icon( Icons.done_all_outlined, - color: Theme.of(context) - .colorScheme - .primary, + color: theme.colorScheme.primary, ), ), ), @@ -148,9 +146,7 @@ class FavPgcItem extends StatelessWidget { '${item.newEp?['index_show']}${item.isFinish == 0 && item.renewalTime?.isNotEmpty == true ? ',${item.renewalTime}' : ''}', style: TextStyle( fontSize: 13, - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, ), ), ], @@ -162,9 +158,7 @@ class FavPgcItem extends StatelessWidget { item.progress!, style: TextStyle( fontSize: 13, - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, ), ), ], @@ -183,7 +177,7 @@ class FavPgcItem extends StatelessWidget { context: context, onPressed: onUpdateStatus, icon: Icons.more_vert, - iconColor: Theme.of(context).colorScheme.outline, + iconColor: theme.colorScheme.outline, bgColor: Colors.transparent, ), ), diff --git a/lib/pages/fav/video/widgets/item.dart b/lib/pages/fav/video/widgets/item.dart index c3a7c523..406f1722 100644 --- a/lib/pages/fav/video/widgets/item.dart +++ b/lib/pages/fav/video/widgets/item.dart @@ -27,7 +27,6 @@ class FavItem extends StatelessWidget { (onTap == null ? null : () => imageSaveDialog( - context: context, title: favFolderItem.title, cover: favFolderItem.cover, )), @@ -61,6 +60,9 @@ class FavItem extends StatelessWidget { } Widget videoContent(context) { + final theme = Theme.of(context); + final fontSize = theme.textTheme.labelMedium!.fontSize; + final color = theme.colorScheme.outline; return Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -76,23 +78,23 @@ class FavItem extends StatelessWidget { Text( favFolderItem.intro!, style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: fontSize, + color: color, ), ), Text( '${favFolderItem.mediaCount}个内容', style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: fontSize, + color: color, ), ), const Spacer(), Text( Utils.isPublicFavText(favFolderItem.attr ?? 0), style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: fontSize, + color: color, ), ), ], diff --git a/lib/pages/fav_detail/view.dart b/lib/pages/fav_detail/view.dart index 2b29bab4..dcbf3b2f 100644 --- a/lib/pages/fav_detail/view.dart +++ b/lib/pages/fav_detail/view.dart @@ -56,6 +56,7 @@ class _FavDetailPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Obx( () => PopScope( canPop: _favDetailController.enableMultiSelect.value.not, @@ -111,13 +112,11 @@ class _FavDetailPageState extends State { children: [ Text( _favDetailController.item.value.title ?? '', - style: - Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, ), Text( '共${_favDetailController.item.value.mediaCount}条视频', - style: - Theme.of(context).textTheme.labelMedium, + style: theme.textTheme.labelMedium, ) ], ), @@ -152,9 +151,7 @@ class _FavDetailPageState extends State { child: Text( '复制', style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, ), ), ), @@ -176,9 +173,7 @@ class _FavDetailPageState extends State { child: Text( '移动', style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, ), ), ), @@ -191,8 +186,8 @@ class _FavDetailPageState extends State { _favDetailController.onDelChecked(context), child: Text( '删除', - style: TextStyle( - color: Theme.of(context).colorScheme.error), + style: + TextStyle(color: theme.colorScheme.error), ), ), const SizedBox(width: 6), @@ -310,9 +305,7 @@ class _FavDetailPageState extends State { child: Text( '删除', style: TextStyle( - color: Theme.of(context) - .colorScheme - .error, + color: theme.colorScheme.error, ), ), ), @@ -362,10 +355,8 @@ class _FavDetailPageState extends State { .item.value.title ?? '', style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .titleMedium! - .fontSize, + fontSize: theme.textTheme + .titleMedium!.fontSize, fontWeight: FontWeight.bold), ), if (_favDetailController @@ -376,13 +367,10 @@ class _FavDetailPageState extends State { .item.value.intro ?? '', style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, - color: Theme.of(context) - .colorScheme - .outline), + fontSize: theme.textTheme + .labelSmall!.fontSize, + color: + theme.colorScheme.outline), ), const SizedBox(height: 4), Text( @@ -390,13 +378,9 @@ class _FavDetailPageState extends State { .item.value.upper?.name ?? '', style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, - color: Theme.of(context) - .colorScheme - .outline), + fontSize: theme.textTheme + .labelSmall!.fontSize, + color: theme.colorScheme.outline), ), const Spacer(), if (_favDetailController @@ -405,13 +389,10 @@ class _FavDetailPageState extends State { Text( '共${_favDetailController.item.value.mediaCount}条视频 · ${Utils.isPublicFavText(_favDetailController.item.value.attr ?? 0)}', style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, - color: Theme.of(context) - .colorScheme - .outline), + fontSize: theme.textTheme + .labelSmall!.fontSize, + color: + theme.colorScheme.outline), ), ], ), @@ -424,8 +405,8 @@ class _FavDetailPageState extends State { ), ), ), - Obx(() => - _buildBody(_favDetailController.loadingState.value)), + Obx(() => _buildBody( + theme, _favDetailController.loadingState.value)), ], ), ), @@ -435,7 +416,8 @@ class _FavDetailPageState extends State { ); } - Widget _buildBody(LoadingState?> loadingState) { + Widget _buildBody( + ThemeData theme, LoadingState?> loadingState) { return switch (loadingState) { Loading() => SliverGrid( gridDelegate: Grid.videoCardHDelegate(context), @@ -463,7 +445,7 @@ class _FavDetailPageState extends State { child: Text( _favDetailController.isEnd.not ? '加载中...' : '没有更多了', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, fontSize: 13, ), ), @@ -552,9 +534,7 @@ class _FavDetailPageState extends State { backgroundColor: WidgetStateProperty.resolveWith( (states) { - return Theme.of(context) - .colorScheme - .surface + return theme.colorScheme.surface .withOpacity(0.8); }, ), @@ -562,9 +542,7 @@ class _FavDetailPageState extends State { onPressed: null, icon: Icon( Icons.done_all_outlined, - color: Theme.of(context) - .colorScheme - .primary, + color: theme.colorScheme.primary, ), ), ), diff --git a/lib/pages/fav_detail/widget/fav_video_card.dart b/lib/pages/fav_detail/widget/fav_video_card.dart index e28b59d8..ec75608b 100644 --- a/lib/pages/fav_detail/widget/fav_video_card.dart +++ b/lib/pages/fav_detail/widget/fav_video_card.dart @@ -75,7 +75,6 @@ class FavVideoCardH extends StatelessWidget { onLongPress!(); } else { imageSaveDialog( - context: context, title: videoItem.title, cover: videoItem.pic, ); @@ -130,6 +129,7 @@ class FavVideoCardH extends StatelessWidget { } Widget videoContent(context) { + final theme = Theme.of(context); return Expanded( child: Stack( children: [ @@ -154,7 +154,7 @@ class FavVideoCardH extends StatelessWidget { style: TextStyle( height: 1, fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), const SizedBox(height: 3), @@ -184,7 +184,7 @@ class FavVideoCardH extends StatelessWidget { context: context, icon: Icons.clear, tooltip: '取消收藏', - iconColor: Theme.of(context).colorScheme.outline, + iconColor: theme.colorScheme.outline, bgColor: Colors.transparent, onPressed: () { showDialog( @@ -198,8 +198,8 @@ class FavVideoCardH extends StatelessWidget { onPressed: Get.back, child: Text( '取消', - style: TextStyle( - color: Theme.of(context).colorScheme.outline), + style: + TextStyle(color: theme.colorScheme.outline), ), ), TextButton( diff --git a/lib/pages/follow/widgets/follow_item.dart b/lib/pages/follow/widgets/follow_item.dart index 8a26a5fa..c78da51d 100644 --- a/lib/pages/follow/widgets/follow_item.dart +++ b/lib/pages/follow/widgets/follow_item.dart @@ -23,6 +23,7 @@ class FollowItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); String heroTag = Utils.makeHeroTag(item.mid); return ListTile( onTap: () { @@ -60,7 +61,7 @@ class FollowItem extends StatelessWidget { child: Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, ), child: Icon( Icons.offline_bolt, @@ -99,12 +100,11 @@ class FollowItem extends StatelessWidget { }, style: FilledButton.styleFrom( padding: const EdgeInsets.fromLTRB(15, 0, 15, 0), - foregroundColor: item.attribute == -1 - ? null - : Theme.of(context).colorScheme.outline, + foregroundColor: + item.attribute == -1 ? null : theme.colorScheme.outline, backgroundColor: item.attribute == -1 ? null - : Theme.of(context).colorScheme.onInverseSurface, + : theme.colorScheme.onInverseSurface, ), child: Text( '${item.attribute == -1 ? '' : '已'}关注', diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index 534f27d1..5907a2f5 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -36,6 +36,7 @@ class HistoryItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); int aid = videoItem.history.oid!; String bvid = videoItem.history.bvid ?? IdUtils.av2bv(aid); return InkWell( @@ -112,7 +113,6 @@ class HistoryItem extends StatelessWidget { return; } imageSaveDialog( - context: context, title: videoItem.title, cover: videoItem.cover, ); @@ -200,9 +200,7 @@ class HistoryItem extends StatelessWidget { backgroundColor: WidgetStateProperty.resolveWith( (states) { - return Theme.of(context) - .colorScheme - .surface + return theme.colorScheme.surface .withOpacity(0.8); }, ), @@ -212,8 +210,7 @@ class HistoryItem extends StatelessWidget { onChoose?.call(); }, icon: Icon(Icons.done_all_outlined, - color: - Theme.of(context).colorScheme.primary), + color: theme.colorScheme.primary), ), ), ), @@ -237,7 +234,7 @@ class HistoryItem extends StatelessWidget { ], ), const SizedBox(width: 10), - videoContent(context), + videoContent(theme), ], ), ), @@ -252,7 +249,7 @@ class HistoryItem extends StatelessWidget { tooltip: '功能菜单', icon: Icon( Icons.more_vert_outlined, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, size: 18, ), position: PopupMenuPosition.under, @@ -321,7 +318,7 @@ class HistoryItem extends StatelessWidget { ); } - Widget videoContent(context) { + Widget videoContent(ThemeData theme) { return Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -331,7 +328,7 @@ class HistoryItem extends StatelessWidget { videoItem.title, textAlign: TextAlign.start, style: TextStyle( - fontSize: Theme.of(context).textTheme.bodyMedium!.fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, height: 1.42, letterSpacing: 0.3, ), @@ -343,16 +340,16 @@ class HistoryItem extends StatelessWidget { Text( videoItem.authorName!, style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), ), const SizedBox(height: 2), Text( Utils.dateFormat(videoItem.viewAt!), style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), ), ], diff --git a/lib/pages/home/view.dart b/lib/pages/home/view.dart index f64fd68e..5337e139 100644 --- a/lib/pages/home/view.dart +++ b/lib/pages/home/view.dart @@ -30,6 +30,7 @@ class _HomePageState extends State @override Widget build(BuildContext context) { super.build(context); + final theme = Theme.of(context); return Scaffold( resizeToAvoidBottomInset: false, appBar: AppBar(toolbarHeight: 0), @@ -37,10 +38,10 @@ class _HomePageState extends State children: [ if (!_homeController.useSideBar && context.orientation == Orientation.portrait) - customAppBar, + customAppBar(theme), if (_homeController.tabs.length > 1) Material( - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, child: Container( height: 42, padding: const EdgeInsets.only(top: 4), @@ -78,10 +79,10 @@ class _HomePageState extends State ); } - Widget get searchBarAndUser { + Widget searchBarAndUser(ThemeData theme) { return Row( children: [ - searchBar, + searchBar(theme), const SizedBox(width: 4), Obx( () => _homeController.isLogin.value @@ -108,9 +109,7 @@ class _HomePageState extends State child: InkWell( onTap: () => _homeController.showUserInfoDialog(context), - splashColor: Theme.of(context) - .colorScheme - .primaryContainer + splashColor: theme.colorScheme.primaryContainer .withOpacity(0.3), borderRadius: const BorderRadius.all( Radius.circular(50), @@ -126,17 +125,14 @@ class _HomePageState extends State child: Container( padding: const EdgeInsets.all(2), decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer, + color: theme.colorScheme.secondaryContainer, shape: BoxShape.circle, ), child: Icon( size: 16, MdiIcons.incognito, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + color: + theme.colorScheme.onSecondaryContainer, ), ), ) @@ -144,7 +140,8 @@ class _HomePageState extends State ), ], ) - : DefaultUser( + : defaultUser( + theme: theme, onPressed: () => _homeController.showUserInfoDialog(context), ), @@ -154,7 +151,7 @@ class _HomePageState extends State ); } - Widget get customAppBar { + Widget customAppBar(ThemeData theme) { return StreamBuilder( stream: _homeController.hideSearchBar ? _mainController.navSearchStreamDebounce @@ -173,14 +170,14 @@ class _HomePageState extends State duration: const Duration(milliseconds: 500), height: snapshot.data ? 52 : 0, padding: const EdgeInsets.fromLTRB(14, 6, 14, 0), - child: searchBarAndUser, + child: searchBarAndUser(theme), ), ); }, ); } - Widget get searchBar { + Widget searchBar(ThemeData theme) { return Expanded( child: Container( height: 44, @@ -189,13 +186,9 @@ class _HomePageState extends State borderRadius: BorderRadius.circular(25), ), child: Material( - color: Theme.of(context) - .colorScheme - .onSecondaryContainer - .withOpacity(0.05), + color: theme.colorScheme.onSecondaryContainer.withOpacity(0.05), child: InkWell( - splashColor: - Theme.of(context).colorScheme.primaryContainer.withOpacity(0.3), + splashColor: theme.colorScheme.primaryContainer.withOpacity(0.3), onTap: () => Get.toNamed( '/search', parameters: { @@ -208,7 +201,7 @@ class _HomePageState extends State const SizedBox(width: 14), Icon( Icons.search_outlined, - color: Theme.of(context).colorScheme.onSecondaryContainer, + color: theme.colorScheme.onSecondaryContainer, semanticLabel: '搜索', ), const SizedBox(width: 10), @@ -219,8 +212,7 @@ class _HomePageState extends State _homeController.defaultSearch.value, maxLines: 1, overflow: TextOverflow.ellipsis, - style: TextStyle( - color: Theme.of(context).colorScheme.outline), + style: TextStyle(color: theme.colorScheme.outline), ), ), ), @@ -235,32 +227,29 @@ class _HomePageState extends State } } -class DefaultUser extends StatelessWidget { - const DefaultUser({super.key, required this.onPressed}); - final VoidCallback onPressed; - - @override - Widget build(BuildContext context) { - return SizedBox( - width: 38, - height: 38, - child: IconButton( - tooltip: '默认用户头像', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - backgroundColor: WidgetStateProperty.resolveWith((states) { - return Theme.of(context).colorScheme.onInverseSurface; - }), - ), - onPressed: onPressed, - icon: Icon( - Icons.person_rounded, - size: 22, - color: Theme.of(context).colorScheme.primary, - ), +Widget defaultUser({ + required ThemeData theme, + required VoidCallback onPressed, +}) { + return SizedBox( + width: 38, + height: 38, + child: IconButton( + tooltip: '默认用户头像', + style: ButtonStyle( + padding: WidgetStateProperty.all(EdgeInsets.zero), + backgroundColor: WidgetStateProperty.resolveWith((states) { + return theme.colorScheme.onInverseSurface; + }), ), - ); - } + onPressed: onPressed, + icon: Icon( + Icons.person_rounded, + size: 22, + color: theme.colorScheme.primary, + ), + ), + ); } Widget msgBadge(MainController mainController) { diff --git a/lib/pages/later/child_view.dart b/lib/pages/later/child_view.dart index 8c7cb8ad..87e9128c 100644 --- a/lib/pages/later/child_view.dart +++ b/lib/pages/later/child_view.dart @@ -61,6 +61,7 @@ class _LaterViewChildPageState extends State } Widget _buildBody(LoadingState?> loadingState) { + final theme = Theme.of(context); return switch (loadingState) { Loading() => SliverGrid( gridDelegate: Grid.videoCardHDelegate(context), @@ -150,9 +151,7 @@ class _LaterViewChildPageState extends State backgroundColor: WidgetStateProperty.resolveWith( (states) { - return Theme.of(context) - .colorScheme - .surface + return theme.colorScheme.surface .withOpacity(0.8); }, ), @@ -160,9 +159,7 @@ class _LaterViewChildPageState extends State onPressed: null, icon: Icon( Icons.done_all_outlined, - color: Theme.of(context) - .colorScheme - .primary, + color: theme.colorScheme.primary, ), ), ), @@ -186,7 +183,7 @@ class _LaterViewChildPageState extends State ); }, icon: Icons.clear, - iconColor: Theme.of(context).colorScheme.outline, + iconColor: theme.colorScheme.outline, bgColor: Colors.transparent, ), ), diff --git a/lib/pages/later/view.dart b/lib/pages/later/view.dart index b8725dd7..8b428cb7 100644 --- a/lib/pages/later/view.dart +++ b/lib/pages/later/view.dart @@ -129,7 +129,8 @@ class _LaterPageState extends State } PreferredSizeWidget get _buildAppbar { - Color color = Theme.of(context).colorScheme.secondary; + final theme = Theme.of(context); + Color color = theme.colorScheme.secondary; return AppBarWidget( visible: _baseCtr.enableMultiSelect.value, @@ -284,7 +285,7 @@ class _LaterPageState extends State child: Text( '复制', style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, ), ), ), @@ -305,7 +306,7 @@ class _LaterPageState extends State child: Text( '移动', style: TextStyle( - color: Theme.of(context).colorScheme.onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, ), ), ), @@ -316,7 +317,7 @@ class _LaterPageState extends State onPressed: () => currCtr().onDelChecked(context), child: Text( '移除', - style: TextStyle(color: Theme.of(context).colorScheme.error), + style: TextStyle(color: theme.colorScheme.error), ), ), const SizedBox(width: 6), diff --git a/lib/pages/live/view.dart b/lib/pages/live/view.dart index 32b49060..fc215c99 100644 --- a/lib/pages/live/view.dart +++ b/lib/pages/live/view.dart @@ -120,6 +120,7 @@ class _LivePageState extends CommonPageState } Widget _buildFollowList() { + final theme = Theme.of(context); return Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -135,14 +136,14 @@ class _LivePageState extends CommonPageState text: '${controller.liveCount.value}', style: TextStyle( fontSize: 13, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), TextSpan( text: '人正在直播', style: TextStyle( fontSize: 13, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ], @@ -160,25 +161,25 @@ class _LivePageState extends CommonPageState Text( '查看更多', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), Icon( size: 20, Icons.keyboard_arrow_right_outlined, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ], ), ), ], ), - Obx(() => _buildFollowBody(controller.followListState.value)), + Obx(() => _buildFollowBody(theme, controller.followListState.value)), ], ); } - Widget _buildFollowBody(LoadingState loadingState) { + Widget _buildFollowBody(ThemeData theme, LoadingState loadingState) { return switch (loadingState) { Loading() => SizedBox( height: 80, @@ -223,7 +224,7 @@ class _LivePageState extends CommonPageState decoration: BoxDecoration( border: Border.all( width: 1.5, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, strokeAlign: BorderSide.strokeAlignOutside, ), shape: BoxShape.circle, diff --git a/lib/pages/live/widgets/live_item.dart b/lib/pages/live/widgets/live_item.dart index 2a30e85c..e215f797 100644 --- a/lib/pages/live/widgets/live_item.dart +++ b/lib/pages/live/widgets/live_item.dart @@ -26,7 +26,6 @@ class LiveCardV extends StatelessWidget { Get.toNamed('/liveRoom?roomid=${liveItem.roomId}'); }, onLongPress: () => imageSaveDialog( - context: context, title: liveItem.title, cover: liveItem.cover, ), @@ -72,6 +71,7 @@ class LiveCardV extends StatelessWidget { } Widget liveContent(context) { + final theme = Theme.of(context); return Expanded( flex: 1, child: Padding( @@ -96,9 +96,8 @@ class LiveCardV extends StatelessWidget { '${liveItem.uname}', textAlign: TextAlign.start, style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), maxLines: 1, overflow: TextOverflow.ellipsis, diff --git a/lib/pages/live/widgets/live_item_follow.dart b/lib/pages/live/widgets/live_item_follow.dart index 85ef3f10..82978e6e 100644 --- a/lib/pages/live/widgets/live_item_follow.dart +++ b/lib/pages/live/widgets/live_item_follow.dart @@ -26,7 +26,6 @@ class LiveCardVFollow extends StatelessWidget { Get.toNamed('/liveRoom?roomid=${liveItem.roomId}'); }, onLongPress: () => imageSaveDialog( - context: context, title: liveItem.title, cover: liveItem.roomCover, ), @@ -72,6 +71,7 @@ class LiveCardVFollow extends StatelessWidget { } Widget liveContent(context) { + final theme = Theme.of(context); return Expanded( flex: 1, child: Padding( @@ -96,9 +96,8 @@ class LiveCardVFollow extends StatelessWidget { '${liveItem.uname}', textAlign: TextAlign.start, style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), maxLines: 1, overflow: TextOverflow.ellipsis, diff --git a/lib/pages/live_room/send_dm_panel.dart b/lib/pages/live_room/send_dm_panel.dart index e324bf70..5df34d3c 100644 --- a/lib/pages/live_room/send_dm_panel.dart +++ b/lib/pages/live_room/send_dm_panel.dart @@ -48,6 +48,7 @@ class _ReplyPageState extends CommonPublishPageState { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return MediaQuery.removePadding( removeTop: true, context: context, @@ -67,9 +68,8 @@ class _ReplyPageState extends CommonPublishPageState { child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ - buildInputView(), - buildPanelContainer( - Theme.of(context).colorScheme.surface), + buildInputView(theme), + buildPanelContainer(theme.colorScheme.surface), ], ), ), @@ -98,7 +98,7 @@ class _ReplyPageState extends CommonPublishPageState { ), ); - Widget buildInputView() { + Widget buildInputView(ThemeData theme) { return Container( clipBehavior: Clip.hardEdge, margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top), @@ -107,7 +107,7 @@ class _ReplyPageState extends CommonPublishPageState { topLeft: Radius.circular(12), topRight: Radius.circular(12), ), - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, ), child: Column( mainAxisSize: MainAxisSize.min, @@ -145,7 +145,7 @@ class _ReplyPageState extends CommonPublishPageState { hintText: "输入弹幕内容", border: InputBorder.none, hintStyle: TextStyle(fontSize: 14)), - style: Theme.of(context).textTheme.bodyLarge, + style: theme.textTheme.bodyLarge, inputFormatters: [LengthLimitingTextInputFormatter(20)], ), ), @@ -154,7 +154,7 @@ class _ReplyPageState extends CommonPublishPageState { ), Divider( height: 1, - color: Theme.of(context).dividerColor.withOpacity(0.1), + color: theme.dividerColor.withOpacity(0.1), ), Container( height: 52, diff --git a/lib/pages/login/view.dart b/lib/pages/login/view.dart index 1794d6f4..62c156b8 100644 --- a/lib/pages/login/view.dart +++ b/lib/pages/login/view.dart @@ -26,7 +26,7 @@ class _LoginPageState extends State { bool showPassword = false; GlobalKey globalKey = GlobalKey(); - Widget loginByQRCode() { + Widget loginByQRCode(ThemeData theme) { return Column( children: [ const SizedBox(height: 20), @@ -35,7 +35,7 @@ class _LoginPageState extends State { Obx(() => Text('剩余有效时间: ${_loginPageCtr.qrCodeLeftTime} 秒', style: TextStyle( fontFeatures: const [FontFeature.tabularFigures()], - color: Theme.of(context).colorScheme.primaryFixedDim))), + color: theme.colorScheme.primaryFixedDim))), const SizedBox(height: 5), Row( mainAxisAlignment: MainAxisAlignment.center, @@ -110,8 +110,7 @@ class _LoginPageState extends State { const SizedBox(height: 10), Obx(() => Text( _loginPageCtr.statusQRCode.value, - style: TextStyle( - color: Theme.of(context).colorScheme.secondaryFixedDim), + style: TextStyle(color: theme.colorScheme.secondaryFixedDim), )), Obx(() => GestureDetector( onTap: () { @@ -123,26 +122,20 @@ class _LoginPageState extends State { padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), child: Text(_loginPageCtr.codeInfo['data']?['url'] ?? "", - style: Theme.of(context).textTheme.labelSmall!.copyWith( - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(0.4))), + style: theme.textTheme.labelSmall!.copyWith( + color: theme.colorScheme.onSurface.withOpacity(0.4))), ), )), Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Text('请务必在 PiliPlus 开源仓库等可信渠道下载安装。', - style: Theme.of(context).textTheme.labelSmall!.copyWith( - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(0.4)))), + style: theme.textTheme.labelSmall!.copyWith( + color: theme.colorScheme.onSurface.withOpacity(0.4)))), ], ); } - Widget loginByCookie() { + Widget loginByCookie(ThemeData theme) { return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -153,9 +146,9 @@ class _LoginPageState extends State { padding: const EdgeInsets.symmetric(horizontal: 20), child: Text( '使用App端Api实现的功能将不可用', - style: Theme.of(context).textTheme.labelMedium!.copyWith( - color: Theme.of(context).colorScheme.primary, - ), + style: theme.textTheme.labelMedium!.copyWith( + color: theme.colorScheme.primary, + ), ), ), const SizedBox(height: 10), @@ -186,7 +179,7 @@ class _LoginPageState extends State { ); } - Widget loginByPassword() { + Widget loginByPassword(ThemeData theme) { return Column( children: [ const SizedBox(height: 20), @@ -317,16 +310,13 @@ class _LoginPageState extends State { '账号密码仅用于该登录接口,不予保存;本地仅存储登录凭证。\n' '请务必在 PiliPlus 开源仓库等可信渠道下载安装。', textAlign: TextAlign.center, - style: Theme.of(context).textTheme.labelSmall!.copyWith( - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(0.4)))), + style: theme.textTheme.labelSmall!.copyWith( + color: theme.colorScheme.onSurface.withOpacity(0.4)))), ], ); } - Widget loginBySmS() { + Widget loginBySmS(ThemeData theme) { return Column( children: [ const SizedBox(height: 20), @@ -337,15 +327,14 @@ class _LoginPageState extends State { child: Container( decoration: UnderlineTabIndicator( borderSide: BorderSide( - color: - Theme.of(context).colorScheme.outline.withOpacity(0.4)), + color: theme.colorScheme.outline.withOpacity(0.4)), ), child: Row( children: [ const SizedBox(width: 12), Icon( Icons.phone, - color: Theme.of(context).colorScheme.onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, ), const SizedBox(width: 12), PopupMenuButton>( @@ -379,10 +368,7 @@ class _LoginPageState extends State { SizedBox( height: 24, child: VerticalDivider( - color: Theme.of(context) - .colorScheme - .outline - .withOpacity(0.5), + color: theme.colorScheme.outline.withOpacity(0.5), ), ), const SizedBox(width: 6), @@ -410,8 +396,7 @@ class _LoginPageState extends State { child: Container( decoration: UnderlineTabIndicator( borderSide: BorderSide( - color: - Theme.of(context).colorScheme.outline.withOpacity(0.4)), + color: theme.colorScheme.outline.withOpacity(0.4)), ), child: Row( children: [ @@ -455,17 +440,15 @@ class _LoginPageState extends State { '本地仅存储登录凭证。\n' '请务必在 PiliPlus 开源仓库等可信渠道下载安装。', textAlign: TextAlign.center, - style: Theme.of(context).textTheme.labelSmall!.copyWith( - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(0.4)))), + style: theme.textTheme.labelSmall!.copyWith( + color: theme.colorScheme.onSurface.withOpacity(0.4)))), ], ); } @override Widget build(BuildContext context) { + final theme = Theme.of(context); return OrientationBuilder(builder: (context, orientation) { return Scaffold( appBar: AppBar( @@ -542,10 +525,10 @@ class _LoginPageState extends State { child: tabBarView( controller: _loginPageCtr.tabController, children: [ - tabViewOuter(loginByPassword()), - tabViewOuter(loginBySmS()), - tabViewOuter(loginByQRCode()), - tabViewOuter(loginByCookie()), + tabViewOuter(loginByPassword(theme)), + tabViewOuter(loginBySmS(theme)), + tabViewOuter(loginByQRCode(theme)), + tabViewOuter(loginByCookie(theme)), ], ), ), diff --git a/lib/pages/main/view.dart b/lib/pages/main/view.dart index 2e700140..c7280343 100644 --- a/lib/pages/main/view.dart +++ b/lib/pages/main/view.dart @@ -173,6 +173,7 @@ class _MainAppState extends State @override Widget build(BuildContext context) { + final theme = Theme.of(context); final bool isPortrait = context.orientation == Orientation.portrait; return PopScope( canPop: false, @@ -192,8 +193,7 @@ class _MainAppState extends State child: AnnotatedRegion( value: SystemUiOverlayStyle( systemNavigationBarColor: Colors.transparent, - systemNavigationBarIconBrightness: - Theme.of(context).brightness.reverse, + systemNavigationBarIconBrightness: theme.brightness.reverse, ), child: Scaffold( resizeToAvoidBottomInset: false, @@ -210,7 +210,7 @@ class _MainAppState extends State SizedBox( height: MediaQuery.paddingOf(context).top + 50), - userAndSearchVertical, + userAndSearchVertical(theme), const Spacer(flex: 2), Expanded( flex: 5, @@ -259,7 +259,7 @@ class _MainAppState extends State _mainController.selectedIndex.value, onDestinationSelected: setIndex, labelType: NavigationRailLabelType.selected, - leading: userAndSearchVertical, + leading: userAndSearchVertical(theme), destinations: _mainController.navigationBars .map( (e) => NavigationRailDestination( @@ -285,7 +285,7 @@ class _MainAppState extends State top: 10, ), width: 80, - child: userAndSearchVertical, + child: userAndSearchVertical(theme), ), ), ), @@ -293,8 +293,7 @@ class _MainAppState extends State width: 1, indent: MediaQuery.of(context).padding.top, endIndent: MediaQuery.of(context).padding.bottom, - color: - Theme.of(context).colorScheme.outline.withOpacity(0.06), + color: theme.colorScheme.outline.withOpacity(0.06), ), ], Expanded( @@ -418,7 +417,7 @@ class _MainAppState extends State ) : icon; - Widget get userAndSearchVertical { + Widget userAndSearchVertical(ThemeData theme) { return Column( children: [ Semantics( @@ -440,9 +439,7 @@ class _MainAppState extends State child: InkWell( onTap: () => _homeController.showUserInfoDialog(context), - splashColor: Theme.of(context) - .colorScheme - .primaryContainer + splashColor: theme.colorScheme.primaryContainer .withOpacity(0.3), borderRadius: const BorderRadius.all( Radius.circular(50), @@ -458,17 +455,14 @@ class _MainAppState extends State child: Container( padding: const EdgeInsets.all(2), decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer, + color: theme.colorScheme.secondaryContainer, shape: BoxShape.circle, ), child: Icon( size: 16, MdiIcons.incognito, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + color: + theme.colorScheme.onSecondaryContainer, ), ), ) @@ -476,9 +470,11 @@ class _MainAppState extends State ), ], ) - : DefaultUser( + : defaultUser( + theme: theme, onPressed: () => - _homeController.showUserInfoDialog(context)), + _homeController.showUserInfoDialog(context), + ), ), ), const SizedBox(height: 8), diff --git a/lib/pages/media/view.dart b/lib/pages/media/view.dart index 7c27d692..3a5c4980 100644 --- a/lib/pages/media/view.dart +++ b/lib/pages/media/view.dart @@ -39,7 +39,8 @@ class _MediaPageState extends CommonPageState @override Widget build(BuildContext context) { super.build(context); - Color primary = Theme.of(context).colorScheme.primary; + final theme = Theme.of(context); + Color primary = theme.colorScheme.primary; return MediaQuery.removePadding( context: context, removeLeft: context.orientation == Orientation.landscape, @@ -59,7 +60,7 @@ class _MediaPageState extends CommonPageState child: Text( '媒体库', style: TextStyle( - fontSize: Theme.of(context).textTheme.titleLarge!.fontSize, + fontSize: theme.textTheme.titleLarge!.fontSize, fontWeight: FontWeight.bold, ), ), @@ -97,7 +98,7 @@ class _MediaPageState extends CommonPageState Obx( () => controller.loadingState.value is Loading ? const SizedBox.shrink() - : favFolder(), + : favFolder(theme), ) ], ), @@ -105,12 +106,12 @@ class _MediaPageState extends CommonPageState ); } - Widget favFolder() { + Widget favFolder(ThemeData theme) { return Column( children: [ Divider( height: 20, - color: Theme.of(context).dividerColor.withOpacity(0.1), + color: theme.dividerColor.withOpacity(0.1), ), ListTile( onTap: () async { @@ -129,24 +130,22 @@ class _MediaPageState extends CommonPageState TextSpan( text: '我的收藏 ', style: TextStyle( - fontSize: - Theme.of(context).textTheme.titleMedium!.fontSize, + fontSize: theme.textTheme.titleMedium!.fontSize, fontWeight: FontWeight.bold), ), if (controller.count.value != -1) TextSpan( text: "${controller.count.value} ", style: TextStyle( - fontSize: - Theme.of(context).textTheme.titleSmall!.fontSize, - color: Theme.of(context).colorScheme.primary, + fontSize: theme.textTheme.titleSmall!.fontSize, + color: theme.colorScheme.primary, ), ), WidgetSpan( child: Icon( Icons.arrow_forward_ios, size: 18, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ], @@ -163,14 +162,14 @@ class _MediaPageState extends CommonPageState SizedBox( width: double.infinity, height: 200, - child: Obx(() => _buildBody(controller.loadingState.value)), + child: Obx(() => _buildBody(theme, controller.loadingState.value)), ), const SizedBox(height: 100), ], ); } - Widget _buildBody(LoadingState loadingState) { + Widget _buildBody(ThemeData theme, LoadingState loadingState) { if (loadingState is Success) { List? favFolderList = loadingState.response.list; if (favFolderList.isNullOrEmpty) { @@ -189,9 +188,7 @@ class _MediaPageState extends CommonPageState style: ButtonStyle( padding: WidgetStateProperty.all(EdgeInsets.zero), backgroundColor: WidgetStateProperty.resolveWith((states) { - return Theme.of(context) - .colorScheme - .primaryContainer + return theme.colorScheme.primaryContainer .withOpacity(0.5); }), ), @@ -204,7 +201,7 @@ class _MediaPageState extends CommonPageState icon: Icon( Icons.arrow_forward_ios, size: 18, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ), @@ -266,6 +263,7 @@ class FavFolderItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Container( margin: EdgeInsets.only(left: index == 0 ? 20 : 0, right: 14), child: GestureDetector( @@ -282,16 +280,10 @@ class FavFolderItem extends StatelessWidget { clipBehavior: Clip.hardEdge, decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), - color: Theme.of(context) - .colorScheme - .onInverseSurface - .withOpacity(0.4), + color: theme.colorScheme.onInverseSurface.withOpacity(0.4), boxShadow: [ BoxShadow( - color: Theme.of(context) - .colorScheme - .onInverseSurface - .withOpacity(0.4), + color: theme.colorScheme.onInverseSurface.withOpacity(0.4), offset: const Offset(4, -12), blurRadius: 0.0, spreadRadius: 0.0, @@ -318,10 +310,8 @@ class FavFolderItem extends StatelessWidget { ), Text( ' 共${item!.mediaCount}条视频 · ${Utils.isPublicFavText(item?.attr ?? 0)}', - style: Theme.of(context) - .textTheme - .labelSmall! - .copyWith(color: Theme.of(context).colorScheme.outline), + style: theme.textTheme.labelSmall! + .copyWith(color: theme.colorScheme.outline), ) ], ), diff --git a/lib/pages/member/content/member_contribute/content/article/widget/item.dart b/lib/pages/member/content/member_contribute/content/article/widget/item.dart index 06136f12..67910b5d 100644 --- a/lib/pages/member/content/member_contribute/content/article/widget/item.dart +++ b/lib/pages/member/content/member_contribute/content/article/widget/item.dart @@ -13,6 +13,8 @@ class MemberArticleItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); + final outline = theme.colorScheme.outline; return Material( color: Colors.transparent, child: InkWell( @@ -23,7 +25,6 @@ class MemberArticleItem extends StatelessWidget { }, onLongPress: () { imageSaveDialog( - context: context, title: item.title, cover: item.originImageUrls?.firstOrNull, ); @@ -65,10 +66,7 @@ class MemberArticleItem extends StatelessWidget { maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .bodyMedium! - .fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, height: 1.42, letterSpacing: 0.3, ), @@ -80,7 +78,7 @@ class MemberArticleItem extends StatelessWidget { style: TextStyle( fontSize: 12, height: 1, - color: Theme.of(context).colorScheme.outline, + color: outline, ), ), const SizedBox(height: 3), @@ -90,14 +88,14 @@ class MemberArticleItem extends StatelessWidget { context: context, value: item.stats?.view ?? 0, goto: 'picture', - textColor: Theme.of(context).colorScheme.outline, + textColor: outline, ), const SizedBox(width: 16), StatView( context: context, goto: 'reply', value: item.stats?.reply ?? 0, - textColor: Theme.of(context).colorScheme.outline, + textColor: outline, ), ], ), diff --git a/lib/pages/member/content/member_contribute/content/favorite/member_favorite.dart b/lib/pages/member/content/member_contribute/content/favorite/member_favorite.dart index 50c26224..6961e29c 100644 --- a/lib/pages/member/content/member_contribute/content/favorite/member_favorite.dart +++ b/lib/pages/member/content/member_contribute/content/favorite/member_favorite.dart @@ -39,6 +39,7 @@ class _MemberFavoriteState extends State } _buildBody(LoadingState loadingState) { + final theme = Theme.of(context); return switch (loadingState) { Loading() => loadingWidget, Success() => (loadingState.response as List?)?.isNotEmpty == true @@ -50,12 +51,12 @@ class _MemberFavoriteState extends State slivers: [ SliverToBoxAdapter( child: Obx( - () => _buildItem(_controller.first.value, true), + () => _buildItem(theme, _controller.first.value, true), ), ), SliverToBoxAdapter( child: Obx( - () => _buildItem(_controller.second.value, false), + () => _buildItem(theme, _controller.second.value, false), ), ), SliverToBoxAdapter( @@ -76,9 +77,9 @@ class _MemberFavoriteState extends State }; } - _buildItem(Datum data, bool isFirst) { + _buildItem(ThemeData theme, Datum data, bool isFirst) { return Theme( - data: Theme.of(context).copyWith( + data: theme.copyWith( dividerColor: Colors.transparent, ), child: ExpansionTile( @@ -95,7 +96,7 @@ class _MemberFavoriteState extends State text: ' ${data.mediaListResponse?.count}', style: TextStyle( fontSize: 13, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ], @@ -127,14 +128,14 @@ class _MemberFavoriteState extends State ? _controller.firstEnd.value : _controller.secondEnd.value) ? const SizedBox.shrink() - : _buildLoadMoreItem(isFirst), + : _buildLoadMoreItem(theme, isFirst), ), ], ), ); } - _buildLoadMoreItem(bool isFirst) { + _buildLoadMoreItem(ThemeData theme, bool isFirst) { return ListTile( dense: true, onTap: () { @@ -148,7 +149,7 @@ class _MemberFavoriteState extends State '查看更多内容', textAlign: TextAlign.center, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ); diff --git a/lib/pages/member/content/member_contribute/content/favorite/widget/item.dart b/lib/pages/member/content/member_contribute/content/favorite/widget/item.dart index 177e1837..6c959318 100644 --- a/lib/pages/member/content/member_contribute/content/favorite/widget/item.dart +++ b/lib/pages/member/content/member_contribute/content/favorite/widget/item.dart @@ -16,6 +16,7 @@ class MemberFavItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Material( color: Colors.transparent, child: InkWell( @@ -58,7 +59,6 @@ class MemberFavItem extends StatelessWidget { }, onLongPress: () { imageSaveDialog( - context: context, title: item.title, cover: item.cover, ); @@ -100,12 +100,12 @@ class MemberFavItem extends StatelessWidget { padding: const EdgeInsets.all(5), decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), child: Icon( Icons.video_library_outlined, size: 12, - color: Theme.of(context).colorScheme.onPrimary, + color: theme.colorScheme.onPrimary, ), ), ), @@ -136,7 +136,7 @@ class MemberFavItem extends StatelessWidget { : '${item.mediaCount}个内容', style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ], diff --git a/lib/pages/member/content/member_contribute/content/season_series/widget/season_series_card.dart b/lib/pages/member/content/member_contribute/content/season_series/widget/season_series_card.dart index d9e58658..c42ff859 100644 --- a/lib/pages/member/content/member_contribute/content/season_series/widget/season_series_card.dart +++ b/lib/pages/member/content/member_contribute/content/season_series/widget/season_series_card.dart @@ -19,7 +19,6 @@ class SeasonSeriesCard extends StatelessWidget { return InkWell( onLongPress: () { imageSaveDialog( - context: context, title: item['meta']['name'], cover: item['meta']['cover'], ); @@ -67,6 +66,7 @@ class SeasonSeriesCard extends StatelessWidget { } Widget videoContent(context) { + final theme = Theme.of(context); return Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -75,7 +75,7 @@ class SeasonSeriesCard extends StatelessWidget { item['meta']['name'], textAlign: TextAlign.start, style: TextStyle( - fontSize: Theme.of(context).textTheme.bodyMedium!.fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, height: 1.42, letterSpacing: 0.3, ), @@ -89,7 +89,7 @@ class SeasonSeriesCard extends StatelessWidget { style: TextStyle( fontSize: 12, height: 1, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, overflow: TextOverflow.clip, ), ), diff --git a/lib/pages/member/content/member_contribute/content/video/member_video.dart b/lib/pages/member/content/member_contribute/content/video/member_video.dart index e75e55d5..1b3e92ab 100644 --- a/lib/pages/member/content/member_contribute/content/video/member_video.dart +++ b/lib/pages/member/content/member_contribute/content/video/member_video.dart @@ -61,6 +61,7 @@ class _MemberVideoState extends State } _buildBody(LoadingState?> loadingState) { + final theme = Theme.of(context); return switch (loadingState) { Loading() => loadingWidget, Success() => loadingState.response?.isNotEmpty == true @@ -82,7 +83,7 @@ class _MemberVideoState extends State floating: true, delegate: CustomSliverPersistentHeaderDelegate( extent: 40, - bgColor: Theme.of(context).colorScheme.surface, + bgColor: theme.colorScheme.surface, child: SizedBox( height: 40, child: Row( @@ -115,9 +116,8 @@ class _MemberVideoState extends State icon: Icon( Icons.play_circle_outline_rounded, size: 16, - color: Theme.of(context) - .colorScheme - .secondary, + color: + theme.colorScheme.secondary, ), label: Text( _controller.episodicButton.value @@ -125,9 +125,8 @@ class _MemberVideoState extends State '播放全部', style: TextStyle( fontSize: 13, - color: Theme.of(context) - .colorScheme - .secondary, + color: + theme.colorScheme.secondary, ), ), ), @@ -142,9 +141,7 @@ class _MemberVideoState extends State icon: Icon( Icons.sort, size: 16, - color: Theme.of(context) - .colorScheme - .secondary, + color: theme.colorScheme.secondary, ), label: Obx( () => Text( @@ -158,9 +155,7 @@ class _MemberVideoState extends State : '倒序', style: TextStyle( fontSize: 13, - color: Theme.of(context) - .colorScheme - .secondary, + color: theme.colorScheme.secondary, ), ), ), diff --git a/lib/pages/member/content/member_contribute/member_contribute.dart b/lib/pages/member/content/member_contribute/member_contribute.dart index 85ea741b..1bfebc0a 100644 --- a/lib/pages/member/content/member_contribute/member_contribute.dart +++ b/lib/pages/member/content/member_contribute/member_contribute.dart @@ -40,6 +40,7 @@ class _MemberContributeState extends State @override Widget build(BuildContext context) { super.build(context); + final theme = Theme.of(context); return _controller.tabs != null ? Column( children: [ @@ -58,7 +59,7 @@ class _MemberContributeState extends State indicatorPadding: const EdgeInsets.symmetric(horizontal: 3, vertical: 8), indicator: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, + color: theme.colorScheme.secondaryContainer, borderRadius: BorderRadius.circular(20), ), indicatorSize: TabBarIndicatorSize.tab, @@ -66,9 +67,8 @@ class _MemberContributeState extends State .labelStyle ?.copyWith(fontSize: 14) ?? const TextStyle(fontSize: 14), - labelColor: - Theme.of(context).colorScheme.onSecondaryContainer, - unselectedLabelColor: Theme.of(context).colorScheme.outline, + labelColor: theme.colorScheme.onSecondaryContainer, + unselectedLabelColor: theme.colorScheme.outline, ), ), Expanded( diff --git a/lib/pages/member/content/member_home/member_home.dart b/lib/pages/member/content/member_home/member_home.dart index b7f2483c..424eb94f 100644 --- a/lib/pages/member/content/member_home/member_home.dart +++ b/lib/pages/member/content/member_home/member_home.dart @@ -245,100 +245,94 @@ class _MemberHomeState extends State required String param, String? param1, required int count, - }) => - SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text.rich( + }) { + final color = Theme.of(context).colorScheme.outline; + return SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text.rich( + TextSpan( + children: [ + TextSpan(text: '$title '), + TextSpan( + text: count.toString(), + style: TextStyle(fontSize: 13, color: color), + ), + ], + ), + ), + GestureDetector( + onTap: () { + int index = + _ctr.tab2!.indexWhere((item) => item.param == param); + if (index != -1) { + if (['video', 'article', 'audio'].contains(param1)) { + List items = _ctr.tab2! + .firstWhere((item) => item.param == param) + .items!; + int index1 = + items.indexWhere((item) => item.param == param1); + try { + final contributeCtr = + Get.find(tag: widget.heroTag); + // contributeCtr.tabController?.animateTo(index1); + if (contributeCtr.tabController?.index != index1) { + contributeCtr.tabController?.index = index1; + } + debugPrint('initialized'); + } catch (e) { + _ctr.contributeInitialIndex.value = index1; + debugPrint('not initialized'); + } + } + _ctr.tabController?.animateTo(index); + } else { + if (param == 'coinArchive') { + Get.to(MemberCoinPage( + mid: _ctr.mid, + name: _ctr.username, + )); + return; + } + + if (param == 'likeArchive') { + Get.to(MemberLikePage( + mid: _ctr.mid, + name: _ctr.username, + )); + return; + } + + // else TODO + SmartDialog.showToast('view $param'); + } + }, + child: Text.rich( TextSpan( children: [ - TextSpan(text: '$title '), TextSpan( - text: count.toString(), - style: TextStyle( - fontSize: 13, - color: Theme.of(context).colorScheme.outline, + text: '查看更多', + style: TextStyle(color: color), + ), + WidgetSpan( + alignment: PlaceholderAlignment.top, + child: Icon( + Icons.arrow_forward_ios, + size: 14, + color: color, ), + style: TextStyle(fontSize: 13, color: color), ), ], ), ), - GestureDetector( - onTap: () { - int index = - _ctr.tab2!.indexWhere((item) => item.param == param); - if (index != -1) { - if (['video', 'article', 'audio'].contains(param1)) { - List items = _ctr.tab2! - .firstWhere((item) => item.param == param) - .items!; - int index1 = - items.indexWhere((item) => item.param == param1); - try { - final contributeCtr = - Get.find(tag: widget.heroTag); - // contributeCtr.tabController?.animateTo(index1); - if (contributeCtr.tabController?.index != index1) { - contributeCtr.tabController?.index = index1; - } - debugPrint('initialized'); - } catch (e) { - _ctr.contributeInitialIndex.value = index1; - debugPrint('not initialized'); - } - } - _ctr.tabController?.animateTo(index); - } else { - if (param == 'coinArchive') { - Get.to(MemberCoinPage( - mid: _ctr.mid, - name: _ctr.username, - )); - return; - } - - if (param == 'likeArchive') { - Get.to(MemberLikePage( - mid: _ctr.mid, - name: _ctr.username, - )); - return; - } - - // else TODO - SmartDialog.showToast('view $param'); - } - }, - child: Text.rich( - TextSpan( - children: [ - TextSpan( - text: '查看更多', - style: TextStyle( - color: Theme.of(context).colorScheme.outline, - ), - ), - WidgetSpan( - alignment: PlaceholderAlignment.top, - child: Icon( - Icons.arrow_forward_ios, - size: 14, - color: Theme.of(context).colorScheme.outline, - ), - style: TextStyle( - fontSize: 13, - color: Theme.of(context).colorScheme.outline, - ), - ), - ], - ), - ), - ), - ], - ), + ), + ], ), - ); + ), + ); + } } diff --git a/lib/pages/member/content/member_home/widget/fav_item.dart b/lib/pages/member/content/member_home/widget/fav_item.dart index d75ada1b..34afdf33 100644 --- a/lib/pages/member/content/member_home/widget/fav_item.dart +++ b/lib/pages/member/content/member_home/widget/fav_item.dart @@ -28,7 +28,6 @@ class MemberFavItem extends StatelessWidget { }, onLongPress: () { imageSaveDialog( - context: context, title: item['title'], cover: item['cover'], ); diff --git a/lib/pages/member/member_page.dart b/lib/pages/member/member_page.dart index f7277f4f..7ed2c0dd 100644 --- a/lib/pages/member/member_page.dart +++ b/lib/pages/member/member_page.dart @@ -60,6 +60,7 @@ class _MemberPageNewState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( extendBody: true, extendBodyBehindAppBar: true, @@ -149,13 +150,12 @@ class _MemberPageNewState extends State { Icon( Icons.error_outline, size: 19, - color: Theme.of(context).colorScheme.error, + color: theme.colorScheme.error, ), const SizedBox(width: 10), Text( '举报', - style: TextStyle( - color: Theme.of(context).colorScheme.error), + style: TextStyle(color: theme.colorScheme.error), ), ], ), @@ -192,7 +192,7 @@ class _MemberPageNewState extends State { child: Column( children: [ if ((_userController.tab2?.length ?? 0) > 1) - _buildTab, + _buildTab(theme), Expanded(child: _buildBody), ], ), @@ -208,8 +208,8 @@ class _MemberPageNewState extends State { ); } - Widget get _buildTab => Material( - color: Theme.of(context).colorScheme.surface, + Widget _buildTab(ThemeData theme) => Material( + color: theme.colorScheme.surface, child: TabBar( controller: _userController.tabController, tabs: _userController.tabs, @@ -316,6 +316,7 @@ class _ReportPanelState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, @@ -364,8 +365,7 @@ class _ReportPanelState extends State { onPressed: Get.back, child: Text( '取消', - style: - TextStyle(color: Theme.of(context).colorScheme.outline), + style: TextStyle(color: theme.colorScheme.outline), ), ), TextButton( diff --git a/lib/pages/member/widget/edit_profile_page.dart b/lib/pages/member/widget/edit_profile_page.dart index bf4fd23b..6303c905 100644 --- a/lib/pages/member/widget/edit_profile_page.dart +++ b/lib/pages/member/widget/edit_profile_page.dart @@ -47,9 +47,10 @@ class _EditProfilePageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: AppBar(title: const Text('账号资料')), - body: _buildBody(_loadingState), + body: _buildBody(theme, _loadingState), ); } @@ -77,23 +78,24 @@ class _EditProfilePageState extends State { }); } - Widget get _divider => Divider( - height: 1, - color: Theme.of(context).dividerColor.withOpacity(0.1), - ); + Widget _buildBody(ThemeData theme, LoadingState loadingState) { + late final divider = Divider( + height: 1, + color: theme.dividerColor.withOpacity(0.1), + ); - Widget get _divider1 => Divider( - thickness: 16, - color: Theme.of(context).dividerColor.withOpacity(0.1), - ); + late final divider1 = Divider( + thickness: 16, + color: theme.dividerColor.withOpacity(0.1), + ); - Widget _buildBody(LoadingState loadingState) { return switch (loadingState) { Loading() => loadingWidget, Success() => SingleChildScrollView( child: Column( children: [ _item( + theme: theme, title: '头像', widget: Padding( padding: const EdgeInsets.symmetric(vertical: 5), @@ -108,12 +110,13 @@ class _EditProfilePageState extends State { EasyThrottle.throttle( 'imagePicker', const Duration(milliseconds: 500), () async { - _pickImg(); + _pickImg(theme); }); }, ), - _divider, + divider, _item( + theme: theme, title: '昵称', text: loadingState.response['name'], onTap: () { @@ -128,8 +131,9 @@ class _EditProfilePageState extends State { } }, ), - _divider, + divider, _item( + theme: theme, title: '性别', text: _sex(loadingState.response['sex']), onTap: () { @@ -140,8 +144,9 @@ class _EditProfilePageState extends State { ); }, ), - _divider, + divider, _item( + theme: theme, title: '出生年月', text: loadingState.response['birthday'], onTap: () { @@ -161,8 +166,9 @@ class _EditProfilePageState extends State { }); }, ), - _divider, + divider, _item( + theme: theme, title: '个性签名', text: loadingState.response['sign'].isEmpty ? '无' @@ -175,27 +181,30 @@ class _EditProfilePageState extends State { ); }, ), - _divider1, + divider1, _item( + theme: theme, title: '头像挂件', onTap: () => PageUtils.launchURL( 'https://www.bilibili.com/h5/mall/pendant/home'), ), - _divider1, + divider1, _item( + theme: theme, title: 'UID', needIcon: false, text: loadingState.response['mid'].toString(), onTap: () => Utils.copyText(loadingState.response['mid'].toString()), ), - _divider1, + divider1, _item( + theme: theme, title: '哔哩哔哩认证', onTap: () => PageUtils.launchURL( 'https://account.bilibili.com/official/mobile/home'), ), - _divider, + divider, SizedBox(height: 25 + MediaQuery.paddingOf(context).bottom), ], ), @@ -254,6 +263,7 @@ class _EditProfilePageState extends State { showDialog( context: context, builder: (BuildContext context) { + final theme = Theme.of(context); return AlertDialog( title: Text('修改$title'), content: TextField( @@ -272,7 +282,7 @@ class _EditProfilePageState extends State { hintText: text, hintStyle: TextStyle( fontSize: 14, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -281,7 +291,7 @@ class _EditProfilePageState extends State { onPressed: Get.back, child: Text( '取消', - style: TextStyle(color: Theme.of(context).colorScheme.outline), + style: TextStyle(color: theme.colorScheme.outline), ), ), TextButton( @@ -372,6 +382,7 @@ class _EditProfilePageState extends State { } Widget _item({ + required ThemeData theme, required String title, Widget? widget, String? text, @@ -399,7 +410,7 @@ class _EditProfilePageState extends State { style: TextStyle( fontSize: 14, fontWeight: FontWeight.normal, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ) else if (widget != null) @@ -407,14 +418,14 @@ class _EditProfilePageState extends State { if (needIcon) Icon( Icons.keyboard_arrow_right, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ) ], ), ); } - void _pickImg() async { + void _pickImg(ThemeData theme) async { try { XFile? pickedFile = await _imagePicker.pickImage( source: ImageSource.gallery, @@ -432,9 +443,8 @@ class _EditProfilePageState extends State { uiSettings: [ AndroidUiSettings( toolbarTitle: '裁剪', - toolbarColor: Theme.of(context).colorScheme.secondaryContainer, - toolbarWidgetColor: - Theme.of(context).colorScheme.onSecondaryContainer, + toolbarColor: theme.colorScheme.secondaryContainer, + toolbarWidgetColor: theme.colorScheme.onSecondaryContainer, aspectRatioPresets: [ CropAspectRatioPresetCustom(), ], diff --git a/lib/pages/member/widget/user_info_card.dart b/lib/pages/member/widget/user_info_card.dart index 3896edad..a748074e 100644 --- a/lib/pages/member/widget/user_info_card.dart +++ b/lib/pages/member/widget/user_info_card.dart @@ -38,10 +38,12 @@ class UserInfoCard extends StatelessWidget { @override Widget build(BuildContext context) { - return isV ? _buildV(context) : _buildH(context); + final theme = Theme.of(context); + return isV ? _buildV(context, theme) : _buildH(context, theme); } Widget _countWidget({ + required ThemeData theme, required String title, required int count, required VoidCallback onTap, @@ -62,7 +64,7 @@ class UserInfoCard extends StatelessWidget { style: TextStyle( height: 1, fontSize: 11, - color: Theme.of(Get.context!).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ], @@ -70,8 +72,8 @@ class UserInfoCard extends StatelessWidget { ); } - _buildHeader(BuildContext context) { - bool darken = Theme.of(context).brightness == Brightness.dark; + _buildHeader(BuildContext context, ThemeData theme) { + bool darken = theme.brightness == Brightness.dark; String imgUrl = (darken ? images.nightImgurl?.isEmpty == true ? images.imgUrl @@ -107,7 +109,7 @@ class UserInfoCard extends StatelessWidget { ); } - _buildLeft(BuildContext context) => [ + _buildLeft(BuildContext context, ThemeData theme) => [ Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Wrap( @@ -181,7 +183,7 @@ class UserInfoCard extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2), decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(12)), - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, ), child: Text.rich( TextSpan( @@ -192,7 +194,7 @@ class UserInfoCard extends StatelessWidget { child: DecoratedBox( decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, ), child: Icon( Icons.offline_bolt, @@ -212,10 +214,7 @@ class UserInfoCard extends StatelessWidget { style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(0.7), + color: theme.colorScheme.onSurface.withOpacity(0.7), ), ) ], @@ -245,7 +244,7 @@ class UserInfoCard extends StatelessWidget { 'UID: ${card.mid}', style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -255,7 +254,7 @@ class UserInfoCard extends StatelessWidget { item.title ?? '', style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -264,14 +263,14 @@ class UserInfoCard extends StatelessWidget { ), if (silence == 1) Builder(builder: (context) { - bool isLight = Theme.of(context).brightness == Brightness.light; + bool isLight = theme.brightness == Brightness.light; return Container( width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(6), color: isLight - ? Theme.of(context).colorScheme.errorContainer - : Theme.of(context).colorScheme.error, + ? theme.colorScheme.errorContainer + : theme.colorScheme.error, ), margin: const EdgeInsets.only(left: 20, top: 8, right: 20), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), @@ -284,16 +283,16 @@ class UserInfoCard extends StatelessWidget { Icons.info, size: 17, color: isLight - ? Theme.of(context).colorScheme.onErrorContainer - : Theme.of(context).colorScheme.onError, + ? theme.colorScheme.onErrorContainer + : theme.colorScheme.onError, ), ), TextSpan( text: ' 该账号封禁中${endTime ?? ''}', style: TextStyle( color: isLight - ? Theme.of(context).colorScheme.onErrorContainer - : Theme.of(context).colorScheme.onError, + ? theme.colorScheme.onErrorContainer + : theme.colorScheme.onError, ), ), ], @@ -303,7 +302,7 @@ class UserInfoCard extends StatelessWidget { }), ]; - _buildRight(BuildContext context) => Column( + _buildRight(BuildContext context, ThemeData theme) => Column( mainAxisSize: MainAxisSize.min, children: [ Row( @@ -312,6 +311,7 @@ class UserInfoCard extends StatelessWidget { 5, (index) => index % 2 == 0 ? _countWidget( + theme: theme, title: ['粉丝', '关注', '获赞'][index ~/ 2], count: index == 0 ? card.fans @@ -358,10 +358,7 @@ class UserInfoCard extends StatelessWidget { style: IconButton.styleFrom( side: BorderSide( width: 1.0, - color: Theme.of(context) - .colorScheme - .outline - .withOpacity(0.5), + color: theme.colorScheme.outline.withOpacity(0.5), ), padding: EdgeInsets.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, @@ -378,7 +375,7 @@ class UserInfoCard extends StatelessWidget { onPressed: onFollow, style: FilledButton.styleFrom( backgroundColor: relation != 0 - ? Theme.of(context).colorScheme.onInverseSurface + ? theme.colorScheme.onInverseSurface : null, visualDensity: const VisualDensity( horizontal: -2, @@ -387,9 +384,7 @@ class UserInfoCard extends StatelessWidget { ), child: Text.rich( style: TextStyle( - color: relation != 0 - ? Theme.of(context).colorScheme.outline - : null, + color: relation != 0 ? theme.colorScheme.outline : null, ), TextSpan( children: [ @@ -399,7 +394,7 @@ class UserInfoCard extends StatelessWidget { child: Icon( Icons.sort, size: 16, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), TextSpan( @@ -440,7 +435,7 @@ class UserInfoCard extends StatelessWidget { .imageView(imgList: [SourceModel(url: card.face.http2https)]), )); - _buildV(BuildContext context) => Column( + _buildV(BuildContext context, ThemeData theme) => Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, @@ -450,7 +445,7 @@ class UserInfoCard extends StatelessWidget { Column( mainAxisSize: MainAxisSize.min, children: [ - _buildHeader(context), + _buildHeader(context, theme), const SizedBox(width: double.infinity, height: 85) ], ), @@ -468,21 +463,21 @@ class UserInfoCard extends StatelessWidget { builder: (_, constraints) => FittedBox( child: SizedBox( width: constraints.maxWidth, - child: _buildRight(context), + child: _buildRight(context, theme), ), ), ), ), ], ), - ..._buildLeft(context), - if (card.prInfo?.content?.isNotEmpty == true) buildPrInfo, + ..._buildLeft(context, theme), + if (card.prInfo?.content?.isNotEmpty == true) buildPrInfo(theme), const SizedBox(height: 5), ], ); - Widget get buildPrInfo => Builder(builder: (context) { - final isDark = Theme.of(context).brightness == Brightness.dark; + Widget buildPrInfo(ThemeData theme) => Builder(builder: (context) { + final isDark = theme.brightness == Brightness.dark; final textColor = isDark ? Color(int.parse('FF${card.prInfo?.textColorNight?.substring(1)}', radix: 16)) @@ -537,7 +532,7 @@ class UserInfoCard extends StatelessWidget { ); }); - _buildH(BuildContext context) => Column( + _buildH(BuildContext context, ThemeData theme) => Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, @@ -565,16 +560,16 @@ class UserInfoCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 10), - ..._buildLeft(context), + ..._buildLeft(context, theme), const SizedBox(height: 5), ], ), ), - Expanded(child: _buildRight(context)), + Expanded(child: _buildRight(context, theme)), ], ), ), - if (card.prInfo?.content?.isNotEmpty == true) buildPrInfo, + if (card.prInfo?.content?.isNotEmpty == true) buildPrInfo(theme), ], ); } diff --git a/lib/pages/member_coin/widgets/item.dart b/lib/pages/member_coin/widgets/item.dart index 3555b188..eb7d695e 100644 --- a/lib/pages/member_coin/widgets/item.dart +++ b/lib/pages/member_coin/widgets/item.dart @@ -35,7 +35,6 @@ class MemberCoinsItem extends StatelessWidget { ); }, onLongPress: () => imageSaveDialog( - context: context, title: coinItem.title, cover: coinItem.pic, ), diff --git a/lib/pages/mine/controller.dart b/lib/pages/mine/controller.dart index 2d0732a1..cb98e0b6 100644 --- a/lib/pages/mine/controller.dart +++ b/lib/pages/mine/controller.dart @@ -93,8 +93,9 @@ class MineController extends GetxController { displayTime: const Duration(seconds: 2), alignment: Alignment.bottomCenter, builder: (context) { + final theme = Theme.of(context); return ColoredBox( - color: Theme.of(context).colorScheme.primaryContainer, + color: theme.colorScheme.primaryContainer, child: Padding( padding: EdgeInsets.only( top: 15, @@ -111,8 +112,7 @@ class MineController extends GetxController { MdiIcons.incognito, ), const SizedBox(width: 10), - Text('已进入无痕模式', - style: Theme.of(context).textTheme.titleMedium) + Text('已进入无痕模式', style: theme.textTheme.titleMedium) ], ), const SizedBox(height: 10), @@ -121,7 +121,7 @@ class MineController extends GetxController { '不产生查询或播放记录\n' '点赞等其它操作不受影响\n' '(前往隐私设置了解详情)', - style: Theme.of(context).textTheme.bodySmall), + style: theme.textTheme.bodySmall), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ @@ -133,7 +133,7 @@ class MineController extends GetxController { child: Text( '保存为永久', style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), )), const SizedBox(width: 10), @@ -145,7 +145,7 @@ class MineController extends GetxController { child: Text( '仅本次(默认)', style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ), @@ -169,8 +169,9 @@ class MineController extends GetxController { displayTime: const Duration(seconds: 1), alignment: Alignment.bottomCenter, builder: (context) { + final theme = Theme.of(context); return ColoredBox( - color: Theme.of(context).colorScheme.secondaryContainer, + color: theme.colorScheme.secondaryContainer, child: Padding( padding: EdgeInsets.only( top: 15, @@ -185,8 +186,7 @@ class MineController extends GetxController { MdiIcons.incognitoOff, ), const SizedBox(width: 10), - Text('已退出无痕模式', - style: Theme.of(context).textTheme.titleMedium), + Text('已退出无痕模式', style: theme.textTheme.titleMedium), ], ), ), diff --git a/lib/pages/mine/view.dart b/lib/pages/mine/view.dart index c67adcbb..260f8cdc 100644 --- a/lib/pages/mine/view.dart +++ b/lib/pages/mine/view.dart @@ -18,7 +18,7 @@ class _MinePageState extends State { final MineController _mineController = Get.put(MineController()) ..queryUserInfo(); - Widget get _header => FittedBox( + Widget _header(ThemeData theme) => FittedBox( child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -31,7 +31,7 @@ class _MinePageState extends State { const SizedBox(width: 5), Text( 'PiliPlus', - style: Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, ), const SizedBox(width: 30), IconButton( @@ -92,24 +92,25 @@ class _MinePageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return IntrinsicWidth( child: Column( mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 8), - _header, + _header(theme), const SizedBox(height: 10), - Obx(userInfoBuild), + Obx(() => userInfoBuild(theme)), ], ), ); } - Widget userInfoBuild() { + Widget userInfoBuild(ThemeData theme) { LevelInfo? levelInfo = _mineController.userInfo.value.levelInfo; TextStyle style = TextStyle( - fontSize: Theme.of(context).textTheme.titleMedium!.fontSize, - color: Theme.of(context).colorScheme.primary, + fontSize: theme.textTheme.titleMedium!.fontSize, + color: theme.colorScheme.primary, fontWeight: FontWeight.bold, ); return Column( @@ -137,7 +138,7 @@ class _MinePageState extends State { alignment: Alignment.center, decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, ), child: Image.asset( 'assets/images/noface.jpeg', @@ -158,9 +159,7 @@ class _MinePageState extends State { children: [ Text( _mineController.userInfo.value.uname ?? '点击头像登录', - style: Theme.of(context) - .textTheme - .titleMedium! + style: theme.textTheme.titleMedium! .copyWith(height: 1), ), const SizedBox(width: 4), @@ -181,11 +180,8 @@ class _MinePageState extends State { TextSpan( text: '硬币 ', style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline, ), ), TextSpan( @@ -193,22 +189,16 @@ class _MinePageState extends State { (_mineController.userInfo.value.money ?? '-') .toString(), style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, + fontSize: theme.textTheme.labelSmall!.fontSize, fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), TextSpan( text: " 经验 ", style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline, ), ), TextSpan( @@ -216,23 +206,17 @@ class _MinePageState extends State { semanticsLabel: "当前${levelInfo?.currentExp ?? '-'}", style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, + fontSize: theme.textTheme.labelSmall!.fontSize, fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), TextSpan( text: "/${levelInfo?.nextExp ?? '-'}", semanticsLabel: "升级需${levelInfo?.nextExp ?? '-'}", style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline, ), ), ], @@ -247,10 +231,9 @@ class _MinePageState extends State { value: levelInfo != null ? (levelInfo.currentExp! / levelInfo.nextExp!) : 0, - backgroundColor: - Theme.of(context).colorScheme.inversePrimary, + backgroundColor: theme.colorScheme.inversePrimary, valueColor: AlwaysStoppedAnimation( - Theme.of(context).colorScheme.primary), + theme.colorScheme.primary), ), ), ], @@ -286,7 +269,7 @@ class _MinePageState extends State { const SizedBox(height: 8), Text( '动态', - style: Theme.of(context).textTheme.labelMedium, + style: theme.textTheme.labelMedium, ), ], ), @@ -307,7 +290,7 @@ class _MinePageState extends State { const SizedBox(height: 8), Text( '关注', - style: Theme.of(context).textTheme.labelMedium, + style: theme.textTheme.labelMedium, ), ], ), @@ -329,7 +312,7 @@ class _MinePageState extends State { const SizedBox(height: 8), Text( '粉丝', - style: Theme.of(context).textTheme.labelMedium, + style: theme.textTheme.labelMedium, ), ], ), diff --git a/lib/pages/msg_feed_top/at_me/view.dart b/lib/pages/msg_feed_top/at_me/view.dart index 68d844d1..6caa1e66 100644 --- a/lib/pages/msg_feed_top/at_me/view.dart +++ b/lib/pages/msg_feed_top/at_me/view.dart @@ -24,6 +24,7 @@ class _AtMePageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: AppBar( title: const Text('@我的'), @@ -38,7 +39,8 @@ class _AtMePageState extends State { SliverPadding( padding: EdgeInsets.only( bottom: MediaQuery.paddingOf(context).bottom + 80), - sliver: Obx(() => _buildBody(_atMeController.loadingState.value)), + sliver: Obx( + () => _buildBody(theme, _atMeController.loadingState.value)), ), ], ), @@ -46,7 +48,8 @@ class _AtMePageState extends State { ); } - Widget _buildBody(LoadingState?> loadingState) { + Widget _buildBody( + ThemeData theme, LoadingState?> loadingState) { return switch (loadingState) { Loading() => SliverList.builder( itemCount: 12, @@ -94,21 +97,15 @@ class _AtMePageState extends State { children: [ TextSpan( text: "${item.user?.nickname}", - style: Theme.of(context) - .textTheme - .titleSmall! - .copyWith( - color: Theme.of(context).colorScheme.primary, - ), + style: theme.textTheme.titleSmall!.copyWith( + color: theme.colorScheme.primary, + ), ), TextSpan( text: " 在${item.item?.business}中@了我", - style: - Theme.of(context).textTheme.titleSmall!.copyWith( - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, - ), + style: theme.textTheme.titleSmall!.copyWith( + color: theme.colorScheme.onSurfaceVariant, + ), ), ], ), @@ -121,20 +118,16 @@ class _AtMePageState extends State { Text(item.item!.sourceContent!, maxLines: 3, overflow: TextOverflow.ellipsis, - style: Theme.of(context) - .textTheme - .bodyMedium! - .copyWith( - color: - Theme.of(context).colorScheme.outline)), + style: theme.textTheme.bodyMedium! + .copyWith(color: theme.colorScheme.outline)), ], const SizedBox(height: 4), Text( Utils.dateFormat(item.atTime), - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - fontSize: 13, - color: Theme.of(context).colorScheme.outline, - ), + style: theme.textTheme.bodyMedium!.copyWith( + fontSize: 13, + color: theme.colorScheme.outline, + ), ), ], ), diff --git a/lib/pages/msg_feed_top/like_me/view.dart b/lib/pages/msg_feed_top/like_me/view.dart index fa20a013..392c0d13 100644 --- a/lib/pages/msg_feed_top/like_me/view.dart +++ b/lib/pages/msg_feed_top/like_me/view.dart @@ -57,6 +57,7 @@ class _LikeMePageState extends State { }, ), Success() => () { + final theme = Theme.of(context); Pair, List> pair = loadingState.response; List latest = pair.first; @@ -65,13 +66,14 @@ class _LikeMePageState extends State { return SliverMainAxisGroup( slivers: [ if (latest.isNotEmpty) ...[ - _buildHeader('最新'), + _buildHeader(theme, '最新'), SliverList.separated( itemBuilder: (context, index) { if (total.isEmpty && index == latest.length - 1) { _likeMeController.onLoadMore(); } return _buildItem( + theme, latest[index], (id) { _likeMeController.onRemove(id, index, true); @@ -90,13 +92,14 @@ class _LikeMePageState extends State { ), ], if (total.isNotEmpty) ...[ - _buildHeader('累计'), + _buildHeader(theme, '累计'), SliverList.separated( itemBuilder: (context, index) { if (index == total.length - 1) { _likeMeController.onLoadMore(); } return _buildItem( + theme, total[index], (id) { _likeMeController.onRemove(id, index, false); @@ -126,7 +129,7 @@ class _LikeMePageState extends State { }; } - Widget _buildHeader(String title) { + Widget _buildHeader(ThemeData theme, String title) { return SliverSafeArea( top: false, bottom: false, @@ -135,16 +138,16 @@ class _LikeMePageState extends State { padding: const EdgeInsets.only(left: 16), child: Text( title, - style: Theme.of(context).textTheme.labelLarge!.copyWith( - color: Theme.of(context).colorScheme.secondary, - ), + style: theme.textTheme.labelLarge!.copyWith( + color: theme.colorScheme.secondary, + ), ), ), ), ); } - Widget _buildItem(LikeMeItems item, ValueChanged onRemove) { + Widget _buildItem(ThemeData theme, LikeMeItems item, ValueChanged onRemove) { return ListTile( onTap: () { String? nativeUri = item.item?.nativeUri; @@ -193,23 +196,21 @@ class _LikeMePageState extends State { children: [ TextSpan( text: "${item.users![0].nickname}", - style: Theme.of(context).textTheme.titleSmall!.copyWith( - height: 1.5, color: Theme.of(context).colorScheme.primary), + style: theme.textTheme.titleSmall! + .copyWith(height: 1.5, color: theme.colorScheme.primary), ), if (item.counts! > 1) TextSpan( text: ' 等${item.counts}人', - style: Theme.of(context) - .textTheme - .titleSmall! + style: theme.textTheme.titleSmall! .copyWith(fontSize: 12, height: 1.5), ), TextSpan( text: " 赞了我的${item.item?.business}", - style: Theme.of(context).textTheme.titleSmall!.copyWith( - height: 1.5, - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), + style: theme.textTheme.titleSmall!.copyWith( + height: 1.5, + color: theme.colorScheme.onSurfaceVariant, + ), ), ], ), @@ -224,16 +225,16 @@ class _LikeMePageState extends State { Text(item.item!.title!, maxLines: 3, overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - color: Theme.of(context).colorScheme.outline, height: 1.5)), + style: theme.textTheme.bodyMedium! + .copyWith(color: theme.colorScheme.outline, height: 1.5)), ], const SizedBox(height: 4), Text( Utils.dateFormat(item.likeTime), - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - fontSize: 13, - color: Theme.of(context).colorScheme.outline, - ), + style: theme.textTheme.bodyMedium!.copyWith( + fontSize: 13, + color: theme.colorScheme.outline, + ), ), ], ), diff --git a/lib/pages/msg_feed_top/reply_me/view.dart b/lib/pages/msg_feed_top/reply_me/view.dart index 552e89e2..d8ed53dc 100644 --- a/lib/pages/msg_feed_top/reply_me/view.dart +++ b/lib/pages/msg_feed_top/reply_me/view.dart @@ -24,6 +24,7 @@ class _ReplyMePageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: AppBar(title: const Text('回复我的')), body: refreshIndicator( @@ -36,8 +37,8 @@ class _ReplyMePageState extends State { SliverPadding( padding: EdgeInsets.only( bottom: MediaQuery.paddingOf(context).bottom + 80), - sliver: - Obx(() => _buildBody(_replyMeController.loadingState.value)), + sliver: Obx(() => + _buildBody(theme, _replyMeController.loadingState.value)), ), ], ), @@ -45,7 +46,8 @@ class _ReplyMePageState extends State { ); } - Widget _buildBody(LoadingState?> loadingState) { + Widget _buildBody( + ThemeData theme, LoadingState?> loadingState) { return switch (loadingState) { Loading() => SliverList.builder( itemCount: 12, @@ -98,30 +100,20 @@ class _ReplyMePageState extends State { children: [ TextSpan( text: "${item.user?.nickname}", - style: Theme.of(context) - .textTheme - .titleSmall! - .copyWith( - color: Theme.of(context).colorScheme.primary), + style: theme.textTheme.titleSmall! + .copyWith(color: theme.colorScheme.primary), ), if (item.isMulti == 1) TextSpan( text: " 等人", - style: Theme.of(context) - .textTheme - .titleSmall! + style: theme.textTheme.titleSmall! .copyWith(fontSize: 12), ), TextSpan( text: " 对我的${item.item?.business}发布了${item.counts}条评论", - style: Theme.of(context) - .textTheme - .titleSmall! - .copyWith( - color: Theme.of(context) - .colorScheme - .onSurfaceVariant), + style: theme.textTheme.titleSmall!.copyWith( + color: theme.colorScheme.onSurfaceVariant), ), ], ), @@ -132,38 +124,28 @@ class _ReplyMePageState extends State { children: [ const SizedBox(height: 4), Text(item.item?.sourceContent ?? "", - style: Theme.of(context).textTheme.bodyMedium), + style: theme.textTheme.bodyMedium), const SizedBox(height: 4), if (item.item?.targetReplyContent != null && item.item?.targetReplyContent != "") Text("| ${item.item?.targetReplyContent}", maxLines: 1, overflow: TextOverflow.ellipsis, - style: Theme.of(context) - .textTheme - .labelMedium! - .copyWith( - color: - Theme.of(context).colorScheme.outline, - height: 1.5)), + style: theme.textTheme.labelMedium!.copyWith( + color: theme.colorScheme.outline, height: 1.5)), if (item.item?.rootReplyContent != null && item.item?.rootReplyContent != "") Text(" | ${item.item?.rootReplyContent}", maxLines: 1, overflow: TextOverflow.ellipsis, - style: Theme.of(context) - .textTheme - .labelMedium! - .copyWith( - color: - Theme.of(context).colorScheme.outline, - height: 1.5)), + style: theme.textTheme.labelMedium!.copyWith( + color: theme.colorScheme.outline, height: 1.5)), Text( Utils.dateFormat(item.replyTime), - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - fontSize: 13, - color: Theme.of(context).colorScheme.outline, - ), + style: theme.textTheme.bodyMedium!.copyWith( + fontSize: 13, + color: theme.colorScheme.outline, + ), ), ], ), diff --git a/lib/pages/msg_feed_top/sys_msg/view.dart b/lib/pages/msg_feed_top/sys_msg/view.dart index 049c2b2c..c5024d52 100644 --- a/lib/pages/msg_feed_top/sys_msg/view.dart +++ b/lib/pages/msg_feed_top/sys_msg/view.dart @@ -29,6 +29,7 @@ class _SysMsgPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: AppBar( title: const Text('系统通知'), @@ -43,8 +44,8 @@ class _SysMsgPageState extends State { SliverPadding( padding: EdgeInsets.only( bottom: MediaQuery.paddingOf(context).bottom + 80), - sliver: - Obx(() => _buildBody(_sysMsgController.loadingState.value)), + sliver: Obx(() => + _buildBody(theme, _sysMsgController.loadingState.value)), ), ], ), @@ -52,7 +53,8 @@ class _SysMsgPageState extends State { ); } - Widget _buildBody(LoadingState?> loadingState) { + Widget _buildBody( + ThemeData theme, LoadingState?> loadingState) { return switch (loadingState) { Loading() => SliverSafeArea( sliver: SliverList.builder( @@ -92,20 +94,17 @@ class _SysMsgPageState extends State { }, title: Text( "${item.title}", - style: Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 4), Text.rich( - _buildContent(content ?? ''), + _buildContent(theme, content ?? ''), style: TextStyle( fontSize: 14, - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(0.85), + color: theme.colorScheme.onSurface.withOpacity(0.85), ), ), const SizedBox(height: 5), @@ -115,13 +114,10 @@ class _SysMsgPageState extends State { "${item.timeAt}", maxLines: 1, overflow: TextOverflow.ellipsis, - style: Theme.of(context) - .textTheme - .bodyMedium! - .copyWith( - fontSize: 13, - color: Theme.of(context).colorScheme.outline, - ), + style: theme.textTheme.bodyMedium!.copyWith( + fontSize: 13, + color: theme.colorScheme.outline, + ), textAlign: TextAlign.end, ), ), @@ -146,7 +142,7 @@ class _SysMsgPageState extends State { }; } - InlineSpan _buildContent(String content) { + InlineSpan _buildContent(ThemeData theme, String content) { final List spanChildren = []; RegExp urlRegExp = RegExp( r'#\{([^}]*)\}\{([^}]*)\}|https?:\/\/[^\s/\$.?#].[^\s]*|www\.[^\s/\$.?#].[^\s]*|【(.*?)】|((\d+))'); @@ -158,7 +154,7 @@ class _SysMsgPageState extends State { spanChildren.add( TextSpan( text: match[1], - style: TextStyle(color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), recognizer: TapGestureRecognizer() ..onTap = () { try { @@ -181,7 +177,7 @@ class _SysMsgPageState extends State { spanChildren.add( TextSpan( text: match[3], - style: TextStyle(color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), recognizer: TapGestureRecognizer() ..onTap = () { try { @@ -206,7 +202,7 @@ class _SysMsgPageState extends State { spanChildren.add( TextSpan( text: '查看动态', - style: TextStyle(color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), recognizer: TapGestureRecognizer() ..onTap = () { try { @@ -225,7 +221,7 @@ class _SysMsgPageState extends State { spanChildren.add( TextSpan( text: '\u{1F517}网页链接', - style: TextStyle(color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), recognizer: TapGestureRecognizer() ..onTap = () { try { diff --git a/lib/pages/rank/view.dart b/lib/pages/rank/view.dart index fa278f2d..5bd70f52 100644 --- a/lib/pages/rank/view.dart +++ b/lib/pages/rank/view.dart @@ -20,6 +20,7 @@ class _RankPageState extends State @override Widget build(BuildContext context) { + final theme = Theme.of(context); super.build(context); return Row( children: [ @@ -45,8 +46,8 @@ class _RankPageState extends State }, child: ColoredBox( color: index == _rankController.tabIndex.value - ? Theme.of(context).colorScheme.onInverseSurface - : Theme.of(context).colorScheme.surface, + ? theme.colorScheme.onInverseSurface + : theme.colorScheme.surface, child: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -54,7 +55,7 @@ class _RankPageState extends State height: double.infinity, width: 3, color: index == _rankController.tabIndex.value - ? Theme.of(context).colorScheme.primary + ? theme.colorScheme.primary : Colors.transparent, ), Expanded( @@ -66,12 +67,10 @@ class _RankPageState extends State child: Text( tabsConfig[index]['label'], style: TextStyle( - color: index == - _rankController.tabIndex.value - ? Theme.of(context).colorScheme.primary - : Theme.of(context) - .colorScheme - .onSurface, + color: + index == _rankController.tabIndex.value + ? theme.colorScheme.primary + : theme.colorScheme.onSurface, fontSize: 15, ), maxLines: 1, diff --git a/lib/pages/rank/zone/widget/pgc_rank_item.dart b/lib/pages/rank/zone/widget/pgc_rank_item.dart index 799fb428..a5a9064c 100644 --- a/lib/pages/rank/zone/widget/pgc_rank_item.dart +++ b/lib/pages/rank/zone/widget/pgc_rank_item.dart @@ -23,7 +23,6 @@ class PgcRankItem extends StatelessWidget { }, onLongPress: () { imageSaveDialog( - context: context, title: item.title, cover: item.cover, ); diff --git a/lib/pages/search/view.dart b/lib/pages/search/view.dart index 83d8b33d..60a9204d 100644 --- a/lib/pages/search/view.dart +++ b/lib/pages/search/view.dart @@ -27,12 +27,13 @@ class _SearchPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( resizeToAvoidBottomInset: true, appBar: AppBar( shape: Border( bottom: BorderSide( - color: Theme.of(context).dividerColor.withOpacity(0.08), + color: theme.dividerColor.withOpacity(0.08), width: 1, ), ), @@ -81,9 +82,9 @@ class _SearchPageState extends State { // 搜索建议 if (_searchController.searchSuggestion) _searchSuggest(), if (context.orientation == Orientation.portrait) ...[ - if (_searchController.enableHotKey) hotSearch(), - if (_searchController.recordSearchHistory.value) _history(), - if (_searchController.enableSearchRcmd) hotSearch(false) + if (_searchController.enableHotKey) hotSearch(theme), + if (_searchController.recordSearchHistory.value) _history(theme), + if (_searchController.enableSearchRcmd) hotSearch(theme, false) ] else Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -93,14 +94,14 @@ class _SearchPageState extends State { Expanded( child: Column( children: [ - if (_searchController.enableHotKey) hotSearch(), + if (_searchController.enableHotKey) hotSearch(theme), if (_searchController.enableSearchRcmd) - hotSearch(false) + hotSearch(theme, false) ], ), ), if (_searchController.recordSearchHistory.value) - Expanded(child: _history()), + Expanded(child: _history(theme)), ], ), ], @@ -141,13 +142,11 @@ class _SearchPageState extends State { ); } - Widget hotSearch([bool isHot = true]) { + Widget hotSearch(ThemeData theme, [bool isHot = true]) { final text = Text( isHot ? '大家都在搜' : '搜索发现', strutStyle: const StrutStyle(leading: 0, height: 1), - style: Theme.of(context) - .textTheme - .titleMedium! + style: theme.textTheme.titleMedium! .copyWith(height: 1, fontWeight: FontWeight.bold), ); return Padding( @@ -180,14 +179,13 @@ class _SearchPageState extends State { '完整榜单', style: TextStyle( fontSize: 13, - color: - Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), icon: Icon( size: 16, Icons.keyboard_arrow_right, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), iconAlignment: IconAlignment.end, ), @@ -209,12 +207,12 @@ class _SearchPageState extends State { icon: Icon( Icons.refresh_outlined, size: 18, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), label: Text( '刷新', style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), ), @@ -233,7 +231,7 @@ class _SearchPageState extends State { ); } - Widget _history() { + Widget _history(ThemeData theme) { return Obx( () => Padding( padding: EdgeInsets.fromLTRB( @@ -257,9 +255,7 @@ class _SearchPageState extends State { Text( '搜索历史', strutStyle: StrutStyle(leading: 0, height: 1), - style: Theme.of(context) - .textTheme - .titleMedium! + style: theme.textTheme.titleMedium! .copyWith(height: 1, fontWeight: FontWeight.bold), ), const SizedBox(width: 12), @@ -273,8 +269,8 @@ class _SearchPageState extends State { ? '记录搜索' : '无痕搜索', icon: _searchController.recordSearchHistory.value - ? historyIcon - : historyIcon.disable(), + ? historyIcon(theme) + : historyIcon(theme).disable(), style: IconButton.styleFrom( padding: EdgeInsets.zero, ), @@ -307,12 +303,12 @@ class _SearchPageState extends State { icon: Icon( Icons.clear_all_outlined, size: 18, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), label: Text( '清空', style: TextStyle( - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), ), @@ -343,8 +339,8 @@ class _SearchPageState extends State { ); } - Icon get historyIcon => Icon(Icons.history, - color: Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.8)); + Icon historyIcon(ThemeData theme) => Icon(Icons.history, + color: theme.colorScheme.onSurfaceVariant.withOpacity(0.8)); Widget _buildHotKey( LoadingState loadingState, bool isHot) { diff --git a/lib/pages/search/widgets/search_text.dart b/lib/pages/search/widgets/search_text.dart index 9ec0cdee..8decac7f 100644 --- a/lib/pages/search/widgets/search_text.dart +++ b/lib/pages/search/widgets/search_text.dart @@ -24,8 +24,9 @@ class SearchText extends StatelessWidget { @override Widget build(BuildContext context) { + late final theme = Theme.of(context); return Material( - color: bgColor ?? Theme.of(context).colorScheme.onInverseSurface, + color: bgColor ?? theme.colorScheme.onInverseSurface, borderRadius: BorderRadius.circular(6), child: InkWell( onTap: () { @@ -45,8 +46,7 @@ class SearchText extends StatelessWidget { textAlign: textAlign, style: TextStyle( fontSize: fontSize, - color: - textColor ?? Theme.of(context).colorScheme.onSurfaceVariant, + color: textColor ?? theme.colorScheme.onSurfaceVariant, ), ), ), diff --git a/lib/pages/search_panel/all/view.dart b/lib/pages/search_panel/all/view.dart index 0657b579..f3b727c0 100644 --- a/lib/pages/search_panel/all/view.dart +++ b/lib/pages/search_panel/all/view.dart @@ -17,7 +17,6 @@ class SearchAllPanel extends CommonSearchPanel { required super.keyword, required super.tag, required super.searchType, - super.hasHeader = false, }); @override @@ -36,22 +35,12 @@ class _SearchAllPanelState tag: widget.searchType.name + widget.tag, ); - late final TextStyle pgcStyle = TextStyle(fontSize: 13); - late TextStyle userStyle; - @override - void didChangeDependencies() { - super.didChangeDependencies(); - userStyle = TextStyle( - fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, - color: Theme.of(context).colorScheme.outline, - ); - } - - @override - Widget buildList(List list) { + Widget buildList(ThemeData theme, List list) { return SliverPadding( - padding: const EdgeInsets.only(bottom: 80), + padding: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom + 80, + ), sliver: SliverWaterfallFlow.extent( maxCrossAxisExtent: Grid.smallCardWidth * 2, crossAxisSpacing: StyleString.safeSpace, @@ -76,7 +65,7 @@ class _SearchAllPanelState List() => item.length == 1 ? SizedBox( height: 160, - child: SearchPgcItem(style: pgcStyle, item: item.first), + child: SearchPgcItem(item: item.first), ) : SizedBox( height: Grid.smallCardWidth / 2 / 0.75 + @@ -103,7 +92,6 @@ class _SearchAllPanelState SearchUserItemModel() => Padding( padding: const EdgeInsets.only(bottom: 5), child: SearchUserItem( - style: userStyle, item: item, ), ), diff --git a/lib/pages/search_panel/article/controller.dart b/lib/pages/search_panel/article/controller.dart index abdd5041..6d5f162b 100644 --- a/lib/pages/search_panel/article/controller.dart +++ b/lib/pages/search_panel/article/controller.dart @@ -69,83 +69,87 @@ class SearchArticleController constraints: BoxConstraints( maxWidth: min(640, min(Get.width, Get.height)), ), - builder: (context) => SingleChildScrollView( - child: Container( - width: double.infinity, - padding: EdgeInsets.only( - top: 20, - left: 16, - right: 16, - bottom: 80 + MediaQuery.of(context).padding.bottom, + builder: (context) { + final theme = Theme.of(context); + return SingleChildScrollView( + child: Container( + width: double.infinity, + padding: EdgeInsets.only( + top: 20, + left: 16, + right: 16, + bottom: 80 + MediaQuery.of(context).padding.bottom, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + const Text('排序', style: TextStyle(fontSize: 16)), + const SizedBox(height: 10), + Wrap( + spacing: 8, + runSpacing: 8, + children: orderFiltersList + .map( + (item) => SearchText( + text: item['label'], + onTap: (_) async { + Get.back(); + currentOrderFilterval.value = item['value']; + SmartDialog.dismiss(); + SmartDialog.showToast("「${item['label']}」的筛选结果"); + order.value = item['order']; + SmartDialog.showLoading(msg: 'loading'); + await onReload(); + SmartDialog.dismiss(); + }, + bgColor: item['value'] == currentOrderFilterval.value + ? theme.colorScheme.secondaryContainer + : null, + textColor: + item['value'] == currentOrderFilterval.value + ? theme.colorScheme.onSecondaryContainer + : null, + ), + ) + .toList(), + ), + const SizedBox(height: 20), + const Text('分区', style: TextStyle(fontSize: 16)), + const SizedBox(height: 10), + Wrap( + spacing: 8, + runSpacing: 8, + children: zoneFiltersList + .map( + (item) => SearchText( + text: item['label'], + onTap: (_) async { + Get.back(); + currentZoneFilterval.value = item['value']; + SmartDialog.dismiss(); + SmartDialog.showToast("「${item['label']}」的筛选结果"); + categoryId = item['categoryId']; + SmartDialog.showLoading(msg: 'loading'); + await onReload(); + SmartDialog.dismiss(); + }, + bgColor: item['value'] == currentZoneFilterval.value + ? theme.colorScheme.secondaryContainer + : null, + textColor: item['value'] == currentZoneFilterval.value + ? theme.colorScheme.onSecondaryContainer + : null, + ), + ) + .toList(), + ), + ], + ), ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 10), - const Text('排序', style: TextStyle(fontSize: 16)), - const SizedBox(height: 10), - Wrap( - spacing: 8, - runSpacing: 8, - children: orderFiltersList - .map( - (item) => SearchText( - text: item['label'], - onTap: (_) async { - Get.back(); - currentOrderFilterval.value = item['value']; - SmartDialog.dismiss(); - SmartDialog.showToast("「${item['label']}」的筛选结果"); - order.value = item['order']; - SmartDialog.showLoading(msg: 'loading'); - await onReload(); - SmartDialog.dismiss(); - }, - bgColor: item['value'] == currentOrderFilterval.value - ? Theme.of(context).colorScheme.secondaryContainer - : null, - textColor: item['value'] == currentOrderFilterval.value - ? Theme.of(context).colorScheme.onSecondaryContainer - : null, - ), - ) - .toList(), - ), - const SizedBox(height: 20), - const Text('分区', style: TextStyle(fontSize: 16)), - const SizedBox(height: 10), - Wrap( - spacing: 8, - runSpacing: 8, - children: zoneFiltersList - .map( - (item) => SearchText( - text: item['label'], - onTap: (_) async { - Get.back(); - currentZoneFilterval.value = item['value']; - SmartDialog.dismiss(); - SmartDialog.showToast("「${item['label']}」的筛选结果"); - categoryId = item['categoryId']; - SmartDialog.showLoading(msg: 'loading'); - await onReload(); - SmartDialog.dismiss(); - }, - bgColor: item['value'] == currentZoneFilterval.value - ? Theme.of(context).colorScheme.secondaryContainer - : null, - textColor: item['value'] == currentZoneFilterval.value - ? Theme.of(context).colorScheme.onSecondaryContainer - : null, - ), - ) - .toList(), - ), - ], - ), - ), - ), + ); + }, ); } } diff --git a/lib/pages/search_panel/article/view.dart b/lib/pages/search_panel/article/view.dart index a8cd8b7a..821c15ca 100644 --- a/lib/pages/search_panel/article/view.dart +++ b/lib/pages/search_panel/article/view.dart @@ -1,13 +1,9 @@ -import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart'; -import 'package:PiliPlus/common/widgets/image_save.dart'; -import 'package:PiliPlus/common/widgets/network_img_layer.dart'; -import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/search/result.dart'; import 'package:PiliPlus/pages/search_panel/article/controller.dart'; +import 'package:PiliPlus/pages/search_panel/article/widgets/item.dart'; import 'package:PiliPlus/pages/search_panel/view.dart'; import 'package:PiliPlus/utils/grid.dart'; -import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -17,7 +13,6 @@ class SearchArticlePanel extends CommonSearchPanel { required super.keyword, required super.tag, required super.searchType, - super.hasHeader = true, }); @override @@ -36,191 +31,78 @@ class _SearchArticlePanelState extends CommonSearchPanelState< tag: widget.searchType.name + widget.tag, ); - late TextStyle textStyle; - @override - void didChangeDependencies() { - super.didChangeDependencies(); - textStyle = TextStyle( - fontSize: Theme.of(context).textTheme.labelSmall!.fontSize, - color: Theme.of(context).colorScheme.outline, - ); - } - - @override - Widget buildHeader(LoadingState?> loadingState) { - if (loadingState is Success) { - return SliverPersistentHeader( - pinned: false, - floating: true, - delegate: CustomSliverPersistentHeaderDelegate( - extent: 40, - bgColor: Theme.of(context).colorScheme.surface, - child: Container( - height: 40, - padding: const EdgeInsets.only(left: 25, right: 12), - child: Row( - children: [ - Obx( - () => Text( - '排序: ${controller.orderFiltersList[controller.currentOrderFilterval.value]['label']}', - maxLines: 1, - style: - TextStyle(color: Theme.of(context).colorScheme.outline), - ), - ), - const Spacer(), - Obx( - () => Text( - '分区: ${controller.zoneFiltersList[controller.currentZoneFilterval.value]['label']}', - maxLines: 1, - style: - TextStyle(color: Theme.of(context).colorScheme.outline), - ), - ), - const Spacer(), - SizedBox( - width: 32, - height: 32, - child: IconButton( - tooltip: '筛选', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: () { - controller.onShowFilterDialog(context); - }, - icon: Icon( - Icons.filter_list_outlined, - size: 18, - color: Theme.of(context).colorScheme.primary, + Widget buildList(ThemeData theme, List list) { + return SliverMainAxisGroup( + slivers: [ + SliverPersistentHeader( + pinned: false, + floating: true, + delegate: CustomSliverPersistentHeaderDelegate( + extent: 40, + bgColor: theme.colorScheme.surface, + child: Container( + height: 40, + padding: const EdgeInsets.only(left: 25, right: 12), + child: Row( + children: [ + Obx( + () => Text( + '排序: ${controller.orderFiltersList[controller.currentOrderFilterval.value]['label']}', + maxLines: 1, + style: TextStyle(color: theme.colorScheme.outline), ), ), - ), - ], + const Spacer(), + Obx( + () => Text( + '分区: ${controller.zoneFiltersList[controller.currentZoneFilterval.value]['label']}', + maxLines: 1, + style: TextStyle(color: theme.colorScheme.outline), + ), + ), + const Spacer(), + SizedBox( + width: 32, + height: 32, + child: IconButton( + tooltip: '筛选', + style: ButtonStyle( + padding: WidgetStateProperty.all(EdgeInsets.zero), + ), + onPressed: () { + controller.onShowFilterDialog(context); + }, + icon: Icon( + Icons.filter_list_outlined, + size: 18, + color: theme.colorScheme.primary, + ), + ), + ), + ], + ), ), ), ), - ); - } - return const SliverToBoxAdapter(); - } - - late final TextStyle style = TextStyle(fontSize: 13); - - @override - Widget buildList(List list) { - return SliverPadding( - padding: const EdgeInsets.only(bottom: 80), - sliver: SliverGrid( - gridDelegate: Grid.videoCardHDelegate(context), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - if (index == list.length - 1) { - controller.onLoadMore(); - } - final item = list[index]; - return InkWell( - onTap: () { - Get.toNamed( - '/articlePage', - parameters: { - 'id': '${item.id}', - 'type': 'read', - }, - ); + SliverPadding( + padding: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom + 80, + ), + sliver: SliverGrid( + gridDelegate: Grid.videoCardHDelegate(context), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + if (index == list.length - 1) { + controller.onLoadMore(); + } + return SearchArticleItem(item: list[index]); }, - onLongPress: () => imageSaveDialog( - context: context, - title: item.title?.map((item) => item['text']).join() ?? '', - cover: item.imageUrls?.firstOrNull, - ), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: StyleString.safeSpace, - vertical: 5, - ), - child: LayoutBuilder( - builder: (context, boxConstraints) { - final double width = (boxConstraints.maxWidth - - StyleString.cardSpace * - 6 / - MediaQuery.textScalerOf(context).scale(1.0)) / - 2; - return Container( - constraints: const BoxConstraints(minHeight: 88), - height: width / StyleString.aspectRatio, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (item.imageUrls?.isNotEmpty == true) - AspectRatio( - aspectRatio: StyleString.aspectRatio, - child: LayoutBuilder( - builder: (context, boxConstraints) { - double maxWidth = boxConstraints.maxWidth; - double maxHeight = boxConstraints.maxHeight; - return NetworkImgLayer( - width: maxWidth, - height: maxHeight, - src: item.imageUrls?.firstOrNull, - ); - }), - ), - const SizedBox(width: 10), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text.rich( - maxLines: 2, - TextSpan( - children: [ - for (var i in item.title!) ...[ - TextSpan( - text: i['text'], - style: TextStyle( - color: i['type'] == 'em' - ? Theme.of(context) - .colorScheme - .primary - : Theme.of(context) - .colorScheme - .onSurface, - ), - ), - ] - ], - ), - ), - const Spacer(), - Text( - Utils.dateFormat(item.pubTime, - formatType: 'detail'), - style: textStyle, - ), - Row( - children: [ - Text('${item.view}浏览', style: textStyle), - Text(' • ', style: textStyle), - Text('${item.reply}评论', style: textStyle), - ], - ), - ], - ), - ), - ], - ), - ); - }, - ), - ), - ); - }, - childCount: list.length, + childCount: list.length, + ), + ), ), - ), + ], ); } } diff --git a/lib/pages/search_panel/article/widgets/item.dart b/lib/pages/search_panel/article/widgets/item.dart new file mode 100644 index 00000000..580cf5a9 --- /dev/null +++ b/lib/pages/search_panel/article/widgets/item.dart @@ -0,0 +1,99 @@ +import 'package:PiliPlus/common/constants.dart'; +import 'package:PiliPlus/common/widgets/image_save.dart'; +import 'package:PiliPlus/common/widgets/network_img_layer.dart'; +import 'package:PiliPlus/models/search/result.dart'; +import 'package:PiliPlus/utils/utils.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class SearchArticleItem extends StatelessWidget { + const SearchArticleItem({super.key, required this.item}); + + final SearchArticleItemModel item; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final textStyle = TextStyle( + fontSize: theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline, + ); + return InkWell( + onTap: () { + Get.toNamed( + '/articlePage', + parameters: { + 'id': '${item.id}', + 'type': 'read', + }, + ); + }, + onLongPress: () => imageSaveDialog( + title: item.title?.map((item) => item['text']).join() ?? '', + cover: item.imageUrls?.firstOrNull, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: StyleString.safeSpace, + vertical: 5, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (item.imageUrls?.isNotEmpty == true) + AspectRatio( + aspectRatio: StyleString.aspectRatio, + child: LayoutBuilder(builder: (context, boxConstraints) { + double maxWidth = boxConstraints.maxWidth; + double maxHeight = boxConstraints.maxHeight; + return NetworkImgLayer( + width: maxWidth, + height: maxHeight, + src: item.imageUrls?.firstOrNull, + ); + }), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text.rich( + maxLines: 2, + TextSpan( + children: [ + for (var i in item.title!) ...[ + TextSpan( + text: i['text'], + style: TextStyle( + color: i['type'] == 'em' + ? theme.colorScheme.primary + : theme.colorScheme.onSurface, + ), + ), + ] + ], + ), + ), + const Spacer(), + Text( + Utils.dateFormat(item.pubTime, formatType: 'detail'), + style: textStyle, + ), + Row( + children: [ + Text('${item.view}浏览', style: textStyle), + Text(' • ', style: textStyle), + Text('${item.reply}评论', style: textStyle), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/search_panel/live/view.dart b/lib/pages/search_panel/live/view.dart index 05daed6a..5c4c2b90 100644 --- a/lib/pages/search_panel/live/view.dart +++ b/lib/pages/search_panel/live/view.dart @@ -32,12 +32,12 @@ class _SearchLivePanelState extends CommonSearchPanelState list) { + Widget buildList(ThemeData theme, List list) { return SliverPadding( - padding: const EdgeInsets.only( + padding: EdgeInsets.only( left: StyleString.safeSpace, right: StyleString.safeSpace, - bottom: 80, + bottom: MediaQuery.paddingOf(context).bottom + 80, ), sliver: SliverGrid( gridDelegate: SliverGridDelegateWithExtentAndRatio( diff --git a/lib/pages/search_panel/live/widgets/item.dart b/lib/pages/search_panel/live/widgets/item.dart index 8efe0f56..9562f52d 100644 --- a/lib/pages/search_panel/live/widgets/item.dart +++ b/lib/pages/search_panel/live/widgets/item.dart @@ -12,6 +12,7 @@ class LiveItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Card( elevation: 1, clipBehavior: Clip.hardEdge, @@ -21,7 +22,6 @@ class LiveItem extends StatelessWidget { Get.toNamed('/liveRoom?roomid=${liveItem.roomid}'); }, onLongPress: () => imageSaveDialog( - context: context, title: liveItem.title?.map((item) => item['text']).join() ?? '', cover: liveItem.cover, ), @@ -60,14 +60,14 @@ class LiveItem extends StatelessWidget { }), ), ), - liveContent(context) + liveContent(theme) ], ), ), ); } - Widget liveContent(BuildContext context) => Expanded( + Widget liveContent(ThemeData theme) => Expanded( child: Padding( padding: const EdgeInsets.fromLTRB(9, 8, 9, 6), child: Column( @@ -83,8 +83,8 @@ class LiveItem extends StatelessWidget { style: TextStyle( letterSpacing: 0.3, color: i['type'] == 'em' - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurface, + ? theme.colorScheme.primary + : theme.colorScheme.onSurface, ), ), ] @@ -97,8 +97,8 @@ class LiveItem extends StatelessWidget { liveItem.uname!, maxLines: 1, style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), ), ), diff --git a/lib/pages/search_panel/pgc/view.dart b/lib/pages/search_panel/pgc/view.dart index 6684c6f2..7ab1656f 100644 --- a/lib/pages/search_panel/pgc/view.dart +++ b/lib/pages/search_panel/pgc/view.dart @@ -30,12 +30,11 @@ class _SearchPgcPanelState extends CommonSearchPanelState list) { + Widget buildList(ThemeData theme, List list) { return SliverPadding( - padding: const EdgeInsets.only(bottom: 80), + padding: + EdgeInsets.only(bottom: MediaQuery.paddingOf(context).bottom + 80), sliver: SliverGrid( gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: Grid.smallCardWidth * 2, @@ -46,7 +45,7 @@ class _SearchPgcPanelState extends CommonSearchPanelState imageSaveDialog( - context: context, title: item.title?.map((item) => item['text']).join() ?? '', cover: item.cover, ), @@ -60,21 +59,17 @@ class SearchPgcItem extends StatelessWidget { const SizedBox(height: 4), Text.rich( TextSpan( - style: TextStyle( - color: Theme.of(context).colorScheme.onSurface), + style: TextStyle(color: theme.colorScheme.onSurface), children: [ for (var i in item.title!) ...[ TextSpan( text: i['text'], style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .titleSmall! - .fontSize!, + fontSize: theme.textTheme.titleSmall!.fontSize!, fontWeight: FontWeight.bold, color: i['type'] == 'em' - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurface, + ? theme.colorScheme.primary + : theme.colorScheme.onSurface, ), ), ], diff --git a/lib/pages/search_panel/user/controller.dart b/lib/pages/search_panel/user/controller.dart index 21aba713..bbb36615 100644 --- a/lib/pages/search_panel/user/controller.dart +++ b/lib/pages/search_panel/user/controller.dart @@ -41,85 +41,90 @@ class SearchUserController constraints: BoxConstraints( maxWidth: min(640, min(Get.width, Get.height)), ), - builder: (context) => SingleChildScrollView( - child: Container( - width: double.infinity, - padding: EdgeInsets.only( - top: 20, - left: 16, - right: 16, - bottom: 80 + MediaQuery.of(context).padding.bottom, + builder: (context) { + final theme = Theme.of(context); + return SingleChildScrollView( + child: Container( + width: double.infinity, + padding: EdgeInsets.only( + top: 20, + left: 16, + right: 16, + bottom: 80 + MediaQuery.of(context).padding.bottom, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + const Text('用户粉丝数及等级排序顺序', style: TextStyle(fontSize: 16)), + const SizedBox(height: 10), + Wrap( + spacing: 8, + runSpacing: 8, + children: orderFiltersList + .map( + (item) => SearchText( + text: item['label'], + onTap: (_) async { + Get.back(); + currentOrderFilterval.value = item['value']; + SmartDialog.dismiss(); + SmartDialog.showToast("「${item['label']}」的筛选结果"); + orderSort = item['orderSort']; + order.value = item['order']; + SmartDialog.showLoading(msg: 'loading'); + await onReload(); + SmartDialog.dismiss(); + }, + bgColor: item['value'] == currentOrderFilterval.value + ? theme.colorScheme.secondaryContainer + : null, + textColor: + item['value'] == currentOrderFilterval.value + ? theme.colorScheme.onSecondaryContainer + : null, + ), + ) + .toList(), + ), + const SizedBox(height: 20), + const Text('用户分类', style: TextStyle(fontSize: 16)), + const SizedBox(height: 10), + Wrap( + spacing: 8, + runSpacing: 8, + children: userTypeFiltersList + .map( + (item) => SearchText( + text: item['label'], + onTap: (_) async { + Get.back(); + currentUserTypeFilterval.value = item['value']; + SmartDialog.dismiss(); + SmartDialog.showToast("「${item['label']}」的筛选结果"); + userType = item['userType']; + SmartDialog.showLoading(msg: 'loading'); + await onReload(); + SmartDialog.dismiss(); + }, + bgColor: + item['value'] == currentUserTypeFilterval.value + ? theme.colorScheme.secondaryContainer + : null, + textColor: + item['value'] == currentUserTypeFilterval.value + ? theme.colorScheme.onSecondaryContainer + : null, + ), + ) + .toList(), + ), + ], + ), ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 10), - const Text('用户粉丝数及等级排序顺序', style: TextStyle(fontSize: 16)), - const SizedBox(height: 10), - Wrap( - spacing: 8, - runSpacing: 8, - children: orderFiltersList - .map( - (item) => SearchText( - text: item['label'], - onTap: (_) async { - Get.back(); - currentOrderFilterval.value = item['value']; - SmartDialog.dismiss(); - SmartDialog.showToast("「${item['label']}」的筛选结果"); - orderSort = item['orderSort']; - order.value = item['order']; - SmartDialog.showLoading(msg: 'loading'); - await onReload(); - SmartDialog.dismiss(); - }, - bgColor: item['value'] == currentOrderFilterval.value - ? Theme.of(context).colorScheme.secondaryContainer - : null, - textColor: item['value'] == currentOrderFilterval.value - ? Theme.of(context).colorScheme.onSecondaryContainer - : null, - ), - ) - .toList(), - ), - const SizedBox(height: 20), - const Text('用户分类', style: TextStyle(fontSize: 16)), - const SizedBox(height: 10), - Wrap( - spacing: 8, - runSpacing: 8, - children: userTypeFiltersList - .map( - (item) => SearchText( - text: item['label'], - onTap: (_) async { - Get.back(); - currentUserTypeFilterval.value = item['value']; - SmartDialog.dismiss(); - SmartDialog.showToast("「${item['label']}」的筛选结果"); - userType = item['userType']; - SmartDialog.showLoading(msg: 'loading'); - await onReload(); - SmartDialog.dismiss(); - }, - bgColor: item['value'] == currentUserTypeFilterval.value - ? Theme.of(context).colorScheme.secondaryContainer - : null, - textColor: item['value'] == - currentUserTypeFilterval.value - ? Theme.of(context).colorScheme.onSecondaryContainer - : null, - ), - ) - .toList(), - ), - ], - ), - ), - ), + ); + }, ); } } diff --git a/lib/pages/search_panel/user/view.dart b/lib/pages/search_panel/user/view.dart index 80ee1d08..57924009 100644 --- a/lib/pages/search_panel/user/view.dart +++ b/lib/pages/search_panel/user/view.dart @@ -1,5 +1,4 @@ import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart'; -import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/search/result.dart'; import 'package:PiliPlus/pages/search_panel/user/controller.dart'; import 'package:PiliPlus/pages/search_panel/user/widgets/item.dart'; @@ -14,7 +13,6 @@ class SearchUserPanel extends CommonSearchPanel { required super.keyword, required super.tag, required super.searchType, - super.hasHeader = true, }); @override @@ -33,98 +31,82 @@ class _SearchUserPanelState extends CommonSearchPanelState?> loadingState) { - if (loadingState is Success) { - return SliverPersistentHeader( - pinned: false, - floating: true, - delegate: CustomSliverPersistentHeaderDelegate( - extent: 40, - bgColor: Theme.of(context).colorScheme.surface, - child: Container( - height: 40, - padding: const EdgeInsets.only(left: 25, right: 12), - child: Row( - children: [ - Obx( - () => Text( - '排序: ${controller.orderFiltersList[controller.currentOrderFilterval.value]['label']}', - maxLines: 1, - style: - TextStyle(color: Theme.of(context).colorScheme.outline), - ), - ), - const Spacer(), - Obx( - () => Text( - '用户类型: ${controller.userTypeFiltersList[controller.currentUserTypeFilterval.value]['label']}', - maxLines: 1, - style: - TextStyle(color: Theme.of(context).colorScheme.outline), - ), - ), - const Spacer(), - SizedBox( - width: 32, - height: 32, - child: IconButton( - tooltip: '筛选', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: () { - controller.onShowFilterDialog(context); - }, - icon: Icon( - Icons.filter_list_outlined, - size: 18, - color: Theme.of(context).colorScheme.primary, + Widget buildList(ThemeData theme, List list) { + return SliverMainAxisGroup( + slivers: [ + SliverPersistentHeader( + pinned: false, + floating: true, + delegate: CustomSliverPersistentHeaderDelegate( + extent: 40, + bgColor: theme.colorScheme.surface, + child: Container( + height: 40, + padding: const EdgeInsets.only(left: 25, right: 12), + child: Row( + children: [ + Obx( + () => Text( + '排序: ${controller.orderFiltersList[controller.currentOrderFilterval.value]['label']}', + maxLines: 1, + style: TextStyle(color: theme.colorScheme.outline), ), ), - ), - ], + const Spacer(), + Obx( + () => Text( + '用户类型: ${controller.userTypeFiltersList[controller.currentUserTypeFilterval.value]['label']}', + maxLines: 1, + style: TextStyle(color: theme.colorScheme.outline), + ), + ), + const Spacer(), + SizedBox( + width: 32, + height: 32, + child: IconButton( + tooltip: '筛选', + style: ButtonStyle( + padding: WidgetStateProperty.all(EdgeInsets.zero), + ), + onPressed: () { + controller.onShowFilterDialog(context); + }, + icon: Icon( + Icons.filter_list_outlined, + size: 18, + color: theme.colorScheme.primary, + ), + ), + ), + ], + ), ), ), ), - ); - } - return const SliverToBoxAdapter(); - } - - @override - Widget buildList(List list) { - return SliverPadding( - padding: const EdgeInsets.only(bottom: 80), - sliver: SliverGrid( - gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: Grid.smallCardWidth * 2, - mainAxisExtent: 66, + SliverPadding( + padding: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom + 80), + sliver: SliverGrid( + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: Grid.smallCardWidth * 2, + mainAxisExtent: 66, + ), + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + if (index == list.length - 1) { + controller.onLoadMore(); + } + return SearchUserItem( + item: list[index], + ); + }, + childCount: list.length, + ), + ), ), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - if (index == list.length - 1) { - controller.onLoadMore(); - } - return SearchUserItem( - style: style, - item: list[index], - ); - }, - childCount: list.length, - ), - ), + ], ); } } diff --git a/lib/pages/search_panel/user/widgets/item.dart b/lib/pages/search_panel/user/widgets/item.dart index 37d6897b..995f4303 100644 --- a/lib/pages/search_panel/user/widgets/item.dart +++ b/lib/pages/search_panel/user/widgets/item.dart @@ -7,16 +7,19 @@ import 'package:get/get.dart'; class SearchUserItem extends StatelessWidget { const SearchUserItem({ super.key, - required this.style, required this.item, }); - final TextStyle style; final SearchUserItemModel item; @override Widget build(BuildContext context) { String heroTag = Utils.makeHeroTag(item.mid); + final theme = Theme.of(context); + final style = TextStyle( + fontSize: theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline, + ); return InkWell( onTap: () => Get.toNamed( '/member?mid=${item.mid}', diff --git a/lib/pages/search_panel/video/controller.dart b/lib/pages/search_panel/video/controller.dart index 1920b990..30cb51e8 100644 --- a/lib/pages/search_panel/video/controller.dart +++ b/lib/pages/search_panel/video/controller.dart @@ -151,6 +151,7 @@ class SearchVideoController ), builder: (context) => StatefulBuilder( builder: (context, setState) { + final theme = Theme.of(context); Widget dateWidget([bool isFirst = true]) { return SearchText( text: DateFormat('yyyy-MM-dd') @@ -200,12 +201,12 @@ class SearchVideoController }, bgColor: currentPubTimeFilter == -1 && (isFirst ? customPubBeginDate : customPubEndDate) - ? Theme.of(context).colorScheme.secondaryContainer - : Theme.of(context).colorScheme.outline.withOpacity(0.1), + ? theme.colorScheme.secondaryContainer + : theme.colorScheme.outline.withOpacity(0.1), textColor: currentPubTimeFilter == -1 && (isFirst ? customPubBeginDate : customPubEndDate) - ? Theme.of(context).colorScheme.onSecondaryContainer - : Theme.of(context).colorScheme.outline.withOpacity(0.8), + ? theme.colorScheme.onSecondaryContainer + : theme.colorScheme.outline.withOpacity(0.8), ); } @@ -271,14 +272,10 @@ class SearchVideoController SmartDialog.dismiss(); }, bgColor: item['value'] == currentPubTimeFilter - ? Theme.of(context) - .colorScheme - .secondaryContainer + ? theme.colorScheme.secondaryContainer : null, textColor: item['value'] == currentPubTimeFilter - ? Theme.of(context) - .colorScheme - .onSecondaryContainer + ? theme.colorScheme.onSecondaryContainer : null, ), ) @@ -318,14 +315,10 @@ class SearchVideoController SmartDialog.dismiss(); }, bgColor: item['value'] == currentTimeFilter - ? Theme.of(context) - .colorScheme - .secondaryContainer + ? theme.colorScheme.secondaryContainer : null, textColor: item['value'] == currentTimeFilter - ? Theme.of(context) - .colorScheme - .onSecondaryContainer + ? theme.colorScheme.onSecondaryContainer : null, ), ) @@ -352,14 +345,10 @@ class SearchVideoController SmartDialog.dismiss(); }, bgColor: item['value'] == currentZoneFilter - ? Theme.of(context) - .colorScheme - .secondaryContainer + ? theme.colorScheme.secondaryContainer : null, textColor: item['value'] == currentZoneFilter - ? Theme.of(context) - .colorScheme - .onSecondaryContainer + ? theme.colorScheme.onSecondaryContainer : null, ), ) diff --git a/lib/pages/search_panel/video/view.dart b/lib/pages/search_panel/video/view.dart index 627d31b5..79372a75 100644 --- a/lib/pages/search_panel/video/view.dart +++ b/lib/pages/search_panel/video/view.dart @@ -1,6 +1,5 @@ import 'package:PiliPlus/common/widgets/custom_sliver_persistent_header_delegate.dart'; import 'package:PiliPlus/common/widgets/video_card_h.dart'; -import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/search/result.dart'; import 'package:PiliPlus/pages/search/widgets/search_text.dart'; import 'package:PiliPlus/pages/search_panel/video/controller.dart'; @@ -16,7 +15,6 @@ class SearchVideoPanel extends CommonSearchPanel { required super.keyword, required super.tag, required super.searchType, - super.hasHeader = true, }); @override @@ -36,95 +34,93 @@ class _SearchVideoPanelState extends CommonSearchPanelState?> loadingState) { - if (loadingState is Success) { - return SliverPersistentHeader( - pinned: false, - floating: true, - delegate: CustomSliverPersistentHeaderDelegate( - extent: 34, - bgColor: Theme.of(context).colorScheme.surface, - child: Container( - height: 34, - padding: const EdgeInsets.symmetric(horizontal: 12), - child: Row( - children: [ - Expanded( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Wrap( - children: [ - for (var i in controller.filterList) ...[ - Obx( - () => SearchText( - fontSize: 13, - text: i['label'], - bgColor: Colors.transparent, - textColor: - controller.selectedType.value == i['type'] - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, - onTap: (value) async { - controller.selectedType.value = i['type']; - controller.order.value = - i['type'].toString().split('.').last; - SmartDialog.showLoading(msg: 'loading'); - await controller.onReload(); - SmartDialog.dismiss(); - }, + Widget buildList(ThemeData theme, List list) { + return SliverMainAxisGroup( + slivers: [ + SliverPersistentHeader( + pinned: false, + floating: true, + delegate: CustomSliverPersistentHeaderDelegate( + extent: 34, + bgColor: theme.colorScheme.surface, + child: Container( + height: 34, + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Row( + children: [ + Expanded( + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Wrap( + children: [ + for (var i in controller.filterList) ...[ + Obx( + () => SearchText( + fontSize: 13, + text: i['label'], + bgColor: Colors.transparent, + textColor: + controller.selectedType.value == i['type'] + ? theme.colorScheme.primary + : theme.colorScheme.outline, + onTap: (value) async { + controller.selectedType.value = i['type']; + controller.order.value = + i['type'].toString().split('.').last; + SmartDialog.showLoading(msg: 'loading'); + await controller.onReload(); + SmartDialog.dismiss(); + }, + ), ), - ), - ] - ], + ] + ], + ), ), ), - ), - const VerticalDivider(indent: 7, endIndent: 8), - const SizedBox(width: 3), - SizedBox( - width: 32, - height: 32, - child: IconButton( - tooltip: '筛选', - style: ButtonStyle( - padding: WidgetStateProperty.all(EdgeInsets.zero), - ), - onPressed: () => controller.onShowFilterDialog(context), - icon: Icon( - Icons.filter_list_outlined, - size: 18, - color: Theme.of(context).colorScheme.primary, + const VerticalDivider(indent: 7, endIndent: 8), + const SizedBox(width: 3), + SizedBox( + width: 32, + height: 32, + child: IconButton( + tooltip: '筛选', + style: ButtonStyle( + padding: WidgetStateProperty.all(EdgeInsets.zero), + ), + onPressed: () => controller.onShowFilterDialog(context), + icon: Icon( + Icons.filter_list_outlined, + size: 18, + color: theme.colorScheme.primary, + ), ), ), - ), - ], + ], + ), ), ), ), - ); - } - return const SliverToBoxAdapter(); - } - - @override - Widget buildList(List list) { - return SliverPadding( - padding: const EdgeInsets.only(bottom: 80), - sliver: SliverGrid( - gridDelegate: Grid.videoCardHDelegate(context), - delegate: SliverChildBuilderDelegate( - (context, index) { - if (index == list.length - 1) { - controller.onLoadMore(); - } - return VideoCardH( - videoItem: list[index], - showPubdate: true, - ); - }, - childCount: list.length, + SliverPadding( + padding: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom + 80), + sliver: SliverGrid( + gridDelegate: Grid.videoCardHDelegate(context), + delegate: SliverChildBuilderDelegate( + (context, index) { + if (index == list.length - 1) { + controller.onLoadMore(); + } + return VideoCardH( + videoItem: list[index], + showPubdate: true, + ); + }, + childCount: list.length, + ), + ), ), - ), + ], ); } } diff --git a/lib/pages/search_panel/view.dart b/lib/pages/search_panel/view.dart index bf2398c5..f068c1ae 100644 --- a/lib/pages/search_panel/view.dart +++ b/lib/pages/search_panel/view.dart @@ -20,13 +20,11 @@ abstract class CommonSearchPanel extends StatefulWidget { required this.keyword, required this.searchType, required this.tag, - this.hasHeader = false, }); final String keyword; final SearchType searchType; final String tag; - final bool hasHeader; } abstract class CommonSearchPanelState< @@ -41,6 +39,7 @@ abstract class CommonSearchPanelState< @override Widget build(BuildContext context) { super.build(context); + final theme = Theme.of(context); return refreshIndicator( onRefresh: () async { await controller.onRefresh(); @@ -49,18 +48,12 @@ abstract class CommonSearchPanelState< controller: controller.scrollController, physics: const AlwaysScrollableScrollPhysics(), slivers: [ - if (widget.hasHeader) - Obx(() => buildHeader(controller.loadingState.value)), - Obx(() => _buildBody(controller.loadingState.value)), + Obx(() => _buildBody(theme, controller.loadingState.value)), ], ), ); } - Widget buildHeader(LoadingState?> loadingState) { - throw UnimplementedError(); - } - Widget get _builLoading { return SliverGrid( gridDelegate: switch (widget.searchType) { @@ -103,7 +96,7 @@ abstract class CommonSearchPanelState< ); } - Widget _buildBody(LoadingState?> loadingState) { + Widget _buildBody(ThemeData theme, LoadingState?> loadingState) { return switch (loadingState) { Loading() => widget.searchType == SearchType.live_room ? SliverPadding( @@ -115,7 +108,7 @@ abstract class CommonSearchPanelState< ) : _builLoading, Success() => loadingState.response?.isNotEmpty == true - ? buildList(loadingState.response!) + ? buildList(theme, loadingState.response!) : HttpError( onReload: controller.onReload, ), @@ -126,5 +119,5 @@ abstract class CommonSearchPanelState< }; } - Widget buildList(List list); + Widget buildList(ThemeData theme, List list); } diff --git a/lib/pages/search_result/view.dart b/lib/pages/search_result/view.dart index d0fbeb86..4d9f660f 100644 --- a/lib/pages/search_result/view.dart +++ b/lib/pages/search_result/view.dart @@ -62,11 +62,12 @@ class _SearchResultPageState extends State @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: AppBar( shape: Border( bottom: BorderSide( - color: Theme.of(context).dividerColor.withOpacity(0.08), + color: theme.dividerColor.withOpacity(0.08), width: 1, ), ), @@ -86,7 +87,7 @@ class _SearchResultPageState extends State width: double.infinity, child: Text( _searchResultController.keyword, - style: Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, maxLines: 1, ), ), @@ -121,18 +122,18 @@ class _SearchResultPageState extends State indicatorPadding: const EdgeInsets.symmetric(horizontal: 3, vertical: 8), indicator: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, + color: theme.colorScheme.secondaryContainer, borderRadius: const BorderRadius.all(Radius.circular(20)), ), indicatorSize: TabBarIndicatorSize.tab, - labelColor: Theme.of(context).colorScheme.onSecondaryContainer, + labelColor: theme.colorScheme.onSecondaryContainer, labelStyle: TabBarTheme.of(context) .labelStyle ?.copyWith(fontSize: 13) ?? const TextStyle(fontSize: 13), dividerColor: Colors.transparent, dividerHeight: 0, - unselectedLabelColor: Theme.of(context).colorScheme.outline, + unselectedLabelColor: theme.colorScheme.outline, tabAlignment: TabAlignment.start, onTap: (index) { if (_tabController.indexIsChanging.not) { diff --git a/lib/pages/search_trending/view.dart b/lib/pages/search_trending/view.dart index 3d50a218..8d00c77e 100644 --- a/lib/pages/search_trending/view.dart +++ b/lib/pages/search_trending/view.dart @@ -52,6 +52,7 @@ class _SearchTrendingPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return LayoutBuilder(builder: (context, constraints) { final maxWidth = constraints.maxWidth; final width = constraints.maxWidth > constraints.maxHeight @@ -78,10 +79,8 @@ class _SearchTrendingPageState extends State { ), ), ), - backgroundColor: Theme.of(context) - .colorScheme - .surface - .withOpacity(_scrollRatio.value), + backgroundColor: + theme.colorScheme.surface.withOpacity(_scrollRatio.value), foregroundColor: flag ? null : Colors.white, systemOverlayStyle: flag ? null @@ -94,10 +93,7 @@ class _SearchTrendingPageState extends State { preferredSize: Size.fromHeight(1), child: Divider( height: 1, - color: Theme.of(context) - .colorScheme - .outline - .withOpacity(0.1), + color: theme.colorScheme.outline.withOpacity(0.1), ), ) : null, @@ -134,7 +130,8 @@ class _SearchTrendingPageState extends State { }, ), ), - Obx(() => _buildBody(_controller.loadingState.value)), + Obx(() => + _buildBody(theme, _controller.loadingState.value)), ], ), ), @@ -145,7 +142,8 @@ class _SearchTrendingPageState extends State { }); } - Widget _buildBody(LoadingState?> loadingState) { + Widget _buildBody( + ThemeData theme, LoadingState?> loadingState) { return switch (loadingState) { Loading() => SliverToBoxAdapter(child: LinearProgressIndicator()), Success() => loadingState.response?.isNotEmpty == true @@ -180,7 +178,7 @@ class _SearchTrendingPageState extends State { 0 => const Color(0xFFfdad13), 1 => const Color(0xFF8aace1), 2 => const Color(0xFFdfa777), - _ => Theme.of(context).colorScheme.outline, + _ => theme.colorScheme.outline, }, fontSize: 17, fontStyle: FontStyle.italic, @@ -218,7 +216,7 @@ class _SearchTrendingPageState extends State { separatorBuilder: (context, index) => Divider( height: 1, indent: 48, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), + color: theme.colorScheme.outline.withOpacity(0.1), ), ), ) diff --git a/lib/pages/setting/pages/color_select.dart b/lib/pages/setting/pages/color_select.dart index 000b5566..d99ef634 100644 --- a/lib/pages/setting/pages/color_select.dart +++ b/lib/pages/setting/pages/color_select.dart @@ -42,14 +42,13 @@ class _ColorSelectPageState extends State { final ColorSelectController ctr = Get.put(ColorSelectController()); FlexSchemeVariant _dynamicSchemeVariant = FlexSchemeVariant.values[GStorage.schemeVariant]; - TextStyle get titleStyle => Theme.of(context).textTheme.titleMedium!; - TextStyle get subTitleStyle => Theme.of(context) - .textTheme - .labelMedium! - .copyWith(color: Theme.of(context).colorScheme.outline); @override Widget build(BuildContext context) { + final theme = Theme.of(context); + TextStyle titleStyle = theme.textTheme.titleMedium!; + TextStyle subTitleStyle = + theme.textTheme.labelMedium!.copyWith(color: theme.colorScheme.outline); return Scaffold( appBar: AppBar(title: const Text('选择应用主题')), body: SafeArea( @@ -119,11 +118,8 @@ class _ColorSelectPageState extends State { height: 1, fontSize: 13, color: ctr.type.value == 0 - ? Theme.of(context) - .colorScheme - .outline - .withOpacity(0.8) - : Theme.of(context).colorScheme.secondary, + ? theme.colorScheme.outline.withOpacity(0.8) + : theme.colorScheme.secondary, ), strutStyle: StrutStyle(leading: 0, height: 1), ), @@ -131,11 +127,8 @@ class _ColorSelectPageState extends State { size: 20, Icons.keyboard_arrow_right, color: ctr.type.value == 0 - ? Theme.of(context) - .colorScheme - .outline - .withOpacity(0.8) - : Theme.of(context).colorScheme.secondary, + ? theme.colorScheme.outline.withOpacity(0.8) + : theme.colorScheme.secondary, ) ], ), @@ -236,9 +229,7 @@ class _ColorSelectPageState extends State { style: TextStyle( fontSize: 12, color: ctr.currentColor.value != index - ? Theme.of(context) - .colorScheme - .outline + ? theme.colorScheme.outline : null, ), ), diff --git a/lib/pages/setting/pages/font_size_select.dart b/lib/pages/setting/pages/font_size_select.dart index 45808586..8277d69d 100644 --- a/lib/pages/setting/pages/font_size_select.dart +++ b/lib/pages/setting/pages/font_size_select.dart @@ -35,6 +35,7 @@ class _FontSizeSelectPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: AppBar( actions: [ @@ -65,11 +66,8 @@ class _FontSizeSelectPageState extends State { decoration: BoxDecoration( border: Border( top: BorderSide( - color: Theme.of(context) - .colorScheme - .primary - .withOpacity(0.3))), - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.primary.withOpacity(0.3))), + color: theme.colorScheme.surface, ), child: Row( children: [ diff --git a/lib/pages/setting/pages/play_speed_set.dart b/lib/pages/setting/pages/play_speed_set.dart index c0dd58cd..2f59ac8b 100644 --- a/lib/pages/setting/pages/play_speed_set.dart +++ b/lib/pages/setting/pages/play_speed_set.dart @@ -129,7 +129,7 @@ class _PlaySpeedPageState extends State { } // 设定倍速弹窗 - void showBottomSheet(index) { + void showBottomSheet(ThemeData theme, int index) { showModalBottomSheet( context: context, useSafeArea: true, @@ -150,11 +150,11 @@ class _PlaySpeedPageState extends State { menuAction(index, item['id']); }, minLeadingWidth: 0, - iconColor: Theme.of(context).colorScheme.onSurface, + iconColor: theme.colorScheme.onSurface, leading: item['leading'], title: Text( item['title'], - style: Theme.of(context).textTheme.titleSmall, + style: theme.textTheme.titleSmall, ), ), ), @@ -194,6 +194,7 @@ class _PlaySpeedPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: AppBar( title: const Text('倍速设置'), @@ -218,7 +219,7 @@ class _PlaySpeedPageState extends State { const EdgeInsets.only(left: 14, right: 14, top: 6, bottom: 0), child: Text( '点击下方按钮设置默认(长按)倍速', - style: TextStyle(color: Theme.of(context).colorScheme.outline), + style: TextStyle(color: theme.colorScheme.outline), ), ), ListTile( @@ -255,7 +256,7 @@ class _PlaySpeedPageState extends State { children: [ Text( '倍速列表', - style: Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, ), const SizedBox(width: 12), TextButton( @@ -278,7 +279,7 @@ class _PlaySpeedPageState extends State { children: List.generate( speedList.length, (index) => FilledButton.tonal( - onPressed: () => showBottomSheet(index), + onPressed: () => showBottomSheet(theme, index), child: Text(speedList[index].toString()), ), ), diff --git a/lib/pages/setting/recommend_setting.dart b/lib/pages/setting/recommend_setting.dart index 54447a20..109bf8f7 100644 --- a/lib/pages/setting/recommend_setting.dart +++ b/lib/pages/setting/recommend_setting.dart @@ -8,6 +8,7 @@ class RecommendSetting extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: showAppBar == false ? null : AppBar(title: const Text('推荐流设置')), body: ListView( @@ -20,9 +21,8 @@ class RecommendSetting extends StatelessWidget { '* 其它(如热门视频、手动搜索、链接跳转等)均不受过滤器影响。\n' '* 设定较严苛的条件可导致推荐项数锐减或多次请求,请酌情选择。\n' '* 后续可能会增加更多过滤条件,敬请期待。', - style: Theme.of(context).textTheme.labelSmall!.copyWith( - color: - Theme.of(context).colorScheme.outline.withOpacity(0.7)), + style: theme.textTheme.labelSmall! + .copyWith(color: theme.colorScheme.outline.withOpacity(0.7)), ), ), SizedBox(height: MediaQuery.paddingOf(context).bottom + 80), diff --git a/lib/pages/setting/sponsor_block_page.dart b/lib/pages/setting/sponsor_block_page.dart index 192b1358..758389ac 100644 --- a/lib/pages/setting/sponsor_block_page.dart +++ b/lib/pages/setting/sponsor_block_page.dart @@ -56,12 +56,6 @@ class _SponsorBlockPageState extends State { super.dispose(); } - TextStyle get _titleStyle => TextStyle(fontSize: 15); - TextStyle get _subTitleStyle => TextStyle( - fontSize: 13, - color: Theme.of(context).colorScheme.outline, - ); - _checkServerStatus() { Request() .get( @@ -78,7 +72,9 @@ class _SponsorBlockPageState extends State { }); } - Widget get _blockLimitItem => ListTile( + Widget _blockLimitItem( + ThemeData theme, TextStyle titleStyle, TextStyle subTitleStyle) => + ListTile( dense: true, onTap: () { _textController.text = _blockLimit.toString(); @@ -86,7 +82,7 @@ class _SponsorBlockPageState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text('最短片段时长', style: _titleStyle), + title: Text('最短片段时长', style: titleStyle), content: TextFormField( keyboardType: TextInputType.numberWithOptions(decimal: true), controller: _textController, @@ -102,7 +98,7 @@ class _SponsorBlockPageState extends State { child: Text( '取消', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -121,10 +117,10 @@ class _SponsorBlockPageState extends State { }, ); }, - title: Text('最短片段时长', style: _titleStyle), + title: Text('最短片段时长', style: titleStyle), subtitle: Text( '忽略短于此时长的片段', - style: _subTitleStyle, + style: subTitleStyle, ), trailing: Text( '${_blockLimit}s', @@ -132,17 +128,19 @@ class _SponsorBlockPageState extends State { ), ); - Widget get _aboudItem => ListTile( + Widget _aboudItem(TextStyle titleStyle, TextStyle subTitleStyle) => ListTile( dense: true, - title: Text('关于空降助手', style: _titleStyle), - subtitle: Text(_url, style: _subTitleStyle), + title: Text('关于空降助手', style: titleStyle), + subtitle: Text(_url, style: subTitleStyle), onTap: () => PageUtils.launchURL(_url), ); - Widget get _userIdItem => ListTile( + Widget _userIdItem( + ThemeData theme, TextStyle titleStyle, TextStyle subTitleStyle) => + ListTile( dense: true, - title: Text('用户ID', style: _titleStyle), - subtitle: Text(_userId, style: _subTitleStyle), + title: Text('用户ID', style: titleStyle), + subtitle: Text(_userId, style: subTitleStyle), onTap: () { final key = GlobalKey(); _textController.text = _userId; @@ -150,7 +148,7 @@ class _SponsorBlockPageState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text('用户ID', style: _titleStyle), + title: Text('用户ID', style: titleStyle), content: Form( key: key, child: TextFormField( @@ -184,7 +182,7 @@ class _SponsorBlockPageState extends State { child: Text( '取消', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -218,12 +216,12 @@ class _SponsorBlockPageState extends State { setState(() {}); } - Widget get _blockToastItem => ListTile( + Widget _blockToastItem(TextStyle titleStyle) => ListTile( dense: true, onTap: _updateBlockToast, title: Text( '显示跳过Toast', - style: _titleStyle, + style: titleStyle, ), trailing: Transform.scale( alignment: Alignment.centerRight, @@ -242,36 +240,39 @@ class _SponsorBlockPageState extends State { ), )); - Widget get _blockTrackItem => ListTile( - dense: true, - onTap: _updateBlockTrack, - title: Text( - '跳过次数统计跟踪', - style: _titleStyle, - ), - subtitle: Text( - // from origin extension - '此功能追踪您跳过了哪些片段,让用户知道他们提交的片段帮助了多少人。同时点赞会作为依据,确保垃圾信息不会污染数据库。在您每次跳过片段时,我们都会向服务器发送一条消息。希望大家开启此项设置,以便得到更准确的统计数据。:)', - style: _subTitleStyle, - ), - trailing: Transform.scale( - alignment: Alignment.centerRight, - scale: 0.8, - child: Switch( - thumbIcon: WidgetStateProperty.resolveWith((states) { - if (states.isNotEmpty && states.first == WidgetState.selected) { - return const Icon(Icons.done); - } - return null; - }), - value: _blockTrack, - onChanged: (val) { - _updateBlockTrack(); - }, - ), - )); + Widget _blockTrackItem(TextStyle titleStyle, TextStyle subTitleStyle) => + ListTile( + dense: true, + onTap: _updateBlockTrack, + title: Text( + '跳过次数统计跟踪', + style: titleStyle, + ), + subtitle: Text( + // from origin extension + '此功能追踪您跳过了哪些片段,让用户知道他们提交的片段帮助了多少人。同时点赞会作为依据,确保垃圾信息不会污染数据库。在您每次跳过片段时,我们都会向服务器发送一条消息。希望大家开启此项设置,以便得到更准确的统计数据。:)', + style: subTitleStyle, + ), + trailing: Transform.scale( + alignment: Alignment.centerRight, + scale: 0.8, + child: Switch( + thumbIcon: WidgetStateProperty.resolveWith((states) { + if (states.isNotEmpty && states.first == WidgetState.selected) { + return const Icon(Icons.done); + } + return null; + }), + value: _blockTrack, + onChanged: (val) { + _updateBlockTrack(); + }, + ), + )); - Widget get _blockServerItem => ListTile( + Widget _blockServerItem( + ThemeData theme, TextStyle titleStyle, TextStyle subTitleStyle) => + ListTile( dense: true, onTap: () { _textController.text = _blockServer; @@ -279,7 +280,7 @@ class _SponsorBlockPageState extends State { context: context, builder: (BuildContext context) { return AlertDialog( - title: Text('服务器地址', style: _titleStyle), + title: Text('服务器地址', style: titleStyle), content: TextFormField( keyboardType: TextInputType.url, controller: _textController, @@ -302,7 +303,7 @@ class _SponsorBlockPageState extends State { child: Text( '取消', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -324,20 +325,20 @@ class _SponsorBlockPageState extends State { }, title: Text( '服务器地址', - style: _titleStyle, + style: titleStyle, ), subtitle: Text( _blockServer, - style: _subTitleStyle, + style: subTitleStyle, ), ); - Widget get _serverStatusItem => ListTile( + Widget _serverStatusItem(ThemeData theme, TextStyle titleStyle) => ListTile( dense: true, onTap: _checkServerStatus, title: Text( '服务器状态', - style: _titleStyle, + style: titleStyle, ), trailing: Text( _serverStatus == null @@ -350,41 +351,51 @@ class _SponsorBlockPageState extends State { color: _serverStatus == null ? null : _serverStatus == true - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.error, + ? theme.colorScheme.primary + : theme.colorScheme.error, ), ), ); - Widget get _divider => SliverToBoxAdapter( - child: Divider( - height: 1, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), - ), - ); - - Widget get _dividerL => SliverToBoxAdapter( - child: Divider( - thickness: 16, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), - ), - ); - @override Widget build(BuildContext context) { + final theme = Theme.of(context); + + final titleStyle = TextStyle(fontSize: 15); + + final subTitleStyle = TextStyle( + fontSize: 13, + color: theme.colorScheme.outline, + ); + + final divider = SliverToBoxAdapter( + child: Divider( + height: 1, + color: theme.colorScheme.outline.withOpacity(0.1), + ), + ); + + final dividerL = SliverToBoxAdapter( + child: Divider( + thickness: 16, + color: theme.colorScheme.outline.withOpacity(0.1), + ), + ); + return Scaffold( appBar: AppBar(title: Text('空降助手')), body: CustomScrollView( slivers: [ - _dividerL, - SliverToBoxAdapter(child: _serverStatusItem), - _dividerL, - SliverToBoxAdapter(child: _blockLimitItem), - _divider, - SliverToBoxAdapter(child: _blockToastItem), - _divider, - SliverToBoxAdapter(child: _blockTrackItem), - _dividerL, + dividerL, + SliverToBoxAdapter(child: _serverStatusItem(theme, titleStyle)), + dividerL, + SliverToBoxAdapter( + child: _blockLimitItem(theme, titleStyle, subTitleStyle)), + divider, + SliverToBoxAdapter(child: _blockToastItem(titleStyle)), + divider, + SliverToBoxAdapter(child: _blockTrackItem(titleStyle, titleStyle)), + dividerL, SliverList.separated( itemCount: _blockSettings.length, itemBuilder: (context, index) => ListTile( @@ -493,11 +504,8 @@ class _SponsorBlockPageState extends State { fontSize: 14, color: _blockSettings[index].second == SkipType.disable - ? Theme.of(context) - .colorScheme - .outline - .withOpacity(0.7) - : Theme.of(context).colorScheme.secondary, + ? theme.colorScheme.outline.withOpacity(0.7) + : theme.colorScheme.secondary, ), strutStyle: StrutStyle(height: 1, leading: 0), ), @@ -506,11 +514,8 @@ class _SponsorBlockPageState extends State { size: MediaQuery.textScalerOf(context).scale(14), color: _blockSettings[index].second == SkipType.disable - ? Theme.of(context) - .colorScheme - .outline - .withOpacity(0.7) - : Theme.of(context).colorScheme.secondary, + ? theme.colorScheme.outline.withOpacity(0.7) + : theme.colorScheme.secondary, ), ], ), @@ -524,22 +529,24 @@ class _SponsorBlockPageState extends State { fontSize: 12, color: _blockSettings[index].second == SkipType.disable ? null - : Theme.of(context).colorScheme.outline, + : theme.colorScheme.outline, ), ), ), separatorBuilder: (context, index) => Divider( height: 1, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), + color: theme.colorScheme.outline.withOpacity(0.1), ), ), - _dividerL, - SliverToBoxAdapter(child: _userIdItem), - _divider, - SliverToBoxAdapter(child: _blockServerItem), - _dividerL, - SliverToBoxAdapter(child: _aboudItem), - _dividerL, + dividerL, + SliverToBoxAdapter( + child: _userIdItem(theme, titleStyle, subTitleStyle)), + divider, + SliverToBoxAdapter( + child: _blockServerItem(theme, titleStyle, subTitleStyle)), + dividerL, + SliverToBoxAdapter(child: _aboudItem(titleStyle, subTitleStyle)), + dividerL, SliverToBoxAdapter( child: SizedBox( height: 55 + MediaQuery.paddingOf(context).bottom, diff --git a/lib/pages/setting/view.dart b/lib/pages/setting/view.dart index 4ecf7f98..0bf0c200 100644 --- a/lib/pages/setting/view.dart +++ b/lib/pages/setting/view.dart @@ -42,11 +42,6 @@ class SettingPage extends StatefulWidget { class _SettingPageState extends State { late String _type = 'privacySetting'; final RxBool _noAccount = Accounts.accountMode.isEmpty.obs; - TextStyle get _titleStyle => Theme.of(context).textTheme.titleMedium!; - TextStyle get _subTitleStyle => Theme.of(context) - .textTheme - .labelMedium! - .copyWith(color: Theme.of(context).colorScheme.outline); bool get _isPortrait => context.orientation == Orientation.portrait; final List<_SettingsModel> _items = [ @@ -100,6 +95,7 @@ class _SettingPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: AppBar( title: _isPortrait @@ -117,7 +113,7 @@ class _SettingPageState extends State { }), ), body: _isPortrait - ? _buildList + ? _buildList(theme) : Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -127,12 +123,12 @@ class _SettingPageState extends State { context: context, removeRight: true, removeTop: true, - child: _buildList, + child: _buildList(theme), ), ), VerticalDivider( width: 1, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), + color: theme.colorScheme.outline.withOpacity(0.1), ), Expanded( flex: 6, @@ -167,29 +163,30 @@ class _SettingPageState extends State { } } - Color? _getTileColor(String name) { + Color? _getTileColor(ThemeData theme, String name) { if (_isPortrait) { return null; } else { - return name == _type - ? Theme.of(context).colorScheme.onInverseSurface - : null; + return name == _type ? theme.colorScheme.onInverseSurface : null; } } - Widget get _buildList { + Widget _buildList(ThemeData theme) { + TextStyle titleStyle = theme.textTheme.titleMedium!; + TextStyle subTitleStyle = + theme.textTheme.labelMedium!.copyWith(color: theme.colorScheme.outline); return ListView( children: [ - _buildSearchItem, + _buildSearchItem(theme), ..._items.sublist(0, _items.length - 1).map( (item) => ListTile( - tileColor: _getTileColor(item.name), + tileColor: _getTileColor(theme, item.name), onTap: () => _toPage(item.name), leading: Icon(item.icon), - title: Text(item.title, style: _titleStyle), + title: Text(item.title, style: titleStyle), subtitle: item.subtitle == null ? null - : Text(item.subtitle!, style: _subTitleStyle), + : Text(item.subtitle!, style: subTitleStyle), ), ), ListTile( @@ -203,14 +200,14 @@ class _SettingPageState extends State { : ListTile( leading: const Icon(Icons.logout_outlined), onTap: () => _logoutDialog(context), - title: Text('退出登录', style: _titleStyle), + title: Text('退出登录', style: titleStyle), ), ), ListTile( - tileColor: _getTileColor(_items.last.name), + tileColor: _getTileColor(theme, _items.last.name), onTap: () => _toPage(_items.last.name), leading: Icon(_items.last.icon), - title: Text(_items.last.title, style: _titleStyle), + title: Text(_items.last.title, style: titleStyle), ), SizedBox(height: MediaQuery.paddingOf(context).bottom + 80), ], @@ -234,9 +231,10 @@ class _SettingPageState extends State { return Accounts.deleteAll(result); } - await showDialog( + showDialog( context: context, builder: (context) { + final theme = Theme.of(context); return AlertDialog( title: const Text('提示'), content: Text( @@ -247,7 +245,7 @@ class _SettingPageState extends State { child: Text( '点错了', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -258,7 +256,7 @@ class _SettingPageState extends State { }, child: Text( '仅登出', - style: TextStyle(color: Theme.of(context).colorScheme.error), + style: TextStyle(color: theme.colorScheme.error), ), ), TextButton( @@ -281,7 +279,7 @@ class _SettingPageState extends State { }); } - Widget get _buildSearchItem => Padding( + Widget _buildSearchItem(ThemeData theme) => Padding( padding: const EdgeInsets.only(left: 16, right: 16, bottom: 5), child: InkWell( onTap: () => Get.toNamed('/settingsSearch'), @@ -290,7 +288,7 @@ class _SettingPageState extends State { padding: const EdgeInsets.symmetric(vertical: 6), decoration: BoxDecoration( borderRadius: BorderRadius.circular(50), - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, ), child: Center( child: Row( diff --git a/lib/pages/setting/widgets/multi_select_dialog.dart b/lib/pages/setting/widgets/multi_select_dialog.dart index 0f487f07..351e1b2b 100644 --- a/lib/pages/setting/widgets/multi_select_dialog.dart +++ b/lib/pages/setting/widgets/multi_select_dialog.dart @@ -27,6 +27,7 @@ class _MultiSelectDialogState extends State> { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return AlertDialog( clipBehavior: Clip.hardEdge, title: Text(widget.title), @@ -43,7 +44,7 @@ class _MultiSelectDialogState extends State> { controlAffinity: ListTileControlAffinity.leading, title: Text( i.value, - style: Theme.of(context).textTheme.titleMedium!, + style: theme.textTheme.titleMedium!, ), onChanged: (value) { isChecked @@ -63,7 +64,7 @@ class _MultiSelectDialogState extends State> { child: Text( '取消', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), diff --git a/lib/pages/setting/widgets/select_item.dart b/lib/pages/setting/widgets/select_item.dart index 85712641..9064fa1e 100644 --- a/lib/pages/setting/widgets/select_item.dart +++ b/lib/pages/setting/widgets/select_item.dart @@ -91,10 +91,9 @@ class _SetSelectItemState extends State { @override Widget build(BuildContext context) { - TextStyle subTitleStyle = Theme.of(context) - .textTheme - .labelMedium! - .copyWith(color: Theme.of(context).colorScheme.outline); + final theme = Theme.of(context); + TextStyle subTitleStyle = + theme.textTheme.labelMedium!.copyWith(color: theme.colorScheme.outline); return ListTile( onTap: () {}, title: Text(widget.title!), diff --git a/lib/pages/setting/widgets/switch_item.dart b/lib/pages/setting/widgets/switch_item.dart index e29ef8d7..0d391265 100644 --- a/lib/pages/setting/widgets/switch_item.dart +++ b/lib/pages/setting/widgets/switch_item.dart @@ -59,7 +59,7 @@ class _SetSwitchItemState extends State { setVal(); } - void switchChange(value) async { + void switchChange(ThemeData theme, value) async { if (widget.setKey == SettingBoxKey.badCertificateCallback && (value ?? !val)) { showDialog( @@ -73,7 +73,7 @@ class _SetSwitchItemState extends State { child: Text( '取消', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -111,22 +111,21 @@ class _SetSwitchItemState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); TextStyle titleStyle = widget.titleStyle ?? - Theme.of(context).textTheme.titleMedium!.copyWith( - color: widget.onTap != null && !val - ? Theme.of(context).colorScheme.outline - : null, - ); - TextStyle subTitleStyle = Theme.of(context) - .textTheme - .labelMedium! - .copyWith(color: Theme.of(context).colorScheme.outline); + theme.textTheme.titleMedium!.copyWith( + color: + widget.onTap != null && !val ? theme.colorScheme.outline : null, + ); + TextStyle subTitleStyle = + theme.textTheme.labelMedium!.copyWith(color: theme.colorScheme.outline); return ListTile( contentPadding: widget.contentPadding, enabled: widget.onTap != null ? val : true, enableFeedback: true, - onTap: () => - widget.onTap != null ? widget.onTap?.call() : switchChange(null), + onTap: () => widget.onTap != null + ? widget.onTap?.call() + : switchChange(theme, null), title: Text(widget.title!, style: titleStyle), subtitle: widget.subtitle != null ? Text(widget.subtitle!, style: subTitleStyle) @@ -144,7 +143,7 @@ class _SetSwitchItemState extends State { return null; }), value: val, - onChanged: switchChange, + onChanged: (value) => switchChange(theme, value), ), ), ); diff --git a/lib/pages/share/view.dart b/lib/pages/share/view.dart index 7aa8e833..73e0f401 100644 --- a/lib/pages/share/view.dart +++ b/lib/pages/share/view.dart @@ -73,6 +73,7 @@ class _SharePanelState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Padding( padding: const EdgeInsets.all(12) + MediaQuery.paddingOf(context) + @@ -141,15 +142,12 @@ class _SharePanelState extends State { width: 50, height: 50, decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .primary + color: theme.colorScheme.primary .withOpacity(0.3), shape: BoxShape.circle, border: Border.all( width: 1.5, - color: - Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), child: Icon( @@ -195,15 +193,11 @@ class _SharePanelState extends State { height: 40, decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context) - .colorScheme - .secondaryContainer, + color: theme.colorScheme.secondaryContainer, ), child: Icon( Icons.person_add_alt, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + color: theme.colorScheme.onSecondaryContainer, ), ), ), @@ -236,7 +230,7 @@ class _SharePanelState extends State { isDense: true, contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - fillColor: Theme.of(context).colorScheme.onInverseSurface, + fillColor: theme.colorScheme.onInverseSurface, ), ), ), diff --git a/lib/pages/subscription/widgets/item.dart b/lib/pages/subscription/widgets/item.dart index 8272f403..4029c917 100644 --- a/lib/pages/subscription/widgets/item.dart +++ b/lib/pages/subscription/widgets/item.dart @@ -29,7 +29,6 @@ class SubItem extends StatelessWidget { }, ), onLongPress: () => imageSaveDialog( - context: context, title: subFolderItem.title, cover: subFolderItem.cover, ), @@ -65,6 +64,7 @@ class SubItem extends StatelessWidget { } Widget videoContent(context) { + final theme = Theme.of(context); // subFolderItem.type == 11:播单 // subFolderItem.type == 21:合集 // 其它:其它 @@ -91,8 +91,8 @@ class SubItem extends StatelessWidget { '[$typeString] UP主:${subFolderItem.upper!.name!}', textAlign: TextAlign.start, style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), ), const SizedBox(height: 2), @@ -100,8 +100,8 @@ class SubItem extends StatelessWidget { '${subFolderItem.mediaCount}个视频', textAlign: TextAlign.start, style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), ), const Spacer(), @@ -116,7 +116,7 @@ class SubItem extends StatelessWidget { child: IconButton( onPressed: () => cancelSub(subFolderItem), style: TextButton.styleFrom( - foregroundColor: Theme.of(context).colorScheme.outline, + foregroundColor: theme.colorScheme.outline, padding: const EdgeInsets.fromLTRB(0, 0, 0, 0), ), icon: const Icon(Icons.delete_outline, size: 18), diff --git a/lib/pages/subscription_detail/view.dart b/lib/pages/subscription_detail/view.dart index 4683db1b..1252dbf9 100644 --- a/lib/pages/subscription_detail/view.dart +++ b/lib/pages/subscription_detail/view.dart @@ -44,6 +44,7 @@ class _SubDetailPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( body: SafeArea( top: false, @@ -52,8 +53,8 @@ class _SubDetailPageState extends State { controller: _subDetailController.scrollController, physics: const AlwaysScrollableScrollPhysics(), slivers: [ - _buildAppBar, - _buildCount, + _buildAppBar(theme), + _buildCount(theme), Obx(() => _buildBody(_subDetailController.loadingState.value)), ], ), @@ -100,15 +101,15 @@ class _SubDetailPageState extends State { }; } - Widget get _buildCount => SliverToBoxAdapter( + Widget _buildCount(ThemeData theme) => SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: 12, bottom: 8, left: 14), child: Obx( () => Text( '共${_subDetailController.mediaCount}条视频', style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, letterSpacing: 1, ), ), @@ -116,7 +117,7 @@ class _SubDetailPageState extends State { ), ); - Widget get _buildAppBar => SliverAppBar( + Widget _buildAppBar(ThemeData theme) => SliverAppBar( expandedHeight: 210 - MediaQuery.paddingOf(context).top, pinned: true, title: Obx( @@ -132,11 +133,11 @@ class _SubDetailPageState extends State { _subDetailController.item.title!, maxLines: 1, overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, ), Text( '共${_subDetailController.mediaCount.value}条视频', - style: Theme.of(context).textTheme.labelMedium, + style: theme.textTheme.labelMedium, ) ], ), @@ -149,7 +150,7 @@ class _SubDetailPageState extends State { decoration: BoxDecoration( border: Border( bottom: BorderSide( - color: Theme.of(context).dividerColor.withOpacity(0.2), + color: theme.dividerColor.withOpacity(0.2), ), ), ), @@ -180,10 +181,7 @@ class _SubDetailPageState extends State { Text( _subDetailController.item.title!, style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .titleMedium! - .fontSize, + fontSize: theme.textTheme.titleMedium!.fontSize, fontWeight: FontWeight.bold), ), const SizedBox(height: 4), @@ -199,8 +197,7 @@ class _SubDetailPageState extends State { }, child: Text( _subDetailController.item.upper!.name!, - style: TextStyle( - color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), ), ), const SizedBox(height: 4), @@ -209,7 +206,7 @@ class _SubDetailPageState extends State { '${Utils.numFormat(_subDetailController.playCount.value)}次播放', style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), diff --git a/lib/pages/subscription_detail/widget/sub_video_card.dart b/lib/pages/subscription_detail/widget/sub_video_card.dart index 2e1880a8..8932a825 100644 --- a/lib/pages/subscription_detail/widget/sub_video_card.dart +++ b/lib/pages/subscription_detail/widget/sub_video_card.dart @@ -38,7 +38,6 @@ class SubVideoCardH extends StatelessWidget { ); }, onLongPress: () => imageSaveDialog( - context: context, title: videoItem.title, cover: videoItem.cover, ), diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index f297c653..72a86e2b 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -128,79 +128,76 @@ class _VideoInfoState extends State { late final _horizontalMemberPage = GStorage.horizontalMemberPage; - Widget _buildVideoTitle([bool isExpand = false]) => videoDetailCtr - .enableSponsorBlock - ? Obx( - () => Text.rich( - TextSpan( - children: [ - if (videoDetailCtr.videoLabel.value.isNotEmpty) ...[ - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 4, - vertical: 2, - ), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, - borderRadius: BorderRadius.circular(4), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Stack( - alignment: Alignment.center, + Widget _buildVideoTitle(ThemeData theme, [bool isExpand = false]) => + videoDetailCtr.enableSponsorBlock + ? Obx( + () => Text.rich( + TextSpan( + children: [ + if (videoDetailCtr.videoLabel.value.isNotEmpty) ...[ + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 4, + vertical: 2, + ), + decoration: BoxDecoration( + color: theme.colorScheme.secondaryContainer, + borderRadius: BorderRadius.circular(4), + ), + child: Row( + mainAxisSize: MainAxisSize.min, children: [ - Icon( - Icons.shield_outlined, - size: 16, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + Stack( + alignment: Alignment.center, + children: [ + Icon( + Icons.shield_outlined, + size: 16, + color: + theme.colorScheme.onSecondaryContainer, + ), + Icon( + Icons.play_arrow_rounded, + size: 12, + color: + theme.colorScheme.onSecondaryContainer, + ), + ], ), - Icon( - Icons.play_arrow_rounded, - size: 12, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + Text( + videoDetailCtr.videoLabel.value, + textScaler: TextScaler.linear(1), + strutStyle: StrutStyle(leading: 0, height: 1), + style: TextStyle( + height: 1, + fontSize: 13, + color: theme.colorScheme.onSecondaryContainer, + ), ), ], ), - Text( - videoDetailCtr.videoLabel.value, - textScaler: TextScaler.linear(1), - strutStyle: StrutStyle(leading: 0, height: 1), - style: TextStyle( - height: 1, - fontSize: 13, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, - ), - ), - ], + ), ), - ), - ), - TextSpan(text: ' '), - ], - TextSpan( - text: '${videoDetail.title ?? videoItem['title'] ?? ''}'), - ], - ), - maxLines: isExpand ? null : 2, - overflow: isExpand ? null : TextOverflow.ellipsis, - style: const TextStyle(fontSize: 16), - ), - ) - : Text( - '${videoDetail.title ?? videoItem['title'] ?? ''}', - maxLines: isExpand ? null : 2, - overflow: isExpand ? null : TextOverflow.ellipsis, - style: const TextStyle(fontSize: 16), - ); + TextSpan(text: ' '), + ], + TextSpan( + text: + '${videoDetail.title ?? videoItem['title'] ?? ''}'), + ], + ), + maxLines: isExpand ? null : 2, + overflow: isExpand ? null : TextOverflow.ellipsis, + style: const TextStyle(fontSize: 16), + ), + ) + : Text( + '${videoDetail.title ?? videoItem['title'] ?? ''}', + maxLines: isExpand ? null : 2, + overflow: isExpand ? null : TextOverflow.ellipsis, + style: const TextStyle(fontSize: 16), + ); void handleState(Future Function() action) async { if (isProcessing.not) { @@ -263,7 +260,7 @@ class _VideoInfoState extends State { @override Widget build(BuildContext context) { - final ThemeData themeData = Theme.of(context); + final ThemeData theme = Theme.of(context); return SliverLayoutBuilder( builder: (BuildContext context, SliverConstraints constraints) { bool isHorizontal = context.orientation == Orientation.landscape && @@ -350,8 +347,7 @@ class _VideoInfoState extends State { '${Utils.numFormat(videoIntroController.userStat['follower'])}粉丝 ${videoIntroController.userStat['archive_count'] != null ? '${Utils.numFormat(videoIntroController.userStat['archive_count'])}视频' : ''}', style: TextStyle( fontSize: 12, - color: - themeData.colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -362,7 +358,7 @@ class _VideoInfoState extends State { ), ), ), - followButton(context, themeData), + followButton(context, theme), ] else Expanded( child: SelfSizedHorizontalList( @@ -409,9 +405,8 @@ class _VideoInfoState extends State { child: Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: Theme.of(context) - .colorScheme - .surface, + color: + theme.colorScheme.surface, ), child: Icon( Icons.offline_bolt, @@ -461,16 +456,14 @@ class _VideoInfoState extends State { const EdgeInsets.all( 2), decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme + color: theme.colorScheme .secondaryContainer, shape: BoxShape.circle, ), child: Icon( MdiIcons.plus, size: 16, - color: Theme.of(context) - .colorScheme + color: theme.colorScheme .onSecondaryContainer, ), ), @@ -508,9 +501,7 @@ class _VideoInfoState extends State { videoItem['staff'][index].title, style: TextStyle( fontSize: 12, - color: Theme.of(context) - .colorScheme - .outline, + color: theme.colorScheme.outline, ), ), ], @@ -537,7 +528,7 @@ class _VideoInfoState extends State { Utils.copyText( '${videoDetail.title ?? videoItem['title'] ?? ''}'); }, - child: _buildVideoTitle(), + child: _buildVideoTitle(theme), ), expanded: GestureDetector( onLongPress: () { @@ -545,7 +536,7 @@ class _VideoInfoState extends State { Utils.copyText( '${videoDetail.title ?? videoItem['title'] ?? ''}'); }, - child: _buildVideoTitle(true), + child: _buildVideoTitle(theme, true), ), theme: const ExpandableThemeData( animationDuration: Duration(milliseconds: 300), @@ -566,7 +557,7 @@ class _VideoInfoState extends State { value: Utils.numFormat(!widget.loadingStatus ? videoDetail.stat?.view ?? '-' : videoItem['stat']?.view ?? '-'), - textColor: themeData.colorScheme.outline, + textColor: theme.colorScheme.outline, ), const SizedBox(width: 10), StatDanMu( @@ -575,7 +566,7 @@ class _VideoInfoState extends State { value: Utils.numFormat(!widget.loadingStatus ? videoDetail.stat?.danmaku ?? '-' : videoItem['stat']?.danmu ?? '-'), - textColor: themeData.colorScheme.outline, + textColor: theme.colorScheme.outline, ), const SizedBox(width: 10), Text( @@ -586,7 +577,7 @@ class _VideoInfoState extends State { formatType: 'detail'), style: TextStyle( fontSize: 12, - color: themeData.colorScheme.outline, + color: theme.colorScheme.outline, ), ), if (MineController.anonymity.value) ...[ @@ -594,7 +585,7 @@ class _VideoInfoState extends State { Icon( MdiIcons.incognito, size: 15, - color: themeData.colorScheme.outline, + color: theme.colorScheme.outline, semanticLabel: '无痕', ), ], @@ -605,7 +596,7 @@ class _VideoInfoState extends State { '${videoIntroController.total.value}人在看', style: TextStyle( fontSize: 12, - color: themeData.colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -656,7 +647,7 @@ class _VideoInfoState extends State { child: Icon( size: 13, Icons.error_outline, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), WidgetSpan(child: SizedBox(width: 2)), @@ -668,7 +659,7 @@ class _VideoInfoState extends State { ), style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ], @@ -689,7 +680,7 @@ class _VideoInfoState extends State { videoIntroController.videoDetail.value.bvid ?? '', style: TextStyle( fontSize: 14, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ), @@ -702,7 +693,7 @@ class _VideoInfoState extends State { ), TextSpan( children: [ - buildContent(context, + buildContent(theme, videoIntroController.videoDetail.value), ], ), @@ -1013,7 +1004,7 @@ class _VideoInfoState extends State { ]); } - InlineSpan buildContent(BuildContext context, VideoDetailData content) { + InlineSpan buildContent(ThemeData theme, VideoDetailData content) { final List descV2 = content.descV2!; // type // 1 普通文本 @@ -1039,8 +1030,7 @@ class _VideoInfoState extends State { spanChildren.add( TextSpan( text: matchStr, - style: TextStyle( - color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), recognizer: TapGestureRecognizer() ..onTap = () { PiliScheme.videoPush(aid, null); @@ -1057,8 +1047,7 @@ class _VideoInfoState extends State { spanChildren.add( TextSpan( text: matchStr, - style: TextStyle( - color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), recognizer: TapGestureRecognizer() ..onTap = () { PiliScheme.videoPush(null, matchStr); @@ -1072,8 +1061,7 @@ class _VideoInfoState extends State { spanChildren.add( TextSpan( text: matchStr, - style: - TextStyle(color: Theme.of(context).colorScheme.primary), + style: TextStyle(color: theme.colorScheme.primary), recognizer: TapGestureRecognizer() ..onTap = () { try { @@ -1094,8 +1082,7 @@ class _VideoInfoState extends State { ); return TextSpan(children: spanChildren); case 2: - final Color colorSchemePrimary = - Theme.of(context).colorScheme.primary; + final Color colorSchemePrimary = theme.colorScheme.primary; final String heroTag = Utils.makeHeroTag(currentDesc.bizId); return TextSpan( text: '@${currentDesc.rawText}', diff --git a/lib/pages/video/detail/introduction/widgets/action_item.dart b/lib/pages/video/detail/introduction/widgets/action_item.dart index 8f1facf7..f7633d06 100644 --- a/lib/pages/video/detail/introduction/widgets/action_item.dart +++ b/lib/pages/video/detail/introduction/widgets/action_item.dart @@ -127,10 +127,13 @@ class ActionItemState extends State @override Widget build(BuildContext context) { - return widget.expand == false ? _buildItem : Expanded(child: _buildItem); + final theme = Theme.of(context); + return widget.expand == false + ? _buildItem(theme) + : Expanded(child: _buildItem(theme)); } - Widget get _buildItem => Semantics( + Widget _buildItem(ThemeData theme) => Semantics( label: (widget.text ?? "") + (widget.selectStatus ? "已" : "") + widget.semanticsLabel, @@ -160,7 +163,7 @@ class ActionItemState extends State CustomPaint( size: const Size(28, 28), painter: _ArcPainter( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, sweepAngle: _animation!.value, ), ) @@ -172,9 +175,8 @@ class ActionItemState extends State : widget.icon.icon, size: 18, color: widget.selectStatus - ? Theme.of(context).colorScheme.primary - : widget.icon.color ?? - Theme.of(context).colorScheme.outline, + ? theme.colorScheme.primary + : widget.icon.color ?? theme.colorScheme.outline, ), ], ), @@ -193,10 +195,9 @@ class ActionItemState extends State key: ValueKey(widget.text!), style: TextStyle( color: widget.selectStatus - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, - fontSize: - Theme.of(context).textTheme.labelSmall!.fontSize, + ? theme.colorScheme.primary + : theme.colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize, ), semanticsLabel: "", ), diff --git a/lib/pages/video/detail/introduction/widgets/action_row_item.dart b/lib/pages/video/detail/introduction/widgets/action_row_item.dart index f4cd45d8..0c4aba27 100644 --- a/lib/pages/video/detail/introduction/widgets/action_row_item.dart +++ b/lib/pages/video/detail/introduction/widgets/action_row_item.dart @@ -23,10 +23,11 @@ class ActionRowItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Material( color: selectStatus - ? Theme.of(context).colorScheme.primaryContainer.withOpacity(0.6) - : Theme.of(context).highlightColor.withOpacity(0.2), + ? theme.colorScheme.primaryContainer.withOpacity(0.6) + : theme.highlightColor.withOpacity(0.2), borderRadius: const BorderRadius.all(Radius.circular(30)), clipBehavior: Clip.hardEdge, child: InkWell( @@ -47,8 +48,8 @@ class ActionRowItem extends StatelessWidget { Icon(icon!.icon!, size: 13, color: selectStatus - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSecondaryContainer), + ? theme.colorScheme.primary + : theme.colorScheme.onSecondaryContainer), const SizedBox(width: 6), ], AnimatedOpacity( @@ -64,11 +65,8 @@ class ActionRowItem extends StatelessWidget { text ?? '', key: ValueKey(text ?? ''), style: TextStyle( - color: selectStatus - ? Theme.of(context).colorScheme.primary - : null, - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize), + color: selectStatus ? theme.colorScheme.primary : null, + fontSize: theme.textTheme.labelMedium!.fontSize), ), ), ), diff --git a/lib/pages/video/detail/introduction/widgets/create_fav_page.dart b/lib/pages/video/detail/introduction/widgets/create_fav_page.dart index c17b08cf..f74c33b9 100644 --- a/lib/pages/video/detail/introduction/widgets/create_fav_page.dart +++ b/lib/pages/video/detail/introduction/widgets/create_fav_page.dart @@ -61,6 +61,7 @@ class _CreateFavPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Scaffold( appBar: AppBar( title: Text(_mediaId != null ? '编辑' : '创建'), @@ -94,7 +95,7 @@ class _CreateFavPageState extends State { ), body: _mediaId != null ? _titleController.text.isNotEmpty - ? _buildBody + ? _buildBody(theme) : _errMsg?.isNotEmpty == true ? Center( child: CustomScrollView( @@ -108,11 +109,11 @@ class _CreateFavPageState extends State { ), ) : Center(child: CircularProgressIndicator()) - : _buildBody, + : _buildBody(theme), ); } - void _pickImg() async { + void _pickImg(ThemeData theme) async { try { XFile? pickedFile = await _imagePicker.pickImage( source: ImageSource.gallery, @@ -124,9 +125,8 @@ class _CreateFavPageState extends State { uiSettings: [ AndroidUiSettings( toolbarTitle: '裁剪', - toolbarColor: Theme.of(context).colorScheme.secondaryContainer, - toolbarWidgetColor: - Theme.of(context).colorScheme.onSecondaryContainer, + toolbarColor: theme.colorScheme.secondaryContainer, + toolbarWidgetColor: theme.colorScheme.onSecondaryContainer, aspectRatioPresets: [ CropAspectRatioPreset.ratio16x9, ], @@ -167,12 +167,12 @@ class _CreateFavPageState extends State { dynamic leadingStyle = TextStyle(fontSize: 14); - Widget get _buildBody => SingleChildScrollView( + Widget _buildBody(ThemeData theme) => SingleChildScrollView( child: Column( children: [ if (_attr == null || !Utils.isDefaultFav(_attr!)) ...[ ListTile( - tileColor: Theme.of(context).colorScheme.onInverseSurface, + tileColor: theme.colorScheme.onInverseSurface, onTap: () { EasyThrottle.throttle( 'imagePicker', const Duration(milliseconds: 500), @@ -192,7 +192,7 @@ class _CreateFavPageState extends State { dense: true, onTap: () { Get.back(); - _pickImg(); + _pickImg(theme); }, title: const Text( '替换封面', @@ -217,7 +217,7 @@ class _CreateFavPageState extends State { }, ); } else { - _pickImg(); + _pickImg(theme); } }); }, @@ -248,7 +248,7 @@ class _CreateFavPageState extends State { const SizedBox(width: 10), Icon( Icons.keyboard_arrow_right, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ], ), @@ -256,7 +256,7 @@ class _CreateFavPageState extends State { const SizedBox(height: 16), ], ListTile( - tileColor: Theme.of(context).colorScheme.onInverseSurface, + tileColor: theme.colorScheme.onInverseSurface, leading: Text.rich( style: TextStyle( height: 1, @@ -269,7 +269,7 @@ class _CreateFavPageState extends State { style: TextStyle( fontSize: 14, height: 1, - color: Theme.of(context).colorScheme.error, + color: theme.colorScheme.error, ), ), TextSpan( @@ -289,7 +289,7 @@ class _CreateFavPageState extends State { style: TextStyle( fontSize: 14, color: _attr != null && Utils.isDefaultFav(_attr!) - ? Theme.of(context).colorScheme.outline + ? theme.colorScheme.outline : null, ), inputFormatters: [ @@ -300,7 +300,7 @@ class _CreateFavPageState extends State { hintText: '名称', hintStyle: TextStyle( fontSize: 14, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), border: OutlineInputBorder( borderSide: BorderSide.none, @@ -313,7 +313,7 @@ class _CreateFavPageState extends State { const SizedBox(height: 16), if (_attr == null || !Utils.isDefaultFav(_attr!)) ...[ ListTile( - tileColor: Theme.of(context).colorScheme.onInverseSurface, + tileColor: theme.colorScheme.onInverseSurface, title: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -324,9 +324,7 @@ class _CreateFavPageState extends State { text: '简介', style: TextStyle( fontSize: 14, - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, ), ), TextSpan( @@ -351,7 +349,7 @@ class _CreateFavPageState extends State { hintText: '可填写简介', hintStyle: TextStyle( fontSize: 14, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), border: OutlineInputBorder( borderSide: BorderSide.none, @@ -372,7 +370,7 @@ class _CreateFavPageState extends State { _isPublic = !_isPublic; }); }, - tileColor: Theme.of(context).colorScheme.onInverseSurface, + tileColor: theme.colorScheme.onInverseSurface, leading: Text( '公开', style: leadingStyle, diff --git a/lib/pages/video/detail/introduction/widgets/fav_panel.dart b/lib/pages/video/detail/introduction/widgets/fav_panel.dart index 564a80d5..98c06cde 100644 --- a/lib/pages/video/detail/introduction/widgets/fav_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/fav_panel.dart @@ -31,6 +31,7 @@ class _FavPanelState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return NotificationListener( onNotification: (notification) { if (notification.extent <= 1e-5) { @@ -62,7 +63,7 @@ class _FavPanelState extends State { }, icon: Icon( Icons.add, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), label: const Text('新建收藏夹'), style: TextButton.styleFrom( @@ -156,7 +157,7 @@ class _FavPanelState extends State { ), Divider( height: 1, - color: Theme.of(context).disabledColor.withOpacity(0.08), + color: theme.disabledColor.withOpacity(0.08), ), Padding( padding: EdgeInsets.only( @@ -177,9 +178,8 @@ class _FavPanelState extends State { horizontal: -1, vertical: -2, ), - foregroundColor: Theme.of(context).colorScheme.outline, - backgroundColor: - Theme.of(context).colorScheme.onInverseSurface, + foregroundColor: theme.colorScheme.outline, + backgroundColor: theme.colorScheme.onInverseSurface, ), child: const Text('取消'), ), diff --git a/lib/pages/video/detail/introduction/widgets/group_panel.dart b/lib/pages/video/detail/introduction/widgets/group_panel.dart index 6a966ca6..f5355a38 100644 --- a/lib/pages/video/detail/introduction/widgets/group_panel.dart +++ b/lib/pages/video/detail/introduction/widgets/group_panel.dart @@ -68,6 +68,7 @@ class _GroupPanelState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return NotificationListener( onNotification: (notification) { if (notification.extent <= 1e-5) { @@ -159,7 +160,7 @@ class _GroupPanelState extends State { ), Divider( height: 1, - color: Theme.of(context).disabledColor.withOpacity(0.08), + color: theme.disabledColor.withOpacity(0.08), ), Padding( padding: EdgeInsets.only( @@ -175,8 +176,8 @@ class _GroupPanelState extends State { onPressed: () => onSave(), style: TextButton.styleFrom( padding: const EdgeInsets.only(left: 30, right: 30), - foregroundColor: Theme.of(context).colorScheme.onPrimary, - backgroundColor: Theme.of(context).colorScheme.primary, + foregroundColor: theme.colorScheme.onPrimary, + backgroundColor: theme.colorScheme.primary, ), child: Text(showDefaultBtn ? '保存至默认分组' : '保存'), ), diff --git a/lib/pages/video/detail/introduction/widgets/menu_row.dart b/lib/pages/video/detail/introduction/widgets/menu_row.dart index 7b1dfc59..4558b71c 100644 --- a/lib/pages/video/detail/introduction/widgets/menu_row.dart +++ b/lib/pages/video/detail/introduction/widgets/menu_row.dart @@ -10,9 +10,10 @@ class MenuRow extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Container( width: double.infinity, - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, padding: const EdgeInsets.only(top: 9, bottom: 9, left: 12), child: SingleChildScrollView( scrollDirection: Axis.horizontal, @@ -50,11 +51,11 @@ class MenuRow extends StatelessWidget { } Widget actionRowLineItem( - BuildContext context, Function? onTap, bool? loadingStatus, String? text, + ThemeData theme, Function? onTap, bool? loadingStatus, String? text, {bool selectStatus = false}) { return Material( color: selectStatus - ? Theme.of(context).highlightColor.withOpacity(0.2) + ? theme.highlightColor.withOpacity(0.2) : Colors.transparent, borderRadius: const BorderRadius.all(Radius.circular(30)), clipBehavior: Clip.hardEdge, @@ -70,7 +71,7 @@ class MenuRow extends StatelessWidget { border: Border.all( color: selectStatus ? Colors.transparent - : Theme.of(context).highlightColor.withOpacity(0.2), + : theme.highlightColor.withOpacity(0.2), ), ), child: Row( @@ -84,8 +85,8 @@ class MenuRow extends StatelessWidget { style: TextStyle( fontSize: 13, color: selectStatus - ? Theme.of(context).colorScheme.onSurface - : Theme.of(context).colorScheme.outline), + ? theme.colorScheme.onSurface + : theme.colorScheme.outline), ), ), ], @@ -115,9 +116,10 @@ class ActionRowLineItem extends StatelessWidget { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Material( color: selectStatus - ? Theme.of(context).colorScheme.secondaryContainer + ? theme.colorScheme.secondaryContainer : Colors.transparent, borderRadius: const BorderRadius.all(Radius.circular(30)), clipBehavior: Clip.hardEdge, @@ -133,7 +135,7 @@ class ActionRowLineItem extends StatelessWidget { border: Border.all( color: selectStatus ? Colors.transparent - : Theme.of(context).colorScheme.secondaryContainer, + : theme.colorScheme.secondaryContainer, ), ), child: Row( @@ -144,8 +146,8 @@ class ActionRowLineItem extends StatelessWidget { iconData, size: 13, color: selectStatus - ? Theme.of(context).colorScheme.onSecondaryContainer - : Theme.of(context).colorScheme.outline, + ? theme.colorScheme.onSecondaryContainer + : theme.colorScheme.outline, ) else if (icon != null) icon!, @@ -157,8 +159,8 @@ class ActionRowLineItem extends StatelessWidget { style: TextStyle( fontSize: 13, color: selectStatus - ? Theme.of(context).colorScheme.onSecondaryContainer - : Theme.of(context).colorScheme.outline), + ? theme.colorScheme.onSecondaryContainer + : theme.colorScheme.outline), ), ), ], diff --git a/lib/pages/video/detail/introduction/widgets/page.dart b/lib/pages/video/detail/introduction/widgets/page.dart index 3873e644..397555e7 100644 --- a/lib/pages/video/detail/introduction/widgets/page.dart +++ b/lib/pages/video/detail/introduction/widgets/page.dart @@ -87,6 +87,7 @@ class _PagesPanelState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Column( children: [ if (widget.showEpisodes != null) @@ -102,7 +103,7 @@ class _PagesPanelState extends State { overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -145,7 +146,7 @@ class _PagesPanelState extends State { right: i != pages.length - 1 ? 10 : 0, ), child: Material( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, borderRadius: BorderRadius.circular(6), clipBehavior: Clip.hardEdge, child: InkWell( @@ -175,7 +176,7 @@ class _PagesPanelState extends State { if (isCurrentIndex) ...[ Image.asset( 'assets/images/live.png', - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, height: 12, semanticLabel: "正在播放:", ), @@ -188,8 +189,8 @@ class _PagesPanelState extends State { style: TextStyle( fontSize: 13, color: isCurrentIndex - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.onSurface, + ? theme.colorScheme.primary + : theme.colorScheme.onSurface, ), overflow: TextOverflow.ellipsis, )) diff --git a/lib/pages/video/detail/introduction/widgets/season.dart b/lib/pages/video/detail/introduction/widgets/season.dart index e0b2a51b..d18647b6 100644 --- a/lib/pages/video/detail/introduction/widgets/season.dart +++ b/lib/pages/video/detail/introduction/widgets/season.dart @@ -88,6 +88,7 @@ class _SeasonPanelState extends State { if (episodes.isEmpty) { return const SizedBox.shrink(); } + final theme = Theme.of(context); return Builder(builder: (BuildContext context) { return Container( margin: const EdgeInsets.only( @@ -96,7 +97,7 @@ class _SeasonPanelState extends State { right: 2, ), child: Material( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, borderRadius: BorderRadius.circular(6), clipBehavior: Clip.hardEdge, child: InkWell( @@ -117,14 +118,14 @@ class _SeasonPanelState extends State { Expanded( child: Text( '合集:${videoDetail.ugcSeason!.title!}', - style: Theme.of(context).textTheme.labelMedium, + style: theme.textTheme.labelMedium, overflow: TextOverflow.ellipsis, ), ), const SizedBox(width: 15), Image.asset( 'assets/images/live.png', - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, height: 12, semanticLabel: "正在播放:", ), @@ -132,7 +133,7 @@ class _SeasonPanelState extends State { Obx( () => Text( '${currentIndex.value + 1}/${episodes.length}', - style: Theme.of(context).textTheme.labelMedium, + style: theme.textTheme.labelMedium, semanticsLabel: '第${currentIndex.value + 1}集,共${episodes.length}集', ), diff --git a/lib/pages/video/detail/member/horizontal_member_page.dart b/lib/pages/video/detail/member/horizontal_member_page.dart index e7f71493..ffba12e7 100644 --- a/lib/pages/video/detail/member/horizontal_member_page.dart +++ b/lib/pages/video/detail/member/horizontal_member_page.dart @@ -78,12 +78,13 @@ class _HorizontalMemberPageState extends State { @override Widget build(BuildContext context) { + final theme = Theme.of(context); return Obx( - () => _buildUserPage(_controller.userState.value), + () => _buildUserPage(theme, _controller.userState.value), ); } - Widget _buildUserPage(LoadingState userState) { + Widget _buildUserPage(ThemeData theme, LoadingState userState) { return switch (userState) { Loading() => loadingWidget, Success() => Column( @@ -102,10 +103,11 @@ class _HorizontalMemberPageState extends State { const SizedBox(width: 16), ], ), - _buildUserInfo(userState.response), + _buildUserInfo(theme, userState.response), const SizedBox(height: 5), Expanded( - child: Obx(() => _buildVideoList(_controller.loadingState.value)), + child: Obx( + () => _buildVideoList(theme, _controller.loadingState.value)), ), ], ), @@ -120,13 +122,13 @@ class _HorizontalMemberPageState extends State { }; } - Widget get _buildSliverHeader { + Widget _buildSliverHeader(ThemeData theme) { return SliverPersistentHeader( pinned: false, floating: true, delegate: CustomSliverPersistentHeaderDelegate( extent: 40, - bgColor: Theme.of(context).colorScheme.surface, + bgColor: theme.colorScheme.surface, child: Container( height: 40, padding: const EdgeInsets.fromLTRB(12, 0, 6, 0), @@ -153,14 +155,14 @@ class _HorizontalMemberPageState extends State { icon: Icon( Icons.sort, size: 16, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), label: Obx( () => Text( _controller.order.value == 'pubdate' ? '最新发布' : '最多播放', style: TextStyle( fontSize: 13, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), ), @@ -173,7 +175,7 @@ class _HorizontalMemberPageState extends State { ); } - Widget _buildVideoList(LoadingState loadingState) { + Widget _buildVideoList(ThemeData theme, LoadingState loadingState) { return switch (loadingState) { Loading() => loadingWidget, Success() => Material( @@ -185,7 +187,7 @@ class _HorizontalMemberPageState extends State { parent: ClampingScrollPhysics(), ), slivers: [ - _buildSliverHeader, + _buildSliverHeader(theme), SliverPadding( padding: EdgeInsets.only( bottom: MediaQuery.of(context).padding.bottom + 80, @@ -234,19 +236,19 @@ class _HorizontalMemberPageState extends State { }; } - Widget _buildUserInfo(MemberInfoModel memberInfoModel) { + Widget _buildUserInfo(ThemeData theme, MemberInfoModel memberInfoModel) { return Row( children: [ const SizedBox(width: 16), _buildAvatar(memberInfoModel.face), const SizedBox(width: 10), - Expanded(child: _buildInfo(memberInfoModel)), + Expanded(child: _buildInfo(theme, memberInfoModel)), const SizedBox(width: 16), ], ); } - _buildInfo(MemberInfoModel memberInfoModel) => Column( + _buildInfo(ThemeData theme, MemberInfoModel memberInfoModel) => Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -281,6 +283,7 @@ class _HorizontalMemberPageState extends State { children: List.generate(5, (index) { if (index % 2 == 0) { return _buildChildInfo( + theme: theme, title: const ['粉丝', '关注', '获赞'][index ~/ 2], num: index == 0 ? _controller.userStat['follower'] != null @@ -307,7 +310,7 @@ class _HorizontalMemberPageState extends State { width: 20, child: VerticalDivider( width: 1, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ); } @@ -321,10 +324,10 @@ class _HorizontalMemberPageState extends State { child: FilledButton.tonal( style: FilledButton.styleFrom( backgroundColor: memberInfoModel.isFollowed == true - ? Theme.of(context).colorScheme.onInverseSurface + ? theme.colorScheme.onInverseSurface : null, foregroundColor: memberInfoModel.isFollowed == true - ? Theme.of(context).colorScheme.outline + ? theme.colorScheme.outline : null, padding: const EdgeInsets.all(0), visualDensity: const VisualDensity( @@ -389,6 +392,7 @@ class _HorizontalMemberPageState extends State { ); Widget _buildChildInfo({ + required ThemeData theme, required String title, required dynamic num, required VoidCallback onTap, @@ -399,7 +403,7 @@ class _HorizontalMemberPageState extends State { '$num$title', style: TextStyle( fontSize: 14, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ); diff --git a/lib/pages/video/detail/note/note_list_page.dart b/lib/pages/video/detail/note/note_list_page.dart index 6a362830..23352b7b 100644 --- a/lib/pages/video/detail/note/note_list_page.dart +++ b/lib/pages/video/detail/note/note_list_page.dart @@ -50,87 +50,91 @@ class _NoteListPageState extends CommonSlidePageState { } @override - Widget get buildPage => Scaffold( - key: _key, + Widget buildPage(ThemeData theme) { + return Scaffold( + key: _key, + resizeToAvoidBottomInset: false, + body: Scaffold( + backgroundColor: Colors.transparent, resizeToAvoidBottomInset: false, - body: Scaffold( - backgroundColor: Colors.transparent, - resizeToAvoidBottomInset: false, - appBar: AppBar( - automaticallyImplyLeading: false, - titleSpacing: 16, - toolbarHeight: 45, - title: Obx( - () => Text( - '笔记${_controller.count.value == -1 ? '' : '(${_controller.count.value})'}'), - ), - bottom: PreferredSize( - preferredSize: Size.fromHeight(1), - child: Divider( - height: 1, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), - ), - ), - actions: [ - iconButton( - context: context, - tooltip: '关闭', - icon: Icons.clear, - onPressed: Get.back, - size: 32, - ), - const SizedBox(width: 16), - ], + appBar: AppBar( + automaticallyImplyLeading: false, + titleSpacing: 16, + toolbarHeight: 45, + title: Obx( + () => Text( + '笔记${_controller.count.value == -1 ? '' : '(${_controller.count.value})'}'), ), - body: enableSlide - ? slideList(Obx(() => _buildBody(_controller.loadingState.value))) - : Obx(() => _buildBody(_controller.loadingState.value)), - bottomNavigationBar: Container( - padding: EdgeInsets.only( - left: 12, - right: 12, - top: 6, - bottom: MediaQuery.paddingOf(context).bottom + 6, + bottom: PreferredSize( + preferredSize: Size.fromHeight(1), + child: Divider( + height: 1, + color: theme.colorScheme.outline.withOpacity(0.1), ), - width: double.infinity, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onInverseSurface, - border: Border( - top: BorderSide( - width: 0.5, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), - ), + ), + actions: [ + iconButton( + context: context, + tooltip: '关闭', + icon: Icons.clear, + onPressed: Get.back, + size: 32, + ), + const SizedBox(width: 16), + ], + ), + body: enableSlide + ? slideList(theme, + Obx(() => _buildBody(theme, _controller.loadingState.value))) + : Obx(() => _buildBody(theme, _controller.loadingState.value)), + bottomNavigationBar: Container( + padding: EdgeInsets.only( + left: 12, + right: 12, + top: 6, + bottom: MediaQuery.paddingOf(context).bottom + 6, + ), + width: double.infinity, + decoration: BoxDecoration( + color: theme.colorScheme.onInverseSurface, + border: Border( + top: BorderSide( + width: 0.5, + color: theme.colorScheme.outline.withOpacity(0.1), ), ), - child: FilledButton.tonal( - style: FilledButton.styleFrom( - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - padding: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(6), - ), + ), + child: FilledButton.tonal( + style: FilledButton.styleFrom( + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + padding: EdgeInsets.zero, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), ), - onPressed: () { - if (!Accounts.main.isLogin) { - SmartDialog.showToast('账号未登录'); - return; - } - _key.currentState?.showBottomSheet( - (context) => WebviewPageNew( - oid: widget.oid, - title: widget.title, - url: - 'https://www.bilibili.com/h5/note-app?oid=${widget.oid}&pagefrom=ugcvideo&is_stein_gate=${widget.isStein ? 1 : 0}', - ), - ); - }, - child: const Text('开始记笔记'), ), + onPressed: () { + if (!Accounts.main.isLogin) { + SmartDialog.showToast('账号未登录'); + return; + } + _key.currentState?.showBottomSheet( + (context) => WebviewPageNew( + oid: widget.oid, + title: widget.title, + url: + 'https://www.bilibili.com/h5/note-app?oid=${widget.oid}&pagefrom=ugcvideo&is_stein_gate=${widget.isStein ? 1 : 0}', + ), + ); + }, + child: const Text('开始记笔记'), ), ), - ); + ), + ); + } - Widget _buildBody(LoadingState?> loadingState) { + Widget _buildBody( + ThemeData theme, LoadingState?> loadingState) { return switch (loadingState) { Loading() => CustomScrollView( physics: const NeverScrollableScrollPhysics(), @@ -158,15 +162,12 @@ class _NoteListPageState extends CommonSlidePageState { _controller.onLoadMore(); } return _itemWidget( - context, loadingState.response![index]); + context, theme, loadingState.response![index]); }, itemCount: loadingState.response!.length, separatorBuilder: (context, index) => Divider( height: 1, - color: Theme.of(context) - .colorScheme - .outline - .withOpacity(0.1), + color: theme.colorScheme.outline.withOpacity(0.1), ), ), SliverToBoxAdapter( @@ -193,7 +194,7 @@ class _NoteListPageState extends CommonSlidePageState { ); } -Widget _itemWidget(BuildContext context, dynamic item) { +Widget _itemWidget(BuildContext context, ThemeData theme, dynamic item) { return InkWell( onTap: () { if (item['web_url'] != null && item['web_url'] != '') { @@ -235,7 +236,7 @@ Widget _itemWidget(BuildContext context, dynamic item) { 0 && item['author']?['vip_info']?['type'] == 2 ? context.vipColor - : Theme.of(context).colorScheme.outline, + : theme.colorScheme.outline, fontSize: 13, ), ), @@ -251,7 +252,7 @@ Widget _itemWidget(BuildContext context, dynamic item) { Text( item['pubtime'], style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, fontSize: 12, ), ), @@ -261,18 +262,16 @@ Widget _itemWidget(BuildContext context, dynamic item) { item['summary'], style: TextStyle( height: 1.75, - fontSize: - Theme.of(context).textTheme.bodyMedium!.fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, ), ), if (item['web_url'] != null && item['web_url'] != '') Text( '查看全部', style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, height: 1.75, - fontSize: - Theme.of(context).textTheme.bodyMedium!.fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, ), ), ], diff --git a/lib/pages/video/detail/post_panel/post_panel.dart b/lib/pages/video/detail/post_panel/post_panel.dart index 45bee52e..0cf53724 100644 --- a/lib/pages/video/detail/post_panel/post_panel.dart +++ b/lib/pages/video/detail/post_panel/post_panel.dart @@ -50,352 +50,363 @@ class _PostPanelState extends CommonCollapseSlidePageState { plPlayerController.position.value.inMilliseconds / 1000; @override - Widget get buildPage => Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - automaticallyImplyLeading: false, - titleSpacing: 16, - title: const Text('提交片段'), - actions: [ - iconButton( - context: context, - tooltip: '添加片段', - onPressed: () { - setState(() { - list?.insert( - 0, - PostSegmentModel( - segment: Pair( - first: 0, - second: currentPos, - ), - category: SegmentType.sponsor, - actionType: ActionType.skip, + Widget buildPage(ThemeData theme) { + return Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + automaticallyImplyLeading: false, + titleSpacing: 16, + title: const Text('提交片段'), + actions: [ + iconButton( + context: context, + tooltip: '添加片段', + onPressed: () { + setState(() { + list?.insert( + 0, + PostSegmentModel( + segment: Pair( + first: 0, + second: currentPos, ), - ); - }); - }, - icon: Icons.add, - ), - const SizedBox(width: 10), - iconButton( - context: context, - tooltip: '关闭', - onPressed: Get.back, - icon: Icons.close, - ), - const SizedBox(width: 16), - ], - ), - body: enableSlide ? slideList() : buildList, - ); + category: SegmentType.sponsor, + actionType: ActionType.skip, + ), + ); + }); + }, + icon: Icons.add, + ), + const SizedBox(width: 10), + iconButton( + context: context, + tooltip: '关闭', + onPressed: Get.back, + icon: Icons.close, + ), + const SizedBox(width: 16), + ], + ), + body: enableSlide ? slideList(theme) : buildList(theme), + ); + } @override - Widget get buildList => list?.isNotEmpty == true - ? Stack( - children: [ - SingleChildScrollView( - controller: ScrollController(), - physics: const AlwaysScrollableScrollPhysics(), - child: Column( - children: [ - ...List.generate( - list!.length, - (index) => Stack( - clipBehavior: Clip.none, - children: [ - Container( - width: double.infinity, - margin: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 5, - ), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: - Theme.of(context).colorScheme.onInverseSurface, - borderRadius: BorderRadius.circular(12), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (list![index].actionType != - ActionType.full) ...[ + Widget buildList(ThemeData theme) { + return list?.isNotEmpty == true + ? Stack( + children: [ + SingleChildScrollView( + controller: ScrollController(), + physics: const AlwaysScrollableScrollPhysics(), + child: Column( + children: [ + ...List.generate( + list!.length, + (index) => Stack( + clipBehavior: Clip.none, + children: [ + Container( + width: double.infinity, + margin: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 5, + ), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: theme.colorScheme.onInverseSurface, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (list![index].actionType != + ActionType.full) ...[ + Wrap( + runSpacing: 8, + spacing: 16, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + children: segmentWidget( + theme, + isFirst: true, + index: index, + ), + ), + if (list![index].category != + SegmentType.poi_highlight) + Row( + mainAxisSize: MainAxisSize.min, + children: segmentWidget( + theme, + isFirst: false, + index: index, + ), + ), + ], + ), + const SizedBox(height: 8), + ], Wrap( runSpacing: 8, spacing: 16, children: [ Row( mainAxisSize: MainAxisSize.min, - children: segmentWidget( - isFirst: true, - index: index, - ), - ), - if (list![index].category != - SegmentType.poi_highlight) - Row( - mainAxisSize: MainAxisSize.min, - children: segmentWidget( - isFirst: false, - index: index, + children: [ + const Text('分类: '), + PopupMenuButton( + initialValue: list![index].category, + onSelected: (item) async { + list![index].category = item; + List constraintList = + segmentType2ActionType(item); + if (constraintList + .contains( + list![index].actionType) + .not) { + list![index].actionType = + constraintList.first; + } + switch (item) { + case SegmentType.poi_highlight: + updateSegment( + isFirst: false, + index: index, + value: list![index] + .segment + .first, + ); + break; + case SegmentType.exclusive_access: + updateSegment( + isFirst: true, + index: index, + value: 0, + ); + break; + case _: + } + setState(() {}); + }, + itemBuilder: (context) => SegmentType + .values + .map((item) => + PopupMenuItem( + value: item, + child: Text(item.title), + )) + .toList(), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + list![index].category.title, + style: TextStyle( + height: 1, + fontSize: 14, + color: theme + .colorScheme.secondary, + ), + strutStyle: StrutStyle( + height: 1, + leading: 0, + ), + ), + Icon( + MdiIcons.unfoldMoreHorizontal, + size: MediaQuery.textScalerOf( + context) + .scale(14), + color: + theme.colorScheme.secondary, + ), + ], + ), ), - ), - ], - ), - const SizedBox(height: 8), - ], - Wrap( - runSpacing: 8, - spacing: 16, - children: [ - Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Text('分类: '), - PopupMenuButton( - initialValue: list![index].category, - onSelected: (item) async { - list![index].category = item; - List constraintList = - segmentType2ActionType(item); - if (constraintList - .contains(list![index].actionType) - .not) { - list![index].actionType = - constraintList.first; - } - switch (item) { - case SegmentType.poi_highlight: - updateSegment( - isFirst: false, - index: index, - value: - list![index].segment.first, - ); - break; - case SegmentType.exclusive_access: + ], + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Text('行为类别: '), + PopupMenuButton( + initialValue: list![index].actionType, + onSelected: (item) async { + list![index].actionType = item; + if (item == ActionType.full) { updateSegment( isFirst: true, index: index, value: 0, ); - break; - case _: - } - setState(() {}); - }, - itemBuilder: (context) => SegmentType - .values - .map((item) => - PopupMenuItem( + } + setState(() {}); + }, + itemBuilder: (context) => ActionType + .values + .map( + (item) => + PopupMenuItem( + enabled: + segmentType2ActionType( + list![index] + .category) + .contains(item), value: item, child: Text(item.title), - )) - .toList(), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - list![index].category.title, - style: TextStyle( - height: 1, - fontSize: 14, - color: Theme.of(context) - .colorScheme - .secondary, + ), + ) + .toList(), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + list![index].actionType.title, + style: TextStyle( + height: 1, + fontSize: 14, + color: theme + .colorScheme.secondary, + ), + strutStyle: StrutStyle( + height: 1, + leading: 0, + ), ), - strutStyle: StrutStyle( - height: 1, - leading: 0, + Icon( + MdiIcons.unfoldMoreHorizontal, + size: MediaQuery.textScalerOf( + context) + .scale(14), + color: + theme.colorScheme.secondary, ), - ), - Icon( - MdiIcons.unfoldMoreHorizontal, - size: MediaQuery.textScalerOf( - context) - .scale(14), - color: Theme.of(context) - .colorScheme - .secondary, - ), - ], + ], + ), ), - ), - ], - ), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Text('行为类别: '), - PopupMenuButton( - initialValue: list![index].actionType, - onSelected: (item) async { - list![index].actionType = item; - if (item == ActionType.full) { - updateSegment( - isFirst: true, - index: index, - value: 0, - ); - } - setState(() {}); - }, - itemBuilder: (context) => ActionType - .values - .map( - (item) => - PopupMenuItem( - enabled: segmentType2ActionType( - list![index].category) - .contains(item), - value: item, - child: Text(item.title), - ), - ) - .toList(), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - list![index].actionType.title, - style: TextStyle( - height: 1, - fontSize: 14, - color: Theme.of(context) - .colorScheme - .secondary, - ), - strutStyle: StrutStyle( - height: 1, - leading: 0, - ), - ), - Icon( - MdiIcons.unfoldMoreHorizontal, - size: MediaQuery.textScalerOf( - context) - .scale(14), - color: Theme.of(context) - .colorScheme - .secondary, - ), - ], - ), - ), - ], - ), - ], - ), - ], - ), - ), - Positioned( - top: 0, - right: 4, - child: iconButton( - context: context, - size: 26, - tooltip: '移除', - icon: Icons.clear, - onPressed: () { - setState(() { - list!.removeAt(index); - }); - }, - ), - ), - Positioned( - top: 0, - left: 4, - child: iconButton( - context: context, - size: 26, - tooltip: '预览', - icon: Icons.preview_outlined, - onPressed: () async { - if (widget.plPlayerController - .videoPlayerController != - null) { - int start = max( - 0, - (list![index].segment.first * 1000).toInt() - - 1, - ); - await widget - .plPlayerController.videoPlayerController! - .seek( - Duration(milliseconds: start), - ); - if (widget.plPlayerController - .videoPlayerController!.state.playing.not) { - await widget - .plPlayerController.videoPlayerController! - .play(); - } - if (start != 0) { - await Future.delayed( - const Duration(seconds: 1)); - } - widget.plPlayerController.videoPlayerController! - .seek( - Duration( - milliseconds: - (list![index].segment.second * 1000) - .toInt(), - ), - ); - } - }, - ), - ), - ], - ), - ), - SizedBox( - height: 88 + MediaQuery.paddingOf(context).bottom, - ), - ], - ), - ), - Positioned( - right: 16, - bottom: 16 + MediaQuery.paddingOf(context).bottom, - child: FloatingActionButton( - tooltip: '提交', - onPressed: () { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('确定无误再提交'), - actions: [ - TextButton( - onPressed: Get.back, - child: Text( - '取消', - style: TextStyle( - color: Theme.of(context).colorScheme.outline, + ], + ), + ], + ), + ], ), ), - ), - TextButton( - onPressed: () { - Get.back(); - _onPost(); - }, - child: const Text('确定提交'), - ), - ], + Positioned( + top: 0, + right: 4, + child: iconButton( + context: context, + size: 26, + tooltip: '移除', + icon: Icons.clear, + onPressed: () { + setState(() { + list!.removeAt(index); + }); + }, + ), + ), + Positioned( + top: 0, + left: 4, + child: iconButton( + context: context, + size: 26, + tooltip: '预览', + icon: Icons.preview_outlined, + onPressed: () async { + if (widget.plPlayerController + .videoPlayerController != + null) { + int start = max( + 0, + (list![index].segment.first * 1000) + .toInt() - + 1, + ); + await widget + .plPlayerController.videoPlayerController! + .seek( + Duration(milliseconds: start), + ); + if (widget + .plPlayerController + .videoPlayerController! + .state + .playing + .not) { + await widget.plPlayerController + .videoPlayerController! + .play(); + } + if (start != 0) { + await Future.delayed( + const Duration(seconds: 1)); + } + widget + .plPlayerController.videoPlayerController! + .seek( + Duration( + milliseconds: + (list![index].segment.second * 1000) + .toInt(), + ), + ); + } + }, + ), + ), + ], + ), ), - ); - }, - child: Icon(Icons.check), + SizedBox( + height: 88 + MediaQuery.paddingOf(context).bottom, + ), + ], + ), ), - ) - ], - ) - : errorWidget(); + Positioned( + right: 16, + bottom: 16 + MediaQuery.paddingOf(context).bottom, + child: FloatingActionButton( + tooltip: '提交', + onPressed: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('确定无误再提交'), + actions: [ + TextButton( + onPressed: Get.back, + child: Text( + '取消', + style: TextStyle( + color: theme.colorScheme.outline, + ), + ), + ), + TextButton( + onPressed: () { + Get.back(); + _onPost(); + }, + child: const Text('确定提交'), + ), + ], + ), + ); + }, + child: Icon(Icons.check), + ), + ) + ], + ) + : errorWidget(); + } void updateSegment({ required bool isFirst, @@ -413,7 +424,8 @@ class _PostPanelState extends CommonCollapseSlidePageState { } } - List segmentWidget({ + List segmentWidget( + ThemeData theme, { required int index, required bool isFirst, }) { @@ -484,8 +496,7 @@ class _PostPanelState extends CommonCollapseSlidePageState { onPressed: Get.back, child: Text( '取消', - style: TextStyle( - color: Theme.of(context).colorScheme.outline), + style: TextStyle(color: theme.colorScheme.outline), ), ), TextButton( diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index 8d1b0f14..70cc2530 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -98,6 +98,7 @@ class _VideoReplyPanelState extends State @override Widget build(BuildContext context) { super.build(context); + final theme = Theme.of(context); return refreshIndicator( onRefresh: () async { await _videoReplyController.onRefresh(); @@ -120,7 +121,7 @@ class _VideoReplyPanelState extends State floating: true, delegate: CustomSliverPersistentHeaderDelegate( extent: 40, - bgColor: Theme.of(context).colorScheme.surface, + bgColor: theme.colorScheme.surface, child: Container( height: 40, padding: const EdgeInsets.fromLTRB(12, 0, 6, 0), @@ -141,15 +142,14 @@ class _VideoReplyPanelState extends State icon: Icon( Icons.sort, size: 16, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), label: Obx( () => Text( _videoReplyController.sortType.value.label, style: TextStyle( fontSize: 13, - color: - Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), ), @@ -160,7 +160,8 @@ class _VideoReplyPanelState extends State ), ), ), - Obx(() => _buildBody(_videoReplyController.loadingState.value)), + Obx(() => + _buildBody(theme, _videoReplyController.loadingState.value)), ], ), Positioned( @@ -194,7 +195,7 @@ class _VideoReplyPanelState extends State ); } - Widget _buildBody(LoadingState loadingState) { + Widget _buildBody(ThemeData theme, LoadingState loadingState) { return switch (loadingState) { Loading() => SliverList.builder( itemBuilder: (BuildContext context, index) { @@ -220,7 +221,7 @@ class _VideoReplyPanelState extends State : '没有更多了', style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ); diff --git a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart index bee183b9..8ff03a2d 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart @@ -62,6 +62,7 @@ class ReplyItemGrpc extends StatelessWidget { @override Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); return Material( color: Colors.transparent, child: InkWell( @@ -90,17 +91,17 @@ class ReplyItemGrpc extends StatelessWidget { }, ); }, - child: _buildContent(context), + child: _buildContent(context, theme), ), ); } - Widget _buildAuthorPanel(context) => Padding( + Widget _buildAuthorPanel(BuildContext context, ThemeData theme) => Padding( padding: const EdgeInsets.fromLTRB(12, 14, 8, 5), - child: content(context), + child: content(context, theme), ); - Widget _buildContent(context) { + Widget _buildContent(BuildContext context, ThemeData theme) { return Column( children: [ if (Avatar.showDynDecorate && replyItem.member.hasGarbCardImage()) @@ -138,18 +139,18 @@ class ReplyItemGrpc extends StatelessWidget { ), SizedBox( width: double.infinity, - child: _buildAuthorPanel(context), + child: _buildAuthorPanel(context, theme), ), ], ) else - _buildAuthorPanel(context), + _buildAuthorPanel(context, theme), if (needDivider) Divider( indent: 55, endIndent: 15, height: 0.3, - color: Theme.of(context).colorScheme.outline.withOpacity(0.08), + color: theme.colorScheme.outline.withOpacity(0.08), ) ], ); @@ -166,7 +167,7 @@ class ReplyItemGrpc extends StatelessWidget { : null, ); - Widget content(BuildContext context) { + Widget content(BuildContext context, ThemeData theme) { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, @@ -196,7 +197,7 @@ class ReplyItemGrpc extends StatelessWidget { color: (replyItem.member.vipStatus > 0 && replyItem.member.vipType == 2) ? context.vipColor - : Theme.of(context).colorScheme.outline, + : theme.colorScheme.outline, fontSize: 13, ), ), @@ -227,20 +228,16 @@ class ReplyItemGrpc extends StatelessWidget { .substring(0, 19) : Utils.dateFormat(replyItem.ctime.toInt()), style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelSmall!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline, ), ), if (replyItem.replyControl.location.isNotEmpty) Text( ' • ${replyItem.replyControl.location}', style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .labelSmall! - .fontSize, - color: Theme.of(context).colorScheme.outline), + fontSize: theme.textTheme.labelSmall!.fontSize, + color: theme.colorScheme.outline), ), ], ) @@ -262,7 +259,7 @@ class ReplyItemGrpc extends StatelessWidget { String text = replyItem.content.message; TextStyle style = TextStyle( height: 1.75, - fontSize: Theme.of(context).textTheme.bodyMedium!.fontSize, + fontSize: theme.textTheme.bodyMedium!.fontSize, ); TextPainter? textPainter; bool? didExceedMaxLines; @@ -297,8 +294,8 @@ class ReplyItemGrpc extends StatelessWidget { ], buildContent( context, + theme, replyItem, - replyReply, null, textPainter, didExceedMaxLines, @@ -311,16 +308,15 @@ class ReplyItemGrpc extends StatelessWidget { ), ), // 操作区域 - if (replyLevel != '') buttonAction(context, replyItem.replyControl), + if (replyLevel != '') + buttonAction(context, theme, replyItem.replyControl), // 一楼的评论 if (replyLevel == '1' && (replyItem.replies.isNotEmpty || replyItem.replyControl.subReplyEntryText.isNotEmpty)) ...[ Padding( padding: const EdgeInsets.only(top: 5, bottom: 12), - child: replyItemRow( - context: context, - ), + child: replyItemRow(context, theme), ), ], ], @@ -334,7 +330,8 @@ class ReplyItemGrpc extends StatelessWidget { ); // 感谢、回复、复制 - Widget buttonAction(BuildContext context, replyControl) { + Widget buttonAction( + BuildContext context, ThemeData theme, ReplyControl replyControl) { return Row( children: [ const SizedBox(width: 36), @@ -350,14 +347,14 @@ class ReplyItemGrpc extends StatelessWidget { Icon( Icons.reply, size: 18, - color: Theme.of(context).colorScheme.outline.withOpacity(0.8), + color: theme.colorScheme.outline.withOpacity(0.8), ), const SizedBox(width: 3), Text( '回复', style: TextStyle( - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, - color: Theme.of(context).colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, ), ), ]), @@ -373,8 +370,8 @@ class ReplyItemGrpc extends StatelessWidget { child: Text( 'UP主觉得很赞', style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, + color: theme.colorScheme.secondary, + fontSize: theme.textTheme.labelMedium!.fontSize, fontWeight: FontWeight.normal, ), ), @@ -389,8 +386,8 @@ class ReplyItemGrpc extends StatelessWidget { Text( '热评', style: TextStyle( - color: Theme.of(context).colorScheme.secondary, - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize), + color: theme.colorScheme.secondary, + fontSize: theme.textTheme.labelMedium!.fontSize), ), if (replyLevel == '2' && needDivider && @@ -403,8 +400,8 @@ class ReplyItemGrpc extends StatelessWidget { child: Text( '查看对话', style: TextStyle( - color: Theme.of(context).colorScheme.outline, - fontSize: Theme.of(context).textTheme.labelMedium!.fontSize, + color: theme.colorScheme.outline, + fontSize: theme.textTheme.labelMedium!.fontSize, fontWeight: FontWeight.normal, ), ), @@ -417,12 +414,12 @@ class ReplyItemGrpc extends StatelessWidget { ); } - Widget replyItemRow({required BuildContext context}) { + Widget replyItemRow(BuildContext context, ThemeData theme) { final bool extraRow = replyItem.replies.length < replyItem.count.toInt(); return Container( margin: const EdgeInsets.only(left: 42, right: 4, top: 0), child: Material( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, borderRadius: BorderRadius.circular(6), clipBehavior: Clip.hardEdge, animationDuration: Duration.zero, @@ -471,14 +468,9 @@ class ReplyItemGrpc extends StatelessWidget { excludeSemantics: true, child: Text.rich( style: TextStyle( - fontSize: Theme.of(context) - .textTheme - .bodyMedium! - .fontSize, - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(0.85), + fontSize: theme.textTheme.bodyMedium!.fontSize, + color: + theme.colorScheme.onSurface.withOpacity(0.85), height: 1.6), overflow: TextOverflow.ellipsis, maxLines: 2, @@ -487,7 +479,7 @@ class ReplyItemGrpc extends StatelessWidget { TextSpan( text: replyItem.replies[i].member.name, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -521,8 +513,8 @@ class ReplyItemGrpc extends StatelessWidget { ), buildContent( context, + theme, replyItem.replies[i], - replyReply, replyItem, null, null, @@ -544,24 +536,21 @@ class ReplyItemGrpc extends StatelessWidget { child: Text.rich( TextSpan( style: TextStyle( - fontSize: - Theme.of(context).textTheme.labelMedium!.fontSize, + fontSize: theme.textTheme.labelMedium!.fontSize, ), children: [ if (replyItem.replyControl.upReply) TextSpan( text: 'UP主等人 ', style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSurface - .withOpacity(0.85), + color: + theme.colorScheme.onSurface.withOpacity(0.85), ), ), TextSpan( text: replyItem.replyControl.subReplyEntryText, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ) ], @@ -577,11 +566,11 @@ class ReplyItemGrpc extends StatelessWidget { InlineSpan buildContent( BuildContext context, - replyItem, - replyReply, - fReplyItem, - textPainter, - didExceedMaxLines, + ThemeData theme, + ReplyInfo replyItem, + ReplyInfo? fReplyItem, + TextPainter? textPainter, + bool? didExceedMaxLines, ) { final String routePath = Get.currentRoute; bool isVideoPage = routePath.startsWith('/video'); @@ -594,7 +583,7 @@ class ReplyItemGrpc extends StatelessWidget { final List spanChildren = []; if (didExceedMaxLines == true) { - final textSize = textPainter.size; + final textSize = textPainter!.size; final double maxHeight = textPainter.preferredLineHeight * 6; var position = textPainter.getPositionForOffset( Offset(textSize.width, maxHeight), @@ -609,7 +598,7 @@ class ReplyItemGrpc extends StatelessWidget { TextSpan( text: '投票: ${content.vote.title}', style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -689,7 +678,7 @@ class ReplyItemGrpc extends StatelessWidget { TextSpan( text: matchStr, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -724,7 +713,7 @@ class ReplyItemGrpc extends StatelessWidget { text: isValid ? ' $matchStr ' : matchStr, style: isValid && isVideoPage ? TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ) : null, recognizer: isValid @@ -765,7 +754,7 @@ class ReplyItemGrpc extends StatelessWidget { imageUrl: Utils.thumbnailImgUrl( content.url[matchStr]!.prefixIcon), height: 19, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, placeholder: (context, url) { return const SizedBox.shrink(); }, @@ -775,7 +764,7 @@ class ReplyItemGrpc extends StatelessWidget { TextSpan( text: content.url[matchStr]!.title, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () async { @@ -827,7 +816,7 @@ class ReplyItemGrpc extends StatelessWidget { TextSpan( text: matchStr, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -845,7 +834,7 @@ class ReplyItemGrpc extends StatelessWidget { TextSpan( text: matchStr, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -885,7 +874,7 @@ class ReplyItemGrpc extends StatelessWidget { imageUrl: Utils.thumbnailImgUrl( content.url[patternStr]!.prefixIcon), height: 19, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, placeholder: (context, url) { return const SizedBox.shrink(); }, @@ -895,7 +884,7 @@ class ReplyItemGrpc extends StatelessWidget { TextSpan( text: content.url[patternStr]!.title, style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -927,7 +916,7 @@ class ReplyItemGrpc extends StatelessWidget { TextSpan( text: '\n查看更多', style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ); @@ -965,7 +954,7 @@ class ReplyItemGrpc extends StatelessWidget { TextSpan( text: ' 笔记', style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), recognizer: TapGestureRecognizer() ..onTap = @@ -1040,6 +1029,7 @@ class ReplyItemGrpc extends StatelessWidget { bool? isDelete = await showDialog( context: context, builder: (context) { + final theme = Theme.of(context); return AlertDialog( title: const Text('删除评论'), content: Text.rich( @@ -1050,7 +1040,7 @@ class ReplyItemGrpc extends StatelessWidget { TextSpan( text: '@${item.member.name}', style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), TextSpan(text: ':\n'), @@ -1067,7 +1057,7 @@ class ReplyItemGrpc extends StatelessWidget { child: Text( '取消', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -1114,7 +1104,9 @@ class ReplyItemGrpc extends StatelessWidget { } } - Color errorColor = Theme.of(context).colorScheme.error; + final theme = Theme.of(context); + Color errorColor = theme.colorScheme.error; + final style = theme.textTheme.titleSmall; return Padding( padding: @@ -1136,7 +1128,7 @@ class ReplyItemGrpc extends StatelessWidget { width: 32, height: 3, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, borderRadius: const BorderRadius.all(Radius.circular(3))), ), ), @@ -1147,48 +1139,42 @@ class ReplyItemGrpc extends StatelessWidget { onTap: () => menuActionHandler('delete'), minLeadingWidth: 0, leading: Icon(Icons.delete_outlined, color: errorColor, size: 19), - title: Text('删除', - style: Theme.of(context) - .textTheme - .titleSmall! - .copyWith(color: errorColor)), + title: Text('删除', style: style!.copyWith(color: errorColor)), ), if (ownerMid != 0) ListTile( onTap: () => menuActionHandler('report'), minLeadingWidth: 0, leading: Icon(Icons.error_outline, color: errorColor, size: 19), - title: Text('举报', - style: Theme.of(context) - .textTheme - .titleSmall! - .copyWith(color: errorColor)), + title: Text('举报', style: style!.copyWith(color: errorColor)), ), if (replyLevel == '1' && isSubReply.not && ownerMid == upMid.toInt()) ListTile( onTap: () => menuActionHandler('top'), minLeadingWidth: 0, leading: Icon(Icons.vertical_align_top, size: 19), - title: Text('${replyItem.replyControl.isUpTop ? '取消' : ''}置顶', - style: Theme.of(context).textTheme.titleSmall!), + title: Text( + '${replyItem.replyControl.isUpTop ? '取消' : ''}置顶', + style: style, + ), ), ListTile( onTap: () => menuActionHandler('copyAll'), minLeadingWidth: 0, leading: const Icon(Icons.copy_all_outlined, size: 19), - title: Text('复制全部', style: Theme.of(context).textTheme.titleSmall), + title: Text('复制全部', style: style), ), ListTile( onTap: () => menuActionHandler('copyFreedom'), minLeadingWidth: 0, leading: const Icon(Icons.copy_outlined, size: 19), - title: Text('自由复制', style: Theme.of(context).textTheme.titleSmall), + title: Text('自由复制', style: style), ), ListTile( onTap: () => menuActionHandler('saveReply'), minLeadingWidth: 0, leading: const Icon(Icons.save_alt, size: 19), - title: Text('保存评论', style: Theme.of(context).textTheme.titleSmall), + title: Text('保存评论', style: style), ), if (item.mid.toInt() == ownerMid) ListTile( @@ -1201,8 +1187,7 @@ class ReplyItemGrpc extends StatelessWidget { const Icon(Icons.reply, size: 12), ], ), - title: - Text('检查评论', style: Theme.of(context).textTheme.titleSmall), + title: Text('检查评论', style: style), ), ], ), diff --git a/lib/pages/video/detail/reply/widgets/zan_grpc.dart b/lib/pages/video/detail/reply/widgets/zan_grpc.dart index 62eab522..2bf92c15 100644 --- a/lib/pages/video/detail/reply/widgets/zan_grpc.dart +++ b/lib/pages/video/detail/reply/widgets/zan_grpc.dart @@ -102,9 +102,9 @@ class _ZanButtonGrpcState extends State { @override Widget build(BuildContext context) { - final ThemeData t = Theme.of(context); - final Color color = t.colorScheme.outline; - final Color primary = t.colorScheme.primary; + final ThemeData theme = Theme.of(context); + final Color color = theme.colorScheme.outline; + final Color primary = theme.colorScheme.primary; return Row( mainAxisSize: MainAxisSize.min, children: [ @@ -160,7 +160,7 @@ class _ZanButtonGrpcState extends State { color: widget.replyItem.replyControl.action.toInt() == 1 ? primary : color, - fontSize: t.textTheme.labelSmall!.fontSize, + fontSize: theme.textTheme.labelSmall!.fontSize, ), ), ), diff --git a/lib/pages/video/detail/reply_new/toolbar_icon_button.dart b/lib/pages/video/detail/reply_new/toolbar_icon_button.dart index 8f906495..d036ce13 100644 --- a/lib/pages/video/detail/reply_new/toolbar_icon_button.dart +++ b/lib/pages/video/detail/reply_new/toolbar_icon_button.dart @@ -16,6 +16,7 @@ class ToolbarIconButton extends StatelessWidget { @override Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); return SizedBox( width: 36, height: 36, @@ -23,16 +24,14 @@ class ToolbarIconButton extends StatelessWidget { tooltip: tooltip, onPressed: onPressed, icon: icon, - highlightColor: Theme.of(context).colorScheme.secondaryContainer, + highlightColor: theme.colorScheme.secondaryContainer, color: selected - ? Theme.of(context).colorScheme.onSecondaryContainer - : Theme.of(context).colorScheme.outline, + ? theme.colorScheme.onSecondaryContainer + : theme.colorScheme.outline, style: ButtonStyle( padding: WidgetStateProperty.all(EdgeInsets.zero), backgroundColor: WidgetStateProperty.resolveWith((states) { - return selected - ? Theme.of(context).colorScheme.secondaryContainer - : null; + return selected ? theme.colorScheme.secondaryContainer : null; }), ), ), diff --git a/lib/pages/video/detail/reply_reply/view.dart b/lib/pages/video/detail/reply_reply/view.dart index dbad9ab9..9327b47b 100644 --- a/lib/pages/video/detail/reply_reply/view.dart +++ b/lib/pages/video/detail/reply_reply/view.dart @@ -93,8 +93,8 @@ class _VideoReplyReplyPanelState super.dispose(); } - Widget get _header => firstFloor == null - ? _sortWidget + Widget _header(ThemeData theme) => firstFloor == null + ? _sortWidget(theme) : ValueListenableBuilder>( valueListenable: itemPositionsListener.itemPositions, builder: (context, positions, child) { @@ -109,139 +109,144 @@ class _VideoReplyReplyPanelState : min) .index; } - return min >= 2 ? _sortWidget : const SizedBox.shrink(); + return min >= 2 ? _sortWidget(theme) : const SizedBox.shrink(); }, ); @override - Widget get buildPage => Scaffold( - key: _key, - resizeToAvoidBottomInset: false, - body: Column( - children: [ - widget.source == 'videoDetail' - ? Container( - height: 45, - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - width: 1, - color: - Theme.of(context).dividerColor.withOpacity(0.1), - ), + Widget buildPage(ThemeData theme) { + return Scaffold( + key: _key, + resizeToAvoidBottomInset: false, + body: Column( + children: [ + widget.source == 'videoDetail' + ? Container( + height: 45, + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + width: 1, + color: theme.dividerColor.withOpacity(0.1), ), ), - padding: const EdgeInsets.only(left: 12, right: 2), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(widget.isDialogue ? '对话列表' : '评论详情'), - IconButton( - tooltip: '关闭', - icon: const Icon(Icons.close, size: 20), - onPressed: Get.back, - ), - ], - ), - ) - : Divider( - height: 1, - color: Theme.of(context).dividerColor.withOpacity(0.1), ), - Expanded( - child: enableSlide ? slideList() : buildList, - ), - ], - ), - ); + padding: const EdgeInsets.only(left: 12, right: 2), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(widget.isDialogue ? '对话列表' : '评论详情'), + IconButton( + tooltip: '关闭', + icon: const Icon(Icons.close, size: 20), + onPressed: Get.back, + ), + ], + ), + ) + : Divider( + height: 1, + color: theme.dividerColor.withOpacity(0.1), + ), + Expanded( + child: enableSlide ? slideList(theme) : buildList(theme), + ), + ], + ), + ); + } @override - Widget get buildList => ClipRect( - child: refreshIndicator( - onRefresh: () async { - await _videoReplyReplyController.onRefresh(); - }, - child: Obx( - () => Stack( - children: [ - ScrollablePositionedList.builder( - key: _listKey, - itemPositionsListener: itemPositionsListener, - itemCount: - _itemCount(_videoReplyReplyController.loadingState.value), - itemScrollController: - _videoReplyReplyController.itemScrollCtr, - physics: const AlwaysScrollableScrollPhysics(), - itemBuilder: (context, index) { - if (widget.isDialogue) { - return _buildBody( - _videoReplyReplyController.loadingState.value, index); - } else if (firstFloor != null) { - if (index == 0) { - return ReplyItemGrpc( - replyItem: firstFloor, - replyLevel: '2', - needDivider: false, - onReply: () { - _onReply(firstFloor, -1); - }, - upMid: _videoReplyReplyController.upMid, - onViewImage: widget.onViewImage, - onDismissed: widget.onDismissed, - callback: _getImageCallback, - onCheckReply: (item) => _videoReplyReplyController - .onCheckReply(context, item), - onToggleTop: (isUpTop, rpid) => - _videoReplyReplyController.onToggleTop( - index, - _videoReplyReplyController.oid, - _videoReplyReplyController.replyType.index, - isUpTop, - rpid, - ), - ); - } else if (index == 1) { - return Divider( - height: 20, - color: - Theme.of(context).dividerColor.withOpacity(0.1), - thickness: 6, - ); - } else if (index == 2) { - return _sortWidget; - } else { - return _buildBody( - _videoReplyReplyController.loadingState.value, - index - 3); - } + Widget buildList(ThemeData theme) { + return ClipRect( + child: refreshIndicator( + onRefresh: () async { + await _videoReplyReplyController.onRefresh(); + }, + child: Obx( + () => Stack( + children: [ + ScrollablePositionedList.builder( + key: _listKey, + itemPositionsListener: itemPositionsListener, + itemCount: + _itemCount(_videoReplyReplyController.loadingState.value), + itemScrollController: _videoReplyReplyController.itemScrollCtr, + physics: const AlwaysScrollableScrollPhysics(), + itemBuilder: (context, index) { + if (widget.isDialogue) { + return _buildBody(theme, + _videoReplyReplyController.loadingState.value, index); + } else if (firstFloor != null) { + if (index == 0) { + return ReplyItemGrpc( + replyItem: firstFloor, + replyLevel: '2', + needDivider: false, + onReply: () { + _onReply(firstFloor, -1); + }, + upMid: _videoReplyReplyController.upMid, + onViewImage: widget.onViewImage, + onDismissed: widget.onDismissed, + callback: _getImageCallback, + onCheckReply: (item) => _videoReplyReplyController + .onCheckReply(context, item), + onToggleTop: (isUpTop, rpid) => + _videoReplyReplyController.onToggleTop( + index, + _videoReplyReplyController.oid, + _videoReplyReplyController.replyType.index, + isUpTop, + rpid, + ), + ); + } else if (index == 1) { + return Divider( + height: 20, + color: theme.dividerColor.withOpacity(0.1), + thickness: 6, + ); + } else if (index == 2) { + return _sortWidget(theme); } else { - if (index == 0) { - return _sortWidget; - } else { - return _buildBody( - _videoReplyReplyController.loadingState.value, - index - 1); - } + return _buildBody( + theme, + _videoReplyReplyController.loadingState.value, + index - 3, + ); } - }, - ), - if (!widget.isDialogue && - _videoReplyReplyController.loadingState.value is Success) - _header, - ], - ), + } else { + if (index == 0) { + return _sortWidget(theme); + } else { + return _buildBody( + theme, + _videoReplyReplyController.loadingState.value, + index - 1, + ); + } + } + }, + ), + if (!widget.isDialogue && + _videoReplyReplyController.loadingState.value is Success) + _header(theme), + ], ), ), - ); + ), + ); + } - Widget get _sortWidget => Container( + Widget _sortWidget(ThemeData theme) => Container( height: 40, padding: const EdgeInsets.fromLTRB(12, 0, 6, 0), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, boxShadow: [ BoxShadow( - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, offset: const Offset(0, -2), ), ], @@ -264,7 +269,7 @@ class _VideoReplyReplyPanelState icon: Icon( Icons.sort, size: 16, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), label: Obx( () => Text( @@ -273,7 +278,7 @@ class _VideoReplyReplyPanelState : '按时间', style: TextStyle( fontSize: 13, - color: Theme.of(context).colorScheme.secondary, + color: theme.colorScheme.secondary, ), ), ), @@ -384,7 +389,7 @@ class _VideoReplyReplyPanelState }); } - Widget _buildBody(LoadingState loadingState, int index) { + Widget _buildBody(ThemeData theme, LoadingState loadingState, int index) { return switch (loadingState) { Loading() => IgnorePointer( child: CustomScrollView( @@ -416,7 +421,7 @@ class _VideoReplyReplyPanelState : '没有更多了', style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ); @@ -424,15 +429,15 @@ class _VideoReplyReplyPanelState if (_videoReplyReplyController.index != null && _videoReplyReplyController.index == index) { colorAnimation ??= ColorTween( - begin: Theme.of(context).colorScheme.onInverseSurface, - end: Theme.of(context).colorScheme.surface, + begin: theme.colorScheme.onInverseSurface, + end: theme.colorScheme.surface, ).animate(_videoReplyReplyController.controller!); return AnimatedBuilder( animation: colorAnimation!, builder: (context, child) { return ColoredBox( color: colorAnimation!.value ?? - Theme.of(context).colorScheme.onInverseSurface, + theme.colorScheme.onInverseSurface, child: _replyItem(loadingState.response[index], index), ); }, diff --git a/lib/pages/video/detail/view_point/view_points_page.dart b/lib/pages/video/detail/view_point/view_points_page.dart index 87278fc1..d1ab88d6 100644 --- a/lib/pages/video/detail/view_point/view_points_page.dart +++ b/lib/pages/video/detail/view_point/view_points_page.dart @@ -33,136 +33,134 @@ class _ViewPointsPageState int currentIndex = -1; @override - Widget get buildPage => Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - automaticallyImplyLeading: false, - titleSpacing: 16, - title: const Text('分段信息'), - toolbarHeight: 45, - actions: [ - Text( - '分段进度条', - style: TextStyle(fontSize: 16), - ), - Obx( - () => Transform.scale( - alignment: Alignment.centerLeft, - scale: 0.8, - child: Switch( - thumbIcon: WidgetStateProperty.resolveWith((states) { - if (states.isNotEmpty && - states.first == WidgetState.selected) { - return const Icon(Icons.done); - } - return null; - }), - value: videoDetailController.plPlayerController.showVP.value, - onChanged: (value) { - videoDetailController.plPlayerController.showVP.value = - value; - }, - ), + Widget buildPage(ThemeData theme) { + return Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + automaticallyImplyLeading: false, + titleSpacing: 16, + title: const Text('分段信息'), + toolbarHeight: 45, + actions: [ + Text( + '分段进度条', + style: TextStyle(fontSize: 16), + ), + Obx( + () => Transform.scale( + alignment: Alignment.centerLeft, + scale: 0.8, + child: Switch( + thumbIcon: WidgetStateProperty.resolveWith((states) { + if (states.isNotEmpty && + states.first == WidgetState.selected) { + return const Icon(Icons.done); + } + return null; + }), + value: videoDetailController.plPlayerController.showVP.value, + onChanged: (value) { + videoDetailController.plPlayerController.showVP.value = value; + }, ), ), - iconButton( - context: context, - size: 30, - icon: Icons.clear, - tooltip: '关闭', - onPressed: Get.back, - ), - const SizedBox(width: 16), - ], - bottom: PreferredSize( - preferredSize: Size.fromHeight(1), - child: Divider( - height: 1, - color: Theme.of(context).dividerColor.withOpacity(0.1), - ), + ), + iconButton( + context: context, + size: 30, + icon: Icons.clear, + tooltip: '关闭', + onPressed: Get.back, + ), + const SizedBox(width: 16), + ], + bottom: PreferredSize( + preferredSize: Size.fromHeight(1), + child: Divider( + height: 1, + color: theme.dividerColor.withOpacity(0.1), ), ), - body: enableSlide ? slideList() : buildList, - ); + ), + body: enableSlide ? slideList(theme) : buildList(theme), + ); + } @override - Widget get buildList => ListView.separated( - controller: ScrollController(), - physics: const AlwaysScrollableScrollPhysics(), - padding: - EdgeInsets.only(bottom: MediaQuery.paddingOf(context).bottom + 80), - itemCount: videoDetailController.viewPointList.length, - itemBuilder: (context, index) { - Segment segment = videoDetailController.viewPointList[index]; - if (currentIndex == -1 && - segment.from != null && - segment.to != null) { - if (videoDetailController - .plPlayerController.positionSeconds.value >= - segment.from! && - videoDetailController.plPlayerController.positionSeconds.value < - segment.to!) { - currentIndex = index; - } + Widget buildList(ThemeData theme) { + return ListView.separated( + controller: ScrollController(), + physics: const AlwaysScrollableScrollPhysics(), + padding: + EdgeInsets.only(bottom: MediaQuery.paddingOf(context).bottom + 80), + itemCount: videoDetailController.viewPointList.length, + itemBuilder: (context, index) { + Segment segment = videoDetailController.viewPointList[index]; + if (currentIndex == -1 && segment.from != null && segment.to != null) { + if (videoDetailController.plPlayerController.positionSeconds.value >= + segment.from! && + videoDetailController.plPlayerController.positionSeconds.value < + segment.to!) { + currentIndex = index; } - return ListTile( - dense: true, - onTap: segment.from != null - ? () { - currentIndex = index; - plPlayerController?.danmakuController?.clear(); - plPlayerController?.videoPlayerController - ?.seek(Duration(seconds: segment.from!)); - Get.back(); - } - : null, - leading: segment.url?.isNotEmpty == true - ? Container( - margin: const EdgeInsets.symmetric(vertical: 6), - decoration: currentIndex == index - ? BoxDecoration( - borderRadius: BorderRadius.circular(6), - border: Border.all( - width: 1.8, - strokeAlign: BorderSide.strokeAlignOutside, - color: Theme.of(context).colorScheme.primary, - ), - ) - : null, - child: LayoutBuilder( - builder: (context, constraints) => NetworkImgLayer( - radius: 6, - src: segment.url, - width: constraints.maxHeight * StyleString.aspectRatio, - height: constraints.maxHeight, - ), + } + return ListTile( + dense: true, + onTap: segment.from != null + ? () { + currentIndex = index; + plPlayerController?.danmakuController?.clear(); + plPlayerController?.videoPlayerController + ?.seek(Duration(seconds: segment.from!)); + Get.back(); + } + : null, + leading: segment.url?.isNotEmpty == true + ? Container( + margin: const EdgeInsets.symmetric(vertical: 6), + decoration: currentIndex == index + ? BoxDecoration( + borderRadius: BorderRadius.circular(6), + border: Border.all( + width: 1.8, + strokeAlign: BorderSide.strokeAlignOutside, + color: theme.colorScheme.primary, + ), + ) + : null, + child: LayoutBuilder( + builder: (context, constraints) => NetworkImgLayer( + radius: 6, + src: segment.url, + width: constraints.maxHeight * StyleString.aspectRatio, + height: constraints.maxHeight, ), - ) - : null, - title: Text( - segment.title ?? '', - style: TextStyle( - fontSize: 14, - fontWeight: currentIndex == index ? FontWeight.bold : null, - color: currentIndex == index - ? Theme.of(context).colorScheme.primary - : null, - ), + ), + ) + : null, + title: Text( + segment.title ?? '', + style: TextStyle( + fontSize: 14, + fontWeight: currentIndex == index ? FontWeight.bold : null, + color: currentIndex == index ? theme.colorScheme.primary : null, ), - subtitle: Text( - '${segment.from != null ? Utils.timeFormat(segment.from) : ''} - ${segment.to != null ? Utils.timeFormat(segment.to) : ''}', - style: TextStyle( - fontSize: 13, - color: currentIndex == index - ? Theme.of(context).colorScheme.primary - : Theme.of(context).colorScheme.outline, - ), + ), + subtitle: Text( + '${segment.from != null ? Utils.timeFormat(segment.from) : ''} - ${segment.to != null ? Utils.timeFormat(segment.to) : ''}', + style: TextStyle( + fontSize: 13, + color: currentIndex == index + ? theme.colorScheme.primary + : theme.colorScheme.outline, ), - ); - }, - separatorBuilder: (context, index) => Divider( - height: 1, - color: Theme.of(context).dividerColor.withOpacity(0.1), - ), - ); + ), + ); + }, + separatorBuilder: (context, index) => Divider( + height: 1, + color: theme.dividerColor.withOpacity(0.1), + ), + ); + } } diff --git a/lib/pages/video/detail/widgets/ai_detail.dart b/lib/pages/video/detail/widgets/ai_detail.dart index 14a470b4..8897c3d2 100644 --- a/lib/pages/video/detail/widgets/ai_detail.dart +++ b/lib/pages/video/detail/widgets/ai_detail.dart @@ -1,10 +1,7 @@ -import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/pages/common/common_collapse_slide_page.dart'; import 'package:PiliPlus/pages/video/detail/controller.dart'; -import 'package:PiliPlus/utils/page_utils.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:PiliPlus/models/video/ai.dart'; import 'package:PiliPlus/utils/utils.dart'; @@ -22,199 +19,133 @@ class AiDetail extends CommonCollapseSlidePage { } class _AiDetailState extends CommonCollapseSlidePageState { - InlineSpan buildContent(BuildContext context, content) { - List descV2 = content.descV2; - // type - // 1 普通文本 - // 2 @用户 - List spanChildren = List.generate(descV2.length, (index) { - final currentDesc = descV2[index]; - switch (currentDesc.type) { - case 1: - List spanChildren = []; - RegExp urlRegExp = RegExp(Constants.urlPattern); - Iterable matches = urlRegExp.allMatches(currentDesc.rawText); - - int previousEndIndex = 0; - for (Match match in matches) { - if (match.start > previousEndIndex) { - spanChildren.add(TextSpan( - text: currentDesc.rawText - .substring(previousEndIndex, match.start))); - } - spanChildren.add( - TextSpan( - text: match.group(0), - style: TextStyle(color: Theme.of(context).colorScheme.primary), - recognizer: TapGestureRecognizer() - ..onTap = () { - try { - PageUtils.handleWebview(match.group(0)!); - } catch (err) { - SmartDialog.showToast(err.toString()); - } - }, + @override + Widget buildPage(ThemeData theme) { + return Material( + color: theme.colorScheme.surface, + child: Column( + children: [ + GestureDetector( + onTap: Get.back, + child: Container( + height: 35, + padding: const EdgeInsets.only(bottom: 2), + child: Center( + child: Container( + width: 32, + height: 3, + decoration: BoxDecoration( + color: theme.colorScheme.primary, + borderRadius: const BorderRadius.all(Radius.circular(3)), + ), + ), ), - ); - previousEndIndex = match.end; - } - - if (previousEndIndex < currentDesc.rawText.length) { - spanChildren.add(TextSpan( - text: currentDesc.rawText.substring(previousEndIndex))); - } - - TextSpan result = TextSpan(children: spanChildren); - return result; - case 2: - final colorSchemePrimary = Theme.of(context).colorScheme.primary; - final heroTag = Utils.makeHeroTag(currentDesc.bizId); - return TextSpan( - text: '@${currentDesc.rawText}', - style: TextStyle(color: colorSchemePrimary), - recognizer: TapGestureRecognizer() - ..onTap = () { - Get.toNamed( - '/member?mid=${currentDesc.bizId}', - arguments: {'face': '', 'heroTag': heroTag}, - ); - }, - ); - default: - return const TextSpan(); - } - }); - return TextSpan(children: spanChildren); + ), + ), + Expanded( + child: enableSlide ? slideList(theme) : buildList(theme), + ), + ], + ), + ); } @override - Widget get buildPage => Material( - color: Theme.of(context).colorScheme.surface, - child: Column( - children: [ - GestureDetector( - onTap: Get.back, - child: Container( - height: 35, - padding: const EdgeInsets.only(bottom: 2), - child: Center( - child: Container( - width: 32, - height: 3, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary, - borderRadius: const BorderRadius.all(Radius.circular(3)), - ), - ), + Widget buildList(ThemeData theme) { + return CustomScrollView( + controller: ScrollController(), + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + if (widget.modelResult.summary?.isNotEmpty == true) ...[ + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 14), + child: SelectableText( + widget.modelResult.summary!, + style: const TextStyle( + fontSize: 15, + height: 1.5, ), ), ), - Expanded( - child: enableSlide ? slideList() : buildList, - ), - ], - ), - ); - - @override - Widget get buildList => CustomScrollView( - controller: ScrollController(), - physics: const AlwaysScrollableScrollPhysics(), - slivers: [ - if (widget.modelResult.summary?.isNotEmpty == true) ...[ - SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 14), - child: SelectableText( - widget.modelResult.summary!, - style: const TextStyle( - fontSize: 15, - height: 1.5, - ), - ), - ), - ), - if (widget.modelResult.outline?.isNotEmpty == true) - SliverToBoxAdapter( - child: Divider( - height: 20, - color: Theme.of(context).dividerColor.withOpacity(0.1), - thickness: 6, - ), - ), - ], + ), if (widget.modelResult.outline?.isNotEmpty == true) - SliverPadding( - padding: EdgeInsets.only( - left: 14, - right: 14, - bottom: MediaQuery.paddingOf(context).bottom + 80, - ), - sliver: SliverList.builder( - itemCount: widget.modelResult.outline!.length, - itemBuilder: (context, index) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (index != 0) const SizedBox(height: 10), - SelectableText( - widget.modelResult.outline![index].title!, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - height: 1.5, - ), - ), - const SizedBox(height: 6), - if (widget.modelResult.outline![index].partOutline - ?.isNotEmpty == - true) - ...widget.modelResult.outline![index].partOutline!.map( - (item) => Wrap( - children: [ - SelectableText.rich( - TextSpan( - style: TextStyle( - fontSize: 14, - color: - Theme.of(context).colorScheme.onSurface, - height: 1.5, - ), - children: [ - TextSpan( - text: - Utils.formatDuration(item.timestamp!), - style: TextStyle( - color: Theme.of(context) - .colorScheme - .primary, - ), - recognizer: TapGestureRecognizer() - ..onTap = () { - // 跳转到指定位置 - try { - Get.find( - tag: Get - .arguments['heroTag']) - .plPlayerController - .seekTo(Duration( - seconds: item.timestamp!)); - } catch (_) {} - }, - ), - const TextSpan(text: ' '), - TextSpan(text: item.content!), - ], - ), - ), - ], - ), - ), - ], - ); - }, + SliverToBoxAdapter( + child: Divider( + height: 20, + color: theme.dividerColor.withOpacity(0.1), + thickness: 6, ), ), ], - ); + if (widget.modelResult.outline?.isNotEmpty == true) + SliverPadding( + padding: EdgeInsets.only( + left: 14, + right: 14, + bottom: MediaQuery.paddingOf(context).bottom + 80, + ), + sliver: SliverList.builder( + itemCount: widget.modelResult.outline!.length, + itemBuilder: (context, index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (index != 0) const SizedBox(height: 10), + SelectableText( + widget.modelResult.outline![index].title!, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + height: 1.5, + ), + ), + const SizedBox(height: 6), + if (widget.modelResult.outline![index].partOutline + ?.isNotEmpty == + true) + ...widget.modelResult.outline![index].partOutline!.map( + (item) => Wrap( + children: [ + SelectableText.rich( + TextSpan( + style: TextStyle( + fontSize: 14, + color: theme.colorScheme.onSurface, + height: 1.5, + ), + children: [ + TextSpan( + text: Utils.formatDuration(item.timestamp!), + style: TextStyle( + color: theme.colorScheme.primary, + ), + recognizer: TapGestureRecognizer() + ..onTap = () { + // 跳转到指定位置 + try { + Get.find( + tag: Get.arguments['heroTag']) + .plPlayerController + .seekTo(Duration( + seconds: item.timestamp!)); + } catch (_) {} + }, + ), + const TextSpan(text: ' '), + TextSpan(text: item.content!), + ], + ), + ), + ], + ), + ), + ], + ); + }, + ), + ), + ], + ); + } } diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index d6482b72..0779f308 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -118,452 +118,456 @@ class HeaderControlState extends State { /// 设置面板 void showSettingSheet() { showBottomSheet( - (context, setState) => Padding( - padding: const EdgeInsets.all(12), - child: Material( - clipBehavior: Clip.hardEdge, - color: Theme.of(context).colorScheme.surface, - borderRadius: const BorderRadius.all(Radius.circular(12)), - child: ListView( - padding: EdgeInsets.zero, - children: [ - const SizedBox(height: 14), - ListTile( - dense: true, - onTap: () { - Get.back(); - videoIntroController.viewLater(); - }, - leading: const Icon(Icons.watch_later_outlined, size: 20), - title: const Text('添加至「稍后再看」', style: titleStyle), - ), - if (videoDetailCtr.epId == null) + (context, setState) { + final theme = Theme.of(context); + return Padding( + padding: const EdgeInsets.all(12), + child: Material( + clipBehavior: Clip.hardEdge, + color: theme.colorScheme.surface, + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: ListView( + padding: EdgeInsets.zero, + children: [ + const SizedBox(height: 14), ListTile( dense: true, onTap: () { Get.back(); - videoDetailCtr.showNoteList(context); + videoIntroController.viewLater(); }, - leading: const Icon(Icons.note_alt_outlined, size: 20), - title: const Text('查看笔记', style: titleStyle), + leading: const Icon(Icons.watch_later_outlined, size: 20), + title: const Text('添加至「稍后再看」', style: titleStyle), ), - if (widget.videoDetailCtr.videoItem['pic'] != null) - ListTile( - dense: true, - onTap: () { - Get.back(); - DownloadUtils.downloadImg( - context, - [widget.videoDetailCtr.videoItem['pic']], - ); - }, - leading: const Icon(Icons.image_outlined, size: 20), - title: const Text('保存封面', style: titleStyle), - ), - ListTile( - dense: true, - onTap: () => { - Get.back(), - PageUtils.scheduleExit(this.context, isFullScreen) - }, - leading: const Icon(Icons.hourglass_top_outlined, size: 20), - title: const Text('定时关闭', style: titleStyle), - ), - ListTile( - dense: true, - onTap: () => { - Get.back(), - videoDetailCtr.queryVideoUrl( - videoDetailCtr.playedTime, - ) - }, - leading: const Icon(Icons.refresh_outlined, size: 20), - title: const Text('重载视频', style: titleStyle), - ), - ListTile( - dense: true, - leading: - const Icon(Icons.stay_current_landscape_outlined, size: 20), - title: Row( - children: [ - const Text( - '超分辨率', - strutStyle: StrutStyle(leading: 0, height: 1), - style: TextStyle( - height: 1, - fontSize: 14, - ), - ), - const SizedBox(width: 10), - Builder( - builder: (context) => PopupMenuButton( - initialValue: SuperResolutionType - .values[widget.controller.superResolutionType], - child: Padding( - padding: const EdgeInsets.all(4), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - SuperResolutionType - .values[ - widget.controller.superResolutionType] - .title, - strutStyle: StrutStyle(leading: 0, height: 1), - style: TextStyle( - height: 1, - fontSize: 14, - color: - Theme.of(context).colorScheme.secondary, - ), - ), - Icon( - MdiIcons.unfoldMoreHorizontal, - size: - MediaQuery.textScalerOf(context).scale(14), - color: Theme.of(context).colorScheme.secondary, - ) - ], - ), - ), - onSelected: (value) { - widget.controller.setShader(value.index); - if (context.mounted) { - (context as Element).markNeedsBuild(); - } - }, - itemBuilder: (context) => SuperResolutionType.values - .map((item) => PopupMenuItem( - value: item, - child: Text(item.title), - )) - .toList(), - ), - ), - ], - ), - ), - ListTile( - dense: true, - title: const Text('CDN 设置', style: titleStyle), - leading: Icon(MdiIcons.cloudPlusOutline, size: 20), - subtitle: Text( - '当前:${CDNServiceCode.fromCode(defaultCDNService)!.description},无法播放请切换', - style: subTitleStyle, - ), - onTap: () async { - Get.back(); - String? result = await showDialog( - context: context, - builder: (context) { - return CdnSelectDialog( - sample: videoInfo.dash?.video?.first); + if (videoDetailCtr.epId == null) + ListTile( + dense: true, + onTap: () { + Get.back(); + videoDetailCtr.showNoteList(context); }, - ); - if (result != null) { - defaultCDNService = result; - setting.put(SettingBoxKey.CDNService, result); - SmartDialog.showToast( - '已设置为 ${CDNServiceCode.fromCode(result)!.description},正在重载视频'); - setState(() {}); - videoDetailCtr.queryVideoUrl( - videoDetailCtr.playedTime, - ); - } - }, - ), - SelfSizedHorizontalList( - itemCount: 4, - gapSize: 10, - padding: const EdgeInsets.symmetric(horizontal: 16), - childBuilder: (index) { - return switch (index) { - 0 => Obx( - () => ActionRowLineItem( - iconData: Icons.flip, - onTap: () { - widget.controller.flipX.value = - !widget.controller.flipX.value; - }, - text: " 左右翻转 ", - selectStatus: widget.controller.flipX.value, - ), - ), - 1 => Obx( - () => ActionRowLineItem( - icon: Transform.rotate( - angle: pi / 2, - child: Icon( - Icons.flip, - size: 13, - color: widget.controller.flipY.value - ? Theme.of(context) - .colorScheme - .onSecondaryContainer - : Theme.of(context).colorScheme.outline, - ), - ), - onTap: () { - widget.controller.flipY.value = - !widget.controller.flipY.value; - }, - text: " 上下翻转 ", - selectStatus: widget.controller.flipY.value, - ), - ), - 2 => Obx( - () => ActionRowLineItem( - iconData: Icons.headphones, - onTap: () { - widget.controller.onlyPlayAudio.value = - !widget.controller.onlyPlayAudio.value; - widget.videoDetailCtr.playerInit(); - }, - text: " 听视频 ", - selectStatus: widget.controller.onlyPlayAudio.value, - ), - ), - 3 => Obx( - () => ActionRowLineItem( - iconData: Icons.play_circle_outline, - onTap: widget.controller.setContinuePlayInBackground, - text: " 后台播放 ", - selectStatus: - widget.controller.continuePlayInBackground.value, - ), - ), - int() => throw UnimplementedError(), - }; - }, - ), - ListTile( - dense: true, - onTap: () => {Get.back(), showSetVideoQa()}, - leading: const Icon(Icons.play_circle_outline, size: 20), - title: const Text('选择画质', style: titleStyle), - subtitle: Text( - '当前画质 ${videoDetailCtr.currentVideoQa.description}', - style: subTitleStyle), - ), - if (videoDetailCtr.currentAudioQa != null) - ListTile( - dense: true, - onTap: () => {Get.back(), showSetAudioQa()}, - leading: const Icon(Icons.album_outlined, size: 20), - title: const Text('选择音质', style: titleStyle), - subtitle: Text( - '当前音质 ${videoDetailCtr.currentAudioQa!.description}', - style: subTitleStyle), - ), - ListTile( - dense: true, - onTap: () => {Get.back(), showSetDecodeFormats()}, - leading: const Icon(Icons.av_timer_outlined, size: 20), - title: const Text('解码格式', style: titleStyle), - subtitle: Text( - '当前解码格式 ${videoDetailCtr.currentDecodeFormats.description}', - style: subTitleStyle), - ), - ListTile( - dense: true, - onTap: () => {Get.back(), showSetRepeat()}, - leading: const Icon(Icons.repeat, size: 20), - title: const Text('播放顺序', style: titleStyle), - subtitle: Text(widget.controller.playRepeat.description, - style: subTitleStyle), - ), - ListTile( - dense: true, - onTap: () => {Get.back(), showSetDanmaku()}, - leading: Transform.rotate( - angle: pi, - child: const Icon(Icons.subtitles_outlined, size: 20), - ), - title: const Text('弹幕设置', style: titleStyle), - ), - ListTile( - dense: true, - onTap: () => {Get.back(), showSetSubtitle()}, - leading: const Icon(Icons.subtitles_outlined, size: 20), - title: const Text('字幕设置', style: titleStyle), - ), - if (videoDetailCtr.subtitles.isNotEmpty) - ListTile( - dense: true, - onTap: () => {Get.back(), onExportSubtitle()}, - leading: const Icon(Icons.download_outlined, size: 20), - title: const Text('保存字幕', style: titleStyle), - ), - ListTile( - dense: true, - title: const Text('播放信息', style: titleStyle), - leading: const Icon(Icons.info_outline, size: 20), - onTap: () { - Player? player = widget.controller.videoPlayerController; - if (player == null) { - SmartDialog.showToast('播放器未初始化'); - return; - } - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('播放信息'), - content: SizedBox( - width: double.maxFinite, - child: ListView( - children: [ - ListTile( - dense: true, - title: const Text("Resolution"), - subtitle: Text( - '${player.state.width}x${player.state.height}'), - onTap: () { - Utils.copyText( - 'Resolution\n${player.state.width}x${player.state.height}', - needToast: false, - ); - }, - ), - ListTile( - dense: true, - title: const Text("VideoParams"), - subtitle: - Text(player.state.videoParams.toString()), - onTap: () { - Utils.copyText( - 'VideoParams\n${player.state.videoParams}', - needToast: false, - ); - }, - ), - ListTile( - dense: true, - title: const Text("AudioParams"), - subtitle: - Text(player.state.audioParams.toString()), - onTap: () { - Utils.copyText( - 'AudioParams\n${player.state.audioParams}', - needToast: false, - ); - }, - ), - ListTile( - dense: true, - title: const Text("Media"), - subtitle: - Text(player.state.playlist.toString()), - onTap: () { - Utils.copyText( - 'Media\n${player.state.playlist}', - needToast: false, - ); - }, - ), - ListTile( - dense: true, - title: const Text("AudioTrack"), - subtitle: - Text(player.state.track.audio.toString()), - onTap: () { - Utils.copyText( - 'AudioTrack\n${player.state.track.audio}', - needToast: false, - ); - }, - ), - ListTile( - dense: true, - title: const Text("VideoTrack"), - subtitle: - Text(player.state.track.video.toString()), - onTap: () { - Utils.copyText( - 'VideoTrack\n${player.state.track.audio}', - needToast: false, - ); - }, - ), - ListTile( - dense: true, - title: const Text("pitch"), - subtitle: Text(player.state.pitch.toString()), - onTap: () { - Utils.copyText( - 'pitch\n${player.state.pitch}', - needToast: false, - ); - }), - ListTile( - dense: true, - title: const Text("rate"), - subtitle: Text(player.state.rate.toString()), - onTap: () { - Utils.copyText( - 'rate\n${player.state.rate}', - needToast: false, - ); - }), - ListTile( - dense: true, - title: const Text("AudioBitrate"), - subtitle: - Text(player.state.audioBitrate.toString()), - onTap: () { - Utils.copyText( - 'AudioBitrate\n${player.state.audioBitrate}', - needToast: false, - ); - }, - ), - ListTile( - dense: true, - title: const Text("Volume"), - subtitle: Text(player.state.volume.toString()), - onTap: () { - Utils.copyText( - 'Volume\n${player.state.volume}', - needToast: false, - ); - }, - ), - ], - ), - ), - actions: [ - TextButton( - onPressed: () => Get.back(), - child: Text( - '确定', - style: TextStyle( - color: Theme.of(context).colorScheme.outline), - ), - ), - ], + leading: const Icon(Icons.note_alt_outlined, size: 20), + title: const Text('查看笔记', style: titleStyle), + ), + if (widget.videoDetailCtr.videoItem['pic'] != null) + ListTile( + dense: true, + onTap: () { + Get.back(); + DownloadUtils.downloadImg( + context, + [widget.videoDetailCtr.videoItem['pic']], ); }, - ); - }, - ), - ListTile( - dense: true, - onTap: () { - if (!Accounts.main.isLogin) { - SmartDialog.showToast('账号未登录'); - return; - } - Get.back(); - PageUtils.reportVideo(videoDetailCtr.oid.value); - }, - leading: const Icon(Icons.error_outline, size: 20), - title: const Text('举报', style: titleStyle), - ), - const SizedBox(height: 14), - ], + leading: const Icon(Icons.image_outlined, size: 20), + title: const Text('保存封面', style: titleStyle), + ), + ListTile( + dense: true, + onTap: () => { + Get.back(), + PageUtils.scheduleExit(this.context, isFullScreen) + }, + leading: const Icon(Icons.hourglass_top_outlined, size: 20), + title: const Text('定时关闭', style: titleStyle), + ), + ListTile( + dense: true, + onTap: () => { + Get.back(), + videoDetailCtr.queryVideoUrl( + videoDetailCtr.playedTime, + ) + }, + leading: const Icon(Icons.refresh_outlined, size: 20), + title: const Text('重载视频', style: titleStyle), + ), + ListTile( + dense: true, + leading: const Icon(Icons.stay_current_landscape_outlined, + size: 20), + title: Row( + children: [ + const Text( + '超分辨率', + strutStyle: StrutStyle(leading: 0, height: 1), + style: TextStyle( + height: 1, + fontSize: 14, + ), + ), + const SizedBox(width: 10), + Builder( + builder: (context) => PopupMenuButton( + initialValue: SuperResolutionType + .values[widget.controller.superResolutionType], + child: Padding( + padding: const EdgeInsets.all(4), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + SuperResolutionType + .values[ + widget.controller.superResolutionType] + .title, + strutStyle: StrutStyle(leading: 0, height: 1), + style: TextStyle( + height: 1, + fontSize: 14, + color: theme.colorScheme.secondary, + ), + ), + Icon( + MdiIcons.unfoldMoreHorizontal, + size: MediaQuery.textScalerOf(context) + .scale(14), + color: theme.colorScheme.secondary, + ) + ], + ), + ), + onSelected: (value) { + widget.controller.setShader(value.index); + if (context.mounted) { + (context as Element).markNeedsBuild(); + } + }, + itemBuilder: (context) => SuperResolutionType.values + .map((item) => PopupMenuItem( + value: item, + child: Text(item.title), + )) + .toList(), + ), + ), + ], + ), + ), + ListTile( + dense: true, + title: const Text('CDN 设置', style: titleStyle), + leading: Icon(MdiIcons.cloudPlusOutline, size: 20), + subtitle: Text( + '当前:${CDNServiceCode.fromCode(defaultCDNService)!.description},无法播放请切换', + style: subTitleStyle, + ), + onTap: () async { + Get.back(); + String? result = await showDialog( + context: context, + builder: (context) { + return CdnSelectDialog( + sample: videoInfo.dash?.video?.first); + }, + ); + if (result != null) { + defaultCDNService = result; + setting.put(SettingBoxKey.CDNService, result); + SmartDialog.showToast( + '已设置为 ${CDNServiceCode.fromCode(result)!.description},正在重载视频'); + setState(() {}); + videoDetailCtr.queryVideoUrl( + videoDetailCtr.playedTime, + ); + } + }, + ), + SelfSizedHorizontalList( + itemCount: 4, + gapSize: 10, + padding: const EdgeInsets.symmetric(horizontal: 16), + childBuilder: (index) { + return switch (index) { + 0 => Obx( + () => ActionRowLineItem( + iconData: Icons.flip, + onTap: () { + widget.controller.flipX.value = + !widget.controller.flipX.value; + }, + text: " 左右翻转 ", + selectStatus: widget.controller.flipX.value, + ), + ), + 1 => Obx( + () => ActionRowLineItem( + icon: Transform.rotate( + angle: pi / 2, + child: Icon( + Icons.flip, + size: 13, + color: widget.controller.flipY.value + ? theme.colorScheme.onSecondaryContainer + : theme.colorScheme.outline, + ), + ), + onTap: () { + widget.controller.flipY.value = + !widget.controller.flipY.value; + }, + text: " 上下翻转 ", + selectStatus: widget.controller.flipY.value, + ), + ), + 2 => Obx( + () => ActionRowLineItem( + iconData: Icons.headphones, + onTap: () { + widget.controller.onlyPlayAudio.value = + !widget.controller.onlyPlayAudio.value; + widget.videoDetailCtr.playerInit(); + }, + text: " 听视频 ", + selectStatus: widget.controller.onlyPlayAudio.value, + ), + ), + 3 => Obx( + () => ActionRowLineItem( + iconData: Icons.play_circle_outline, + onTap: + widget.controller.setContinuePlayInBackground, + text: " 后台播放 ", + selectStatus: widget + .controller.continuePlayInBackground.value, + ), + ), + int() => throw UnimplementedError(), + }; + }, + ), + ListTile( + dense: true, + onTap: () => {Get.back(), showSetVideoQa()}, + leading: const Icon(Icons.play_circle_outline, size: 20), + title: const Text('选择画质', style: titleStyle), + subtitle: Text( + '当前画质 ${videoDetailCtr.currentVideoQa.description}', + style: subTitleStyle), + ), + if (videoDetailCtr.currentAudioQa != null) + ListTile( + dense: true, + onTap: () => {Get.back(), showSetAudioQa()}, + leading: const Icon(Icons.album_outlined, size: 20), + title: const Text('选择音质', style: titleStyle), + subtitle: Text( + '当前音质 ${videoDetailCtr.currentAudioQa!.description}', + style: subTitleStyle), + ), + ListTile( + dense: true, + onTap: () => {Get.back(), showSetDecodeFormats()}, + leading: const Icon(Icons.av_timer_outlined, size: 20), + title: const Text('解码格式', style: titleStyle), + subtitle: Text( + '当前解码格式 ${videoDetailCtr.currentDecodeFormats.description}', + style: subTitleStyle), + ), + ListTile( + dense: true, + onTap: () => {Get.back(), showSetRepeat()}, + leading: const Icon(Icons.repeat, size: 20), + title: const Text('播放顺序', style: titleStyle), + subtitle: Text(widget.controller.playRepeat.description, + style: subTitleStyle), + ), + ListTile( + dense: true, + onTap: () => {Get.back(), showSetDanmaku()}, + leading: Transform.rotate( + angle: pi, + child: const Icon(Icons.subtitles_outlined, size: 20), + ), + title: const Text('弹幕设置', style: titleStyle), + ), + ListTile( + dense: true, + onTap: () => {Get.back(), showSetSubtitle()}, + leading: const Icon(Icons.subtitles_outlined, size: 20), + title: const Text('字幕设置', style: titleStyle), + ), + if (videoDetailCtr.subtitles.isNotEmpty) + ListTile( + dense: true, + onTap: () => {Get.back(), onExportSubtitle()}, + leading: const Icon(Icons.download_outlined, size: 20), + title: const Text('保存字幕', style: titleStyle), + ), + ListTile( + dense: true, + title: const Text('播放信息', style: titleStyle), + leading: const Icon(Icons.info_outline, size: 20), + onTap: () { + Player? player = widget.controller.videoPlayerController; + if (player == null) { + SmartDialog.showToast('播放器未初始化'); + return; + } + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('播放信息'), + content: SizedBox( + width: double.maxFinite, + child: ListView( + children: [ + ListTile( + dense: true, + title: const Text("Resolution"), + subtitle: Text( + '${player.state.width}x${player.state.height}'), + onTap: () { + Utils.copyText( + 'Resolution\n${player.state.width}x${player.state.height}', + needToast: false, + ); + }, + ), + ListTile( + dense: true, + title: const Text("VideoParams"), + subtitle: + Text(player.state.videoParams.toString()), + onTap: () { + Utils.copyText( + 'VideoParams\n${player.state.videoParams}', + needToast: false, + ); + }, + ), + ListTile( + dense: true, + title: const Text("AudioParams"), + subtitle: + Text(player.state.audioParams.toString()), + onTap: () { + Utils.copyText( + 'AudioParams\n${player.state.audioParams}', + needToast: false, + ); + }, + ), + ListTile( + dense: true, + title: const Text("Media"), + subtitle: + Text(player.state.playlist.toString()), + onTap: () { + Utils.copyText( + 'Media\n${player.state.playlist}', + needToast: false, + ); + }, + ), + ListTile( + dense: true, + title: const Text("AudioTrack"), + subtitle: + Text(player.state.track.audio.toString()), + onTap: () { + Utils.copyText( + 'AudioTrack\n${player.state.track.audio}', + needToast: false, + ); + }, + ), + ListTile( + dense: true, + title: const Text("VideoTrack"), + subtitle: + Text(player.state.track.video.toString()), + onTap: () { + Utils.copyText( + 'VideoTrack\n${player.state.track.audio}', + needToast: false, + ); + }, + ), + ListTile( + dense: true, + title: const Text("pitch"), + subtitle: + Text(player.state.pitch.toString()), + onTap: () { + Utils.copyText( + 'pitch\n${player.state.pitch}', + needToast: false, + ); + }), + ListTile( + dense: true, + title: const Text("rate"), + subtitle: + Text(player.state.rate.toString()), + onTap: () { + Utils.copyText( + 'rate\n${player.state.rate}', + needToast: false, + ); + }), + ListTile( + dense: true, + title: const Text("AudioBitrate"), + subtitle: Text( + player.state.audioBitrate.toString()), + onTap: () { + Utils.copyText( + 'AudioBitrate\n${player.state.audioBitrate}', + needToast: false, + ); + }, + ), + ListTile( + dense: true, + title: const Text("Volume"), + subtitle: + Text(player.state.volume.toString()), + onTap: () { + Utils.copyText( + 'Volume\n${player.state.volume}', + needToast: false, + ); + }, + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Get.back(), + child: Text( + '确定', + style: + TextStyle(color: theme.colorScheme.outline), + ), + ), + ], + ); + }, + ); + }, + ), + ListTile( + dense: true, + onTap: () { + if (!Accounts.main.isLogin) { + SmartDialog.showToast('账号未登录'); + return; + } + Get.back(); + PageUtils.reportVideo(videoDetailCtr.oid.value); + }, + leading: const Icon(Icons.error_outline, size: 20), + title: const Text('举报', style: titleStyle), + ), + const SizedBox(height: 14), + ], + ), ), - ), - ), + ); + }, ); } @@ -592,110 +596,112 @@ class HeaderControlState extends State { } showBottomSheet( - (context, setState) => Padding( - padding: const EdgeInsets.all(12), - child: Material( - clipBehavior: Clip.hardEdge, - color: Theme.of(context).colorScheme.surface, - borderRadius: const BorderRadius.all(Radius.circular(12)), - child: Column( - children: [ - SizedBox( - height: 45, - child: GestureDetector( - onTap: () { - SmartDialog.showToast( - '标灰画质需要bilibili会员(已是会员?请关闭无痕模式);4k和杜比视界播放效果可能不佳'); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text('选择画质', style: titleStyle), - SizedBox(width: buttonSpace), - Icon( - Icons.info_outline, - size: 16, - color: Theme.of(context).colorScheme.outline, - ) - ], - ), - ), - ), - Expanded( - child: Material( - color: Colors.transparent, - child: Scrollbar( - child: ListView( - padding: EdgeInsets.zero, + (context, setState) { + final theme = Theme.of(context); + return Padding( + padding: const EdgeInsets.all(12), + child: Material( + clipBehavior: Clip.hardEdge, + color: theme.colorScheme.surface, + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: Column( + children: [ + SizedBox( + height: 45, + child: GestureDetector( + onTap: () { + SmartDialog.showToast( + '标灰画质需要bilibili会员(已是会员?请关闭无痕模式);4k和杜比视界播放效果可能不佳'); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - for (int i = 0; i < totalQaSam; i++) ...[ - ListTile( - dense: true, - onTap: () async { - if (currentVideoQa.code == - videoFormat[i].quality) { - return; - } - Get.back(); - final int quality = videoFormat[i].quality!; - videoDetailCtr.currentVideoQa = - VideoQualityCode.fromCode(quality)!; - videoDetailCtr.updatePlayer(); - - // update - late String oldQualityDesc; - await Connectivity() - .checkConnectivity() - .then((res) { - if (res.contains(ConnectivityResult.wifi)) { - oldQualityDesc = VideoQualityCode.fromCode( - GStorage.defaultVideoQa)! - .description; - setting.put( - SettingBoxKey.defaultVideoQa, - quality, - ); - } else { - oldQualityDesc = VideoQualityCode.fromCode( - GStorage.defaultVideoQaCellular)! - .description; - setting.put( - SettingBoxKey.defaultVideoQaCellular, - quality, - ); - } - }); - SmartDialog.showToast( - "默认画质由:$oldQualityDesc 变为:${VideoQualityCode.fromCode(quality)!.description}", - ); - }, - // 可能包含会员解锁画质 - enabled: i >= totalQaSam - userfulQaSam, - contentPadding: - const EdgeInsets.only(left: 20, right: 20), - title: Text(videoFormat[i].newDesc!), - trailing: currentVideoQa.code == - videoFormat[i].quality - ? Icon( - Icons.done, - color: - Theme.of(context).colorScheme.primary, - ) - : Text( - videoFormat[i].format!, - style: subTitleStyle, - ), - ), - ] + const Text('选择画质', style: titleStyle), + SizedBox(width: buttonSpace), + Icon( + Icons.info_outline, + size: 16, + color: theme.colorScheme.outline, + ) ], ), ), ), - ), - ], + Expanded( + child: Material( + color: Colors.transparent, + child: Scrollbar( + child: ListView( + padding: EdgeInsets.zero, + children: [ + for (int i = 0; i < totalQaSam; i++) ...[ + ListTile( + dense: true, + onTap: () async { + if (currentVideoQa.code == + videoFormat[i].quality) { + return; + } + Get.back(); + final int quality = videoFormat[i].quality!; + videoDetailCtr.currentVideoQa = + VideoQualityCode.fromCode(quality)!; + videoDetailCtr.updatePlayer(); + + // update + late String oldQualityDesc; + await Connectivity() + .checkConnectivity() + .then((res) { + if (res.contains(ConnectivityResult.wifi)) { + oldQualityDesc = VideoQualityCode.fromCode( + GStorage.defaultVideoQa)! + .description; + setting.put( + SettingBoxKey.defaultVideoQa, + quality, + ); + } else { + oldQualityDesc = VideoQualityCode.fromCode( + GStorage.defaultVideoQaCellular)! + .description; + setting.put( + SettingBoxKey.defaultVideoQaCellular, + quality, + ); + } + }); + SmartDialog.showToast( + "默认画质由:$oldQualityDesc 变为:${VideoQualityCode.fromCode(quality)!.description}", + ); + }, + // 可能包含会员解锁画质 + enabled: i >= totalQaSam - userfulQaSam, + contentPadding: + const EdgeInsets.only(left: 20, right: 20), + title: Text(videoFormat[i].newDesc!), + trailing: + currentVideoQa.code == videoFormat[i].quality + ? Icon( + Icons.done, + color: theme.colorScheme.primary, + ) + : Text( + videoFormat[i].format!, + style: subTitleStyle, + ), + ), + ] + ], + ), + ), + ), + ), + ], + ), ), - ), - ), + ); + }, ); } @@ -704,86 +710,89 @@ class HeaderControlState extends State { final AudioQuality currentAudioQa = videoDetailCtr.currentAudioQa!; final List audio = videoInfo.dash!.audio!; showBottomSheet( - (context, setState) => Padding( - padding: const EdgeInsets.all(12), - child: Material( - clipBehavior: Clip.hardEdge, - color: Theme.of(context).colorScheme.surface, - borderRadius: const BorderRadius.all(Radius.circular(12)), - child: Column( - children: [ - const SizedBox( - height: 45, - child: Center(child: Text('选择音质', style: titleStyle))), - Expanded( - child: Material( - color: Colors.transparent, - child: ListView( - padding: EdgeInsets.zero, - children: [ - for (final AudioItem i in audio) ...[ - ListTile( - dense: true, - onTap: () async { - if (currentAudioQa.code == i.id) { - return; - } - Get.back(); - final int quality = i.id!; - videoDetailCtr.currentAudioQa = - AudioQualityCode.fromCode(quality)!; - videoDetailCtr.updatePlayer(); - - // update - late String oldQualityDesc; - await Connectivity() - .checkConnectivity() - .then((res) { - if (res.contains(ConnectivityResult.wifi)) { - oldQualityDesc = AudioQualityCode.fromCode( - GStorage.defaultAudioQa)! - .description; - setting.put( - SettingBoxKey.defaultAudioQa, - quality, - ); - } else { - oldQualityDesc = AudioQualityCode.fromCode( - GStorage.defaultAudioQaCellular)! - .description; - setting.put( - SettingBoxKey.defaultAudioQaCellular, - quality, - ); + (context, setState) { + final theme = Theme.of(context); + return Padding( + padding: const EdgeInsets.all(12), + child: Material( + clipBehavior: Clip.hardEdge, + color: theme.colorScheme.surface, + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: Column( + children: [ + const SizedBox( + height: 45, + child: Center(child: Text('选择音质', style: titleStyle))), + Expanded( + child: Material( + color: Colors.transparent, + child: ListView( + padding: EdgeInsets.zero, + children: [ + for (final AudioItem i in audio) ...[ + ListTile( + dense: true, + onTap: () async { + if (currentAudioQa.code == i.id) { + return; } - }); - SmartDialog.showToast( - "默认音质由:$oldQualityDesc 变为:${AudioQualityCode.fromCode(quality)!.description}", - ); - }, - contentPadding: - const EdgeInsets.only(left: 20, right: 20), - title: Text(i.quality!), - subtitle: Text( - i.codecs!, - style: subTitleStyle, + Get.back(); + final int quality = i.id!; + videoDetailCtr.currentAudioQa = + AudioQualityCode.fromCode(quality)!; + videoDetailCtr.updatePlayer(); + + // update + late String oldQualityDesc; + await Connectivity() + .checkConnectivity() + .then((res) { + if (res.contains(ConnectivityResult.wifi)) { + oldQualityDesc = AudioQualityCode.fromCode( + GStorage.defaultAudioQa)! + .description; + setting.put( + SettingBoxKey.defaultAudioQa, + quality, + ); + } else { + oldQualityDesc = AudioQualityCode.fromCode( + GStorage.defaultAudioQaCellular)! + .description; + setting.put( + SettingBoxKey.defaultAudioQaCellular, + quality, + ); + } + }); + SmartDialog.showToast( + "默认音质由:$oldQualityDesc 变为:${AudioQualityCode.fromCode(quality)!.description}", + ); + }, + contentPadding: + const EdgeInsets.only(left: 20, right: 20), + title: Text(i.quality!), + subtitle: Text( + i.codecs!, + style: subTitleStyle, + ), + trailing: currentAudioQa.code == i.id + ? Icon( + Icons.done, + color: theme.colorScheme.primary, + ) + : const SizedBox.shrink(), ), - trailing: currentAudioQa.code == i.id - ? Icon( - Icons.done, - color: Theme.of(context).colorScheme.primary, - ) - : const SizedBox.shrink(), - ), - ] - ], + ] + ], + ), ), ), - ), - ], + ], + ), ), - ), - ), + ); + }, ); } @@ -804,59 +813,62 @@ class HeaderControlState extends State { } showBottomSheet( - (context, setState) => Padding( - padding: const EdgeInsets.all(12), - child: Material( - clipBehavior: Clip.hardEdge, - color: Theme.of(context).colorScheme.surface, - borderRadius: const BorderRadius.all(Radius.circular(12)), - child: Column( - children: [ - const SizedBox( - height: 45, - child: Center(child: Text('选择解码格式', style: titleStyle))), - Expanded( - child: Material( - color: Colors.transparent, - child: ListView( - padding: EdgeInsets.zero, - children: [ - for (var i in list) ...[ - ListTile( - dense: true, - onTap: () { - if (i.startsWith(currentDecodeFormats.code)) { - return; - } - videoDetailCtr.currentDecodeFormats = - VideoDecodeFormatsCode.fromString(i)!; - videoDetailCtr.updatePlayer(); - Get.back(); - }, - contentPadding: - const EdgeInsets.only(left: 20, right: 20), - title: Text(VideoDecodeFormatsCode.fromString(i)! - .description), - subtitle: Text( - i!, - style: subTitleStyle, + (context, setState) { + final theme = Theme.of(context); + return Padding( + padding: const EdgeInsets.all(12), + child: Material( + clipBehavior: Clip.hardEdge, + color: theme.colorScheme.surface, + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: Column( + children: [ + const SizedBox( + height: 45, + child: Center(child: Text('选择解码格式', style: titleStyle))), + Expanded( + child: Material( + color: Colors.transparent, + child: ListView( + padding: EdgeInsets.zero, + children: [ + for (var i in list) ...[ + ListTile( + dense: true, + onTap: () { + if (i.startsWith(currentDecodeFormats.code)) { + return; + } + videoDetailCtr.currentDecodeFormats = + VideoDecodeFormatsCode.fromString(i)!; + videoDetailCtr.updatePlayer(); + Get.back(); + }, + contentPadding: + const EdgeInsets.only(left: 20, right: 20), + title: Text(VideoDecodeFormatsCode.fromString(i)! + .description), + subtitle: Text( + i!, + style: subTitleStyle, + ), + trailing: i.startsWith(currentDecodeFormats.code) + ? Icon( + Icons.done, + color: theme.colorScheme.primary, + ) + : const SizedBox.shrink(), ), - trailing: i.startsWith(currentDecodeFormats.code) - ? Icon( - Icons.done, - color: Theme.of(context).colorScheme.primary, - ) - : const SizedBox.shrink(), - ), - ] - ], + ] + ], + ), ), ), - ), - ], + ], + ), ), - ), - ), + ); + }, ); } @@ -941,10 +953,12 @@ class HeaderControlState extends State { showBottomSheet( padding: isFullScreen ? 70 : null, (context, setState) { + final theme = Theme.of(context); + final sliderTheme = SliderThemeData( trackShape: MSliderTrackShape(), - thumbColor: Theme.of(context).colorScheme.primary, - activeTrackColor: Theme.of(context).colorScheme.primary, + thumbColor: theme.colorScheme.primary, + activeTrackColor: theme.colorScheme.primary, trackHeight: 10, thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 6.0), ); @@ -1016,7 +1030,7 @@ class HeaderControlState extends State { padding: const EdgeInsets.all(12), child: Material( clipBehavior: Clip.hardEdge, - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), child: Padding( padding: const EdgeInsets.only(left: 14, right: 14), @@ -1033,7 +1047,7 @@ class HeaderControlState extends State { children: [ Text( '字体大小 ${(subtitleFontScale * 100).toStringAsFixed(1)}%'), - resetBtn('100.0%', () => updateFontScale(1.0)), + resetBtn(theme, '100.0%', () => updateFontScale(1.0)), ], ), Padding( @@ -1061,7 +1075,7 @@ class HeaderControlState extends State { children: [ Text( '全屏字体大小 ${(subtitleFontScaleFS * 100).toStringAsFixed(1)}%'), - resetBtn('150.0%', () => updateFontScaleFS(1.5)), + resetBtn(theme, '150.0%', () => updateFontScaleFS(1.5)), ], ), Padding( @@ -1088,7 +1102,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('字体粗细 ${subtitleFontWeight + 1}(可能无法精确调节)'), - resetBtn(6, () => updateFontWeight(5)), + resetBtn(theme, 6, () => updateFontWeight(5)), ], ), Padding( @@ -1116,7 +1130,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('描边粗细 $subtitleStrokeWidth'), - resetBtn(2.0, () => updateStrokeWidth(2.0)), + resetBtn(theme, 2.0, () => updateStrokeWidth(2.0)), ], ), Padding( @@ -1142,7 +1156,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('左右边距 $subtitlePaddingH'), - resetBtn(24, () => updateHorizontalPadding(24)), + resetBtn(theme, 24, () => updateHorizontalPadding(24)), ], ), Padding( @@ -1170,7 +1184,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('底部边距 $subtitlePaddingB'), - resetBtn(24, () => updateBottomPadding(24)), + resetBtn(theme, 24, () => updateBottomPadding(24)), ], ), Padding( @@ -1198,7 +1212,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('背景不透明度 ${(subtitleBgOpaticy * 100).toInt()}%'), - resetBtn('67%', () => updateOpacity(0.67)), + resetBtn(theme, '67%', () => updateOpacity(0.67)), ], ), Padding( @@ -1229,14 +1243,14 @@ class HeaderControlState extends State { ); } - Widget resetBtn(def, VoidCallback onPressed) { + Widget resetBtn(ThemeData theme, def, VoidCallback onPressed) { return iconButton( context: context, tooltip: '默认值: $def', icon: Icons.refresh, onPressed: onPressed, bgColor: Colors.transparent, - iconColor: Theme.of(context).colorScheme.outline, + iconColor: theme.colorScheme.outline, size: 24, iconSize: 24, ); @@ -1277,10 +1291,12 @@ class HeaderControlState extends State { showBottomSheet( (context, setState) { + final theme = Theme.of(context); + final sliderTheme = SliderThemeData( trackShape: MSliderTrackShape(), - thumbColor: Theme.of(context).colorScheme.primary, - activeTrackColor: Theme.of(context).colorScheme.primary, + thumbColor: theme.colorScheme.primary, + activeTrackColor: theme.colorScheme.primary, trackHeight: 10, thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 6.0), ); @@ -1419,7 +1435,7 @@ class HeaderControlState extends State { padding: const EdgeInsets.all(12), child: Material( clipBehavior: Clip.hardEdge, - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), child: Padding( padding: const EdgeInsets.only(left: 14, right: 14), @@ -1535,7 +1551,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('显示区域 ${showArea * 100}%'), - resetBtn('50.0%', () => updateShowArea(0.5)), + resetBtn(theme, '50.0%', () => updateShowArea(0.5)), ], ), Padding( @@ -1563,7 +1579,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('不透明度 ${opacity * 100}%'), - resetBtn('100.0%', () => updateOpacity(1.0)), + resetBtn(theme, '100.0%', () => updateOpacity(1.0)), ], ), Padding( @@ -1589,7 +1605,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('字体粗细 ${fontWeight + 1}(可能无法精确调节)'), - resetBtn(6, () => updateFontWeight(5)), + resetBtn(theme, 6, () => updateFontWeight(5)), ], ), Padding( @@ -1617,7 +1633,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('描边粗细 $strokeWidth'), - resetBtn(1.5, () => updateStrokeWidth(1.5)), + resetBtn(theme, 1.5, () => updateStrokeWidth(1.5)), ], ), Padding( @@ -1643,7 +1659,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('字体大小 ${(fontSize * 100).toStringAsFixed(1)}%'), - resetBtn('100.0%', () => updateFontSize(1.0)), + resetBtn(theme, '100.0%', () => updateFontSize(1.0)), ], ), Padding( @@ -1669,7 +1685,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('全屏字体大小 ${(fontSizeFS * 100).toStringAsFixed(1)}%'), - resetBtn('120.0%', () => updateFontSizeFS(1.2)), + resetBtn(theme, '120.0%', () => updateFontSizeFS(1.2)), ], ), Padding( @@ -1695,7 +1711,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('滚动弹幕时长 $danmakuDuration 秒'), - resetBtn(7.0, () => updateDuration(7.0)), + resetBtn(theme, 7.0, () => updateDuration(7.0)), ], ), Padding( @@ -1723,7 +1739,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('静态弹幕时长 $danmakuStaticDuration 秒'), - resetBtn(4.0, () => updateStaticDuration(4.0)), + resetBtn(theme, 4.0, () => updateStaticDuration(4.0)), ], ), Padding( @@ -1751,7 +1767,7 @@ class HeaderControlState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('弹幕行高 $danmakuLineHeight'), - resetBtn(1.6, () => updateLineHeight(1.6)), + resetBtn(theme, 1.6, () => updateLineHeight(1.6)), ], ), Padding( @@ -1785,49 +1801,52 @@ class HeaderControlState extends State { /// 播放顺序 void showSetRepeat() { showBottomSheet( - (context, setState) => Padding( - padding: const EdgeInsets.all(12), - child: Material( - clipBehavior: Clip.hardEdge, - color: Theme.of(context).colorScheme.surface, - borderRadius: const BorderRadius.all(Radius.circular(12)), - child: Column( - children: [ - const SizedBox( - height: 45, - child: Center(child: Text('选择播放顺序', style: titleStyle))), - Expanded( - child: Material( - color: Colors.transparent, - child: ListView( - padding: EdgeInsets.zero, - children: [ - for (final PlayRepeat i in PlayRepeat.values) ...[ - ListTile( - dense: true, - onTap: () { - widget.controller.setPlayRepeat(i); - Get.back(); - }, - contentPadding: - const EdgeInsets.only(left: 20, right: 20), - title: Text(i.description), - trailing: widget.controller.playRepeat == i - ? Icon( - Icons.done, - color: Theme.of(context).colorScheme.primary, - ) - : const SizedBox.shrink(), - ) + (context, setState) { + final theme = Theme.of(context); + return Padding( + padding: const EdgeInsets.all(12), + child: Material( + clipBehavior: Clip.hardEdge, + color: theme.colorScheme.surface, + borderRadius: const BorderRadius.all(Radius.circular(12)), + child: Column( + children: [ + const SizedBox( + height: 45, + child: Center(child: Text('选择播放顺序', style: titleStyle))), + Expanded( + child: Material( + color: Colors.transparent, + child: ListView( + padding: EdgeInsets.zero, + children: [ + for (final PlayRepeat i in PlayRepeat.values) ...[ + ListTile( + dense: true, + onTap: () { + widget.controller.setPlayRepeat(i); + Get.back(); + }, + contentPadding: + const EdgeInsets.only(left: 20, right: 20), + title: Text(i.description), + trailing: widget.controller.playRepeat == i + ? Icon( + Icons.done, + color: theme.colorScheme.primary, + ) + : const SizedBox.shrink(), + ) + ], ], - ], + ), ), ), - ), - ], + ], + ), ), - ), - ), + ); + }, ); } @@ -2110,6 +2129,7 @@ class HeaderControlState extends State { SettingBoxKey.enableBackgroundPlay, defaultValue: true); if (!enableBackgroundPlay && mounted) { + final theme = Theme.of(context); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Column( @@ -2138,8 +2158,7 @@ class HeaderControlState extends State { foregroundColor: WidgetStateProperty.resolveWith( (states) { - return Theme.of(context) - .snackBarTheme + return theme.snackBarTheme .actionTextColor; }), ), @@ -2155,8 +2174,7 @@ class HeaderControlState extends State { foregroundColor: WidgetStateProperty.resolveWith( (states) { - return Theme.of(context) - .snackBarTheme + return theme.snackBarTheme .actionTextColor; }), ), diff --git a/lib/pages/video/detail/widgets/media_list_panel.dart b/lib/pages/video/detail/widgets/media_list_panel.dart index fa708364..80ed6451 100644 --- a/lib/pages/video/detail/widgets/media_list_panel.dart +++ b/lib/pages/video/detail/widgets/media_list_panel.dart @@ -78,9 +78,9 @@ class _MediaListPanelState } @override - Widget get buildPage { + Widget buildPage(ThemeData theme) { return Material( - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, child: Column( children: [ AppBar( @@ -111,10 +111,10 @@ class _MediaListPanelState ), Divider( height: 1, - color: Theme.of(context).colorScheme.outline.withOpacity(0.1), + color: theme.colorScheme.outline.withOpacity(0.1), ), Expanded( - child: enableSlide ? slideList() : buildList, + child: enableSlide ? slideList(theme) : buildList(theme), ), ], ), @@ -122,16 +122,18 @@ class _MediaListPanelState } @override - Widget get buildList => widget.loadPrevious != null - ? refreshIndicator( - onRefresh: () async { - await widget.loadPrevious!(); - }, - child: _buildList, - ) - : _buildList; + Widget buildList(ThemeData theme) { + return widget.loadPrevious != null + ? refreshIndicator( + onRefresh: () async { + await widget.loadPrevious!(); + }, + child: _buildList(theme), + ) + : _buildList(theme); + } - Widget get _buildList => Obx( + Widget _buildList(ThemeData theme) => Obx( () { final showDelBtn = widget.onDelete != null && widget.mediaList.length > 1; @@ -172,7 +174,6 @@ class _MediaListPanelState }, onLongPress: () { imageSaveDialog( - context: context, title: item.title, cover: item.cover, ); @@ -225,9 +226,7 @@ class _MediaListPanelState ? FontWeight.bold : null, color: item.bvid == widget.getBvId() - ? Theme.of(context) - .colorScheme - .primary + ? theme.colorScheme.primary : null, ), ), @@ -236,8 +235,7 @@ class _MediaListPanelState item.upper!.name!, style: TextStyle( fontSize: 12, - color: - Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), const SizedBox(height: 3), @@ -283,9 +281,7 @@ class _MediaListPanelState child: Icon( Icons.clear, size: 18, - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, + color: theme.colorScheme.onSurfaceVariant, ), ), ), diff --git a/lib/pages/whisper/view.dart b/lib/pages/whisper/view.dart index 5dd5d3db..9651ee85 100644 --- a/lib/pages/whisper/view.dart +++ b/lib/pages/whisper/view.dart @@ -93,6 +93,7 @@ class _WhisperPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: List.generate(_whisperController.msgFeedTopItems.length, (index) { + final ThemeData theme = Theme.of(context); return GestureDetector( behavior: HitTestBehavior.opaque, child: Padding( @@ -111,12 +112,11 @@ class _WhisperPageState extends State { alignment: Alignment.topRight, child: CircleAvatar( radius: 22, - backgroundColor: - Theme.of(context).colorScheme.onInverseSurface, + backgroundColor: theme.colorScheme.onInverseSurface, child: Icon( _whisperController.msgFeedTopItems[index]['icon'], size: 20, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ), diff --git a/lib/pages/whisper/widgets/item.dart b/lib/pages/whisper/widgets/item.dart index 5185a68f..fa5599c8 100644 --- a/lib/pages/whisper/widgets/item.dart +++ b/lib/pages/whisper/widgets/item.dart @@ -21,6 +21,7 @@ class WhisperSessionItem extends StatelessWidget { @override Widget build(BuildContext context) { dynamic content = item.lastMsg?.content; + final ThemeData theme = Theme.of(context); if (content == null || content == "") { content = '不支持的消息类型'; } else { @@ -37,9 +38,7 @@ class WhisperSessionItem extends StatelessWidget { } return ListTile( - tileColor: item.topTs == 0 - ? null - : Theme.of(context).colorScheme.onInverseSurface, + tileColor: item.topTs == 0 ? null : theme.colorScheme.onInverseSurface, onLongPress: () { showDialog( context: context, @@ -122,17 +121,15 @@ class WhisperSessionItem extends StatelessWidget { '$content', maxLines: 1, overflow: TextOverflow.ellipsis, - style: Theme.of(context) - .textTheme - .labelMedium! - .copyWith(color: Theme.of(context).colorScheme.outline), + style: theme.textTheme.labelMedium! + .copyWith(color: theme.colorScheme.outline), ), trailing: item.lastMsg?.timestamp != null ? Text( Utils.dateFormat(item.lastMsg!.timestamp, formatType: "day"), style: TextStyle( fontSize: 12, - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ) : null, diff --git a/lib/pages/whisper_detail/view.dart b/lib/pages/whisper_detail/view.dart index 9129f3a3..6037c599 100644 --- a/lib/pages/whisper_detail/view.dart +++ b/lib/pages/whisper_detail/view.dart @@ -38,6 +38,7 @@ class _WhisperDetailPageState @override Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); return Scaffold( resizeToAvoidBottomInset: false, appBar: AppBar( @@ -49,14 +50,13 @@ class _WhisperDetailPageState tooltip: '返回', style: IconButton.styleFrom( padding: EdgeInsets.zero, - backgroundColor: - Theme.of(context).colorScheme.secondaryContainer, + backgroundColor: theme.colorScheme.secondaryContainer, ), onPressed: Get.back, icon: Icon( Icons.arrow_back_outlined, size: 18, - color: Theme.of(context).colorScheme.onSecondaryContainer, + color: theme.colorScheme.onSecondaryContainer, ), ), ), @@ -87,7 +87,7 @@ class _WhisperDetailPageState _whisperDetailController.name, maxLines: 1, overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.titleMedium, + style: theme.textTheme.titleMedium, ), ), ], @@ -109,8 +109,8 @@ class _WhisperDetailPageState }, ), ), - _buildInputView(), - buildPanelContainer(Theme.of(context).colorScheme.onInverseSurface), + _buildInputView(theme), + buildPanelContainer(theme.colorScheme.onInverseSurface), ], ), ), @@ -192,11 +192,11 @@ class _WhisperDetailPageState }; } - Widget _buildInputView() { + Widget _buildInputView(theme) { return Container( padding: const EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( - color: Theme.of(context).colorScheme.onInverseSurface, + color: theme.colorScheme.onInverseSurface, borderRadius: BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), @@ -243,7 +243,7 @@ class _WhisperDetailPageState decoration: InputDecoration( filled: true, hintText: '发个消息聊聊呗~', - fillColor: Theme.of(context).colorScheme.surface, + fillColor: theme.colorScheme.surface, border: OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.circular(6), diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index 9619fcd7..96b37541 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -68,10 +68,11 @@ class ChatItem extends StatelessWidget { item.msgType == MsgType.pic_card.value || item.msgType == MsgType.auto_reply_push.value; dynamic content = item.content ?? ''; + final ThemeData theme = Theme.of(context); Color textColor() { return isOwner - ? Theme.of(context).colorScheme.onSecondaryContainer - : Theme.of(context).colorScheme.onSurfaceVariant; + ? theme.colorScheme.onSecondaryContainer + : theme.colorScheme.onSurfaceVariant; } Widget richTextMessage(BuildContext context) { @@ -140,9 +141,9 @@ class ChatItem extends StatelessWidget { Widget messageContent(BuildContext context) { switch (MsgType.parse(item.msgType!)) { case MsgType.notify_msg: - return SystemNotice(item: item); + return systemNotice(theme); case MsgType.pic_card: - return SystemNotice2(item: item); + return systemNotice2(); case MsgType.notify_text: return Text( jsonDecode(content['content']) @@ -152,7 +153,7 @@ class ChatItem extends StatelessWidget { style: TextStyle( letterSpacing: 0.6, height: 5, - color: Theme.of(context).colorScheme.outline.withOpacity(0.8), + color: theme.colorScheme.outline.withOpacity(0.8), ), ); case MsgType.text: @@ -355,10 +356,7 @@ class ChatItem extends StatelessWidget { maxWidth: 300.0, // 设置最大宽度为200.0 ), decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer - .withOpacity(0.4), + color: theme.colorScheme.secondaryContainer.withOpacity(0.4), borderRadius: const BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), @@ -591,8 +589,8 @@ class ChatItem extends StatelessWidget { ), decoration: BoxDecoration( color: isOwner - ? Theme.of(context).colorScheme.secondaryContainer - : Theme.of(context).colorScheme.onInverseSurface, + ? theme.colorScheme.secondaryContainer + : theme.colorScheme.onInverseSurface, borderRadius: BorderRadius.only( topLeft: const Radius.circular(16), topRight: const Radius.circular(16), @@ -619,31 +617,19 @@ class ChatItem extends StatelessWidget { children: [ Text( Utils.dateFormat(item.timestamp), - style: Theme.of(context) - .textTheme - .labelSmall! - .copyWith( - color: isOwner - ? Theme.of(context) - .colorScheme - .onSecondaryContainer - .withOpacity(0.8) - : Theme.of(context) - .colorScheme - .onSurfaceVariant - .withOpacity(0.8)), + style: theme.textTheme.labelSmall!.copyWith( + color: isOwner + ? theme.colorScheme.onSecondaryContainer + .withOpacity(0.8) + : theme.colorScheme.onSurfaceVariant + .withOpacity(0.8)), ), if (item.msgStatus == 1) Text( ' 已撤回', - style: Theme.of(context) - .textTheme - .labelSmall! - .copyWith( - color: Theme.of(context) - .colorScheme - .onErrorContainer, - ), + style: theme.textTheme.labelSmall!.copyWith( + color: theme.colorScheme.onErrorContainer, + ), ), ], ) @@ -656,15 +642,8 @@ class ChatItem extends StatelessWidget { ), ); } -} -class SystemNotice extends StatelessWidget { - final dynamic item; - const SystemNotice({super.key, this.item}); - - @override - Widget build(BuildContext context) { - Map content = item.content ?? ''; + Widget systemNotice(ThemeData theme) { return Row( children: [ const SizedBox(width: 12), @@ -673,10 +652,7 @@ class SystemNotice extends StatelessWidget { maxWidth: 300.0, // 设置最大宽度为200.0 ), decoration: BoxDecoration( - color: Theme.of(context) - .colorScheme - .secondaryContainer - .withOpacity(0.4), + color: theme.colorScheme.secondaryContainer.withOpacity(0.4), borderRadius: const BorderRadius.only( topLeft: Radius.circular(16), topRight: Radius.circular(16), @@ -689,23 +665,19 @@ class SystemNotice extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SelectableText(content['title'], - style: Theme.of(context) - .textTheme - .titleMedium! + SelectableText(item.content['title'], + style: theme.textTheme.titleMedium! .copyWith(fontWeight: FontWeight.bold)), Text( Utils.dateFormat(item.timestamp), - style: Theme.of(context) - .textTheme - .labelSmall! - .copyWith(color: Theme.of(context).colorScheme.outline), + style: theme.textTheme.labelSmall! + .copyWith(color: theme.colorScheme.outline), ), Divider( - color: Theme.of(context).colorScheme.primary.withOpacity(0.05), + color: theme.colorScheme.primary.withOpacity(0.05), ), SelectableText( - content['text'], + item.content['text'], ) ], ), @@ -714,15 +686,8 @@ class SystemNotice extends StatelessWidget { ], ); } -} -class SystemNotice2 extends StatelessWidget { - final dynamic item; - const SystemNotice2({super.key, this.item}); - - @override - Widget build(BuildContext context) { - Map content = item.content ?? ''; + Widget systemNotice2() { return Row( children: [ const SizedBox(width: 12), @@ -735,7 +700,7 @@ class SystemNotice2 extends StatelessWidget { child: NetworkImgLayer( width: 320, height: 150, - src: content['pic_url'], + src: item.content['pic_url'], ), ), const Spacer(), diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 3c2f878f..cdaf1fa0 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -722,7 +722,8 @@ class _PLVideoPlayerState extends State @override Widget build(BuildContext context) { - final Color colorTheme = Theme.of(context).colorScheme.primary; + final ThemeData theme = Theme.of(context); + final Color primary = theme.colorScheme.primary; const TextStyle textStyle = TextStyle( color: Colors.white, fontSize: 12, @@ -855,15 +856,12 @@ class _PLVideoPlayerState extends State horizontal: 8, vertical: 4), decoration: BoxDecoration( borderRadius: BorderRadius.circular(6), - color: - Theme.of(context).colorScheme.secondaryContainer, + color: theme.colorScheme.secondaryContainer, ), child: Text( '松开手指,取消进退', style: TextStyle( - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + color: theme.colorScheme.onSecondaryContainer, ), ), ), @@ -1328,9 +1326,8 @@ class _PLVideoPlayerState extends State child: FilledButton.tonal( style: FilledButton.styleFrom( tapTargetSize: MaterialTapTargetSize.shrinkWrap, - backgroundColor: Theme.of(context) - .colorScheme - .secondaryContainer + backgroundColor: theme + .colorScheme.secondaryContainer .withOpacity(0.8), visualDensity: VisualDensity(horizontal: -2, vertical: -2), @@ -1411,7 +1408,7 @@ class _PLVideoPlayerState extends State children: [ if (plPlayerController.dmTrend.isNotEmpty && plPlayerController.showDmChart.value) - buildDmChart(context, plPlayerController), + buildDmChart(theme, plPlayerController), if (plPlayerController.viewPointList.isNotEmpty && plPlayerController.showVP.value) buildViewPointWidget(plPlayerController, 4.25), @@ -1420,14 +1417,11 @@ class _PLVideoPlayerState extends State progress: Duration(seconds: value), buffered: Duration(seconds: buffer), total: Duration(seconds: max), - progressBarColor: colorTheme, + progressBarColor: primary, baseBarColor: Colors.white.withOpacity(0.2), - bufferedBarColor: Theme.of(context) - .colorScheme - .primary - .withOpacity(0.4), + bufferedBarColor: primary.withOpacity(0.4), timeLabelLocation: TimeLabelLocation.none, - thumbColor: colorTheme, + thumbColor: primary, barHeight: 3.5, thumbRadius: draggingFixedProgressBar.value ? 7 : 2.5, // onDragStart: (duration) { @@ -1757,10 +1751,11 @@ class _PLVideoPlayerState extends State } Widget buildDmChart( - BuildContext context, + ThemeData theme, PlPlayerController plPlayerController, [ double offset = 0, ]) { + final color = theme.colorScheme.primary; return IgnorePointer( child: Container( height: 12, @@ -1793,11 +1788,11 @@ Widget buildDmChart( ), isCurved: true, barWidth: 1, - color: Theme.of(context).colorScheme.primary, + color: color, dotData: const FlDotData(show: false), belowBarData: BarAreaData( show: true, - color: Theme.of(context).colorScheme.primary.withOpacity(0.4), + color: color.withOpacity(0.4), ), ), ], diff --git a/lib/plugin/pl_player/widgets/bottom_control.dart b/lib/plugin/pl_player/widgets/bottom_control.dart index cdc34a4b..df8bf89b 100644 --- a/lib/plugin/pl_player/widgets/bottom_control.dart +++ b/lib/plugin/pl_player/widgets/bottom_control.dart @@ -30,7 +30,8 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { - Color colorTheme = Theme.of(context).colorScheme.primary; + final theme = Theme.of(context); + Color colorTheme = theme.colorScheme.primary; //阅读器限制 Timer? accessibilityDebounce; double lastAnnouncedValue = -1; @@ -57,7 +58,7 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget { children: [ if (controller.dmTrend.isNotEmpty && controller.showDmChart.value) - buildDmChart(context, controller, 4.5), + buildDmChart(theme, controller, 4.5), if (controller.viewPointList.isNotEmpty && controller.showVP.value) buildViewPointWidget(controller, 8.75), diff --git a/lib/utils/page_utils.dart b/lib/utils/page_utils.dart index ed3293db..648b87c3 100644 --- a/lib/utils/page_utils.dart +++ b/lib/utils/page_utils.dart @@ -78,19 +78,20 @@ class PageUtils { if (isLive) { shutdownTimerService.waitForPlayingCompleted = false; } - PageUtils.showVideoBottomSheet( + showVideoBottomSheet( context, isFullScreen: () => isFullScreen, child: StatefulBuilder( builder: (_, setState) { + final ThemeData theme = Theme.of(context); return Theme( - data: Theme.of(context), + data: theme, child: Material( color: Colors.transparent, child: Container( clipBehavior: Clip.hardEdge, decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surface, + color: theme.colorScheme.surface, borderRadius: const BorderRadius.all(Radius.circular(12)), ), margin: const EdgeInsets.all(12), @@ -140,9 +141,7 @@ class PageUtils { child: Text( '取消', style: TextStyle( - color: Theme.of(context) - .colorScheme - .outline), + color: theme.colorScheme.outline), ), ), TextButton( @@ -179,7 +178,7 @@ class PageUtils { choice ? Icon( Icons.done, - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ) : null, ), diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 93bc1573..23608aee 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -517,6 +517,7 @@ class Utils { SmartDialog.show( animationType: SmartAnimationType.centerFade_otherSlide, builder: (context) { + final ThemeData theme = Theme.of(context); return AlertDialog( title: const Text('🎉 发现新版本 '), content: SizedBox( @@ -541,7 +542,7 @@ class Utils { child: Text( "点此查看完整更新(即commit)内容", style: TextStyle( - color: Theme.of(context).colorScheme.primary, + color: theme.colorScheme.primary, ), ), ), @@ -558,7 +559,7 @@ class Utils { child: Text( '不再提醒', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ), @@ -567,7 +568,7 @@ class Utils { child: Text( '取消', style: TextStyle( - color: Theme.of(context).colorScheme.outline, + color: theme.colorScheme.outline, ), ), ),