- Updated multiple providers to use `@Riverpod(keepAlive: true)` for better state retention throughout the app lifecycle. - Enhanced `SocketConnectionStream` and `ConversationDeltaStream` with comments clarifying the purpose of public getters. - Improved error handling in the `_ChatPageState` by ensuring proper checks for mounted state before using context. - Added comments to clarify the rationale behind keepAlive usage in various providers, ensuring better maintainability and understanding of the codebase.
142 lines
4.3 KiB
Dart
142 lines
4.3 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import '../../../core/auth/auth_state_manager.dart';
|
|
import '../../../core/models/user.dart';
|
|
import '../../../core/providers/app_providers.dart';
|
|
|
|
/// Unified auth providers using the new auth state manager
|
|
/// These replace the old auth providers for better efficiency
|
|
|
|
/// Imperative auth actions wrapper to avoid side-effects during provider build
|
|
class AuthActions {
|
|
final Ref _ref;
|
|
AuthActions(this._ref);
|
|
|
|
AuthStateManager get _auth => _ref.read(authStateManagerProvider.notifier);
|
|
|
|
Future<bool> login(
|
|
String username,
|
|
String password, {
|
|
bool rememberCredentials = false,
|
|
}) {
|
|
return _auth.login(
|
|
username,
|
|
password,
|
|
rememberCredentials: rememberCredentials,
|
|
);
|
|
}
|
|
|
|
Future<bool> loginWithApiKey(
|
|
String apiKey, {
|
|
bool rememberCredentials = false,
|
|
}) {
|
|
return _auth.loginWithApiKey(
|
|
apiKey,
|
|
rememberCredentials: rememberCredentials,
|
|
);
|
|
}
|
|
|
|
Future<bool> silentLogin() {
|
|
return _auth.silentLogin();
|
|
}
|
|
|
|
Future<void> logout() {
|
|
return _auth.logout();
|
|
}
|
|
|
|
Future<void> refresh() {
|
|
return _auth.refresh();
|
|
}
|
|
}
|
|
|
|
final authActionsProvider = Provider<AuthActions>((ref) => AuthActions(ref));
|
|
|
|
// Legacy action providers have been replaced by `authActionsProvider`
|
|
|
|
/// Check if saved credentials exist
|
|
final hasSavedCredentialsProvider2 = FutureProvider<bool>((ref) async {
|
|
final authManager = ref.read(authStateManagerProvider.notifier);
|
|
return await authManager.hasSavedCredentials();
|
|
});
|
|
|
|
/// Computed providers for UI consumption
|
|
/// These automatically update when auth state changes
|
|
/// These are keepAlive since they derive from keepAlive authStateManagerProvider
|
|
/// and are used throughout the app lifecycle
|
|
|
|
final isAuthenticatedProvider2 = Provider<bool>((ref) {
|
|
final authState = ref.watch(authStateManagerProvider);
|
|
return authState.maybeWhen(
|
|
data: (state) => state.isAuthenticated,
|
|
orElse: () => false,
|
|
);
|
|
});
|
|
|
|
final authTokenProvider3 = Provider<String?>((ref) {
|
|
final authState = ref.watch(authStateManagerProvider);
|
|
return authState.maybeWhen(data: (state) => state.token, orElse: () => null);
|
|
});
|
|
|
|
final currentUserProvider2 = Provider<User?>((ref) {
|
|
final authState = ref.watch(authStateManagerProvider);
|
|
return authState.maybeWhen(data: (state) => state.user, orElse: () => null);
|
|
});
|
|
|
|
final authErrorProvider3 = Provider<String?>((ref) {
|
|
final authState = ref.watch(authStateManagerProvider);
|
|
return authState.maybeWhen(data: (state) => state.error, orElse: () => null);
|
|
});
|
|
|
|
final isAuthLoadingProvider2 = Provider<bool>((ref) {
|
|
final authState = ref.watch(authStateManagerProvider);
|
|
if (authState.isLoading) return true;
|
|
return authState.maybeWhen(
|
|
data: (state) => state.isLoading,
|
|
orElse: () => false,
|
|
);
|
|
});
|
|
|
|
final authStatusProvider = Provider<AuthStatus>((ref) {
|
|
final authState = ref.watch(authStateManagerProvider);
|
|
return authState.maybeWhen(
|
|
data: (state) => state.status,
|
|
orElse: () => AuthStatus.loading,
|
|
);
|
|
});
|
|
|
|
// Use `ref.read(authActionsProvider).refresh()` instead of refresh providers
|
|
|
|
/// Provider to watch for auth state changes and update API service
|
|
final authApiIntegrationProvider = Provider<void>((ref) {
|
|
ref.listen(authTokenProvider3, (previous, next) {
|
|
final api = ref.read(apiServiceProvider);
|
|
if (api != null && next != null && next.isNotEmpty) {
|
|
api.updateAuthToken(next);
|
|
}
|
|
});
|
|
});
|
|
|
|
/// Navigation helper provider - determines where user should go
|
|
final authNavigationStateProvider = Provider<AuthNavigationState>((ref) {
|
|
final authState = ref.watch(authStateManagerProvider);
|
|
return authState.when(
|
|
data: (state) {
|
|
switch (state.status) {
|
|
case AuthStatus.initial:
|
|
case AuthStatus.loading:
|
|
return AuthNavigationState.loading;
|
|
case AuthStatus.authenticated:
|
|
return AuthNavigationState.authenticated;
|
|
case AuthStatus.unauthenticated:
|
|
case AuthStatus.tokenExpired:
|
|
return AuthNavigationState.needsLogin;
|
|
case AuthStatus.error:
|
|
return AuthNavigationState.error;
|
|
}
|
|
},
|
|
loading: () => AuthNavigationState.loading,
|
|
error: (_, stack) => AuthNavigationState.error,
|
|
);
|
|
});
|
|
|
|
enum AuthNavigationState { loading, authenticated, needsLogin, error }
|