fix: video theme, view later

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-03-11 11:54:39 +08:00
parent af6188be77
commit a6a1de169b
6 changed files with 312 additions and 345 deletions

View File

@@ -652,6 +652,7 @@ class VideoIntroController extends GetxController
} catch (_) {} } catch (_) {}
} }
hasLater.value = false;
this.bvid = bvid; this.bvid = bvid;
lastPlayCid.value = cid; lastPlayCid.value = cid;
queryVideoIntro(); queryVideoIntro();

View File

@@ -21,6 +21,7 @@ class VideoReplyReplyController extends ReplyController
required this.dialog, required this.dialog,
required this.replyType, required this.replyType,
required this.isDialogue, required this.isDialogue,
required this.getThemeData,
}); });
final int? dialog; final int? dialog;
final bool isDialogue; final bool isDialogue;
@@ -60,6 +61,8 @@ class VideoReplyReplyController extends ReplyController
return super.onRefresh(); return super.onRefresh();
} }
final ThemeData Function() getThemeData;
@override @override
bool customHandleResponse(Success response) { bool customHandleResponse(Success response) {
if (GlobalData().grpcReply) { if (GlobalData().grpcReply) {
@@ -81,8 +84,8 @@ class VideoReplyReplyController extends ReplyController
vsync: this, vsync: this,
); );
colorAnimation = ColorTween( colorAnimation = ColorTween(
begin: Theme.of(Get.context!).colorScheme.onInverseSurface, begin: getThemeData().colorScheme.onInverseSurface,
end: Theme.of(Get.context!).colorScheme.surface, end: getThemeData().colorScheme.surface,
).animate(controller!); ).animate(controller!);
WidgetsBinding.instance.addPostFrameCallback((_) async { WidgetsBinding.instance.addPostFrameCallback((_) async {
if (index != null) { if (index != null) {

View File

@@ -80,6 +80,7 @@ class _VideoReplyReplyPanelState
dialog: widget.dialog, dialog: widget.dialog,
replyType: widget.replyType, replyType: widget.replyType,
isDialogue: widget.isDialogue, isDialogue: widget.isDialogue,
getThemeData: () => Theme.of(context),
), ),
tag: '${widget.rpid}${widget.dialog}${widget.isDialogue}', tag: '${widget.rpid}${widget.dialog}${widget.isDialogue}',
); );
@@ -473,9 +474,9 @@ class _VideoReplyReplyPanelState
animation: _videoReplyReplyController.colorAnimation!, animation: _videoReplyReplyController.colorAnimation!,
builder: (context, child) { builder: (context, child) {
return ColoredBox( return ColoredBox(
color: _videoReplyReplyController color:
.colorAnimation?.value ?? _videoReplyReplyController.colorAnimation?.value ??
Theme.of(Get.context!).colorScheme.onInverseSurface, Theme.of(context).colorScheme.onInverseSurface,
child: _replyItem(loadingState.response[index], index), child: _replyItem(loadingState.response[index], index),
); );
}, },

View File

@@ -590,14 +590,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
: MediaQuery.of(context).padding.top) : MediaQuery.of(context).padding.top)
: videoHeight, : videoHeight,
width: context.width, width: context.width,
child: PopScope( child: videoPlayer(videoWidth, videoHeight),
canPop: !isFullScreen &&
(horizontalScreen ||
MediaQuery.of(context).orientation ==
Orientation.portrait),
onPopInvokedWithResult: _onPopInvokedWithResult,
child: videoPlayer(videoWidth, videoHeight),
),
); );
}, },
), ),
@@ -648,11 +641,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
SizedBox( SizedBox(
height: videoHeight, height: videoHeight,
width: isFullScreen ? context.width : videoWidth, width: isFullScreen ? context.width : videoWidth,
child: PopScope( child: videoPlayer(videoWidth, videoHeight),
canPop: !isFullScreen,
onPopInvokedWithResult: _onPopInvokedWithResult,
child: videoPlayer(videoWidth, videoHeight),
),
), ),
Expanded( Expanded(
child: Scaffold( child: Scaffold(
@@ -693,11 +682,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
: (MediaQuery.of(context).padding.top + : (MediaQuery.of(context).padding.top +
MediaQuery.of(context).padding.bottom)) MediaQuery.of(context).padding.bottom))
: videoHeight, : videoHeight,
child: PopScope( child: videoPlayer(videoWidth, videoHeight),
canPop: !isFullScreen,
onPopInvokedWithResult: _onPopInvokedWithResult,
child: videoPlayer(videoWidth, videoHeight),
),
), ),
Expanded( Expanded(
child: Scaffold( child: Scaffold(
@@ -745,11 +730,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
SizedBox( SizedBox(
height: videoHeight, height: videoHeight,
width: isFullScreen ? context.width : videoWidth, width: isFullScreen ? context.width : videoWidth,
child: PopScope( child: videoPlayer(videoWidth, videoHeight),
canPop: !isFullScreen,
onPopInvokedWithResult: _onPopInvokedWithResult,
child: videoPlayer(videoWidth, videoHeight),
),
), ),
Expanded( Expanded(
child: Expanded( child: Expanded(
@@ -829,11 +810,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
SizedBox( SizedBox(
width: isFullScreen ? context.width : videoWidth, width: isFullScreen ? context.width : videoWidth,
height: isFullScreen ? context.height : videoHeight, height: isFullScreen ? context.height : videoHeight,
child: PopScope( child: videoPlayer(videoWidth, videoHeight),
canPop: !isFullScreen,
onPopInvokedWithResult: _onPopInvokedWithResult,
child: videoPlayer(videoWidth, videoHeight),
),
), ),
Offstage( Offstage(
offstage: isFullScreen, offstage: isFullScreen,
@@ -1367,152 +1344,158 @@ class _VideoDetailPageState extends State<VideoDetailPage>
); );
} }
Widget videoPlayer(double videoWidth, double videoHeight) => Stack( Widget videoPlayer(double videoWidth, double videoHeight) => PopScope(
children: [ canPop: !isFullScreen,
Positioned.fill(child: ColoredBox(color: Colors.black)), onPopInvokedWithResult: _onPopInvokedWithResult,
child: Stack(
children: [
Positioned.fill(child: ColoredBox(color: Colors.black)),
if (isShowing) plPlayer, if (isShowing) plPlayer,
/// 关闭自动播放时 手动播放 /// 关闭自动播放时 手动播放
if (!videoDetailController.autoPlay.value) ...[ if (!videoDetailController.autoPlay.value) ...[
Obx( Obx(
() => Visibility( () => Visibility(
visible: videoDetailController.isShowCover.value, visible: videoDetailController.isShowCover.value,
child: Positioned( child: Positioned(
top: 0, top: 0,
left: 0, left: 0,
right: 0, right: 0,
child: GestureDetector( child: GestureDetector(
onTap: handlePlay, onTap: handlePlay,
child: Obx( child: Obx(
() => NetworkImgLayer( () => NetworkImgLayer(
type: 'emote', type: 'emote',
src: videoDetailController.videoItem['pic'], src: videoDetailController.videoItem['pic'],
width: videoWidth, width: videoWidth,
height: videoHeight, height: videoHeight,
),
), ),
), ),
), ),
), ),
), ),
), manualPlayerWidget,
manualPlayerWidget, ],
],
if (videoDetailController.enableSponsorBlock || if (videoDetailController.enableSponsorBlock ||
videoDetailController.continuePlayingPart) videoDetailController.continuePlayingPart)
Positioned( Positioned(
left: 16, left: 16,
bottom: isFullScreen ? max(75, Get.height * 0.25) : 75, bottom: isFullScreen ? max(75, Get.height * 0.25) : 75,
child: SizedBox( child: SizedBox(
width: MediaQuery.textScalerOf(context).scale(120), width: MediaQuery.textScalerOf(context).scale(120),
child: AnimatedList( child: AnimatedList(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
key: videoDetailController.listKey, key: videoDetailController.listKey,
reverse: true, reverse: true,
shrinkWrap: true, shrinkWrap: true,
initialItemCount: videoDetailController.listData.length, initialItemCount: videoDetailController.listData.length,
itemBuilder: (context, index, animation) { itemBuilder: (context, index, animation) {
return videoDetailController.buildItem( return videoDetailController.buildItem(
videoDetailController.listData[index], videoDetailController.listData[index],
animation, animation,
); );
}, },
),
), ),
), ),
),
// for debug // for debug
// Positioned( // Positioned(
// right: 16, // right: 16,
// bottom: 75, // bottom: 75,
// child: FilledButton.tonal( // child: FilledButton.tonal(
// onPressed: () { // onPressed: () {
// videoDetailController.onAddItem( // videoDetailController.onAddItem(
// SegmentModel( // SegmentModel(
// UUID: '', // UUID: '',
// segmentType: SegmentType.sponsor, // segmentType: SegmentType.sponsor,
// segment: Pair(first: 0, second: 0), // segment: Pair(first: 0, second: 0),
// skipType: SkipType.alwaysSkip, // skipType: SkipType.alwaysSkip,
// ), // ),
// ); // );
// }, // },
// child: Text('skip'), // child: Text('skip'),
// ), // ),
// ), // ),
// Positioned( // Positioned(
// right: 16, // right: 16,
// bottom: 120, // bottom: 120,
// child: FilledButton.tonal( // child: FilledButton.tonal(
// onPressed: () { // onPressed: () {
// videoDetailController.onAddItem(2); // videoDetailController.onAddItem(2);
// }, // },
// child: Text('index'), // child: Text('index'),
// ), // ),
// ), // ),
Obx( Obx(
() { () {
if (videoDetailController.showSteinEdgeInfo.value) { if (videoDetailController.showSteinEdgeInfo.value) {
try { try {
return Align( return Align(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
child: Padding( child: Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 16, horizontal: 16,
vertical: plPlayerController?.showControls.value == true vertical:
? 75 plPlayerController?.showControls.value == true
: 16, ? 75
), : 16,
child: Wrap( ),
spacing: 25, child: Wrap(
runSpacing: 10, spacing: 25,
children: (videoDetailController.steinEdgeInfo!['edges'] runSpacing: 10,
['questions'][0]['choices'] as List) children:
.map((item) { (videoDetailController.steinEdgeInfo!['edges']
return FilledButton.tonal( ['questions'][0]['choices'] as List)
style: FilledButton.styleFrom( .map((item) {
shape: RoundedRectangleBorder( return FilledButton.tonal(
borderRadius: BorderRadius.circular(6), style: FilledButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
backgroundColor: themeData
.colorScheme.secondaryContainer
.withOpacity(0.8),
padding: const EdgeInsets.symmetric(
horizontal: 15,
vertical: 10,
),
visualDensity:
VisualDensity(horizontal: -2, vertical: -2),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
), ),
backgroundColor: themeData onPressed: () {
.colorScheme.secondaryContainer videoIntroController.changeSeasonOrbangu(
.withOpacity(0.8), null,
padding: const EdgeInsets.symmetric( videoDetailController.bvid,
horizontal: 15, item['cid'],
vertical: 10, IdUtils.bv2av(videoDetailController.bvid),
), null,
visualDensity: true,
VisualDensity(horizontal: -2, vertical: -2), );
tapTargetSize: MaterialTapTargetSize.shrinkWrap, videoDetailController
), .getSteinEdgeInfo(item['id']);
onPressed: () { },
videoIntroController.changeSeasonOrbangu( child: Text(item['option']),
null, );
videoDetailController.bvid, }).toList(),
item['cid'], ),
IdUtils.bv2av(videoDetailController.bvid),
null,
true,
);
videoDetailController
.getSteinEdgeInfo(item['id']);
},
child: Text(item['option']),
);
}).toList(),
), ),
), );
); } catch (e) {
} catch (e) { debugPrint('build stein edges: $e');
debugPrint('build stein edges: $e'); return const SizedBox.shrink();
return const SizedBox.shrink(); }
} }
} return const SizedBox.shrink();
return const SizedBox.shrink(); },
}, ),
), ],
], ),
); );
Widget videoIntro([bool needRelated = true]) { Widget videoIntro([bool needRelated = true]) {

View File

@@ -768,22 +768,15 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
? animHeight ? animHeight
: videoDetailController.videoHeight, : videoDetailController.videoHeight,
width: context.width, width: context.width,
child: PopScope( child: videoPlayer(
canPop: !isFullScreen && videoWidth,
(horizontalScreen || context.orientation == Orientation.landscape ||
MediaQuery.of(context).orientation == isFullScreen
Orientation.portrait), ? context.height
onPopInvokedWithResult: _onPopInvokedWithResult, : videoDetailController.isExpanding ||
child: videoPlayer( videoDetailController.isCollapsing
videoWidth, ? animHeight
context.orientation == Orientation.landscape || : videoDetailController.videoHeight,
isFullScreen
? context.height
: videoDetailController.isExpanding ||
videoDetailController.isCollapsing
? animHeight
: videoDetailController.videoHeight,
),
), ),
); );
}, },
@@ -1026,11 +1019,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
SizedBox( SizedBox(
height: videoHeight, height: videoHeight,
width: isFullScreen ? context.width : videoWidth, width: isFullScreen ? context.width : videoWidth,
child: PopScope( child: videoPlayer(videoWidth, videoHeight),
canPop: !isFullScreen,
onPopInvokedWithResult: _onPopInvokedWithResult,
child: videoPlayer(videoWidth, videoHeight),
),
), ),
Expanded( Expanded(
child: Scaffold( child: Scaffold(
@@ -1071,11 +1060,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
: (MediaQuery.of(context).padding.top + : (MediaQuery.of(context).padding.top +
MediaQuery.of(context).padding.bottom)) MediaQuery.of(context).padding.bottom))
: videoHeight, : videoHeight,
child: PopScope( child: videoPlayer(videoWidth, videoHeight),
canPop: !isFullScreen,
onPopInvokedWithResult: _onPopInvokedWithResult,
child: videoPlayer(videoWidth, videoHeight),
),
), ),
Expanded( Expanded(
child: Scaffold( child: Scaffold(
@@ -1123,11 +1108,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
SizedBox( SizedBox(
height: videoHeight, height: videoHeight,
width: isFullScreen ? context.width : videoWidth, width: isFullScreen ? context.width : videoWidth,
child: PopScope( child: videoPlayer(videoWidth, videoHeight),
canPop: !isFullScreen,
onPopInvokedWithResult: _onPopInvokedWithResult,
child: videoPlayer(videoWidth, videoHeight),
),
), ),
Expanded( Expanded(
child: Expanded( child: Expanded(
@@ -1208,11 +1189,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
SizedBox( SizedBox(
width: isFullScreen ? context.width : videoWidth, width: isFullScreen ? context.width : videoWidth,
height: isFullScreen ? context.height : videoHeight, height: isFullScreen ? context.height : videoHeight,
child: PopScope( child: videoPlayer(videoWidth, videoHeight),
canPop: !isFullScreen,
onPopInvokedWithResult: _onPopInvokedWithResult,
child: videoPlayer(videoWidth, videoHeight),
),
), ),
Offstage( Offstage(
offstage: isFullScreen, offstage: isFullScreen,
@@ -1752,160 +1729,165 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
} }
Widget videoPlayer(double videoWidth, double videoHeight) { Widget videoPlayer(double videoWidth, double videoHeight) {
return Stack( return PopScope(
children: [ canPop: !isFullScreen,
Positioned.fill(child: ColoredBox(color: Colors.black)), onPopInvokedWithResult: _onPopInvokedWithResult,
child: Stack(
children: [
Positioned.fill(child: ColoredBox(color: Colors.black)),
if (isShowing) plPlayer, if (isShowing) plPlayer,
if (!videoDetailController.autoPlay.value) ...[ if (!videoDetailController.autoPlay.value) ...[
Obx( Obx(
() => videoDetailController.isShowCover.value () => videoDetailController.isShowCover.value
? Positioned( ? Positioned(
top: 0, top: 0,
left: 0, left: 0,
right: 0, right: 0,
child: GestureDetector( child: GestureDetector(
onTap: handlePlay, onTap: handlePlay,
child: Obx( child: Obx(
() => CachedNetworkImage( () => CachedNetworkImage(
imageUrl: imageUrl:
videoDetailController.videoItem['pic'] != null videoDetailController.videoItem['pic'] != null
? (videoDetailController.videoItem['pic'] ? (videoDetailController.videoItem['pic']
as String) as String)
.http2https .http2https
: '', : '',
width: videoWidth, width: videoWidth,
height: videoHeight, height: videoHeight,
fit: BoxFit.cover, fit: BoxFit.cover,
fadeOutDuration: const Duration(milliseconds: 120), fadeOutDuration: const Duration(milliseconds: 120),
fadeInDuration: const Duration(milliseconds: 120), fadeInDuration: const Duration(milliseconds: 120),
memCacheWidth: videoWidth.cacheSize(context), memCacheWidth: videoWidth.cacheSize(context),
placeholder: (context, url) => Center( placeholder: (context, url) => Center(
child: Image.asset('assets/images/loading.png'), child: Image.asset('assets/images/loading.png'),
),
), ),
), ),
), ),
), )
) : const SizedBox.shrink(),
: const SizedBox.shrink(), ),
), manualPlayerWidget,
manualPlayerWidget, ],
],
if (videoDetailController.enableSponsorBlock || if (videoDetailController.enableSponsorBlock ||
videoDetailController.continuePlayingPart) videoDetailController.continuePlayingPart)
Positioned( Positioned(
left: 16, left: 16,
bottom: isFullScreen ? max(75, Get.height * 0.25) : 75, bottom: isFullScreen ? max(75, Get.height * 0.25) : 75,
child: SizedBox( child: SizedBox(
width: MediaQuery.textScalerOf(context).scale(120), width: MediaQuery.textScalerOf(context).scale(120),
child: AnimatedList( child: AnimatedList(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
key: videoDetailController.listKey, key: videoDetailController.listKey,
reverse: true, reverse: true,
shrinkWrap: true, shrinkWrap: true,
initialItemCount: videoDetailController.listData.length, initialItemCount: videoDetailController.listData.length,
itemBuilder: (context, index, animation) { itemBuilder: (context, index, animation) {
return videoDetailController.buildItem( return videoDetailController.buildItem(
videoDetailController.listData[index], videoDetailController.listData[index],
animation, animation,
); );
}, },
),
), ),
), ),
),
// for debug // for debug
// Positioned( // Positioned(
// right: 16, // right: 16,
// bottom: 75, // bottom: 75,
// child: FilledButton.tonal( // child: FilledButton.tonal(
// onPressed: () { // onPressed: () {
// videoDetailController.onAddItem( // videoDetailController.onAddItem(
// SegmentModel( // SegmentModel(
// UUID: '', // UUID: '',
// segmentType: SegmentType.sponsor, // segmentType: SegmentType.sponsor,
// segment: Pair(first: 0, second: 0), // segment: Pair(first: 0, second: 0),
// skipType: SkipType.alwaysSkip, // skipType: SkipType.alwaysSkip,
// ), // ),
// ); // );
// }, // },
// child: Text('skip'), // child: Text('skip'),
// ), // ),
// ), // ),
// Positioned( // Positioned(
// right: 16, // right: 16,
// bottom: 120, // bottom: 120,
// child: FilledButton.tonal( // child: FilledButton.tonal(
// onPressed: () { // onPressed: () {
// videoDetailController.onAddItem(2); // videoDetailController.onAddItem(2);
// }, // },
// child: Text('index'), // child: Text('index'),
// ), // ),
// ), // ),
Obx( Obx(
() { () {
if (videoDetailController.showSteinEdgeInfo.value) { if (videoDetailController.showSteinEdgeInfo.value) {
try { try {
return Align( return Align(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
child: Padding( child: Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 16, horizontal: 16,
vertical: plPlayerController?.showControls.value == true vertical: plPlayerController?.showControls.value == true
? 75 ? 75
: 16, : 16,
), ),
child: Wrap( child: Wrap(
spacing: 25, spacing: 25,
runSpacing: 10, runSpacing: 10,
children: (videoDetailController.steinEdgeInfo!['edges'] children: (videoDetailController.steinEdgeInfo!['edges']
['questions'][0]['choices'] as List) ['questions'][0]['choices'] as List)
.map((item) { .map((item) {
return FilledButton.tonal( return FilledButton.tonal(
style: FilledButton.styleFrom( style: FilledButton.styleFrom(
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
),
backgroundColor: themeData
.colorScheme.secondaryContainer
.withOpacity(0.8),
padding: const EdgeInsets.symmetric(
horizontal: 15,
vertical: 10,
),
visualDensity:
VisualDensity(horizontal: -2, vertical: -2),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
), ),
backgroundColor: themeData onPressed: () {
.colorScheme.secondaryContainer videoIntroController.changeSeasonOrbangu(
.withOpacity(0.8), null,
padding: const EdgeInsets.symmetric( videoDetailController.bvid,
horizontal: 15, item['cid'],
vertical: 10, IdUtils.bv2av(videoDetailController.bvid),
), null,
visualDensity: true,
VisualDensity(horizontal: -2, vertical: -2), );
tapTargetSize: MaterialTapTargetSize.shrinkWrap, videoDetailController
), .getSteinEdgeInfo(item['id']);
onPressed: () { },
videoIntroController.changeSeasonOrbangu( child: Text(item['option']),
null, );
videoDetailController.bvid, }).toList(),
item['cid'], ),
IdUtils.bv2av(videoDetailController.bvid),
null,
true,
);
videoDetailController.getSteinEdgeInfo(item['id']);
},
child: Text(item['option']),
);
}).toList(),
), ),
), );
); } catch (e) {
} catch (e) { debugPrint('build stein edges: $e');
debugPrint('build stein edges: $e'); return const SizedBox.shrink();
return const SizedBox.shrink(); }
} }
} return const SizedBox.shrink();
return const SizedBox.shrink(); },
}, ),
), ],
], ),
); );
} }

View File

@@ -21,7 +21,6 @@ import 'package:get/get.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:media_kit/media_kit.dart'; import 'package:media_kit/media_kit.dart';
import 'package:PiliPlus/http/user.dart';
import 'package:PiliPlus/models/video/play/quality.dart'; import 'package:PiliPlus/models/video/play/quality.dart';
import 'package:PiliPlus/models/video/play/url.dart'; import 'package:PiliPlus/models/video/play/url.dart';
import 'package:PiliPlus/pages/video/detail/index.dart'; import 'package:PiliPlus/pages/video/detail/index.dart';
@@ -147,9 +146,7 @@ class _HeaderControlState extends State<HeaderControl> {
dense: true, dense: true,
onTap: () async { onTap: () async {
Get.back(); Get.back();
final res = videoIntroController.viewLater();
await UserHttp.toViewLater(bvid: videoDetailCtr.bvid);
SmartDialog.showToast(res['msg']);
}, },
leading: const Icon(Icons.watch_later_outlined, size: 20), leading: const Icon(Icons.watch_later_outlined, size: 20),
title: const Text('添加至「稍后再看」', style: titleStyle), title: const Text('添加至「稍后再看」', style: titleStyle),