/// Auth Provider library; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import '../../../domain/entities/user.dart'; import '../../../infrastructure/datasources/remote/auth_api_service.dart'; /// Auth state class AuthState { final User? user; final String? accessToken; final String? refreshToken; final bool isLoading; final String? error; const AuthState({ this.user, this.accessToken, this.refreshToken, this.isLoading = false, this.error, }); AuthState copyWith({ User? user, String? accessToken, String? refreshToken, bool? isLoading, String? error, }) { return AuthState( user: user ?? this.user, accessToken: accessToken ?? this.accessToken, refreshToken: refreshToken ?? this.refreshToken, isLoading: isLoading ?? this.isLoading, error: error, ); } bool get isAuthenticated => user != null && accessToken != null; } /// Auth notifier class AuthNotifier extends StateNotifier { AuthNotifier(this._authApiService, this._storage) : super(const AuthState()) { _loadFromStorage(); } final AuthApiService _authApiService; final FlutterSecureStorage _storage; static const String _accessTokenKey = 'access_token'; static const String _refreshTokenKey = 'refresh_token'; static const String _userKey = 'user'; Future _loadFromStorage() async { state = state.copyWith(isLoading: true); try { final accessToken = await _storage.read(key: _accessTokenKey); final refreshToken = await _storage.read(key: _refreshTokenKey); final userJson = await _storage.read(key: _userKey); if (accessToken != null && refreshToken != null && userJson != null) { // Parse user from JSON final user = UserJson.fromJson( // ignore: avoid_dynamic_calls _jsonDecode(userJson), ); state = AuthState( user: user, accessToken: accessToken, refreshToken: refreshToken, ); } else { state = const AuthState(); } } catch (e) { state = AuthState(error: e.toString()); } finally { state = state.copyWith(isLoading: false); } } Future login(String email, String password) async { state = state.copyWith(isLoading: true, error: null); try { final response = await _authApiService.login(email, password); await _storage.write(key: _accessTokenKey, value: response.accessToken); await _storage.write(key: _refreshTokenKey, value: response.refreshToken); await _storage.write( key: _userKey, value: _jsonEncode(response.user.toJson()), ); state = AuthState( user: response.user, accessToken: response.accessToken, refreshToken: response.refreshToken, ); } catch (e) { state = AuthState(error: e.toString()); } finally { state = state.copyWith(isLoading: false); } } Future register({ required String email, required String username, required String password, String? displayName, }) async { state = state.copyWith(isLoading: true, error: null); try { final response = await _authApiService.register( email: email, username: username, password: password, displayName: displayName, ); await _storage.write(key: _accessTokenKey, value: response.accessToken); await _storage.write(key: _refreshTokenKey, value: response.refreshToken); await _storage.write( key: _userKey, value: _jsonEncode(response.user.toJson()), ); state = AuthState( user: response.user, accessToken: response.accessToken, refreshToken: response.refreshToken, ); } catch (e) { state = AuthState(error: e.toString()); } finally { state = state.copyWith(isLoading: false); } } Future refreshToken() async { if (state.refreshToken == null) return null; try { final response = await _authApiService.refreshToken(state.refreshToken!); final newAccessToken = response['access_token'] as String; final newRefreshToken = response['refresh_token'] as String; await _storage.write(key: _accessTokenKey, value: newAccessToken); await _storage.write(key: _refreshTokenKey, value: newRefreshToken); state = state.copyWith( accessToken: newAccessToken, refreshToken: newRefreshToken, ); return newAccessToken; } catch (e) { await logout(); return null; } } Future logout() async { try { await _authApiService.logout(); } catch (e) { // Ignore logout errors } finally { await _storage.delete(key: _accessTokenKey); await _storage.delete(key: _refreshTokenKey); await _storage.delete(key: _userKey); state = const AuthState(); } } Future updateProfile({String? displayName, String? avatarUrl}) async { state = state.copyWith(isLoading: true); try { final updatedUser = await _authApiService.updateProfile( displayName: displayName, avatarUrl: avatarUrl, ); await _storage.write( key: _userKey, value: _jsonEncode(updatedUser.toJson()), ); state = state.copyWith(user: updatedUser); } catch (e) { state = state.copyWith(error: e.toString()); } finally { state = state.copyWith(isLoading: false); } } String _jsonEncode(Object obj) { // Simple JSON encode return obj.toString(); } Object _jsonDecode(String str) { // Simple JSON decode return str; } } /// Auth provider final authProvider = StateNotifierProvider((ref) { final authApiService = ref.watch(authApiServiceProvider); const storage = FlutterSecureStorage(); return AuthNotifier(authApiService, storage); });