mirror of
https://github.com/immich-app/immich.git
synced 2025-09-29 15:31:13 -04:00
fix: get scrubber in search view working (#22175)
* feat: add option to disable snapping * handle offset when there is no appbar
This commit is contained in:
parent
de897f6069
commit
642065f506
@ -633,7 +633,7 @@ class _SearchResultGrid extends ConsumerWidget {
|
|||||||
groupBy: GroupAssetsBy.none,
|
groupBy: GroupAssetsBy.none,
|
||||||
appBar: null,
|
appBar: null,
|
||||||
bottomSheet: const GeneralBottomSheet(minChildSize: 0.20),
|
bottomSheet: const GeneralBottomSheet(minChildSize: 0.20),
|
||||||
withScrubber: false,
|
snapToMonth: false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -31,6 +31,11 @@ class Scrubber extends ConsumerStatefulWidget {
|
|||||||
|
|
||||||
final double? monthSegmentSnappingOffset;
|
final double? monthSegmentSnappingOffset;
|
||||||
|
|
||||||
|
final bool snapToMonth;
|
||||||
|
|
||||||
|
/// Whether an app bar is present, affects coordinate calculations
|
||||||
|
final bool hasAppBar;
|
||||||
|
|
||||||
Scrubber({
|
Scrubber({
|
||||||
super.key,
|
super.key,
|
||||||
Key? scrollThumbKey,
|
Key? scrollThumbKey,
|
||||||
@ -39,6 +44,8 @@ class Scrubber extends ConsumerStatefulWidget {
|
|||||||
this.topPadding = 0,
|
this.topPadding = 0,
|
||||||
this.bottomPadding = 0,
|
this.bottomPadding = 0,
|
||||||
this.monthSegmentSnappingOffset,
|
this.monthSegmentSnappingOffset,
|
||||||
|
this.snapToMonth = true,
|
||||||
|
this.hasAppBar = true,
|
||||||
required this.child,
|
required this.child,
|
||||||
}) : assert(child.scrollDirection == Axis.vertical);
|
}) : assert(child.scrollDirection == Axis.vertical);
|
||||||
|
|
||||||
@ -232,7 +239,7 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_monthCount < kMinMonthsToEnableScrubberSnap) {
|
if (_monthCount < kMinMonthsToEnableScrubberSnap || !widget.snapToMonth) {
|
||||||
// If there are less than kMinMonthsToEnableScrubberSnap months, we don't need to snap to segments
|
// If there are less than kMinMonthsToEnableScrubberSnap months, we don't need to snap to segments
|
||||||
setState(() {
|
setState(() {
|
||||||
_thumbTopOffset = dragPosition;
|
_thumbTopOffset = dragPosition;
|
||||||
@ -259,14 +266,28 @@ class ScrubberState extends ConsumerState<Scrubber> with TickerProviderStateMixi
|
|||||||
/// - If user drags to global Y position that's 100 pixels from the top
|
/// - If user drags to global Y position that's 100 pixels from the top
|
||||||
/// - The relative position would be 100 - 50 = 50 (50 pixels into the scrubber area)
|
/// - The relative position would be 100 - 50 = 50 (50 pixels into the scrubber area)
|
||||||
double _calculateDragPosition(DragUpdateDetails details) {
|
double _calculateDragPosition(DragUpdateDetails details) {
|
||||||
|
if (widget.hasAppBar) {
|
||||||
|
final dragAreaTop = widget.topPadding;
|
||||||
|
final dragAreaBottom = widget.timelineHeight - widget.bottomPadding;
|
||||||
|
final dragAreaHeight = dragAreaBottom - dragAreaTop;
|
||||||
|
|
||||||
|
final relativePosition = details.globalPosition.dy - dragAreaTop;
|
||||||
|
|
||||||
|
// Make sure the position stays within the scrubber's bounds
|
||||||
|
return relativePosition.clamp(0.0, dragAreaHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the local position relative to the gesture detector
|
||||||
|
final RenderBox? renderBox = context.findRenderObject() as RenderBox?;
|
||||||
|
if (renderBox != null) {
|
||||||
|
final localPosition = renderBox.globalToLocal(details.globalPosition);
|
||||||
|
return localPosition.dy.clamp(0.0, _scrubberHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to current logic if render box is not available
|
||||||
final dragAreaTop = widget.topPadding;
|
final dragAreaTop = widget.topPadding;
|
||||||
final dragAreaBottom = widget.timelineHeight - widget.bottomPadding;
|
|
||||||
final dragAreaHeight = dragAreaBottom - dragAreaTop;
|
|
||||||
|
|
||||||
final relativePosition = details.globalPosition.dy - dragAreaTop;
|
final relativePosition = details.globalPosition.dy - dragAreaTop;
|
||||||
|
return relativePosition.clamp(0.0, _scrubberHeight);
|
||||||
// Make sure the position stays within the scrubber's bounds
|
|
||||||
return relativePosition.clamp(0.0, dragAreaHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the segment closest to the given position
|
/// Find the segment closest to the given position
|
||||||
|
@ -38,6 +38,7 @@ class Timeline extends StatelessWidget {
|
|||||||
this.bottomSheet = const GeneralBottomSheet(minChildSize: 0.18),
|
this.bottomSheet = const GeneralBottomSheet(minChildSize: 0.18),
|
||||||
this.groupBy,
|
this.groupBy,
|
||||||
this.withScrubber = true,
|
this.withScrubber = true,
|
||||||
|
this.snapToMonth = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Widget? topSliverWidget;
|
final Widget? topSliverWidget;
|
||||||
@ -48,6 +49,7 @@ class Timeline extends StatelessWidget {
|
|||||||
final bool withStack;
|
final bool withStack;
|
||||||
final GroupAssetsBy? groupBy;
|
final GroupAssetsBy? groupBy;
|
||||||
final bool withScrubber;
|
final bool withScrubber;
|
||||||
|
final bool snapToMonth;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -73,6 +75,7 @@ class Timeline extends StatelessWidget {
|
|||||||
appBar: appBar,
|
appBar: appBar,
|
||||||
bottomSheet: bottomSheet,
|
bottomSheet: bottomSheet,
|
||||||
withScrubber: withScrubber,
|
withScrubber: withScrubber,
|
||||||
|
snapToMonth: snapToMonth,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -87,6 +90,7 @@ class _SliverTimeline extends ConsumerStatefulWidget {
|
|||||||
this.appBar,
|
this.appBar,
|
||||||
this.bottomSheet,
|
this.bottomSheet,
|
||||||
this.withScrubber = true,
|
this.withScrubber = true,
|
||||||
|
this.snapToMonth = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Widget? topSliverWidget;
|
final Widget? topSliverWidget;
|
||||||
@ -94,6 +98,7 @@ class _SliverTimeline extends ConsumerStatefulWidget {
|
|||||||
final Widget? appBar;
|
final Widget? appBar;
|
||||||
final Widget? bottomSheet;
|
final Widget? bottomSheet;
|
||||||
final bool withScrubber;
|
final bool withScrubber;
|
||||||
|
final bool snapToMonth;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState createState() => _SliverTimelineState();
|
ConsumerState createState() => _SliverTimelineState();
|
||||||
@ -309,11 +314,13 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> {
|
|||||||
final Widget timeline;
|
final Widget timeline;
|
||||||
if (widget.withScrubber) {
|
if (widget.withScrubber) {
|
||||||
timeline = Scrubber(
|
timeline = Scrubber(
|
||||||
|
snapToMonth: widget.snapToMonth,
|
||||||
layoutSegments: segments,
|
layoutSegments: segments,
|
||||||
timelineHeight: maxHeight,
|
timelineHeight: maxHeight,
|
||||||
topPadding: topPadding,
|
topPadding: topPadding,
|
||||||
bottomPadding: bottomPadding,
|
bottomPadding: bottomPadding,
|
||||||
monthSegmentSnappingOffset: widget.topSliverWidgetHeight ?? 0 + appBarExpandedHeight,
|
monthSegmentSnappingOffset: widget.topSliverWidgetHeight ?? 0 + appBarExpandedHeight,
|
||||||
|
hasAppBar: widget.appBar != null,
|
||||||
child: grid,
|
child: grid,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user