feat: Release version 3.1.4 - Mode terrain et génération PDF
✨ Nouvelles fonctionnalités: - Ajout du mode terrain pour utilisation mobile hors connexion - Génération automatique de reçus PDF avec template personnalisé - Révision complète du système de cartes avec amélioration des performances 🔧 Améliorations techniques: - Refactoring du module chat avec architecture simplifiée - Optimisation du système de sécurité NIST SP 800-63B - Amélioration de la gestion des secteurs géographiques - Support UTF-8 étendu pour les noms d'utilisateurs 📱 Application mobile: - Nouveau mode terrain dans user_field_mode_page - Interface utilisateur adaptative pour conditions difficiles - Synchronisation offline améliorée 🗺️ Cartographie: - Optimisation des performances MapBox - Meilleure gestion des tuiles hors ligne - Amélioration de l'affichage des secteurs 📄 Documentation: - Ajout guide Android (ANDROID-GUIDE.md) - Documentation sécurité API (API-SECURITY.md) - Guide module chat (CHAT_MODULE.md) 🐛 Corrections: - Résolution des erreurs 400 lors de la création d'utilisateurs - Correction de la validation des noms d'utilisateurs - Fix des problèmes de synchronisation chat 🤖 Generated with Claude Code (https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:flutter_map_cache/flutter_map_cache.dart';
|
||||
import 'package:http_cache_file_store/http_cache_file_store.dart';
|
||||
@@ -46,6 +47,9 @@ class MapboxMap extends StatefulWidget {
|
||||
|
||||
/// Désactive le drag de la carte
|
||||
final bool disableDrag;
|
||||
|
||||
/// Utiliser OpenStreetMap au lieu de Mapbox (en cas de problème de token)
|
||||
final bool useOpenStreetMap;
|
||||
|
||||
const MapboxMap({
|
||||
super.key,
|
||||
@@ -60,6 +64,7 @@ class MapboxMap extends StatefulWidget {
|
||||
this.showControls = true,
|
||||
this.mapStyle,
|
||||
this.disableDrag = false,
|
||||
this.useOpenStreetMap = false,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -70,7 +75,8 @@ class _MapboxMapState extends State<MapboxMap> {
|
||||
/// Contrôleur de carte interne
|
||||
late final MapController _mapController;
|
||||
|
||||
/// Niveau de zoom actuel
|
||||
/// Niveau de zoom actuel (utilisé pour l'affichage futur)
|
||||
// ignore: unused_field
|
||||
double _currentZoom = 13.0;
|
||||
|
||||
/// Provider de cache pour les tuiles
|
||||
@@ -91,7 +97,9 @@ class _MapboxMapState extends State<MapboxMap> {
|
||||
Future<void> _initializeCache() async {
|
||||
try {
|
||||
final dir = await getTemporaryDirectory();
|
||||
final cacheStore = FileCacheStore('${dir.path}${Platform.pathSeparator}MapboxTileCache');
|
||||
// Utiliser un nom de cache différent selon le provider
|
||||
final cacheName = widget.useOpenStreetMap ? 'OSMTileCache' : 'MapboxTileCache';
|
||||
final cacheStore = FileCacheStore('${dir.path}${Platform.pathSeparator}$cacheName');
|
||||
|
||||
_tileProvider = CachedTileProvider(
|
||||
store: cacheStore,
|
||||
@@ -105,12 +113,14 @@ class _MapboxMapState extends State<MapboxMap> {
|
||||
_cacheInitialized = true;
|
||||
});
|
||||
}
|
||||
debugPrint('MapboxMap: Cache initialisé avec succès pour ${widget.useOpenStreetMap ? "OpenStreetMap" : "Mapbox"}');
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de l\'initialisation du cache: $e');
|
||||
debugPrint('MapboxMap: Erreur lors de l\'initialisation du cache: $e');
|
||||
// En cas d'erreur, on continue sans cache
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_cacheInitialized = true;
|
||||
_tileProvider = null; // Utiliser NetworkTileProvider en fallback
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -138,7 +148,7 @@ class _MapboxMapState extends State<MapboxMap> {
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
color: Colors.black.withValues(alpha: 0.2),
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 3),
|
||||
),
|
||||
@@ -155,19 +165,41 @@ class _MapboxMapState extends State<MapboxMap> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Déterminer l'URL du template de tuiles Mapbox
|
||||
// Utiliser l'environnement actuel pour obtenir la bonne clé API
|
||||
final String environment = ApiService.instance.getCurrentEnvironment();
|
||||
final String mapboxToken = AppKeys.getMapboxApiKey(environment);
|
||||
final String mapStyle = widget.mapStyle ?? 'mapbox/streets-v11';
|
||||
final String urlTemplate = 'https://api.mapbox.com/styles/v1/$mapStyle/tiles/256/{z}/{x}/{y}@2x?access_token=$mapboxToken';
|
||||
String urlTemplate;
|
||||
|
||||
if (widget.useOpenStreetMap) {
|
||||
// Utiliser OpenStreetMap comme alternative
|
||||
urlTemplate = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
|
||||
debugPrint('MapboxMap: Utilisation d\'OpenStreetMap');
|
||||
} else {
|
||||
// Déterminer l'URL du template de tuiles Mapbox
|
||||
// Utiliser l'environnement actuel pour obtenir la bonne clé API
|
||||
final String environment = ApiService.instance.getCurrentEnvironment();
|
||||
final String mapboxToken = AppKeys.getMapboxApiKey(environment);
|
||||
|
||||
// Essayer différentes API Mapbox selon la plateforme
|
||||
if (kIsWeb) {
|
||||
// Sur web, on peut utiliser l'API styles
|
||||
urlTemplate = 'https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/256/{z}/{x}/{y}@2x?access_token=$mapboxToken';
|
||||
} else {
|
||||
// Sur mobile, utiliser l'API v4 qui fonctionne mieux avec les tokens standards
|
||||
// Format: mapbox.streets pour les rues, mapbox.satellite pour satellite
|
||||
urlTemplate = 'https://api.tiles.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}@2x.png?access_token=$mapboxToken';
|
||||
}
|
||||
|
||||
// Debug pour vérifier la configuration
|
||||
debugPrint('MapboxMap: Plateforme: ${kIsWeb ? "Web" : "Mobile"}');
|
||||
debugPrint('MapboxMap: Environnement: $environment');
|
||||
debugPrint('MapboxMap: Token: ${mapboxToken.substring(0, 10)}...'); // Afficher seulement le début du token
|
||||
debugPrint('MapboxMap: URL Template: ${urlTemplate.substring(0, 50)}...');
|
||||
}
|
||||
|
||||
// Afficher un indicateur pendant l'initialisation du cache
|
||||
if (!_cacheInitialized) {
|
||||
return Stack(
|
||||
children: [
|
||||
// Carte sans cache en attendant
|
||||
_buildMapContent(urlTemplate, mapboxToken),
|
||||
_buildMapContent(urlTemplate),
|
||||
// Indicateur discret
|
||||
const Positioned(
|
||||
top: 8,
|
||||
@@ -194,10 +226,10 @@ class _MapboxMapState extends State<MapboxMap> {
|
||||
);
|
||||
}
|
||||
|
||||
return _buildMapContent(urlTemplate, mapboxToken);
|
||||
return _buildMapContent(urlTemplate);
|
||||
}
|
||||
|
||||
Widget _buildMapContent(String urlTemplate, String mapboxToken) {
|
||||
Widget _buildMapContent(String urlTemplate) {
|
||||
return Stack(
|
||||
children: [
|
||||
// Carte principale
|
||||
@@ -232,13 +264,24 @@ class _MapboxMapState extends State<MapboxMap> {
|
||||
urlTemplate: urlTemplate,
|
||||
userAgentPackageName: 'app.geosector.fr',
|
||||
maxNativeZoom: 19,
|
||||
additionalOptions: {
|
||||
'accessToken': mapboxToken,
|
||||
},
|
||||
// Utilise le cache si disponible
|
||||
maxZoom: 20,
|
||||
minZoom: 1,
|
||||
// Retirer tileSize pour utiliser la valeur par défaut
|
||||
// Les additionalOptions ne sont pas nécessaires car le token est dans l'URL
|
||||
// Utilise le cache si disponible sur web, NetworkTileProvider sur mobile
|
||||
tileProvider: _cacheInitialized && _tileProvider != null
|
||||
? _tileProvider!
|
||||
: NetworkTileProvider(),
|
||||
: NetworkTileProvider(
|
||||
headers: {
|
||||
'User-Agent': 'geosector_app/3.1.3',
|
||||
'Accept': '*/*',
|
||||
},
|
||||
),
|
||||
errorTileCallback: (tile, error, stackTrace) {
|
||||
debugPrint('MapboxMap: Erreur de chargement de tuile: $error');
|
||||
debugPrint('MapboxMap: Coordonnées de la tuile: ${tile.coordinates}');
|
||||
debugPrint('MapboxMap: Stack trace: $stackTrace');
|
||||
},
|
||||
),
|
||||
|
||||
// Polygones
|
||||
|
||||
Reference in New Issue
Block a user