opt player

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-08-10 13:03:49 +08:00
parent b788794f4b
commit dbde90459b
4 changed files with 1263 additions and 1230 deletions

View File

@@ -14,7 +14,6 @@ import 'package:PiliPlus/plugin/pl_player/models/play_status.dart';
import 'package:PiliPlus/plugin/pl_player/utils/fullscreen.dart';
import 'package:PiliPlus/plugin/pl_player/view.dart';
import 'package:PiliPlus/services/service_locator.dart';
import 'package:PiliPlus/utils/context_ext.dart';
import 'package:PiliPlus/utils/duration_util.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/page_utils.dart';
@@ -113,20 +112,39 @@ class _LiveRoomPageState extends State<LiveRoomPage>
}
}
late double maxWidth;
late double maxHeight;
late EdgeInsets padding;
@override
Widget build(BuildContext context) {
final isPortrait = context.isPortrait;
padding = MediaQuery.paddingOf(context);
return LayoutBuilder(
builder: (context, constraints) {
maxWidth = constraints.maxWidth;
maxHeight = constraints.maxHeight;
final isPortrait = maxHeight >= maxWidth;
if (Platform.isAndroid) {
return Floating().isPipMode
? videoPlayerPanel(isFullScreen, isPipMode: true)
? videoPlayerPanel(
isFullScreen,
width: maxWidth,
height: maxHeight,
isPipMode: true,
)
: childWhenDisabled(isPortrait);
} else {
return childWhenDisabled(isPortrait);
}
},
);
}
Widget videoPlayerPanel(
bool isFullScreen, {
required double width,
required double height,
bool isPipMode = false,
Color? fill,
Alignment? alignment,
@@ -144,6 +162,8 @@ class _LiveRoomPageState extends State<LiveRoomPage>
final roomInfoH5 = _liveRoomController.roomInfoH5.value;
return PLVideoPlayer(
key: playerKey,
maxWidth: width,
maxHeight: height,
fill: fill,
alignment: alignment,
plPlayerController: plPlayerController,
@@ -212,11 +232,10 @@ class _LiveRoomPageState extends State<LiveRoomPage>
?.appBackground;
Widget child;
if (appBackground?.isNotEmpty == true) {
final size = Get.size;
child = CachedNetworkImage(
fit: BoxFit.cover,
width: size.width,
height: size.height,
width: maxWidth,
height: maxHeight,
imageUrl: appBackground!.http2https,
);
} else {
@@ -254,14 +273,18 @@ class _LiveRoomPageState extends State<LiveRoomPage>
Widget get _buildPH {
final isFullScreen = this.isFullScreen;
final size = Get.size;
final height = isFullScreen ? maxHeight : maxWidth * 9 / 16;
return Column(
children: [
if (!isFullScreen) _buildAppBar,
SizedBox(
width: size.width,
height: isFullScreen ? size.height : size.width * 9 / 16,
child: videoPlayerPanel(isFullScreen),
width: maxWidth,
height: height,
child: videoPlayerPanel(
isFullScreen,
width: maxWidth,
height: height,
),
),
..._buildBottomWidget,
],
@@ -270,11 +293,17 @@ class _LiveRoomPageState extends State<LiveRoomPage>
Widget get _buildPP {
final isFullScreen = this.isFullScreen;
final bottomHeight = 85.0 + padding.bottom;
final height = isFullScreen
? maxHeight
: maxHeight - padding.top - kToolbarHeight - bottomHeight;
Widget child = Stack(
clipBehavior: Clip.none,
children: [
Positioned.fill(
child: videoPlayerPanel(
width: maxWidth,
height: height,
isFullScreen,
alignment: isFullScreen ? null : Alignment.topCenter,
needDm: isFullScreen,
@@ -288,7 +317,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
maintainState: true,
visible: !isFullScreen,
child: SizedBox(
height: Get.height * 0.32,
height: maxHeight * 0.32,
child: _buildChatWidget(true),
),
),
@@ -302,7 +331,10 @@ class _LiveRoomPageState extends State<LiveRoomPage>
children: [
_buildAppBar,
Expanded(child: child),
_buildInputWidget,
SizedBox(
height: bottomHeight,
child: _buildInputWidget,
),
],
);
}
@@ -471,23 +503,23 @@ class _LiveRoomPageState extends State<LiveRoomPage>
Widget get _buildBodyH {
double videoWidth =
clampDouble(context.height / context.width * 1.08, 0.58, 0.75) *
context.width;
clampDouble(maxHeight / maxWidth * 1.08, 0.58, 0.75) * maxWidth;
return Obx(
() {
final isFullScreen = this.isFullScreen;
final size = Get.size;
final width = isFullScreen ? maxWidth : videoWidth;
final height = isFullScreen ? maxHeight : maxWidth * 9 / 16;
Widget child = Row(
children: [
Container(
margin: EdgeInsets.only(
bottom: MediaQuery.paddingOf(context).bottom,
),
width: isFullScreen ? size.width : videoWidth,
height: isFullScreen ? size.height : size.width * 9 / 16,
margin: EdgeInsets.only(bottom: padding.bottom),
width: width,
height: height,
child: videoPlayerPanel(
isFullScreen,
fill: Colors.transparent,
width: width,
height: height,
),
),
Expanded(
@@ -531,7 +563,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
top: 5,
left: 10,
right: 10,
bottom: 15 + MediaQuery.paddingOf(context).bottom,
bottom: 15 + padding.bottom,
),
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(

View File

@@ -665,8 +665,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
showStatusBar();
}
}
return SizedBox(
height: !isPortrait || isFullScreen
final height = !isPortrait || isFullScreen
? maxHeight -
(!isPortrait || removeSafeArea
? 0
@@ -674,16 +673,13 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
: videoDetailController.isExpanding ||
videoDetailController.isCollapsing
? animHeight
: videoDetailController.videoHeight,
: videoDetailController.videoHeight;
return SizedBox(
width: maxWidth,
height: height,
child: videoPlayer(
maxWidth,
!isPortrait || isFullScreen
? maxHeight
: videoDetailController.isExpanding ||
videoDetailController.isCollapsing
? animHeight
: videoDetailController.videoHeight,
width: maxWidth,
height: height,
),
);
},
@@ -964,14 +960,18 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
if (videoDetailController.isVertical.value && enableVerticalExpand) {
final double videoHeight =
maxHeight - (removeSafeArea ? 0 : padding.vertical);
final double videoWidth = videoHeight * 9 / 16;
final double width = videoHeight * 9 / 16;
final videoWidth = isFullScreen ? maxWidth : width;
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: videoWidth,
height: videoHeight,
width: isFullScreen ? maxWidth : videoWidth,
child: videoPlayer(videoWidth, videoHeight),
child: videoPlayer(
width: videoWidth,
height: videoHeight,
),
),
Expanded(
child: Scaffold(
@@ -986,7 +986,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
controller: videoDetailController.tabCtr,
children: [
videoIntro(
width: maxWidth - videoWidth,
width: maxWidth - width,
height: maxHeight,
),
if (videoDetailController.showReply)
@@ -1002,16 +1002,20 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
],
);
}
final double videoHeight = maxHeight / 2.5;
final shouldShowSeasonPanel = _shouldShowSeasonPanel;
final double height = maxHeight / 2.5;
final videoHeight = isFullScreen
? maxHeight - (removeSafeArea ? 0 : padding.vertical)
: height;
return Column(
children: [
SizedBox(
width: maxWidth,
height: isFullScreen
? maxHeight - (removeSafeArea ? 0 : padding.vertical)
: videoHeight,
child: videoPlayer(maxWidth, videoHeight),
height: videoHeight,
child: videoPlayer(
width: maxWidth,
height: videoHeight,
),
),
Expanded(
child: Scaffold(
@@ -1032,7 +1036,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
if (shouldShowSeasonPanel) flex++;
return maxWidth / flex;
}(),
height: maxHeight - videoHeight,
height: maxHeight - height,
),
),
if (videoDetailController.showReply)
@@ -1056,20 +1060,24 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
if (videoDetailController.isVertical.value && enableVerticalExpand) {
final double videoHeight =
maxHeight - (removeSafeArea ? 0 : padding.top);
final double videoWidth = videoHeight * 9 / 16;
final double width = videoHeight * 9 / 16;
final videoWidth = isFullScreen ? maxWidth : width;
return Row(
children: [
if (!isFullScreen)
Expanded(
child: videoIntro(
width: (maxWidth - videoWidth) / 2,
width: (maxWidth - width) / 2,
height: maxHeight,
),
),
SizedBox(
width: videoWidth,
height: videoHeight,
width: isFullScreen ? maxWidth : videoWidth,
child: videoPlayer(videoWidth, videoHeight),
child: videoPlayer(
width: videoWidth,
height: videoHeight,
),
),
Expanded(
child: Scaffold(
@@ -1096,12 +1104,13 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
],
);
}
double videoWidth =
double width =
clampDouble(maxHeight / maxWidth * 1.08, 0.5, 0.7) * maxWidth;
if (maxWidth >= 560) {
videoWidth = min(videoWidth, maxWidth - 280);
width = min(width, maxWidth - 280);
}
final double videoHeight = videoWidth * 9 / 16;
final videoWidth = isFullScreen ? maxWidth : width;
final double videoHeight = isFullScreen ? maxHeight : width * 9 / 16;
final introHeight =
maxHeight - videoHeight - (removeSafeArea ? 0 : padding.top);
return Row(
@@ -1109,17 +1118,20 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
Column(
children: [
SizedBox(
width: isFullScreen ? maxWidth : videoWidth,
height: isFullScreen ? maxHeight : videoHeight,
child: videoPlayer(videoWidth, videoHeight),
width: videoWidth,
height: videoHeight,
child: videoPlayer(
width: videoWidth,
height: videoHeight,
),
),
Offstage(
offstage: isFullScreen,
child: SizedBox(
width: videoWidth,
width: width,
height: introHeight,
child: videoIntro(
width: videoWidth,
width: width,
height: introHeight,
needRelated: false,
needCtr: false,
@@ -1132,9 +1144,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
offstage: isFullScreen,
child: SizedBox(
width:
maxWidth -
videoWidth -
(removeSafeArea ? 0 : padding.horizontal),
maxWidth - width - (removeSafeArea ? 0 : padding.horizontal),
height: maxHeight - (removeSafeArea ? 0 : padding.top),
child: Scaffold(
key: videoDetailController.childKey,
@@ -1372,7 +1382,11 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
return const SizedBox.shrink();
});
Widget plPlayer([bool isPipMode = false]) => Obx(
Widget plPlayer({
required double width,
required double height,
bool isPipMode = false,
}) => Obx(
key: videoPlayerKey,
() =>
videoDetailController.videoState.value is! Success ||
@@ -1381,6 +1395,8 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
? const SizedBox.shrink()
: PLVideoPlayer(
key: playerKey,
maxWidth: width,
maxHeight: height,
plPlayerController: plPlayerController!,
videoDetailController: videoDetailController,
introController: videoDetailController.isUgc
@@ -1410,7 +1426,9 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
Widget autoChoose(Widget childWhenDisabled) {
if (Platform.isAndroid) {
return Floating().isPipMode ? plPlayer(true) : childWhenDisabled;
return Floating().isPipMode
? plPlayer(width: maxWidth, height: maxHeight, isPipMode: true)
: childWhenDisabled;
}
return childWhenDisabled;
}
@@ -1428,7 +1446,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
builder: (context, constraints) {
maxWidth = constraints.maxWidth;
maxHeight = constraints.maxHeight;
isPortrait = maxHeight > maxWidth;
isPortrait = maxHeight >= maxWidth;
if (!videoDetailController.horizontalScreen) {
return autoChoose(childWhenDisabled);
@@ -1599,7 +1617,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
);
}
Widget videoPlayer(double videoWidth, double videoHeight) {
Widget videoPlayer({required double width, required double height}) {
final isFullScreen = this.isFullScreen;
return PopScope(
canPop:
@@ -1611,7 +1629,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
children: [
const Positioned.fill(child: ColoredBox(color: Colors.black)),
if (isShowing) plPlayer(),
if (isShowing) plPlayer(width: width, height: height),
Obx(() {
if (!videoDetailController.autoPlay.value) {
@@ -1621,12 +1639,12 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
child: Obx(
() => CachedNetworkImage(
imageUrl: videoDetailController.cover.value.http2https,
width: videoWidth,
height: videoHeight,
width: width,
height: height,
fit: BoxFit.cover,
fadeOutDuration: const Duration(milliseconds: 120),
fadeInDuration: const Duration(milliseconds: 120),
memCacheWidth: videoWidth.cacheSize(context),
memCacheWidth: width.cacheSize(context),
placeholder: (context, url) => Center(
child: Image.asset('assets/images/loading.png'),
),

View File

@@ -46,6 +46,8 @@ import 'package:screen_brightness/screen_brightness.dart';
class PLVideoPlayer extends StatefulWidget {
const PLVideoPlayer({
required this.maxWidth,
required this.maxHeight,
required this.plPlayerController,
this.videoDetailController,
this.introController,
@@ -61,6 +63,8 @@ class PLVideoPlayer extends StatefulWidget {
super.key,
});
final double maxWidth;
final double maxHeight;
final PlPlayerController plPlayerController;
final VideoDetailController? videoDetailController;
final CommonIntroController? introController;
@@ -244,7 +248,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
}
// 动态构建底部控制条
Widget buildBottomControl() {
Widget buildBottomControl(double maxWidth) {
final videoDetail = introController.videoDetail.value;
final isSeason = videoDetail.ugcSeason != null;
final isPart = videoDetail.pages != null && videoDetail.pages!.length > 1;
@@ -659,12 +663,9 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
children: [
...userSpecifyItemLeft.map(progressWidget),
Expanded(
child: LayoutBuilder(
builder: (context, constraints) => FittedBox(
child: FittedBox(
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: constraints.maxWidth,
),
constraints: BoxConstraints(minWidth: maxWidth),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: userSpecifyItemRight.map(progressWidget).toList(),
@@ -672,7 +673,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
),
),
),
),
],
);
}
@@ -691,10 +691,10 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
color: Colors.white,
fontSize: 12,
);
return LayoutBuilder(
builder: (context, constraints) {
final maxWidth = constraints.maxWidth;
final maxHeight = constraints.maxHeight;
final maxWidth = widget.maxWidth;
final maxHeight = widget.maxHeight;
return Stack(
fit: StackFit.passthrough,
key: _playerKey,
@@ -739,8 +739,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
if (interacting || _initialFocalPoint == Offset.zero) return;
Offset cumulativeDelta =
details.localFocalPoint - _initialFocalPoint;
if (details.pointerCount == 2 &&
cumulativeDelta.distance < 1.5) {
if (details.pointerCount == 2 && cumulativeDelta.distance < 1.5) {
interacting = true;
_gestureType = null;
return;
@@ -751,8 +750,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
if (_gestureType == null) {
if (cumulativeDelta.distance < 1) return;
if (cumulativeDelta.dx.abs() >
3 * cumulativeDelta.dy.abs()) {
if (cumulativeDelta.dx.abs() > 3 * cumulativeDelta.dy.abs()) {
_gestureType = GestureType.horizontal;
} else if (cumulativeDelta.dy.abs() >
3 * cumulativeDelta.dx.abs()) {
@@ -910,8 +908,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
'setVolume',
const Duration(milliseconds: 20),
() {
final double volume =
_volumeValue.value - delta.dy / level;
final double volume = _volumeValue.value - delta.dy / level;
final double result = volume.clamp(0.0, 1.0);
setVolume(result);
},
@@ -1087,9 +1084,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
translation: const Offset(0.0, 0.3), // 上下偏移量(负数向上偏移)
child: AnimatedOpacity(
curve: Curves.easeInOut,
opacity: plPlayerController.longPressStatus.value
? 1.0
: 0.0,
opacity: plPlayerController.longPressStatus.value ? 1.0 : 0.0,
duration: const Duration(milliseconds: 150),
child: Container(
alignment: Alignment.center,
@@ -1126,9 +1121,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
child: Obx(
() => AnimatedOpacity(
curve: Curves.easeInOut,
opacity: plPlayerController.isSliderMoving.value
? 1.0
: 0.0,
opacity: plPlayerController.isSliderMoving.value ? 1.0 : 0.0,
duration: const Duration(milliseconds: 150),
child: IntrinsicWidth(
child: Container(
@@ -1302,6 +1295,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
BottomControl(
controller: plPlayerController,
buildBottomControl: buildBottomControl,
maxWidth: maxWidth,
),
),
],
@@ -1328,8 +1322,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
// ),
Obx(
() =>
showRestoreScaleBtn.value &&
plPlayerController.showControls.value
showRestoreScaleBtn.value && plPlayerController.showControls.value
? Align(
alignment: Alignment.bottomCenter,
child: Padding(
@@ -1337,9 +1330,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
child: FilledButton.tonal(
style: FilledButton.styleFrom(
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
backgroundColor: theme
.colorScheme
.secondaryContainer
backgroundColor: theme.colorScheme.secondaryContainer
.withValues(alpha: 0.8),
visualDensity: VisualDensity.compact,
padding: const EdgeInsets.all(15),
@@ -1384,10 +1375,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
/// 进度条 live模式下禁用
Obx(
() {
final int value =
plPlayerController.sliderPositionSeconds.value;
final int max =
plPlayerController.durationSeconds.value.inSeconds;
final int value = plPlayerController.sliderPositionSeconds.value;
final int max = plPlayerController.durationSeconds.value.inSeconds;
final int buffer = plPlayerController.bufferedSeconds.value;
if (plPlayerController.showControls.value) {
return const SizedBox.shrink();
@@ -1433,7 +1422,11 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
buildDmChart(theme, plPlayerController),
if (plPlayerController.viewPointList.isNotEmpty &&
plPlayerController.showVP.value)
buildViewPointWidget(plPlayerController, 4.25),
buildViewPointWidget(
plPlayerController,
4.25,
maxWidth,
),
IgnorePointer(
child: ProgressBar(
progress: Duration(seconds: value),
@@ -1445,9 +1438,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
timeLabelLocation: TimeLabelLocation.none,
thumbColor: primary,
barHeight: 3.5,
thumbRadius: draggingFixedProgressBar.value
? 7
: 2.5,
thumbRadius: draggingFixedProgressBar.value ? 7 : 2.5,
// onDragStart: (duration) {
// feedBack();
// plPlayerController.onChangedSliderStart();
@@ -1500,8 +1491,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
child: CustomPaint(
size: const Size(double.infinity, 3.5),
painter: SegmentProgressBar(
segmentColors:
plPlayerController.viewPointList,
segmentColors: plPlayerController.viewPointList,
),
),
),
@@ -1511,7 +1501,10 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
left: 0,
right: 0,
bottom: 12,
child: buildSeekPreviewWidget(plPlayerController),
child: buildSeekPreviewWidget(
plPlayerController,
maxWidth,
),
),
],
),
@@ -1541,8 +1534,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
child: Visibility(
visible:
plPlayerController.showControls.value &&
(isFullScreen ||
plPlayerController.controlsLock.value),
(isFullScreen || plPlayerController.controlsLock.value),
child: DecoratedBox(
decoration: const BoxDecoration(
color: Color(0x45000000),
@@ -1553,8 +1545,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
plPlayerController.controlsLock.value
? FontAwesomeIcons.lock
: FontAwesomeIcons.lockOpen,
semanticLabel:
plPlayerController.controlsLock.value
semanticLabel: plPlayerController.controlsLock.value
? '解锁'
: '锁定',
size: 15,
@@ -1611,7 +1602,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
8,
),
insetPadding: EdgeInsets.only(
left: context.width / 2,
left: maxWidth / 2,
),
//移除圆角
shape: const RoundedRectangleBorder(),
@@ -1719,9 +1710,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
/// 点击 快进/快退
Obx(
() =>
_mountSeekBackwardButton.value ||
_mountSeekForwardButton.value
() => _mountSeekBackwardButton.value || _mountSeekForwardButton.value
? Positioned.fill(
child: Row(
children: [
@@ -1735,15 +1724,14 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
child: child,
),
child: BackwardSeekIndicator(
duration: plPlayerController
.fastForBackwardDuration,
duration:
plPlayerController.fastForBackwardDuration,
onSubmitted: (Duration value) {
_mountSeekBackwardButton.value = false;
final Player player = widget
.plPlayerController
.videoPlayerController!;
Duration result =
player.state.position - value;
Duration result = player.state.position - value;
result = result.clamp(
Duration.zero,
player.state.duration,
@@ -1766,15 +1754,14 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
child: child,
),
child: ForwardSeekIndicator(
duration: plPlayerController
.fastForBackwardDuration,
duration:
plPlayerController.fastForBackwardDuration,
onSubmitted: (Duration value) {
_mountSeekForwardButton.value = false;
final Player player = widget
.plPlayerController
.videoPlayerController!;
Duration result =
player.state.position + value;
Duration result = player.state.position + value;
result = result.clamp(
Duration.zero,
player.state.duration,
@@ -1793,8 +1780,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
),
],
);
},
);
}
}
@@ -1851,7 +1836,10 @@ Widget buildDmChart(
);
}
Widget buildSeekPreviewWidget(PlPlayerController plPlayerController) {
Widget buildSeekPreviewWidget(
PlPlayerController plPlayerController,
double maxWidth,
) {
return Obx(
() {
if (!plPlayerController.showPreview.value ||
@@ -1864,8 +1852,6 @@ Widget buildSeekPreviewWidget(PlPlayerController plPlayerController) {
VideoShotData data = plPlayerController.videoShot!['data'];
return LayoutBuilder(
builder: (context, constraints) {
try {
double scale =
plPlayerController.isFullScreen.value &&
@@ -1874,7 +1860,7 @@ Widget buildSeekPreviewWidget(PlPlayerController plPlayerController) {
: 2.5;
// offset
double left = (plPlayerController.previewDx.value - 48 * scale / 2)
.clamp(8, constraints.maxWidth - 48 * scale - 8);
.clamp(8, maxWidth - 48 * scale - 8);
// index
// int index = plPlayerController.sliderPositionSeconds.value ~/ 5;
@@ -1883,8 +1869,7 @@ Widget buildSeekPreviewWidget(PlPlayerController plPlayerController) {
(data.index!
.where(
(item) =>
item <=
plPlayerController.sliderPositionSeconds.value,
item <= plPlayerController.sliderPositionSeconds.value,
)
.length -
2),
@@ -1933,16 +1918,13 @@ Widget buildSeekPreviewWidget(PlPlayerController plPlayerController) {
}
},
);
},
);
}
Widget buildViewPointWidget(
PlPlayerController plPlayerController,
double offset,
double maxWidth,
) {
return LayoutBuilder(
builder: (context, constraints) {
return Container(
height: 16,
margin: EdgeInsets.only(bottom: offset),
@@ -1950,7 +1932,7 @@ Widget buildViewPointWidget(
behavior: HitTestBehavior.opaque,
onPointerDown: (event) {
try {
double seg = event.localPosition.dx / constraints.maxWidth;
double seg = event.localPosition.dx / maxWidth;
Segment item = plPlayerController.viewPointList
.where((item) => item.start >= seg)
.reduce((a, b) => a.start < b.start ? a : b);
@@ -1966,6 +1948,4 @@ Widget buildViewPointWidget(
},
),
);
},
);
}

View File

@@ -10,14 +10,17 @@ import 'package:flutter/rendering.dart';
import 'package:get/get.dart';
class BottomControl extends StatelessWidget {
final PlPlayerController controller;
final Function buildBottomControl;
const BottomControl({
required this.controller,
required this.buildBottomControl,
required this.maxWidth,
super.key,
});
final PlPlayerController controller;
final Widget Function(double maxWidth) buildBottomControl;
final double maxWidth;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
@@ -51,7 +54,7 @@ class BottomControl extends StatelessWidget {
buildDmChart(theme, controller, 4.5),
if (controller.viewPointList.isNotEmpty &&
controller.showVP.value)
buildViewPointWidget(controller, 8.75),
buildViewPointWidget(controller, 8.75, maxWidth),
ProgressBar(
progress: Duration(seconds: value),
buffered: Duration(seconds: buffer),
@@ -146,7 +149,7 @@ class BottomControl extends StatelessWidget {
left: 0,
right: 0,
bottom: 18,
child: buildSeekPreviewWidget(controller),
child: buildSeekPreviewWidget(controller, maxWidth),
),
],
),
@@ -154,7 +157,7 @@ class BottomControl extends StatelessWidget {
);
},
),
buildBottomControl(),
buildBottomControl(maxWidth),
const SizedBox(height: 12),
],
),