initial commit
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
/// Mixed into a `@riverpod` `AutoDisposeAsyncNotifier` to auto-refresh it on
|
||||
/// a timer while it has at least one listener — Dashboard's summary and
|
||||
/// Fleet's aggregated view, specifically. The API has no push/websocket, so
|
||||
/// this is the honest refresh model: a manual pull plus a background
|
||||
/// timer, not a live stream.
|
||||
///
|
||||
/// Usage: `class FooNotifier extends _$FooNotifier with PollingMixin<Foo>`,
|
||||
/// implement [interval] and [fetch], and have `build()` return
|
||||
/// `startPolling()`.
|
||||
mixin PollingMixin<T> on $AsyncNotifier<T> {
|
||||
/// How often to refetch while this provider has at least one listener.
|
||||
Duration get interval;
|
||||
|
||||
/// Performs the actual fetch. Thrown exceptions surface as
|
||||
/// `AsyncValue.error` exactly like any other async provider.
|
||||
Future<T> fetch();
|
||||
|
||||
/// Call from `build()`: starts the periodic timer (cancelled on dispose)
|
||||
/// and returns the initial fetch.
|
||||
Future<T> startPolling() {
|
||||
final timer = Timer.periodic(interval, (_) => refresh());
|
||||
ref.onDispose(timer.cancel);
|
||||
return fetch();
|
||||
}
|
||||
|
||||
/// Re-fetches and updates state. Deliberately never emits an
|
||||
/// intermediate `AsyncLoading` — the previous data/error stays on screen
|
||||
/// until the new result lands, so a background tick never flashes the
|
||||
/// UI back to a loading spinner.
|
||||
Future<void> refresh() async {
|
||||
state = await AsyncValue.guard(fetch);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user