feat: Add initial Flutter Android project setup, core API client with authentication token management, and authentication service.

This commit is contained in:
Michael committed 2025-12-09 17:20:28 +01:00
1 parent ab6c7f585f
commit 664e89f2b8
3 files changed
+29 -21

No files matched your search

+1 -1
View File
@@ -21,7 +21,7 @@ android {
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.xtremflow" applicationId = "com.xtremflow.mobile"
// You can update the following values to match your application needs. // You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config. // For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion minSdk = flutter.minSdkVersion
+23 -15
View File
@@ -1,5 +1,5 @@
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'dart:html' as html; import 'package:shared_preferences/shared_preferences.dart';
/// API Client for communicating with the backend /// API Client for communicating with the backend
class ApiClient { class ApiClient {
@@ -26,39 +26,47 @@ class ApiClient {
/// Get base URL (same origin for production) /// Get base URL (same origin for production)
String _getBaseUrl() { String _getBaseUrl() {
// Use current origin for API calls // For mobile, this needs to be configured or passed in.
// For now, returning empty string implies relative path (works for web).
// TODO: Configure base URL for mobile
return ''; return '';
} }
/// Set authentication token /// Set authentication token
void setToken(String? token) { Future<void> setToken(String? token) async {
_token = token; _token = token;
if (token != null) { if (token != null) {
_dio.options.headers['Authorization'] = 'Bearer $token'; _dio.options.headers['Authorization'] = 'Bearer $token';
// Store in localStorage for persistence // Store in SharedPreferences for persistence
html.window.localStorage['auth_token'] = token; final prefs = await SharedPreferences.getInstance();
await prefs.setString('auth_token', token);
} else { } else {
_dio.options.headers.remove('Authorization'); _dio.options.headers.remove('Authorization');
html.window.localStorage.remove('auth_token'); final prefs = await SharedPreferences.getInstance();
await prefs.remove('auth_token');
} }
} }
/// Get stored token from localStorage /// Get stored token from memory
String? getStoredToken() { String? getToken() {
return html.window.localStorage['auth_token']; return _token;
} }
/// Restore token from localStorage /// Restore token from SharedPreferences
void restoreToken() { Future<void> restoreToken() async {
final storedToken = getStoredToken(); final prefs = await SharedPreferences.getInstance();
final storedToken = prefs.getString('auth_token');
if (storedToken != null) { if (storedToken != null) {
setToken(storedToken); // We call setToken but avoid the async loop?
// Just set memory and header directly to avoid double SP call
_token = storedToken;
_dio.options.headers['Authorization'] = 'Bearer $storedToken';
} }
} }
/// Clear token /// Clear token
void clearToken() { Future<void> clearToken() async {
setToken(null); await setToken(null);
} }
/// GET request /// GET request
+5 -5
View File
@@ -19,7 +19,7 @@ class AuthApiService {
final token = data['token'] as String; final token = data['token'] as String;
final userData = data['user'] as Map<String, dynamic>; final userData = data['user'] as Map<String, dynamic>;
_api.setToken(token); await _api.setToken(token);
return AuthResult( return AuthResult(
success: true, success: true,
@@ -51,15 +51,15 @@ class AuthApiService {
try { try {
await _api.post('/api/auth/logout'); await _api.post('/api/auth/logout');
} finally { } finally {
_api.clearToken(); await _api.clearToken();
} }
} }
/// Get current user from token /// Get current user from token
Future<AppUser?> getCurrentUser() async { Future<AppUser?> getCurrentUser() async {
_api.restoreToken(); await _api.restoreToken();
if (_api.getStoredToken() == null) { if (_api.getToken() == null) {
return null; return null;
} }
@@ -76,7 +76,7 @@ class AuthApiService {
createdAt: DateTime.now(), createdAt: DateTime.now(),
); );
} catch (e) { } catch (e) {
_api.clearToken(); await _api.clearToken();
return null; return null;
} }
} }