mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-19 08:50:07 +08:00
@@ -7,21 +7,21 @@ class Arc extends LeafRenderObjectWidget {
|
||||
super.key,
|
||||
required this.size,
|
||||
required this.color,
|
||||
required this.sweepAngle,
|
||||
required this.progress,
|
||||
this.strokeWidth = 2,
|
||||
});
|
||||
|
||||
final double size;
|
||||
final Color color;
|
||||
final double sweepAngle;
|
||||
final double progress;
|
||||
final double strokeWidth;
|
||||
|
||||
@override
|
||||
RenderObject createRenderObject(BuildContext context) {
|
||||
return RenderArc(
|
||||
size: size,
|
||||
preferredSize: size,
|
||||
color: color,
|
||||
sweepAngle: sweepAngle,
|
||||
progress: progress,
|
||||
strokeWidth: strokeWidth,
|
||||
);
|
||||
}
|
||||
@@ -32,21 +32,22 @@ class Arc extends LeafRenderObjectWidget {
|
||||
RenderArc renderObject,
|
||||
) {
|
||||
renderObject
|
||||
..preferredSize = size
|
||||
..color = color
|
||||
..sweepAngle = sweepAngle
|
||||
..progress = progress
|
||||
..strokeWidth = strokeWidth;
|
||||
}
|
||||
}
|
||||
|
||||
class RenderArc extends RenderBox {
|
||||
RenderArc({
|
||||
required double size,
|
||||
required double preferredSize,
|
||||
required Color color,
|
||||
required double sweepAngle,
|
||||
required double progress,
|
||||
required double strokeWidth,
|
||||
}) : _preferredSize = Size.square(size),
|
||||
}) : _preferredSize = preferredSize,
|
||||
_color = color,
|
||||
_sweepAngle = sweepAngle,
|
||||
_progress = progress,
|
||||
_strokeWidth = strokeWidth;
|
||||
|
||||
Color _color;
|
||||
@@ -57,11 +58,11 @@ class RenderArc extends RenderBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
double _sweepAngle;
|
||||
double get sweepAngle => _sweepAngle;
|
||||
set sweepAngle(double value) {
|
||||
if (_sweepAngle == value) return;
|
||||
_sweepAngle = value;
|
||||
double _progress;
|
||||
double get progress => _progress;
|
||||
set progress(double value) {
|
||||
if (_progress == value) return;
|
||||
_progress = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
@@ -73,8 +74,9 @@ class RenderArc extends RenderBox {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
Size _preferredSize;
|
||||
set preferredSize(Size value) {
|
||||
double _preferredSize;
|
||||
double get preferredSize => _preferredSize;
|
||||
set preferredSize(double value) {
|
||||
if (_preferredSize == value) return;
|
||||
_preferredSize = value;
|
||||
markNeedsLayout();
|
||||
@@ -82,12 +84,12 @@ class RenderArc extends RenderBox {
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = constraints.constrain(_preferredSize);
|
||||
size = constraints.constrainDimensions(_preferredSize, _preferredSize);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
if (sweepAngle == 0) {
|
||||
if (progress == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,15 +98,14 @@ class RenderArc extends RenderBox {
|
||||
..strokeWidth = strokeWidth
|
||||
..style = PaintingStyle.stroke;
|
||||
|
||||
final size = this.size;
|
||||
final radius = size.width / 2;
|
||||
final rect = Rect.fromCircle(
|
||||
center: Offset(size.width / 2, size.height / 2),
|
||||
radius: size.width / 2,
|
||||
center: Offset(radius, radius),
|
||||
radius: radius,
|
||||
);
|
||||
|
||||
const startAngle = -pi / 2;
|
||||
|
||||
context.canvas.drawArc(rect, startAngle, sweepAngle, false, paint);
|
||||
context.canvas.drawArc(rect, startAngle, progress * 2 * pi, false, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -7,14 +7,18 @@ class DisabledIcon<T extends Widget> extends SingleChildRenderObjectWidget {
|
||||
const DisabledIcon({
|
||||
super.key,
|
||||
required T child,
|
||||
this.disable = false,
|
||||
this.color,
|
||||
this.iconSize,
|
||||
double? lineLengthScale,
|
||||
StrokeCap? strokeCap,
|
||||
}) : lineLengthScale = lineLengthScale ?? 0.9,
|
||||
strokeCap = strokeCap ?? StrokeCap.butt,
|
||||
super(child: child);
|
||||
|
||||
final bool disable;
|
||||
final Color? color;
|
||||
final double? iconSize;
|
||||
final StrokeCap strokeCap;
|
||||
final double lineLengthScale;
|
||||
|
||||
@@ -22,12 +26,18 @@ class DisabledIcon<T extends Widget> extends SingleChildRenderObjectWidget {
|
||||
|
||||
@override
|
||||
RenderObject createRenderObject(BuildContext context) {
|
||||
late final iconTheme = IconTheme.of(context);
|
||||
return RenderMaskedIcon(
|
||||
disable: disable,
|
||||
iconSize:
|
||||
iconSize ??
|
||||
(child is Icon ? (child as Icon?)?.size : null) ??
|
||||
iconTheme.size ??
|
||||
24.0,
|
||||
color:
|
||||
color ??
|
||||
(child is Icon
|
||||
? (child as Icon).color ?? IconTheme.of(context).color!
|
||||
: IconTheme.of(context).color!),
|
||||
(child is Icon ? (child as Icon?)?.color : null) ??
|
||||
iconTheme.color!,
|
||||
strokeCap: strokeCap,
|
||||
lineLengthScale: lineLengthScale,
|
||||
);
|
||||
@@ -35,12 +45,18 @@ class DisabledIcon<T extends Widget> extends SingleChildRenderObjectWidget {
|
||||
|
||||
@override
|
||||
void updateRenderObject(BuildContext context, RenderMaskedIcon renderObject) {
|
||||
late final iconTheme = IconTheme.of(context);
|
||||
renderObject
|
||||
..disable = disable
|
||||
..iconSize =
|
||||
iconSize ??
|
||||
(child is Icon ? (child as Icon?)?.size : null) ??
|
||||
iconTheme.size ??
|
||||
24.0
|
||||
..color =
|
||||
color ??
|
||||
(child is Icon
|
||||
? (child as Icon).color ?? IconTheme.of(context).color!
|
||||
: IconTheme.of(context).color!)
|
||||
(child is Icon ? (child as Icon?)?.color : null) ??
|
||||
iconTheme.color!
|
||||
..strokeCap = strokeCap
|
||||
..lineLengthScale = lineLengthScale;
|
||||
}
|
||||
@@ -48,13 +64,33 @@ class DisabledIcon<T extends Widget> extends SingleChildRenderObjectWidget {
|
||||
|
||||
class RenderMaskedIcon extends RenderProxyBox {
|
||||
RenderMaskedIcon({
|
||||
required bool disable,
|
||||
required double iconSize,
|
||||
required Color color,
|
||||
required StrokeCap strokeCap,
|
||||
required double lineLengthScale,
|
||||
}) : _color = color,
|
||||
}) : _disable = disable,
|
||||
_iconSize = iconSize,
|
||||
_color = color,
|
||||
_strokeCap = strokeCap,
|
||||
_lineLengthScale = lineLengthScale;
|
||||
|
||||
bool _disable;
|
||||
bool get disable => _disable;
|
||||
set disable(bool value) {
|
||||
if (_disable == value) return;
|
||||
_disable = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
double _iconSize;
|
||||
double get iconSize => _iconSize;
|
||||
set iconSize(double value) {
|
||||
if (_iconSize == value) return;
|
||||
_iconSize = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
Color _color;
|
||||
Color get color => _color;
|
||||
set color(Color value) {
|
||||
@@ -81,23 +117,30 @@ class RenderMaskedIcon extends RenderProxyBox {
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
final strokeWidth = size.width / 12;
|
||||
if (!disable) {
|
||||
return super.paint(context, offset);
|
||||
}
|
||||
|
||||
final canvas = context.canvas;
|
||||
|
||||
Size size = this.size;
|
||||
final exceedWidth = size.width > _iconSize;
|
||||
final exceedHeight = size.height > _iconSize;
|
||||
if (exceedWidth || exceedHeight) {
|
||||
final dx = exceedWidth ? (size.width - _iconSize) / 2.0 : 0.0;
|
||||
final dy = exceedHeight ? (size.height - _iconSize) / 2.0 : 0.0;
|
||||
size = Size.square(_iconSize);
|
||||
offset = Offset(dx, dy);
|
||||
} else if (size.width < _iconSize && size.height < _iconSize) {
|
||||
size = Size.square(_iconSize);
|
||||
}
|
||||
|
||||
final strokeWidth = size.width / 12;
|
||||
|
||||
var rect = offset & size;
|
||||
|
||||
final sqrt2Width = strokeWidth * sqrt2; // rotate pi / 4
|
||||
|
||||
// final path = Path.combine(
|
||||
// PathOperation.difference,
|
||||
// Path()..addRect(rect),
|
||||
// Path()..moveTo(rect.left, rect.top)
|
||||
// ..relativeLineTo(sqrt2Width, 0)
|
||||
// ..lineTo(rect.right, rect.bottom - sqrt2Width)
|
||||
// ..lineTo(rect.right, rect.bottom)
|
||||
// ..close(),
|
||||
// );
|
||||
|
||||
final path = Path.combine(
|
||||
PathOperation.union,
|
||||
Path() // bottom
|
||||
@@ -114,7 +157,7 @@ class RenderMaskedIcon extends RenderProxyBox {
|
||||
canvas
|
||||
..save()
|
||||
..clipPath(path, doAntiAlias: false);
|
||||
super.paint(context, offset);
|
||||
super.paint(context, .zero);
|
||||
|
||||
canvas.restore();
|
||||
|
||||
@@ -137,8 +180,3 @@ class RenderMaskedIcon extends RenderProxyBox {
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
}
|
||||
|
||||
extension DisabledIconExt on Icon {
|
||||
DisabledIcon<Icon> disable([double? lineLengthScale]) =>
|
||||
DisabledIcon(lineLengthScale: lineLengthScale, child: this);
|
||||
}
|
||||
|
||||
@@ -81,9 +81,7 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
||||
|
||||
final GlobalKey _parentKey = GlobalKey();
|
||||
Animation<Offset>? _animation;
|
||||
CurvedAnimation? _curvedAnimation;
|
||||
Animation<double>? _scaleAnimation;
|
||||
CurvedAnimation? _curvedScaleAnimation;
|
||||
late Offset _scaleAnimationFocalPoint;
|
||||
late AnimationController _controller;
|
||||
late AnimationController _scaleController;
|
||||
@@ -435,20 +433,15 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
||||
details.velocity.pixelsPerSecond.distance,
|
||||
widget.interactionEndFrictionCoefficient,
|
||||
);
|
||||
_animation =
|
||||
Tween<Offset>(
|
||||
begin: translation,
|
||||
end: Offset(
|
||||
frictionSimulationX.finalX,
|
||||
frictionSimulationY.finalX,
|
||||
),
|
||||
).animate(
|
||||
_curvedAnimation ??= CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: Curves.decelerate,
|
||||
),
|
||||
)
|
||||
..addListener(_handleInertiaAnimation);
|
||||
_animation = _controller.drive(
|
||||
Tween<Offset>(
|
||||
begin: translation,
|
||||
end: Offset(
|
||||
frictionSimulationX.finalX,
|
||||
frictionSimulationY.finalX,
|
||||
),
|
||||
).chain(CurveTween(curve: Curves.decelerate)),
|
||||
)..addListener(_handleInertiaAnimation);
|
||||
_controller
|
||||
..duration = Duration(milliseconds: (tFinal * 1000).round())
|
||||
..forward();
|
||||
@@ -468,17 +461,12 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
||||
widget.interactionEndFrictionCoefficient,
|
||||
effectivelyMotionless: 0.1,
|
||||
);
|
||||
_scaleAnimation =
|
||||
Tween<double>(
|
||||
begin: scale,
|
||||
end: frictionSimulation.x(tFinal),
|
||||
).animate(
|
||||
_curvedScaleAnimation ??= CurvedAnimation(
|
||||
parent: _scaleController,
|
||||
curve: Curves.decelerate,
|
||||
),
|
||||
)
|
||||
..addListener(_handleScaleAnimation);
|
||||
_scaleAnimation = _scaleController.drive(
|
||||
Tween<double>(
|
||||
begin: scale,
|
||||
end: frictionSimulation.x(tFinal),
|
||||
).chain(CurveTween(curve: Curves.decelerate)),
|
||||
)..addListener(_handleScaleAnimation);
|
||||
_scaleController
|
||||
..duration = Duration(milliseconds: (tFinal * 1000).round())
|
||||
..forward();
|
||||
@@ -732,9 +720,7 @@ class _MouseInteractiveViewerState extends State<MouseInteractiveViewer>
|
||||
@override
|
||||
void dispose() {
|
||||
_scaleGestureRecognizer.dispose();
|
||||
_curvedAnimation?.dispose();
|
||||
_controller.dispose();
|
||||
_curvedScaleAnimation?.dispose();
|
||||
_scaleController.dispose();
|
||||
_transformer.removeListener(_handleTransformation);
|
||||
if (widget.transformationController == null) {
|
||||
|
||||
@@ -31,18 +31,6 @@ class HeroDialogRoute<T> extends PageRoute<T> {
|
||||
@override
|
||||
Color? get barrierColor => null;
|
||||
|
||||
CurvedAnimation? _curvedAnimation;
|
||||
|
||||
void _setAnimation(Animation<double> animation) {
|
||||
if (_curvedAnimation?.parent != animation) {
|
||||
_curvedAnimation?.dispose();
|
||||
_curvedAnimation = CurvedAnimation(
|
||||
parent: animation,
|
||||
curve: Curves.easeOut,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildTransitions(
|
||||
BuildContext context,
|
||||
@@ -50,19 +38,12 @@ class HeroDialogRoute<T> extends PageRoute<T> {
|
||||
Animation<double> secondaryAnimation,
|
||||
Widget child,
|
||||
) {
|
||||
_setAnimation(animation);
|
||||
return FadeTransition(
|
||||
opacity: _curvedAnimation!,
|
||||
opacity: animation.drive(CurveTween(curve: Curves.easeOut)),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_curvedAnimation?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildPage(
|
||||
BuildContext context,
|
||||
|
||||
@@ -503,9 +503,7 @@ class _InteractiveViewerState extends State<InteractiveViewer>
|
||||
final GlobalKey _childKey = GlobalKey();
|
||||
final GlobalKey _parentKey = GlobalKey();
|
||||
Animation<Offset>? _animation;
|
||||
CurvedAnimation? _curvedAnimation;
|
||||
Animation<double>? _scaleAnimation;
|
||||
CurvedAnimation? _curvedScaleAnimation;
|
||||
late Offset _scaleAnimationFocalPoint;
|
||||
late AnimationController _controller;
|
||||
late AnimationController _scaleController;
|
||||
@@ -924,19 +922,15 @@ class _InteractiveViewerState extends State<InteractiveViewer>
|
||||
details.velocity.pixelsPerSecond.distance,
|
||||
widget.interactionEndFrictionCoefficient,
|
||||
);
|
||||
_animation =
|
||||
Tween<Offset>(
|
||||
begin: translation,
|
||||
end: Offset(
|
||||
frictionSimulationX.finalX,
|
||||
frictionSimulationY.finalX,
|
||||
),
|
||||
).animate(
|
||||
_curvedAnimation ??= CurvedAnimation(
|
||||
parent: _controller,
|
||||
curve: Curves.decelerate,
|
||||
),
|
||||
);
|
||||
_animation = _controller.drive(
|
||||
Tween<Offset>(
|
||||
begin: translation,
|
||||
end: Offset(
|
||||
frictionSimulationX.finalX,
|
||||
frictionSimulationY.finalX,
|
||||
),
|
||||
).chain(CurveTween(curve: Curves.decelerate)),
|
||||
);
|
||||
_controller.duration = Duration(milliseconds: (tFinal * 1000).round());
|
||||
_animation!.addListener(_handleInertiaAnimation);
|
||||
_controller.forward();
|
||||
@@ -956,16 +950,12 @@ class _InteractiveViewerState extends State<InteractiveViewer>
|
||||
widget.interactionEndFrictionCoefficient,
|
||||
effectivelyMotionless: 0.1,
|
||||
);
|
||||
_scaleAnimation =
|
||||
Tween<double>(
|
||||
begin: scale,
|
||||
end: frictionSimulation.x(tFinal),
|
||||
).animate(
|
||||
_curvedScaleAnimation ??= CurvedAnimation(
|
||||
parent: _scaleController,
|
||||
curve: Curves.decelerate,
|
||||
),
|
||||
);
|
||||
_scaleAnimation = _scaleController.drive(
|
||||
Tween<double>(
|
||||
begin: scale,
|
||||
end: frictionSimulation.x(tFinal),
|
||||
).chain(CurveTween(curve: Curves.decelerate)),
|
||||
);
|
||||
_scaleController.duration = Duration(
|
||||
milliseconds: (tFinal * 1000).round(),
|
||||
);
|
||||
@@ -1155,9 +1145,7 @@ class _InteractiveViewerState extends State<InteractiveViewer>
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_curvedAnimation?.dispose();
|
||||
_controller.dispose();
|
||||
_curvedScaleAnimation?.dispose();
|
||||
_scaleController.dispose();
|
||||
_transformer.removeListener(_handleTransformation);
|
||||
if (widget.transformationController == null) {
|
||||
|
||||
@@ -114,7 +114,7 @@ class InteractiveViewerBoundaryState extends State<InteractiveViewerBoundary>
|
||||
|
||||
_scaleAnimation = _animateController.drive(
|
||||
Tween<double>(
|
||||
begin: 1,
|
||||
begin: 1.0,
|
||||
end: 0.25,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -207,13 +207,12 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
|
||||
if (_transformationController.value != Matrix4.identity()) {
|
||||
// animate the reset for the transformation of the interactive viewer
|
||||
|
||||
_animation =
|
||||
Matrix4Tween(
|
||||
begin: _transformationController.value,
|
||||
end: Matrix4.identity(),
|
||||
).animate(
|
||||
CurveTween(curve: Curves.easeOut).animate(_animationController),
|
||||
);
|
||||
_animation = _animationController.drive(
|
||||
Matrix4Tween(
|
||||
begin: _transformationController.value,
|
||||
end: Matrix4.identity(),
|
||||
).chain(CurveTween(curve: Curves.easeOut)),
|
||||
);
|
||||
|
||||
_animationController.forward(from: 0);
|
||||
}
|
||||
@@ -401,13 +400,12 @@ class _InteractiveviewerGalleryState extends State<InteractiveviewerGallery>
|
||||
matrix.row3.w,
|
||||
]);
|
||||
|
||||
_animation =
|
||||
Matrix4Tween(
|
||||
begin: _transformationController.value,
|
||||
end: matrix,
|
||||
).animate(
|
||||
CurveTween(curve: Curves.easeOut).animate(_animationController),
|
||||
);
|
||||
_animation = _animationController.drive(
|
||||
Matrix4Tween(
|
||||
begin: _transformationController.value,
|
||||
end: matrix,
|
||||
).chain(CurveTween(curve: Curves.easeOut)),
|
||||
);
|
||||
_animationController
|
||||
.forward(from: 0)
|
||||
.whenComplete(() => _onScaleChanged(targetScale));
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:PiliPlus/common/widgets/custom_arc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -35,7 +33,7 @@ class LoadingWidget extends StatelessWidget {
|
||||
size: 40,
|
||||
color: onSurfaceVariant,
|
||||
strokeWidth: 3,
|
||||
sweepAngle: progress.value * 2 * pi,
|
||||
progress: progress.value,
|
||||
),
|
||||
),
|
||||
//msg
|
||||
|
||||
@@ -10,14 +10,7 @@ import 'package:flutter/services.dart'
|
||||
PointerEnterEventListener,
|
||||
PointerExitEventListener;
|
||||
|
||||
/// The shape of the progress bar at the left and right ends.
|
||||
enum BarCapShape {
|
||||
/// The left and right ends of the bar are round.
|
||||
round,
|
||||
|
||||
/// The left and right ends of the bar are square.
|
||||
square,
|
||||
}
|
||||
/// https://github.com/suragch/audio_video_progress_bar
|
||||
|
||||
/// A progress bar widget to show or set the location of the currently
|
||||
/// playing audio or video content.
|
||||
@@ -36,7 +29,7 @@ class ProgressBar extends LeafRenderObjectWidget {
|
||||
super.key,
|
||||
required this.progress,
|
||||
required this.total,
|
||||
this.buffered,
|
||||
this.buffered = .zero,
|
||||
this.onSeek,
|
||||
this.onDragStart,
|
||||
this.onDragUpdate,
|
||||
@@ -45,7 +38,6 @@ class ProgressBar extends LeafRenderObjectWidget {
|
||||
required this.baseBarColor,
|
||||
required this.progressBarColor,
|
||||
required this.bufferedBarColor,
|
||||
this.barCapShape = BarCapShape.round,
|
||||
this.thumbRadius = 10.0,
|
||||
required this.thumbColor,
|
||||
required this.thumbGlowColor,
|
||||
@@ -65,7 +57,7 @@ class ProgressBar extends LeafRenderObjectWidget {
|
||||
///
|
||||
/// This is useful for streamed content. If you are playing a local file
|
||||
/// then you can leave this out.
|
||||
final Duration? buffered;
|
||||
final Duration buffered;
|
||||
|
||||
/// A callback when user moves the thumb.
|
||||
///
|
||||
@@ -142,12 +134,6 @@ class ProgressBar extends LeafRenderObjectWidget {
|
||||
/// a shade darker than [baseBarColor].
|
||||
final Color bufferedBarColor;
|
||||
|
||||
/// The shape of the bar at the left and right ends.
|
||||
///
|
||||
/// This affects the base bar for the total time, the current progress bar,
|
||||
/// and the buffered progress bar. The default is [BarCapShape.round].
|
||||
final BarCapShape barCapShape;
|
||||
|
||||
/// The radius of the circle for the moveable progress bar thumb.
|
||||
final double thumbRadius;
|
||||
|
||||
@@ -189,7 +175,7 @@ class ProgressBar extends LeafRenderObjectWidget {
|
||||
return RenderProgressBar(
|
||||
progress: progress,
|
||||
total: total,
|
||||
buffered: buffered ?? Duration.zero,
|
||||
buffered: buffered,
|
||||
onSeek: onSeek,
|
||||
onDragStart: onDragStart,
|
||||
onDragUpdate: onDragUpdate,
|
||||
@@ -198,7 +184,6 @@ class ProgressBar extends LeafRenderObjectWidget {
|
||||
baseBarColor: baseBarColor,
|
||||
progressBarColor: progressBarColor,
|
||||
bufferedBarColor: bufferedBarColor,
|
||||
barCapShape: barCapShape,
|
||||
thumbRadius: thumbRadius,
|
||||
thumbColor: thumbColor,
|
||||
thumbGlowColor: thumbGlowColor,
|
||||
@@ -215,7 +200,7 @@ class ProgressBar extends LeafRenderObjectWidget {
|
||||
renderObject
|
||||
..total = total
|
||||
..progress = progress
|
||||
..buffered = buffered ?? Duration.zero
|
||||
..buffered = buffered
|
||||
..onSeek = onSeek
|
||||
..onDragStart = onDragStart
|
||||
..onDragUpdate = onDragUpdate
|
||||
@@ -224,7 +209,6 @@ class ProgressBar extends LeafRenderObjectWidget {
|
||||
..baseBarColor = baseBarColor
|
||||
..progressBarColor = progressBarColor
|
||||
..bufferedBarColor = bufferedBarColor
|
||||
..barCapShape = barCapShape
|
||||
..thumbRadius = thumbRadius
|
||||
..thumbColor = thumbColor
|
||||
..thumbGlowColor = thumbGlowColor
|
||||
@@ -271,7 +255,6 @@ class ProgressBar extends LeafRenderObjectWidget {
|
||||
..add(ColorProperty('baseBarColor', baseBarColor))
|
||||
..add(ColorProperty('progressBarColor', progressBarColor))
|
||||
..add(ColorProperty('bufferedBarColor', bufferedBarColor))
|
||||
..add(StringProperty('barCapShape', barCapShape.toString()))
|
||||
..add(DoubleProperty('thumbRadius', thumbRadius))
|
||||
..add(ColorProperty('thumbColor', thumbColor))
|
||||
..add(ColorProperty('thumbGlowColor', thumbGlowColor))
|
||||
@@ -348,7 +331,6 @@ class RenderProgressBar extends RenderBox implements MouseTrackerAnnotation {
|
||||
required Color baseBarColor,
|
||||
required Color progressBarColor,
|
||||
required Color bufferedBarColor,
|
||||
required BarCapShape barCapShape,
|
||||
double thumbRadius = 20.0,
|
||||
required Color thumbColor,
|
||||
required Color thumbGlowColor,
|
||||
@@ -364,7 +346,6 @@ class RenderProgressBar extends RenderBox implements MouseTrackerAnnotation {
|
||||
_baseBarColor = baseBarColor,
|
||||
_progressBarColor = progressBarColor,
|
||||
_bufferedBarColor = bufferedBarColor,
|
||||
_barCapShape = barCapShape,
|
||||
_thumbRadius = thumbRadius,
|
||||
_thumbColor = thumbColor,
|
||||
_thumbGlowColor = thumbGlowColor,
|
||||
@@ -598,14 +579,6 @@ class RenderProgressBar extends RenderBox implements MouseTrackerAnnotation {
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
BarCapShape get barCapShape => _barCapShape;
|
||||
BarCapShape _barCapShape;
|
||||
set barCapShape(BarCapShape value) {
|
||||
if (_barCapShape == value) return;
|
||||
_barCapShape = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
/// The color of the moveable thumb.
|
||||
Color get thumbColor => _thumbColor;
|
||||
Color _thumbColor;
|
||||
@@ -765,12 +738,9 @@ class RenderProgressBar extends RenderBox implements MouseTrackerAnnotation {
|
||||
required double widthProportion,
|
||||
required Color color,
|
||||
}) {
|
||||
final strokeCap = (_barCapShape == BarCapShape.round)
|
||||
? StrokeCap.round
|
||||
: StrokeCap.square;
|
||||
final baseBarPaint = Paint()
|
||||
..color = color
|
||||
..strokeCap = strokeCap
|
||||
..strokeCap = StrokeCap.round
|
||||
..strokeWidth = _barHeight;
|
||||
final capRadius = _barHeight / 2;
|
||||
final adjustedWidth = availableSize.width - barHeight;
|
||||
|
||||
@@ -862,6 +862,7 @@ class _AudioPageState extends State<AudioPage> {
|
||||
src: cover,
|
||||
width: 170,
|
||||
height: 170,
|
||||
cacheWidth: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -40,7 +40,6 @@ abstract class CommonDynPageState<T extends StatefulWidget> extends State<T>
|
||||
final fabOffset = const Offset(0, 1);
|
||||
|
||||
late final AnimationController _fabAnimationCtr;
|
||||
late final CurvedAnimation _curvedAnimation;
|
||||
late final Animation<Offset> fabAnim;
|
||||
|
||||
@override
|
||||
@@ -50,14 +49,12 @@ abstract class CommonDynPageState<T extends StatefulWidget> extends State<T>
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
)..forward();
|
||||
_curvedAnimation = CurvedAnimation(
|
||||
parent: _fabAnimationCtr,
|
||||
curve: Curves.easeInOut,
|
||||
fabAnim = _fabAnimationCtr.drive(
|
||||
Tween<Offset>(
|
||||
begin: fabOffset,
|
||||
end: Offset.zero,
|
||||
).chain(CurveTween(curve: Curves.easeInOut)),
|
||||
);
|
||||
fabAnim = Tween<Offset>(
|
||||
begin: fabOffset,
|
||||
end: Offset.zero,
|
||||
).animate(_curvedAnimation);
|
||||
scrollController = ScrollController()..addListener(listener);
|
||||
}
|
||||
|
||||
@@ -100,7 +97,6 @@ abstract class CommonDynPageState<T extends StatefulWidget> extends State<T>
|
||||
scrollController
|
||||
..removeListener(listener)
|
||||
..dispose();
|
||||
_curvedAnimation.dispose();
|
||||
_fabAnimationCtr.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class PublishRoute<T> extends PopupRoute<T> {
|
||||
}
|
||||
return SlideTransition(
|
||||
position: animation.drive(
|
||||
Tween(
|
||||
Tween<Offset>(
|
||||
begin: const Offset(0.0, 1.0),
|
||||
end: Offset.zero,
|
||||
).chain(CurveTween(curve: Curves.linear)),
|
||||
|
||||
@@ -956,7 +956,7 @@ class _BorderIndicator extends LeafRenderObjectWidget {
|
||||
|
||||
@override
|
||||
RenderObject createRenderObject(BuildContext context) {
|
||||
return RenderBorderIndicator(
|
||||
return _RenderBorderIndicator(
|
||||
radius: radius,
|
||||
isLeft: isLeft,
|
||||
);
|
||||
@@ -965,7 +965,7 @@ class _BorderIndicator extends LeafRenderObjectWidget {
|
||||
@override
|
||||
void updateRenderObject(
|
||||
BuildContext context,
|
||||
RenderBorderIndicator renderObject,
|
||||
_RenderBorderIndicator renderObject,
|
||||
) {
|
||||
renderObject
|
||||
..radius = radius
|
||||
@@ -973,8 +973,8 @@ class _BorderIndicator extends LeafRenderObjectWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class RenderBorderIndicator extends RenderBox {
|
||||
RenderBorderIndicator({
|
||||
class _RenderBorderIndicator extends RenderBox {
|
||||
_RenderBorderIndicator({
|
||||
required Radius radius,
|
||||
required bool isLeft,
|
||||
}) : _radius = radius,
|
||||
|
||||
@@ -17,7 +17,6 @@ class MainReplyController extends ReplyController<MainListReply>
|
||||
bool _showFab = true;
|
||||
|
||||
late final AnimationController _fabAnimationCtr;
|
||||
late final CurvedAnimation _curvedAnimation;
|
||||
late final Animation<Offset> fabAnim;
|
||||
|
||||
@override
|
||||
@@ -27,15 +26,12 @@ class MainReplyController extends ReplyController<MainListReply>
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
)..forward();
|
||||
_curvedAnimation = CurvedAnimation(
|
||||
parent: _fabAnimationCtr,
|
||||
curve: Curves.easeInOut,
|
||||
fabAnim = _fabAnimationCtr.drive(
|
||||
Tween<Offset>(
|
||||
begin: const Offset(0.0, 2.0),
|
||||
end: Offset.zero,
|
||||
).chain(CurveTween(curve: Curves.easeInOut)),
|
||||
);
|
||||
fabAnim = Tween<Offset>(
|
||||
begin: const Offset(0, 2),
|
||||
end: Offset.zero,
|
||||
).animate(_curvedAnimation);
|
||||
|
||||
final args = Get.arguments;
|
||||
oid = args['oid'];
|
||||
replyType = args['replyType'];
|
||||
@@ -71,7 +67,6 @@ class MainReplyController extends ReplyController<MainListReply>
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_curvedAnimation.dispose();
|
||||
_fabAnimationCtr.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@@ -53,12 +53,7 @@ class SavePanel extends StatefulWidget {
|
||||
transitionDuration: const Duration(milliseconds: 255),
|
||||
transitionBuilder: (context, animation, secondaryAnimation, child) {
|
||||
return FadeTransition(
|
||||
opacity: animation.drive(
|
||||
Tween<double>(
|
||||
begin: 0,
|
||||
end: 1,
|
||||
).chain(CurveTween(curve: Curves.easeInOut)),
|
||||
),
|
||||
opacity: animation.drive(CurveTween(curve: Curves.easeInOut)),
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
|
||||
@@ -312,9 +312,14 @@ class _SearchPageState extends State<SearchPage> {
|
||||
child: IconButton(
|
||||
iconSize: 22,
|
||||
tooltip: enable ? '记录搜索' : '无痕搜索',
|
||||
icon: enable
|
||||
? historyIcon(theme)
|
||||
: historyIcon(theme).disable(),
|
||||
icon: DisabledIcon(
|
||||
disable: !enable,
|
||||
child: Icon(
|
||||
Icons.history,
|
||||
color: theme.colorScheme.onSurfaceVariant
|
||||
.withValues(alpha: 0.8),
|
||||
),
|
||||
),
|
||||
style: IconButton.styleFrom(
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
@@ -406,11 +411,6 @@ class _SearchPageState extends State<SearchPage> {
|
||||
),
|
||||
);
|
||||
|
||||
Icon historyIcon(ThemeData theme) => Icon(
|
||||
Icons.history,
|
||||
color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.8),
|
||||
);
|
||||
|
||||
Widget _buildHotKey(
|
||||
LoadingState<SearchRcmdData> loadingState,
|
||||
bool isTrending,
|
||||
|
||||
@@ -941,10 +941,12 @@ class VideoDetailController extends GetxController
|
||||
return Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: SlideTransition(
|
||||
position: Tween<Offset>(
|
||||
begin: const Offset(-1, 0),
|
||||
end: Offset.zero,
|
||||
).animate(animation),
|
||||
position: animation.drive(
|
||||
Tween<Offset>(
|
||||
begin: const Offset(-1.0, 0.0),
|
||||
end: Offset.zero,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: GestureDetector(
|
||||
|
||||
@@ -56,7 +56,7 @@ class ActionItem extends StatelessWidget {
|
||||
builder: (context, child) => Arc(
|
||||
size: 28,
|
||||
color: primary,
|
||||
sweepAngle: animation!.value,
|
||||
progress: -animation!.value,
|
||||
),
|
||||
),
|
||||
child,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math' show pi;
|
||||
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -24,7 +23,6 @@ mixin TripleMixin on GetxController, TickerProvider {
|
||||
|
||||
// no need for pugv
|
||||
AnimationController? _tripleAnimCtr;
|
||||
CurvedAnimation? _curvedAnimation;
|
||||
Animation<double>? _tripleAnimation;
|
||||
|
||||
AnimationController get tripleAnimCtr =>
|
||||
@@ -34,15 +32,8 @@ mixin TripleMixin on GetxController, TickerProvider {
|
||||
reverseDuration: const Duration(milliseconds: 400),
|
||||
);
|
||||
|
||||
CurvedAnimation get curvedAnimation => _curvedAnimation ??= CurvedAnimation(
|
||||
parent: tripleAnimCtr,
|
||||
curve: Curves.easeInOut,
|
||||
);
|
||||
|
||||
Animation<double> get tripleAnimation => _tripleAnimation ??= Tween<double>(
|
||||
begin: 0,
|
||||
end: -2 * pi,
|
||||
).animate(curvedAnimation);
|
||||
Animation<double> get tripleAnimation => _tripleAnimation ??= tripleAnimCtr
|
||||
.drive(CurveTween(curve: Curves.easeInOut));
|
||||
|
||||
Timer? _timer;
|
||||
|
||||
@@ -84,7 +75,6 @@ mixin TripleMixin on GetxController, TickerProvider {
|
||||
@override
|
||||
void onClose() {
|
||||
_cancelTimer();
|
||||
_curvedAnimation?.dispose();
|
||||
_tripleAnimCtr?.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@@ -46,12 +46,7 @@ class PayCoinsPage extends StatefulWidget {
|
||||
transitionDuration: const Duration(milliseconds: 225),
|
||||
transitionBuilder: (context, animation, secondaryAnimation, child) {
|
||||
return FadeTransition(
|
||||
opacity: animation.drive(
|
||||
Tween<double>(
|
||||
begin: 0.0,
|
||||
end: 1.0,
|
||||
).chain(CurveTween(curve: Curves.linear)),
|
||||
),
|
||||
opacity: animation,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
@@ -73,9 +68,8 @@ class _PayCoinsPageState extends State<PayCoinsPage>
|
||||
late final Animation<Offset> _slide22Anim;
|
||||
late final AnimationController _scale22Controller;
|
||||
late final Animation<double> _scale22Anim;
|
||||
late final AnimationController _coinSlideController;
|
||||
late final AnimationController _coinController;
|
||||
late final Animation<Offset> _coinSlideAnim;
|
||||
late final AnimationController _coinFadeController;
|
||||
late final Animation<double> _coinFadeAnim;
|
||||
late final AnimationController _boxAnimController;
|
||||
late final Animation<Offset> _boxAnim;
|
||||
@@ -155,7 +149,7 @@ class _PayCoinsPageState extends State<PayCoinsPage>
|
||||
duration: const Duration(milliseconds: 50),
|
||||
);
|
||||
_slide22Anim = _slide22Controller.drive(
|
||||
Tween(
|
||||
Tween<Offset>(
|
||||
begin: Offset.zero,
|
||||
end: const Offset(0.0, -0.2),
|
||||
),
|
||||
@@ -165,32 +159,30 @@ class _PayCoinsPageState extends State<PayCoinsPage>
|
||||
duration: const Duration(milliseconds: 50),
|
||||
);
|
||||
_scale22Anim = _scale22Controller.drive(
|
||||
Tween(begin: 1, end: 1.1),
|
||||
Tween<double>(begin: 1.0, end: 1.1),
|
||||
);
|
||||
_coinSlideController = AnimationController(
|
||||
_coinController = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
);
|
||||
_coinSlideAnim = _coinSlideController.drive(
|
||||
Tween(
|
||||
_coinSlideAnim = _coinController.drive(
|
||||
Tween<Offset>(
|
||||
begin: Offset.zero,
|
||||
end: const Offset(0.0, -2),
|
||||
),
|
||||
end: const Offset(0.0, -2.0),
|
||||
).chain(CurveTween(curve: const Interval(0.0, 2 / 3))),
|
||||
);
|
||||
_coinFadeController = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
_coinFadeAnim = _coinController.drive(
|
||||
Tween<double>(
|
||||
begin: 1.0,
|
||||
end: 0.0,
|
||||
).chain(CurveTween(curve: const Interval(2 / 3, 1.0))),
|
||||
);
|
||||
_coinFadeAnim = Tween<double>(
|
||||
begin: 1,
|
||||
end: 0,
|
||||
).animate(_coinFadeController);
|
||||
_boxAnimController = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 50),
|
||||
);
|
||||
_boxAnim = _boxAnimController.drive(
|
||||
Tween(
|
||||
Tween<Offset>(
|
||||
begin: Offset.zero,
|
||||
end: const Offset(0.0, -0.2),
|
||||
),
|
||||
@@ -204,8 +196,7 @@ class _PayCoinsPageState extends State<PayCoinsPage>
|
||||
_cancelTimer();
|
||||
_slide22Controller.dispose();
|
||||
_scale22Controller.dispose();
|
||||
_coinSlideController.dispose();
|
||||
_coinFadeController.dispose();
|
||||
_coinController.dispose();
|
||||
_boxAnimController.dispose();
|
||||
_controller?.dispose();
|
||||
super.dispose();
|
||||
@@ -570,11 +561,9 @@ class _PayCoinsPageState extends State<PayCoinsPage>
|
||||
});
|
||||
}
|
||||
_boxAnimController.forward().whenComplete(_boxAnimController.reverse);
|
||||
_coinSlideController.forward().whenComplete(() {
|
||||
_coinFadeController.forward().whenComplete(() {
|
||||
Get.back();
|
||||
widget.onPayCoin(_pageIndex.value + 1, _coinWithLike.value);
|
||||
});
|
||||
_coinController.forward().whenComplete(() {
|
||||
Get.back();
|
||||
widget.onPayCoin(_pageIndex.value + 1, _coinWithLike.value);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,7 +28,6 @@ class VideoReplyController extends ReplyController<MainListReply>
|
||||
|
||||
bool _isFabVisible = true;
|
||||
late final AnimationController _fabAnimationCtr;
|
||||
late final CurvedAnimation _curvedAnimation;
|
||||
late final Animation<Offset> animation;
|
||||
|
||||
@override
|
||||
@@ -38,14 +37,12 @@ class VideoReplyController extends ReplyController<MainListReply>
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 100),
|
||||
)..forward();
|
||||
_curvedAnimation = CurvedAnimation(
|
||||
parent: _fabAnimationCtr,
|
||||
curve: Curves.easeInOut,
|
||||
animation = _fabAnimationCtr.drive(
|
||||
Tween<Offset>(
|
||||
begin: const Offset(0.0, 2.0),
|
||||
end: Offset.zero,
|
||||
).chain(CurveTween(curve: Curves.easeInOut)),
|
||||
);
|
||||
animation = Tween<Offset>(
|
||||
begin: const Offset(0, 2),
|
||||
end: Offset.zero,
|
||||
).animate(_curvedAnimation);
|
||||
}
|
||||
|
||||
void showFab() {
|
||||
@@ -78,7 +75,6 @@ class VideoReplyController extends ReplyController<MainListReply>
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_curvedAnimation.dispose();
|
||||
_fabAnimationCtr.dispose();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@@ -94,7 +94,6 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel>
|
||||
with SingleTickerProviderStateMixin, CommonSlideMixin {
|
||||
late VideoReplyReplyController _controller;
|
||||
late final _tag = Utils.makeHeroTag('${widget.rpid}${widget.dialog}');
|
||||
CurvedAnimation? _curvedAnimation;
|
||||
Animation<Color?>? _colorAnimation;
|
||||
|
||||
late final bool isDialogue = widget.dialog != null;
|
||||
@@ -129,7 +128,6 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel>
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_curvedAnimation?.dispose();
|
||||
Get.delete<VideoReplyReplyController>(tag: _tag);
|
||||
super.dispose();
|
||||
}
|
||||
@@ -334,16 +332,16 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel>
|
||||
final child = _replyItem(context, response[index], index);
|
||||
if (jumpIndex == index) {
|
||||
return AnimatedBuilder(
|
||||
animation: _colorAnimation ??=
|
||||
ColorTween(
|
||||
begin: theme.colorScheme.onInverseSurface,
|
||||
end: theme.colorScheme.surface,
|
||||
).animate(
|
||||
_curvedAnimation ??= CurvedAnimation(
|
||||
parent: _controller.animController,
|
||||
curve: const Interval(0.8, 1.0), // 前0.8s不变, 后0.2s开始动画
|
||||
),
|
||||
animation: _colorAnimation ??= _controller.animController.drive(
|
||||
ColorTween(
|
||||
begin: theme.colorScheme.onInverseSurface,
|
||||
end: theme.colorScheme.surface,
|
||||
).chain(
|
||||
CurveTween(
|
||||
curve: const Interval(0.8, 1.0), // 前0.8s不变, 后0.2s开始动画
|
||||
),
|
||||
),
|
||||
),
|
||||
child: child,
|
||||
builder: (context, child) {
|
||||
return ColoredBox(
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'dart:ui' as ui;
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/cropped_image.dart';
|
||||
import 'package:PiliPlus/common/widgets/custom_icon.dart';
|
||||
import 'package:PiliPlus/common/widgets/disabled_icon.dart';
|
||||
import 'package:PiliPlus/common/widgets/gesture/immediate_tap_gesture_recognizer.dart';
|
||||
import 'package:PiliPlus/common/widgets/gesture/mouse_interactive_viewer.dart';
|
||||
import 'package:PiliPlus/common/widgets/loading_widget.dart';
|
||||
@@ -414,34 +415,20 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
() {
|
||||
final list = videoDetailController.dmTrend.value?.dataOrNull;
|
||||
if (list != null && list.isNotEmpty) {
|
||||
final show = videoDetailController.showDmTrendChart.value;
|
||||
return ComBtn(
|
||||
width: widgetWidth,
|
||||
height: 30,
|
||||
tooltip: '高能进度条',
|
||||
icon: videoDetailController.showDmTrendChart.value
|
||||
? const Icon(
|
||||
Icons.show_chart,
|
||||
size: 22,
|
||||
color: Colors.white,
|
||||
)
|
||||
: const Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.show_chart,
|
||||
size: 22,
|
||||
color: Colors.white,
|
||||
),
|
||||
Icon(
|
||||
Icons.hide_source,
|
||||
size: 22,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () => videoDetailController.showDmTrendChart.value =
|
||||
!videoDetailController.showDmTrendChart.value,
|
||||
icon: DisabledIcon(
|
||||
disable: !show,
|
||||
child: const Icon(
|
||||
Icons.show_chart,
|
||||
size: 22,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
onTap: () => videoDetailController.showDmTrendChart.value = !show,
|
||||
);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
@@ -450,64 +437,76 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
|
||||
/// 超分辨率
|
||||
BottomControlType.superResolution => Obx(
|
||||
() => PopupMenuButton<SuperResolutionType>(
|
||||
tooltip: '超分辨率',
|
||||
requestFocus: false,
|
||||
initialValue: plPlayerController.superResolutionType.value,
|
||||
color: Colors.black.withValues(alpha: 0.8),
|
||||
itemBuilder: (context) {
|
||||
return SuperResolutionType.values
|
||||
.map(
|
||||
(type) => PopupMenuItem<SuperResolutionType>(
|
||||
height: 35,
|
||||
padding: const EdgeInsets.only(left: 30),
|
||||
value: type,
|
||||
onTap: () => plPlayerController.setShader(type),
|
||||
child: Text(
|
||||
type.title,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||
() {
|
||||
final type = plPlayerController.superResolutionType.value;
|
||||
return PopupMenuButton<SuperResolutionType>(
|
||||
tooltip: '超分辨率',
|
||||
requestFocus: false,
|
||||
initialValue: type,
|
||||
color: Colors.black.withValues(alpha: 0.8),
|
||||
itemBuilder: (context) {
|
||||
return SuperResolutionType.values
|
||||
.map(
|
||||
(type) => PopupMenuItem<SuperResolutionType>(
|
||||
height: 35,
|
||||
padding: const EdgeInsets.only(left: 30),
|
||||
value: type,
|
||||
onTap: () => plPlayerController.setShader(type),
|
||||
child: Text(
|
||||
type.title,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
plPlayerController.superResolutionType.value.title,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||
)
|
||||
.toList();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
type.title,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
/// 分段信息
|
||||
BottomControlType.viewPoints => Obx(
|
||||
() => videoDetailController.viewPointList.isEmpty
|
||||
? const SizedBox.shrink()
|
||||
: ComBtn(
|
||||
width: widgetWidth,
|
||||
height: 30,
|
||||
tooltip: '分段信息',
|
||||
icon: Transform.rotate(
|
||||
() {
|
||||
if (videoDetailController.viewPointList.isNotEmpty) {
|
||||
final show = videoDetailController.showVP.value;
|
||||
return ComBtn(
|
||||
width: widgetWidth,
|
||||
height: 30,
|
||||
tooltip: '分段信息',
|
||||
icon: DisabledIcon(
|
||||
iconSize: 22,
|
||||
disable: !show,
|
||||
child: Transform.rotate(
|
||||
angle: math.pi / 2,
|
||||
child: const Icon(
|
||||
MdiIcons.viewHeadline,
|
||||
Icons.reorder,
|
||||
size: 22,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
onTap: widget.showViewPoints,
|
||||
onLongPress: () {
|
||||
Feedback.forLongPress(context);
|
||||
videoDetailController.showVP.value =
|
||||
!videoDetailController.showVP.value;
|
||||
},
|
||||
onSecondaryTap: PlatformUtils.isMobile
|
||||
? null
|
||||
: () => videoDetailController.showVP.value =
|
||||
!videoDetailController.showVP.value,
|
||||
),
|
||||
onTap: widget.showViewPoints,
|
||||
onLongPress: () {
|
||||
Feedback.forLongPress(context);
|
||||
videoDetailController.showVP.value = !show;
|
||||
},
|
||||
onSecondaryTap: PlatformUtils.isMobile
|
||||
? null
|
||||
: () => videoDetailController.showVP.value = !show,
|
||||
);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
),
|
||||
|
||||
/// 选集
|
||||
@@ -567,35 +566,41 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
|
||||
/// 画面比例
|
||||
BottomControlType.fit => Obx(
|
||||
() => PopupMenuButton<VideoFitType>(
|
||||
tooltip: '画面比例',
|
||||
requestFocus: false,
|
||||
initialValue: plPlayerController.videoFit.value,
|
||||
color: Colors.black.withValues(alpha: 0.8),
|
||||
itemBuilder: (context) {
|
||||
return VideoFitType.values
|
||||
.map(
|
||||
(boxFit) => PopupMenuItem<VideoFitType>(
|
||||
height: 35,
|
||||
padding: const EdgeInsets.only(left: 30),
|
||||
value: boxFit,
|
||||
onTap: () => plPlayerController.toggleVideoFit(boxFit),
|
||||
child: Text(
|
||||
boxFit.desc,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||
() {
|
||||
final fit = plPlayerController.videoFit.value;
|
||||
return PopupMenuButton<VideoFitType>(
|
||||
tooltip: '画面比例',
|
||||
requestFocus: false,
|
||||
initialValue: fit,
|
||||
color: Colors.black.withValues(alpha: 0.8),
|
||||
itemBuilder: (context) {
|
||||
return VideoFitType.values
|
||||
.map(
|
||||
(boxFit) => PopupMenuItem<VideoFitType>(
|
||||
height: 35,
|
||||
padding: const EdgeInsets.only(left: 30),
|
||||
value: boxFit,
|
||||
onTap: () => plPlayerController.toggleVideoFit(boxFit),
|
||||
child: Text(
|
||||
boxFit.desc,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
plPlayerController.videoFit.value.desc,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||
)
|
||||
.toList();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
fit.desc,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
BottomControlType.aiTranslate => Obx(
|
||||
@@ -654,66 +659,65 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
|
||||
/// 字幕
|
||||
BottomControlType.subtitle => Obx(
|
||||
() => videoDetailController.subtitles.isEmpty
|
||||
? const SizedBox.shrink()
|
||||
: PopupMenuButton<int>(
|
||||
tooltip: '字幕',
|
||||
requestFocus: false,
|
||||
initialValue: videoDetailController.vttSubtitlesIndex.value
|
||||
.clamp(
|
||||
0,
|
||||
videoDetailController.subtitles.length,
|
||||
() {
|
||||
if (videoDetailController.subtitles.isNotEmpty) {
|
||||
final val = videoDetailController.vttSubtitlesIndex.value;
|
||||
return PopupMenuButton<int>(
|
||||
tooltip: '字幕',
|
||||
requestFocus: false,
|
||||
initialValue: val,
|
||||
color: Colors.black.withValues(alpha: 0.8),
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
PopupMenuItem<int>(
|
||||
value: 0,
|
||||
height: 35,
|
||||
onTap: () => videoDetailController.setSubtitle(0),
|
||||
child: const Text(
|
||||
"关闭字幕",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
color: Colors.black.withValues(alpha: 0.8),
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
PopupMenuItem<int>(
|
||||
value: 0,
|
||||
),
|
||||
...videoDetailController.subtitles.indexed.map((e) {
|
||||
return PopupMenuItem<int>(
|
||||
value: e.$1 + 1,
|
||||
height: 35,
|
||||
onTap: () => videoDetailController.setSubtitle(0),
|
||||
child: const Text(
|
||||
"关闭字幕",
|
||||
style: TextStyle(
|
||||
onTap: () => videoDetailController.setSubtitle(e.$1 + 1),
|
||||
child: Text(
|
||||
"${e.$2.lanDoc}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
),
|
||||
...videoDetailController.subtitles.indexed.map((e) {
|
||||
return PopupMenuItem<int>(
|
||||
value: e.$1 + 1,
|
||||
height: 35,
|
||||
onTap: () =>
|
||||
videoDetailController.setSubtitle(e.$1 + 1),
|
||||
child: Text(
|
||||
"${e.$2.lanDoc}",
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
];
|
||||
},
|
||||
child: SizedBox(
|
||||
width: widgetWidth,
|
||||
height: 30,
|
||||
child: videoDetailController.vttSubtitlesIndex.value == 0
|
||||
? const Icon(
|
||||
Icons.closed_caption_off_outlined,
|
||||
size: 22,
|
||||
color: Colors.white,
|
||||
)
|
||||
: const Icon(
|
||||
Icons.closed_caption_off_rounded,
|
||||
size: 22,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
];
|
||||
},
|
||||
child: SizedBox(
|
||||
width: widgetWidth,
|
||||
height: 30,
|
||||
child: val == 0
|
||||
? const Icon(
|
||||
Icons.closed_caption_off_outlined,
|
||||
size: 22,
|
||||
color: Colors.white,
|
||||
)
|
||||
: const Icon(
|
||||
Icons.closed_caption_off_rounded,
|
||||
size: 22,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
),
|
||||
|
||||
/// 播放速度
|
||||
@@ -1701,15 +1705,12 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 255),
|
||||
);
|
||||
final anim =
|
||||
Matrix4Tween(
|
||||
begin: transformationController.value,
|
||||
end: Matrix4.identity(),
|
||||
).animate(
|
||||
CurveTween(
|
||||
curve: Curves.easeOut,
|
||||
).animate(animController),
|
||||
);
|
||||
final anim = animController.drive(
|
||||
Matrix4Tween(
|
||||
begin: transformationController.value,
|
||||
end: Matrix4.identity(),
|
||||
).chain(CurveTween(curve: Curves.easeOut)),
|
||||
);
|
||||
void listener() {
|
||||
transformationController.value = anim.value;
|
||||
}
|
||||
@@ -2748,17 +2749,20 @@ class _DanmakuTip extends SingleChildRenderObjectWidget {
|
||||
|
||||
@override
|
||||
RenderObject createRenderObject(BuildContext context) {
|
||||
return RenderDanmakuTip(offset: offset);
|
||||
return _RenderDanmakuTip(offset: offset);
|
||||
}
|
||||
|
||||
@override
|
||||
void updateRenderObject(BuildContext context, RenderDanmakuTip renderObject) {
|
||||
void updateRenderObject(
|
||||
BuildContext context,
|
||||
_RenderDanmakuTip renderObject,
|
||||
) {
|
||||
renderObject.offset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
class RenderDanmakuTip extends RenderProxyBox {
|
||||
RenderDanmakuTip({
|
||||
class _RenderDanmakuTip extends RenderProxyBox {
|
||||
_RenderDanmakuTip({
|
||||
required double offset,
|
||||
}) : _offset = offset;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class AppBarAni extends StatelessWidget {
|
||||
final bool isFullScreen;
|
||||
|
||||
static final _topPos = Tween<Offset>(
|
||||
begin: const Offset(0, -1),
|
||||
begin: const Offset(0.0, -1.0),
|
||||
end: Offset.zero,
|
||||
);
|
||||
|
||||
@@ -49,8 +49,8 @@ class AppBarAni extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return SlideTransition(
|
||||
position: isTop
|
||||
? _topPos.animate(controller)
|
||||
: _bottomPos.animate(controller),
|
||||
? controller.drive(_topPos)
|
||||
: controller.drive(_bottomPos),
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: isTop ? _topDecoration : _bottomDecoration,
|
||||
|
||||
@@ -699,7 +699,7 @@ abstract final class PageUtils {
|
||||
: const Offset(1.0, 0.0);
|
||||
return SlideTransition(
|
||||
position: animation.drive(
|
||||
Tween(
|
||||
Tween<Offset>(
|
||||
begin: begin,
|
||||
end: Offset.zero,
|
||||
).chain(CurveTween(curve: Curves.easeInOut)),
|
||||
|
||||
@@ -528,8 +528,8 @@ abstract final class RequestUtils {
|
||||
token: captchaData.token,
|
||||
validate: captchaData.validate,
|
||||
);
|
||||
if (res case Success(:final response)) {
|
||||
if (response != null && response['is_valid'] == 1) {
|
||||
if (res case Success(:final response?)) {
|
||||
if (response['is_valid'] == 1) {
|
||||
final griskId = response['grisk_id'];
|
||||
if (griskId is String) {
|
||||
onSuccess(griskId);
|
||||
|
||||
Reference in New Issue
Block a user