triggerRefresh method
Implementation
Future<void> triggerRefresh(Future<void> Function() onRefresh) async {
if (isRefreshing.value) return;
if (enableHaptics) {
HapticFeedback.mediumImpact();
}
hasThresholdBeenReached.value = false;
isRefreshing.value = true;
// Lock the header to a stable, visible height so the loader is always
// shown regardless of how the underlying physics settle.
await animateToOffset(settleDistance);
tickerController.repeat();
final DateTime started = DateTime.now();
try {
await onRefresh();
} finally {
// Keep the indicator visible for at least [refreshDuration] (3-5s) so the
// premium animation runs fully, accounting for time already spent.
final Duration elapsed = DateTime.now().difference(started);
if (elapsed < refreshDuration) {
await Future.delayed(refreshDuration - elapsed);
}
tickerController.stop();
tickerController.reset();
// Collapse the header up smoothly (loader slides away).
await snapBack(0.0);
// Then bring the list content to the very top.
if (scrollController != null &&
scrollController!.hasClients &&
scrollController!.offset > 0) {
await scrollController!.animateTo(
0.0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOutCubic,
);
}
isRefreshing.value = false;
hasSelectionHapticFired.value = false;
}
}