mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-10 21:11:27 +08:00
opt: RepaintBoundary (#1840)
* opt: RepaintBoundary * fix [skip ci] * opt time width * opt: video position * update --------- Co-authored-by: dom <githubaccount56556@proton.me>
This commit is contained in:
committed by
GitHub
parent
a63ca93762
commit
d7d9655f81
@@ -65,7 +65,4 @@ class RenderCustomHeightWidget extends RenderProxyBox {
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
context.paintChild(child!, offset + _offset);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
}
|
||||
|
||||
@@ -95,7 +95,4 @@ class _RenderDecoratedBox extends RenderProxyBox {
|
||||
|
||||
@override
|
||||
bool hitTestSelf(Offset position) => true;
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
}
|
||||
|
||||
@@ -259,9 +259,6 @@ class _RenderToolTip extends RenderBox
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
}
|
||||
|
||||
class Triangle extends LeafRenderObjectWidget {
|
||||
@@ -328,14 +325,11 @@ class RenderTriangle extends RenderBox {
|
||||
..style = PaintingStyle.fill;
|
||||
|
||||
final path = Path()
|
||||
..moveTo(0, 0)
|
||||
..lineTo(size.width, 0)
|
||||
..lineTo(size.width / 2, size.height)
|
||||
..moveTo(offset.dx, offset.dy)
|
||||
..lineTo(offset.dx + size.width, offset.dy)
|
||||
..lineTo(offset.dx + size.width / 2, size.height + offset.dy)
|
||||
..close();
|
||||
|
||||
context.canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@ class RenderMaskedIcon extends RenderProxyBox {
|
||||
|
||||
final canvas = context.canvas;
|
||||
|
||||
var rectOffset = offset;
|
||||
Size size = this.size;
|
||||
final exceedWidth = size.width > _iconSize;
|
||||
final exceedHeight = size.height > _iconSize;
|
||||
@@ -128,14 +129,14 @@ class RenderMaskedIcon extends RenderProxyBox {
|
||||
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);
|
||||
rectOffset += Offset(dx, dy);
|
||||
} else if (size.width < _iconSize && size.height < _iconSize) {
|
||||
size = Size.square(_iconSize);
|
||||
}
|
||||
|
||||
final strokeWidth = size.width / 12;
|
||||
|
||||
var rect = offset & size;
|
||||
var rect = rectOffset & size;
|
||||
|
||||
final sqrt2Width = strokeWidth * sqrt2; // rotate pi / 4
|
||||
|
||||
@@ -155,7 +156,7 @@ class RenderMaskedIcon extends RenderProxyBox {
|
||||
canvas
|
||||
..save()
|
||||
..clipPath(path, doAntiAlias: false);
|
||||
super.paint(context, .zero);
|
||||
super.paint(context, offset);
|
||||
|
||||
canvas.restore();
|
||||
|
||||
@@ -174,7 +175,4 @@ class RenderMaskedIcon extends RenderProxyBox {
|
||||
linePaint,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
}
|
||||
|
||||
@@ -440,5 +440,5 @@ class RenderImageGrid extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
bool get isRepaintBoundary => true; // gif repaint
|
||||
}
|
||||
|
||||
@@ -226,13 +226,14 @@ abstract class MarqueeRender extends RenderBox
|
||||
if (_distance > 0) {
|
||||
updateSize();
|
||||
_ticker.initIfNeeded(_onTick);
|
||||
markNeedsCompositingBitsUpdate();
|
||||
} else {
|
||||
_ticker.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
bool get isRepaintBoundary => _ticker._ticker != null;
|
||||
|
||||
void paintCenter(PaintingContext context, Offset offset) {
|
||||
if (_direction == Axis.horizontal) {
|
||||
|
||||
@@ -123,17 +123,17 @@ class RenderProgressBar extends BaseRenderProgressBar<Segment> {
|
||||
|
||||
for (final segment in segments) {
|
||||
paint.color = segment.color;
|
||||
final segmentStart = segment.start * size.width;
|
||||
final segmentEnd = segment.end * size.width;
|
||||
final segmentStart = offset.dx + segment.start * size.width;
|
||||
final segmentEnd = offset.dx + segment.end * size.width;
|
||||
|
||||
if (segmentEnd > segmentStart ||
|
||||
(segmentEnd == segmentStart && segmentStart > 0)) {
|
||||
canvas.drawRect(
|
||||
Rect.fromLTRB(
|
||||
segmentStart,
|
||||
0,
|
||||
offset.dy,
|
||||
segmentEnd == segmentStart ? segmentStart + 2 : segmentEnd,
|
||||
size.height,
|
||||
size.height + offset.dy,
|
||||
),
|
||||
paint,
|
||||
);
|
||||
@@ -225,6 +225,12 @@ class RenderViewPointProgressBar
|
||||
final canvas = context.canvas;
|
||||
final paint = Paint()..style = PaintingStyle.fill;
|
||||
|
||||
if (offset != .zero) {
|
||||
canvas
|
||||
..save()
|
||||
..translate(offset.dx, offset.dy);
|
||||
}
|
||||
|
||||
assert(segments.isSortedBy((i) => i.end));
|
||||
|
||||
canvas.drawRect(
|
||||
@@ -276,6 +282,7 @@ class RenderViewPointProgressBar
|
||||
}
|
||||
prevEnd = segmentEnd + _dividerWidth;
|
||||
}
|
||||
if (offset != .zero) canvas.restore();
|
||||
}
|
||||
|
||||
ValueSetter<Duration>? _onSeek;
|
||||
@@ -371,7 +378,4 @@ class BaseRenderProgressBar<T extends BaseSegment> extends RenderBox {
|
||||
void performLayout() {
|
||||
size = constraints.constrainDimensions(constraints.maxWidth, height);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,9 @@ class RenderProgressBar extends RenderBox {
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
final size = this.size;
|
||||
final canvas = context.canvas;
|
||||
final canvas = context.canvas
|
||||
..save()
|
||||
..translate(offset.dx, offset.dy);
|
||||
final paint = Paint()..style = .fill;
|
||||
|
||||
canvas.clipRect(
|
||||
@@ -147,8 +149,6 @@ class RenderProgressBar extends RenderBox {
|
||||
..drawRect(left, paint..color = _color)
|
||||
..drawRect(right, paint..color = _backgroundColor);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
}
|
||||
|
||||
@@ -997,12 +997,15 @@ class _RenderBorderIndicator extends RenderBox {
|
||||
final size = this.size;
|
||||
final canvas = context.canvas;
|
||||
final width = size.width / 2;
|
||||
if (!_isLeft) {
|
||||
canvas.translate(width, 0);
|
||||
}
|
||||
|
||||
BoxBorder.paintNonUniformBorder(
|
||||
canvas,
|
||||
Rect.fromLTRB(0, 0, width, size.height),
|
||||
Rect.fromLTWH(
|
||||
offset.dx + (_isLeft ? 0 : width),
|
||||
offset.dy,
|
||||
width,
|
||||
size.height,
|
||||
),
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: _isLeft ? _radius : .zero,
|
||||
topRight: _isLeft ? .zero : _radius,
|
||||
@@ -1012,9 +1015,6 @@ class _RenderBorderIndicator extends RenderBox {
|
||||
color: Colors.white38,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
}
|
||||
|
||||
class LiveDanmaku extends StatefulWidget {
|
||||
|
||||
@@ -66,22 +66,25 @@ class ActionItem extends StatelessWidget {
|
||||
child = SizedBox.square(dimension: 28, child: child);
|
||||
}
|
||||
|
||||
child = InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
onTap: _isThumbsUp ? null : onTap,
|
||||
onLongPress: _isThumbsUp ? null : onLongPress,
|
||||
onSecondaryTap: PlatformUtils.isMobile || _isThumbsUp
|
||||
? null
|
||||
: onLongPress,
|
||||
onTapDown: _isThumbsUp ? (_) => onStartTriple!() : null,
|
||||
onTapUp: _isThumbsUp ? (_) => onCancelTriple!(true) : null,
|
||||
onTapCancel: _isThumbsUp ? onCancelTriple : null,
|
||||
child: expand
|
||||
? Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [child, _buildText(theme)],
|
||||
)
|
||||
: child,
|
||||
child = Material(
|
||||
type: .transparency,
|
||||
child: InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
onTap: _isThumbsUp ? null : onTap,
|
||||
onLongPress: _isThumbsUp ? null : onLongPress,
|
||||
onSecondaryTap: PlatformUtils.isMobile || _isThumbsUp
|
||||
? null
|
||||
: onLongPress,
|
||||
onTapDown: _isThumbsUp ? (_) => onStartTriple!() : null,
|
||||
onTapUp: _isThumbsUp ? (_) => onCancelTriple!(true) : null,
|
||||
onTapCancel: _isThumbsUp ? onCancelTriple : null,
|
||||
child: expand
|
||||
? Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [child, _buildText(theme)],
|
||||
)
|
||||
: child,
|
||||
),
|
||||
);
|
||||
return expand ? Expanded(child: child) : child;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,8 @@ import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart' show RenderProxyBox;
|
||||
import 'package:flutter/rendering.dart'
|
||||
show RenderProxyBox, SemanticsConfiguration;
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
@@ -379,38 +380,15 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
),
|
||||
|
||||
/// 时间进度
|
||||
BottomControlType.time => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
// 播放时间
|
||||
Obx(
|
||||
() => Text(
|
||||
DurationUtils.formatDuration(
|
||||
plPlayerController.positionSeconds.value,
|
||||
),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 10,
|
||||
height: 1.4,
|
||||
fontFeatures: [FontFeature.tabularFigures()],
|
||||
),
|
||||
),
|
||||
BottomControlType.time => Obx(
|
||||
() => _VideoTime(
|
||||
position: DurationUtils.formatDuration(
|
||||
plPlayerController.positionSeconds.value,
|
||||
),
|
||||
Obx(
|
||||
() => Text(
|
||||
DurationUtils.formatDuration(
|
||||
plPlayerController.duration.value.inSeconds,
|
||||
),
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFD0D0D0),
|
||||
fontSize: 10,
|
||||
height: 1.4,
|
||||
fontFeatures: [FontFeature.tabularFigures()],
|
||||
),
|
||||
),
|
||||
duration: DurationUtils.formatDuration(
|
||||
plPlayerController.duration.value.inSeconds,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
/// 高能进度条
|
||||
@@ -1617,39 +1595,41 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
top: -1,
|
||||
bottom: -1,
|
||||
child: ClipRect(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
AppBarAni(
|
||||
isTop: true,
|
||||
controller: animationController,
|
||||
isFullScreen: isFullScreen,
|
||||
child: plPlayerController.isDesktopPip
|
||||
? GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onPanStart: (_) => windowManager.startDragging(),
|
||||
child: widget.headerControl,
|
||||
)
|
||||
: widget.headerControl,
|
||||
),
|
||||
AppBarAni(
|
||||
isTop: false,
|
||||
controller: animationController,
|
||||
isFullScreen: isFullScreen,
|
||||
child:
|
||||
widget.bottomControl ??
|
||||
BottomControl(
|
||||
maxWidth: maxWidth,
|
||||
isFullScreen: isFullScreen,
|
||||
controller: plPlayerController,
|
||||
videoDetailController: videoDetailController,
|
||||
buildBottomControl: () => buildBottomControl(
|
||||
videoDetailController,
|
||||
maxWidth > maxHeight,
|
||||
child: RepaintBoundary(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
AppBarAni(
|
||||
isTop: true,
|
||||
controller: animationController,
|
||||
isFullScreen: isFullScreen,
|
||||
child: plPlayerController.isDesktopPip
|
||||
? GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onPanStart: (_) => windowManager.startDragging(),
|
||||
child: widget.headerControl,
|
||||
)
|
||||
: widget.headerControl,
|
||||
),
|
||||
AppBarAni(
|
||||
isTop: false,
|
||||
controller: animationController,
|
||||
isFullScreen: isFullScreen,
|
||||
child:
|
||||
widget.bottomControl ??
|
||||
BottomControl(
|
||||
maxWidth: maxWidth,
|
||||
isFullScreen: isFullScreen,
|
||||
controller: plPlayerController,
|
||||
videoDetailController: videoDetailController,
|
||||
buildBottomControl: () => buildBottomControl(
|
||||
videoDetailController,
|
||||
maxWidth > maxHeight,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -2767,12 +2747,7 @@ class _RenderDanmakuTip extends RenderProxyBox {
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
final paint = Paint()
|
||||
..color = const Color(0xB3000000)
|
||||
..style = PaintingStyle.fill;
|
||||
|
||||
final strokePaint = Paint()
|
||||
..color = const Color(0x7EFFFFFF)
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1.25;
|
||||
..style = .fill;
|
||||
|
||||
final radius = size.height / 2;
|
||||
const triangleBase = _triangleHeight * 2 / 3;
|
||||
@@ -2803,11 +2778,140 @@ class _RenderDanmakuTip extends RenderProxyBox {
|
||||
..close();
|
||||
|
||||
context.canvas
|
||||
..save()
|
||||
..translate(offset.dx, offset.dy)
|
||||
..drawPath(path, paint)
|
||||
..drawPath(path, strokePaint);
|
||||
..drawPath(
|
||||
path,
|
||||
paint
|
||||
..color = const Color(0x7EFFFFFF)
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 1.25,
|
||||
)
|
||||
..restore();
|
||||
|
||||
super.paint(context, offset);
|
||||
}
|
||||
}
|
||||
|
||||
class _VideoTime extends LeafRenderObjectWidget {
|
||||
const _VideoTime({
|
||||
required this.position,
|
||||
required this.duration,
|
||||
});
|
||||
|
||||
final String position;
|
||||
final String duration;
|
||||
|
||||
@override
|
||||
_RenderVideoTime createRenderObject(BuildContext context) => _RenderVideoTime(
|
||||
position: position,
|
||||
duration: duration,
|
||||
);
|
||||
|
||||
@override
|
||||
void updateRenderObject(
|
||||
BuildContext context,
|
||||
covariant _RenderVideoTime renderObject,
|
||||
) {
|
||||
renderObject
|
||||
..position = position
|
||||
..duration = duration;
|
||||
}
|
||||
}
|
||||
|
||||
class _RenderVideoTime extends RenderBox {
|
||||
_RenderVideoTime({
|
||||
required String position,
|
||||
required String duration,
|
||||
}) : _position = position,
|
||||
_duration = duration;
|
||||
|
||||
String _duration;
|
||||
set duration(String value) {
|
||||
_duration = value;
|
||||
final paragraph = _buildParagraph(const Color(0xFFD0D0D0), _duration);
|
||||
if (paragraph.maxIntrinsicWidth != _cache?.maxIntrinsicWidth) {
|
||||
markNeedsLayout();
|
||||
}
|
||||
_cache?.dispose();
|
||||
_cache = paragraph;
|
||||
markNeedsSemanticsUpdate();
|
||||
}
|
||||
|
||||
String _position;
|
||||
set position(String value) {
|
||||
_position = value;
|
||||
markNeedsPaint();
|
||||
markNeedsSemanticsUpdate();
|
||||
}
|
||||
|
||||
ui.Paragraph? _cache;
|
||||
|
||||
ui.Paragraph _buildParagraph(Color color, String time) {
|
||||
final builder =
|
||||
ui.ParagraphBuilder(
|
||||
ui.ParagraphStyle(
|
||||
fontSize: 10,
|
||||
height: 1.4,
|
||||
fontFamily: 'Monospace',
|
||||
),
|
||||
)
|
||||
..pushStyle(
|
||||
ui.TextStyle(
|
||||
color: color,
|
||||
fontSize: 10,
|
||||
height: 1.4,
|
||||
fontFamily: 'Monospace',
|
||||
fontFeatures: const [FontFeature.tabularFigures()],
|
||||
),
|
||||
)
|
||||
..addText(time);
|
||||
return builder.build()
|
||||
..layout(ui.ParagraphConstraints(width: constraints.maxWidth));
|
||||
}
|
||||
|
||||
@override
|
||||
ui.Size computeDryLayout(covariant BoxConstraints constraints) {
|
||||
final paragraph = _cache ??= _buildParagraph(
|
||||
const Color(0xFFD0D0D0),
|
||||
_duration,
|
||||
);
|
||||
return Size(paragraph.maxIntrinsicWidth, paragraph.height * 2);
|
||||
}
|
||||
|
||||
@override
|
||||
void describeSemanticsConfiguration(SemanticsConfiguration config) {
|
||||
super.describeSemanticsConfiguration(config);
|
||||
config.label = 'position:$_position\nduration:$_duration';
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = computeDryLayout(constraints);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, ui.Offset offset) {
|
||||
final para = _buildParagraph(Colors.white, _position);
|
||||
context.canvas
|
||||
..drawParagraph(
|
||||
para,
|
||||
Offset(
|
||||
offset.dx + _cache!.maxIntrinsicWidth - para.maxIntrinsicWidth,
|
||||
offset.dy,
|
||||
),
|
||||
)
|
||||
..drawParagraph(_cache!, Offset(offset.dx, offset.dy + para.height));
|
||||
para.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_cache?.dispose();
|
||||
_cache = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRepaintBoundary => true;
|
||||
|
||||
@@ -105,7 +105,7 @@ class MpvConvertWebp {
|
||||
final text = log.text.toDartString().trim();
|
||||
debugPrint('WebpConvert: $level $prefix : $text');
|
||||
if (kDebugMode) {
|
||||
_success = level != 'error' && level != 'fatal';
|
||||
if (level == 'error' || level == 'fatal') _success = false;
|
||||
} else {
|
||||
_success = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user