feat: optimisation du démarrage de l'application et de la gestion de l'authentification
- **Refonte du démarrage** : Mise en place d'un `AppInitializer` pour gérer l'initialisation asynchrone de Firebase et du cache en arrière-plan, réduisant le travail synchrone au lancement.
- **Sécurisation de l'authentification** :
- Création d'un `AppStartGate` pour gérer proprement la restauration de la session Firebase Auth et les erreurs potentielles sur le Web.
- Amélioration du `LocalUserProvider` avec un "bootstrap léger" permettant de rendre l'UID disponible immédiatement avant le chargement complet du profil.
- Ajout de protections contre les erreurs d'accès à `FirebaseAuth.instance` (notamment pour les problèmes d'interop JS sur le Web).
- **Optimisation de l'UI** :
- Remplacement du `AutoLoginWrapper` par une gestion plus robuste de la navigation post-authentification.
- Amélioration de l'`AuthGuard` pour permettre l'affichage de certains écrans (comme le calendrier) pendant le chargement des données utilisateur (`allowWhileLoading`).
- Ajout d'un écran de splash screen uniformisé (`StartupSplashScreen`).
- **Services & Cache** :
- Introduction de `CacheService` utilisant `shared_preferences` pour le stockage local léger.
- Refactoring des services (`AlertService`, `EmailService`, `FirebaseStorageManager`) pour accéder aux instances Firebase de manière plus flexible via des getters.
- Mise à jour des dépendances dans `pubspec.yaml` pour inclure `shared_preferences`.
- **Calendrier** : Ajout d'une logique de chargement initial différé des événements (`_scheduleInitialEventsLoad`) pour éviter les appels redondants au démarrage.
- **Maintenance** : Mise à jour de la version de l'application à `1.1.23` et nettoyage des fichiers de cache de déploiement.
This commit is contained in:
@@ -12,7 +12,7 @@ import '../utils/performance_monitor.dart';
|
||||
class LocalUserProvider with ChangeNotifier {
|
||||
UserModel? _currentUser;
|
||||
RoleModel? _currentRole;
|
||||
final FirebaseAuth _auth = FirebaseAuth.instance;
|
||||
FirebaseAuth? _auth;
|
||||
final FirebaseStorageManager _storageManager = FirebaseStorageManager();
|
||||
final DataService _dataService = DataService(apiService);
|
||||
|
||||
@@ -43,11 +43,41 @@ class LocalUserProvider with ChangeNotifier {
|
||||
|
||||
/// Charge les données de l'utilisateur actuel via Cloud Function
|
||||
Future<void> loadUserData({bool forceReload = false}) async {
|
||||
if (_auth.currentUser == null) {
|
||||
// Si FirebaseAuth n'est pas encore disponible
|
||||
final FirebaseAuth auth;
|
||||
try {
|
||||
auth = _getAuthInstance();
|
||||
} catch (e) {
|
||||
print('Auth instance not ready in loadUserData: $e');
|
||||
return;
|
||||
}
|
||||
|
||||
if (auth.currentUser == null) {
|
||||
print('No current user in Auth');
|
||||
return;
|
||||
}
|
||||
|
||||
// Bootstrap léger : rendre l'UID disponible tout de suite pour les écrans
|
||||
// qui en ont besoin, même si le profil complet n'est pas encore chargé.
|
||||
if (_currentUser == null) {
|
||||
final firebaseUser = auth.currentUser!;
|
||||
_currentUser = UserModel(
|
||||
uid: firebaseUser.uid,
|
||||
email: firebaseUser.email ?? '',
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
role: 'USER',
|
||||
phoneNumber: '',
|
||||
profilePhotoUrl: firebaseUser.photoURL ?? '',
|
||||
);
|
||||
_currentRole = RoleModel(
|
||||
id: 'USER',
|
||||
name: '',
|
||||
permissions: const [],
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Éviter les rechargements inutiles
|
||||
if (!forceReload && !_shouldReloadUserData()) {
|
||||
print('Using cached user data');
|
||||
@@ -62,7 +92,7 @@ class LocalUserProvider with ChangeNotifier {
|
||||
|
||||
_isLoadingUserData = true;
|
||||
PerformanceMonitor.start('LocalUserProvider.loadUserData');
|
||||
print('Loading user data for: ${_auth.currentUser!.uid}');
|
||||
print('Loading user data for: ${_auth!.currentUser!.uid}');
|
||||
try {
|
||||
// Utiliser la Cloud Function getCurrentUser
|
||||
PerformanceMonitor.start('LocalUserProvider.getCurrentUser_API');
|
||||
@@ -194,7 +224,8 @@ class LocalUserProvider with ChangeNotifier {
|
||||
Future<UserCredential> signInWithEmailAndPassword(
|
||||
String email, String password) async {
|
||||
try {
|
||||
UserCredential userCredential = await _auth.signInWithEmailAndPassword(
|
||||
final auth = _getAuthInstance();
|
||||
UserCredential userCredential = await auth.signInWithEmailAndPassword(
|
||||
email: email, password: password);
|
||||
// Note: loadUserData() sera appelé en arrière-plan dans main.dart
|
||||
// pour ne pas bloquer la navigation
|
||||
@@ -206,10 +237,25 @@ class LocalUserProvider with ChangeNotifier {
|
||||
|
||||
/// Déconnexion
|
||||
Future<void> signOut() async {
|
||||
await _auth.signOut();
|
||||
try {
|
||||
final auth = _getAuthInstance();
|
||||
await auth.signOut();
|
||||
} catch (e) {
|
||||
debugPrint('Error during signOut: $e');
|
||||
}
|
||||
clearUser();
|
||||
}
|
||||
|
||||
FirebaseAuth _getAuthInstance() {
|
||||
try {
|
||||
_auth ??= FirebaseAuth.instance;
|
||||
return _auth!;
|
||||
} catch (e, st) {
|
||||
debugPrint('[LocalUserProvider] FirebaseAuth.instance access error: $e\n$st');
|
||||
throw Exception('FirebaseAuth not available');
|
||||
}
|
||||
}
|
||||
|
||||
/// Vérifie si l'utilisateur a une permission spécifique
|
||||
bool hasPermission(String permission) {
|
||||
return _currentRole?.permissions.contains(permission) ?? false;
|
||||
|
||||
Reference in New Issue
Block a user