mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-07-14 21:30:15 +08:00
opt video page
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -487,456 +487,440 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget get childWhenDisabled => SafeArea(
|
Widget get childWhenDisabled {
|
||||||
top: !removeSafeArea &&
|
final isPortrait =
|
||||||
MediaQuery.of(context).orientation == Orientation.portrait &&
|
MediaQuery.orientationOf(context) == Orientation.portrait;
|
||||||
isFullScreen,
|
final useSafeArea = !removeSafeArea && isPortrait && isFullScreen;
|
||||||
bottom: !removeSafeArea &&
|
final size = MediaQuery.sizeOf(context);
|
||||||
MediaQuery.of(context).orientation == Orientation.portrait &&
|
final double width = size.width;
|
||||||
isFullScreen,
|
final double height = size.height;
|
||||||
left: false,
|
return SafeArea(
|
||||||
right: false,
|
top: useSafeArea,
|
||||||
child: Scaffold(
|
bottom: useSafeArea,
|
||||||
resizeToAvoidBottomInset: false,
|
left: false,
|
||||||
key: videoDetailController.scaffoldKey,
|
right: false,
|
||||||
appBar: removeSafeArea
|
child: Scaffold(
|
||||||
? null
|
resizeToAvoidBottomInset: false,
|
||||||
: PreferredSize(
|
key: videoDetailController.scaffoldKey,
|
||||||
preferredSize: const Size.fromHeight(0),
|
appBar: removeSafeArea
|
||||||
child: Obx(
|
? null
|
||||||
() {
|
: PreferredSize(
|
||||||
bool shouldShow =
|
preferredSize: const Size.fromHeight(0),
|
||||||
videoDetailController.scrollRatio.value != 0 &&
|
child: Obx(
|
||||||
videoDetailController.scrollCtr.offset != 0 &&
|
() {
|
||||||
context.orientation == Orientation.portrait;
|
bool shouldShow =
|
||||||
return Stack(
|
videoDetailController.scrollRatio.value != 0 &&
|
||||||
clipBehavior: Clip.none,
|
videoDetailController.scrollCtr.offset != 0 &&
|
||||||
children: [
|
isPortrait;
|
||||||
AppBar(
|
return Stack(
|
||||||
backgroundColor: Colors.black,
|
clipBehavior: Clip.none,
|
||||||
toolbarHeight: 0,
|
children: [
|
||||||
systemOverlayStyle: Platform.isAndroid
|
AppBar(
|
||||||
? shouldShow
|
backgroundColor: Colors.black,
|
||||||
? null
|
toolbarHeight: 0,
|
||||||
: SystemUiOverlayStyle(
|
systemOverlayStyle: Platform.isAndroid
|
||||||
statusBarIconBrightness:
|
? shouldShow
|
||||||
Brightness.light,
|
? null
|
||||||
systemNavigationBarIconBrightness:
|
: SystemUiOverlayStyle(
|
||||||
themeData.brightness.reverse,
|
statusBarIconBrightness: Brightness.light,
|
||||||
)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
if (shouldShow)
|
|
||||||
AppBar(
|
|
||||||
backgroundColor: themeData.colorScheme.surface
|
|
||||||
.withValues(
|
|
||||||
alpha: videoDetailController
|
|
||||||
.scrollRatio.value),
|
|
||||||
toolbarHeight: 0,
|
|
||||||
systemOverlayStyle: Platform.isAndroid
|
|
||||||
? SystemUiOverlayStyle(
|
|
||||||
statusBarIconBrightness:
|
|
||||||
themeData.brightness.reverse,
|
|
||||||
systemNavigationBarIconBrightness:
|
systemNavigationBarIconBrightness:
|
||||||
themeData.brightness.reverse,
|
themeData.brightness.reverse,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
],
|
if (shouldShow)
|
||||||
);
|
AppBar(
|
||||||
},
|
backgroundColor: themeData.colorScheme.surface
|
||||||
),
|
.withValues(
|
||||||
|
alpha: videoDetailController
|
||||||
|
.scrollRatio.value),
|
||||||
|
toolbarHeight: 0,
|
||||||
|
systemOverlayStyle: Platform.isAndroid
|
||||||
|
? SystemUiOverlayStyle(
|
||||||
|
statusBarIconBrightness:
|
||||||
|
themeData.brightness.reverse,
|
||||||
|
systemNavigationBarIconBrightness:
|
||||||
|
themeData.brightness.reverse,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
body: ExtendedNestedScrollView(
|
),
|
||||||
key: videoDetailController.scrollKey,
|
body: ExtendedNestedScrollView(
|
||||||
physics: const NeverScrollableScrollPhysics(
|
key: videoDetailController.scrollKey,
|
||||||
parent: ClampingScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(
|
||||||
),
|
parent: ClampingScrollPhysics(),
|
||||||
controller: videoDetailController.scrollCtr,
|
),
|
||||||
onlyOneScrollInBody: true,
|
controller: videoDetailController.scrollCtr,
|
||||||
pinnedHeaderSliverHeightBuilder: () {
|
onlyOneScrollInBody: true,
|
||||||
double height = isFullScreen ||
|
pinnedHeaderSliverHeightBuilder: () {
|
||||||
context.orientation == Orientation.landscape
|
double pinnedHeight = isFullScreen || !isPortrait
|
||||||
? MediaQuery.sizeOf(context).height
|
? height
|
||||||
: videoDetailController.isExpanding ||
|
: videoDetailController.isExpanding ||
|
||||||
videoDetailController.isCollapsing
|
videoDetailController.isCollapsing
|
||||||
? animHeight
|
? animHeight
|
||||||
: videoDetailController.isCollapsing ||
|
: videoDetailController.isCollapsing ||
|
||||||
plPlayerController?.playerStatus.status.value ==
|
plPlayerController?.playerStatus.status.value ==
|
||||||
PlayerStatus.playing
|
PlayerStatus.playing
|
||||||
? videoDetailController.minVideoHeight
|
? videoDetailController.minVideoHeight
|
||||||
: kToolbarHeight;
|
: kToolbarHeight;
|
||||||
if (videoDetailController.isExpanding &&
|
if (videoDetailController.isExpanding &&
|
||||||
videoDetailController.animationController.value == 1) {
|
videoDetailController.animationController.value == 1) {
|
||||||
videoDetailController.isExpanding = false;
|
videoDetailController.isExpanding = false;
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
videoDetailController.scrollRatio.value = 0;
|
videoDetailController.scrollRatio.value = 0;
|
||||||
refreshPage();
|
refreshPage();
|
||||||
});
|
});
|
||||||
} else if (videoDetailController.isCollapsing &&
|
} else if (videoDetailController.isCollapsing &&
|
||||||
videoDetailController.animationController.value == 1) {
|
videoDetailController.animationController.value == 1) {
|
||||||
videoDetailController.isCollapsing = false;
|
videoDetailController.isCollapsing = false;
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
refreshPage();
|
refreshPage();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return height;
|
return pinnedHeight;
|
||||||
},
|
},
|
||||||
headerSliverBuilder:
|
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||||
(BuildContext context, bool innerBoxIsScrolled) {
|
return [
|
||||||
return [
|
SliverAppBar(
|
||||||
SliverAppBar(
|
elevation: 0,
|
||||||
elevation: 0,
|
scrolledUnderElevation: 0,
|
||||||
scrolledUnderElevation: 0,
|
primary: false,
|
||||||
primary: false,
|
automaticallyImplyLeading: false,
|
||||||
automaticallyImplyLeading: false,
|
pinned: true,
|
||||||
pinned: true,
|
expandedHeight: isFullScreen || !isPortrait
|
||||||
expandedHeight: isFullScreen ||
|
? height
|
||||||
context.orientation == Orientation.landscape
|
: videoDetailController.isExpanding ||
|
||||||
? MediaQuery.sizeOf(context).height
|
videoDetailController.isCollapsing
|
||||||
: videoDetailController.isExpanding ||
|
? animHeight
|
||||||
videoDetailController.isCollapsing
|
: videoDetailController.videoHeight,
|
||||||
? animHeight
|
flexibleSpace: Stack(
|
||||||
: videoDetailController.videoHeight,
|
clipBehavior: Clip.none,
|
||||||
flexibleSpace: Stack(
|
children: [
|
||||||
clipBehavior: Clip.none,
|
Builder(
|
||||||
children: [
|
builder: (context) {
|
||||||
Builder(
|
if (!isPortrait &&
|
||||||
builder: (context) {
|
!videoDetailController.horizontalScreen &&
|
||||||
final double videoWidth = context.width;
|
!isFullScreen &&
|
||||||
if (MediaQuery.of(context).orientation ==
|
isShowing &&
|
||||||
Orientation.landscape &&
|
mounted) {
|
||||||
!videoDetailController.horizontalScreen &&
|
hideStatusBar();
|
||||||
!isFullScreen &&
|
}
|
||||||
isShowing &&
|
if (isPortrait &&
|
||||||
mounted) {
|
!isFullScreen &&
|
||||||
hideStatusBar();
|
isShowing &&
|
||||||
|
mounted) {
|
||||||
|
if (!videoDetailController.imageStatus &&
|
||||||
|
!removeSafeArea) {
|
||||||
|
showStatusBar();
|
||||||
}
|
}
|
||||||
if (MediaQuery.of(context).orientation ==
|
}
|
||||||
Orientation.portrait &&
|
return SizedBox(
|
||||||
!isFullScreen &&
|
height: !isPortrait || isFullScreen
|
||||||
isShowing &&
|
? height -
|
||||||
mounted) {
|
(!isPortrait || removeSafeArea
|
||||||
if (!videoDetailController.imageStatus &&
|
? 0
|
||||||
!removeSafeArea) {
|
: MediaQuery.of(this.context).padding.top)
|
||||||
showStatusBar();
|
: videoDetailController.isExpanding ||
|
||||||
}
|
videoDetailController.isCollapsing
|
||||||
}
|
? animHeight
|
||||||
return SizedBox(
|
: videoDetailController.videoHeight,
|
||||||
height: MediaQuery.of(context).orientation ==
|
width: width,
|
||||||
Orientation.landscape ||
|
child: videoPlayer(
|
||||||
isFullScreen
|
width,
|
||||||
? MediaQuery.sizeOf(context).height -
|
!isPortrait || isFullScreen
|
||||||
(MediaQuery.of(context).orientation ==
|
? height
|
||||||
Orientation.landscape ||
|
|
||||||
removeSafeArea
|
|
||||||
? 0
|
|
||||||
: MediaQuery.of(this.context)
|
|
||||||
.padding
|
|
||||||
.top)
|
|
||||||
: videoDetailController.isExpanding ||
|
: videoDetailController.isExpanding ||
|
||||||
videoDetailController.isCollapsing
|
videoDetailController.isCollapsing
|
||||||
? animHeight
|
? animHeight
|
||||||
: videoDetailController.videoHeight,
|
: videoDetailController.videoHeight,
|
||||||
width: context.width,
|
),
|
||||||
child: videoPlayer(
|
);
|
||||||
videoWidth,
|
},
|
||||||
context.orientation == Orientation.landscape ||
|
),
|
||||||
isFullScreen
|
Obx(
|
||||||
? context.height
|
() {
|
||||||
: videoDetailController.isExpanding ||
|
Widget toolbar() => Opacity(
|
||||||
videoDetailController.isCollapsing
|
opacity: videoDetailController.scrollRatio.value,
|
||||||
? animHeight
|
child: Container(
|
||||||
: videoDetailController.videoHeight,
|
color: themeData.colorScheme.surface,
|
||||||
),
|
alignment: Alignment.topCenter,
|
||||||
);
|
child: SizedBox(
|
||||||
},
|
height: kToolbarHeight,
|
||||||
),
|
child: Stack(
|
||||||
Obx(
|
clipBehavior: Clip.none,
|
||||||
() {
|
children: [
|
||||||
Widget toolbar() => Opacity(
|
Align(
|
||||||
opacity:
|
alignment: Alignment.centerLeft,
|
||||||
videoDetailController.scrollRatio.value,
|
child: Row(
|
||||||
child: Container(
|
mainAxisSize: MainAxisSize.min,
|
||||||
color: themeData.colorScheme.surface,
|
children: [
|
||||||
alignment: Alignment.topCenter,
|
SizedBox(
|
||||||
child: SizedBox(
|
width: 42,
|
||||||
height: kToolbarHeight,
|
height: 34,
|
||||||
child: Stack(
|
child: IconButton(
|
||||||
clipBehavior: Clip.none,
|
tooltip: '返回',
|
||||||
children: [
|
icon: Icon(
|
||||||
Align(
|
FontAwesomeIcons.arrowLeft,
|
||||||
alignment: Alignment.centerLeft,
|
size: 15,
|
||||||
child: Row(
|
color: themeData
|
||||||
mainAxisSize: MainAxisSize.min,
|
.colorScheme.onSurface,
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: 42,
|
|
||||||
height: 34,
|
|
||||||
child: IconButton(
|
|
||||||
tooltip: '返回',
|
|
||||||
icon: Icon(
|
|
||||||
FontAwesomeIcons.arrowLeft,
|
|
||||||
size: 15,
|
|
||||||
color: themeData
|
|
||||||
.colorScheme.onSurface,
|
|
||||||
),
|
|
||||||
onPressed: Get.back,
|
|
||||||
),
|
),
|
||||||
|
onPressed: Get.back,
|
||||||
),
|
),
|
||||||
SizedBox(
|
),
|
||||||
width: 42,
|
SizedBox(
|
||||||
height: 34,
|
width: 42,
|
||||||
child: IconButton(
|
height: 34,
|
||||||
tooltip: '返回主页',
|
child: IconButton(
|
||||||
icon: Icon(
|
tooltip: '返回主页',
|
||||||
FontAwesomeIcons.house,
|
icon: Icon(
|
||||||
size: 15,
|
FontAwesomeIcons.house,
|
||||||
color: themeData
|
size: 15,
|
||||||
.colorScheme.onSurface,
|
color: themeData
|
||||||
),
|
.colorScheme.onSurface,
|
||||||
onPressed: () {
|
|
||||||
videoDetailController
|
|
||||||
.plPlayerController
|
|
||||||
.backToHome = true;
|
|
||||||
Get.until((route) =>
|
|
||||||
route.isFirst);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
onPressed: () {
|
||||||
|
videoDetailController
|
||||||
|
.plPlayerController
|
||||||
|
.backToHome = true;
|
||||||
|
Get.until(
|
||||||
|
(route) => route.isFirst);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
Center(
|
),
|
||||||
child: Row(
|
Center(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Row(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
Icon(
|
children: [
|
||||||
Icons.play_arrow_rounded,
|
Icon(
|
||||||
|
Icons.play_arrow_rounded,
|
||||||
|
color:
|
||||||
|
themeData.colorScheme.primary,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'${videoDetailController.playedTime == null ? '立即' : plPlayerController!.playerStatus.status.value == PlayerStatus.completed ? '重新' : '继续'}播放',
|
||||||
|
style: TextStyle(
|
||||||
color: themeData
|
color: themeData
|
||||||
.colorScheme.primary,
|
.colorScheme.primary,
|
||||||
),
|
),
|
||||||
Text(
|
),
|
||||||
'${videoDetailController.playedTime == null ? '立即' : plPlayerController!.playerStatus.status.value == PlayerStatus.completed ? '重新' : '继续'}播放',
|
],
|
||||||
style: TextStyle(
|
|
||||||
color: themeData
|
|
||||||
.colorScheme.primary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Align(
|
),
|
||||||
alignment: Alignment.centerRight,
|
Align(
|
||||||
child: videoDetailController
|
alignment: Alignment.centerRight,
|
||||||
.playedTime ==
|
child: videoDetailController
|
||||||
null
|
.playedTime ==
|
||||||
? PopupMenuButton<String>(
|
null
|
||||||
|
? PopupMenuButton<String>(
|
||||||
|
icon: Icon(
|
||||||
|
size: 22,
|
||||||
|
Icons.more_vert,
|
||||||
|
color: themeData
|
||||||
|
.colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
onSelected:
|
||||||
|
(String type) async {
|
||||||
|
switch (type) {
|
||||||
|
case 'later':
|
||||||
|
await videoIntroController
|
||||||
|
.viewLater();
|
||||||
|
break;
|
||||||
|
case 'report':
|
||||||
|
if (!Accounts
|
||||||
|
.main.isLogin) {
|
||||||
|
SmartDialog.showToast(
|
||||||
|
'账号未登录');
|
||||||
|
} else {
|
||||||
|
PageUtils.reportVideo(
|
||||||
|
videoDetailController
|
||||||
|
.oid.value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'note':
|
||||||
|
videoDetailController
|
||||||
|
.showNoteList(
|
||||||
|
context);
|
||||||
|
break;
|
||||||
|
case 'savePic':
|
||||||
|
DownloadUtils.downloadImg(
|
||||||
|
context,
|
||||||
|
[
|
||||||
|
videoDetailController
|
||||||
|
.videoItem['pic']
|
||||||
|
],
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemBuilder: (BuildContext
|
||||||
|
context) =>
|
||||||
|
<PopupMenuEntry<String>>[
|
||||||
|
const PopupMenuItem<String>(
|
||||||
|
value: 'later',
|
||||||
|
child: Text('稍后再看'),
|
||||||
|
),
|
||||||
|
if (videoDetailController
|
||||||
|
.epId ==
|
||||||
|
null)
|
||||||
|
const PopupMenuItem<String>(
|
||||||
|
value: 'note',
|
||||||
|
child: Text('查看笔记'),
|
||||||
|
),
|
||||||
|
if (videoDetailController
|
||||||
|
.videoItem['pic'] !=
|
||||||
|
null)
|
||||||
|
const PopupMenuItem<String>(
|
||||||
|
value: 'savePic',
|
||||||
|
child: Text('保存封面'),
|
||||||
|
),
|
||||||
|
const PopupMenuItem<String>(
|
||||||
|
value: 'report',
|
||||||
|
child: Text('举报'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: SizedBox(
|
||||||
|
width: 42,
|
||||||
|
height: 34,
|
||||||
|
child: IconButton(
|
||||||
|
tooltip: "更多设置",
|
||||||
|
style: ButtonStyle(
|
||||||
|
padding:
|
||||||
|
WidgetStateProperty.all(
|
||||||
|
EdgeInsets.zero),
|
||||||
|
),
|
||||||
|
onPressed: () =>
|
||||||
|
videoDetailController
|
||||||
|
.headerCtrKey
|
||||||
|
.currentState
|
||||||
|
?.showSettingSheet(),
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
size: 22,
|
Icons.more_vert_outlined,
|
||||||
Icons.more_vert,
|
size: 19,
|
||||||
color: themeData
|
color: themeData
|
||||||
.colorScheme.onSurface,
|
.colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
onSelected:
|
|
||||||
(String type) async {
|
|
||||||
switch (type) {
|
|
||||||
case 'later':
|
|
||||||
await videoIntroController
|
|
||||||
.viewLater();
|
|
||||||
break;
|
|
||||||
case 'report':
|
|
||||||
if (!Accounts
|
|
||||||
.main.isLogin) {
|
|
||||||
SmartDialog.showToast(
|
|
||||||
'账号未登录');
|
|
||||||
} else {
|
|
||||||
PageUtils.reportVideo(
|
|
||||||
videoDetailController
|
|
||||||
.oid.value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'note':
|
|
||||||
videoDetailController
|
|
||||||
.showNoteList(
|
|
||||||
context);
|
|
||||||
break;
|
|
||||||
case 'savePic':
|
|
||||||
DownloadUtils
|
|
||||||
.downloadImg(
|
|
||||||
context,
|
|
||||||
[
|
|
||||||
videoDetailController
|
|
||||||
.videoItem[
|
|
||||||
'pic']
|
|
||||||
],
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemBuilder: (BuildContext
|
|
||||||
context) =>
|
|
||||||
<PopupMenuEntry<String>>[
|
|
||||||
const PopupMenuItem<String>(
|
|
||||||
value: 'later',
|
|
||||||
child: Text('稍后再看'),
|
|
||||||
),
|
|
||||||
if (videoDetailController
|
|
||||||
.epId ==
|
|
||||||
null)
|
|
||||||
const PopupMenuItem<
|
|
||||||
String>(
|
|
||||||
value: 'note',
|
|
||||||
child: Text('查看笔记'),
|
|
||||||
),
|
|
||||||
if (videoDetailController
|
|
||||||
.videoItem['pic'] !=
|
|
||||||
null)
|
|
||||||
const PopupMenuItem<
|
|
||||||
String>(
|
|
||||||
value: 'savePic',
|
|
||||||
child: Text('保存封面'),
|
|
||||||
),
|
|
||||||
const PopupMenuItem<String>(
|
|
||||||
value: 'report',
|
|
||||||
child: Text('举报'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: SizedBox(
|
|
||||||
width: 42,
|
|
||||||
height: 34,
|
|
||||||
child: IconButton(
|
|
||||||
tooltip: "更多设置",
|
|
||||||
style: ButtonStyle(
|
|
||||||
padding:
|
|
||||||
WidgetStateProperty
|
|
||||||
.all(EdgeInsets
|
|
||||||
.zero),
|
|
||||||
),
|
|
||||||
onPressed: () =>
|
|
||||||
videoDetailController
|
|
||||||
.headerCtrKey
|
|
||||||
.currentState
|
|
||||||
?.showSettingSheet(),
|
|
||||||
icon: Icon(
|
|
||||||
Icons.more_vert_outlined,
|
|
||||||
size: 19,
|
|
||||||
color: themeData
|
|
||||||
.colorScheme
|
|
||||||
.onSurface,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
return videoDetailController.scrollRatio.value == 0 ||
|
);
|
||||||
videoDetailController.scrollCtr.offset == 0 ||
|
return videoDetailController.scrollRatio.value == 0 ||
|
||||||
context.orientation != Orientation.portrait
|
videoDetailController.scrollCtr.offset == 0 ||
|
||||||
? const SizedBox.shrink()
|
!isPortrait
|
||||||
: Positioned.fill(
|
? const SizedBox.shrink()
|
||||||
bottom: -2,
|
: Positioned.fill(
|
||||||
child: GestureDetector(
|
bottom: -2,
|
||||||
onTap: () async {
|
child: GestureDetector(
|
||||||
if (videoDetailController.isQuerying) {
|
onTap: () async {
|
||||||
if (kDebugMode) {
|
if (videoDetailController.isQuerying) {
|
||||||
debugPrint('handlePlay: querying');
|
if (kDebugMode) {
|
||||||
}
|
debugPrint('handlePlay: querying');
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (videoDetailController.videoUrl ==
|
return;
|
||||||
null ||
|
}
|
||||||
videoDetailController.audioUrl ==
|
if (videoDetailController.videoUrl ==
|
||||||
null) {
|
null ||
|
||||||
if (kDebugMode) {
|
videoDetailController.audioUrl ==
|
||||||
debugPrint(
|
null) {
|
||||||
'handlePlay: videoUrl/audioUrl not initialized');
|
if (kDebugMode) {
|
||||||
}
|
debugPrint(
|
||||||
videoDetailController.queryVideoUrl();
|
'handlePlay: videoUrl/audioUrl not initialized');
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
videoDetailController.scrollRatio.value =
|
videoDetailController.queryVideoUrl();
|
||||||
0;
|
return;
|
||||||
if (plPlayerController == null ||
|
}
|
||||||
videoDetailController.playedTime ==
|
videoDetailController.scrollRatio.value = 0;
|
||||||
null) {
|
if (plPlayerController == null ||
|
||||||
handlePlay();
|
videoDetailController.playedTime ==
|
||||||
} else {
|
null) {
|
||||||
if (plPlayerController!
|
handlePlay();
|
||||||
|
} else {
|
||||||
|
if (plPlayerController!
|
||||||
|
.videoPlayerController!
|
||||||
|
.state
|
||||||
|
.completed) {
|
||||||
|
await plPlayerController!
|
||||||
.videoPlayerController!
|
.videoPlayerController!
|
||||||
.state
|
.seek(Duration.zero);
|
||||||
.completed) {
|
plPlayerController!
|
||||||
await plPlayerController!
|
.videoPlayerController!
|
||||||
.videoPlayerController!
|
.play();
|
||||||
.seek(Duration.zero);
|
} else {
|
||||||
plPlayerController!
|
plPlayerController!
|
||||||
.videoPlayerController!
|
.videoPlayerController!
|
||||||
.play();
|
.playOrPause();
|
||||||
} else {
|
|
||||||
plPlayerController!
|
|
||||||
.videoPlayerController!
|
|
||||||
.playOrPause();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
behavior: HitTestBehavior.opaque,
|
},
|
||||||
child: toolbar(),
|
behavior: HitTestBehavior.opaque,
|
||||||
),
|
child: toolbar(),
|
||||||
);
|
),
|
||||||
},
|
);
|
||||||
),
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
body: Scaffold(
|
||||||
|
key: videoDetailController.childKey,
|
||||||
|
resizeToAvoidBottomInset: false,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
buildTabbar(
|
||||||
|
showReply: videoDetailController.showReply,
|
||||||
|
onTap: videoDetailController.animToTop,
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: videoTabBarView(
|
||||||
|
controller: videoDetailController.tabCtr,
|
||||||
|
children: [
|
||||||
|
videoIntro(true, false),
|
||||||
|
if (videoDetailController.showReply)
|
||||||
|
videoReplyPanel(false),
|
||||||
|
if (_shouldShowSeasonPanel) seasonPanel,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
],
|
||||||
},
|
|
||||||
body: Scaffold(
|
|
||||||
key: videoDetailController.childKey,
|
|
||||||
resizeToAvoidBottomInset: false,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
body: Column(
|
|
||||||
children: [
|
|
||||||
buildTabbar(
|
|
||||||
showReply: videoDetailController.showReply,
|
|
||||||
onTap: videoDetailController.animToTop,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: videoTabBarView(
|
|
||||||
controller: videoDetailController.tabCtr,
|
|
||||||
children: [
|
|
||||||
videoIntro(true, false),
|
|
||||||
if (videoDetailController.showReply)
|
|
||||||
videoReplyPanel(false),
|
|
||||||
if (_shouldShowSeasonPanel) seasonPanel,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget get childWhenDisabledAlmostSquareInner => Obx(
|
Widget get childWhenDisabledAlmostSquareInner => Obx(
|
||||||
() {
|
() {
|
||||||
|
final size = MediaQuery.sizeOf(context);
|
||||||
|
final double width = size.width;
|
||||||
|
final double height = size.height;
|
||||||
|
final padding = MediaQuery.paddingOf(context);
|
||||||
if (enableVerticalExpand &&
|
if (enableVerticalExpand &&
|
||||||
videoDetailController.direction.value == 'vertical') {
|
videoDetailController.direction.value == 'vertical') {
|
||||||
final double videoHeight = context.height -
|
final double videoHeight =
|
||||||
(removeSafeArea
|
height - (removeSafeArea ? 0 : padding.vertical);
|
||||||
? 0
|
|
||||||
: (MediaQuery.of(context).padding.top +
|
|
||||||
MediaQuery.of(context).padding.bottom));
|
|
||||||
final double videoWidth = videoHeight * 9 / 16;
|
final double videoWidth = videoHeight * 9 / 16;
|
||||||
return Row(
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: videoHeight,
|
height: videoHeight,
|
||||||
width: isFullScreen ? context.width : videoWidth,
|
width: isFullScreen ? width : videoWidth,
|
||||||
child: videoPlayer(videoWidth, videoHeight),
|
child: videoPlayer(videoWidth, videoHeight),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -965,20 +949,15 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final double videoHeight = context.height / 2.5;
|
final double videoHeight = height / 2.5;
|
||||||
final double videoWidth = context.width;
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: videoWidth,
|
width: width,
|
||||||
height: isFullScreen
|
height: isFullScreen
|
||||||
? context.height -
|
? height - (removeSafeArea ? 0 : padding.vertical)
|
||||||
(removeSafeArea
|
|
||||||
? 0
|
|
||||||
: (MediaQuery.of(context).padding.top +
|
|
||||||
MediaQuery.of(context).padding.bottom))
|
|
||||||
: videoHeight,
|
: videoHeight,
|
||||||
child: videoPlayer(videoWidth, videoHeight),
|
child: videoPlayer(width, videoHeight),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
@@ -1013,10 +992,14 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
|
|
||||||
Widget get childWhenDisabledLandscapeInner => Obx(
|
Widget get childWhenDisabledLandscapeInner => Obx(
|
||||||
() {
|
() {
|
||||||
|
final size = MediaQuery.sizeOf(context);
|
||||||
|
final double width = size.width;
|
||||||
|
final double height = size.height;
|
||||||
|
final padding = MediaQuery.paddingOf(context);
|
||||||
if (enableVerticalExpand &&
|
if (enableVerticalExpand &&
|
||||||
videoDetailController.direction.value == 'vertical') {
|
videoDetailController.direction.value == 'vertical') {
|
||||||
final double videoHeight = context.height -
|
final double videoHeight =
|
||||||
(removeSafeArea ? 0 : MediaQuery.of(context).padding.top);
|
height - (removeSafeArea ? 0 : padding.top);
|
||||||
final double videoWidth = videoHeight * 9 / 16;
|
final double videoWidth = videoHeight * 9 / 16;
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
@@ -1025,7 +1008,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
isFullScreen ? const SizedBox.shrink() : videoIntro()),
|
isFullScreen ? const SizedBox.shrink() : videoIntro()),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: videoHeight,
|
height: videoHeight,
|
||||||
width: isFullScreen ? context.width : videoWidth,
|
width: isFullScreen ? width : videoWidth,
|
||||||
child: videoPlayer(videoWidth, videoHeight),
|
child: videoPlayer(videoWidth, videoHeight),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -1059,10 +1042,9 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
double videoWidth =
|
double videoWidth =
|
||||||
clampDouble(context.height / context.width * 1.08, 0.5, 0.7) *
|
clampDouble(height / width * 1.08, 0.5, 0.7) * width;
|
||||||
context.width;
|
if (width >= 560) {
|
||||||
if (context.width >= 560) {
|
videoWidth = min(videoWidth, width - 280);
|
||||||
videoWidth = min(videoWidth, context.width - 280);
|
|
||||||
}
|
}
|
||||||
final double videoHeight = videoWidth * 9 / 16;
|
final double videoHeight = videoWidth * 9 / 16;
|
||||||
return Row(
|
return Row(
|
||||||
@@ -1070,19 +1052,17 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: isFullScreen ? context.width : videoWidth,
|
width: isFullScreen ? width : videoWidth,
|
||||||
height: isFullScreen ? context.height : videoHeight,
|
height: isFullScreen ? height : videoHeight,
|
||||||
child: videoPlayer(videoWidth, videoHeight),
|
child: videoPlayer(videoWidth, videoHeight),
|
||||||
),
|
),
|
||||||
Offstage(
|
Offstage(
|
||||||
offstage: isFullScreen,
|
offstage: isFullScreen,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: videoWidth,
|
width: videoWidth,
|
||||||
height: context.height -
|
height: height -
|
||||||
videoHeight -
|
videoHeight -
|
||||||
(removeSafeArea
|
(removeSafeArea ? 0 : padding.top),
|
||||||
? 0
|
|
||||||
: MediaQuery.of(context).padding.top),
|
|
||||||
child: videoIntro(false, false),
|
child: videoIntro(false, false),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1091,14 +1071,10 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
Offstage(
|
Offstage(
|
||||||
offstage: isFullScreen,
|
offstage: isFullScreen,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: (context.width -
|
width: width -
|
||||||
videoWidth -
|
videoWidth -
|
||||||
(removeSafeArea
|
(removeSafeArea ? 0 : padding.horizontal),
|
||||||
? 0
|
height: height - (removeSafeArea ? 0 : padding.top),
|
||||||
: (MediaQuery.of(context).padding.left +
|
|
||||||
MediaQuery.of(context).padding.right))),
|
|
||||||
height: context.height -
|
|
||||||
(removeSafeArea ? 0 : MediaQuery.of(context).padding.top),
|
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
key: videoDetailController.childKey,
|
key: videoDetailController.childKey,
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
@@ -1591,7 +1567,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
return PopScope(
|
return PopScope(
|
||||||
canPop: !isFullScreen &&
|
canPop: !isFullScreen &&
|
||||||
(videoDetailController.horizontalScreen ||
|
(videoDetailController.horizontalScreen ||
|
||||||
MediaQuery.of(context).orientation == Orientation.portrait),
|
MediaQuery.orientationOf(context) == Orientation.portrait),
|
||||||
onPopInvokedWithResult: _onPopInvokedWithResult,
|
onPopInvokedWithResult: _onPopInvokedWithResult,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
@@ -1753,6 +1729,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget videoIntro([bool needRelated = true, bool needCtr = true]) {
|
Widget videoIntro([bool needRelated = true, bool needCtr = true]) {
|
||||||
|
final bottom = MediaQuery.paddingOf(context).bottom;
|
||||||
Widget introPanel() => Scaffold(
|
Widget introPanel() => Scaffold(
|
||||||
resizeToAvoidBottomInset: false,
|
resizeToAvoidBottomInset: false,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
@@ -1793,8 +1770,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
] else
|
] else
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: MediaQuery.paddingOf(context).bottom +
|
height: bottom + StyleString.safeSpace,
|
||||||
StyleString.safeSpace,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
] else if (videoDetailController.videoType ==
|
] else if (videoDetailController.videoType ==
|
||||||
@@ -1810,7 +1786,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: MediaQuery.paddingOf(context).bottom +
|
height: bottom +
|
||||||
(videoDetailController.isPlayAll &&
|
(videoDetailController.isPlayAll &&
|
||||||
MediaQuery.orientationOf(context) ==
|
MediaQuery.orientationOf(context) ==
|
||||||
Orientation.landscape
|
Orientation.landscape
|
||||||
@@ -1829,7 +1805,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
Positioned(
|
Positioned(
|
||||||
left: 12,
|
left: 12,
|
||||||
right: 12,
|
right: 12,
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 12,
|
bottom: bottom + 12,
|
||||||
child: Material(
|
child: Material(
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
@@ -2233,7 +2209,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
|||||||
if (isFullScreen) {
|
if (isFullScreen) {
|
||||||
plPlayerController!.triggerFullScreen(status: false);
|
plPlayerController!.triggerFullScreen(status: false);
|
||||||
}
|
}
|
||||||
if (MediaQuery.of(context).orientation == Orientation.landscape &&
|
if (MediaQuery.orientationOf(context) == Orientation.landscape &&
|
||||||
!videoDetailController.horizontalScreen) {
|
!videoDetailController.horizontalScreen) {
|
||||||
verticalScreenForTwoSeconds();
|
verticalScreenForTwoSeconds();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1801,15 +1801,12 @@ Widget buildSeekPreviewWidget(PlPlayerController plPlayerController) {
|
|||||||
if (plPlayerController.videoShot == null) {
|
if (plPlayerController.videoShot == null) {
|
||||||
plPlayerController.getVideoShot();
|
plPlayerController.getVideoShot();
|
||||||
}
|
}
|
||||||
return SizedBox.shrink(
|
return const SizedBox.shrink();
|
||||||
key: ValueKey(plPlayerController.previewDx.value),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoShotData data = plPlayerController.videoShot!['data'];
|
VideoShotData data = plPlayerController.videoShot!['data'];
|
||||||
|
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
key: ValueKey(plPlayerController.previewDx.value),
|
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
try {
|
try {
|
||||||
double scale = plPlayerController.isFullScreen.value &&
|
double scale = plPlayerController.isFullScreen.value &&
|
||||||
|
|||||||
Reference in New Issue
Block a user