blob: 4f1c6f580a49425dfe5d59fb88d140d4f8e9a67b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'api_client_provider.dart';
/// Returns whether the server has no registered users yet (first-run state).
///
/// The go_router redirect callback reads this provider to decide whether
/// an unauthenticated visit should go to /login (normal case) or /bootstrap
/// (no accounts exist).
///
/// Implementation notes:
/// - Uses [FutureProvider] so the loading/error states are handled uniformly
/// alongside [authStateProvider] in the router's redirect callback.
/// - [FutureProvider] caches its result for the lifetime of the enclosing
/// [ProviderScope]; the value is re-fetched only when the provider is
/// explicitly invalidated (e.g. via `ref.invalidate`) or the scope is
/// recreated. After bootstrap completes the app navigates away and the
/// cached value is simply never re-read in the same session.
/// - Errors (e.g. server unreachable) are treated as non-first-run so the
/// login screen is shown and the user can retry; this avoids looping to
/// /bootstrap on connectivity failures.
final firstRunProvider = FutureProvider<bool>((ref) async {
final apiClient = ref.read(apiClientProvider);
try {
final count = await apiClient.countUsers();
return count == 0;
} catch (_) {
// Network or server error: assume not first-run so we show login.
// The login screen will surface the connectivity problem when the user
// attempts to authenticate.
return false;
}
});
|