mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-01 08:38:18 +08:00
@@ -984,6 +984,7 @@ class _InheritedResetNotifier extends InheritedNotifier<_ResetNotifier> {
|
||||
required _ResetNotifier super.notifier,
|
||||
});
|
||||
|
||||
// ignore: unused_element
|
||||
bool _sendReset() => notifier!.sendReset();
|
||||
|
||||
/// Specifies whether the [DraggableScrollableSheet] should reset to its
|
||||
|
||||
@@ -168,21 +168,55 @@ class VideoDetailController extends GetxController
|
||||
late final scrollKey = GlobalKey<ExtendedNestedScrollViewState>();
|
||||
late final RxBool isVertical;
|
||||
late final RxDouble scrollRatio = 0.0.obs;
|
||||
|
||||
ScrollController? _scrollCtr;
|
||||
ScrollController get scrollCtr =>
|
||||
_scrollCtr ??= ScrollController()..addListener(scrollListener);
|
||||
|
||||
late bool isExpanding = false;
|
||||
late bool isCollapsing = false;
|
||||
AnimationController? animController;
|
||||
|
||||
AnimationController get animationController =>
|
||||
animController ??= AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
);
|
||||
late double minVideoHeight;
|
||||
late double maxVideoHeight;
|
||||
late double videoHeight;
|
||||
late double animHeight;
|
||||
|
||||
AnimationController? animController;
|
||||
AnimationController get animationController =>
|
||||
animController ??= (AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
)..addListener(_animListener));
|
||||
|
||||
void refreshPage() {
|
||||
if (scrollKey.currentState?.mounted ?? false) {
|
||||
(scrollKey.currentState!.context as Element).markNeedsBuild();
|
||||
}
|
||||
}
|
||||
|
||||
void _animListener() {
|
||||
if (animationController.isForwardOrCompleted) {
|
||||
_calcAnimHeight();
|
||||
refreshPage();
|
||||
}
|
||||
}
|
||||
|
||||
void _calcAnimHeight() {
|
||||
if (isExpanding) {
|
||||
animHeight = clampDouble(
|
||||
videoHeight * animationController.value,
|
||||
kToolbarHeight,
|
||||
videoHeight,
|
||||
);
|
||||
} else if (isCollapsing) {
|
||||
animHeight = clampDouble(
|
||||
maxVideoHeight -
|
||||
(maxVideoHeight - minVideoHeight) * animationController.value,
|
||||
minVideoHeight,
|
||||
maxVideoHeight,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void animToTop() {
|
||||
final outerController = scrollKey.currentState!.outerController;
|
||||
@@ -195,8 +229,18 @@ class VideoDetailController extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
bool _needAnimOnDimensionChanged(bool isVertical) {
|
||||
if (isFullScreen) {
|
||||
if (PlatformUtils.isMobile) {
|
||||
plPlayerController.changeOrientation(isVertical: isVertical);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@pragma('vm:notify-debugger-on-exception')
|
||||
void setVideoHeight() {
|
||||
void _setVideoHeight() {
|
||||
try {
|
||||
var width = firstVideo.width;
|
||||
var height = firstVideo.height;
|
||||
@@ -205,10 +249,11 @@ class VideoDetailController extends GetxController
|
||||
final ugcIntroCtr = Get.find<UgcIntroController>(tag: heroTag);
|
||||
final data = ugcIntroCtr.videoDetail.value;
|
||||
if (data.cid == cid.value) {
|
||||
width = data.dimension!.width!;
|
||||
height = data.dimension!.height!;
|
||||
final dimension = data.dimension!;
|
||||
width = dimension.width!;
|
||||
height = dimension.height!;
|
||||
} else {
|
||||
ugcIntroCtr.queryVideoIntro().whenComplete(setVideoHeight);
|
||||
ugcIntroCtr.queryVideoIntro().whenComplete(_setVideoHeight);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -227,10 +272,12 @@ class VideoDetailController extends GetxController
|
||||
if (this.videoHeight != videoHeight) {
|
||||
if (videoHeight > this.videoHeight) {
|
||||
// current minVideoHeight
|
||||
if (_needAnimOnDimensionChanged(isVertical)) {
|
||||
isExpanding = true;
|
||||
animationController.forward(
|
||||
from: (minVideoHeight - scrollCtr.offset) / maxVideoHeight,
|
||||
);
|
||||
}
|
||||
this.videoHeight = maxVideoHeight;
|
||||
} else {
|
||||
// current maxVideoHeight
|
||||
@@ -238,20 +285,28 @@ class VideoDetailController extends GetxController
|
||||
.toPrecision(2);
|
||||
double minVideoHeightPrecise = minVideoHeight.toPrecision(2);
|
||||
if (currentHeight == minVideoHeightPrecise) {
|
||||
if (_needAnimOnDimensionChanged(isVertical)) {
|
||||
isExpanding = true;
|
||||
this.videoHeight = minVideoHeight;
|
||||
}
|
||||
animationController.forward(from: 1);
|
||||
} else if (currentHeight < minVideoHeightPrecise) {
|
||||
// expand
|
||||
if (_needAnimOnDimensionChanged(isVertical)) {
|
||||
isExpanding = true;
|
||||
animationController.forward(from: currentHeight / minVideoHeight);
|
||||
animationController.forward(
|
||||
from: currentHeight / minVideoHeight,
|
||||
);
|
||||
}
|
||||
this.videoHeight = minVideoHeight;
|
||||
} else {
|
||||
// collapse
|
||||
if (_needAnimOnDimensionChanged(isVertical)) {
|
||||
isCollapsing = true;
|
||||
animationController.forward(
|
||||
from: scrollCtr.offset / (maxVideoHeight - minVideoHeight),
|
||||
);
|
||||
}
|
||||
this.videoHeight = minVideoHeight;
|
||||
}
|
||||
}
|
||||
@@ -313,7 +368,7 @@ class VideoDetailController extends GetxController
|
||||
defaultST = Duration.zero;
|
||||
}
|
||||
data = PlayUrlModel(timeLength: entry.totalTimeMilli);
|
||||
setVideoHeight();
|
||||
_setVideoHeight();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -844,7 +899,7 @@ class VideoDetailController extends GetxController
|
||||
codecs: 'avc1',
|
||||
quality: videoQuality,
|
||||
);
|
||||
setVideoHeight();
|
||||
_setVideoHeight();
|
||||
currentDecodeFormats = VideoDecodeFormatType.fromString('avc1');
|
||||
currentVideoQa.value = videoQuality;
|
||||
await _initPlayerIfNeeded(autoFullScreenFlag);
|
||||
@@ -856,7 +911,7 @@ class VideoDetailController extends GetxController
|
||||
_autoPlay.value = false;
|
||||
videoState.value = false;
|
||||
if (plPlayerController.isFullScreen.value) {
|
||||
plPlayerController.toggleFullScreen(false);
|
||||
plPlayerController.triggerFullScreen(status: false);
|
||||
}
|
||||
isQuerying = false;
|
||||
return;
|
||||
@@ -918,7 +973,7 @@ class VideoDetailController extends GetxController
|
||||
(e) => currentDecodeFormats.codes.any(e.codecs!.startsWith),
|
||||
orElse: () => videosList.first,
|
||||
);
|
||||
setVideoHeight();
|
||||
_setVideoHeight();
|
||||
|
||||
videoUrl = VideoUtils.getCdnUrl(firstVideo.playUrls);
|
||||
|
||||
@@ -951,8 +1006,9 @@ class VideoDetailController extends GetxController
|
||||
_autoPlay.value = false;
|
||||
videoState.value = false;
|
||||
if (plPlayerController.isFullScreen.value) {
|
||||
plPlayerController.toggleFullScreen(false);
|
||||
plPlayerController.triggerFullScreen(status: false);
|
||||
}
|
||||
result.toast();
|
||||
}
|
||||
isQuerying = false;
|
||||
}
|
||||
@@ -1217,7 +1273,9 @@ class VideoDetailController extends GetxController
|
||||
_scrollCtr
|
||||
?..removeListener(scrollListener)
|
||||
..dispose();
|
||||
animController?.dispose();
|
||||
animController
|
||||
?..removeListener(_animListener)
|
||||
..dispose();
|
||||
subtitles.clear();
|
||||
vttSubtitles.clear();
|
||||
super.onClose();
|
||||
|
||||
@@ -219,10 +219,10 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
videoDetailController.videoHeight,
|
||||
);
|
||||
} else {
|
||||
refreshPage();
|
||||
videoDetailController.refreshPage();
|
||||
}
|
||||
} else {
|
||||
refreshPage();
|
||||
videoDetailController.refreshPage();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -326,8 +326,6 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
?..removeStatusLister(playerListener)
|
||||
..removePositionListener(positionListener);
|
||||
|
||||
videoDetailController.animController?.removeListener(animListener);
|
||||
|
||||
Get.delete<HorizontalMemberPageController>(
|
||||
tag: videoDetailController.heroTag,
|
||||
);
|
||||
@@ -480,48 +478,10 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
: Theme.of(context);
|
||||
}
|
||||
|
||||
void animListener() {
|
||||
if (videoDetailController.animationController.isForwardOrCompleted) {
|
||||
cal();
|
||||
refreshPage();
|
||||
}
|
||||
}
|
||||
|
||||
late double animHeight;
|
||||
|
||||
void cal() {
|
||||
if (videoDetailController.isExpanding) {
|
||||
animHeight = clampDouble(
|
||||
videoDetailController.videoHeight *
|
||||
videoDetailController.animationController.value,
|
||||
kToolbarHeight,
|
||||
videoDetailController.videoHeight,
|
||||
);
|
||||
} else if (videoDetailController.isCollapsing) {
|
||||
animHeight = clampDouble(
|
||||
videoDetailController.maxVideoHeight -
|
||||
(videoDetailController.maxVideoHeight -
|
||||
videoDetailController.minVideoHeight) *
|
||||
videoDetailController.animationController.value,
|
||||
videoDetailController.minVideoHeight,
|
||||
videoDetailController.maxVideoHeight,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void refreshPage() {
|
||||
if (videoDetailController.scrollKey.currentState?.mounted == true) {
|
||||
videoDetailController.scrollKey.currentState?.setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
bool get removeAppBar =>
|
||||
videoDetailController.removeSafeArea || (isFullScreen && !isPortrait);
|
||||
|
||||
Widget get childWhenDisabled {
|
||||
videoDetailController.animationController
|
||||
..removeListener(animListener)
|
||||
..addListener(animListener);
|
||||
return Obx(
|
||||
() {
|
||||
final isFullScreen = this.isFullScreen;
|
||||
@@ -570,7 +530,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
? maxHeight - (isPortrait ? padding.top : 0)
|
||||
: videoDetailController.isExpanding ||
|
||||
videoDetailController.isCollapsing
|
||||
? animHeight
|
||||
? videoDetailController.animHeight
|
||||
: videoDetailController.isCollapsing ||
|
||||
(plPlayerController?.playerStatus.isPlaying ?? false)
|
||||
? videoDetailController.minVideoHeight
|
||||
@@ -580,13 +540,13 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
videoDetailController.isExpanding = false;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
videoDetailController.scrollRatio.value = 0;
|
||||
refreshPage();
|
||||
videoDetailController.refreshPage();
|
||||
});
|
||||
} else if (videoDetailController.isCollapsing &&
|
||||
videoDetailController.animationController.value == 1) {
|
||||
videoDetailController.isCollapsing = false;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
refreshPage();
|
||||
videoDetailController.refreshPage();
|
||||
});
|
||||
}
|
||||
return pinnedHeight;
|
||||
@@ -596,7 +556,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
? maxHeight - (isPortrait ? padding.top : 0)
|
||||
: videoDetailController.isExpanding ||
|
||||
videoDetailController.isCollapsing
|
||||
? animHeight
|
||||
? videoDetailController.animHeight
|
||||
: videoDetailController.videoHeight;
|
||||
return [
|
||||
SliverPinnedDynamicHeader(
|
||||
@@ -833,10 +793,10 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
? null
|
||||
: AppBar(backgroundColor: Colors.black, toolbarHeight: 0),
|
||||
body: Padding(
|
||||
padding: !isFullScreen
|
||||
? padding.copyWith(top: 0, bottom: 0)
|
||||
: EdgeInsets.zero,
|
||||
child: childWhenDisabledLandscapeInner(isFullScreen, padding),
|
||||
padding: isFullScreen
|
||||
? EdgeInsets.zero
|
||||
: padding.copyWith(top: 0, bottom: 0),
|
||||
child: childWhenDisabledLandscapeInner(isFullScreen),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -893,13 +853,10 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
);
|
||||
}
|
||||
|
||||
Widget childWhenDisabledLandscapeInner(
|
||||
bool isFullScreen,
|
||||
EdgeInsets padding,
|
||||
) => Obx(() {
|
||||
if (videoDetailController.isVertical.value &&
|
||||
enableVerticalExpand &&
|
||||
!isPortrait) {
|
||||
Widget childWhenDisabledLandscapeInner(bool isFullScreen) {
|
||||
if (enableVerticalExpand) {
|
||||
return Obx(() {
|
||||
if (videoDetailController.isVertical.value && !isPortrait) {
|
||||
final double videoHeight = maxHeight - padding.vertical;
|
||||
final double width = videoHeight / Style.aspectRatio16x9;
|
||||
final videoWidth = isFullScreen ? maxWidth : width;
|
||||
@@ -957,6 +914,14 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return _childWhenDisabledLandscapeInner(isFullScreen);
|
||||
});
|
||||
}
|
||||
return _childWhenDisabledLandscapeInner(isFullScreen);
|
||||
}
|
||||
|
||||
Widget _childWhenDisabledLandscapeInner(bool isFullScreen) {
|
||||
double width =
|
||||
clampDouble(maxHeight / maxWidth * 1.08, 0.5, 0.7) * maxWidth;
|
||||
if (maxWidth >= 560) {
|
||||
@@ -1053,7 +1018,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget get childWhenDisabledAlmostSquare => Obx(() {
|
||||
final isFullScreen = this.isFullScreen;
|
||||
@@ -1063,25 +1028,31 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
? null
|
||||
: AppBar(backgroundColor: Colors.black, toolbarHeight: 0),
|
||||
body: Padding(
|
||||
padding: !isFullScreen
|
||||
? padding.copyWith(top: 0, bottom: 0)
|
||||
: EdgeInsets.zero,
|
||||
child: childWhenDisabledAlmostSquareInner(isFullScreen, padding),
|
||||
padding: isFullScreen
|
||||
? EdgeInsets.zero
|
||||
: padding.copyWith(top: 0, bottom: 0),
|
||||
child: childWhenDisabledAlmostSquareInner(isFullScreen),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
Widget childWhenDisabledAlmostSquareInner(
|
||||
bool isFullScreen,
|
||||
EdgeInsets padding,
|
||||
) => Obx(
|
||||
Widget childWhenDisabledAlmostSquareInner(bool isFullScreen) {
|
||||
if (enableVerticalExpand) {
|
||||
return Obx(
|
||||
() {
|
||||
final isFullScreen = this.isFullScreen;
|
||||
if (videoDetailController.isVertical.value &&
|
||||
enableVerticalExpand &&
|
||||
!isPortrait) {
|
||||
if (videoDetailController.isVertical.value && !isPortrait) {
|
||||
return childSplit(9 / 16);
|
||||
}
|
||||
|
||||
return _childWhenDisabledAlmostSquareInner(isFullScreen);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return _childWhenDisabledAlmostSquareInner(isFullScreen);
|
||||
}
|
||||
|
||||
Widget _childWhenDisabledAlmostSquareInner(bool isFullScreen) {
|
||||
final shouldShowSeasonPanel = _shouldShowSeasonPanel;
|
||||
final double height = maxHeight / 2.5;
|
||||
final videoHeight = isFullScreen
|
||||
@@ -1129,8 +1100,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
),
|
||||
if (videoDetailController.showReply)
|
||||
Expanded(child: videoReplyPanel()),
|
||||
if (shouldShowSeasonPanel)
|
||||
Expanded(child: seasonPanel),
|
||||
if (shouldShowSeasonPanel) Expanded(child: seasonPanel),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -1141,8 +1111,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget get manualPlayerWidget => Obx(() {
|
||||
if (!videoDetailController.autoPlay) {
|
||||
|
||||
@@ -1415,7 +1415,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
controls = !val;
|
||||
}
|
||||
|
||||
void toggleFullScreen(bool val) {
|
||||
void _setFullScreen(bool val) {
|
||||
isFullScreen.value = val;
|
||||
updateSubtitleStyle();
|
||||
}
|
||||
@@ -1426,6 +1426,37 @@ class PlPlayerController with BlockConfigMixin {
|
||||
late final horizontalScreen = Pref.horizontalScreen;
|
||||
late final removeSafeArea = Pref.removeSafeArea;
|
||||
|
||||
Future<void>? changeOrientation({
|
||||
required bool isVertical,
|
||||
DeviceOrientation? orientation,
|
||||
}) {
|
||||
if (orientation == null && (mode == .none || mode == .gravity)) {
|
||||
return null;
|
||||
}
|
||||
if (orientation == null &&
|
||||
(mode == .vertical ||
|
||||
(mode == .auto && isVertical) ||
|
||||
(mode == .ratio && (isVertical || screenRatio < kScreenRatio)))) {
|
||||
return portraitUpMode();
|
||||
} else {
|
||||
// https://github.com/flutter/flutter/issues/73651
|
||||
// https://github.com/flutter/flutter/issues/183708
|
||||
if (Platform.isAndroid) {
|
||||
if ((orientation ?? _orientation) == .landscapeRight) {
|
||||
return landscapeRightMode();
|
||||
} else {
|
||||
return landscapeLeftMode();
|
||||
}
|
||||
} else {
|
||||
if (orientation == .landscapeLeft) {
|
||||
return landscapeLeftMode();
|
||||
} else {
|
||||
return landscapeRightMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 全屏
|
||||
bool _fsProcessing = false;
|
||||
Future<void> triggerFullScreen({
|
||||
@@ -1439,38 +1470,15 @@ class PlPlayerController with BlockConfigMixin {
|
||||
|
||||
if (_fsProcessing) return;
|
||||
_fsProcessing = true;
|
||||
toggleFullScreen(status);
|
||||
this.isManualFS = isManualFS;
|
||||
try {
|
||||
if (status) {
|
||||
if (PlatformUtils.isMobile) {
|
||||
hideStatusBar();
|
||||
if (orientation == null && mode == .none) {
|
||||
return;
|
||||
}
|
||||
if (orientation == null &&
|
||||
(mode == .vertical ||
|
||||
(mode == .auto && isVertical) ||
|
||||
(mode == .ratio &&
|
||||
(isVertical || screenRatio < kScreenRatio)))) {
|
||||
await portraitUpMode();
|
||||
} else {
|
||||
// https://github.com/flutter/flutter/issues/73651
|
||||
// https://github.com/flutter/flutter/issues/183708
|
||||
if (Platform.isAndroid) {
|
||||
if ((orientation ?? _orientation) == .landscapeRight) {
|
||||
await landscapeRightMode();
|
||||
} else {
|
||||
await landscapeLeftMode();
|
||||
}
|
||||
} else {
|
||||
if (orientation == .landscapeLeft) {
|
||||
await landscapeLeftMode();
|
||||
} else {
|
||||
await landscapeRightMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
await changeOrientation(
|
||||
isVertical: isVertical,
|
||||
orientation: orientation,
|
||||
);
|
||||
} else {
|
||||
await enterDesktopFullScreen(inAppFullScreen: inAppFullScreen);
|
||||
}
|
||||
@@ -1502,6 +1510,7 @@ class PlPlayerController with BlockConfigMixin {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
_setFullScreen(status);
|
||||
_fsProcessing = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user