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>
132 lines
4.2 KiB
Dart
132 lines
4.2 KiB
Dart
import 'package:PiliPlus/common/constants.dart';
|
|
import 'package:PiliPlus/common/skeleton/dynamic_card.dart';
|
|
import 'package:PiliPlus/utils/global_data.dart';
|
|
import 'package:PiliPlus/utils/grid.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart' show SliverConstraints;
|
|
import 'package:waterfall_flow/waterfall_flow.dart'
|
|
show SliverWaterfallFlowDelegate;
|
|
|
|
mixin DynMixin {
|
|
late double maxWidth;
|
|
|
|
late final dynGridDelegate =
|
|
SliverWaterfallFlowDelegateWithMaxCrossAxisExtent(
|
|
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
|
crossAxisSpacing: 4,
|
|
callback: (value) => maxWidth = value,
|
|
);
|
|
|
|
Widget buildPage(Widget child) {
|
|
if (GlobalData().dynamicsWaterfallFlow) {
|
|
return child;
|
|
}
|
|
return SliverLayoutBuilder(
|
|
builder: (context, constraints) {
|
|
final maxWidth = constraints.crossAxisExtent;
|
|
final cardWidth = Grid.smallCardWidth * 2;
|
|
final flag = cardWidth < maxWidth;
|
|
this.maxWidth = flag ? cardWidth : maxWidth;
|
|
if (!flag) {
|
|
return child;
|
|
}
|
|
return SliverPadding(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: (maxWidth - cardWidth) / 2,
|
|
),
|
|
sliver: child,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
late final skeDelegate = SliverGridDelegateWithExtentAndRatio(
|
|
crossAxisSpacing: 4,
|
|
mainAxisSpacing: 4,
|
|
maxCrossAxisExtent: Grid.smallCardWidth * 2,
|
|
childAspectRatio: StyleString.aspectRatio,
|
|
mainAxisExtent: 50,
|
|
);
|
|
|
|
Widget get dynSkeleton {
|
|
if (GlobalData().dynamicsWaterfallFlow) {
|
|
return SliverGrid.builder(
|
|
gridDelegate: skeDelegate,
|
|
itemBuilder: (_, _) => const DynamicCardSkeleton(),
|
|
itemCount: 10,
|
|
);
|
|
}
|
|
return SliverPrototypeExtentList.builder(
|
|
prototypeItem: const DynamicCardSkeleton(),
|
|
itemBuilder: (_, _) => const DynamicCardSkeleton(),
|
|
itemCount: 10,
|
|
);
|
|
}
|
|
}
|
|
|
|
class SliverWaterfallFlowDelegateWithMaxCrossAxisExtent
|
|
extends SliverWaterfallFlowDelegate {
|
|
/// Creates a delegate that makes masonry layouts with tiles that have a maximum
|
|
/// cross-axis extent.
|
|
///
|
|
/// All of the arguments must not be null. The [maxCrossAxisExtent],
|
|
/// [mainAxisSpacing], and [crossAxisSpacing] arguments must not be negative.
|
|
SliverWaterfallFlowDelegateWithMaxCrossAxisExtent({
|
|
required this.maxCrossAxisExtent,
|
|
super.mainAxisSpacing,
|
|
super.crossAxisSpacing,
|
|
super.lastChildLayoutTypeBuilder,
|
|
super.collectGarbage,
|
|
super.viewportBuilder,
|
|
super.closeToTrailing,
|
|
this.callback,
|
|
}) : assert(maxCrossAxisExtent >= 0);
|
|
|
|
/// 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;
|
|
|
|
int? crossAxisCount;
|
|
double? crossAxisExtent;
|
|
|
|
final ValueChanged<double>? callback;
|
|
|
|
@override
|
|
int getCrossAxisCount(SliverConstraints constraints) {
|
|
final crossAxisExtent = constraints.crossAxisExtent;
|
|
if (crossAxisCount != null && this.crossAxisExtent == crossAxisExtent) {
|
|
return crossAxisCount!;
|
|
}
|
|
this.crossAxisExtent = crossAxisExtent;
|
|
crossAxisCount = (crossAxisExtent / (maxCrossAxisExtent + crossAxisSpacing))
|
|
.ceil();
|
|
callback?.call(
|
|
(crossAxisExtent - ((crossAxisCount! - 1) * crossAxisSpacing)) /
|
|
crossAxisCount!,
|
|
);
|
|
return crossAxisCount!;
|
|
}
|
|
|
|
@override
|
|
bool shouldRelayout(SliverWaterfallFlowDelegate oldDelegate) {
|
|
final flag =
|
|
(oldDelegate.runtimeType != runtimeType) ||
|
|
(oldDelegate is SliverWaterfallFlowDelegateWithMaxCrossAxisExtent &&
|
|
(oldDelegate.maxCrossAxisExtent != maxCrossAxisExtent ||
|
|
super.shouldRelayout(oldDelegate)));
|
|
if (flag) {
|
|
crossAxisCount = null;
|
|
}
|
|
return flag;
|
|
}
|
|
}
|