Files
manager/lib/features/dashboard/providers/dashboard_summary_provider.dart
T

40 lines
1.6 KiB
Dart
Raw Normal View History

2026-07-27 14:42:23 +02:00
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../../../core/network/api_exception.dart';
import '../../../core/polling/polling_async_notifier.dart';
import '../../../data/repositories/node_repository.dart';
import '../../../data/repositories/services_repository.dart';
import 'dashboard_summary.dart';
part 'dashboard_summary_provider.g.dart';
/// Polled every 20s while the Dashboard is mounted — deliberately its own
/// notifier rather than watching `servicesListProvider`/`currentNodeProvider`
/// directly, so Dashboard auto-refreshes independent of whether the
/// Services screen (manual-refresh only) happens to be open too.
@riverpod
class DashboardSummaryNotifier extends _$DashboardSummaryNotifier
with PollingMixin<DashboardSummary> {
@override
Duration get interval => const Duration(seconds: 20);
@override
Future<DashboardSummary> fetch() async {
final servicesRepo = ref.watch(servicesRepositoryProvider);
final nodeRepo = ref.watch(nodeRepositoryProvider);
if (servicesRepo == null || nodeRepo == null) {
// The router redirects to Settings whenever there's no active
// connection, so reaching this in the UI would mean that redirect
// hasn't fired yet — an ApiException here (vs. a raw StateError)
// keeps error handling on the same path as every other screen.
throw const ApiException.unknown('No active connection.');
}
final services = await servicesRepo.getAll();
final node = await nodeRepo.getNode();
return DashboardSummary(services: services, node: node);
}
@override
Future<DashboardSummary> build() => startPolling();
}