opt: video page

show tabbar on landscape page
prevent showing bottomsheet above fullscreen video
This commit is contained in:
bggRGjQaUbCoE
2024-09-17 18:36:45 +08:00
parent c48400f5cd
commit 974f4bb848
3 changed files with 365 additions and 343 deletions

View File

@@ -12,7 +12,6 @@ import 'package:PiliPalaX/common/widgets/stat/danmu.dart';
import 'package:PiliPalaX/common/widgets/stat/view.dart'; import 'package:PiliPalaX/common/widgets/stat/view.dart';
import 'package:PiliPalaX/models/video_detail_res.dart'; import 'package:PiliPalaX/models/video_detail_res.dart';
import 'package:PiliPalaX/pages/video/detail/introduction/controller.dart'; import 'package:PiliPalaX/pages/video/detail/introduction/controller.dart';
import 'package:PiliPalaX/pages/video/detail/widgets/ai_detail.dart';
import 'package:PiliPalaX/utils/feed_back.dart'; import 'package:PiliPalaX/utils/feed_back.dart';
import 'package:PiliPalaX/utils/storage.dart'; import 'package:PiliPalaX/utils/storage.dart';
import 'package:PiliPalaX/utils/utils.dart'; import 'package:PiliPalaX/utils/utils.dart';
@@ -26,8 +25,15 @@ import 'widgets/page.dart';
import 'widgets/season.dart'; import 'widgets/season.dart';
class VideoIntroPanel extends StatefulWidget { class VideoIntroPanel extends StatefulWidget {
const VideoIntroPanel({required this.heroTag, super.key}); const VideoIntroPanel({
super.key,
required this.heroTag,
required this.showAiBottomSheet,
required this.showIntroDetail,
});
final String heroTag; final String heroTag;
final Function showAiBottomSheet;
final Function showIntroDetail;
@override @override
State<VideoIntroPanel> createState() => _VideoIntroPanelState(); State<VideoIntroPanel> createState() => _VideoIntroPanelState();
@@ -74,6 +80,8 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
loadingStatus: true, loadingStatus: true,
videoDetail: videoDetail, videoDetail: videoDetail,
heroTag: heroTag, heroTag: heroTag,
showAiBottomSheet: widget.showAiBottomSheet,
showIntroDetail: widget.showIntroDetail,
) )
: VideoInfo( : VideoInfo(
//key:herotag //key:herotag
@@ -81,6 +89,8 @@ class _VideoIntroPanelState extends State<VideoIntroPanel>
loadingStatus: false, loadingStatus: false,
videoDetail: videoIntroController.videoDetail.value, videoDetail: videoIntroController.videoDetail.value,
heroTag: heroTag, heroTag: heroTag,
showAiBottomSheet: widget.showAiBottomSheet,
showIntroDetail: widget.showIntroDetail,
)); ));
} }
} }
@@ -89,10 +99,17 @@ class VideoInfo extends StatefulWidget {
final bool loadingStatus; final bool loadingStatus;
final VideoDetailData? videoDetail; final VideoDetailData? videoDetail;
final String? heroTag; final String? heroTag;
final Function showAiBottomSheet;
final Function showIntroDetail;
const VideoInfo( const VideoInfo({
{Key? key, this.loadingStatus = false, this.videoDetail, this.heroTag}) Key? key,
: super(key: key); this.loadingStatus = false,
this.videoDetail,
this.heroTag,
required this.showAiBottomSheet,
required this.showIntroDetail,
}) : super(key: key);
@override @override
State<VideoInfo> createState() => _VideoInfoState(); State<VideoInfo> createState() => _VideoInfoState();
@@ -177,13 +194,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
return; return;
} }
feedBack(); feedBack();
showBottomSheet( widget.showIntroDetail(widget.videoDetail);
context: context,
enableDrag: true,
builder: (BuildContext context) {
return IntroDetail(videoDetail: widget.videoDetail!);
},
);
} }
// 用户主页 // 用户主页
@@ -200,17 +211,6 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
arguments: {'face': face, 'heroTag': memberHeroTag}); arguments: {'face': face, 'heroTag': memberHeroTag});
} }
// ai总结
showAiBottomSheet() {
showBottomSheet(
context: context,
enableDrag: true,
builder: (BuildContext context) {
return AiDetail(modelResult: videoIntroController.modelResult);
},
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ThemeData t = Theme.of(context); final ThemeData t = Theme.of(context);
@@ -384,7 +384,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
final res = final res =
await videoIntroController.aiConclusion(); await videoIntroController.aiConclusion();
if (res['status']) { if (res['status']) {
showAiBottomSheet(); widget.showAiBottomSheet();
} }
}, },
child: child:

