feat: Version 3.6.3 - Carte IGN, mode boussole, corrections Flutter analyze

Nouvelles fonctionnalités:
- #215 Mode boussole + carte IGN/satellite (Mode terrain)
- #53 Définition zoom maximal pour éviter sur-zoom
- #14 Correction bug F5 déconnexion
- #204 Design couleurs flashy
- #205 Écrans utilisateurs simplifiés

Corrections Flutter analyze:
- Suppression warnings room.g.dart, chat_service.dart, api_service.dart
- 0 error, 0 warning, 30 infos (suggestions de style)

Autres:
- Intégration tuiles IGN Plan et IGN Ortho (geopf.fr)
- flutter_compass pour Android/iOS
- Réorganisation assets store

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-19 17:46:03 +01:00
parent 232940b1eb
commit 5b6808db25
62 changed files with 1428 additions and 3130 deletions

View File

@@ -313,13 +313,29 @@ class _SplashPageState extends State<SplashPage> with SingleTickerProviderStateM
// Appeler le nouvel endpoint API pour restaurer la session
// IMPORTANT: Utiliser getWithoutQueue() pour ne JAMAIS mettre cette requête en file d'attente
// Les refresh de session sont liés à une session spécifique et ne doivent pas être rejoués
debugPrint('🔄 Appel API: user/session avec sessionId: ${sessionId.substring(0, 10)}...');
final response = await ApiService.instance.getWithoutQueue(
'/api/user/session',
'user/session',
queryParameters: {'mode': displayMode},
);
// Gestion des codes de retour HTTP
final statusCode = response.statusCode ?? 0;
// Vérifier que la réponse est bien du JSON et pas du HTML
if (response.data is String) {
final dataStr = response.data as String;
if (dataStr.contains('<!DOCTYPE') || dataStr.contains('<html')) {
debugPrint('❌ ERREUR: L\'API a retourné du HTML au lieu de JSON !');
debugPrint('❌ StatusCode: $statusCode');
debugPrint('❌ URL de base: ${ApiService.instance.baseUrl}');
debugPrint('❌ Début de la réponse: ${dataStr.substring(0, 100)}...');
await CurrentUserService.instance.clearUser();
return false;
}
}
final data = response.data as Map<String, dynamic>?;
switch (statusCode) {
@@ -589,9 +605,9 @@ class _SplashPageState extends State<SplashPage> with SingleTickerProviderStateM
_progress = 0.12;
});
}
await Future.delayed(const Duration(milliseconds: 200)); // Petit délai pour voir le début
if (mounted) {
setState(() {
_statusMessage = "Chargement des composants...";
@@ -599,21 +615,68 @@ class _SplashPageState extends State<SplashPage> with SingleTickerProviderStateM
});
}
// Étape 2: Initialisation Hive - 15 à 60% (étape la plus longue)
await HiveService.instance.initializeAndResetHive();
// === GESTION F5 WEB : Vérifier session AVANT de détruire les données ===
// Sur Web, on essaie d'abord de récupérer une session existante
if (kIsWeb) {
debugPrint('🌐 Web détecté - tentative de récupération de session existante...');
if (mounted) {
setState(() {
_statusMessage = "Vérification de session...";
_progress = 0.20;
});
}
// Initialisation légère qui préserve les données
final hasExistingSession = await HiveService.instance.initializeWithoutReset();
if (hasExistingSession) {
debugPrint('✅ Session existante détectée, tentative de restauration...');
if (mounted) {
setState(() {
_statusMessage = "Restauration de la session...";
_progress = 0.40;
});
}
// Tenter la restauration via l'API
final sessionRestored = await _handleSessionRefreshIfNeeded();
if (sessionRestored) {
debugPrint('✅ Session restaurée via F5 - fin de l\'initialisation');
return;
}
// Si la restauration API échoue, on continue vers le login
debugPrint('⚠️ Restauration API échouée, passage au login normal');
} else {
debugPrint(' Pas de session existante, initialisation normale');
}
}
// === INITIALISATION NORMALE (si pas de session F5 ou pas Web) ===
// Étape 2: Initialisation Hive complète - 15 à 60%
if (mounted) {
setState(() {
_statusMessage = "Configuration du stockage...";
_progress = 0.45;
_progress = 0.30;
});
}
await Future.delayed(const Duration(milliseconds: 300)); // Simulation du temps de traitement
await HiveService.instance.initializeAndResetHive();
if (mounted) {
setState(() {
_statusMessage = "Préparation des données...";
_progress = 0.45;
});
}
await Future.delayed(const Duration(milliseconds: 300)); // Simulation du temps de traitement
if (mounted) {
setState(() {
_statusMessage = "Ouverture des bases...";
_progress = 0.60;
});
}
@@ -621,19 +684,9 @@ class _SplashPageState extends State<SplashPage> with SingleTickerProviderStateM
// Étape 3: Ouverture des Box - 60 à 80%
await HiveService.instance.ensureBoxesAreOpen();
// NOUVEAU : Vérifier et nettoyer si nouvelle version (Web uniquement)
// Maintenant que les boxes sont ouvertes, on peut vérifier la version dans Hive
// Vérifier et nettoyer si nouvelle version (Web uniquement)
await _checkVersionAndCleanIfNeeded();
// NOUVEAU : Détecter et gérer le F5 (refresh de page web avec session existante)
final sessionRestored = await _handleSessionRefreshIfNeeded();
if (sessionRestored) {
// Session restaurée avec succès, on arrête ici
// L'utilisateur a été redirigé vers son interface
debugPrint('✅ Session restaurée via F5 - fin de l\'initialisation');
return;
}
// Gérer la box pending_requests séparément pour préserver les données
try {
debugPrint('📦 Gestion de la box pending_requests...');