- Configuration complète Stripe pour les 3 environnements (DEV/REC/PROD) * DEV: Clés TEST Pierre (mode test) * REC: Clés TEST Client (mode test) * PROD: Clés LIVE Client (mode live) - Ajout de la gestion des bases de données immeubles/bâtiments * Configuration buildings_database pour DEV/REC/PROD * Service BuildingService pour enrichissement des adresses - Optimisations pages et améliorations ergonomie - Mises à jour des dépendances Composer - Nettoyage des fichiers obsolètes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
901 lines
25 KiB
Markdown
901 lines
25 KiB
Markdown
# FLOW DE DÉMARRAGE DE L'APPLICATION GEOSECTOR
|
|
|
|
**Version** : 3.2.4
|
|
**Date** : 04 octobre 2025
|
|
**Objectif** : Cartographie complète du démarrage de l'application jusqu'à `login_page.dart`
|
|
|
|
---
|
|
|
|
## 📋 Table des matières
|
|
|
|
1. [Vue d'ensemble](#-vue-densemble)
|
|
2. [Flow normal de démarrage](#-flow-normal-de-démarrage)
|
|
3. [Flow avec nettoyage du cache](#-flow-avec-nettoyage-du-cache)
|
|
4. [Gestion des Hive Box](#-gestion-des-hive-box)
|
|
5. [Vérifications et redirections](#-vérifications-et-redirections)
|
|
6. [Points critiques](#-points-critiques)
|
|
|
|
---
|
|
|
|
## 🎯 Vue d'ensemble
|
|
|
|
L'application GEOSECTOR utilise une architecture de démarrage en **3 étapes principales** :
|
|
|
|
```mermaid
|
|
graph LR
|
|
A[main.dart] --> B[SplashPage]
|
|
B --> C[LoginPage]
|
|
C --> D[UserPage / AdminPage]
|
|
|
|
style A fill:#e1f5ff
|
|
style B fill:#fff4e1
|
|
style C fill:#e8f5e9
|
|
style D fill:#f3e5f5
|
|
```
|
|
|
|
**Responsabilités** :
|
|
- **main.dart** : Initialisation minimale des services et Hive
|
|
- **SplashPage** : Initialisation complète Hive + vérification permissions GPS
|
|
- **LoginPage** : Validation Hive + formulaire de connexion
|
|
|
|
---
|
|
|
|
## 🚀 Flow normal de démarrage
|
|
|
|
### **1. Point d'entrée : `main.dart`**
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant M as main()
|
|
participant AS as ApiService
|
|
participant H as Hive
|
|
participant App as GeosectorApp
|
|
|
|
M->>M: usePathUrlStrategy()
|
|
M->>M: WidgetsFlutterBinding.ensureInitialized()
|
|
|
|
M->>AS: ApiService.initialize()
|
|
Note over AS: Détection environnement<br/>(DEV/REC/PROD)
|
|
AS-->>M: ✅ ApiService prêt
|
|
|
|
M->>H: Hive.initFlutter()
|
|
Note over H: Initialisation minimale<br/>PAS d'adaptateurs<br/>PAS de Box
|
|
H-->>M: ✅ Hive base initialisé
|
|
|
|
M->>App: runApp(GeosectorApp())
|
|
App->>App: Build MaterialApp.router
|
|
App->>App: Route initiale: '/' (SplashPage)
|
|
```
|
|
|
|
#### **Code : main.dart (lignes 10-32)**
|
|
|
|
```dart
|
|
void main() async {
|
|
usePathUrlStrategy(); // URLs sans #
|
|
WidgetsFlutterBinding.ensureInitialized();
|
|
|
|
await _initializeServices(); // ApiService + autres
|
|
await _initializeHive(); // Hive.initFlutter() seulement
|
|
|
|
runApp(const GeosectorApp()); // Lancer l'app
|
|
}
|
|
```
|
|
|
|
**🔑 Points clés :**
|
|
- ✅ **Initialisation minimale** : Pas d'adaptateurs, pas de Box
|
|
- ✅ **Services singleton** : ApiService, CurrentUserService, etc.
|
|
- ✅ **Hive base** : Juste `Hive.initFlutter()`, le reste dans SplashPage
|
|
|
|
---
|
|
|
|
### **2. Étape d'initialisation : `SplashPage`**
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant SP as SplashPage
|
|
participant HS as HiveService
|
|
participant LS as LocationService
|
|
participant GPS as Permissions GPS
|
|
|
|
SP->>SP: initState()
|
|
SP->>SP: _getAppVersion()
|
|
SP->>SP: _startInitialization()
|
|
|
|
Note over SP: Progress: 0%
|
|
|
|
alt Sur Mobile (non-Web)
|
|
SP->>LS: checkAndRequestPermission()
|
|
LS->>GPS: Demande permissions
|
|
|
|
alt Permissions OK
|
|
GPS-->>LS: Granted
|
|
LS-->>SP: true
|
|
Note over SP: Progress: 10%
|
|
else Permissions refusées
|
|
GPS-->>LS: Denied
|
|
LS-->>SP: false
|
|
SP->>SP: _showLocationError = true
|
|
Note over SP: ❌ ARRÊT de l'initialisation
|
|
end
|
|
end
|
|
|
|
SP->>HS: initializeAndResetHive()
|
|
Note over SP: Progress: 15-60%
|
|
|
|
HS->>HS: _registerAdapters()
|
|
Note over HS: Enregistrement 14 adaptateurs
|
|
|
|
HS->>HS: _destroyAllData()
|
|
Note over HS: Fermeture boxes<br/>Suppression fichiers
|
|
|
|
HS->>HS: _createAllBoxes()
|
|
Note over HS: Ouverture 14 boxes typées
|
|
|
|
HS-->>SP: ✅ Hive initialisé
|
|
|
|
SP->>HS: ensureBoxesAreOpen()
|
|
Note over SP: Progress: 60-80%
|
|
HS-->>SP: ✅ Toutes les boxes ouvertes
|
|
|
|
SP->>SP: _checkVersionAndCleanIfNeeded()
|
|
Note over SP: Vérification app_version<br/>Nettoyage si nouvelle version
|
|
|
|
SP->>SP: Ouvrir pending_requests box
|
|
Note over SP: Progress: 80%
|
|
|
|
SP->>HS: areAllBoxesOpen()
|
|
HS-->>SP: true
|
|
Note over SP: Progress: 95%
|
|
|
|
SP->>SP: Sauvegarder hive_initialized = true
|
|
Note over SP: Progress: 100%
|
|
|
|
alt Paramètres URL fournis
|
|
SP->>SP: _handleAutoRedirect()
|
|
Note over SP: Redirection auto vers<br/>/login/user ou /login/admin
|
|
else Pas de paramètres
|
|
SP->>SP: Afficher boutons de choix
|
|
Note over SP: User / Admin / Register
|
|
end
|
|
```
|
|
|
|
#### **Code : SplashPage._startInitialization() (lignes 325-501)**
|
|
|
|
```dart
|
|
void _startInitialization() async {
|
|
// Étape 1: Permissions GPS (Mobile uniquement) - 0 à 10%
|
|
if (!kIsWeb) {
|
|
final hasPermission = await LocationService.checkAndRequestPermission();
|
|
if (!hasPermission) {
|
|
setState(() {
|
|
_showLocationError = true;
|
|
_isInitializing = false;
|
|
});
|
|
return; // ❌ ARRÊT si permissions refusées
|
|
}
|
|
}
|
|
|
|
// Étape 2: Initialisation Hive complète - 15 à 60%
|
|
await HiveService.instance.initializeAndResetHive();
|
|
|
|
// Étape 3: Ouverture des Box - 60 à 80%
|
|
await HiveService.instance.ensureBoxesAreOpen();
|
|
|
|
// Étape 4: Vérification version + nettoyage auto - 80%
|
|
await _checkVersionAndCleanIfNeeded();
|
|
|
|
// Étape 5: Box pending_requests - 80%
|
|
await Hive.openBox(AppKeys.pendingRequestsBoxName);
|
|
|
|
// Étape 6: Vérification finale - 80 à 95%
|
|
final allBoxesOpen = HiveService.instance.areAllBoxesOpen();
|
|
|
|
// Étape 7: Marquer initialisation terminée - 95 à 100%
|
|
final settingsBox = Hive.box(AppKeys.settingsBoxName);
|
|
await settingsBox.put('hive_initialized', true);
|
|
await settingsBox.put('app_version', _appVersion);
|
|
|
|
// Redirection ou affichage boutons
|
|
if (widget.action != null) {
|
|
await _handleAutoRedirect();
|
|
} else {
|
|
setState(() => _showButtons = true);
|
|
}
|
|
}
|
|
```
|
|
|
|
**🔑 Boxes créées (14 au total) :**
|
|
|
|
| Box Name | Type | Usage |
|
|
|----------|------|-------|
|
|
| `users` | UserModel | Utilisateur connecté |
|
|
| `amicales` | AmicaleModel | Organisations |
|
|
| `clients` | ClientModel | Clients distributions |
|
|
| `operations` | OperationModel | Campagnes |
|
|
| `sectors` | SectorModel | Secteurs géographiques |
|
|
| `passages` | PassageModel | Distributions |
|
|
| `membres` | MembreModel | Équipes membres |
|
|
| `user_sector` | UserSectorModel | Affectations secteurs |
|
|
| `chat_rooms` | Room | Salles de chat |
|
|
| `chat_messages` | Message | Messages chat |
|
|
| `pending_requests` | PendingRequest | File requêtes offline |
|
|
| `temp_entities` | dynamic | Entités temporaires |
|
|
| `settings` | dynamic | **Paramètres app** ⚠️ |
|
|
| `regions` | dynamic | Régions |
|
|
|
|
**⚠️ Box critique : `settings`**
|
|
- Contient `hive_initialized` (flag d'initialisation complète)
|
|
- Contient `app_version` (détection changement de version)
|
|
|
|
---
|
|
|
|
### **3. Page de connexion : `LoginPage`**
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant LP as LoginPage
|
|
participant HS as HiveService
|
|
participant S as Settings Box
|
|
participant UR as UserRepository
|
|
|
|
LP->>LP: initState()
|
|
|
|
LP->>HS: areBoxesInitialized()
|
|
HS->>HS: Vérifier boxes critiques:<br/>users, membres, settings
|
|
|
|
alt Boxes non initialisées
|
|
HS-->>LP: false
|
|
LP->>LP: Redirection: '/?action=login&type=admin'
|
|
Note over LP: ❌ Retour SplashPage<br/>pour réinitialisation
|
|
else Boxes initialisées
|
|
HS-->>LP: true
|
|
|
|
LP->>S: get('hive_initialized')
|
|
|
|
alt hive_initialized != true
|
|
S-->>LP: false
|
|
LP->>LP: Redirection: '/?action=login&type=admin'
|
|
Note over LP: ❌ Retour SplashPage<br/>pour réinitialisation complète
|
|
else hive_initialized == true
|
|
S-->>LP: true
|
|
|
|
LP->>LP: Continuer initialisation
|
|
LP->>LP: Détecter loginType (user/admin)
|
|
LP->>UR: getAllUsers()
|
|
LP->>LP: Pré-remplir username si rôle correspond
|
|
LP->>LP: Afficher formulaire de connexion
|
|
end
|
|
end
|
|
```
|
|
|
|
#### **Code : LoginPage.initState() (lignes 100-162)**
|
|
|
|
```dart
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
// VÉRIFICATION 1 : Boxes critiques ouvertes ?
|
|
if (!HiveService.instance.areBoxesInitialized()) {
|
|
debugPrint('⚠️ Boxes Hive non initialisées, redirection vers SplashPage');
|
|
|
|
final loginType = widget.loginType ?? 'admin';
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (mounted) {
|
|
context.go('/?action=login&type=$loginType');
|
|
}
|
|
});
|
|
|
|
_loginType = '';
|
|
return; // ❌ ARRÊT de initState
|
|
}
|
|
|
|
// VÉRIFICATION 2 : Flag hive_initialized défini ?
|
|
try {
|
|
if (Hive.isBoxOpen(AppKeys.settingsBoxName)) {
|
|
final settingsBox = Hive.box(AppKeys.settingsBoxName);
|
|
final isInitialized = settingsBox.get('hive_initialized', defaultValue: false);
|
|
|
|
if (isInitialized != true) {
|
|
debugPrint('⚠️ Réinitialisation Hive requise');
|
|
|
|
final loginType = widget.loginType ?? 'admin';
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (mounted) {
|
|
context.go('/?action=login&type=$loginType');
|
|
}
|
|
});
|
|
|
|
_loginType = '';
|
|
return; // ❌ ARRÊT de initState
|
|
}
|
|
|
|
debugPrint('✅ Hive correctement initialisé');
|
|
}
|
|
} catch (e) {
|
|
// En cas d'erreur, forcer réinitialisation
|
|
final loginType = widget.loginType ?? 'admin';
|
|
context.go('/?action=login&type=$loginType');
|
|
return;
|
|
}
|
|
|
|
// ✅ Tout est OK : continuer initialisation normale
|
|
_loginType = widget.loginType!;
|
|
// ... pré-remplissage username, etc.
|
|
}
|
|
```
|
|
|
|
**🔑 Vérifications critiques :**
|
|
1. **`areBoxesInitialized()`** : Vérifie `users`, `membres`, `settings`
|
|
2. **`hive_initialized`** : Flag dans settings confirmant init complète
|
|
3. **Redirection automatique** : Si échec → retour SplashPage avec params
|
|
|
|
---
|
|
|
|
## 🧹 Flow avec nettoyage du cache
|
|
|
|
### **Déclenchement manuel (Web uniquement)**
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant U as Utilisateur
|
|
participant SP as SplashPage
|
|
participant Clean as _performSelectiveCleanup()
|
|
participant SW as Service Worker (Web)
|
|
participant H as Hive
|
|
participant PR as pending_requests
|
|
participant Settings as settings box
|
|
|
|
U->>SP: Clic "Nettoyer le cache"
|
|
SP->>U: Dialog confirmation
|
|
U->>SP: Confirme "Nettoyer"
|
|
|
|
SP->>Clean: _performSelectiveCleanup(manual: true)
|
|
|
|
Note over Clean: Progress: 10%
|
|
|
|
alt Sur Web (kIsWeb)
|
|
Clean->>SW: Désenregistrer Service Workers
|
|
Clean->>SW: Supprimer caches navigateur
|
|
SW-->>Clean: ✅ Caches web nettoyés
|
|
end
|
|
|
|
Note over Clean: Progress: 30%
|
|
|
|
Clean->>PR: Sauvegarder en mémoire
|
|
PR-->>Clean: List<dynamic> pendingRequests
|
|
|
|
Clean->>Settings: Sauvegarder app_version en mémoire
|
|
Settings-->>Clean: String savedAppVersion
|
|
|
|
Clean->>PR: Fermer box
|
|
Clean->>Settings: Fermer box
|
|
|
|
Note over Clean: Progress: 50%
|
|
|
|
Clean->>H: Fermer toutes les boxes
|
|
loop Pour chaque box (11 boxes)
|
|
Clean->>H: close() + deleteBoxFromDisk()
|
|
end
|
|
|
|
Note over Clean: ⚠️ Boxes supprimées:<br/>users, operations, passages,<br/>sectors, membres, amicale,<br/>clients, user_sector,<br/>chatRooms, chatMessages,<br/>settings
|
|
|
|
Note over Clean: ✅ Boxes préservées:<br/>pending_requests
|
|
|
|
Note over Clean: Progress: 70%
|
|
|
|
Clean->>H: Hive.close()
|
|
Clean->>H: Future.delayed(500ms)
|
|
Clean->>H: Hive.initFlutter()
|
|
|
|
Note over Clean: Progress: 80%
|
|
|
|
Clean->>PR: Restaurer pending_requests
|
|
loop Pour chaque requête
|
|
Clean->>PR: add(request)
|
|
end
|
|
|
|
Clean->>Settings: Restaurer app_version
|
|
Clean->>Settings: put('app_version', savedAppVersion)
|
|
|
|
Note over Clean: Progress: 100%
|
|
|
|
Clean-->>SP: ✅ Nettoyage terminé
|
|
|
|
SP->>SP: _startInitialization()
|
|
Note over SP: Redémarrage complet<br/>de l'application
|
|
```
|
|
|
|
#### **Code : SplashPage._performSelectiveCleanup() (lignes 84-243)**
|
|
|
|
```dart
|
|
Future<void> _performSelectiveCleanup({bool manual = false}) async {
|
|
debugPrint('🧹 === DÉBUT DU NETTOYAGE DU CACHE === 🧹');
|
|
|
|
try {
|
|
// Étape 1: Service Worker (Web uniquement) - 10%
|
|
if (kIsWeb) {
|
|
final registrations = await html.window.navigator.serviceWorker?.getRegistrations();
|
|
for (final registration in registrations) {
|
|
await registration.unregister();
|
|
}
|
|
|
|
final cacheNames = await html.window.caches!.keys();
|
|
for (final cacheName in cacheNames) {
|
|
await html.window.caches!.delete(cacheName);
|
|
}
|
|
}
|
|
|
|
// Étape 2: Sauvegarder pending_requests + app_version - 30%
|
|
List<dynamic>? pendingRequests;
|
|
String? savedAppVersion;
|
|
|
|
if (Hive.isBoxOpen(AppKeys.pendingRequestsBoxName)) {
|
|
final pendingBox = Hive.box(AppKeys.pendingRequestsBoxName);
|
|
pendingRequests = pendingBox.values.toList();
|
|
await pendingBox.close();
|
|
}
|
|
|
|
if (Hive.isBoxOpen(AppKeys.settingsBoxName)) {
|
|
final settingsBox = Hive.box(AppKeys.settingsBoxName);
|
|
savedAppVersion = settingsBox.get('app_version') as String?;
|
|
}
|
|
|
|
// Étape 3: Lister boxes à nettoyer - 50%
|
|
final boxesToClean = [
|
|
AppKeys.userBoxName,
|
|
AppKeys.operationsBoxName,
|
|
AppKeys.passagesBoxName,
|
|
AppKeys.sectorsBoxName,
|
|
AppKeys.membresBoxName,
|
|
AppKeys.amicaleBoxName,
|
|
AppKeys.clientsBoxName,
|
|
AppKeys.userSectorBoxName,
|
|
AppKeys.settingsBoxName, // ⚠️ Supprimée (mais version sauvegardée)
|
|
AppKeys.chatRoomsBoxName,
|
|
AppKeys.chatMessagesBoxName,
|
|
];
|
|
|
|
// Étape 4: Supprimer les boxes - 50%
|
|
for (final boxName in boxesToClean) {
|
|
if (Hive.isBoxOpen(boxName)) {
|
|
await Hive.box(boxName).close();
|
|
}
|
|
await Hive.deleteBoxFromDisk(boxName);
|
|
}
|
|
|
|
// Étape 5: Réinitialiser Hive - 70%
|
|
await Hive.close();
|
|
await Future.delayed(const Duration(milliseconds: 500));
|
|
await Hive.initFlutter();
|
|
|
|
// Étape 6: Restaurer données critiques - 80-100%
|
|
if (pendingRequests != null && pendingRequests.isNotEmpty) {
|
|
final pendingBox = await Hive.openBox(AppKeys.pendingRequestsBoxName);
|
|
for (final request in pendingRequests) {
|
|
await pendingBox.add(request);
|
|
}
|
|
}
|
|
|
|
if (savedAppVersion != null) {
|
|
final settingsBox = await Hive.openBox(AppKeys.settingsBoxName);
|
|
await settingsBox.put('app_version', savedAppVersion);
|
|
}
|
|
|
|
debugPrint('🎉 === NETTOYAGE TERMINÉ AVEC SUCCÈS === 🎉');
|
|
|
|
} catch (e) {
|
|
debugPrint('❌ ERREUR CRITIQUE lors du nettoyage: $e');
|
|
}
|
|
}
|
|
```
|
|
|
|
### **Nettoyage automatique sur changement de version**
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant SP as SplashPage
|
|
participant S as Settings Box
|
|
participant Check as _checkVersionAndCleanIfNeeded()
|
|
participant Clean as _performSelectiveCleanup()
|
|
|
|
SP->>SP: _startInitialization()
|
|
SP->>S: Boxes ouvertes
|
|
|
|
SP->>Check: _checkVersionAndCleanIfNeeded()
|
|
|
|
Check->>S: get('app_version')
|
|
S-->>Check: lastVersion = "3.2.3"
|
|
|
|
Check->>Check: currentVersion = "3.2.4"
|
|
|
|
alt Version changée
|
|
Check->>Check: lastVersion != currentVersion
|
|
Note over Check: 🆕 NOUVELLE VERSION DÉTECTÉE
|
|
|
|
Check->>Clean: _performSelectiveCleanup(manual: false)
|
|
Clean-->>Check: ✅ Nettoyage auto terminé
|
|
|
|
Check->>S: put('app_version', '3.2.4')
|
|
S-->>Check: ✅ Version mise à jour
|
|
|
|
else Même version
|
|
Check->>Check: lastVersion == currentVersion
|
|
Note over Check: ✅ Pas de nettoyage nécessaire
|
|
end
|
|
|
|
Check-->>SP: Terminé
|
|
```
|
|
|
|
**🔑 Cas d'usage :**
|
|
- **Déploiement nouvelle version web** : Cache automatiquement nettoyé
|
|
- **Update version mobile** : Détection et nettoyage auto
|
|
- **Préserve** : `pending_requests` (requêtes offline) + `app_version`
|
|
|
|
---
|
|
|
|
## 📦 Gestion des Hive Box
|
|
|
|
### **HiveService : Architecture complète**
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[HiveService Singleton] --> B[Initialisation]
|
|
A --> C[Nettoyage]
|
|
A --> D[Utilitaires]
|
|
|
|
B --> B1[initializeAndResetHive]
|
|
B --> B2[ensureBoxesAreOpen]
|
|
|
|
B1 --> B1a[_registerAdapters]
|
|
B1 --> B1b[_destroyAllData]
|
|
B1 --> B1c[_createAllBoxes]
|
|
|
|
B1b --> B1b1[_destroyDataWeb]
|
|
B1b --> B1b2[_destroyDataIOS]
|
|
B1b --> B1b3[_destroyDataAndroid]
|
|
B1b --> B1b4[_destroyDataDesktop]
|
|
|
|
C --> C1[cleanDataOnLogout]
|
|
C --> C2[_clearSingleBox]
|
|
|
|
D --> D1[areBoxesInitialized]
|
|
D --> D2[areAllBoxesOpen]
|
|
D --> D3[getDiagnostic]
|
|
|
|
style A fill:#e1f5ff
|
|
style B fill:#fff4e1
|
|
style C fill:#ffe1e1
|
|
style D fill:#e8f5e9
|
|
```
|
|
|
|
### **Méthodes critiques**
|
|
|
|
#### **1. `initializeAndResetHive()` - Initialisation complète**
|
|
|
|
**Appelée par** : `SplashPage._startInitialization()`
|
|
|
|
```dart
|
|
Future<void> initializeAndResetHive() async {
|
|
// 1. Initialisation de base
|
|
await Hive.initFlutter();
|
|
|
|
// 2. Enregistrement adaptateurs (14 types)
|
|
_registerAdapters();
|
|
|
|
// 3. Destruction complète des anciennes données
|
|
await _destroyAllData();
|
|
|
|
// 4. Création de toutes les Box vides et propres
|
|
await _createAllBoxes();
|
|
|
|
_isInitialized = true;
|
|
}
|
|
```
|
|
|
|
**⚠️ Comportement destructif** :
|
|
- Supprime TOUTES les boxes existantes
|
|
- Préserve `pending_requests` si elle contient des données
|
|
- Recrée des boxes vierges
|
|
|
|
---
|
|
|
|
#### **2. `areBoxesInitialized()` - Vérification rapide**
|
|
|
|
**Appelée par** : `LoginPage.initState()`
|
|
|
|
```dart
|
|
bool areBoxesInitialized() {
|
|
// Vérifier seulement les boxes critiques
|
|
final criticalBoxes = [
|
|
AppKeys.userBoxName, // getCurrentUser
|
|
AppKeys.membresBoxName, // Pré-remplissage
|
|
AppKeys.settingsBoxName, // Préférences
|
|
];
|
|
|
|
for (final boxName in criticalBoxes) {
|
|
if (!Hive.isBoxOpen(boxName)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!_isInitialized) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
```
|
|
|
|
**🔑 Boxes critiques vérifiées** :
|
|
- ✅ `users` : Nécessaire pour `getCurrentUser()`
|
|
- ✅ `membres` : Nécessaire pour pré-remplissage username
|
|
- ✅ `settings` : Contient `hive_initialized` et `app_version`
|
|
|
|
---
|
|
|
|
#### **3. `cleanDataOnLogout()` - Nettoyage logout**
|
|
|
|
**Appelée par** : `LoginPage` (bouton "Nettoyer le cache")
|
|
|
|
```dart
|
|
Future<void> cleanDataOnLogout() async {
|
|
// Nettoyer toutes les Box SAUF users
|
|
for (final config in _boxConfigs) {
|
|
if (config.name != AppKeys.userBoxName) {
|
|
await _clearSingleBox(config.name);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**⚠️ Préserve** : Box `users` (pour pré-remplissage username au prochain login)
|
|
|
|
---
|
|
|
|
## 🔍 Vérifications et redirections
|
|
|
|
### **Système de redirections automatiques**
|
|
|
|
```mermaid
|
|
graph TD
|
|
Start[Application démarre] --> Main[main.dart]
|
|
Main --> Splash[SplashPage]
|
|
|
|
Splash --> GPS{Permissions GPS?<br/>Mobile uniquement}
|
|
|
|
GPS -->|Refusées| ShowError[Afficher erreur GPS<br/>+ Boutons Réessayer/Paramètres]
|
|
ShowError --> End1[❌ Arrêt initialisation]
|
|
|
|
GPS -->|OK ou Web| InitHive[Initialisation Hive complète]
|
|
|
|
InitHive --> CheckVersion{Changement version?<br/>Web uniquement}
|
|
|
|
CheckVersion -->|Oui| CleanCache[Nettoyage auto du cache]
|
|
CleanCache --> OpenBoxes[Ouverture boxes]
|
|
|
|
CheckVersion -->|Non| OpenBoxes
|
|
|
|
OpenBoxes --> AllOpen{Toutes boxes<br/>ouvertes?}
|
|
|
|
AllOpen -->|Non| ErrorInit[❌ Erreur initialisation]
|
|
ErrorInit --> End2[Afficher message d'erreur]
|
|
|
|
AllOpen -->|Oui| SaveFlag[settings.put<br/>'hive_initialized' = true]
|
|
|
|
SaveFlag --> URLParams{Paramètres URL<br/>fournis?}
|
|
|
|
URLParams -->|Oui| AutoRedirect[Redirection auto<br/>/login/user ou /login/admin]
|
|
URLParams -->|Non| ShowButtons[Afficher boutons choix]
|
|
|
|
AutoRedirect --> Login[LoginPage]
|
|
ShowButtons --> UserClick{Utilisateur clique}
|
|
UserClick --> Login
|
|
|
|
Login --> CheckBoxes{Boxes initialisées?}
|
|
|
|
CheckBoxes -->|Non| BackSplash[Redirection<br/>'/?action=login&type=X']
|
|
BackSplash --> Splash
|
|
|
|
CheckBoxes -->|Oui| CheckFlag{hive_initialized<br/>== true?}
|
|
|
|
CheckFlag -->|Non| BackSplash
|
|
CheckFlag -->|Oui| ShowForm[✅ Afficher formulaire]
|
|
|
|
ShowForm --> UserLogin[Utilisateur se connecte]
|
|
UserLogin --> Dashboard[UserPage / AdminPage]
|
|
|
|
style Start fill:#e1f5ff
|
|
style Splash fill:#fff4e1
|
|
style Login fill:#e8f5e9
|
|
style Dashboard fill:#f3e5f5
|
|
style ShowError fill:#ffe1e1
|
|
style ErrorInit fill:#ffe1e1
|
|
```
|
|
|
|
### **Tableau des redirections**
|
|
|
|
| Condition | Action | Paramètres URL |
|
|
|-----------|--------|----------------|
|
|
| **Boxes non initialisées** | Redirect → SplashPage | `/?action=login&type=admin` |
|
|
| **`hive_initialized` != true** | Redirect → SplashPage | `/?action=login&type=user` |
|
|
| **Permissions GPS refusées** | Afficher erreur | Aucune redirection |
|
|
| **Changement version (Web)** | Nettoyage auto | Transparent |
|
|
| **Nettoyage manuel** | Réinitialisation complète | Vers `/` après nettoyage |
|
|
|
|
---
|
|
|
|
## ⚠️ Points critiques
|
|
|
|
### **1. Box `settings` - Données essentielles**
|
|
|
|
**Contenu** :
|
|
- `hive_initialized` (bool) : Flag confirmant initialisation complète
|
|
- `app_version` (String) : Version actuelle pour détection changements
|
|
- Autres paramètres utilisateur
|
|
|
|
**⚠️ Importance** :
|
|
- Si `settings` est supprimée sans sauvegarde → perte de la version
|
|
- Si `hive_initialized` est absent → boucle de réinitialisation
|
|
|
|
**✅ Solution actuelle** :
|
|
- Nettoyage du cache : sauvegarde `app_version` en mémoire avant suppression
|
|
- Restauration automatique après réinitialisation Hive
|
|
|
|
---
|
|
|
|
### **2. Box `pending_requests` - Requêtes offline**
|
|
|
|
**Contenu** :
|
|
- File d'attente des requêtes API en mode hors ligne
|
|
- Modèle : `PendingRequest`
|
|
|
|
**⚠️ Protection** :
|
|
- JAMAIS supprimée pendant nettoyage si elle contient des données
|
|
- Sauvegardée en mémoire pendant `_performSelectiveCleanup()`
|
|
- Restaurée après réinitialisation
|
|
|
|
**Code protection** :
|
|
```dart
|
|
// Dans _performSelectiveCleanup()
|
|
if (Hive.isBoxOpen(AppKeys.pendingRequestsBoxName)) {
|
|
final pendingBox = Hive.box(AppKeys.pendingRequestsBoxName);
|
|
pendingRequests = pendingBox.values.toList(); // Sauvegarde
|
|
await pendingBox.close();
|
|
}
|
|
|
|
// ... nettoyage des autres boxes ...
|
|
|
|
// Restauration
|
|
if (pendingRequests != null && pendingRequests.isNotEmpty) {
|
|
final pendingBox = await Hive.openBox(AppKeys.pendingRequestsBoxName);
|
|
for (final request in pendingRequests) {
|
|
await pendingBox.add(request);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### **3. Permissions GPS (Mobile uniquement)**
|
|
|
|
**Vérification obligatoire** :
|
|
- Sur mobile : `LocationService.checkAndRequestPermission()`
|
|
- Si refusées : affichage erreur + arrêt initialisation
|
|
- Sur web : vérification ignorée
|
|
|
|
**Messages contextuels** :
|
|
```dart
|
|
final errorMessage = await LocationService.getLocationErrorMessage();
|
|
|
|
// Exemples de messages :
|
|
// - "Permissions refusées temporairement"
|
|
// - "Permissions refusées définitivement - ouvrir Paramètres"
|
|
// - "Service de localisation désactivé"
|
|
```
|
|
|
|
---
|
|
|
|
### **4. Bouton "Nettoyer le cache" (Web uniquement)**
|
|
|
|
**Restriction plateforme** :
|
|
```dart
|
|
// Dans splash_page.dart (ligne 932)
|
|
if (kIsWeb)
|
|
AnimatedOpacity(
|
|
child: TextButton.icon(
|
|
label: Text('Nettoyer le cache'),
|
|
// ...
|
|
),
|
|
),
|
|
```
|
|
|
|
**Fonctionnalités Web spécifiques** :
|
|
- Désenregistrement Service Workers
|
|
- Suppression caches navigateur (`window.caches`)
|
|
- Nettoyage localStorage (via Service Worker)
|
|
|
|
**⚠️ Sur mobile** : Utilise `HiveService.cleanDataOnLogout()` (dans LoginPage)
|
|
|
|
---
|
|
|
|
### **5. Détection automatique d'environnement**
|
|
|
|
**ApiService** :
|
|
```dart
|
|
// Détection basée sur l'URL
|
|
if (currentUrl.contains('dapp.geosector.fr')) → DEV
|
|
if (currentUrl.contains('rapp.geosector.fr')) → REC
|
|
if (currentUrl.contains('app3.geosector.fr')) → PROD
|
|
Sinon → PROD
|
|
```
|
|
|
|
**Impact sur le nettoyage** :
|
|
- Web DEV/REC : nettoyage auto sur changement version
|
|
- Web PROD : nettoyage auto sur changement version
|
|
- Mobile : pas de nettoyage auto (version gérée par stores)
|
|
|
|
---
|
|
|
|
## 📊 Récapitulatif des états
|
|
|
|
### **États de l'application**
|
|
|
|
| État | Description | Boxes Hive | Flag `hive_initialized` |
|
|
|------|-------------|-----------|------------------------|
|
|
| **Démarrage initial** | Premier lancement | Vides | ❌ Absent |
|
|
| **Initialisé** | SplashPage terminé | Ouvertes et vides | ✅ `true` |
|
|
| **Connecté** | Utilisateur loggé | Remplies avec données API | ✅ `true` |
|
|
| **Après nettoyage** | Cache vidé | Réinitialisées | ✅ `true` (restauré) |
|
|
| **Erreur init** | Échec initialisation | Partielles ou fermées | ❌ Absent ou `false` |
|
|
|
|
### **Chemins possibles**
|
|
|
|
```
|
|
main.dart
|
|
↓
|
|
SplashPage (initialisation)
|
|
↓
|
|
[Web] Vérification version → Nettoyage auto si besoin
|
|
↓
|
|
[Mobile] Vérification GPS → Erreur si refusé
|
|
↓
|
|
Ouverture 14 boxes Hive
|
|
↓
|
|
settings.put('hive_initialized', true)
|
|
↓
|
|
LoginPage
|
|
↓
|
|
Vérification boxes + hive_initialized
|
|
↓
|
|
[OK] Afficher formulaire
|
|
[KO] Redirection SplashPage
|
|
```
|
|
|
|
---
|
|
|
|
## 🎯 Conclusion
|
|
|
|
Le système de démarrage GEOSECTOR v3.2.4 implémente une architecture robuste en **3 étapes** avec des **vérifications multiples** et une **gestion intelligente du cache**.
|
|
|
|
**Points forts** :
|
|
- ✅ Initialisation progressive avec feedback visuel (barre de progression)
|
|
- ✅ Protection des données critiques (`pending_requests`, `app_version`)
|
|
- ✅ Détection automatique des problèmes (boxes non ouvertes, version changée)
|
|
- ✅ Redirections automatiques pour forcer réinitialisation si nécessaire
|
|
- ✅ Nettoyage sélectif du cache (Web uniquement)
|
|
|
|
**Sécurités** :
|
|
- ⚠️ Vérification permissions GPS (mobile obligatoire)
|
|
- ⚠️ Double vérification Hive (boxes + flag `hive_initialized`)
|
|
- ⚠️ Sauvegarde mémoire avant nettoyage (`pending_requests`, `app_version`)
|
|
- ⚠️ Restriction plateforme (bouton cache Web uniquement)
|
|
|
|
---
|
|
|
|
**Document généré le** : 04 octobre 2025
|
|
**Version application** : v3.2.4
|
|
**Auteur** : Documentation technique GEOSECTOR
|