initial commit

This commit is contained in:
2026-07-27 14:42:23 +02:00
commit 833c68a189
257 changed files with 17947 additions and 0 deletions
@@ -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);
}
}