mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
* opt: cache * opt: MediaListPanel * feat: nested replyreply panel * tweaks * opt: abstract class * opt: PageStorageKey * opt: contextExt * opt: EpisodePanel * opt * opt: context instead GlobalKey * feat: jump to reply * refa: reply_reply * fix: jump * fix: index * update Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me> * opt: keepalive * reapply: nested replyreply * mod: spacing * opt: CommonSlidePageState * fix drag bottomsheet Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me> * opt reply jump Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me> * opt reply2reply Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me> * tweaks Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me> * tweaks Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me> * reapply: jumpToReply * fix: padding * fix: anim * fix some panels Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me> * opt: implements Scaffold * opt: remove keepalive * revert: GlobalKey * tweaks Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me> --------- Co-authored-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
140 lines
5.0 KiB
Dart
140 lines
5.0 KiB
Dart
import 'dart:math';
|
|
|
|
import 'package:PiliPlus/common/constants.dart';
|
|
import 'package:PiliPlus/common/skeleton/video_card_h.dart';
|
|
import 'package:PiliPlus/utils/storage_pref.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
|
|
mixin GridMixin<T extends StatefulWidget> on State<T> {
|
|
late final gridDelegate = Grid.videoCardHDelegate(context);
|
|
|
|
Widget get gridSkeleton => SliverGrid.builder(
|
|
gridDelegate: gridDelegate,
|
|
itemBuilder: (_, _) => const VideoCardHSkeleton(),
|
|
itemCount: 10,
|
|
);
|
|
}
|
|
|
|
abstract class Grid {
|
|
static final double smallCardWidth = Pref.smallCardWidth;
|
|
|
|
static SliverGridDelegateWithExtentAndRatio videoCardHDelegate(
|
|
BuildContext context, {
|
|
double minHeight = 90,
|
|
}) => SliverGridDelegateWithExtentAndRatio(
|
|
mainAxisSpacing: 2,
|
|
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
|
childAspectRatio: StyleString.aspectRatio * 2.2,
|
|
minHeight: MediaQuery.textScalerOf(context).scale(minHeight),
|
|
);
|
|
}
|
|
|
|
class SliverGridDelegateWithExtentAndRatio extends SliverGridDelegate {
|
|
/// Creates a delegate that makes grid layouts with tiles that have a maximum
|
|
/// cross-axis extent.
|
|
///
|
|
/// The [maxCrossAxisExtent], [mainAxisExtent], [mainAxisSpacing],
|
|
/// and [crossAxisSpacing] arguments must not be negative.
|
|
/// The [childAspectRatio] argument must be greater than zero.
|
|
SliverGridDelegateWithExtentAndRatio({
|
|
required this.maxCrossAxisExtent,
|
|
this.mainAxisSpacing = 0.0,
|
|
this.crossAxisSpacing = 0.0,
|
|
this.childAspectRatio = 1.0,
|
|
this.mainAxisExtent = 0.0,
|
|
this.minHeight = 0.0,
|
|
}) : assert(maxCrossAxisExtent > 0),
|
|
assert(mainAxisSpacing >= 0),
|
|
assert(crossAxisSpacing >= 0),
|
|
assert(childAspectRatio > 0),
|
|
assert(minHeight >= 0);
|
|
|
|
final double minHeight;
|
|
|
|
/// The maximum extent of tiles in the cross axis.
|
|
///
|
|
/// This delegate will select a cross-axis extent for the tiles that is as
|
|
/// large as possible subject to the following conditions:
|
|
///
|
|
/// - The extent evenly divides the cross-axis extent of the grid.
|
|
/// - The extent is at most [maxCrossAxisExtent].
|
|
///
|
|
/// For example, if the grid is vertical, the grid is 500.0 pixels wide, and
|
|
/// [maxCrossAxisExtent] is 150.0, this delegate will create a grid with 4
|
|
/// columns that are 125.0 pixels wide.
|
|
final double maxCrossAxisExtent;
|
|
|
|
/// The number of logical pixels between each child along the main axis.
|
|
final double mainAxisSpacing;
|
|
|
|
/// The number of logical pixels between each child along the cross axis.
|
|
final double crossAxisSpacing;
|
|
|
|
/// The ratio of the cross-axis to the main-axis extent of each child.
|
|
final double childAspectRatio;
|
|
|
|
/// The extent of each tile in the main axis. If provided, it would add
|
|
/// after [childAspectRatio] is used.
|
|
final double mainAxisExtent;
|
|
|
|
bool _debugAssertIsValid(double crossAxisExtent) {
|
|
assert(crossAxisExtent > 0.0);
|
|
assert(maxCrossAxisExtent > 0.0);
|
|
assert(mainAxisSpacing >= 0.0);
|
|
assert(crossAxisSpacing >= 0.0);
|
|
assert(childAspectRatio > 0.0);
|
|
return true;
|
|
}
|
|
|
|
SliverGridLayout? layoutCache;
|
|
double? crossAxisExtentCache;
|
|
|
|
@override
|
|
SliverGridLayout getLayout(SliverConstraints constraints) {
|
|
// invoked before each frame
|
|
assert(_debugAssertIsValid(constraints.crossAxisExtent));
|
|
if (layoutCache != null &&
|
|
constraints.crossAxisExtent == crossAxisExtentCache) {
|
|
return layoutCache!;
|
|
}
|
|
crossAxisExtentCache = constraints.crossAxisExtent;
|
|
int crossAxisCount =
|
|
((constraints.crossAxisExtent - crossAxisSpacing) /
|
|
(maxCrossAxisExtent + crossAxisSpacing))
|
|
.ceil();
|
|
// Ensure a minimum count of 1, can be zero and result in an infinite extent
|
|
// below when the window size is 0.
|
|
crossAxisCount = max(1, crossAxisCount);
|
|
final double usableCrossAxisExtent = max(
|
|
0.0,
|
|
constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1),
|
|
);
|
|
final double childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount;
|
|
final double childMainAxisExtent = max(
|
|
minHeight,
|
|
childCrossAxisExtent / childAspectRatio + mainAxisExtent,
|
|
);
|
|
return layoutCache = SliverGridRegularTileLayout(
|
|
crossAxisCount: crossAxisCount,
|
|
mainAxisStride: childMainAxisExtent + mainAxisSpacing,
|
|
crossAxisStride: childCrossAxisExtent + crossAxisSpacing,
|
|
childMainAxisExtent: childMainAxisExtent,
|
|
childCrossAxisExtent: childCrossAxisExtent,
|
|
reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection),
|
|
);
|
|
}
|
|
|
|
@override
|
|
bool shouldRelayout(SliverGridDelegateWithExtentAndRatio oldDelegate) {
|
|
final flag =
|
|
oldDelegate.maxCrossAxisExtent != maxCrossAxisExtent ||
|
|
oldDelegate.mainAxisSpacing != mainAxisSpacing ||
|
|
oldDelegate.crossAxisSpacing != crossAxisSpacing ||
|
|
oldDelegate.childAspectRatio != childAspectRatio ||
|
|
oldDelegate.mainAxisExtent != mainAxisExtent;
|
|
if (flag) layoutCache = null;
|
|
return flag;
|
|
}
|
|
}
|