diff --git a/lib/common/widgets/progress_bar/audio_video_progress_bar.dart b/lib/common/widgets/progress_bar/audio_video_progress_bar.dart
index abdf56f12..faadf8182 100644
--- a/lib/common/widgets/progress_bar/audio_video_progress_bar.dart
+++ b/lib/common/widgets/progress_bar/audio_video_progress_bar.dart
@@ -365,12 +365,15 @@ class RenderProgressBar extends RenderBox {
_thumbGlowColor = thumbGlowColor,
_thumbGlowRadius = thumbGlowRadius,
_paintThumbGlow = thumbGlowRadius > thumbRadius,
- _thumbCanPaintOutsideBar = thumbCanPaintOutsideBar {
- _drag = _EagerHorizontalDragGestureRecognizer()
- ..onStart = _onDragStart
- ..onUpdate = _onDragUpdate
- ..onEnd = _onDragEnd
- ..onCancel = _finishDrag;
+ _thumbCanPaintOutsideBar = thumbCanPaintOutsideBar,
+ _hitTestSelf = onDragStart != null {
+ if (onDragStart != null) {
+ _drag = _EagerHorizontalDragGestureRecognizer()
+ ..onStart = _onDragStart
+ ..onUpdate = _onDragUpdate
+ ..onEnd = _onDragEnd
+ ..onCancel = _finishDrag;
+ }
if (!_userIsDraggingThumb) {
_progress = progress;
_thumbValue = _proportionOfTotal(_progress);
@@ -380,6 +383,7 @@ class RenderProgressBar extends RenderBox {
@override
void dispose() {
_drag?.dispose();
+ _drag = null;
super.dispose();
}
@@ -659,8 +663,9 @@ class RenderProgressBar extends RenderBox {
@override
double computeMaxIntrinsicHeight(double width) => _heightWhenNoLabels();
+ final bool _hitTestSelf;
@override
- bool hitTestSelf(Offset position) => true;
+ bool hitTestSelf(Offset position) => _hitTestSelf;
@override
void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
diff --git a/lib/common/widgets/progress_bar/segment_progress_bar.dart b/lib/common/widgets/progress_bar/segment_progress_bar.dart
index 84bfdc8d2..bf66e0ae8 100644
--- a/lib/common/widgets/progress_bar/segment_progress_bar.dart
+++ b/lib/common/widgets/progress_bar/segment_progress_bar.dart
@@ -1,23 +1,43 @@
-import 'package:flutter/material.dart';
+/*
+ * This file is part of PiliPlus
+ *
+ * PiliPlus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * PiliPlus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with PiliPlus. If not, see .
+ */
-class Segment {
+import 'package:flutter/foundation.dart' show listEquals, kDebugMode;
+import 'package:flutter/gestures.dart' show TapGestureRecognizer;
+import 'package:flutter/material.dart';
+import 'package:flutter/rendering.dart' show BoxHitTestEntry;
+
+sealed class BaseSegment {
final double start;
final double end;
- final Color color;
- final String? title;
- final String? url;
- final int? from;
- final int? to;
- Segment(
- this.start,
- this.end,
- this.color, [
- this.title,
- this.url,
- this.from,
- this.to,
- ]);
+ BaseSegment({
+ required this.start,
+ required this.end,
+ });
+}
+
+class Segment extends BaseSegment {
+ final Color color;
+
+ Segment({
+ required super.start,
+ required super.end,
+ required this.color,
+ });
@override
bool operator ==(Object other) {
@@ -25,9 +45,38 @@ class Segment {
return true;
}
if (other is Segment) {
+ return start == other.start && end == other.end && color == other.color;
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode => Object.hash(start, end, color);
+}
+
+class ViewPointSegment extends BaseSegment {
+ final String? title;
+ final String? url;
+ final int? from;
+ final int? to;
+
+ ViewPointSegment({
+ required super.start,
+ required super.end,
+ this.title,
+ this.url,
+ this.from,
+ this.to,
+ });
+
+ @override
+ bool operator ==(Object other) {
+ if (identical(this, other)) {
+ return true;
+ }
+ if (other is ViewPointSegment) {
return start == other.start &&
end == other.end &&
- color == other.color &&
title == other.title &&
url == other.url &&
from == other.from &&
@@ -37,116 +86,284 @@ class Segment {
}
@override
- int get hashCode => Object.hash(start, end, color, title, url, from, to);
+ int get hashCode => Object.hash(start, end, title, url, from, to);
}
-class SegmentProgressBar extends CustomPainter {
- final List segmentColors;
- double? _defHeight;
-
- SegmentProgressBar({
- required this.segmentColors,
+class SegmentProgressBar extends BaseSegmentProgressBar {
+ const SegmentProgressBar({
+ super.key,
+ super.height = 3.5,
+ required super.segments,
});
@override
- void paint(Canvas canvas, Size size) {
+ RenderObject createRenderObject(BuildContext context) {
+ return RenderProgressBar(
+ height: height,
+ segments: segments,
+ );
+ }
+}
+
+class RenderProgressBar extends BaseRenderProgressBar {
+ RenderProgressBar({
+ required super.height,
+ required super.segments,
+ });
+
+ @override
+ void paint(PaintingContext context, Offset offset) {
+ final size = this.size;
+ final canvas = context.canvas;
final paint = Paint()..style = PaintingStyle.fill;
- for (int i = 0; i < segmentColors.length; i++) {
- final item = segmentColors[i];
- paint.color = item.color;
+ for (final segment in segments) {
+ paint.color = segment.color;
+ final segmentStart = segment.start * size.width;
+ final segmentEnd = segment.end * size.width;
+
+ if (segmentEnd > segmentStart ||
+ (segmentEnd == segmentStart && segmentStart > 0)) {
+ canvas.drawRect(
+ Rect.fromLTWH(
+ segmentStart,
+ 0,
+ segmentEnd == segmentStart ? 2 : segmentEnd - segmentStart,
+ size.height,
+ ),
+ paint,
+ );
+ }
+ }
+ }
+}
+
+class ViewPointSegmentProgressBar
+ extends BaseSegmentProgressBar {
+ const ViewPointSegmentProgressBar({
+ super.key,
+ super.height = 3.5,
+ required super.segments,
+ this.onSeek,
+ });
+
+ final ValueSetter? onSeek;
+
+ @override
+ RenderObject createRenderObject(BuildContext context) {
+ return RenderViewPointProgressBar(
+ height: height,
+ segments: segments,
+ onSeek: onSeek,
+ );
+ }
+
+ @override
+ void updateRenderObject(
+ BuildContext context,
+ RenderViewPointProgressBar renderObject,
+ ) {
+ renderObject
+ ..height = height
+ ..segments = segments
+ ..onSeek = onSeek;
+ }
+}
+
+class RenderViewPointProgressBar
+ extends BaseRenderProgressBar {
+ RenderViewPointProgressBar({
+ required super.height,
+ required super.segments,
+ ValueSetter? onSeek,
+ }) : _onSeek = onSeek,
+ _hitTestSelf = onSeek != null {
+ if (onSeek != null) {
+ _tapGestureRecognizer = TapGestureRecognizer()..onTapUp = _onTapUp;
+ }
+ }
+
+ static const double barHeight = 15.0;
+
+ @override
+ Size computeDryLayout(BoxConstraints constraints) {
+ return constraints.constrain(Size(constraints.maxWidth, barHeight));
+ }
+
+ @override
+ void paint(PaintingContext context, Offset offset) {
+ final size = this.size;
+ final canvas = context.canvas;
+ final paint = Paint()..style = PaintingStyle.fill;
+
+ canvas.drawRect(
+ Rect.fromLTWH(0, 0, size.width, barHeight),
+ paint..color = Colors.grey[600]!.withValues(alpha: 0.45),
+ );
+
+ paint.color = Colors.black.withValues(alpha: 0.5);
+
+ for (int index = 0; index < segments.length; index++) {
+ final isFirst = index == 0;
+ final item = segments[index];
final segmentStart = item.start * size.width;
final segmentEnd = item.end * size.width;
if (segmentEnd > segmentStart ||
(segmentEnd == segmentStart && segmentStart > 0)) {
- if (item.title != null) {
- double fontSize = 10;
+ double fontSize = 10;
- _defHeight ??=
- (TextPainter(
- text: TextSpan(
- text: item.title,
- style: TextStyle(
- fontSize: fontSize,
- ),
- ),
- textDirection: TextDirection.ltr,
- )..layout()).height +
- 2;
-
- TextPainter getTextPainter() => TextPainter(
- text: TextSpan(
- text: item.title,
- style: TextStyle(
- color: Colors.white,
- fontSize: fontSize,
- height: 1,
- ),
+ TextPainter getTextPainter() => TextPainter(
+ text: TextSpan(
+ text: item.title,
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: fontSize,
+ height: 1,
),
- strutStyle: StrutStyle(leading: 0, height: 1, fontSize: fontSize),
- textDirection: TextDirection.ltr,
- )..layout();
+ ),
+ strutStyle: StrutStyle(leading: 0, height: 1, fontSize: fontSize),
+ textDirection: TextDirection.ltr,
+ )..layout();
- TextPainter textPainter = getTextPainter();
+ TextPainter textPainter = getTextPainter();
- late double prevStart;
- if (i != 0) {
- prevStart = segmentColors[i - 1].start * size.width;
- }
- double width = i == 0 ? segmentStart : segmentStart - prevStart;
-
- while (textPainter.width > width - 2 && fontSize >= 2) {
- fontSize -= 0.5;
- textPainter = getTextPainter();
- }
-
- if (i == 0) {
- canvas.drawRect(
- Rect.fromLTRB(
- 0,
- -_defHeight!,
- size.width,
- 0,
- ),
- Paint()..color = Colors.grey[600]!.withValues(alpha: 0.45),
- );
- }
-
- canvas.drawRect(
- Rect.fromLTWH(
- segmentStart,
- -_defHeight!,
- segmentEnd == segmentStart ? 2 : segmentEnd - segmentStart,
- size.height + _defHeight!,
- ),
- paint,
- );
-
- double textX = i == 0
- ? (segmentStart - textPainter.width) / 2
- : (segmentStart - prevStart - textPainter.width) / 2 +
- prevStart +
- 1;
- double textY = (-_defHeight! - textPainter.height) / 2;
- textPainter.paint(canvas, Offset(textX, textY));
- } else {
- canvas.drawRect(
- Rect.fromLTWH(
- segmentStart,
- 0,
- segmentEnd == segmentStart ? 2 : segmentEnd - segmentStart,
- size.height,
- ),
- paint,
- );
+ late double prevStart;
+ if (!isFirst) {
+ prevStart = segments[index - 1].start * size.width;
}
+ final width = isFirst ? segmentStart : segmentStart - prevStart;
+
+ while (textPainter.width > width - 2 && fontSize >= 2) {
+ fontSize -= 0.5;
+ textPainter.dispose();
+ textPainter = getTextPainter();
+ }
+
+ canvas.drawRect(
+ Rect.fromLTWH(
+ segmentStart,
+ 0,
+ segmentEnd == segmentStart ? 2 : segmentEnd - segmentStart,
+ barHeight + height,
+ ),
+ paint,
+ );
+
+ final textX = isFirst
+ ? (segmentStart - textPainter.width) / 2
+ : (segmentStart - prevStart - textPainter.width) / 2 +
+ prevStart +
+ 1;
+ final textY = (barHeight - textPainter.height) / 2;
+ textPainter.paint(canvas, Offset(textX, textY));
}
}
}
+ ValueSetter? _onSeek;
+ set onSeek(ValueSetter? value) {
+ if (_onSeek == value) {
+ return;
+ }
+ _onSeek = value;
+ }
+
+ TapGestureRecognizer? _tapGestureRecognizer;
+
@override
- bool shouldRepaint(SegmentProgressBar oldDelegate) {
- return segmentColors != oldDelegate.segmentColors;
+ void dispose() {
+ _onSeek = null;
+ _tapGestureRecognizer
+ ?..onTapUp = null
+ ..dispose();
+ _tapGestureRecognizer = null;
+ super.dispose();
+ }
+
+ final bool _hitTestSelf;
+ @override
+ bool hitTestSelf(Offset position) => _hitTestSelf;
+
+ @override
+ void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
+ if (event is PointerDownEvent) {
+ _tapGestureRecognizer?.addPointer(event);
+ }
+ }
+
+ void _onTapUp(TapUpDetails details) {
+ try {
+ final seg = details.localPosition.dx / size.width;
+ final item = _segments
+ .where((item) => item.start >= seg)
+ .reduce((a, b) => a.start < b.start ? a : b);
+ if (item.from case final from?) {
+ _onSeek?.call(Duration(seconds: from));
+ }
+ // if (kDebugMode) debugPrint('${item.title},,${item.from}');
+ } catch (e) {
+ if (kDebugMode) rethrow;
+ }
}
}
+
+abstract class BaseSegmentProgressBar
+ extends LeafRenderObjectWidget {
+ const BaseSegmentProgressBar({
+ super.key,
+ this.height = 3.5,
+ required this.segments,
+ });
+
+ final double height;
+ final List segments;
+
+ @override
+ void updateRenderObject(
+ BuildContext context,
+ BaseRenderProgressBar renderObject,
+ ) {
+ renderObject
+ ..height = height
+ ..segments = segments;
+ }
+}
+
+class BaseRenderProgressBar extends RenderBox {
+ BaseRenderProgressBar({
+ required double height,
+ required List segments,
+ ValueSetter? onSeek,
+ }) : _height = height,
+ _segments = segments;
+
+ double _height;
+ double get height => _height;
+ set height(double value) {
+ if (_height == value) return;
+ _height = value;
+ markNeedsLayout();
+ }
+
+ List _segments;
+ List get segments => _segments;
+ set segments(List value) {
+ if (listEquals(_segments, value)) return;
+ _segments = value;
+ markNeedsPaint();
+ }
+
+ @override
+ void performLayout() {
+ size = computeDryLayout(constraints);
+ }
+
+ @override
+ Size computeDryLayout(BoxConstraints constraints) {
+ return constraints.constrain(Size(constraints.maxWidth, height));
+ }
+
+ @override
+ bool get isRepaintBoundary => true;
+}
diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart
index 3f33cdff8..fd3f66557 100644
--- a/lib/pages/video/controller.dart
+++ b/lib/pages/video/controller.dart
@@ -838,7 +838,11 @@ class VideoDetailController extends GetxController
segmentList.map((e) {
double start = (e.segment.first / duration).clamp(0.0, 1.0);
double end = (e.segment.second / duration).clamp(0.0, 1.0);
- return Segment(start, end, _getColor(e.segmentType));
+ return Segment(
+ start: start,
+ end: end,
+ color: _getColor(e.segmentType),
+ );
}),
);
@@ -1453,7 +1457,7 @@ class VideoDetailController extends GetxController
late final Map vttSubtitles = {};
late final RxInt vttSubtitlesIndex = (-1).obs;
late final RxBool showVP = true.obs;
- late final RxList viewPointList = [].obs;
+ late final RxList viewPointList = [].obs;
// 设定字幕轨道
Future setSubtitle(int index) async {
@@ -1575,14 +1579,13 @@ class VideoDetailController extends GetxController
0.0,
1.0,
);
- return Segment(
- start,
- start,
- Colors.black.withValues(alpha: 0.5),
- item.content,
- item.imgUrl,
- item.from,
- item.to,
+ return ViewPointSegment(
+ start: start,
+ end: start,
+ title: item.content,
+ url: item.imgUrl,
+ from: item.from,
+ to: item.to,
);
}).toList();
} catch (_) {}
diff --git a/lib/pages/video/view_point/view.dart b/lib/pages/video/view_point/view.dart
index d669f85ee..d5d65fc5e 100644
--- a/lib/pages/video/view_point/view.dart
+++ b/lib/pages/video/view_point/view.dart
@@ -100,7 +100,7 @@ class _ViewPointsPageState extends State
),
itemCount: videoDetailController.viewPointList.length,
itemBuilder: (context, index) {
- Segment segment = videoDetailController.viewPointList[index];
+ final segment = videoDetailController.viewPointList[index];
if (currentIndex == -1 && segment.from != null && segment.to != null) {
final positionSeconds =
videoDetailController.plPlayerController.positionSeconds.value;
@@ -122,7 +122,7 @@ class _ViewPointsPageState extends State
return child;
}
- Widget _buildItem(ThemeData theme, Segment segment, bool isCurr) {
+ Widget _buildItem(ThemeData theme, ViewPointSegment segment, bool isCurr) {
final theme = Theme.of(context);
return Material(
type: MaterialType.transparency,
diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart
index a5b1900ad..b7fe8ff8d 100644
--- a/lib/plugin/pl_player/view.dart
+++ b/lib/plugin/pl_player/view.dart
@@ -1740,106 +1740,69 @@ class _PLVideoPlayerState extends State
right: 0,
child: Obx(
() {
- if (plPlayerController.showControls.value) {
- return const SizedBox.shrink();
- }
-
- switch (plPlayerController.progressType) {
- case BtmProgressBehavior.onlyShowFullScreen:
- if (!isFullScreen) {
- return const SizedBox.shrink();
- }
- case BtmProgressBehavior.onlyHideFullScreen:
- if (isFullScreen) {
- return const SizedBox.shrink();
- }
- default:
- }
-
- return Stack(
- clipBehavior: Clip.none,
- alignment: Alignment.bottomCenter,
- children: [
- IgnorePointer(
- child: RepaintBoundary.wrap(
- Obx(() {
- final int value =
- plPlayerController.sliderPositionSeconds.value;
- final int max = plPlayerController
- .durationSeconds
- .value
- .inSeconds;
- final int buffer =
- plPlayerController.bufferedSeconds.value;
- return 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: 2.5,
- );
- }),
- 0,
- ),
- ),
- if (plPlayerController.enableBlock &&
- videoDetailController.segmentProgressList.isNotEmpty)
- Positioned(
- left: 0,
- right: 0,
- bottom: 0.75,
- child: IgnorePointer(
- child: RepaintBoundary.wrap(
- CustomPaint(
- size: const Size(double.infinity, 3.5),
- painter: SegmentProgressBar(
- segmentColors:
- videoDetailController.segmentProgressList,
- ),
- ),
- 1,
+ final offstage = switch (plPlayerController.progressType) {
+ BtmProgressBehavior.onlyShowFullScreen => !isFullScreen,
+ BtmProgressBehavior.onlyHideFullScreen => isFullScreen,
+ _ => plPlayerController.showControls.value,
+ };
+ return Offstage(
+ offstage: offstage,
+ child: Stack(
+ clipBehavior: Clip.none,
+ alignment: Alignment.bottomCenter,
+ children: [
+ Obx(() {
+ final int value =
+ plPlayerController.sliderPositionSeconds.value;
+ final int max =
+ plPlayerController.durationSeconds.value.inSeconds;
+ final int buffer =
+ plPlayerController.bufferedSeconds.value;
+ return 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: 2.5,
+ );
+ }),
+ if (plPlayerController.enableBlock &&
+ videoDetailController.segmentProgressList.isNotEmpty)
+ Positioned(
+ left: 0,
+ right: 0,
+ bottom: 0.75,
+ child: SegmentProgressBar(
+ segments: videoDetailController.segmentProgressList,
),
),
- ),
- if (plPlayerController.showViewPoints &&
- videoDetailController.viewPointList.isNotEmpty &&
- videoDetailController.showVP.value) ...[
- Positioned(
- left: 0,
- right: 0,
- bottom: 0.75,
- child: IgnorePointer(
- child: RepaintBoundary.wrap(
- CustomPaint(
- size: const Size(double.infinity, 3.5),
- painter: SegmentProgressBar(
- segmentColors:
- videoDetailController.viewPointList,
- ),
- ),
- 2,
+ if (plPlayerController.showViewPoints &&
+ videoDetailController.viewPointList.isNotEmpty &&
+ videoDetailController.showVP.value)
+ Padding(
+ padding: const .only(bottom: 4.25),
+ child: ViewPointSegmentProgressBar(
+ segments: videoDetailController.viewPointList,
+ onSeek: PlatformUtils.isMobile
+ ? (position) => plPlayerController.seekTo(
+ position,
+ isSeek: false,
+ )
+ : null,
),
),
- ),
- if (PlatformUtils.isMobile)
- buildViewPointWidget(
- videoDetailController,
- plPlayerController,
- 4.25,
- maxWidth,
- ),
+ if (plPlayerController.showDmChart &&
+ videoDetailController.showDmTrendChart.value)
+ if (videoDetailController.dmTrend.value?.dataOrNull
+ case final list?)
+ buildDmChart(primary, list, videoDetailController),
],
- if (plPlayerController.showDmChart &&
- videoDetailController.showDmTrendChart.value)
- if (videoDetailController.dmTrend.value?.dataOrNull
- case final list?)
- buildDmChart(primary, list, videoDetailController),
- ],
+ ),
);
},
),
@@ -2325,7 +2288,7 @@ class _PLVideoPlayerState extends State
// fullscreen
if (dx > maxWidth) {
_removeDmAction();
- return const Positioned(left: 0, top: 0, child: SizedBox.shrink());
+ return const SizedBox.shrink();
}
final seekOffset = _getValidOffset(item.content.text);
@@ -2346,7 +2309,7 @@ class _PLVideoPlayerState extends State
if (right > (maxWidth - item.xPosition)) {
_removeDmAction();
- return const Positioned(left: 0, top: 0, child: SizedBox.shrink());
+ return const SizedBox.shrink();
}
final extra = item.content.extra;
diff --git a/lib/plugin/pl_player/widgets/bottom_control.dart b/lib/plugin/pl_player/widgets/bottom_control.dart
index f5b0fbc5a..f58851767 100644
--- a/lib/plugin/pl_player/widgets/bottom_control.dart
+++ b/lib/plugin/pl_player/widgets/bottom_control.dart
@@ -22,9 +22,31 @@ class BottomControl extends StatelessWidget {
final double maxWidth;
final bool isFullScreen;
final PlPlayerController controller;
- final Widget Function() buildBottomControl;
+ final ValueGetter buildBottomControl;
final VideoDetailController videoDetailController;
+ void onDragStart(ThumbDragDetails duration) {
+ feedBack();
+ controller.onChangedSliderStart(duration.timeStamp);
+ }
+
+ void onDragUpdate(ThumbDragDetails duration, int max) {
+ if (!controller.isFileSource && controller.showSeekPreview) {
+ controller.updatePreviewIndex(duration.timeStamp.inSeconds);
+ }
+ 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);
+ }
+
@override
Widget build(BuildContext context) {
final colorScheme = ColorScheme.of(context);
@@ -33,27 +55,6 @@ class BottomControl extends StatelessWidget {
: colorScheme.primary;
final thumbGlowColor = primary.withAlpha(80);
final bufferedBarColor = primary.withValues(alpha: 0.4);
- void onDragStart(ThumbDragDetails duration) {
- feedBack();
- controller.onChangedSliderStart(duration.timeStamp);
- }
-
- void onDragUpdate(ThumbDragDetails duration, int max) {
- if (!controller.isFileSource && controller.showSeekPreview) {
- controller.updatePreviewIndex(duration.timeStamp.inSeconds);
- }
- 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);
- }
Widget progressBar() {
final child = Obx(() {
@@ -93,63 +94,42 @@ class BottomControl extends StatelessWidget {
Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 7),
child: Obx(
- () => Stack(
- clipBehavior: Clip.none,
- alignment: Alignment.bottomCenter,
- children: [
- progressBar(),
- if (controller.enableBlock &&
- 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,
- ),
- ),
+ () => Offstage(
+ offstage: !controller.showControls.value,
+ child: Stack(
+ clipBehavior: Clip.none,
+ alignment: Alignment.bottomCenter,
+ children: [
+ progressBar(),
+ if (controller.enableBlock &&
+ videoDetailController.segmentProgressList.isNotEmpty)
+ Positioned(
+ left: 0,
+ right: 0,
+ bottom: 5.25,
+ child: SegmentProgressBar(
+ segments: 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 (controller.showViewPoints &&
+ videoDetailController.viewPointList.isNotEmpty &&
+ videoDetailController.showVP.value)
+ Padding(
+ padding: const .only(bottom: 8.75),
+ child: ViewPointSegmentProgressBar(
+ segments: videoDetailController.viewPointList,
+ onSeek: PlatformUtils.isDesktop
+ ? (position) =>
+ controller.seekTo(position, isSeek: false)
+ : null,
),
),
- ),
- if (!PlatformUtils.isMobile)
- buildViewPointWidget(
- videoDetailController,
- controller,
- 8.75,
- maxWidth - 40,
- ),
+ if (videoDetailController.showDmTrendChart.value)
+ if (videoDetailController.dmTrend.value?.dataOrNull
+ case final list?)
+ buildDmChart(primary, list, videoDetailController, 4.5),
],
- if (videoDetailController.showDmTrendChart.value)
- if (videoDetailController.dmTrend.value?.dataOrNull
- case final list?)
- buildDmChart(primary, list, videoDetailController, 4.5),
- ],
+ ),
),
),
),