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

@@ -4,7 +4,6 @@ import 'dart:io';
import 'package:dio/dio.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:path_provider/path_provider.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:geosector_app/core/data/models/user_model.dart';
@@ -69,10 +68,15 @@ class ApiService {
_dio.options.headers.addAll(headers);
// Gestionnaire de cookies pour les sessions PHP
// Utilise CookieJar en mémoire (cookies maintenus pendant la durée de vie de l'app)
final cookieJar = CookieJar();
_dio.interceptors.add(CookieManager(cookieJar));
debugPrint('🍪 [API] Gestionnaire de cookies activé');
// IMPORTANT: Désactivé sur Web car les navigateurs bloquent la manipulation des cookies via XHR
// Sur Web, on utilise uniquement le header Authorization avec Bearer token
if (!kIsWeb) {
final cookieJar = CookieJar();
_dio.interceptors.add(CookieManager(cookieJar));
debugPrint('🍪 [API] Gestionnaire de cookies activé (mobile)');
} else {
debugPrint('🌐 [API] Mode Web - pas de CookieManager (Bearer token uniquement)');
}
_dio.interceptors.add(InterceptorsWrapper(
onRequest: (options, handler) {

View File

@@ -1,6 +1,6 @@
// ⚠️ AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
// This file is automatically generated by deploy-app.sh script
// Last update: 2026-01-16 13:37:45
// Last update: 2026-01-19 15:35:06
// Source: ../VERSION file
//
// GEOSECTOR App Version Service
@@ -8,10 +8,10 @@
class AppInfoService {
// Version number (format: x.x.x)
static const String version = '3.6.2';
static const String version = '3.6.3';
// Build number (version without dots: xxx)
static const String buildNumber = '362';
static const String buildNumber = '363';
// Full version string (format: vx.x.x+xxx)
static String get fullVersion => 'v$version+$buildNumber';

View File

@@ -140,18 +140,43 @@ class CurrentUserService extends ChangeNotifier {
Future<void> loadFromHive() async {
try {
final box = Hive.box<UserModel>(AppKeys.userBoxName); // Nouvelle Box
final user = box.get('current_user');
// 1. Récupérer l'ID utilisateur depuis settings
if (!Hive.isBoxOpen(AppKeys.settingsBoxName)) {
debugPrint('⚠️ Box settings non ouverte, impossible de charger l\'utilisateur');
_currentUser = null;
notifyListeners();
return;
}
final settingsBox = Hive.box(AppKeys.settingsBoxName);
final userId = settingsBox.get('current_user_id');
if (userId == null) {
debugPrint(' Aucun current_user_id trouvé dans settings');
_currentUser = null;
notifyListeners();
return;
}
debugPrint('🔍 Recherche utilisateur avec ID: $userId');
// 2. Récupérer l'utilisateur avec le bon ID
final box = Hive.box<UserModel>(AppKeys.userBoxName);
final user = box.get(userId);
if (user?.hasValidSession == true) {
_currentUser = user;
debugPrint('📥 Utilisateur chargé depuis Hive: ${user?.email}');
debugPrint('📥 Utilisateur chargé depuis Hive: ${user?.email} (ID: $userId)');
// Charger le mode d'affichage sauvegardé lors de la connexion
await _loadDisplayMode();
} else {
_currentUser = null;
debugPrint(' Aucun utilisateur valide trouvé dans Hive');
if (user == null) {
debugPrint(' Utilisateur ID $userId non trouvé dans la box');
} else {
debugPrint(' Session expirée pour l\'utilisateur ${user.email}');
}
}
notifyListeners();

View File

@@ -50,6 +50,57 @@ class HiveService {
bool _isInitialized = false;
bool get isInitialized => _isInitialized;
// === INITIALISATION LÉGÈRE POUR F5 (préserve les données) ===
/// Initialisation légère de Hive SANS destruction des données
/// Utilisée pour le F5 sur Web afin de vérifier si une session existe
/// Retourne true si l'initialisation a réussi et qu'une session utilisateur existe
Future<bool> initializeWithoutReset() async {
try {
debugPrint('🔧 Initialisation légère de Hive (préservation des données)...');
// 1. Initialisation de base de Hive (idempotent)
await Hive.initFlutter();
debugPrint('✅ Hive.initFlutter() terminé');
// 2. Enregistrement des adaptateurs (idempotent)
_registerAdapters();
// 3. Ouvrir les boxes SANS les détruire
await _createAllBoxes();
// 4. Vérifier si une session utilisateur existe
bool hasSession = false;
try {
if (Hive.isBoxOpen(AppKeys.settingsBoxName)) {
final settingsBox = Hive.box(AppKeys.settingsBoxName);
final userId = settingsBox.get('current_user_id');
if (userId != null) {
// Vérifier que l'utilisateur existe dans la box user
if (Hive.isBoxOpen(AppKeys.userBoxName)) {
final userBox = Hive.box<UserModel>(AppKeys.userBoxName);
final user = userBox.get(userId);
if (user != null && user.hasValidSession) {
hasSession = true;
debugPrint('✅ Session utilisateur trouvée pour ID: $userId');
}
}
}
}
} catch (e) {
debugPrint('⚠️ Erreur vérification session: $e');
}
_isInitialized = true;
debugPrint('✅ Initialisation légère terminée, session existante: $hasSession');
return hasSession;
} catch (e) {
debugPrint('❌ Erreur lors de l\'initialisation légère: $e');
return false;
}
}
// === INITIALISATION COMPLÈTE (appelée par main.dart) ===
/// Initialisation complète de Hive avec réinitialisation totale