import 'dart:async'; import 'package:flutter/foundation.dart' show ValueNotifier; import 'package:sunny_mochi/core/observability/talker_setup.dart'; import 'package:sunny_mochi/core/storage/secure_storage.dart' show secureStorageProvider; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'auth_status_provider.g.dart'; /// 同步可读的登录态门面 — 给 GoRouter `redirect` 用。 /// /// 三态语义: /// - `null` → 启动期未知(异步 storage 还没读完,redirect 应不动) /// - `true` → 已登录 /// - `false` → 未登录(redirect 把非 /login 的访问跳 /login) class AuthStatusController { AuthStatusController() : _notifier = ValueNotifier(null); final ValueNotifier _notifier; ValueNotifier get listenable => _notifier; bool? get value => _notifier.value; void markLoggedIn() { appTalker.info('[AuthStatus] markLoggedIn'); _notifier.value = true; } void markLoggedOut() { appTalker.info('[AuthStatus] markLoggedOut'); _notifier.value = false; } void dispose() => _notifier.dispose(); } @Riverpod(keepAlive: true) AuthStatusController authStatus(Ref ref) { final controller = AuthStatusController(); unawaited(_bootstrap(ref, controller)); ref.onDispose(controller.dispose); return controller; } Future _bootstrap(Ref ref, AuthStatusController controller) async { try { final token = await ref.read(secureStorageProvider).getToken(); final loggedIn = token != null && token.isNotEmpty; if (loggedIn) { controller.markLoggedIn(); } else { controller.markLoggedOut(); } } on Object catch (e, st) { appTalker.warning('[AuthStatus] bootstrap 异常 → 视为未登录', e, st); controller.markLoggedOut(); } }