Current User Service

Overview

1. Clear Provider Delegation

// New - all user-related providers delegate to AuthService
@riverpod
UserModel? currentUser(Ref ref) {
  return ref.watch(authServiceSimpleProvider).user; // Single source
}

@riverpod
bool currentUserIsAuthenticated(Ref ref) {
  return ref.watch(authServiceSimpleProvider).isAuthenticated; // Single source
}

@riverpod
bool currentUserIsLoading(Ref ref) {
  final authLoading = ref.watch(authServiceSimpleProvider).isLoading;
  final userLoading = ref.watch(currentUserServiceProvider).isLoading;
  return authLoading || userLoading; // Combines both loading states clearly
}

2. Clear Separation of Responsibilities

// AuthService: Manages authentication and user state
class AuthService {
  Future<void> signIn(AuthAttempt attempt) { /* handles auth */ }
  Future<void> signOut() { /* handles auth */ }
  void updateUser(UserModel user) { /* updates user state */ }
}

// CurrentUserService: Manages user operations only
class CurrentUserService {
  Future<void> updateUser(UserModel user) { /* API calls, then delegates to AuthService */ }
  Future<void> updateUserField(String field, dynamic value) { /* user operations */ }
  Future<void> refreshUser() { /* refresh from server */ }
}

Usage Examples

// Single source of truth - always consistent
final authState = ref.watch(authServiceSimpleProvider);

if (authState.isAuthenticated) {
  // authState.user is guaranteed to be non-null
  print('User: ${authState.user!.email}'); // Always safe!
}

// Clear loading state
if (ref.watch(currentUserIsLoadingProvider)) {
  showLoadingSpinner(); // Combines both loading states intelligently
}

Usage Patterns

User Authentication State

// Always get from auth service - single source
final isAuth = ref.watch(isAuthenticatedProvider);
final user = ref.watch(currentUserProvider); // Delegates to auth service

User Operations

// Use current user service for operations
final userService = ref.read(currentUserServiceProvider.notifier);
await userService.updateUserField('displayName', 'New Name');
// Automatically updates auth service state too

Loading States

// Intelligent loading state combining both services
final isLoading = ref.watch(currentUserIsLoadingProvider);
// Shows loading for auth operations OR user operations