Files
PiliPlus/lib/plugin/pl_player/widgets/bottom_control.dart
bggRGjQaUbCoE e4a960ecf9 opt ui
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-10-12 16:13:23 +08:00

193 lines
7.0 KiB
Dart

import 'dart:async';
import 'package:PiliPlus/common/widgets/progress_bar/audio_video_progress_bar.dart';
import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart';
import 'package:PiliPlus/pages/video/controller.dart';
import 'package:PiliPlus/plugin/pl_player/controller.dart';
import 'package:PiliPlus/plugin/pl_player/view.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/feed_back.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:get/get.dart';
class BottomControl extends StatelessWidget {
const BottomControl({
super.key,
required this.maxWidth,
required this.isFullScreen,
required this.controller,
required this.buildBottomControl,
required this.videoDetailController,
});
final double maxWidth;
final bool isFullScreen;
final PlPlayerController controller;
final Widget Function() buildBottomControl;
final VideoDetailController videoDetailController;
@override
Widget build(BuildContext context) {
final colorScheme = ColorScheme.of(context);
final primary = colorScheme.isLight
? colorScheme.inversePrimary
: colorScheme.primary;
final thumbGlowColor = primary.withAlpha(80);
final bufferedBarColor = primary.withValues(alpha: 0.4);
//阅读器限制
Timer? accessibilityDebounce;
double lastAnnouncedValue = -1;
void onDragStart(ThumbDragDetails duration) {
feedBack();
controller.onChangedSliderStart(duration.timeStamp);
}
void onDragUpdate(ThumbDragDetails duration, int max) {
if (controller.showSeekPreview) {
controller.updatePreviewIndex(
duration.timeStamp.inSeconds,
);
}
double newProgress = duration.timeStamp.inSeconds / max;
if ((newProgress - lastAnnouncedValue).abs() > 0.02) {
accessibilityDebounce?.cancel();
accessibilityDebounce = Timer(
const Duration(milliseconds: 200),
() {
SemanticsService.announce(
"${(newProgress * 100).round()}%",
TextDirection.ltr,
);
lastAnnouncedValue = newProgress;
},
);
}
controller.onUpdatedSliderProgress(
duration.timeStamp,
);
}
void onSeek(Duration duration, int max) {
if (controller.showSeekPreview) {
controller.showPreview.value = false;
}
controller
..onChangedSliderEnd()
..onChangedSlider(duration.inSeconds.toDouble())
..seekTo(
Duration(seconds: duration.inSeconds),
isSeek: false,
);
SemanticsService.announce(
"${(duration.inSeconds / max * 100).round()}%",
TextDirection.ltr,
);
}
return Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 12),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 7),
child: Obx(
() => Stack(
clipBehavior: Clip.none,
alignment: Alignment.bottomCenter,
children: [
Obx(() {
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 const SizedBox.shrink();
}
final child = ProgressBar(
progress: Duration(seconds: value),
buffered: Duration(seconds: buffer),
total: Duration(seconds: max),
progressBarColor: primary,
baseBarColor: const Color(0x33FFFFFF),
bufferedBarColor: bufferedBarColor,
thumbColor: primary,
thumbGlowColor: thumbGlowColor,
barHeight: 3.5,
thumbRadius: 7,
thumbGlowRadius: 25,
onDragStart: onDragStart,
onDragUpdate: (e) => onDragUpdate(e, max),
onSeek: (e) => onSeek(e, max),
);
if (Utils.isDesktop) {
return MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
);
}
return child;
}),
if (controller.enableSponsorBlock &&
videoDetailController.segmentProgressList.isNotEmpty)
Positioned(
left: 0,
right: 0,
bottom: 5.25,
child: IgnorePointer(
child: RepaintBoundary(
child: CustomPaint(
key: const Key('segmentList'),
size: const Size(double.infinity, 3.5),
painter: SegmentProgressBar(
segmentColors:
videoDetailController.segmentProgressList,
),
),
),
),
),
if (controller.showViewPoints &&
videoDetailController.viewPointList.isNotEmpty &&
videoDetailController.showVP.value) ...[
Positioned(
left: 0,
right: 0,
bottom: 5.25,
child: IgnorePointer(
child: RepaintBoundary(
child: CustomPaint(
key: const Key('viewPointList'),
size: const Size(double.infinity, 3.5),
painter: SegmentProgressBar(
segmentColors:
videoDetailController.viewPointList,
),
),
),
),
),
if (!Utils.isMobile)
buildViewPointWidget(
videoDetailController,
controller,
8.75,
maxWidth - 40,
),
],
if (videoDetailController.showDmTreandChart.value)
if (videoDetailController.dmTrend.value?.dataOrNull
case final list?)
buildDmChart(primary, list, videoDetailController, 4.5),
],
),
),
),
buildBottomControl(),
],
),
);
}
}