mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: video bottom control
Closes #244 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -3,13 +3,11 @@ enum BottomControlType {
|
||||
playOrPause,
|
||||
next,
|
||||
time,
|
||||
space,
|
||||
episode,
|
||||
fit,
|
||||
subtitle,
|
||||
speed,
|
||||
fullscreen,
|
||||
custom,
|
||||
viewPoints,
|
||||
superResolution,
|
||||
dmChart,
|
||||
|
||||
@@ -49,7 +49,6 @@ class PLVideoPlayer extends StatefulWidget {
|
||||
this.headerControl,
|
||||
this.bottomControl,
|
||||
this.danmuWidget,
|
||||
this.bottomList,
|
||||
this.customWidget,
|
||||
this.customWidgets,
|
||||
this.showEpisodes,
|
||||
@@ -63,7 +62,6 @@ class PLVideoPlayer extends StatefulWidget {
|
||||
final PreferredSizeWidget? headerControl;
|
||||
final PreferredSizeWidget? bottomControl;
|
||||
final Widget? danmuWidget;
|
||||
final List<BottomControlType>? bottomList;
|
||||
// List<Widget> or Widget
|
||||
|
||||
final Widget? customWidget;
|
||||
@@ -251,7 +249,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
}
|
||||
|
||||
// 动态构建底部控制条
|
||||
List<Widget> buildBottomControl() {
|
||||
Widget buildBottomControl() {
|
||||
bool isSeason = videoIntroController?.videoDetail.value.ugcSeason != null;
|
||||
bool isPage = videoIntroController?.videoDetail.value.pages != null &&
|
||||
videoIntroController!.videoDetail.value.pages!.length > 1;
|
||||
@@ -321,7 +319,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
|
||||
/// 时间进度
|
||||
BottomControlType.time: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 播放时间
|
||||
Obx(() {
|
||||
@@ -354,9 +352,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
],
|
||||
),
|
||||
|
||||
/// 空白占位
|
||||
BottomControlType.space: const Spacer(),
|
||||
|
||||
/// 高能进度条
|
||||
BottomControlType.dmChart: Obx(() => plPlayerController.dmTrend.isEmpty
|
||||
? const SizedBox.shrink()
|
||||
@@ -622,7 +617,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
BottomControlType.fullscreen: SizedBox(
|
||||
width: widgetWidth,
|
||||
height: 30,
|
||||
child: Obx(() => ComBtn(
|
||||
child: Obx(
|
||||
() => ComBtn(
|
||||
icon: Icon(
|
||||
isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen,
|
||||
semanticLabel: isFullScreen ? '退出全屏' : '全屏',
|
||||
@@ -631,17 +627,19 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
),
|
||||
fuc: () =>
|
||||
plPlayerController.triggerFullScreen(status: !isFullScreen),
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
};
|
||||
final List<Widget> list = [];
|
||||
List<BottomControlType> userSpecifyItem = widget.bottomList ??
|
||||
[
|
||||
|
||||
List<BottomControlType> userSpecifyItemLeft = [
|
||||
BottomControlType.playOrPause,
|
||||
BottomControlType.time,
|
||||
if (anySeason) BottomControlType.pre,
|
||||
if (anySeason) BottomControlType.next,
|
||||
BottomControlType.space,
|
||||
];
|
||||
|
||||
List<BottomControlType> userSpecifyItemRight = [
|
||||
BottomControlType.dmChart,
|
||||
BottomControlType.superResolution,
|
||||
BottomControlType.viewPoints,
|
||||
@@ -651,19 +649,29 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
BottomControlType.speed,
|
||||
BottomControlType.fullscreen,
|
||||
];
|
||||
for (var i = 0; i < userSpecifyItem.length; i++) {
|
||||
if (userSpecifyItem[i] == BottomControlType.custom) {
|
||||
if (widget.customWidget != null && widget.customWidget is Widget) {
|
||||
list.add(widget.customWidget!);
|
||||
}
|
||||
if (widget.customWidgets != null && widget.customWidgets!.isNotEmpty) {
|
||||
list.addAll(widget.customWidgets!);
|
||||
}
|
||||
} else {
|
||||
list.add(videoProgressWidgets[userSpecifyItem[i]]!);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
||||
return Row(
|
||||
children: [
|
||||
...userSpecifyItemLeft.map((item) => videoProgressWidgets[item]!),
|
||||
Expanded(
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => FittedBox(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: constraints.maxWidth,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: userSpecifyItemRight
|
||||
.map((item) => videoProgressWidgets[item]!)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
PlPlayerController get plPlayerController => widget.plPlayerController;
|
||||
@@ -1101,7 +1109,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
|
||||
// 头部、底部控制条
|
||||
Obx(
|
||||
() => Column(
|
||||
() => Positioned.fill(
|
||||
child: Column(
|
||||
children: [
|
||||
if (widget.headerControl != null ||
|
||||
plPlayerController.headerControl != null)
|
||||
@@ -1125,12 +1134,13 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
child: widget.bottomControl ??
|
||||
BottomControl(
|
||||
controller: plPlayerController,
|
||||
buildBottomControl: buildBottomControl(),
|
||||
buildBottomControl: buildBottomControl,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// if (BuildConfig.isDebug)
|
||||
// FilledButton.tonal(
|
||||
|
||||
@@ -17,11 +17,11 @@ import 'package:PiliPlus/utils/feed_back.dart';
|
||||
import '../../../common/widgets/audio_video_progress_bar.dart';
|
||||
|
||||
class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
||||
final PlPlayerController? controller;
|
||||
final List<Widget>? buildBottomControl;
|
||||
final PlPlayerController controller;
|
||||
final Function buildBottomControl;
|
||||
const BottomControl({
|
||||
this.controller,
|
||||
this.buildBottomControl,
|
||||
required this.controller,
|
||||
required this.buildBottomControl,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@@ -37,13 +37,13 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Obx(
|
||||
() {
|
||||
final int value = controller!.sliderPositionSeconds.value;
|
||||
final int max = controller!.durationSeconds.value.inSeconds;
|
||||
final int buffer = controller!.bufferedSeconds.value;
|
||||
final int value = controller.sliderPositionSeconds.value;
|
||||
final int max = controller.durationSeconds.value.inSeconds;
|
||||
final int buffer = controller.bufferedSeconds.value;
|
||||
if (value > max || max <= 0) {
|
||||
return nil;
|
||||
}
|
||||
@@ -57,12 +57,12 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.bottomCenter,
|
||||
children: [
|
||||
if (controller?.dmTrend.isNotEmpty == true &&
|
||||
controller?.showDmChart.value == true)
|
||||
buildDmChart(context, controller!, 4.5),
|
||||
if (controller?.viewPointList.isNotEmpty == true &&
|
||||
controller?.showVP.value == true)
|
||||
buildViewPointWidget(controller!, 8.75),
|
||||
if (controller.dmTrend.isNotEmpty &&
|
||||
controller.showDmChart.value)
|
||||
buildDmChart(context, controller, 4.5),
|
||||
if (controller.viewPointList.isNotEmpty &&
|
||||
controller.showVP.value)
|
||||
buildViewPointWidget(controller, 8.75),
|
||||
ProgressBar(
|
||||
progress: Duration(seconds: value),
|
||||
buffered: Duration(seconds: buffer),
|
||||
@@ -76,16 +76,16 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
||||
thumbRadius: 7,
|
||||
onDragStart: (duration) {
|
||||
feedBack();
|
||||
controller!.onChangedSliderStart();
|
||||
controller.onChangedSliderStart();
|
||||
},
|
||||
onDragUpdate: (duration) {
|
||||
double newProgress =
|
||||
duration.timeStamp.inSeconds / max;
|
||||
if (controller!.showSeekPreview) {
|
||||
if (controller!.showPreview.value.not) {
|
||||
controller!.showPreview.value = true;
|
||||
if (controller.showSeekPreview) {
|
||||
if (controller.showPreview.value.not) {
|
||||
controller.showPreview.value = true;
|
||||
}
|
||||
controller!.previewDx.value =
|
||||
controller.previewDx.value =
|
||||
duration.localPosition.dx;
|
||||
}
|
||||
if ((newProgress - lastAnnouncedValue).abs() > 0.02) {
|
||||
@@ -98,17 +98,17 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
||||
lastAnnouncedValue = newProgress;
|
||||
});
|
||||
}
|
||||
controller!
|
||||
controller
|
||||
.onUpdatedSliderProgress(duration.timeStamp);
|
||||
},
|
||||
onSeek: (duration) {
|
||||
if (controller!.showSeekPreview) {
|
||||
controller!.showPreview.value = false;
|
||||
if (controller.showSeekPreview) {
|
||||
controller.showPreview.value = false;
|
||||
}
|
||||
controller!.onChangedSliderEnd();
|
||||
controller!
|
||||
controller.onChangedSliderEnd();
|
||||
controller
|
||||
.onChangedSlider(duration.inSeconds.toDouble());
|
||||
controller!.seekTo(
|
||||
controller.seekTo(
|
||||
Duration(seconds: duration.inSeconds),
|
||||
type: 'slider');
|
||||
SemanticsService.announce(
|
||||
@@ -116,7 +116,7 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
||||
TextDirection.ltr);
|
||||
},
|
||||
),
|
||||
if (controller?.segmentList.isNotEmpty == true)
|
||||
if (controller.segmentList.isNotEmpty)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
@@ -125,13 +125,13 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
||||
child: CustomPaint(
|
||||
size: Size(double.infinity, 3.5),
|
||||
painter: SegmentProgressBar(
|
||||
segmentColors: controller!.segmentList,
|
||||
segmentColors: controller.segmentList,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (controller?.viewPointList.isNotEmpty == true &&
|
||||
controller?.showVP.value == true)
|
||||
if (controller.viewPointList.isNotEmpty &&
|
||||
controller.showVP.value)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
@@ -140,17 +140,17 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
||||
child: CustomPaint(
|
||||
size: Size(double.infinity, 3.5),
|
||||
painter: SegmentProgressBar(
|
||||
segmentColors: controller!.viewPointList,
|
||||
segmentColors: controller.viewPointList,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (controller?.showSeekPreview == true)
|
||||
if (controller.showSeekPreview)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 18,
|
||||
child: buildSeekPreviewWidget(controller!),
|
||||
child: buildSeekPreviewWidget(controller),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -158,9 +158,7 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
Row(
|
||||
children: [...buildBottomControl!],
|
||||
),
|
||||
buildBottomControl(),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user