mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
@@ -109,9 +109,18 @@ class _ListSheetContentState extends State<ListSheetContent>
|
||||
_indexStream?.add(_ctr?.index);
|
||||
}
|
||||
|
||||
late bool _isInit = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (GStorage.collapsibleVideoPage) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
setState(() {
|
||||
_isInit = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
if (_isList) {
|
||||
_indexStream ??= StreamController<int>.broadcast();
|
||||
_ctr = TabController(
|
||||
@@ -127,7 +136,7 @@ class _ListSheetContentState extends State<ListSheetContent>
|
||||
reverse = _isList
|
||||
? List.generate(widget.season.sections.length, (_) => false)
|
||||
: [false];
|
||||
if (widget.bvid != null && widget.season != null) {
|
||||
if (GStorage.isLogin && widget.bvid != null && widget.season != null) {
|
||||
_favStream ??= StreamController<int>();
|
||||
() async {
|
||||
dynamic result = await VideoHttp.videoRelation(bvid: widget.bvid);
|
||||
@@ -278,6 +287,12 @@ class _ListSheetContentState extends State<ListSheetContent>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (GStorage.collapsibleVideoPage && _isInit) {
|
||||
return CustomScrollView(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
@@ -473,6 +488,7 @@ class _ListSheetContentState extends State<ListSheetContent>
|
||||
),
|
||||
reverse: reverse[i ?? 0],
|
||||
itemCount: episodes.length,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return buildEpisodeListItem(
|
||||
episodes[index],
|
||||
|
||||
@@ -22,6 +22,7 @@ import 'package:PiliPlus/pages/search/widgets/search_text.dart';
|
||||
import 'package:PiliPlus/pages/video/detail/introduction/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/detail/related/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/detail/reply/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/detail/view_v.dart' show ViewPointsPage;
|
||||
import 'package:PiliPlus/pages/video/detail/widgets/send_danmaku_panel.dart';
|
||||
import 'package:PiliPlus/pages/video/detail/widgets/watch_later_list.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
@@ -1329,8 +1330,10 @@ class VideoDetailController extends GetxController
|
||||
} else {
|
||||
childKey.currentState?.showBottomSheet(
|
||||
enableDrag: false,
|
||||
(context) => _postPanel(),
|
||||
backgroundColor: Colors.transparent,
|
||||
(context) => ViewPointsPage(
|
||||
child: _postPanel(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1496,6 +1499,8 @@ class VideoDetailController extends GetxController
|
||||
? Stack(
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
controller: ScrollController(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
...List.generate(
|
||||
|
||||
@@ -107,7 +107,7 @@ class _VideoReplyPanelState extends State<VideoReplyPanel>
|
||||
? null
|
||||
: _videoReplyController.scrollController,
|
||||
physics: widget.needController == false
|
||||
? const NeverScrollableScrollPhysics(
|
||||
? const AlwaysScrollableScrollPhysics(
|
||||
parent: ClampingScrollPhysics(),
|
||||
)
|
||||
: const AlwaysScrollableScrollPhysics(),
|
||||
|
||||
@@ -1796,13 +1796,13 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
);
|
||||
|
||||
Widget videoIntro([bool needRelated = true, bool needCtr = true]) {
|
||||
Widget introPanel() => Material(
|
||||
color: Colors.transparent,
|
||||
child: CustomScrollView(
|
||||
Widget introPanel() => Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
body: CustomScrollView(
|
||||
key: const PageStorageKey<String>('简介'),
|
||||
controller: needCtr ? _introController : null,
|
||||
physics: needCtr.not
|
||||
? const NeverScrollableScrollPhysics(
|
||||
? const AlwaysScrollableScrollPhysics(
|
||||
parent: ClampingScrollPhysics(),
|
||||
)
|
||||
: null,
|
||||
@@ -2260,6 +2260,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
controller: ScrollController(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: Column(
|
||||
children: [
|
||||
...List.generate(
|
||||
@@ -2358,7 +2360,9 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
} else {
|
||||
videoDetailController.childKey.currentState?.showBottomSheet(
|
||||
backgroundColor: Colors.transparent,
|
||||
(context) => listSheetContent(),
|
||||
(context) => ViewPointsPage(
|
||||
child: listSheetContent(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2391,3 +2395,35 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ViewPointsPage extends StatefulWidget {
|
||||
const ViewPointsPage({super.key, required this.child});
|
||||
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
State<ViewPointsPage> createState() => _ViewPointsPageState();
|
||||
}
|
||||
|
||||
class _ViewPointsPageState extends State<ViewPointsPage> {
|
||||
bool _isInit = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
setState(() {
|
||||
_isInit = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _isInit
|
||||
? CustomScrollView(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
)
|
||||
: widget.child;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1125,6 +1125,81 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
child: Semantics(
|
||||
label: '双击开关控件',
|
||||
child: GestureDetector(
|
||||
onVerticalDragStart: (details) {
|
||||
if (plPlayerController.controlsLock.value) return;
|
||||
if (details.localPosition.dy < 40) return;
|
||||
_initialFocalPoint = details.localPosition;
|
||||
_gestureType = null;
|
||||
},
|
||||
onVerticalDragUpdate: (details) {
|
||||
if (plPlayerController.controlsLock.value) return;
|
||||
RenderBox renderBox =
|
||||
_playerKey.currentContext!.findRenderObject() as RenderBox;
|
||||
final double totalWidth = renderBox.size.width;
|
||||
final double tapPosition = details.localPosition.dx;
|
||||
final double sectionWidth = totalWidth / 3;
|
||||
if (tapPosition < sectionWidth) {
|
||||
// 左边区域
|
||||
_gestureType = 'left';
|
||||
} else if (tapPosition < sectionWidth * 2) {
|
||||
// 全屏
|
||||
_gestureType = 'center';
|
||||
} else {
|
||||
// 右边区域
|
||||
_gestureType = 'right';
|
||||
}
|
||||
if (_gestureType == 'left') {
|
||||
// 左边区域 👈
|
||||
final double level = renderBox.size.height * 3;
|
||||
final double brightness =
|
||||
_brightnessValue.value - details.delta.dy / level;
|
||||
final double result = brightness.clamp(0.0, 1.0);
|
||||
setBrightness(result);
|
||||
} else if (_gestureType == 'center') {
|
||||
// 全屏
|
||||
const double threshold = 2.5; // 滑动阈值
|
||||
double cumulativeDy =
|
||||
details.localPosition.dy - _initialFocalPoint.dy;
|
||||
|
||||
void fullScreenTrigger(bool status) {
|
||||
EasyThrottle.throttle(
|
||||
'fullScreen', const Duration(milliseconds: 800),
|
||||
() async {
|
||||
await plPlayerController.triggerFullScreen(
|
||||
status: status);
|
||||
});
|
||||
}
|
||||
|
||||
if (cumulativeDy > threshold) {
|
||||
_gestureType = 'center_down';
|
||||
if (isFullScreen ^ fullScreenGestureReverse) {
|
||||
fullScreenTrigger(fullScreenGestureReverse);
|
||||
}
|
||||
// debugPrint('center_down:$cumulativeDy');
|
||||
} else if (cumulativeDy < -threshold) {
|
||||
_gestureType = 'center_up';
|
||||
if (!isFullScreen ^ fullScreenGestureReverse) {
|
||||
fullScreenTrigger(!fullScreenGestureReverse);
|
||||
}
|
||||
// debugPrint('center_up:$cumulativeDy');
|
||||
}
|
||||
} else if (_gestureType == 'right') {
|
||||
// 右边区域
|
||||
final double level = renderBox.size.height * 0.5;
|
||||
EasyThrottle.throttle(
|
||||
'setVolume', const Duration(milliseconds: 20), () {
|
||||
final double volume =
|
||||
_volumeValue.value - details.delta.dy / level;
|
||||
final double result = volume.clamp(0.0, 1.0);
|
||||
setVolume(result);
|
||||
});
|
||||
}
|
||||
},
|
||||
onVerticalDragEnd: (details) {
|
||||
interacting = false;
|
||||
_initialFocalPoint = Offset.zero;
|
||||
_gestureType = null;
|
||||
},
|
||||
onTap: () {
|
||||
plPlayerController.controls =
|
||||
!plPlayerController.showControls.value;
|
||||
|
||||
Reference in New Issue
Block a user