Files
PiliPlus/lib/utils/waterfall.dart
My-Responsitories 37fb63c3b1 tweaks (#1252)
* 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>
2025-09-15 18:45:28 +08:00

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;
}
}