View File

@@ -1,6 +1,5 @@
import 'package:PiliPalaX/common/widgets/http_error.dart'; import 'package:PiliPalaX/common/widgets/http_error.dart';
import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/http/loading_state.dart';
import 'package:PiliPalaX/pages/video/detail/reply_reply/view.dart';
import 'package:easy_debounce/easy_throttle.dart'; import 'package:easy_debounce/easy_throttle.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
@@ -18,6 +17,7 @@ class VideoReplyPanel extends StatefulWidget {
final int rpid; final int rpid;
final String? replyLevel; final String? replyLevel;
final String heroTag; final String heroTag;
final Function replyReply;
const VideoReplyPanel({ const VideoReplyPanel({
this.bvid, this.bvid,
@@ -25,6 +25,7 @@ class VideoReplyPanel extends StatefulWidget {
this.rpid = 0, this.rpid = 0,
this.replyLevel, this.replyLevel,
required this.heroTag, required this.heroTag,
required this.replyReply,
super.key, super.key,
}); });
@@ -115,21 +116,6 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
} }
} }
// 展示二级回复
void replyReply(replyItem) {
showBottomSheet(
context: context,
builder: (context) => VideoReplyReplyPanel(
rcount: replyItem.rcount,
oid: replyItem.oid,
rpid: replyItem.rpid,
firstFloor: replyItem,
replyType: ReplyType.video,
source: 'videoDetail',
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
@@ -239,7 +225,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
replyItem: loadingState.response[index], replyItem: loadingState.response[index],
showReplyRow: true, showReplyRow: true,
replyLevel: replyLevel, replyLevel: replyLevel,
replyReply: replyReply, replyReply: widget.replyReply,
replyType: ReplyType.video, replyType: ReplyType.video,
onReply: () { onReply: () {
_videoReplyController.onReply( _videoReplyController.onReply(

View File

@@ -4,6 +4,10 @@ import 'dart:math';
import 'package:PiliPalaX/common/constants.dart'; import 'package:PiliPalaX/common/constants.dart';
import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/http/loading_state.dart';
import 'package:PiliPalaX/models/common/reply_type.dart';
import 'package:PiliPalaX/pages/video/detail/introduction/widgets/intro_detail.dart';
import 'package:PiliPalaX/pages/video/detail/reply_reply/view.dart';
import 'package:PiliPalaX/pages/video/detail/widgets/ai_detail.dart';
import 'package:PiliPalaX/utils/extension.dart'; import 'package:PiliPalaX/utils/extension.dart';
import 'package:PiliPalaX/utils/id_utils.dart'; import 'package:PiliPalaX/utils/id_utils.dart';
import 'package:auto_orientation/auto_orientation.dart'; import 'package:auto_orientation/auto_orientation.dart';
@@ -76,6 +80,8 @@ class _VideoDetailPageState extends State<VideoDetailPage>
late final MethodChannel onUserLeaveHintListener; late final MethodChannel onUserLeaveHintListener;
// StreamSubscription<Duration>? _bufferedListener; // StreamSubscription<Duration>? _bufferedListener;
final scaffoldKey = GlobalKey<ScaffoldState>();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -411,102 +417,60 @@ class _VideoDetailPageState extends State<VideoDetailPage>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
/// tabbar /// tabbar
Widget tabbarBuild = Container( Widget tabbarBuild([
width: double.infinity, bool needIndicator = true,
height: 45, String introText = '简介',
decoration: BoxDecoration( ]) {
border: Border( return Container(
bottom: BorderSide( width: double.infinity,
width: 1, height: 45,
color: Theme.of(context).dividerColor.withOpacity(0.1), decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1,
color: Theme.of(context).dividerColor.withOpacity(0.1),
),
), ),
), ),
), child: Material(
child: Material( child: Row(
child: Row( children: [
children: [ Flexible(
Flexible(
flex: 1,
child: Obx(
() => TabBar(
padding: EdgeInsets.zero,
controller: videoDetailController.tabCtr,
labelStyle: const TextStyle(fontSize: 13),
labelPadding:
const EdgeInsets.symmetric(horizontal: 10.0), // 设置每个标签的宽度
dividerColor: Colors.transparent,
onTap: (value) {
if (!videoDetailController.tabCtr.indexIsChanging) {
if (value == 0) {
_introController.animToTop();
} else {
_videoReplyController.animateToTop();
}
}
},
tabs: [
const Tab(text: '简介'),
Tab(
text:
'评论${_videoReplyController.count.value == -1 ? '' : ' ${_videoReplyController.count.value}'}',
),
],
),
),
),
Flexible(
flex: 1, flex: 1,
child: Center( child: Obx(
child: Row( () => TabBar(
mainAxisAlignment: MainAxisAlignment.end, indicatorColor: needIndicator ? null : Colors.transparent,
children: [ padding: EdgeInsets.zero,
SizedBox( controller: videoDetailController.tabCtr,
height: 32, labelStyle: const TextStyle(fontSize: 13),
child: TextButton( labelPadding: const EdgeInsets.symmetric(
style: ButtonStyle( horizontal: 10.0), // 设置每个标签的宽度
padding: WidgetStateProperty.all(EdgeInsets.zero), dividerColor: Colors.transparent,
), onTap: (value) {
onPressed: null, if (!needIndicator ||
// onPressed: () => videoDetailController.showShootDanmakuSheet(), !videoDetailController.tabCtr.indexIsChanging) {
child: if (value == 0) {
const Text('发弹幕', style: TextStyle(fontSize: 12)), _introController.animToTop();
), } else {
_videoReplyController.animateToTop();
}
}
},
tabs: [
Tab(text: introText),
Tab(
text:
'评论${_videoReplyController.count.value == -1 ? '' : ' ${_videoReplyController.count.value}'}',
), ),
// SizedBox(
// width: 38,
// height: 38,
// child: Obx(
// () => IconButton(
// onPressed: () {
// plPlayerController?.isOpenDanmu.value =
// !(plPlayerController?.isOpenDanmu.value ??
// false);
// },
// icon: !(plPlayerController?.isOpenDanmu.value ??
// false)
// ? SvgPicture.asset(
// 'assets/images/video/danmu_close.svg',
// // ignore: deprecated_member_use
// color:
// Theme.of(context).colorScheme.outline,
// )
// : SvgPicture.asset(
// 'assets/images/video/danmu_open.svg',
// // ignore: deprecated_member_use
// color:
// Theme.of(context).colorScheme.primary,
// ),
// ),
// ),
// ),
const SizedBox(width: 14),
], ],
), ),
)), ),
], ),
],
),
), ),
), );
); }
Widget plPlayer = FutureBuilder( Widget plPlayer = FutureBuilder(
future: _futureBuilderFuture, future: _futureBuilderFuture,
@@ -619,125 +583,126 @@ class _VideoDetailPageState extends State<VideoDetailPage>
child: Stack( child: Stack(
children: [ children: [
Scaffold( Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
key: videoDetailController.scaffoldKey, key: videoDetailController.scaffoldKey,
// backgroundColor: Colors.black, // backgroundColor: Colors.black,
appBar: removeSafeArea appBar: removeSafeArea
? null ? null
: AppBar( : AppBar(
backgroundColor: backgroundColor:
showStatusBarBackgroundColor ? null : Colors.black, showStatusBarBackgroundColor ? null : Colors.black,
elevation: 0, elevation: 0,
toolbarHeight: 0, toolbarHeight: 0,
systemOverlayStyle: SystemUiOverlayStyle( systemOverlayStyle: SystemUiOverlayStyle(
statusBarIconBrightness: statusBarIconBrightness:
Theme.of(context).brightness == Brightness.dark || Theme.of(context).brightness == Brightness.dark ||
!showStatusBarBackgroundColor !showStatusBarBackgroundColor
? Brightness.light ? Brightness.light
: Brightness.dark, : Brightness.dark,
systemNavigationBarColor: Colors.transparent), systemNavigationBarColor: Colors.transparent),
), ),
body: Column( body: Column(
children: [ children: [
Obx( Obx(
() { () {
double videoHeight = context.width * 9 / 16; double videoHeight = context.width * 9 / 16;
final double videoWidth = context.width; final double videoWidth = context.width;
// print(videoDetailController.tabCtr.index); // print(videoDetailController.tabCtr.index);
if (enableVerticalExpand && if (enableVerticalExpand &&
plPlayerController?.direction.value == 'vertical') { plPlayerController?.direction.value == 'vertical') {
videoHeight = context.width; videoHeight = context.width;
} }
if (MediaQuery.of(context).orientation == if (MediaQuery.of(context).orientation ==
Orientation.landscape && Orientation.landscape &&
!horizontalScreen && !horizontalScreen &&
!isFullScreen.value && !isFullScreen.value &&
isShowing && isShowing &&
mounted) { mounted) {
hideStatusBar(); hideStatusBar();
} }
if (MediaQuery.of(context).orientation == if (MediaQuery.of(context).orientation ==
Orientation.portrait && Orientation.portrait &&
!isFullScreen.value && !isFullScreen.value &&
isShowing && isShowing &&
mounted) { mounted) {
if (!removeSafeArea) showStatusBar(); if (!removeSafeArea) showStatusBar();
} }
return Container( return Container(
color: color: showStatusBarBackgroundColor ? null : Colors.black,
showStatusBarBackgroundColor ? null : Colors.black, height: MediaQuery.of(context).orientation ==
height: MediaQuery.of(context).orientation == Orientation.landscape ||
Orientation.landscape || isFullScreen.value == true
isFullScreen.value == true ? MediaQuery.sizeOf(context).height -
? MediaQuery.sizeOf(context).height - (MediaQuery.of(context).orientation ==
(MediaQuery.of(context).orientation == Orientation.landscape ||
Orientation.landscape || removeSafeArea
removeSafeArea ? 0
? 0 : MediaQuery.of(context).padding.top)
: MediaQuery.of(context).padding.top) : videoHeight,
: videoHeight, width: context.width,
width: context.width, child: PopScope(
child: PopScope( canPop: isFullScreen.value != true &&
canPop: isFullScreen.value != true && (horizontalScreen ||
(horizontalScreen || MediaQuery.of(context).orientation ==
MediaQuery.of(context).orientation == Orientation.portrait),
Orientation.portrait), onPopInvokedWithResult: (bool didPop, Object? result) {
onPopInvokedWithResult: if (isFullScreen.value == true) {
(bool didPop, Object? result) { plPlayerController!
if (isFullScreen.value == true) { .triggerFullScreen(status: false);
plPlayerController! }
.triggerFullScreen(status: false); if (MediaQuery.of(context).orientation ==
} Orientation.landscape &&
if (MediaQuery.of(context).orientation == !horizontalScreen) {
Orientation.landscape && verticalScreenForTwoSeconds();
!horizontalScreen) { }
verticalScreenForTwoSeconds(); },
} child: Stack(
}, children: <Widget>[
child: Stack( if (isShowing) plPlayer,
children: <Widget>[
if (isShowing) plPlayer,
/// 关闭自动播放时 手动播放 /// 关闭自动播放时 手动播放
if (!videoDetailController if (!videoDetailController
.autoPlay.value) ...<Widget>[ .autoPlay.value) ...<Widget>[
Obx( Obx(
() => Visibility( () => Visibility(
visible: videoDetailController visible:
.isShowCover.value, 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 src: videoDetailController
.videoItem['pic'], .videoItem['pic'],
width: videoWidth, width: videoWidth,
height: videoHeight, height: videoHeight,
),
),
), ),
), ),
), ),
), ),
manualPlayerWidget, ),
] ),
], manualPlayerWidget,
)), ]
); ],
}, ),
), ),
Expanded( );
child: ColoredBox( },
key: Key(heroTag), ),
color: Theme.of(context).colorScheme.surface, Expanded(
child: Column( child: ColoredBox(
key: Key(heroTag),
color: Theme.of(context).colorScheme.surface,
child: Scaffold(
key: scaffoldKey,
body: Column(
children: [ children: [
tabbarBuild, tabbarBuild(),
Expanded( Expanded(
child: TabBarView( child: TabBarView(
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
@@ -749,7 +714,11 @@ class _VideoDetailPageState extends State<VideoDetailPage>
slivers: <Widget>[ slivers: <Widget>[
if (videoDetailController.videoType == if (videoDetailController.videoType ==
SearchType.video) ...[ SearchType.video) ...[
VideoIntroPanel(heroTag: heroTag), VideoIntroPanel(
heroTag: heroTag,
showAiBottomSheet: showAiBottomSheet,
showIntroDetail: showIntroDetail,
),
] else if (videoDetailController ] else if (videoDetailController
.videoType == .videoType ==
SearchType.media_bangumi) ...[ SearchType.media_bangumi) ...[
@@ -776,13 +745,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
RelatedVideoPanel(heroTag: heroTag), RelatedVideoPanel(heroTag: heroTag),
], ],
), ),
Obx( videoReplyPanel,
() => VideoReplyPanel(
bvid: videoDetailController.bvid,
oid: videoDetailController.oid.value,
heroTag: heroTag,
),
)
], ],
), ),
), ),
@@ -790,8 +753,10 @@ class _VideoDetailPageState extends State<VideoDetailPage>
), ),
), ),
), ),
], ),
)), ],
),
),
], ],
), ),
); );
@@ -852,46 +817,56 @@ class _VideoDetailPageState extends State<VideoDetailPage>
), ),
), ),
Expanded( Expanded(
child: TabBarView( child: Scaffold(
physics: const BouncingScrollPhysics(), key: scaffoldKey,
controller: videoDetailController.tabCtr, body: Column(
children: <Widget>[ children: [
CustomScrollView( tabbarBuild(),
key: const PageStorageKey<String>('简介'), Expanded(
slivers: <Widget>[ child: TabBarView(
if (videoDetailController.videoType == physics: const BouncingScrollPhysics(),
SearchType.video) ...[ controller: videoDetailController.tabCtr,
VideoIntroPanel(heroTag: heroTag), children: <Widget>[
] else if (videoDetailController.videoType == CustomScrollView(
SearchType.media_bangumi) ...[ controller: _introController,
Obx(() => BangumiIntroPanel( key: const PageStorageKey<String>('简介'),
heroTag: heroTag, slivers: <Widget>[
cid: videoDetailController.cid.value)), if (videoDetailController.videoType ==
], SearchType.video) ...[
SliverToBoxAdapter( VideoIntroPanel(
child: Padding( heroTag: heroTag,
padding: showAiBottomSheet: showAiBottomSheet,
const EdgeInsets.only(top: StyleString.safeSpace), showIntroDetail: showIntroDetail,
child: Divider( ),
height: 1, ] else if (videoDetailController.videoType ==
indent: 12, SearchType.media_bangumi) ...[
endIndent: 12, Obx(() => BangumiIntroPanel(
color: heroTag: heroTag,
Theme.of(context).dividerColor.withOpacity(0.06), cid: videoDetailController.cid.value)),
],
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.only(
top: StyleString.safeSpace),
child: Divider(
height: 1,
indent: 12,
endIndent: 12,
color: Theme.of(context)
.dividerColor
.withOpacity(0.06),
),
),
),
RelatedVideoPanel(heroTag: heroTag),
],
), ),
), videoReplyPanel,
],
), ),
RelatedVideoPanel(heroTag: heroTag),
],
),
Obx(
() => VideoReplyPanel(
bvid: videoDetailController.bvid,
oid: videoDetailController.oid.value,
heroTag: heroTag,
), ),
) ],
], ),
), ),
), ),
]); ]);
@@ -953,31 +928,46 @@ class _VideoDetailPageState extends State<VideoDetailPage>
), ),
), ),
Expanded( Expanded(
child: Row(children: [ child: Scaffold(
Expanded( key: scaffoldKey,
child: CustomScrollView( body: Column(
key: PageStorageKey<String>('简介${videoDetailController.bvid}'), children: [
slivers: <Widget>[ tabbarBuild(false),
if (videoDetailController.videoType == SearchType.video) ...[ Expanded(
VideoIntroPanel(heroTag: heroTag), child: Row(
RelatedVideoPanel(heroTag: heroTag), children: [
] else if (videoDetailController.videoType == Expanded(
SearchType.media_bangumi) ...[ child: CustomScrollView(
Obx(() => BangumiIntroPanel( controller: _introController,
heroTag: heroTag, cid: videoDetailController.cid.value)), key: PageStorageKey<String>(
] '简介${videoDetailController.bvid}'),
], slivers: <Widget>[
)), if (videoDetailController.videoType ==
Expanded( SearchType.video) ...[
child: Obx( VideoIntroPanel(
() => VideoReplyPanel( heroTag: heroTag,
bvid: videoDetailController.bvid, showAiBottomSheet: showAiBottomSheet,
oid: videoDetailController.oid.value, showIntroDetail: showIntroDetail,
heroTag: heroTag, ),
), RelatedVideoPanel(heroTag: heroTag),
] else if (videoDetailController.videoType ==
SearchType.media_bangumi) ...[
Obx(() => BangumiIntroPanel(
heroTag: heroTag,
cid: videoDetailController.cid.value)),
]
],
)),
Expanded(
child: videoReplyPanel,
)
],
),
)
],
), ),
) ),
])) ),
], ],
); );
}); });
@@ -994,7 +984,11 @@ class _VideoDetailPageState extends State<VideoDetailPage>
key: PageStorageKey<String>('简介${videoDetailController.bvid}'), key: PageStorageKey<String>('简介${videoDetailController.bvid}'),
slivers: <Widget>[ slivers: <Widget>[
if (videoDetailController.videoType == SearchType.video) ...[ if (videoDetailController.videoType == SearchType.video) ...[
VideoIntroPanel(heroTag: heroTag), VideoIntroPanel(
heroTag: heroTag,
showAiBottomSheet: showAiBottomSheet,
showIntroDetail: showIntroDetail,
),
RelatedVideoPanel(heroTag: heroTag), RelatedVideoPanel(heroTag: heroTag),
] else if (videoDetailController.videoType == ] else if (videoDetailController.videoType ==
SearchType.media_bangumi) ...[ SearchType.media_bangumi) ...[
@@ -1052,12 +1046,9 @@ class _VideoDetailPageState extends State<VideoDetailPage>
), ),
), ),
Expanded( Expanded(
child: Obx( child: Scaffold(
() => VideoReplyPanel( key: scaffoldKey,
bvid: videoDetailController.bvid, body: videoReplyPanel,
oid: videoDetailController.oid.value,
heroTag: heroTag,
),
), ),
), ),
// Expanded( // Expanded(
@@ -1169,7 +1160,11 @@ class _VideoDetailPageState extends State<VideoDetailPage>
slivers: <Widget>[ slivers: <Widget>[
if (videoDetailController.videoType == if (videoDetailController.videoType ==
SearchType.video) ...[ SearchType.video) ...[
VideoIntroPanel(heroTag: heroTag), VideoIntroPanel(
heroTag: heroTag,
showAiBottomSheet: showAiBottomSheet,
showIntroDetail: showIntroDetail,
),
// RelatedVideoPanel(heroTag: heroTag), // RelatedVideoPanel(heroTag: heroTag),
] else if (videoDetailController.videoType == ] else if (videoDetailController.videoType ==
SearchType.media_bangumi) ...[ SearchType.media_bangumi) ...[
@@ -1194,24 +1189,30 @@ class _VideoDetailPageState extends State<VideoDetailPage>
MediaQuery.of(context).padding.right))), MediaQuery.of(context).padding.right))),
height: context.height - height: context.height -
(removeSafeArea ? 0 : MediaQuery.of(context).padding.top), (removeSafeArea ? 0 : MediaQuery.of(context).padding.top),
child: TabBarView( child: Scaffold(
physics: const BouncingScrollPhysics(), key: scaffoldKey,
controller: videoDetailController.tabCtr, body: Column(
children: <Widget>[ children: [
if (videoDetailController.videoType == SearchType.video) tabbarBuild(true, '相关视频'),
CustomScrollView( Expanded(
slivers: [ child: TabBarView(
RelatedVideoPanel(heroTag: heroTag), physics: const BouncingScrollPhysics(),
], controller: videoDetailController.tabCtr,
), children: <Widget>[
Obx( if (videoDetailController.videoType ==
() => VideoReplyPanel( SearchType.video)
bvid: videoDetailController.bvid, CustomScrollView(
oid: videoDetailController.oid.value, controller: _introController,
heroTag: heroTag, slivers: [
), RelatedVideoPanel(heroTag: heroTag),
) ],
], ),
videoReplyPanel,
],
),
)
],
),
), ),
), ),
) )
@@ -1239,7 +1240,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
systemNavigationBarColor: Colors.transparent), systemNavigationBarColor: Colors.transparent),
), ),
body: Container( body: Container(
color: Theme.of(context).colorScheme.background, color: Theme.of(context).colorScheme.surface,
child: SafeArea( child: SafeArea(
left: !removeSafeArea && isFullScreen.value != true, left: !removeSafeArea && isFullScreen.value != true,
right: !removeSafeArea && isFullScreen.value != true, right: !removeSafeArea && isFullScreen.value != true,
@@ -1268,7 +1269,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
systemNavigationBarColor: Colors.transparent), systemNavigationBarColor: Colors.transparent),
), ),
body: Container( body: Container(
color: Theme.of(context).colorScheme.background, color: Theme.of(context).colorScheme.surface,
child: SafeArea( child: SafeArea(
left: !removeSafeArea && isFullScreen.value != true, left: !removeSafeArea && isFullScreen.value != true,
right: !removeSafeArea && isFullScreen.value != true, right: !removeSafeArea && isFullScreen.value != true,
@@ -1324,7 +1325,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
return LayoutBuilder( return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) { builder: (BuildContext context, BoxConstraints constraints) {
if (!isShowing) { if (!isShowing) {
return ColoredBox(color: Theme.of(context).colorScheme.background); return ColoredBox(color: Theme.of(context).colorScheme.surface);
} }
if (constraints.maxWidth > constraints.maxHeight * 1.25) { if (constraints.maxWidth > constraints.maxHeight * 1.25) {
// hideStatusBar(); // hideStatusBar();
@@ -1372,4 +1373,39 @@ class _VideoDetailPageState extends State<VideoDetailPage>
// : childWhenDisabledLandscape; // : childWhenDisabledLandscape;
}); });
} }
Widget get videoReplyPanel => Obx(
() => VideoReplyPanel(
bvid: videoDetailController.bvid,
oid: videoDetailController.oid.value,
heroTag: heroTag,
replyReply: replyReply,
),
);
// 展示二级回复
void replyReply(replyItem) {
scaffoldKey.currentState?.showBottomSheet(
(context) => VideoReplyReplyPanel(
rcount: replyItem.rcount,
oid: replyItem.oid,
rpid: replyItem.rpid,
firstFloor: replyItem,
replyType: ReplyType.video,
source: 'videoDetail',
),
);
}
// ai总结
showAiBottomSheet() {
scaffoldKey.currentState?.showBottomSheet(
enableDrag: true,
(context) => AiDetail(modelResult: videoIntroController.modelResult));
}
showIntroDetail(videoDetail) {
scaffoldKey.currentState?.showBottomSheet(
enableDrag: true, (context) => IntroDetail(videoDetail: videoDetail));
}
} }