diff --git a/lib/common/widgets/custom_height_widget.dart b/lib/common/widgets/custom_height_widget.dart index f94655209..6d14c357b 100644 --- a/lib/common/widgets/custom_height_widget.dart +++ b/lib/common/widgets/custom_height_widget.dart @@ -57,7 +57,7 @@ class RenderCustomHeightWidget extends RenderProxyBox { @override void performLayout() { - child!.layout(constraints, parentUsesSize: true); + child!.layout(constraints); size = constraints.constrainDimensions(constraints.maxWidth, height); } diff --git a/lib/common/widgets/image/custom_grid_view.dart b/lib/common/widgets/image/custom_grid_view.dart index 3099bd194..d4c74c4bd 100644 --- a/lib/common/widgets/image/custom_grid_view.dart +++ b/lib/common/widgets/image/custom_grid_view.dart @@ -415,7 +415,7 @@ class RenderImageGrid extends RenderBox while (child != null) { final childParentData = child.parentData as MultiChildLayoutParentData; final index = childParentData.id as int; - child.layout(itemConstraints, parentUsesSize: true); + child.layout(itemConstraints); childParentData.offset = Offset( (space + width) * (index % column), (space + height) * (index ~/ column), diff --git a/lib/common/widgets/player_bar.dart b/lib/common/widgets/player_bar.dart new file mode 100644 index 000000000..29403e61c --- /dev/null +++ b/lib/common/widgets/player_bar.dart @@ -0,0 +1,133 @@ +/* + * 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 . + */ + +import 'dart:math' as math; + +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart' + show + ContainerRenderObjectMixin, + MultiChildLayoutParentData, + RenderBoxContainerDefaultsMixin, + BoxHitTestResult; + +class PlayerBar extends MultiChildRenderObjectWidget { + const PlayerBar({ + super.key, + super.children, + }); + + @override + RenderObject createRenderObject(BuildContext context) { + return RenderBottomBar(); + } +} + +class RenderBottomBar extends RenderBox + with + ContainerRenderObjectMixin, + RenderBoxContainerDefaultsMixin { + @override + void setupParentData(RenderBox child) { + if (child.parentData is! MultiChildLayoutParentData) { + child.parentData = MultiChildLayoutParentData(); + } + } + + Matrix4? _transform; + + @override + void performLayout() { + _transform = null; + + final c = constraints.copyWith(maxWidth: .infinity); + final RenderBox first = firstChild!..layout(c, parentUsesSize: true); + final RenderBox last = lastChild!..layout(c, parentUsesSize: true); + + final firstSize = first.size; + final lastSize = last.size; + + final firstParentData = first.parentData as MultiChildLayoutParentData; + final lastParentData = last.parentData as MultiChildLayoutParentData; + + final firstWidth = firstSize.width; + final lastWidth = lastSize.width; + final totalWidth = firstWidth + lastWidth; + final maxWidth = constraints.maxWidth; + final height = math.max(firstSize.height, lastSize.height); + size = constraints.constrainDimensions(maxWidth, height); + + firstParentData.offset = Offset(0.0, (height - firstSize.height) / 2); + if (totalWidth <= maxWidth) { + lastParentData.offset = Offset( + maxWidth - lastWidth, + (height - lastSize.height) / 2, + ); + } else { + final scale = maxWidth / totalWidth; + _transform = Matrix4.identity() + ..translateByDouble(0.0, height * (1 - scale) / 2, 0.0, 1.0) + ..scaleByDouble(scale, scale, scale, 1.0); + lastParentData.offset = Offset( + (maxWidth - lastWidth * scale) / scale, + (height - lastSize.height) / 2, + ); + } + } + + void _paintChild(PaintingContext context, Offset offset) { + RenderBox? child = firstChild; + while (child != null) { + final childParentData = child.parentData as MultiChildLayoutParentData; + context.paintChild(child, childParentData.offset + offset); + child = childParentData.nextSibling; + } + } + + @override + void paint(PaintingContext context, Offset offset) { + if (_transform != null) { + context.pushTransform(needsCompositing, offset, _transform!, _paintChild); + } else { + _paintChild(context, offset); + } + } + + @override + bool hitTestChildren(BoxHitTestResult result, {required Offset position}) { + return result.addWithPaintTransform( + transform: _transform, + position: position, + hitTest: (BoxHitTestResult result, Offset position) { + return defaultHitTestChildren(result, position: position); + }, + ); + } + + @override + void applyPaintTransform(RenderBox child, Matrix4 transform) { + final childParentData = child.parentData! as MultiChildLayoutParentData; + final Offset offset = childParentData.offset; + if (_transform != null) { + transform + ..translateByDouble(offset.dx * _transform!.storage[0], offset.dy, 0, 1) + ..multiply(_transform!); + } else { + transform.translateByDouble(offset.dx, offset.dy, 0, 1); + } + } +} diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index fe60bbbe4..a23a3f51d 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -11,6 +11,7 @@ import 'package:PiliPlus/common/widgets/gesture/immediate_tap_gesture_recognizer import 'package:PiliPlus/common/widgets/gesture/mouse_interactive_viewer.dart'; import 'package:PiliPlus/common/widgets/loading_widget.dart'; import 'package:PiliPlus/common/widgets/pair.dart'; +import 'package:PiliPlus/common/widgets/player_bar.dart'; import 'package:PiliPlus/common/widgets/progress_bar/audio_video_progress_bar.dart'; import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart'; import 'package:PiliPlus/common/widgets/view_safe_area.dart'; @@ -874,22 +875,15 @@ class _PLVideoPlayerState extends State if (isNotFileSource && flag) BottomControlType.qa, if (!plPlayerController.isDesktopPip) BottomControlType.fullscreen, ]; - - return Row( + return PlayerBar( children: [ - ...userSpecifyItemLeft.map(progressWidget), - Expanded( - child: LayoutBuilder( - builder: (context, constraints) => FittedBox( - child: ConstrainedBox( - constraints: BoxConstraints(minWidth: constraints.maxWidth), - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: userSpecifyItemRight.map(progressWidget).toList(), - ), - ), - ), - ), + Row( + mainAxisSize: .min, + children: userSpecifyItemLeft.map(progressWidget).toList(), + ), + Row( + mainAxisSize: .min, + children: userSpecifyItemRight.map(progressWidget).toList(), ), ], ); @@ -2868,7 +2862,7 @@ class _RenderVideoTime extends RenderBox { ) ..addText(time); return builder.build() - ..layout(ui.ParagraphConstraints(width: constraints.maxWidth)); + ..layout(const ui.ParagraphConstraints(width: .infinity)); } @override