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 813a660e5..abdf56f12 100644 --- a/lib/common/widgets/progress_bar/audio_video_progress_bar.dart +++ b/lib/common/widgets/progress_bar/audio_video_progress_bar.dart @@ -181,7 +181,7 @@ class ProgressBar extends LeafRenderObjectWidget { @override RenderObject createRenderObject(BuildContext context) { - return _RenderProgressBar( + return RenderProgressBar( progress: progress, total: total, buffered: buffered ?? Duration.zero, @@ -203,8 +203,11 @@ class ProgressBar extends LeafRenderObjectWidget { } @override - void updateRenderObject(BuildContext context, RenderObject renderObject) { - (renderObject as _RenderProgressBar) + void updateRenderObject( + BuildContext context, + RenderProgressBar renderObject, + ) { + renderObject ..total = total ..progress = progress ..buffered = buffered ?? Duration.zero @@ -327,8 +330,8 @@ class _EagerHorizontalDragGestureRecognizer String get debugDescription => '_EagerHorizontalDragGestureRecognizer'; } -class _RenderProgressBar extends RenderBox { - _RenderProgressBar({ +class RenderProgressBar extends RenderBox { + RenderProgressBar({ required Duration progress, required Duration total, required Duration buffered, diff --git a/lib/common/widgets/progress_bar/video_progress_indicator.dart b/lib/common/widgets/progress_bar/video_progress_indicator.dart index 909e4aa1f..4cc1a844e 100644 --- a/lib/common/widgets/progress_bar/video_progress_indicator.dart +++ b/lib/common/widgets/progress_bar/video_progress_indicator.dart @@ -1,28 +1,162 @@ -import 'package:PiliPlus/common/constants.dart'; -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 . + */ -Widget videoProgressIndicator(double progress) => ClipRect( - clipper: ProgressClipper(), - child: ClipRRect( - borderRadius: const BorderRadius.vertical(bottom: StyleString.imgRadius), - child: LinearProgressIndicator( - minHeight: 10, - value: progress, - // ignore: deprecated_member_use - year2023: true, - stopIndicatorColor: Colors.transparent, - ), - ), -); +import 'package:flutter/widgets.dart'; + +class VideoProgressIndicator extends LeafRenderObjectWidget { + const VideoProgressIndicator({ + super.key, + required this.color, + required this.backgroundColor, + this.radius = 10, + this.height = 4, + required this.progress, + }) : assert(progress >= 0 && progress <= 1); + + final Color color; + final Color backgroundColor; + final double radius; + final double height; + final double progress; -class ProgressClipper extends CustomClipper { @override - Rect getClip(Size size) { - return Rect.fromLTWH(0, 6, size.width, size.height - 6); + RenderObject createRenderObject(BuildContext context) { + return RenderProgressBar( + color: color, + backgroundColor: backgroundColor, + radius: radius, + height: height, + progress: progress, + ); } @override - bool shouldReclip(CustomClipper oldClipper) { - return false; + void updateRenderObject( + BuildContext context, + RenderProgressBar renderObject, + ) { + renderObject + ..color = color + ..backgroundColor = backgroundColor + ..radius = radius + ..height = height + ..progress = progress; } } + +class RenderProgressBar extends RenderBox { + RenderProgressBar({ + required Color color, + required Color backgroundColor, + required double radius, + required double height, + required double progress, + }) : _color = color, + _backgroundColor = backgroundColor, + _radius = radius, + _height = height, + _progress = progress; + + Color _color; + Color get color => _color; + set color(Color value) { + if (_color == value) return; + _color = value; + markNeedsPaint(); + } + + Color _backgroundColor; + Color get backgroundColor => _backgroundColor; + set backgroundColor(Color value) { + if (_backgroundColor == value) return; + _backgroundColor = value; + markNeedsPaint(); + } + + double _progress; + double get progress => _progress; + set progress(double value) { + if (_progress == value) return; + _progress = value; + markNeedsPaint(); + } + + double _radius; + double get borderRadius => _radius; + set radius(double value) { + if (_radius == value) return; + _radius = value; + markNeedsLayout(); + } + + double _height; + double get height => _height; + set height(double value) { + if (_height == value) return; + _height = value; + markNeedsPaint(); + } + + @override + void performLayout() { + size = computeDryLayout(constraints); + } + + @override + Size computeDryLayout(BoxConstraints constraints) { + return constraints.constrain( + Size(constraints.maxWidth, _radius), + ); + } + + @override + void paint(PaintingContext context, Offset offset) { + final size = this.size; + final canvas = context.canvas; + final paint = Paint()..style = .fill; + + canvas.clipRect( + .fromLTWH(0, size.height - height, size.width, height), + ); + + final radius = Radius.circular(_radius); + final rect = Rect.fromLTWH(0, 0, size.width, size.height); + + if (progress == 0) { + canvas.drawRRect( + .fromRectAndCorners(rect, bottomLeft: radius, bottomRight: radius), + paint..color = _backgroundColor, + ); + } else if (progress == 1) { + canvas.drawRRect( + .fromRectAndCorners(rect, bottomLeft: radius, bottomRight: radius), + paint..color = _color, + ); + } else { + final w = size.width * progress; + final left = Rect.fromLTWH(0, 0, w, size.height); + final right = Rect.fromLTWH(w, 0, size.width - w, size.height); + canvas + ..clipRRect(.fromRectAndRadius(rect, radius)) + ..drawRect(left, paint..color = _color) + ..drawRect(right, paint..color = _backgroundColor); + } + } + + @override + bool get isRepaintBoundary => true; +} diff --git a/lib/common/widgets/video_card/video_card_h.dart b/lib/common/widgets/video_card/video_card_h.dart index 861069fc5..9be6cdd64 100644 --- a/lib/common/widgets/video_card/video_card_h.dart +++ b/lib/common/widgets/video_card/video_card_h.dart @@ -63,6 +63,7 @@ class VideoCardH extends StatelessWidget { title: videoItem.title, cover: videoItem.cover, ); + final colorScheme = ColorScheme.of(context); return Material( type: MaterialType.transparency, child: Stack( @@ -166,8 +167,11 @@ class VideoCardH extends StatelessWidget { left: 0, bottom: 0, right: 0, - child: videoProgressIndicator( - progress == -1 + child: VideoProgressIndicator( + color: colorScheme.primary, + backgroundColor: + colorScheme.secondaryContainer, + progress: progress == -1 ? 1 : progress / videoItem.duration, ), diff --git a/lib/pages/download/detail/widgets/item.dart b/lib/pages/download/detail/widgets/item.dart index 70fe0c815..4cbdf36fb 100644 --- a/lib/pages/download/detail/widgets/item.dart +++ b/lib/pages/download/detail/widgets/item.dart @@ -224,8 +224,11 @@ class DetailItem extends StatelessWidget { child: Stack( clipBehavior: Clip.none, children: [ - videoProgressIndicator( - progress / entry.totalTimeMilli, + VideoProgressIndicator( + color: theme.colorScheme.primary, + backgroundColor: + theme.colorScheme.secondaryContainer, + progress: progress / entry.totalTimeMilli, ), PBadge( text: progress >= entry.totalTimeMilli - 400 diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index 7e2411a47..601b5635d 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -157,8 +157,11 @@ class HistoryItem extends StatelessWidget { left: 0, right: 0, bottom: 0, - child: videoProgressIndicator( - item.progress == -1 + child: VideoProgressIndicator( + color: theme.colorScheme.primary, + backgroundColor: + theme.colorScheme.secondaryContainer, + progress: item.progress == -1 ? 1 : item.progress! / item.duration!, ), diff --git a/lib/pages/later/widgets/video_card_h_later.dart b/lib/pages/later/widgets/video_card_h_later.dart index c99da0681..91e256092 100644 --- a/lib/pages/later/widgets/video_card_h_later.dart +++ b/lib/pages/later/widgets/video_card_h_later.dart @@ -136,8 +136,11 @@ class VideoCardHLater extends StatelessWidget { left: 0, bottom: 0, right: 0, - child: videoProgressIndicator( - progress == -1 + child: VideoProgressIndicator( + color: theme.colorScheme.primary, + backgroundColor: + theme.colorScheme.secondaryContainer, + progress: progress == -1 ? 1 : progress / videoItem.duration!, ), diff --git a/lib/pages/member_video/widgets/video_card_h_member_video.dart b/lib/pages/member_video/widgets/video_card_h_member_video.dart index c549902a0..fb561a863 100644 --- a/lib/pages/member_video/widgets/video_card_h_member_video.dart +++ b/lib/pages/member_video/widgets/video_card_h_member_video.dart @@ -141,8 +141,16 @@ class VideoCardHMemberVideo extends StatelessWidget { left: 0, right: 0, bottom: 0, - child: videoProgressIndicator( - videoItem.history!.progress! / + child: VideoProgressIndicator( + color: + theme.colorScheme.primary, + backgroundColor: theme + .colorScheme + .secondaryContainer, + progress: + videoItem + .history! + .progress! / videoItem .history! .duration!,