feat: Version 3.3.4 - Nouvelle architecture pages, optimisations widgets Flutter et API
- Mise à jour VERSION vers 3.3.4 - Optimisations et révisions architecture API (deploy-api.sh, scripts de migration) - Ajout documentation Stripe Tap to Pay complète - Migration vers polices Inter Variable pour Flutter - Optimisations build Android et nettoyage fichiers temporaires - Amélioration système de déploiement avec gestion backups - Ajout scripts CRON et migrations base de données 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import 'package:geosector_app/core/services/connectivity_service.dart';
|
||||
import 'package:geosector_app/core/data/models/pending_request.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'device_info_service.dart';
|
||||
|
||||
class ApiService {
|
||||
static ApiService? _instance;
|
||||
@@ -150,7 +151,7 @@ class ApiService {
|
||||
|
||||
final currentUrl = html.window.location.href.toLowerCase();
|
||||
|
||||
if (currentUrl.contains('app.geo.dev')) {
|
||||
if (currentUrl.contains('dapp.geosector.fr')) {
|
||||
return 'DEV';
|
||||
} else if (currentUrl.contains('rapp.geosector.fr')) {
|
||||
return 'REC';
|
||||
@@ -208,7 +209,7 @@ class ApiService {
|
||||
}
|
||||
// Fallback sur la vérification directe
|
||||
final connectivityResult = await (Connectivity().checkConnectivity());
|
||||
return connectivityResult.contains(ConnectivityResult.none) == false;
|
||||
return connectivityResult != ConnectivityResult.none;
|
||||
}
|
||||
|
||||
// Met une requête en file d'attente pour envoi ultérieur
|
||||
@@ -1046,6 +1047,15 @@ class ApiService {
|
||||
final sessionId = data['session_id'];
|
||||
if (sessionId != null) {
|
||||
setSessionId(sessionId);
|
||||
|
||||
// Collecter et envoyer les informations du device après login réussi
|
||||
debugPrint('📱 Collecte des informations device après login...');
|
||||
DeviceInfoService.instance.collectAndSendDeviceInfo().then((_) {
|
||||
debugPrint('✅ Informations device collectées et envoyées');
|
||||
}).catchError((error) {
|
||||
debugPrint('⚠️ Erreur lors de l\'envoi des infos device: $error');
|
||||
// Ne pas bloquer le login si l'envoi des infos device échoue
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1058,6 +1068,71 @@ class ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
// === MÉTHODES DE REFRESH DE SESSION ===
|
||||
|
||||
/// Rafraîchit toutes les données de session (pour F5, démarrage)
|
||||
/// Retourne les mêmes données qu'un login normal
|
||||
Future<Response> refreshSessionAll() async {
|
||||
try {
|
||||
debugPrint('🔄 Refresh complet de session');
|
||||
|
||||
// Vérifier qu'on a bien un token/session
|
||||
if (_sessionId == null) {
|
||||
throw ApiException('Pas de session active pour le refresh');
|
||||
}
|
||||
|
||||
final response = await post('/session/refresh/all');
|
||||
|
||||
// Traiter la réponse comme un login
|
||||
final data = response.data as Map<String, dynamic>?;
|
||||
if (data != null && data['status'] == 'success') {
|
||||
// Si nouveau session_id dans la réponse, le mettre à jour
|
||||
if (data.containsKey('session_id')) {
|
||||
final newSessionId = data['session_id'];
|
||||
if (newSessionId != null) {
|
||||
setSessionId(newSessionId);
|
||||
}
|
||||
}
|
||||
|
||||
// Collecter et envoyer les informations du device après refresh réussi
|
||||
debugPrint('📱 Collecte des informations device après refresh de session...');
|
||||
DeviceInfoService.instance.collectAndSendDeviceInfo().then((_) {
|
||||
debugPrint('✅ Informations device collectées et envoyées (refresh)');
|
||||
}).catchError((error) {
|
||||
debugPrint('⚠️ Erreur lors de l\'envoi des infos device (refresh): $error');
|
||||
// Ne pas bloquer le refresh si l'envoi des infos device échoue
|
||||
});
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (e) {
|
||||
debugPrint('❌ Erreur refresh complet: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Rafraîchit partiellement les données modifiées depuis lastSync
|
||||
/// Ne retourne que les données modifiées (delta)
|
||||
Future<Response> refreshSessionPartial(DateTime lastSync) async {
|
||||
try {
|
||||
debugPrint('🔄 Refresh partiel depuis: ${lastSync.toIso8601String()}');
|
||||
|
||||
// Vérifier qu'on a bien un token/session
|
||||
if (_sessionId == null) {
|
||||
throw ApiException('Pas de session active pour le refresh');
|
||||
}
|
||||
|
||||
final response = await post('/session/refresh/partial', data: {
|
||||
'last_sync': lastSync.toIso8601String(),
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (e) {
|
||||
debugPrint('❌ Erreur refresh partiel: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// Déconnexion
|
||||
Future<void> logout() async {
|
||||
try {
|
||||
@@ -1199,7 +1274,7 @@ class ApiService {
|
||||
final blob = html.Blob([bytes]);
|
||||
final url = html.Url.createObjectUrlFromBlob(blob);
|
||||
|
||||
final anchor = html.AnchorElement(href: url)
|
||||
html.AnchorElement(href: url)
|
||||
..setAttribute('download', fileName)
|
||||
..click();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user