feat: Version 3.5.2 - Configuration Stripe et gestion des immeubles

- 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>
This commit is contained in:
pierre
2025-11-09 18:26:27 +01:00
parent 21657a3820
commit 2f5946a184
812 changed files with 142105 additions and 25992 deletions

2
app/.bundle/config Normal file
View File

@@ -0,0 +1,2 @@
---
BUNDLE_PATH: "vendor/bundle"

View File

@@ -11,10 +11,7 @@ import 'package:connectivity_plus/src/connectivity_plus_web.dart';
import 'package:device_info_plus/src/device_info_plus_web.dart';
import 'package:geolocator_web/geolocator_web.dart';
import 'package:image_picker_for_web/image_picker_for_web.dart';
import 'package:network_info_plus/src/network_info_plus_web.dart';
import 'package:package_info_plus/src/package_info_plus_web.dart';
import 'package:permission_handler_html/permission_handler_html.dart';
import 'package:sensors_plus/src/sensors_plus_web.dart';
import 'package:url_launcher_web/url_launcher_web.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
@@ -25,10 +22,7 @@ void registerPlugins([final Registrar? pluginRegistrar]) {
DeviceInfoPlusWebPlugin.registerWith(registrar);
GeolocatorPlugin.registerWith(registrar);
ImagePickerPlugin.registerWith(registrar);
NetworkInfoPlusWebPlugin.registerWith(registrar);
PackageInfoPlusWebPlugin.registerWith(registrar);
WebPermissionHandler.registerWith(registrar);
WebSensorsPlugin.registerWith(registrar);
UrlLauncherPlugin.registerWith(registrar);
registrar.registerMessageHandler();
}

View File

@@ -1,31 +0,0 @@
Extension Discovery Cache
=========================
This folder is used by `package:extension_discovery` to cache lists of
packages that contains extensions for other packages.
DO NOT USE THIS FOLDER
----------------------
* Do not read (or rely) the contents of this folder.
* Do write to this folder.
If you're interested in the lists of extensions stored in this folder use the
API offered by package `extension_discovery` to get this information.
If this package doesn't work for your use-case, then don't try to read the
contents of this folder. It may change, and will not remain stable.
Use package `extension_discovery`
---------------------------------
If you want to access information from this folder.
Feel free to delete this folder
-------------------------------
Files in this folder act as a cache, and the cache is discarded if the files
are older than the modification time of `.dart_tool/package_config.json`.
Hence, it should never be necessary to clear this cache manually, if you find a
need to do please file a bug.

View File

@@ -1 +0,0 @@
{"version":2,"entries":[{"package":"geosector_app","rootUri":"../","packageUri":"lib/"}]}

View File

@@ -1,362 +0,0 @@
//
// Generated file. Do not edit.
// This file is generated from template in file `flutter_tools/lib/src/flutter_plugins.dart`.
//
// @dart = 3.0
import 'dart:io'; // flutter_ignore: dart_io_import.
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:geolocator_android/geolocator_android.dart';
import 'package:image_picker_android/image_picker_android.dart';
import 'package:path_provider_android/path_provider_android.dart';
import 'package:url_launcher_android/url_launcher_android.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:geolocator_apple/geolocator_apple.dart';
import 'package:image_picker_ios/image_picker_ios.dart';
import 'package:path_provider_foundation/path_provider_foundation.dart';
import 'package:url_launcher_ios/url_launcher_ios.dart';
import 'package:battery_plus/battery_plus.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:file_selector_linux/file_selector_linux.dart';
import 'package:flutter_local_notifications_linux/flutter_local_notifications_linux.dart';
import 'package:image_picker_linux/image_picker_linux.dart';
import 'package:network_info_plus/network_info_plus.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider_linux/path_provider_linux.dart';
import 'package:url_launcher_linux/url_launcher_linux.dart';
import 'package:file_selector_macos/file_selector_macos.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:geolocator_apple/geolocator_apple.dart';
import 'package:image_picker_macos/image_picker_macos.dart';
import 'package:path_provider_foundation/path_provider_foundation.dart';
import 'package:url_launcher_macos/url_launcher_macos.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:file_selector_windows/file_selector_windows.dart';
import 'package:flutter_local_notifications_windows/flutter_local_notifications_windows.dart';
import 'package:image_picker_windows/image_picker_windows.dart';
import 'package:network_info_plus/network_info_plus.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider_windows/path_provider_windows.dart';
import 'package:url_launcher_windows/url_launcher_windows.dart';
@pragma('vm:entry-point')
class _PluginRegistrant {
@pragma('vm:entry-point')
static void register() {
if (Platform.isAndroid) {
try {
AndroidFlutterLocalNotificationsPlugin.registerWith();
} catch (err) {
print(
'`flutter_local_notifications` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
GeolocatorAndroid.registerWith();
} catch (err) {
print(
'`geolocator_android` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
ImagePickerAndroid.registerWith();
} catch (err) {
print(
'`image_picker_android` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
PathProviderAndroid.registerWith();
} catch (err) {
print(
'`path_provider_android` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
UrlLauncherAndroid.registerWith();
} catch (err) {
print(
'`url_launcher_android` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
} else if (Platform.isIOS) {
try {
IOSFlutterLocalNotificationsPlugin.registerWith();
} catch (err) {
print(
'`flutter_local_notifications` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
GeolocatorApple.registerWith();
} catch (err) {
print(
'`geolocator_apple` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
ImagePickerIOS.registerWith();
} catch (err) {
print(
'`image_picker_ios` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
PathProviderFoundation.registerWith();
} catch (err) {
print(
'`path_provider_foundation` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
UrlLauncherIOS.registerWith();
} catch (err) {
print(
'`url_launcher_ios` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
} else if (Platform.isLinux) {
try {
BatteryPlusLinuxPlugin.registerWith();
} catch (err) {
print(
'`battery_plus` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
ConnectivityPlusLinuxPlugin.registerWith();
} catch (err) {
print(
'`connectivity_plus` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
DeviceInfoPlusLinuxPlugin.registerWith();
} catch (err) {
print(
'`device_info_plus` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
FileSelectorLinux.registerWith();
} catch (err) {
print(
'`file_selector_linux` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
LinuxFlutterLocalNotificationsPlugin.registerWith();
} catch (err) {
print(
'`flutter_local_notifications_linux` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
ImagePickerLinux.registerWith();
} catch (err) {
print(
'`image_picker_linux` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
NetworkInfoPlusLinuxPlugin.registerWith();
} catch (err) {
print(
'`network_info_plus` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
PackageInfoPlusLinuxPlugin.registerWith();
} catch (err) {
print(
'`package_info_plus` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
PathProviderLinux.registerWith();
} catch (err) {
print(
'`path_provider_linux` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
UrlLauncherLinux.registerWith();
} catch (err) {
print(
'`url_launcher_linux` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
} else if (Platform.isMacOS) {
try {
FileSelectorMacOS.registerWith();
} catch (err) {
print(
'`file_selector_macos` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
MacOSFlutterLocalNotificationsPlugin.registerWith();
} catch (err) {
print(
'`flutter_local_notifications` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
GeolocatorApple.registerWith();
} catch (err) {
print(
'`geolocator_apple` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
ImagePickerMacOS.registerWith();
} catch (err) {
print(
'`image_picker_macos` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
PathProviderFoundation.registerWith();
} catch (err) {
print(
'`path_provider_foundation` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
UrlLauncherMacOS.registerWith();
} catch (err) {
print(
'`url_launcher_macos` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
} else if (Platform.isWindows) {
try {
DeviceInfoPlusWindowsPlugin.registerWith();
} catch (err) {
print(
'`device_info_plus` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
FileSelectorWindows.registerWith();
} catch (err) {
print(
'`file_selector_windows` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
FlutterLocalNotificationsWindows.registerWith();
} catch (err) {
print(
'`flutter_local_notifications_windows` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
ImagePickerWindows.registerWith();
} catch (err) {
print(
'`image_picker_windows` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
NetworkInfoPlusWindowsPlugin.registerWith();
} catch (err) {
print(
'`network_info_plus` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
PackageInfoPlusWindowsPlugin.registerWith();
} catch (err) {
print(
'`package_info_plus` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
PathProviderWindows.registerWith();
} catch (err) {
print(
'`path_provider_windows` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
try {
UrlLauncherWindows.registerWith();
} catch (err) {
print(
'`url_launcher_windows` threw an error: $err. '
'The app may not function as expected until you remove this plugin from pubspec.yaml'
);
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
3.35.5
3.24.5

View File

@@ -13,4 +13,4 @@ BACKUP_SERVER2_KEY="/path/to/private_key2"
BACKUP_SERVER2_PATH="/path/to/backups"
# Configuration générale
BACKUP_RETENTION_DAYS=30 # Nombre de jours de conservation des backups
BACKUP_RETENTION_DAYS=10 # Nombre de jours de conservation des backups

File diff suppressed because one or more lines are too long

12
app/.gitignore vendored
View File

@@ -29,6 +29,7 @@ migrate_working_dir/
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub-cache-local/
.pub/
/build/
@@ -101,6 +102,7 @@ web/flutter.js
*.freezed.dart
.cxx/
.gradle/
.gradle-local/
gradlew
gradlew.bat
local.properties
@@ -109,7 +111,15 @@ local.properties
# *.sh
# /docs/
# Security & Credentials
android/google-play-api-key.json
android/key.properties
android/app/*.jks
fastlane/google-play-api-key.json
ios/AuthKey_*.p8
# Build outputs (APK/AAB)
*.apk
*.aab
*.ipa
*.ipa
vendor/bundle

View File

@@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.
version:
revision: "c23637390482d4cf9598c3ce3f2be31aa7332daf"
revision: "ac4e799d237041cf905519190471f657b657155a"
channel: "stable"
project_type: app
@@ -13,11 +13,11 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf
create_revision: ac4e799d237041cf905519190471f657b657155a
base_revision: ac4e799d237041cf905519190471f657b657155a
- platform: ios
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf
create_revision: ac4e799d237041cf905519190471f657b657155a
base_revision: ac4e799d237041cf905519190471f657b657155a
# User provided section

View File

@@ -56,13 +56,13 @@ adb install -r app-release.apk
adb install -t app-debug.apk
# Désinstaller une application
adb uninstall fr.geosector.app2025
adb uninstall fr.geosector.app3025
# Lister les packages installés
adb shell pm list packages | grep geosector
# Voir le chemin d'installation d'une app
adb shell pm path fr.geosector.app2025
adb shell pm path fr.geosector.app3025
```
## 📊 Logs et débogage en temps réel
@@ -119,13 +119,13 @@ adb logcat | grep -i geosector
### Lancer l'application depuis ADB
```bash
# Démarrer l'application
adb shell monkey -p fr.geosector.app2025 -c android.intent.category.LAUNCHER 1
adb shell monkey -p fr.geosector.app3025 -c android.intent.category.LAUNCHER 1
# Ou avec am (Activity Manager)
adb shell am start -n fr.geosector.app2025/.MainActivity
adb shell am start -n fr.geosector.app3025/.MainActivity
# Forcer l'arrêt de l'application
adb shell am force-stop fr.geosector.app2025
adb shell am force-stop fr.geosector.app3025
```
### Capturer des screenshots
@@ -142,10 +142,10 @@ adb pull /sdcard/demo.mp4 ./demo.mp4
### Informations système
```bash
# Voir l'utilisation mémoire
adb shell dumpsys meminfo fr.geosector.app2025
adb shell dumpsys meminfo fr.geosector.app3025
# Voir les permissions de l'app
adb shell dumpsys package fr.geosector.app2025 | grep permission
adb shell dumpsys package fr.geosector.app3025 | grep permission
# Version d'Android
adb shell getprop ro.build.version.release
@@ -231,10 +231,10 @@ sudo usermod -aG plugdev $USER
### Permissions Android
```bash
# Accorder une permission manuellement
adb shell pm grant fr.geosector.app2025 android.permission.ACCESS_FINE_LOCATION
adb shell pm grant fr.geosector.app3025 android.permission.ACCESS_FINE_LOCATION
# Révoquer une permission
adb shell pm revoke fr.geosector.app2025 android.permission.ACCESS_FINE_LOCATION
adb shell pm revoke fr.geosector.app3025 android.permission.ACCESS_FINE_LOCATION
# Lister toutes les permissions
adb shell pm list permissions -g
@@ -307,7 +307,7 @@ flutter build apk --release
adb install -r build/app/outputs/flutter-apk/app-release.apk
# Lancer l'application
adb shell am start -n fr.geosector.app2025/.MainActivity
adb shell am start -n fr.geosector.app3025/.MainActivity
# Afficher les logs
echo "📊 Logs en temps réel (CTRL+C pour arrêter)..."

287
app/BUILD-IOS-SUCCESS.md Normal file
View File

@@ -0,0 +1,287 @@
# 🎉 BUILD iOS RÉUSSI - GEOSECTOR v3.3.6
**Date** : 14 octobre 2025
**Statut** : ✅ **SUCCÈS**
**Temps de compilation** : 59,1 secondes
```
✓ Built build/ios/iphoneos/Runner.app (107.4MB)
```
---
## 🏆 Résultat
Après **5 tentatives** avec différentes versions de Flutter et **plusieurs heures de debugging**, la compilation iOS fonctionne maintenant parfaitement avec **Flutter 3.24.5 LTS**.
---
## 🔧 Configuration finale qui fonctionne
| Composant | Version | Statut |
|-----------|---------|--------|
| **Flutter** | 3.24.5 LTS | ✅ |
| **Dart** | 3.5.4 | ✅ |
| **Xcode** | 16.4 | ✅ |
| **iOS Deployment Target** | 15.4+ | ✅ |
| **CocoaPods** | 1.16.2 | ✅ |
| **Pods installés** | 22 pods | ✅ |
---
## 💡 La solution en une ligne
**Problème** : `permission_handler_apple-9.4.7` embarquait ses propres headers Flutter
**Solution** : Script automatique `fix-permission-handler.sh` qui :
1. Supprime le dossier `/ios/Classes/Flutter/` du package
2. Corrige les imports : `"Flutter/Flutter.h"``<Flutter/Flutter.h>`
---
## 🚀 Commande unique pour rebuilder
```bash
flutter clean && flutter pub get && ./fix-permission-handler.sh && cd ios && pod install && cd .. && flutter build ios --release --no-codesign
```
---
## 📦 Packages critiques
### ✅ Packages qui fonctionnent
- `flutter_stripe: 11.5.0` - Paiements Stripe
- `mek_stripe_terminal: 4.6.0` - Tap to Pay on iPhone
- `nfc_manager: 3.3.0` - Lecture NFC
- `geolocator: 13.0.4` - GPS
- `permission_handler: 12.0.1` - Permissions iOS
- `device_info_plus: 11.3.0` - Infos device
### ⚠️ Package nécessitant un fix
- `permission_handler_apple: 9.4.7` - **Nécessite `./fix-permission-handler.sh`**
### ❌ Packages supprimés (problématiques)
- `package_info_plus` → Remplacé par `AppInfoService`
- `network_info_plus` → Remplacé par `NetworkInterface` natif
- `sensors_plus` → Mode boussole retiré
---
## 📝 Workflow pour les prochains builds
### Build quotidien (sans modification de dépendances)
```bash
flutter build ios --release --no-codesign
```
### Après modification de dépendances
```bash
flutter pub get
./fix-permission-handler.sh
cd ios && pod install && cd ..
flutter build ios --release --no-codesign
```
### Build complet (clean)
```bash
flutter clean
flutter pub get
./fix-permission-handler.sh
cd ios && pod install && cd ..
flutter build ios --release --no-codesign
```
---
## 🎯 Prochaines étapes vers l'App Store
### 1. Ouvrir dans Xcode
```bash
open ios/Runner.xcworkspace
```
### 2. Vérifier la configuration
- ✅ Team : `6WT84NWCTC`
- ✅ Bundle ID : `fr.geosector.app3`
- ✅ Version : `3.3.6`
- ✅ Build : `336`
### 3. Créer l'archive
Dans Xcode :
1. Sélectionner **Any iOS Device (arm64)**
2. **Product** > **Clean Build Folder** (Cmd+Shift+K)
3. **Product** > **Archive**
### 4. Valider l'archive
1. Organizer s'ouvre automatiquement
2. **Validate App** (~2-5 minutes)
3. Corriger les éventuels problèmes
### 5. Upload vers App Store Connect
1. **Distribute App**
2. Sélectionner **App Store Connect**
3. **Upload**
4. Attendre la fin (~5-15 minutes)
---
## 📚 Documentation créée
| Fichier | Description |
|---------|-------------|
| `SOLUTION-IOS.md` | Guide complet de la solution finale |
| `SCRIPTS-IOS.md` | Documentation des scripts automatisés |
| `BUILD-IOS-SUCCESS.md` | Ce fichier - Récapitulatif du succès |
| `fix-permission-handler.sh` | Script de correction automatique |
| `README-IOS.md` | Historique des tentatives (existant) |
| `TRANSFERT-MAC.md` | Guide de transfert Linux → Mac (existant) |
---
## ⚠️ Points d'attention
### À faire après chaque `flutter pub get`
```bash
./fix-permission-handler.sh
```
**Pourquoi** : Le package `permission_handler_apple` se réinstalle avec ses headers problématiques.
### Avant de mettre à jour Flutter
1. ✅ Vérifier la compatibilité des packages avec la nouvelle version
2. ✅ Tester la compilation iOS après upgrade
3. ✅ Vérifier que le script `fix-permission-handler.sh` fonctionne toujours
### Si problème de compilation après une mise à jour
```bash
# Nettoyage complet
rm -rf build ios/Pods ios/Podfile.lock ios/.symlinks
rm ios/Flutter/Generated.xcconfig
# Régénération
flutter pub get
./fix-permission-handler.sh
cd ios && pod install && cd ..
flutter build ios --release --no-codesign
```
---
## 🎊 Statistiques du projet
### Temps investi dans la résolution iOS
- **Tentatives de compilation** : 5 versions de Flutter testées
- **Packages testés/downgradés** : ~15 packages modifiés
- **Temps total de debugging** : ~6-8 heures
- **Solution trouvée** : 14/10/2025 12:30
### Résultat final
-**Build iOS** : Fonctionnel
-**Build Android** : Fonctionnel (avec fix nfc_manager)
-**Build Web** : Fonctionnel
-**3 plateformes** : Compilent avec succès
---
## 🙏 Leçons apprises
### Ce qui a fonctionné
1.**Downgrade vers Flutter 3.24.5 LTS** - Version stable sans bugs SwiftPM
2.**Suppression des packages problématiques** - Mieux que de chercher des workarounds complexes
3.**Analyse du contenu des packages** - Inspecter `.pub-cache` révèle les vrais problèmes
4.**Scripts automatisés** - Évite de refaire les mêmes corrections manuellement
### Ce qui n'a PAS fonctionné
1. ❌ Flutter 3.35.x - Bugs SwiftPM non résolus
2. ❌ Flutter 3.27.x - Transition SwiftPM instable
3. ❌ Workarounds complexes dans Podfile - Ne résout pas le problème à la source
4. ❌ Copie manuelle des headers Flutter - Créait encore plus de conflits
---
## 🔗 Ressources utiles
### Documentation Apple
- [App Store Connect](https://appstoreconnect.apple.com)
- [Apple Developer](https://developer.apple.com)
- [Tap to Pay on iPhone](https://developer.apple.com/tap-to-pay/)
### Documentation Flutter
- [Flutter 3.24.5 Release Notes](https://github.com/flutter/flutter/releases/tag/3.24.5)
- [iOS Deployment Guide](https://docs.flutter.dev/deployment/ios)
- [CocoaPods Setup](https://guides.cocoapods.org/using/getting-started.html)
### Issues GitHub pertinentes
- [flutter/flutter #137945](https://github.com/flutter/flutter/issues/137945) - SwiftPM transition issues
---
## ✅ Checklist finale avant soumission App Store
### Configuration
- [ ] Team configuré : `6WT84NWCTC`
- [ ] Bundle ID correct : `fr.geosector.app3`
- [ ] Version incrémentée : `3.3.6 (336)`
- [ ] Certificats de signature valides
### Tests
- [ ] Test sur simulateur iOS 15.4+
- [ ] Test sur device physique
- [ ] Test des fonctionnalités critiques :
- [ ] GPS / Géolocalisation
- [ ] NFC (lecture tags)
- [ ] Stripe (paiements)
- [ ] Mode hors ligne
- [ ] Notifications
### Archive et upload
- [ ] Archive créée sans erreur
- [ ] Validation réussie (Organizer)
- [ ] Upload vers App Store Connect terminé
- [ ] Build visible dans App Store Connect
### App Store Connect
- [ ] Métadonnées remplies
- [ ] Captures d'écran uploadées
- [ ] Description mise à jour
- [ ] Nouveautés de version rédigées
- [ ] Politique de confidentialité en ligne
- [ ] Build sélectionné pour révision
---
**🎉 FÉLICITATIONS ! La compilation iOS fonctionne maintenant parfaitement !**
**Prêt pour** : Archive Xcode → App Store Connect → Révision Apple
---
**Auteur** : Claude Code + Pierre
**Version** : 1.0.0
**Date de succès** : 14 octobre 2025
**Statut** : ✅ **RÉSOLU**

154
app/BUNDLE-ID-UPDATE.md Normal file
View File

@@ -0,0 +1,154 @@
# 📝 Mise à jour Bundle ID - GEOSECTOR v3.3.6
**Date** : 14/10/2025
**Raison** : Nouvelle application sur l'App Store
---
## 🆔 Bundle IDs par plateforme
| Plateforme | Bundle ID | Statut |
|-----------|-----------|--------|
| **iOS** | `fr.geosector.app3` | ✅ **NOUVEAU** (App Store v3) |
| **Android** | `fr.geosector.app2025` | ✅ Inchangé |
| **Web** | N/A | ✅ N/A |
---
## 📝 Changements iOS
### Ancien Bundle ID
- `fr.geosector.app2` (ancienne application App Store)
### Nouveau Bundle ID
- `fr.geosector.app3` (nouvelle application App Store)
**Raison du changement** : Nouvelle application distincte sur l'App Store
---
## ✅ Fichiers mis à jour
| Fichier | Type | Modifications |
|---------|------|---------------|
| `ios.sh` | Script | Bundle ID mis à jour |
| `BUILD-IOS-SUCCESS.md` | Documentation | 2 occurrences mises à jour |
| `SOLUTION-IOS.md` | Documentation | 1 occurrence mise à jour |
| `README-SCRIPTS.md` | Documentation | 2 occurrences mises à jour |
| `README-IOS.md` | Documentation | Mise à jour |
| `TRANSFERT-MAC.md` | Documentation | Mise à jour |
| `deploy-app.sh` | Script | Package name mis à jour |
---
## 🔧 Configuration Xcode
### Signing & Capabilities
-**Signing manual** : Activé
-**Bundle Identifier** : `fr.geosector.app3`
-**Team** : Pierre VAISSAIRE (6WT84NWCTC)
-**Provisioning Profile** : GeoSector v3 App Store
-**Signing Certificate** : Apple Distribution: Pierre VAISSAIRE
---
## 📱 App Store Connect
### Nouvelle application à créer
1. ✅ Se connecter sur [App Store Connect](https://appstoreconnect.apple.com)
2. ✅ Créer une nouvelle application
- **Bundle ID** : `fr.geosector.app3`
- **Nom** : GeoSector v3
- **SKU** : geosector-v3
- **Langue principale** : Français
3. ✅ Configurer les métadonnées
4. ✅ Uploader le build
---
## ⚠️ Points d'attention
### Ne pas confondre
-**iOS** : `fr.geosector.app3` (NOUVEAU)
-**Android** : `fr.geosector.app2025` (différent !)
### Ancienne application App Store
- L'ancienne application (`fr.geosector.app2`) reste disponible
- Nouvelle application (`fr.geosector.app3`) = refonte complète v3
- Les utilisateurs devront télécharger la nouvelle app
---
## 🚀 Prochaines étapes
### 1. Créer l'archive Xcode
```bash
./ios.sh
```
Ou manuellement :
```bash
open ios/Runner.xcworkspace
# Product > Archive dans Xcode
```
### 2. Valider l'archive
- Organizer > Validate App
- Vérifier que le Bundle ID est bien `fr.geosector.app3`
### 3. Upload vers App Store Connect
- Organizer > Distribute App > App Store Connect > Upload
### 4. Créer l'application dans App Store Connect
- Utiliser le Bundle ID : `fr.geosector.app3`
- Sélectionner le build uploadé
### 5. Configurer et soumettre
- Métadonnées
- Captures d'écran
- Informations de révision
- Soumettre pour révision Apple
---
## 📚 Historique
| Date | Version | Bundle ID | Notes |
|------|---------|-----------|-------|
| 2024 | 2.7.1 | `fr.geosector.app2` | Ancienne version App Store |
| 14/10/2025 | 3.3.6 | `fr.geosector.app3` | Nouvelle application - Refonte v3 |
---
## ✅ Vérification de la configuration
Pour vérifier que tout est correct :
```bash
# Vérifier le Bundle ID dans le script
grep "Bundle ID" ios.sh
# Vérifier dans Xcode
open ios/Runner.xcworkspace
# Target Runner > General > Bundle Identifier
```
**Résultat attendu** : `fr.geosector.app3`
---
**Auteur** : Claude Code + Pierre
**Date** : 14/10/2025
**Version** : 1.0.0
**Tous les fichiers sont maintenant à jour avec le nouveau Bundle ID iOS `fr.geosector.app3`**

View File

@@ -215,8 +215,8 @@ class MyModel extends HiveObject {
#### **Auto-Detection**
The app automatically detects environment based on URL:
- `dapp.geosector.fr` → DEV environment
- `rapp.geosector.fr` → REC environment
- Production → PROD environment
- `rapp.geosector.fr` → REC environment
- `app3.geosector.fr` → PROD environment
- Non-web platforms → DEV by default
#### **API Configuration**

279
app/FASTLANE.md Normal file
View File

@@ -0,0 +1,279 @@
# 🚀 Guide Fastlane - Déploiement automatisé iOS/Android
**Date** : 22/10/2025
**Version actuelle** : 3.4.2 (Build 342)
---
## 📋 Objectif
Automatiser 100% du déploiement iOS et Android depuis Debian, sans écran ni manipulation manuelle sur le Mac mini.
**Avant** : Transfert manuel + Xcode GUI + 30 min de clics
**Après** : 1 commande SSH + 0 supervision
---
## 🎯 Installation
### 1⃣ Sur le Mac mini (192.168.1.34) - Runtime uniquement
```bash
# Connexion SSH
ssh pierre@192.168.1.34
# Installer fastlane via Homebrew (recommandé)
brew install fastlane
# Vérifier l'installation
fastlane --version
# Activer le partage SSH (si pas déjà fait)
# Préférences Système > Partage > Session à distance
```
### 2⃣ Sur Debian - Configuration du projet
```bash
# Installer Ruby (si pas déjà fait)
sudo apt install ruby-full build-essential
# Configurer Bundler pour installation locale
cd /home/pierre/dev/geosector/app
echo "source 'https://rubygems.org'" > Gemfile
echo "gem 'fastlane'" >> Gemfile
bundle config set --local path 'vendor/bundle'
bundle install
# Ajouter au .gitignore
echo "vendor/bundle" >> .gitignore
# Vérifier
bundle exec fastlane --version
```
**Important** : Cette installation est à faire **une seule fois par projet Flutter**. Le dossier `fastlane/` est versionné dans Git et transféré avec le code.
---
## ⚙️ Configuration initiale
### 1⃣ Initialiser fastlane dans le projet (sur Debian)
```bash
cd /home/pierre/dev/geosector/app
bundle exec fastlane init
# Sélectionner :
# iOS : Option 2 (Automate beta distribution to TestFlight)
# Android : Option 2 (Automate deployment to Google Play)
```
### 2⃣ Configurer les credentials
**Pour iOS (App Store Connect)** :
- Apple ID : votre compte développeur
- Team ID : `6WT84NWCTC`
- App Identifier : `fr.geosector.app`
**Pour Android (Google Play Console)** :
- JSON API Key : télécharger depuis Google Play Console > API Access
- Package name : `fr.geosector.app`
- Keystore : utiliser votre keystore existant
### 3⃣ Créer le Fastfile
Créer `fastlane/Fastfile` avec les lanes iOS et Android :
- Lane iOS : clean + build + archive + upload TestFlight
- Lane Android : clean + build AAB + upload Play Store
### 4⃣ Versionner dans Git
```bash
# Commit la configuration fastlane
git add Gemfile Gemfile.lock fastlane/ .gitignore
git commit -m "chore: add fastlane configuration"
git push
```
### 5⃣ Tester localement
```bash
# Transférer vers Mac mini
rsync -avz --exclude 'build' --exclude '.dart_tool' . pierre@192.168.1.34:/Users/pierre/dev/geosector/app_342/
# Test iOS sur Mac mini
ssh pierre@192.168.1.34 "cd /Users/pierre/dev/geosector/app_342 && fastlane ios release"
# Test Android sur Mac mini
ssh pierre@192.168.1.34 "cd /Users/pierre/dev/geosector/app_342 && fastlane android release"
```
---
## 🚀 Utilisation depuis Debian
### Workflow simple
```bash
# 1. Transférer le code vers le Mac mini (crée app_342/)
cd /home/pierre/dev/geosector/app
rsync -avz --exclude 'build' --exclude '.dart_tool' --exclude 'vendor/bundle' . pierre@192.168.1.34:/Users/pierre/dev/geosector/app_342/
# 2. Lancer le build iOS à distance
ssh pierre@192.168.1.34 "cd /Users/pierre/dev/geosector/app_342 && fastlane ios release"
# 3. Lancer le build Android à distance
ssh pierre@192.168.1.34 "cd /Users/pierre/dev/geosector/app_342 && fastlane android release"
# 4. Archiver la version après succès
ssh pierre@192.168.1.34 "cd /Users/pierre/dev/geosector && zip -r app_342.zip app_342"
```
### Workflow parallèle (iOS + Android simultané)
```bash
# Transfert vers dossier versionné
rsync -avz --exclude 'build' --exclude 'vendor/bundle' . pierre@192.168.1.34:/Users/pierre/dev/geosector/app_342/
# Build iOS et Android en parallèle
ssh pierre@192.168.1.34 "cd /Users/pierre/dev/geosector/app_342 && fastlane ios release & fastlane android release"
```
### Créer un script de déploiement
Créer `deploy-all.sh` dans le projet :
- Étape 1 : rsync vers Mac mini
- Étape 2 : fastlane ios release
- Étape 3 : fastlane android release
- Étape 4 : notification de fin
Usage : `./deploy-all.sh`
---
## ⚡ CI/CD avec Gitea Actions
### Objectif
Automatiser le déploiement à chaque `git push` sur la branche `main` ou `release`.
### Architecture
```
Gitea (gitea.d6soft.fr)
↓ git push
Gitea Actions (workflow)
↓ SSH
Mac mini (self-hosted runner)
↓ fastlane
App Store Connect + Google Play Console
```
### Configuration
**1. Activer Gitea Actions**
- Gitea > Settings > Actions > Enable Actions
- Créer un runner sur le Mac mini
**2. Installer le runner sur le Mac mini**
- Télécharger act_runner depuis Gitea
- Enregistrer le runner avec le token Gitea
- Lancer le runner en service (launchd)
**3. Créer le workflow `.gitea/workflows/deploy.yml`**
- Trigger : `push` sur branche `main` ou tag `v*`
- Steps : checkout + flutter pub get + fastlane ios release + fastlane android release
- Runner : `runs-on: self-hosted`
**4. Sécuriser les secrets**
- Gitea > Settings > Secrets
- Ajouter : APPLE_ID, FASTLANE_PASSWORD, GOOGLE_PLAY_JSON_KEY
- Utiliser `${{ secrets.APPLE_ID }}` dans le workflow
### Résultat
```bash
# Sur Debian
cd /home/pierre/dev/geosector/app
git add .
git commit -m "feat: nouvelle fonctionnalité"
git push origin main
# 🤖 Gitea Actions détecte le push
# 🏗️ Mac mini build automatiquement
# 📤 Upload vers TestFlight + Play Store
# ✅ Notification par email/Slack
```
**Zéro action manuelle, déploiement automatique 24/7.**
---
## 📊 Checklist de migration
### Phase 1 : Installation de base
- [ ] Fastlane installé sur Mac mini
- [ ] Fastfile créé et testé pour iOS
- [ ] Fastfile créé et testé pour Android
- [ ] Credentials configurés (Apple ID, Google Play)
- [ ] Test manuel réussi : `fastlane ios release`
- [ ] Test manuel réussi : `fastlane android release`
### Phase 2 : Déploiement distant
- [ ] SSH sans mot de passe configuré (clé SSH)
- [ ] Script `deploy-all.sh` créé et testé
- [ ] Test de déploiement complet depuis Debian
- [ ] Validation sur TestFlight + Play Store
### Phase 3 : CI/CD (optionnel mais recommandé)
- [ ] Gitea Actions activé sur le dépôt
- [ ] Runner installé sur Mac mini
- [ ] Workflow `.gitea/workflows/deploy.yml` créé
- [ ] Secrets configurés dans Gitea
- [ ] Test de déploiement automatique sur `git push`
- [ ] Notifications configurées (email/Slack)
---
## 🎯 Gains de productivité
| Action | Avant | Après |
|--------|-------|-------|
| Build iOS | 30 min (manuel + VNC) | 1 commande SSH |
| Build Android | 20 min (manuel) | 1 commande SSH |
| Upload stores | 10 min (formulaires) | Automatique |
| Présence requise | 60 min | 0 min |
| Mac mini | Écran + clavier | Headless |
| Déploiement | À la demande | Automatique sur git push |
**Temps gagné par release : ~60 minutes → 0 minute**
---
## 📚 Ressources
- **Fastlane** : https://fastlane.tools
- **Gitea Actions** : https://docs.gitea.com/usage/actions/overview
- **App Store Connect** : https://appstoreconnect.apple.com
- **Google Play Console** : https://play.google.com/console
---
## 🔧 Troubleshooting
**Erreur "Could not find action"**
→ Vérifier que fastlane est dans le PATH du Mac mini
**Erreur de signature iOS**
→ Vérifier que les certificats sont bien installés sur le Mac mini (Xcode > Preferences > Accounts)
**Erreur Google Play API**
→ Vérifier que le JSON key a les bonnes permissions (Admin/Release Manager)
**Runner Gitea ne démarre pas**
→ Vérifier les logs : `journalctl -u gitea-runner -f`
---
**Mac mini headless opérationnel !** 🎉

2
app/Gemfile Normal file
View File

@@ -0,0 +1,2 @@
source 'https://rubygems.org'
gem 'fastlane'

229
app/Gemfile.lock Normal file
View File

@@ -0,0 +1,229 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.7)
base64
nkf
rexml
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.4.0)
aws-partitions (1.1174.0)
aws-sdk-core (3.234.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
base64
bigdecimal
jmespath (~> 1, >= 1.6.1)
logger
aws-sdk-kms (1.115.0)
aws-sdk-core (~> 3, >= 3.234.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.201.0)
aws-sdk-core (~> 3, >= 3.234.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.12.1)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
base64 (0.3.0)
bigdecimal (3.3.1)
claide (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
declarative (0.0.20)
digest-crc (0.7.0)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.6.20240107)
dotenv (2.8.1)
emoji_regex (3.2.3)
excon (0.112.0)
faraday (1.10.4)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.7)
faraday (>= 0.8.0)
http-cookie (~> 1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.1)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.1.1)
multipart-post (~> 2.0)
faraday-net_http (1.0.2)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.1)
faraday (~> 1.0)
fastimage (2.4.0)
fastlane (2.228.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored (~> 1.2)
commander (~> 4.6)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
fastlane-sirp (>= 1.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-env (>= 1.6.0, < 2.0.0)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
naturally (~> 2.2)
optparse (>= 0.1.1, < 1.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.5)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (~> 3)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.4.1)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
fastlane-sirp (1.0.0)
sysrandom (~> 1.0)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.54.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.3)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
rexml
google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.31.0)
google-apis-core (>= 0.11.0, < 2.a)
google-cloud-core (1.8.0)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.5.0)
google-cloud-storage (1.47.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.31.0)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.8.1)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-cookie (1.0.8)
domain_name (~> 0.5)
httpclient (2.9.0)
mutex_m
jmespath (1.6.2)
json (2.15.1)
jwt (2.10.2)
base64
logger (1.7.0)
mini_magick (4.13.2)
mini_mime (1.1.5)
multi_json (1.17.0)
multipart-post (2.4.1)
mutex_m (0.3.0)
nanaimo (0.4.0)
naturally (2.3.0)
nkf (0.2.0)
optparse (0.6.0)
os (1.1.4)
plist (3.7.2)
public_suffix (6.0.2)
rake (13.3.0)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rexml (3.4.4)
rouge (3.28.0)
ruby2_keywords (0.0.5)
rubyzip (2.4.1)
security (0.1.5)
signet (0.21.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 4.0)
multi_json (~> 1.10)
simctl (1.6.10)
CFPropertyList
naturally
sysrandom (1.0.5)
terminal-notifier (2.0.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.2)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
uber (0.1.0)
unicode-display_width (2.6.0)
word_wrap (1.0.0)
xcodeproj (1.27.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.4.0)
rexml (>= 3.3.6, < 4.0)
xcpretty (0.4.1)
rouge (~> 3.28.0)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
x86_64-linux-gnu
DEPENDENCIES
fastlane
BUNDLED WITH
2.7.2

208
app/IOS-BUILD-GUIDE.md Normal file
View File

@@ -0,0 +1,208 @@
# 🍎 Guide de Build iOS - GEOSECTOR
**Date de création** : 21/10/2025
**Version actuelle** : 3.4.2 (Build 342)
---
## 📋 **Prérequis**
### Sur le Mac mini
- ✅ macOS installé
- ✅ Xcode installé avec Command Line Tools
- ✅ Flutter installé (3.24.5 LTS recommandé)
- ✅ CocoaPods installé (`sudo gem install cocoapods`)
- ✅ Certificats Apple configurés (Team ID: 6WT84NWCTC)
### Sur Debian
- ✅ Accès SSH au Mac mini (192.168.1.34)
- ✅ rsync installé
---
## 🚀 **Procédure complète**
### **Étape 1 : Transfert depuis Debian vers Mac mini**
```bash
# Sur votre machine Debian
cd /home/pierre/dev/geosector/app
# Lancer le transfert
./transfer-to-mac.sh
```
**Ce que fait le script** :
1. Détecte automatiquement la version (ex: 342)
2. Crée le dossier `app_342` sur le Mac mini
3. Transfert tous les fichiers nécessaires (lib, ios, pubspec.yaml, etc.)
4. Exclut les dossiers inutiles (build, .dart_tool, Pods, etc.)
**Durée** : 2-5 minutes (selon la connexion réseau)
**Note** : Vous devrez saisir le mot de passe du Mac mini
---
### **Étape 2 : Connexion au Mac mini**
```bash
# Depuis Debian
ssh pierre@192.168.1.34
# Aller dans le dossier transféré
cd /Users/pierre/dev/geosector/app_342
```
---
### **Étape 3 : Lancer le build iOS**
```bash
# Sur le Mac mini
./ios-build-mac.sh
```
**Ce que fait le script** :
1. ✅ Nettoie le projet (`flutter clean`)
2. ✅ Récupère les dépendances (`flutter pub get`)
3. ✅ Installe les pods (`pod install`)
4. ✅ Compile en release (`flutter build ios --release`)
5. ✅ Ouvre Xcode pour l'archive (signature manuelle plus fiable)
**Durée de préparation** : 5-10 minutes
**Résultat** : Xcode s'ouvre, prêt pour Product > Archive
---
### **Étape 4 : Créer l'archive et upload vers App Store Connect**
**Xcode est ouvert automatiquement**
Dans Xcode :
1. ⏳ Attendre le chargement (quelques secondes)
2. ✅ Vérifier **Signing & Capabilities** : Team = 6WT84NWCTC, "Automatically manage signing" coché
3. 🧹 **Product > Clean Build Folder** (Cmd+Shift+K)
4. 📦 **Product > Archive**
5. ⏳ Attendre l'archive (5-10 minutes)
6. 📤 **Organizer** s'ouvre → Clic **Distribute App**
7. ☁️ Choisir **App Store Connect**
8.**Upload** → Automatique
9. 🚀 **Next** jusqu'à validation finale
**⚠️ Ne PAS utiliser xcodebuild en ligne de commande** : erreurs de signature (errSecInternalComponent). Xcode GUI obligatoire.
---
## 📁 **Structure des dossiers sur Mac mini**
```
/Users/pierre/dev/geosector/
├── app_342/ # Version 3.4.2 (Build 342)
│ ├── ios/
│ ├── lib/
│ ├── pubspec.yaml
│ ├── ios-build-mac.sh # Script de build
│ └── build/
│ └── Runner.xcarchive # Archive générée
├── app_341/ # Version précédente (si existe)
└── app_343/ # Version future
```
**Avantage** : Garder plusieurs versions côte à côte pour tests/rollback
---
## 🔧 **Résolution de problèmes**
### **Erreur : "Flutter not found"**
```bash
# Vérifier que Flutter est dans le PATH
echo $PATH | grep flutter
# Ajouter Flutter au PATH (dans ~/.zshrc ou ~/.bash_profile)
export PATH="$PATH:/opt/flutter/bin"
source ~/.zshrc
```
### **Erreur : "xcodebuild not found"**
```bash
# Installer Xcode Command Line Tools
xcode-select --install
```
### **Erreur lors de pod install**
```bash
# Sur le Mac mini
cd ios
rm -rf Pods Podfile.lock
pod install --repo-update
cd ..
```
### **Erreur de signature**
1. Ouvrir Xcode : `open ios/Runner.xcworkspace`
2. Sélectionner le target "Runner"
3. Onglet "Signing & Capabilities"
4. Vérifier Team ID : `6WT84NWCTC`
5. Cocher "Automatically manage signing"
### **Archive créée mais vide**
Vérifier que la compilation iOS a réussi :
```bash
flutter build ios --release --no-codesign --verbose
```
---
## 📊 **Checklist de validation**
- [ ] Version/Build incrémenté dans `pubspec.yaml`
- [ ] Compilation iOS réussie
- [ ] Archive validée dans Xcode Organizer
- [ ] Build uploadé vers App Store Connect
- [ ] **TestFlight** : Ajouter build au groupe "Testeurs externes"
- [ ] Renseigner "Infos sur l'exportation de conformité" :
- **App utilise chiffrement ?** → Oui
- **Algorithmes exempts listés ?** → **Aucun des algorithmes mentionnés ci-dessus**
- (App utilise HTTPS standard iOS uniquement)
- [ ] Soumettre build pour révision TestFlight
- [ ] *(Optionnel)* Captures/Release notes pour production App Store
---
## 🎯 **Workflow complet**
```bash
# 1. Debian → Transfert
cd /home/pierre/dev/geosector/app
./transfer-to-mac.sh
# 2. Mac mini → Build + Archive
ssh pierre@192.168.1.34
cd /Users/pierre/dev/geosector/app_342
./ios-build-mac.sh
# Xcode s'ouvre → Product > Clean + Archive
# 3. Upload → TestFlight
# Organizer > Distribute App > App Store Connect > Upload
# App Store Connect > TestFlight > Conformité export
```
---
## 📞 **Support**
- **Documentation Apple** : https://developer.apple.com
- **App Store Connect** : https://appstoreconnect.apple.com
- **Flutter iOS** : https://docs.flutter.dev/deployment/ios
---
**Prêt pour la production !** 🚀

View File

@@ -0,0 +1,283 @@
# Migration Flutter 3.24.5 LTS - Résolution problèmes iOS SwiftPM
**Date** : 11/10/2025
**Objectif** : Résoudre les erreurs de compilation iOS liées à l'architecture SwiftPM
**Solution** : Downgrade Flutter 3.24.5 LTS + downgrade des packages SwiftPM
---
## 📊 Tableau récapitulatif des changements
| Package | Version avant | Version après | Raison du changement |
|---------|---------------|---------------|----------------------|
| **Flutter SDK** | 3.35.5+ | **3.24.5 LTS** | Bugs SwiftPM dans 3.35.x |
| **Dart SDK** | 3.9.2 | **3.5.4** | Inclus avec Flutter 3.24.5 |
| `package_info_plus` | 8.3.1 | **4.2.0** | Avant SwiftPM - `'Flutter/Flutter.h' file not found` |
| `network_info_plus` | 7.0.0 | **4.1.0** | Avant SwiftPM - Erreurs module Swift |
| `sensors_plus` | 7.0.0 | **3.1.0** | Avant SwiftPM - Erreurs FPPSensorsPlusPlugin.h |
| `image_picker` | 1.1.2 | **0.8.9** | Avant SwiftPM - Erreurs image_picker_ios |
| `url_launcher` | 6.3.1 | **6.1.14** | Version stable compatible |
| `go_router` | 16.0.0 | **15.1.2** | Compatible Flutter 3.24.5 |
| `flutter_map` | 8.2.2 | **7.0.2** | Compatible Flutter 3.24.5 |
| `flutter_map_cache` | 2.0.0 | **1.5.1** | Compatible Flutter 3.24.5 |
| `syncfusion_flutter_charts` | 31.1.22 | **29.1.38** | Compatible Flutter 3.24.5 |
| `flutter_stripe` | 12.0.0 | **11.5.0** | Compatible Dart 3.5.4 |
| `nfc_manager` | 4.1.1 | **3.5.0** | Compatible Flutter 3.24.5 |
| `device_info_plus` | 12.1.0 | **11.3.0** | Compatible Flutter 3.24.5 |
| `flutter_lints` | 6.0.0 | **5.0.0** | Compatible Dart 3.5.4 |
| `intl` | 0.20.2 | **0.19.0** | Piné par Flutter 3.24.5 SDK |
---
## ⚠️ Problèmes résolus
### Erreurs de compilation iOS éliminées :
-`'Flutter/Flutter.h' file not found` dans plugins SwiftPM
-`No such module 'Flutter'` en Swift
- ❌ Erreurs de linking architecture x86_64
- ❌ Incompatibilités SwiftPM entre Flutter et plugins
- ❌ Problèmes url_launcher_ios, sensors_plus, image_picker_ios
---
## ✅ Fonctionnalités conservées
### Toutes les fonctionnalités critiques restent opérationnelles :
-**Stripe Tap to Pay** (mek_stripe_terminal 4.6.0 inchangé)
-**PaymentSheets, Apple Pay, Google Pay**
-**Stripe Connect V1**
-**SCA/PSD2**
-**Géolocalisation GPS** (geolocator 14.0.2)
-**NFC** (nfc_manager 3.5.0)
-**Flutter Maps** (flutter_map 7.0.2)
-**Charts Syncfusion** (syncfusion_flutter_charts 29.1.38)
-**Upload d'images** (image_picker 0.8.9)
-**Notifications locales**
-**Toutes les fonctionnalités métier**
---
## 📉 Fonctionnalités perdues (non critiques)
### Fonctionnalités récentes des packages downgradés :
- ⚠️ Options avancées PaymentSheet ajoutées dans flutter_stripe 12.x
- ⚠️ Méthode `pickMultipleMedia()` de image_picker 1.x (reste `pickMultiImage()`)
- ⚠️ Fonctionnalités NFC avancées de nfc_manager 4.x
- ⚠️ APIs récentes de package_info_plus 8.x
- ⚠️ Nouvelles APIs network_info_plus 7.x
**Impact métier** : Aucun - Les fonctionnalités perdues ne sont pas utilisées dans l'app.
---
## 🚀 Procédure de migration
### **Étape 1 : Downgrade Flutter vers 3.24.5 LTS**
```bash
cd ~/dev/flutter
git checkout 3.24.5
flutter --version
```
**Vérification attendue** :
```
Flutter 3.24.5 • channel stable
Dart 3.5.4 • DevTools 2.37.3
```
### **Étape 2 : Nettoyer complètement le projet**
```bash
cd /home/pierre/dev/geosector/app
# Nettoyer Flutter
flutter clean
# Supprimer les dépendances existantes
rm pubspec.lock
rm -rf ios/Pods ios/Podfile.lock ios/.symlinks
rm -rf build
rm -rf .dart_tool
# Supprimer les caches Flutter
flutter pub cache repair
```
### **Étape 3 : Installer les nouvelles dépendances**
```bash
# Récupérer les packages Flutter avec le nouveau pubspec.yaml
flutter pub get
```
**Vérification attendue** : Aucune erreur de résolution de dépendances.
### **Étape 4 : Réinstaller les Pods iOS**
```bash
cd ios
# Mettre à jour le repo CocoaPods
pod repo update
# Installer les pods
pod install
```
**Vérification attendue** : ~25-26 pods installés sans erreur.
### **Étape 5 : Tester la compilation iOS**
```bash
cd ..
# Tester la compilation sans signature
flutter build ios --release --no-codesign
```
**Résultat attendu** : Compilation réussie sans erreur SwiftPM.
### **Étape 6 : Vérification finale dans Xcode** (optionnel)
```bash
open ios/Runner.xcworkspace
```
**Actions dans Xcode** :
1. Sélectionner `Runner` target
2. Product > Clean Build Folder (`Cmd+Shift+K`)
3. Product > Build (`Cmd+B`)
4. Vérifier qu'il n'y a pas d'erreurs de compilation
---
## 🔍 Vérifications post-migration
### **Checklist de validation** :
- [ ] Flutter version : **3.24.5**
- [ ] Dart version : **3.5.4**
- [ ] `flutter pub get` : ✅ Sans erreurs
- [ ] `pod install` : ✅ ~25-26 pods installés
- [ ] `flutter build ios --release --no-codesign` : ✅ Compilation réussie
- [ ] `flutter analyze` : ✅ Pas d'erreurs bloquantes
- [ ] App démarre en simulateur iOS : ✅
- [ ] Fonctionnalités critiques testées :
- [ ] Login / Authentification
- [ ] Géolocalisation GPS
- [ ] Cartes Flutter Maps
- [ ] Upload d'images
- [ ] Charts Syncfusion
- [ ] NFC (si device compatible)
---
## 🔧 Dépannage
### **Si `flutter pub get` échoue**
```bash
# Réparer le cache Pub
flutter pub cache repair
# Supprimer le lock et réessayer
rm pubspec.lock
flutter pub get
```
### **Si `pod install` échoue**
```bash
cd ios
# Nettoyer complètement CocoaPods
rm -rf Pods Podfile.lock
rm -rf ~/Library/Caches/CocoaPods
pod cache clean --all
# Réinstaller
pod repo update
pod install
```
### **Si erreurs de compilation persistent**
```bash
# Nettoyer Xcode derived data
rm -rf ~/Library/Developer/Xcode/DerivedData
# Nettoyer complètement Flutter
flutter clean
rm -rf build ios/.symlinks
# Réinstaller tout
flutter pub get
cd ios && pod install
```
### **Si erreurs "module not found" dans Xcode**
1. Ouvrir `ios/Runner.xcworkspace` dans Xcode
2. Product > Clean Build Folder (`Cmd+Shift+K`)
3. Fermer Xcode
4. Relancer `pod install`
5. Rouvrir Xcode et rebuild
---
## 📌 Points d'attention
### **NE PAS upgrader Flutter**
- ⚠️ **Ne pas** exécuter `flutter upgrade`
- ⚠️ Rester sur Flutter **3.24.5 LTS** pour stabilité iOS
- ⚠️ Les versions 3.35.x ont des bugs SwiftPM non résolus
### **Versions verrouillées critiques**
- `intl: 0.19.0` - Piné par Flutter SDK, ne pas modifier
- `flutter_stripe: ^11.5.0` - Version max compatible Dart 3.5.4
- `package_info_plus: ^4.2.0` - Ne pas upgrader vers 5.0+ (SwiftPM)
- `network_info_plus: ^4.1.0` - Ne pas upgrader vers 5.0+ (SwiftPM)
- `sensors_plus: ^3.1.0` - Ne pas upgrader vers 4.0+ (SwiftPM)
### **Compatibilité future**
- Migration vers Flutter 3.28+ LTS envisageable quand SwiftPM sera stable
- Surveillance des changelogs Flutter pour support SwiftPM complet
- Prévoir test de migration tous les 6 mois
---
## 📚 Références
### **Problème SwiftPM Flutter iOS**
- Flutter Issue #137945 : SwiftPM integration issues
- Flutter Issue #144832 : 'Flutter/Flutter.h' file not found
- Flutter Docs : https://docs.flutter.dev/packages-and-plugins/swift-package-manager
### **Versions Flutter**
- Flutter 3.24.5 Release Notes : https://github.com/flutter/flutter/releases/tag/3.24.5
- Flutter LTS Policy : https://docs.flutter.dev/release/archive
### **Packages downgradés**
- package_info_plus changelog : https://pub.dev/packages/package_info_plus/changelog
- network_info_plus changelog : https://pub.dev/packages/network_info_plus/changelog
- sensors_plus changelog : https://pub.dev/packages/sensors_plus/changelog
- image_picker changelog : https://pub.dev/packages/image_picker/changelog
---
## ✅ Validation finale
**Migration réussie si** :
1. ✅ Flutter 3.24.5 installé
2. ✅ Tous les packages résolus sans conflit
3. ✅ Pods iOS installés sans erreur
4. ✅ Compilation iOS réussie sans erreurs SwiftPM
5. ✅ App démarre et fonctionne en simulateur iOS
6. ✅ Fonctionnalités critiques testées et opérationnelles
---
**Dernière mise à jour** : 11/10/2025 - 15:00
**Statut** : ✅ pubspec.yaml préparé, prêt pour migration
**Prochaine étape** : Exécuter la procédure de migration

193
app/QUICK-START.md Normal file
View File

@@ -0,0 +1,193 @@
# 🚀 GEOSECTOR - Quick Start Build
**Version** : 3.3.6 (Build 336)
**Date** : 14/10/2025
---
## 📱 Build iOS (Mac uniquement)
### Une seule commande
```bash
./ios.sh
```
**Ce que fait le script** :
1. ✅ Nettoyage complet (flutter clean + suppression caches)
2. ✅ flutter pub get
3. ✅ Patch permission_handler_apple (automatique)
4. ✅ pod install
5. ✅ flutter analyze
6. ✅ flutter build ios --release --no-codesign
7. ✅ Ouvre Xcode pour l'archive (optionnel)
**Durée** : 5-10 minutes
**Résultat** : Application prête dans `build/ios/iphoneos/Runner.app`
### Build sans archive Xcode
```bash
./ios.sh --skip-archive
```
---
## 🤖 Build Android
### Une seule commande
```bash
./android.sh
```
**Ce que fait le script** :
1. ✅ Nettoyage complet (flutter clean)
2. ✅ flutter pub get
3. ✅ Patch nfc_manager (automatique)
4. ✅ flutter analyze
5. ✅ flutter build appbundle --release
6. ✅ Copie avec nom versionné : `geosector-336.aab`
**Durée** : 5-10 minutes
**Résultat** : Bundle Android `geosector-336.aab`
---
## 🌐 Build Web
```bash
flutter build web --release
```
Ou pour déploiement DEV :
```bash
./deploy-app.sh
```
---
## 🔧 Scripts de correction (manuels)
### iOS - Fix permission_handler_apple
```bash
./fix-permission-handler.sh
```
**Quand** : Après `flutter pub get` si compilation iOS échoue
### Android - Fix nfc_manager
```bash
./fix-nfc-manager.sh
```
**Quand** : Après `flutter pub get` si compilation Android échoue
---
## 📋 Checklist rapide
### Avant tout build
- [ ] Version incrémentée dans `pubspec.yaml`
- [ ] Git commit des derniers changements
- [ ] Tests manuels effectués
### iOS uniquement
- [ ] Sur macOS
- [ ] Xcode installé
- [ ] CocoaPods installé
- [ ] Flutter 3.24.5 LTS
### Android uniquement
- [ ] Keystore présent : `android/app/geosector2025.jks`
- [ ] Fichier `android/key.properties` configuré
---
## 🎯 Workflow complet
### Pour une release complète (3 plateformes)
```bash
# 1. Mettre à jour la version
# Modifier pubspec.yaml : version: 3.3.7+337
# 2. Build Android
./android.sh
# 3. Build iOS
./ios.sh
# 4. Build Web
flutter build web --release
# 5. Git tag
git tag v3.3.7
git push --tags
```
---
## 🐛 Erreurs fréquentes
### iOS : "FlutterAppDelegate has different definitions"
**Solution** :
```bash
./fix-permission-handler.sh
cd ios && pod install && cd ..
flutter build ios --release --no-codesign
```
### Android : "namespace not found"
**Solution** :
```bash
./fix-nfc-manager.sh
flutter build appbundle --release
```
### "Flutter not in PATH"
**Solution** :
```bash
export PATH="$PATH:$HOME/dev/flutter/bin"
```
---
## 📚 Documentation complète
| Fichier | Contenu |
|---------|---------|
| `README-SCRIPTS.md` | Documentation complète des scripts |
| `BUILD-IOS-SUCCESS.md` | Guide de la solution iOS |
| `SOLUTION-IOS.md` | Détails techniques iOS |
| `SCRIPTS-IOS.md` | Documentation scripts iOS |
---
## ✅ Statut actuel
| Plateforme | Build | Statut |
|-----------|-------|--------|
| **iOS** | ✅ | Fonctionnel (Runner.app 107.4MB) |
| **Android** | ✅ | Fonctionnel (geosector-336.aab) |
| **Web** | ✅ | Fonctionnel |
---
**🎉 Tout est prêt pour les builds de production !**
Commandes rapides :
- `./ios.sh` - Build iOS complet
- `./android.sh` - Build Android complet
- `flutter build web --release` - Build Web

954
app/README-IOS.md Normal file
View File

@@ -0,0 +1,954 @@
# 📱 GEOSECTOR v3.3.4 - Publication iOS App Store
## 📋 Informations du projet
### Configuration actuelle
- **Version** : 3.3.6 (Build 336)
- **Bundle ID** : `fr.geosector.app3`
- **Team ID** : `6WT84NWCTC`
- **Display Name** : `GeoSector`
- **Bundle Name** : `GeoSector`
- **Deployment Target** : iOS 15.4+
- **Xcode** : 16.4
- **Flutter** : 3.24.5 LTS ✅ **Configuration stable** (downgrade depuis 3.35.5)
- **Dart** : 3.5.4
### Compte Apple Developer
- **Organisation** : Accessible via compte existant
- **Application existante** : Oui (ancienne version 2.7.1)
- **Type de mise à jour** : Refonte complète v3.3.4
---
## ✅ Étapes complétées
### 1. Environnement et dépendances
- [x] Flutter **downgrade vers 3.24.5 LTS** (11/10/2025 sur Debian, 13/10/2025 corrections)
- [x] Dart SDK downgrade vers 3.5.4
- [x] Packages ajustés pour compatibilité Flutter 3.24.5 (voir détails ci-dessous)
- [x] `flutter clean` exécuté
- [x] `flutter pub get` exécuté avec succès
- [x] CocoaPods mis à jour (1.16.2)
- [x] `pod install` exécuté (25 pods installés)
#### Packages downgradés (Flutter 3.24.5 LTS)
**Packages majeurs** :
- `syncfusion_flutter_charts` : 29.1.38 → **27.2.5** (sweet spot sans `withValues()` ni `markNeedsBuild()`)
- `geolocator` : 14.0.2 → **13.0.3** (sans `toARGB32()`)
- `geolocator_android` : forcé à **4.6.1**
- `battery_plus` : 7.0.0 → **6.0.3** (fix Gradle AGP 8)
- `connectivity_plus` : 7.0.0 → **6.0.5** (fix Gradle AGP 8)
- `nfc_manager` : 3.5.0 → **3.3.0** ⚠️ **Patch requis** (voir ci-dessous)
**Raison** : Packages v7.x incompatibles avec Flutter 3.24.5 LTS (propriété Gradle manquante)
**⚠️ Patch critique nfc_manager 3.3.0** :
```bash
# Requis après CHAQUE flutter pub get
./fix-nfc-manager.sh
```
**Pourquoi** :
- nfc_manager 3.3.0 est **obligatoire** pour Stripe Tap to Pay on iPhone
- Android Gradle Plugin 8+ nécessite `namespace` dans build.gradle
- Version 3.3.0 ne l'a pas → patch automatique via script
**Contenu du patch** : Ajoute `namespace 'io.flutter.plugins.nfc_manager'` dans `.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/android/build.gradle:28`
### 2. Configuration du projet iOS
- [x] **CFBundleName** corrigé : `geosector_app``GeoSector`
- [x] **Bundle Identifier** vérifié : `fr.geosector.app3`
- [x] **Team ID** configurée : `6WT84NWCTC`
- [x] **Info.plist** configuré avec toutes les permissions :
- Localisation (GPS)
- NFC (tags secteurs)
- Bluetooth (terminaux Stripe)
- Caméra (scan cartes bancaires)
- Photos (justificatifs)
- Réseau local
- Contacts
### 3. Entitlements Stripe Tap to Pay
- [x] Fichier `Runner.entitlements` créé avec :
- ✅ NFC Tag Reading (NDEF, TAG)
- ✅ Stripe Terminal - Tap to Pay on iPhone
- ✅ Network Access
- ✅ Keychain Sharing
- [x] Fichier présent dans `/ios/Runner/Runner.entitlements`
### 4. Pods installés
```
✅ 26 pods installés au total :
- Flutter (1.0.0)
- Stripe (24.16.2)
- StripeTerminal (4.6.1) ← Essentiel pour Tap to Pay
- StripeApplePay (24.16.2)
- StripeCore (24.16.2)
- StripeFinancialConnections (24.16.2)
- StripePaymentSheet (24.16.2)
- StripePayments (24.16.2)
- StripePaymentsUI (24.16.2)
- StripeUICore (24.16.2)
- mek_stripe_terminal (1.0.0)
- nfc_manager (0.0.1)
- geolocator_apple (1.2.0)
- battery_plus (1.0.0)
- connectivity_plus (0.0.1)
- device_info_plus (0.0.1)
- flutter_local_notifications (0.0.1)
- image_picker_ios (0.0.1)
- network_info_plus (0.0.1)
- package_info_plus (0.4.5)
- path_provider_foundation (0.0.1)
- permission_handler_apple (9.3.0)
- sensors_plus (0.0.1)
- stripe_ios (0.0.1)
- url_launcher_ios (0.0.1)
- ReachabilitySwift (5.2.4)
```
### 5. Analyse du code et compilation
- [x] `flutter analyze` exécuté : **0 erreurs**, 32 warnings (info seulement, pas d'erreurs bloquantes)
- Avertissements de style principalement
- Aucune erreur critique
#### Statut de compilation (13/10/2025 23:15)
-**Web** : Compilation réussie après downgrade syncfusion_flutter_charts 27.2.5
-**Android** : En attente validation après patch nfc_manager 3.3.0
- Toutes erreurs corrigées (battery_plus, connectivity_plus, SDK 35, nfc_manager)
- Script `fix-nfc-manager.sh` créé et prêt
- Test final `./android.sh` requis
-**iOS** : Non testé sur Debian
- Configuration Mac mini requise
- Pods installés : 25 pods (dont StripeTerminal 4.6.1)
---
## 🔄 Étapes en cours
### 6. Validation compilation Android
- [ ] **EN COURS** : Test final Android build après patch nfc_manager
- [ ] Exécution : `./android.sh`
- [ ] Vérification : Build APK réussi sans erreurs
### 7. Transfert projet vers Mac mini
- [ ] **EN ATTENTE** : Copie du projet corrigé via Samba/rsync
- [ ] Vérification : `flutter pub get` sur Mac
- [ ] Exécution : `./fix-nfc-manager.sh` (patch nfc_manager)
- [ ] Test : `cd ios && pod install`
---
## 📝 TODO - Étapes restantes
### 8. Compilation de test iOS
- [ ] Sur Mac mini : Compiler en mode release : `flutter build ios --release --no-codesign`
- [ ] Vérifier l'absence d'erreurs de compilation
- [ ] Corriger les éventuels problèmes
### 9. Configuration Xcode du projet
#### 9.1 Ouvrir le projet dans Xcode
```bash
open ios/Runner.xcworkspace
```
#### 9.2 Lier le fichier Runner.entitlements au projet
**⚠️ IMPORTANT** : Le fichier `Runner.entitlements` existe mais n'est **pas encore référencé** dans le projet Xcode.
**Action requise :**
1. Dans Xcode, sélectionner le target `Runner`
2. Onglet `Signing & Capabilities`
3. Vérifier si `Runner.entitlements` est bien lié
4. Si non lié :
- Aller dans `Build Settings`
- Rechercher `CODE_SIGN_ENTITLEMENTS`
- Ajouter : `Runner/Runner.entitlements`
#### 9.3 Configurer les certificats de signature
- [ ] Sélectionner le Team : `6WT84NWCTC`
- [ ] Choisir le profil de provisioning approprié
- [ ] Mode : **Automatic Signing** ou **Manual Signing** selon préférence
- [ ] Vérifier que le certificat est valide pour distribution App Store
#### 9.4 Vérifier les Capabilities
Dans Xcode > Target Runner > Signing & Capabilities, vérifier :
- [ ] **Near Field Communication Tag Reading**
- [ ] **Tap to Pay on iPhone** ⚠️ (nécessite approbation Apple spéciale)
- [ ] Keychain Sharing (si nécessaire)
**⚠️ ATTENTION TAP TO PAY** :
La capability "Tap to Pay on iPhone" nécessite une demande spéciale à Apple via :
- App Store Connect > votre app > Features
- Ou contact direct avec Apple Developer Support
- Documentation : https://developer.apple.com/tap-to-pay/
#### 9.5 Vérifier la version et le build number
- [ ] Version : `3.3.6`
- [ ] Build : `336`
- [ ] Incrémenter si nécessaire pour mise à jour
### 10. Créer l'archive pour l'App Store
#### 10.1 Build de l'archive
1. Dans Xcode, menu `Product > Archive`
2. Attendre la fin de la compilation (~5-10 minutes)
3. Vérifier qu'il n'y a pas d'erreurs
#### 10.2 Valider l'archive
1. Organizer s'ouvre automatiquement après l'archive
2. Sélectionner l'archive créée
3. Cliquer sur `Validate App`
4. Choisir le bon certificat et profil de provisioning
5. Attendre la validation (~2-5 minutes)
6. Corriger les éventuels problèmes détectés
#### 10.3 Uploader vers App Store Connect
1. Dans Organizer, cliquer sur `Distribute App`
2. Sélectionner `App Store Connect`
3. Choisir `Upload`
4. Sélectionner les options :
- ✅ Upload your app's symbols (pour crashlytics)
- ✅ Manage Version and Build Number (automatique)
5. Cliquer sur `Upload`
6. Attendre la fin de l'upload (~5-15 minutes selon connexion)
### 11. Configuration App Store Connect
#### 11.1 Accéder à App Store Connect
- [ ] Se connecter sur https://appstoreconnect.apple.com
- [ ] Sélectionner l'application GeoSector existante
- [ ] Créer une nouvelle version `3.3.6`
#### 11.2 Métadonnées de l'application
- [ ] **Nom** : GeoSector
- [ ] **Sous-titre** : Gestion de calendriers pompiers
- [ ] **Description** : Rédiger la description complète (highlights v3.3.6)
- [ ] **Mots-clés** : pompiers, calendrier, secteur, distribution, GPS
- [ ] **URL support** : Vérifier/mettre à jour
- [ ] **URL marketing** : Vérifier/mettre à jour
#### 11.3 Captures d'écran
Préparer les captures pour :
- [ ] iPhone 6.7" (iPhone 14 Pro Max, 15 Pro Max) - OBLIGATOIRE
- [ ] iPhone 6.5" (iPhone 11 Pro Max, XS Max) - OBLIGATOIRE
- [ ] iPad Pro 12.9" (3ème génération) - Si support iPad
- [ ] iPad Pro 12.9" (2ème génération) - Si support iPad
**Résolutions requises :**
- iPhone 6.7" : 1290 x 2796 pixels
- iPhone 6.5" : 1242 x 2688 pixels
- iPad Pro 12.9" : 2048 x 2732 pixels
#### 11.4 Informations de version
- [ ] **Nouveautés de cette version** : Rédiger le changelog v3.3.6
- Architecture moderne sans Provider
- Interface responsive optimisée
- Intégration Stripe Connect V1
- Préparation Tap to Pay V2
- Performance améliorée
- Conformité NIST SP 800-63B
#### 11.5 Informations générales
- [ ] **Catégorie principale** : Productivité
- [ ] **Catégorie secondaire** : Utilitaires
- [ ] **Classification par âge** : 4+ (probablement)
- [ ] **Copyright** : Vérifier/mettre à jour
#### 11.6 Confidentialité et permissions
Déclarer l'utilisation des permissions :
- [ ] **Localisation** : Enregistrement GPS des passages
- [ ] **NFC** : Lecture tags secteurs (si utilisé)
- [ ] **Bluetooth** : Connexion terminaux paiement Stripe
- [ ] **Caméra** : Scan cartes bancaires (Stripe)
- [ ] **Photos** : Upload justificatifs passages
- [ ] **Réseau** : Synchronisation données
#### 11.7 Informations de contact
- [ ] **Nom** : Votre nom ou organisation
- [ ] **Email** : Email de contact
- [ ] **Téléphone** : Numéro de contact
- [ ] **URL politique de confidentialité** : OBLIGATOIRE
### 12. Soumission pour révision
#### 12.1 Sélectionner le build
- [ ] Dans App Store Connect, section `Build`
- [ ] Sélectionner le build `3.3.6 (336)` uploadé précédemment
- [ ] Attendre que le build soit traité par Apple (~30-60 minutes)
#### 12.2 Répondre aux questionnaires
- [ ] **Utilise-t-elle le chiffrement ?** : Probablement OUI (HTTPS)
- Si OUI, déclarer l'utilisation de HTTPS standard (exempt)
- [ ] **Utilise-t-elle des identifiants publicitaires ?** : Probablement NON
- [ ] **Contient-elle de la publicité tierce ?** : NON
#### 12.3 Stripe Tap to Pay - Déclaration spéciale
⚠️ **IMPORTANT** : Avant de soumettre, vérifier :
- [ ] Demande d'accès Tap to Pay on iPhone soumise à Apple
- [ ] Compte Stripe Connect configuré et approuvé
- [ ] Tester la fonctionnalité sur un appareil physique compatible
- [ ] Documenter le flux de paiement pour les reviewers Apple
#### 12.4 Notes pour la révision (Review Notes)
Rédiger des notes claires pour les reviewers Apple :
```
Application de gestion de distribution de calendriers pour amicales de pompiers.
COMPTES DE TEST :
- Email : test@geosector.fr
- Mot de passe : [à fournir]
- Rôle : Membre (Rôle 1)
- Email : admin@geosector.fr
- Mot de passe : [à fournir]
- Rôle : Admin Amicale (Rôle 2)
FONCTIONNALITÉS PRINCIPALES :
1. Géolocalisation GPS pour tracking des passages
2. NFC pour lecture des tags secteurs (optionnel)
3. Stripe Connect pour paiements des amicales (V1 - web uniquement)
4. Tap to Pay sur iPhone (V2 - en développement, pas encore actif)
NOTE IMPORTANTE :
La fonctionnalité "Tap to Pay on iPhone" est présente dans les entitlements
mais pas encore activée dans cette version. Elle sera activée dans une mise
à jour ultérieure après approbation Apple.
SERVEUR :
- Environnement de production : https://api.geosector.fr
- API REST avec authentification JWT
```
#### 12.5 Soumettre pour révision
- [ ] Vérifier que toutes les informations sont complètes
- [ ] Cliquer sur `Soumettre pour révision`
- [ ] Confirmer la soumission
---
## 📊 Temps estimés
| Étape | Durée estimée | Statut |
|-------|---------------|--------|
| Validation Android build | 5-10 min | ⏳ En attente |
| Transfert Mac mini | 10-20 min | ⏳ En attente |
| Configuration Xcode | 15-30 min | ⏳ En attente |
| Build + Archive | 10-15 min | ⏳ En attente |
| Validation | 5-10 min | ⏳ En attente |
| Upload App Store | 10-20 min | ⏳ En attente |
| Métadonnées App Store | 30-60 min | ⏳ En attente |
| Captures d'écran | 30-45 min | ⏳ En attente |
| Soumission révision | 10 min | ⏳ En attente |
| **TOTAL** | **2h00 - 3h30** | |
| Révision Apple | **1-3 jours** | ⏳ En attente |
---
## ⚠️ Points d'attention
### 1. ⚠️ CRITIQUE : Patch nfc_manager obligatoire
- **⚠️ REQUIS APRÈS CHAQUE `flutter pub get`** : Exécuter `./fix-nfc-manager.sh`
- **Raison** : nfc_manager 3.3.0 manque la déclaration `namespace` requise par Android Gradle Plugin 8+
- **Impact** : Build Android échoue sans ce patch
- **Fonctionnalité** : **nfc_manager est OBLIGATOIRE** pour Stripe Tap to Pay on iPhone (ne pas désactiver)
- **Automatisation** : Script `fix-nfc-manager.sh` créé dans le dossier racine
- **Vérification** : Le script détecte si le patch est déjà appliqué
### 2. Tap to Pay on iPhone
- **Statut** : Entitlements présents, mais nécessite approbation Apple
- **Action** : Demander l'accès via App Store Connect ou Developer Support
- **Alternative** : Désactiver temporairement la capability si bloquante
### 3. Version deployment target
- **Actuel** : iOS 15.4+
- **Recommandé** : iOS 16.4+ (pour Tap to Pay)
- **Action** : Vérifier la compatibilité avec la base utilisateurs
### 4. Certificats de signature
- **Important** : Utiliser un certificat de distribution App Store
- **Renouvellement** : Vérifier la date d'expiration
### 5. Politique de confidentialité
- **Obligatoire** : URL valide et accessible
- **Contenu** : Doit couvrir toutes les permissions demandées
---
## 🔗 Liens utiles
- **Apple Developer** : https://developer.apple.com
- **App Store Connect** : https://appstoreconnect.apple.com
- **Stripe Tap to Pay** : https://stripe.com/docs/terminal/payments/setup-reader/tap-to-pay
- **Apple Tap to Pay** : https://developer.apple.com/tap-to-pay/
- **Human Interface Guidelines** : https://developer.apple.com/design/human-interface-guidelines/
---
## 📝 Notes de session
### Session du 05/10/2025 - Partie 1 (Configuration initiale)
#### ✅ Étapes complétées
- Début : Configuration initiale du projet
- Flutter upgrade : 3.32.4 → 3.35.5
- Dart upgrade : 3.8.1 → 3.9.2
- Pods installés : 26 pods (incluant Stripe Terminal 4.6.1)
- CFBundleName corrigé : `GeoSector`
- Installation iOS 18.5 : ✅ **TERMINÉE**
- Analyse du code : 32 warnings (pas d'erreurs bloquantes)
#### ❌ Problème rencontré lors de la compilation iOS
**Erreur** : `'Flutter/Flutter.h' file not found`
- Localisation : `/Users/pierre/.pub-cache/hosted/pub.dev/sensors_plus-3.1.0/ios/Classes/FPPSensorsPlusPlugin.h:4:8`
- Cause probable : Incompatibilité de version `sensors_plus` 3.1.0 avec Flutter 3.35.5
- Tentatives effectuées :
1.`flutter clean` + rebuild
2. ❌ Suppression complète Pods + réinstallation
3.`flutter pub get` + `pod install`
#### 🔄 Solution en cours
**Décision** : Mise à jour complète de tous les packages Flutter
- Commande : `flutter pub upgrade`
- Objectif : Résoudre les incompatibilités de versions
- Packages concernés : 49 packages ont des versions plus récentes disponibles
#### 📋 Prochaines étapes après upgrade
1. Exécuter `flutter pub upgrade`
2. Vérifier les changements de versions (notamment sensors_plus, package_info_plus, network_info_plus)
3. Réinstaller les pods iOS :
```bash
cd ios
rm -rf Pods Podfile.lock
pod install
cd ..
```
4. Nettoyer et récupérer les dépendances :
```bash
flutter clean
flutter pub get
```
5. Retenter la compilation : `flutter build ios --release --no-codesign`
6. Si succès → Ouvrir dans Xcode pour configuration finale
7. Si échec → Analyser les nouvelles erreurs et ajuster
---
### Session du 11/10/2025 - Résolution problèmes compilation iOS
#### 🐛 Problème rencontré : Module Swift 'Flutter' non trouvé
**Erreurs principales** :
- `No such module 'Flutter'` dans url_launcher_ios, sensors_plus
- `'Flutter/Flutter.h' file not found` dans plusieurs plugins SwiftPM
- Erreurs de linking avec architecture x86_64
**Cause identifiée** : Flutter 3.35.6 (très récent, 3 jours) a des incompatibilités avec les plugins utilisant la nouvelle architecture SwiftPM.
#### ✅ Solutions appliquées
##### 1. Création du script `fix_flutter_headers.sh`
Script automatique qui copie tous les headers Flutter (18 fichiers) dans les plugins problématiques :
- **Plugins SwiftPM** : package_info_plus, network_info_plus, image_picker_ios, url_launcher_ios
- **Plugins ancienne structure** : permission_handler_apple
Localisation : `/Users/pierre/dev/geosector/app/ios/fix_flutter_headers.sh`
Utilisation : `./fix_flutter_headers.sh` (à exécuter après chaque `pod install`)
##### 2. Modification du fichier `permission_handler_apple`
Correction des imports avec angle brackets → guillemets :
```bash
# Dans ~/.pub-cache/hosted/pub.dev/permission_handler_apple-9.4.7/ios/Classes/
sed -i '' 's|#import <Flutter/Flutter.h>|#import "Flutter/Flutter.h"|g' PermissionManager.h PermissionHandlerPlugin.h
```
##### 3. Création du module.modulemap Flutter
Fichier créé : `/Users/pierre/dev/geosector/app/ios/Flutter/module.modulemap`
```
module Flutter {
header "Flutter.h"
header "FlutterAppDelegate.h"
[... 18 headers au total ...]
export *
}
```
Headers Flutter copiés dans : `/Users/pierre/dev/geosector/app/ios/Flutter/`
##### 4. Downgrade Flutter : 3.35.6 → 3.35.5
**Date** : 11/10/2025 - 10h45
**Raison** : Flutter 3.35.6 (publié il y a 3 jours) a des bugs avec SwiftPM
**Commande** :
```bash
cd ~/dev/flutter
git checkout 3.35.5
flutter --version
```
**Résultat** :
- Flutter 3.35.5 (26 septembre 2025)
- Dart 3.9.2
- DevTools 2.48.0
##### 5. Nettoyage complet du projet
```bash
cd /Users/pierre/dev/geosector/app
flutter clean
rm -rf ios/Pods ios/Podfile.lock ios/.symlinks build
flutter pub get
cd ios
pod install
./fix_flutter_headers.sh
```
##### 6. Configuration Podfile simplifiée
Suppression de toutes les modifications complexes de chemins (HEADER_SEARCH_PATHS, SWIFT_INCLUDE_PATHS) qui causaient des problèmes de linking.
**Podfile actuel** : Configuration minimale avec :
- iOS Deployment Target : 15.4 (requis pour Stripe Tap to Pay)
- Bitcode désactivé
- User Script Sandboxing désactivé
- Permissions de géolocalisation
#### 📋 Workflow de compilation recommandé
**Pour simulateur** :
1. Ouvrir Xcode : `open ios/Runner.xcworkspace`
2. Sélectionner destination : iPhone 16 (simulateur)
3. Product > Clean Build Folder (`Cmd+Shift+K`)
4. Product > Build (`Cmd+B`)
**Pour Archive App Store** :
1. Destination : Any iOS Device (arm64)
2. Product > Clean Build Folder
3. Product > Archive
#### ⚠️ Points d'attention
**Script fix_flutter_headers.sh** :
- ✅ Doit être exécuté après CHAQUE `pod install`
- ✅ Copie les headers dans `.pub-cache` (modifications temporaires)
- ⚠️ Si Flutter est mis à jour, réexécuter le script
**Versions critiques** :
- Flutter : **3.35.5** (ne pas upgrader vers 3.35.6 pour l'instant)
- Dart : **3.9.2**
- Xcode : **16.4**
- iOS Deployment Target : **15.4+**
#### 🔧 Commandes utiles
**Vérifier version Flutter** :
```bash
flutter --version
```
**Réexécuter le fix des headers** :
```bash
cd /Users/pierre/dev/geosector/app/ios
./fix_flutter_headers.sh
```
**Nettoyer et reconstruire** :
```bash
flutter clean
cd ios && pod install && ./fix_flutter_headers.sh
```
**Retourner à Flutter 3.35.5 si nécessaire** :
```bash
cd ~/dev/flutter
git checkout 3.35.5
flutter doctor
```
---
## 🔧 DOWNGRADE FLUTTER 3.24.5 LTS (11/10/2025 - 13:15)
### Problème identifié
Flutter 3.35.x (3.35.5 et 3.35.6) présente des incompatibilités avec l'architecture SwiftPM des plugins iOS :
- Erreurs `'Flutter/Flutter.h' file not found`
- Erreurs `No such module 'Flutter'` en Swift
- Problèmes de compilation persistants malgré workarounds
### Solution appliquée
**Downgrade vers Flutter 3.24.5 LTS** (Long Term Support)
### Packages modifiés pour compatibilité
| Package | Version initiale | Version compatible | Raison |
|---------|-----------------|-------------------|--------|
| `flutter` | 3.35.5 | **3.24.5 LTS** | Version stable sans problèmes SwiftPM |
| `dart` | 3.9.2 | **3.5.4** | Inclus avec Flutter 3.24.5 |
| `flutter_stripe` | 12.0.2 | **11.5.0** | Nécessite Dart 3.8+, downgrade requis |
| `flutter_lints` | 6.0.0 | **5.0.0** | Dev only, compatible Dart 3.5.4 |
| `nfc_manager` | 4.1.1 | **3.5.0** | Compatible Dart 3.5.4 |
| `device_info_plus` | 12.1.0 | **11.3.0** | Compatible avec meta 1.15.0 |
| `flutter_map` | 8.2.2 | **7.0.2** | Compatible Dart 3.5.4 |
| `flutter_map_cache` | 2.0.0 | **1.5.1** | Compatible Dart 3.5.4 |
| `syncfusion_flutter_charts` | 31.1.22 | **29.1.38** | Compatible Dart 3.5.4 |
| `go_router` | 16.2.4 | **15.1.2** | Compatible Dart 3.5.4 |
| `intl` | 0.20.2 | **0.19.0** | Piné par Flutter SDK 3.24.5 |
### Impact fonctionnel
✅ **Fonctionnalités conservées** :
- Tap to Pay on iPhone (mek_stripe_terminal 4.6.0 inchangé)
- PaymentSheets, Apple Pay, Google Pay
- Stripe Connect V1
- SCA/PSD2
- Toutes les fonctionnalités métier
⚠️ **Fonctionnalités perdues** :
- Options avancées PaymentSheet ajoutées en flutter_stripe 12.x
- Sofort payment (déprécié par Stripe)
- Fonctionnalités NFC avancées de nfc_manager 4.x
### Commandes exécutées
```bash
# Downgrade Flutter
cd ~/dev/flutter
git checkout 3.24.5
flutter --version
# Nettoyer complètement
flutter clean
cd ios
rm -rf Pods Podfile.lock .symlinks
# Réinstaller
flutter pub get
pod install
```
### Résultat
✅ 74 packages downgraded
✅ 25 pods iOS installés avec succès
✅ Aucune erreur de dépendances
✅ Configuration stable et testée
---
## 🔴 DIAGNOSTIC FINAL - PROBLÈME STRUCTUREL iOS (11/10/2025 - 18:00)
### 📊 Synthèse du problème persistant
Après **5 tentatives** avec différentes versions de Flutter, **les mêmes erreurs persistent** :
- `'Flutter/Flutter.h' file not found`
- Affectant : `network_info_plus`, `package_info_plus`, `sensors_plus`
- **5 erreurs** systématiques dans Xcode
### 🎯 Explication technique du conflit Flutter / Packages / Xcode
#### **1. L'origine : Transition SwiftPM (Swift Package Manager)**
À partir de 2024, Flutter a introduit une **nouvelle architecture iOS** :
| Architecture | Période | Gestion dépendances | Structure |
|--------------|---------|---------------------|-----------|
| **Ancienne** | < 2024 | CocoaPods uniquement | Headers `.h` dans `/ios/Classes/` |
| **Nouvelle** | > 2024 | SwiftPM + CocoaPods | Modules Swift dans `/Sources/` |
#### **2. Le triangle d'incompatibilité**
```
┌─────────────────────────────────────────────────────────────┐
│ │
│ Flutter 3.24.5 LTS Flutter 3.27.2-3.35.x │
│ (Dart 3.5.4) (Dart 3.6.1-3.9.2) │
│ ↓ ↓ │
│ ✅ Stable ancien ⚠️ Transition SwiftPM │
│ ❌ Headers obsolètes 🐛 Bugs non résolus │
│ ↓ ↓ │
│ Incompatible avec Incompatible avec │
│ plugins récents plugins anciens │
│ ↓ ↓ │
│ ❌ ÉCHEC ❌ ÉCHEC │
└─────────────────────────────────────────────────────────────┘
```
#### **3. Ce que nous avons testé (TOUTES LES TENTATIVES ONT ÉCHOUÉ)**
| # | Configuration testée | Résultat | Erreurs |
|---|---------------------|----------|---------|
| 1 | Flutter **3.35.6** + plugins récents (8.x, 7.x) | ❌ ÉCHEC | `'Flutter/Flutter.h' file not found` |
| 2 | Flutter **3.35.5** + plugins récents | ❌ ÉCHEC | `No such module 'Flutter'` |
| 3 | Flutter **3.27.2** + plugins récents | ❌ ÉCHEC | `'Flutter/Flutter.h' file not found` |
| 4 | Flutter **3.27.2** + plugins anciens (4.x, 3.x) | ❌ ÉCHEC | `'Flutter/Flutter.h' file not found` |
| 5 | Flutter **3.24.5 LTS** + plugins anciens (4.2.0, 3.1.0) | ❌ ÉCHEC | `'Flutter/Flutter.h' file not found` ⚠️ **ACTUEL** |
**Temps investi** : ~6 heures de debug
**Tentatives de workaround** :
- ✅ Script `fix_flutter_headers.sh` créé
- ✅ Modification manuelle des imports Objective-C
- ✅ Création de `module.modulemap`
- ✅ Downgrades massifs de packages (geolocator 14→9, package_info 8→4, etc.)
- ❌ **AUCUNE SOLUTION N'A FONCTIONNÉ**
#### **4. La cause racine**
**Le problème fondamental** : Les plugins anciens (3.1.0, 4.2.0, 4.1.0) ont une **structure Objective-C** qui importe :
```objc
#import <Flutter/Flutter.h>
```
Cette structure ne fonctionne **DANS AUCUNE VERSION** de Flutter testée :
- ❌ **Flutter 3.24.5** : Trop ancien, ne gère pas correctement les imports modulaires modernes
- ❌ **Flutter 3.27.2** : En transition, incompatible avec ancienne ET nouvelle structure
- ❌ **Flutter 3.35.x** : Bugs SwiftPM documentés, headers mal exposés
#### **5. Le dilemme sans solution immédiate**
| Si on utilise... | Problème rencontré |
|------------------|-------------------|
| **Flutter 3.24.5 LTS** | Headers `Flutter/Flutter.h` non accessibles, même avec vieux plugins |
| **Flutter 3.27.2-3.35.x** | Architecture SwiftPM instable, bugs dans le SDK |
| **Plugins récents (7.x, 8.x)** | Nécessitent SwiftPM fonctionnel (Flutter 3.36+) |
| **Plugins anciens (3.x, 4.x)** | Incompatibles avec toutes les versions Flutter testées |
### 💡 Solutions envisageables (non testées)
#### **Option A : Retour aux plugins ENCORE PLUS anciens (pré-2023)**
- Tenter des versions **2.x** des plugins (avant refonte headers)
- **Risque** : Fonctionnalités manquantes, bugs de sécurité
- **Effort** : 2-3h de tests
#### **Option B : Forcer CocoaPods pur (désactiver SwiftPM complètement)**
```bash
# Dans ios/.flutter-plugins-dependencies
"swift_package_manager_enabled": true → false
```
- Modifier les Podfiles pour ignorer SwiftPM
- **Risque** : Peut casser d'autres plugins (Stripe, NFC)
- **Effort** : 3-4h de configuration
#### **Option C : Patcher manuellement les headers de TOUS les plugins**
- Réécrire les imports dans les 3 plugins problématiques
- Créer des copies locales des plugins dans le projet
- **Risque** : Maintenance difficile, fragile aux mises à jour
- **Effort** : 4-6h de dev + tests
#### **Option D : Attendre Flutter 3.28+ LTS (recommandé mais long)**
- Flutter 3.28 devrait stabiliser SwiftPM
- **Date estimée de sortie** : Q1-Q2 2026
- **Avantage** : Solution officielle et stable
- **Inconvénient** : Délai de 3-6 mois
#### **Option E : Migrer vers React Native ou autre framework**
- Abandon temporaire de Flutter pour iOS
- **Effort** : 2-3 semaines de réécriture
- **Avantage** : Écosystème plus mature pour iOS
- **Inconvénient** : Perte de l'investissement Flutter
### 📋 État actuel du projet
**Configuration actuelle (stable mais non compilable)** :
- ✅ Flutter 3.24.5 LTS + Dart 3.5.4
- ✅ 199 packages installés sans conflit
- ✅ 25 Pods iOS installés sans erreur
- ❌ **Compilation iOS impossible** : 5 erreurs persistantes
**Packages downgradés appliqués** :
- `geolocator`: 14.0.2 → 9.0.2
- `package_info_plus`: 8.3.1 → 4.2.0 ⚠️ **TOUJOURS EN ERREUR**
- `network_info_plus`: 7.0.0 → 4.1.0 ⚠️ **TOUJOURS EN ERREUR**
- `sensors_plus`: 7.0.0 → 3.1.0 ⚠️ **TOUJOURS EN ERREUR**
- `image_picker`: 1.1.2 → 0.8.9
### ⚠️ Recommandations
#### **Court terme (1-2 jours)**
1. ✅ **Tester Option B** (désactiver SwiftPM) - Effort moyen, espoir raisonnable
2. ⏸️ Contacter le support Flutter sur GitHub Issues
3. ⏸️ Chercher des forks communautaires des plugins problématiques
#### **Moyen terme (1-2 semaines)**
1. ⏸️ Envisager Option C (patches manuels) si Option B échoue
2. ⏸️ Surveiller les releases Flutter 3.28 beta
3. ⏸️ Préparer un plan de migration React Native si nécessaire
#### **Long terme (3+ mois)**
1. ⏸️ Attendre Flutter 3.28+ LTS avec SwiftPM stable
2. ⏸️ Migrer vers les dernières versions des plugins
3. ⏸️ Refactorer le code pour profiter des nouvelles APIs
### 🔗 Ressources et références
- **Flutter SwiftPM Issue** : https://github.com/flutter/flutter/issues/137945
- **Flutter 3.24.5 Release Notes** : https://github.com/flutter/flutter/releases/tag/3.24.5
- **Package downgrades documentation** : `/Users/pierre/dev/geosector/app/MIGRATION_FLUTTER_3.24.5.md`
---
**Dernière mise à jour** : 11/10/2025 - 18:00
**Statut actuel** : ❌ **BLOQUÉ - Compilation iOS impossible avec toutes les versions Flutter testées**
**Prochaine étape recommandée** : Tester Option B (désactiver SwiftPM complètement) ou attendre retour communauté Flutter
---
### Session du 15/10/2025 - Intégration du logo iOS (Build 338)
#### ✅ Objectif
Intégrer le nouveau logo GEOSECTOR dans l'application iOS pour distribution TestFlight.
#### 🐛 Problème rencontré
**Symptôme** : Logo affiché en carré noir dans Xcode et sur l'appareil
**Cause** :
- Logo source en format RGBA (avec transparence)
- iOS interprète le fond transparent comme noir
- flutter_launcher_icons générait des icônes noirs lors du redimensionnement
#### ✅ Solution appliquée
##### 1. Conversion du logo avec ImageMagick
```bash
magick assets/images/logo-geosector-1024.png \
-background white -alpha remove -alpha off \
-resize 1024x1024 \
assets/images/icons/icon-1024.png
```
**Résultat** : PNG RGB 1024x1024 avec fond blanc (pas de transparence)
##### 2. Génération manuelle des 21 icônes iOS
Abandon de flutter_launcher_icons au profit d'ImageMagick pour générer manuellement chaque taille :
- 20x20@1x,2x,3x
- 29x29@1x,2x,3x
- 40x40@1x,2x,3x
- 50x50@1x,2x
- 57x57@1x,2x
- 60x60@2x,3x
- 72x72@1x,2x
- 76x76@1x,2x
- 83.5x83.5@2x
- 1024x1024@1x (App Store)
**Commande type** :
```bash
magick assets/images/logo-geosector-1024.png \
-background white -alpha remove -alpha off \
-resize 60x60 \
ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
```
##### 3. Nettoyage complet du cache Xcode
```bash
rm -rf ~/Library/Developer/Xcode/DerivedData/*
rm -rf build/ios
```
##### 4. Compilation et création de l'archive
```bash
flutter build ios --release --no-codesign
# Durée : 47.9s
# Taille : 107.6 MB
# Puis dans Xcode :
# Product > Clean Build Folder
# Product > Archive
```
#### 📊 Résultats
| Métrique | Valeur |
|----------|--------|
| **Version** | 3.3.6 |
| **Build uploadé** | 338 ✅ |
| **Builds précédents** | 336, 337 (tests logo) |
| **Plateforme** | TestFlight |
| **Logo** | ✅ Affiché correctement |
| **Taille app** | 107.6 MB |
| **Temps compilation** | 47.9s |
#### 📝 Fichiers modifiés
```
assets/images/icons/
├── icon-1024.png ← Converti RGB fond blanc
└── icon-1024-old.png ← Backup ancien logo
ios/Runner/Assets.xcassets/AppIcon.appiconset/
├── Icon-App-1024x1024@1x.png ← Régénéré manuellement
├── Icon-App-20x20@1x.png ← Régénéré manuellement
├── Icon-App-20x20@2x.png ← Régénéré manuellement
├── Icon-App-20x20@3x.png ← Régénéré manuellement
└── ... (18 autres icônes) ← Tous régénérés
```
#### ⚠️ Points d'attention
1. **flutter_launcher_icons ne fonctionne pas** avec ce logo
- Génère des icônes complètement noirs
- Nécessite génération manuelle avec ImageMagick
2. **Format requis pour iOS** :
- RGB uniquement (pas de canal alpha)
- Fond blanc obligatoire
- Résolution exacte pour chaque taille
3. **Cache Xcode** :
- Nettoyer systématiquement `DerivedData/`
- Clean Build Folder avant Archive
4. **Versioning TestFlight** :
- Même version 3.3.6 autorisée
- Build number incrémenté : 336 → 337 → 338
- Pas besoin de changer la version pour TestFlight
#### 🚀 Prochaines étapes
- [x] Logo intégré avec succès
- [x] Build 338 uploadé sur App Store Connect
- [x] Archive validée dans Xcode
- [ ] Tester l'app sur TestFlight
- [ ] Inviter des testeurs internes
- [ ] Valider l'affichage du logo sur différents appareils
- [ ] Préparer la soumission App Store (si OK)
#### 🔧 Script de régénération complète (si besoin)
Pour régénérer tous les icônes à l'avenir :
```bash
#!/bin/bash
# regenerate-ios-icons.sh
SOURCE="assets/images/logo-geosector-1024.png"
DEST="ios/Runner/Assets.xcassets/AppIcon.appiconset"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 1024x1024 "$DEST/Icon-App-1024x1024@1x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 20x20 "$DEST/Icon-App-20x20@1x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 40x40 "$DEST/Icon-App-20x20@2x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 60x60 "$DEST/Icon-App-20x20@3x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 29x29 "$DEST/Icon-App-29x29@1x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 58x58 "$DEST/Icon-App-29x29@2x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 87x87 "$DEST/Icon-App-29x29@3x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 40x40 "$DEST/Icon-App-40x40@1x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 80x80 "$DEST/Icon-App-40x40@2x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 120x120 "$DEST/Icon-App-40x40@3x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 50x50 "$DEST/Icon-App-50x50@1x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 100x100 "$DEST/Icon-App-50x50@2x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 57x57 "$DEST/Icon-App-57x57@1x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 114x114 "$DEST/Icon-App-57x57@2x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 120x120 "$DEST/Icon-App-60x60@2x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 180x180 "$DEST/Icon-App-60x60@3x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 72x72 "$DEST/Icon-App-72x72@1x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 144x144 "$DEST/Icon-App-72x72@2x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 76x76 "$DEST/Icon-App-76x76@1x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 152x152 "$DEST/Icon-App-76x76@2x.png"
magick "$SOURCE" -background white -alpha remove -alpha off -resize 167x167 "$DEST/Icon-App-83.5x83.5@2x.png"
echo "✅ 21 icônes iOS régénérés avec succès"
```
---
**Dernière mise à jour** : 15/10/2025 - 10:00
**Statut** : ✅ **Build 338 uploadé avec logo correct**
**Prochaine étape** : Tests TestFlight

400
app/README-SCRIPTS.md Normal file
View File

@@ -0,0 +1,400 @@
# 📜 Scripts de Build GEOSECTOR
**Version** : 3.3.6
**Date** : 14/10/2025
---
## 📦 Scripts disponibles
| Script | Plateforme | Description | Statut |
|--------|-----------|-------------|--------|
| `android.sh` | Android | Build bundle (.aab) + APK optionnel | ✅ Fonctionnel |
| `ios.sh` | iOS | Build + Archive Xcode complète | ✅ **NOUVEAU** |
| `fix-permission-handler.sh` | iOS | Patch package problématique | ✅ Testé |
| `fix-nfc-manager.sh` | Android | Patch namespace Android | ⚠️ À vérifier |
| `fix-ios-packages.sh` | iOS | Script maître (tous les patchs) | ⚠️ Dépend du fix nfc |
| `deploy-app.sh` | DEV | Déploiement sur dapp.geosector.fr | ✅ Existant |
---
## 🍎 Script iOS : `ios.sh`
### Fonctionnalités
Le script `ios.sh` automatise **TOUTE** la chaîne de build iOS :
1.**Vérifications préliminaires**
- Vérification Flutter 3.24.5 LTS
- Vérification CocoaPods
- Vérification Xcode
- Vérification que nous sommes sur macOS
2.**Nettoyage complet**
- `flutter clean`
- Suppression `ios/Pods`
- Suppression `ios/Podfile.lock`
- Suppression `ios/.symlinks`
- Suppression `build/ios`
3.**Récupération des dépendances**
- `flutter pub get`
- Vérification des chemins Flutter (détection erreurs Linux)
4.**Patch permission_handler_apple**
- Exécution automatique de `fix-permission-handler.sh`
- Correction des conflits de headers Flutter
5.**Installation des pods**
- `cd ios && pod install`
- Vérification du workspace Xcode
6.**Analyse du code**
- `flutter analyze` (non bloquant)
- Possibilité de continuer malgré les warnings
7.**Compilation iOS**
- `flutter build ios --release --no-codesign`
- Affichage de la taille de l'app
8.**Archive Xcode (optionnel)**
- Ouverture de Xcode
- Instructions pas à pas
- Attente de la fin de l'archive
### Usage
#### Build standard (avec archive Xcode)
```bash
./ios.sh
```
**Étapes** :
1. Exécute toutes les étapes automatiquement
2. Ouvre Xcode à la fin
3. Affiche les instructions pour créer l'archive
4. Attend que vous appuyiez sur Entrée après l'archive
**Durée estimée** : 5-10 minutes (hors archive Xcode)
#### Build rapide (sans archive)
```bash
./ios.sh --skip-archive
```
**Étapes** :
1. Exécute toutes les étapes jusqu'à la compilation
2. N'ouvre pas Xcode
3. Vous laisse créer l'archive manuellement plus tard
**Durée estimée** : 3-5 minutes
### Sorties du script
#### Succès
```
[INFO] =========================================
[SUCCESS] BUILD iOS TERMINÉ AVEC SUCCÈS !
[INFO] =========================================
Version : 3.3.6 (336)
Bundle ID : fr.geosector.app3
Application : build/ios/iphoneos/Runner.app
Prochaines étapes (dans Xcode) :
1. ✅ Build iOS réussi
2. ⏳ Créer l'archive (Product > Archive)
3. ⏳ Valider l'archive (Organizer > Validate App)
4. ⏳ Upload vers App Store Connect
```
#### Erreur
```
[ERROR] Échec de la compilation iOS
[ERROR] Consultez les logs ci-dessus pour plus de détails
```
### Gestion des erreurs
Le script s'arrête automatiquement en cas d'erreur et affiche :
- La ligne de l'erreur
- Un message explicatif
- Les logs de la commande qui a échoué
---
## 🤖 Script Android : `android.sh`
### Fonctionnalités
1. ✅ Nettoyage du projet (`flutter clean`)
2. ✅ Récupération des dépendances (`flutter pub get`)
3. ✅ Patch nfc_manager automatique
4. ✅ Analyse du code Dart
5. ✅ Génération du bundle (.aab)
6. ✅ Copie du bundle avec nom versionné
7. ✅ Génération optionnelle de l'APK
### Usage
```bash
./android.sh
```
**Sortie** : `geosector-336.aab` (+ optionnel `geosector-336.apk`)
---
## 🔧 Scripts de correction
### `fix-permission-handler.sh` (iOS uniquement)
**Problème corrigé** : Conflits de headers Flutter dans `permission_handler_apple-9.4.7`
**Actions** :
1. Supprime `/ios/Classes/Flutter/` du package
2. Corrige les imports dans `PermissionHandlerPlugin.h`
3. Corrige les imports dans `PermissionManager.h`
**Usage** :
```bash
./fix-permission-handler.sh
```
**Quand l'utiliser** :
- Automatiquement via `ios.sh`
- Manuellement après `flutter pub get`
- Si erreur `'FlutterAppDelegate' has different definitions`
---
### `fix-nfc-manager.sh` (Android uniquement)
**Problème corrigé** : Namespace Android manquant dans `nfc_manager-3.3.0`
**Actions** :
1. Ajoute `namespace` dans `AndroidManifest.xml`
2. Corrige `build.gradle`
3. Corrige `Translator.kt`
**Usage** :
```bash
./fix-nfc-manager.sh
```
**Quand l'utiliser** :
- Automatiquement via `android.sh`
- Manuellement après `flutter pub get`
- Si erreur de compilation Android Gradle
**⚠️ Note** : Sur macOS, ce script peut avoir une erreur `sed`. À débugger si nécessaire.
---
## 🚀 Workflows recommandés
### Build iOS complet
```bash
# Option 1 : Tout automatique
./ios.sh
# Option 2 : Build sans archive
./ios.sh --skip-archive
# Puis plus tard :
open ios/Runner.xcworkspace
# Product > Archive dans Xcode
```
### Build Android complet
```bash
./android.sh
# Génère : geosector-336.aab
```
### Build Web
```bash
flutter build web --release
# Ou via deploy-app.sh pour DEV
```
### Build toutes les plateformes
```bash
# 1. Android
./android.sh
# 2. iOS
./ios.sh --skip-archive
# 3. Web
flutter build web --release
```
---
## 📋 Checklist avant build
### Avant `android.sh`
- [ ] Flutter version correcte
- [ ] Keystore présent : `android/app/geosector2025.jks`
- [ ] Fichier `android/key.properties` configuré
- [ ] Version incrémentée dans `pubspec.yaml`
### Avant `ios.sh`
- [ ] Sur macOS
- [ ] Flutter 3.24.5 LTS installé
- [ ] Xcode installé et à jour
- [ ] CocoaPods installé
- [ ] Team ID configuré : `6WT84NWCTC`
- [ ] Bundle ID correct : `fr.geosector.app3`
- [ ] Version incrémentée dans `pubspec.yaml`
- [ ] Script `fix-permission-handler.sh` présent
---
## 🐛 Dépannage
### Erreur : "Flutter n'est pas dans le PATH"
**Solution** :
```bash
# Ajouter Flutter au PATH
export PATH="$PATH:$HOME/dev/flutter/bin"
# Ou ajouter dans ~/.zshrc (Mac)
```
### Erreur : "CocoaPods not installed"
**Solution** :
```bash
sudo gem install cocoapods
```
### Erreur : "Invalid Podfile file"
**Solution** :
```bash
rm ios/Flutter/Generated.xcconfig
flutter pub get
```
### Erreur : "Build iOS failed"
**Solutions** :
1. Vérifier que `fix-permission-handler.sh` a été exécuté
2. Nettoyer complètement :
```bash
flutter clean
rm -rf ios/Pods ios/Podfile.lock
flutter pub get
./fix-permission-handler.sh
cd ios && pod install
```
3. Vérifier les logs Xcode pour l'erreur exacte
### Script `ios.sh` s'arrête à l'étape 3
**Cause** : Script `fix-permission-handler.sh` introuvable ou non exécutable
**Solution** :
```bash
chmod +x fix-permission-handler.sh
./ios.sh
```
---
## 📊 Temps d'exécution estimés
| Script | Durée | Notes |
|--------|-------|-------|
| `android.sh` | 5-10 min | Dépend de la machine |
| `ios.sh` (sans archive) | 3-5 min | Sur Mac mini/MacBook |
| `ios.sh` (avec archive) | 10-20 min | + temps Xcode Archive |
| `fix-permission-handler.sh` | < 5 secondes | Très rapide |
| `flutter clean` | 10-30 secondes | Variable |
| `flutter pub get` | 30-60 secondes | Variable |
| `pod install` | 30-90 secondes | Première fois plus long |
---
## 📝 Logs et debug
### Activer les logs détaillés
**Android** :
```bash
flutter build appbundle --release --verbose
```
**iOS** :
```bash
flutter build ios --release --no-codesign --verbose
```
### Voir les logs Xcode
Dans Xcode après une erreur :
- Product > Show Build Log (Cmd+B puis Cmd+7)
- Ou dans Terminal :
```bash
tail -f ~/Library/Logs/DiagnosticReports/xcodebuild*
```
---
## 🔗 Références
### Documentation créée
- `BUILD-IOS-SUCCESS.md` - Récapitulatif du succès iOS
- `SOLUTION-IOS.md` - Guide complet de la solution
- `SCRIPTS-IOS.md` - Documentation des scripts iOS
- `README-SCRIPTS.md` - Ce fichier
### Scripts
- `ios.sh` - ✅ Script maître iOS
- `android.sh` - ✅ Script maître Android
- `fix-permission-handler.sh` - ✅ Patch iOS
- `fix-nfc-manager.sh` - ⚠️ Patch Android (à vérifier)
---
## 🎯 Prochaines améliorations possibles
### Script `ios.sh`
- [ ] Création de l'archive via ligne de commande (sans ouvrir Xcode)
- [ ] Upload automatique vers App Store Connect via `xcrun altool`
- [ ] Génération automatique des métadonnées App Store
- [ ] Tests automatisés avant build
### Script `android.sh`
- [ ] Upload automatique vers Google Play Console
- [ ] Tests automatisés avant build
- [ ] Génération de screenshots automatiques
### Scripts communs
- [ ] Script `build-all.sh` - Build toutes les plateformes en une fois
- [ ] Script `test-all.sh` - Tests automatisés toutes plateformes
- [ ] Script `deploy-all.sh` - Déploiement vers tous les environnements
---
**Auteur** : Claude Code + Pierre
**Version** : 1.0.0
**Dernière mise à jour** : 14/10/2025
✅ **Les scripts `android.sh` et `ios.sh` sont prêts à l'emploi !**

16
app/README.md Normal file
View File

@@ -0,0 +1,16 @@
# geosector_app
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

248
app/SCRIPTS-IOS.md Normal file
View File

@@ -0,0 +1,248 @@
# 📜 Scripts iOS - Guide d'utilisation
**Date de création** : 14/10/2025
**Objectif** : Automatiser les corrections nécessaires pour compiler l'application iOS
---
## 📂 Scripts disponibles
### 1. `fix-permission-handler.sh` ✅ **TESTÉ ET FONCTIONNEL**
**Problème corrigé** : Le package `permission_handler_apple-9.4.7` embarque ses propres headers Flutter qui créent des conflits de compilation.
**Actions effectuées** :
- ✅ Détecte automatiquement la version du package dans `.pub-cache`
- ✅ Supprime le dossier `/ios/Classes/Flutter/` embarqué
- ✅ Corrige les imports dans `PermissionHandlerPlugin.h`
- ✅ Corrige les imports dans `PermissionManager.h`
**Usage** :
```bash
./fix-permission-handler.sh
```
**Quand l'exécuter** :
- ✅ Après chaque `flutter pub get`
- ✅ Avant `pod install`
- ✅ Si erreurs de compilation `'FlutterAppDelegate' has different definitions`
**Sortie attendue** :
```
🔧 Fix permission_handler_apple - Correction des conflits Flutter headers
📦 Package trouvé : /Users/pierre/.pub-cache/.../permission_handler_apple-9.4.7
✅ Dossier Flutter supprimé
✅ PermissionHandlerPlugin.h corrigé
✅ PermissionManager.h corrigé
🎉 Correction terminée avec succès !
```
---
### 2. `fix-nfc-manager.sh` ⚠️ **PRÉSENT MAIS NON TESTÉ SUR MAC**
**Problème corrigé** : Le package `nfc_manager-3.3.0` manque la déclaration `namespace` requise par Android Gradle Plugin 8+.
**Note** : Ce script était fonctionnel sur Debian Linux. Sur Mac, il semble y avoir une erreur `sed` à corriger.
**Actions prévues** :
- Ajout du `namespace` dans `AndroidManifest.xml`
- Correction du fichier `build.gradle`
- Correction du fichier `Translator.kt`
**Statut** : ⚠️ À débugger si nécessaire (erreur sed détectée)
---
### 3. `fix-ios-packages.sh` (Script maître) ⚠️ **EN DÉVELOPPEMENT**
**Objectif** : Exécuter tous les scripts de correction iOS en une seule commande.
**Inclut** :
- `fix-nfc-manager.sh` (si corrigé)
- `fix-permission-handler.sh`
**Statut actuel** : Fonctionne partiellement (erreur sed dans fix-nfc-manager.sh)
---
## 🚀 Workflow de build iOS complet
### Option A : Build iOS uniquement (recommandé actuellement)
```bash
# 1. Nettoyer
flutter clean
# 2. Récupérer les dépendances
flutter pub get
# 3. 🔧 Corriger permission_handler_apple
./fix-permission-handler.sh
# 4. Installer les pods
cd ios && pod install && cd ..
# 5. Compiler
flutter build ios --release --no-codesign
```
### Option B : Build complet (Web + Android + iOS)
**Android** :
```bash
# Le script fix-nfc-manager.sh devrait être exécuté ici
flutter build appbundle --release
```
**iOS** :
```bash
# Utiliser Option A ci-dessus
```
**Web** :
```bash
flutter build web --release
```
---
## ✅ Vérifications avant compilation iOS
### 1. Version Flutter correcte
```bash
flutter --version
# Attendu : Flutter 3.24.5 • channel [user-branch]
# Dart 3.5.4 • DevTools 2.37.3
```
### 2. Fichiers de configuration régénérés
```bash
cat ios/Flutter/Generated.xcconfig | grep FLUTTER_ROOT
# Attendu : FLUTTER_ROOT=/Users/pierre/dev/flutter
```
### 3. Permission handler corrigé
```bash
ls ~/.pub-cache/hosted/pub.dev/permission_handler_apple-*/ios/Classes/Flutter/
# Attendu : ls: .../Flutter/: No such file or directory (= bon signe !)
```
### 4. Pods installés
```bash
cat ios/Podfile.lock | grep "permission_handler_apple"
# Attendu : - permission_handler_apple (9.3.0):
```
---
## 🐛 Dépannage
### Erreur : `'FlutterAppDelegate' has different definitions`
**Solution** : Exécuter `./fix-permission-handler.sh`
### Erreur : `Flutter/Flutter.h: No such file or directory`
**Causes possibles** :
1. Le script `fix-permission-handler.sh` n'a pas été exécuté
2. Les imports n'ont pas été corrigés correctement
3. Le cache build doit être nettoyé
**Solution** :
```bash
./fix-permission-handler.sh
rm -rf build/ios ios/Pods
cd ios && pod install && cd ..
flutter build ios --release --no-codesign
```
### Erreur : `Invalid Podfile file: cannot load such file -- podhelper`
**Cause** : Le fichier `ios/Flutter/Generated.xcconfig` contient de mauvais chemins (Linux au lieu de Mac).
**Solution** :
```bash
rm ios/Flutter/Generated.xcconfig
flutter pub get
```
### Build réussi mais warnings CocoaPods
**Warning** :
```
[!] CocoaPods did not set the base configuration of your project...
```
**Impact** : ⚠️ Non bloquant, la compilation fonctionne
**Solution** : (Optionnel) Configurer manuellement dans Xcode les fichiers de configuration CocoaPods
---
## 📝 Historique des corrections
### 14/10/2025 - Solution finale trouvée ✅
**Problème** : Compilation iOS impossible avec erreurs de conflits de définitions Flutter
**Cause identifiée** : `permission_handler_apple-9.4.7` embarquait ses propres headers Flutter
**Solution appliquée** :
1. ✅ Suppression du dossier `/ios/Classes/Flutter/` du package
2. ✅ Modification des imports : `"Flutter/Flutter.h"``<Flutter/Flutter.h>`
3. ✅ Création du script `fix-permission-handler.sh`
**Résultat** :
```
✓ Built build/ios/iphoneos/Runner.app (107.4MB)
Xcode build done. 59,1s
```
### 13/10/2025 - Suppression packages problématiques
**Packages supprimés** : `package_info_plus`, `network_info_plus`, `sensors_plus`
**Raison** : Erreurs `'Flutter/Flutter.h' file not found` persistantes
**Impact** : Perte de fonctionnalités mineures (mode boussole, diagnostic WiFi)
### 11/10/2025 - Downgrade vers Flutter 3.24.5 LTS
**Versions testées sans succès** :
- ❌ Flutter 3.35.6 (bugs SwiftPM)
- ❌ Flutter 3.35.5 (bugs SwiftPM)
- ❌ Flutter 3.27.2 (incompatibilités)
**Version retenue** : Flutter 3.24.5 LTS + Dart 3.5.4
---
## 🔗 Références
### Documentation
- `SOLUTION-IOS.md` - Guide complet de la solution finale
- `README-IOS.md` - Historique détaillé des tentatives
- `TRANSFERT-MAC.md` - Guide de transfert Linux → Mac
### Scripts
- `fix-permission-handler.sh` - ✅ Fonctionnel
- `fix-nfc-manager.sh` - ⚠️ À débugger (erreur sed)
- `fix-ios-packages.sh` - ⚠️ Dépend du fix nfc_manager
---
**Auteur** : Claude Code + Pierre
**Version** : 1.0.0
**Dernière mise à jour** : 14/10/2025 12:45
**Le script `fix-permission-handler.sh` est prêt à l'emploi !**

248
app/SOLUTION-IOS.md Normal file
View File

@@ -0,0 +1,248 @@
# ✅ Solution de compilation iOS - GEOSECTOR v3.3.6
**Date de résolution** : 14/10/2025
**Statut** : ✅ **RÉSOLU - Compilation iOS réussie**
**Version Flutter** : 3.24.5 LTS + Dart 3.5.4
---
## 🎉 Résultat final
```bash
✓ Built build/ios/iphoneos/Runner.app (107.4MB)
```
**Temps de compilation** : 59,1 secondes
**Erreurs** : 0
**Warnings** : Configuration CocoaPods (non bloquant)
---
## 🔍 Problème initial
Après 5 tentatives avec différentes versions de Flutter (3.35.6, 3.35.5, 3.27.2, 3.24.5), l'application rencontrait systématiquement des erreurs :
```
Error (Xcode): 'FlutterAppDelegate' has different definitions in different modules
Error (Xcode): 'FlutterViewController' has different definitions in different modules
Error (Xcode): 'FlutterEngine' has different definitions in different modules
```
**Cause racine** : Le package **`permission_handler_apple-9.4.7`** embarquait ses propres copies des headers Flutter dans `/ios/Classes/Flutter/`, créant un conflit de définitions avec les vrais headers Flutter du framework système.
---
## ✅ Solution appliquée
### 1. Suppression du dossier Flutter embarqué
```bash
rm -rf ~/.pub-cache/hosted/pub.dev/permission_handler_apple-9.4.7/ios/Classes/Flutter
```
### 2. Correction des imports dans les headers
**Fichier** : `PermissionHandlerPlugin.h`
```objc
// AVANT
#import "Flutter/Flutter.h"
// APRÈS
#import <Flutter/Flutter.h>
```
**Fichier** : `PermissionManager.h`
```objc
// AVANT
#import "Flutter/Flutter.h"
// APRÈS
#import <Flutter/Flutter.h>
```
### 3. Nettoyage du cache et réinstallation
```bash
rm -rf build/ios ios/Pods
cd ios && pod install && cd ..
flutter build ios --release --no-codesign
```
---
## 🤖 Scripts automatisés créés
### Script 1 : `fix-permission-handler.sh`
Corrige automatiquement le package `permission_handler_apple` :
- ✅ Détecte automatiquement la version installée
- ✅ Supprime le dossier `Flutter/` embarqué
- ✅ Corrige les imports dans les 2 fichiers `.h`
- ✅ Messages colorés avec statut de chaque étape
**Usage** :
```bash
./fix-permission-handler.sh
```
### Script 2 : `fix-ios-packages.sh` (Script maître)
Combine tous les fixes iOS (nfc_manager + permission_handler_apple) :
- ✅ Exécute `fix-nfc-manager.sh` (si présent)
- ✅ Exécute `fix-permission-handler.sh`
- ✅ Affiche le workflow complet de build iOS
**Usage** :
```bash
./fix-ios-packages.sh
```
---
## 📋 Workflow de build iOS recommandé
### Build complet (après modifications de code)
```bash
flutter clean
flutter pub get
./fix-ios-packages.sh
cd ios && pod install && cd ..
flutter build ios --release --no-codesign
```
### Build rapide (sans modification de dépendances)
```bash
flutter build ios --release --no-codesign
```
### Après chaque `flutter pub get`
```bash
./fix-ios-packages.sh
cd ios && pod install && cd ..
```
---
## 🔧 Configuration actuelle
### Versions
- **Flutter** : 3.24.5 LTS
- **Dart** : 3.5.4
- **Xcode** : 16.4
- **iOS Deployment Target** : 15.4+
### Packages critiques iOS
| Package | Version | Notes |
|---------|---------|-------|
| `permission_handler_apple` | 9.4.7 | ⚠️ Nécessite fix (script créé) |
| `nfc_manager` | 3.3.0 | ⚠️ Nécessite fix namespace Android |
| `flutter_stripe` | 11.5.0 | ✅ Compatible |
| `mek_stripe_terminal` | 4.6.0 | ✅ Tap to Pay on iPhone |
| `geolocator` | 13.0.4 | ✅ Compatible |
### Packages supprimés (causes d'erreurs)
Ces packages ont été supprimés car ils causaient des erreurs `'Flutter/Flutter.h' file not found` :
-`package_info_plus` → Remplacé par `AppInfoService` auto-généré
-`network_info_plus` → Remplacé par `NetworkInterface` natif Dart (dart:io)
-`sensors_plus` → Mode boussole retiré (feature optionnelle)
**Impact fonctionnel** : Minimal (fonctionnalités mineures perdues)
---
## 🎯 Prochaines étapes
### Pour l'App Store
1. **Ouvrir Xcode** :
```bash
open ios/Runner.xcworkspace
```
2. **Vérifier la configuration** :
- Team ID : `6WT84NWCTC`
- Bundle ID : `fr.geosector.app3`
- Version : `3.3.6 (336)`
3. **Créer l'archive** :
- Product > Clean Build Folder (Cmd+Shift+K)
- Product > Archive
4. **Uploader vers App Store Connect** :
- Organizer > Validate App
- Distribute App > Upload
### Tests recommandés
- ✅ Test sur simulateur iOS 15.4+
- ✅ Test sur device physique (iPhone)
- ✅ Validation Stripe Tap to Pay (nécessite approbation Apple)
- ✅ Test mode hors ligne
- ✅ Test géolocalisation GPS
---
## 📚 Références
### Documentation créée
- `README-IOS.md` - Historique complet des tentatives et problèmes
- `TRANSFERT-MAC.md` - Guide de transfert depuis Debian Linux
- `fix-permission-handler.sh` - Script de correction automatique
- `fix-ios-packages.sh` - Script maître de correction iOS
### Commits importants
- **13/10/2025** : Suppression packages problématiques (package_info_plus, network_info_plus, sensors_plus)
- **14/10/2025** : ✅ **Solution finale trouvée** - Fix permission_handler_apple
---
## ⚠️ Notes importantes
### Après chaque mise à jour Flutter
Si vous mettez à jour Flutter, vous devrez peut-être :
1. Vérifier la compatibilité des packages
2. Réexécuter `./fix-ios-packages.sh`
3. Réinstaller les pods : `cd ios && pod install`
### Problèmes potentiels futurs
Si `permission_handler_apple` se met à jour vers une version supérieure :
- Le script devrait continuer à fonctionner (détection automatique de version)
- Si problème : vérifier que le dossier `Flutter/` embarqué existe toujours
- Adapter le script si la structure du package change
### Packages à surveiller
Ces packages peuvent causer des problèmes similaires à l'avenir :
- `permission_handler_apple` (actuellement fixé)
- `package_info_plus` (si réintégré)
- `network_info_plus` (si réintégré)
- `sensors_plus` (si réintégré)
---
## 🙏 Remerciements
Cette solution a été trouvée après analyse approfondie de :
- Documentation Flutter sur la transition SwiftPM
- GitHub Issues flutter/flutter #137945
- Tests avec 5 versions différentes de Flutter
- Analyse du contenu des packages problématiques
---
**Auteur** : Claude Code + Pierre
**Version** : 1.0.0
**Dernière mise à jour** : 14/10/2025 12:30
**La compilation iOS fonctionne maintenant parfaitement avec Flutter 3.24.5 LTS !**

286
app/TRANSFERT-MAC.md Normal file
View File

@@ -0,0 +1,286 @@
# 🍎 Guide de transfert et compilation iOS sur Mac mini
**Date** : 14/10/2025
**Projet** : GEOSECTOR v3.3.6 (Build 336)
**Source** : Debian Linux (minipi1)
**Destination** : Mac mini (compilation iOS)
---
## ✅ Corrections effectuées sur Linux (Debian)
### 🎉 Android : COMPILATION RÉUSSIE
**Problèmes résolus** :
1. ✅ JDK incomplet → Installation `openjdk-21-jdk-headless`
2. ✅ nfc_manager 3.3.0 → Triple patch automatique (AndroidManifest + build.gradle + Translator.kt)
3. ✅ Conflit BouncyCastle/Stripe → Configuration `packaging` dans build.gradle.kts
**Scripts créés** :
-`fix-nfc-manager.sh` - Patch automatique nfc_manager 3.3.0 (3 corrections)
-`android.sh` - Build Android avec auto-patch intégré
-`deploy-app.sh` - Déploiement DEV avec auto-patch et nettoyage cache
**Résultat** : Bundle Android généré avec succès → `geosector-336.aab`
---
### 📦 Packages Flutter modifiés
#### Packages supprimés (incompatibles iOS)
Ces packages causaient des erreurs `'Flutter/Flutter.h' file not found` sur iOS :
| Package | Action | Remplacement |
|---------|--------|--------------|
| `package_info_plus` | ❌ SUPPRIMÉ | ✅ `AppInfoService` auto-généré dans `lib/core/services/app_info_service.dart` |
| `network_info_plus` | ❌ SUPPRIMÉ | ✅ `NetworkInterface` natif Dart (dart:io) |
| `sensors_plus` | ❌ SUPPRIMÉ | ⚠️ Mode boussole retiré (feature optionnelle peu utilisée) |
**Impact fonctionnel** : Minimal - Perte de fonctionnalités mineures (mode boussole, diagnostic WiFi SSID/BSSID)
#### Configuration finale pubspec.yaml
```yaml
dependencies:
flutter:
sdk: flutter
environment:
sdk: '>=3.0.0 <4.0.0'
# Flutter 3.24.5 LTS + Dart 3.5.4
# Packages downgradés pour compatibilité
```
**Versions clés** :
- `nfc_manager: 3.3.0` - Nécessite patch (automatique via scripts)
- `syncfusion_flutter_charts: 27.2.5` - Sweet spot compatible
- `geolocator: 13.0.3` - Sans toARGB32()
- `battery_plus: 6.0.3` - Fix Gradle AGP 8
- `connectivity_plus: 6.0.5` - Fix Gradle AGP 8
---
## 📋 Étapes de compilation iOS sur Mac mini
### 1⃣ Décompression et setup initial
```bash
# Décompresser l'archive
cd ~/dev/geosector
unzip app-14oct2025.zip
cd app
# Vérifier la version Flutter (doit être 3.24.5 LTS)
flutter --version
# Flutter 3.24.5 • channel stable
# Dart 3.5.4
```
### 2⃣ Installation des dépendances
```bash
# Nettoyer (par précaution)
flutter clean
# Récupérer les dépendances Flutter
flutter pub get
# Installer les pods iOS
cd ios
pod install
cd ..
```
**Résultat attendu** :
- ✅ 25 pods installés
- ✅ Aucune erreur de dépendances
### 3⃣ Vérification de la configuration iOS
**Fichiers critiques à vérifier** :
#### `ios/Runner/Info.plist`
Doit contenir les permissions :
- ✅ Localisation (GPS)
- ✅ NFC (tags secteurs)
- ✅ Bluetooth (terminaux Stripe)
- ✅ Caméra (scan cartes)
- ✅ Photos (justificatifs)
#### `ios/Runner/Runner.entitlements`
Doit contenir :
- ✅ NFC Tag Reading (NDEF, TAG)
- ✅ Stripe Terminal - Tap to Pay on iPhone
- ✅ Network Access
- ✅ Keychain Sharing
### 4⃣ Compilation de test (sans signature)
```bash
# Build iOS en release sans codesign
flutter build ios --release --no-codesign
```
**Résultats possibles** :
#### ✅ Si compilation réussit
→ Passer directement à l'étape 5 (Xcode)
#### ❌ Si erreurs de compilation
Consulter `README-IOS.md` (section "Diagnostic final - Problème structurel iOS")
**Erreurs possibles** :
- `'Flutter/Flutter.h' file not found` → Problème SwiftPM (voir README-IOS.md)
- Erreurs de pods → Réexécuter `pod install`
### 5⃣ Configuration Xcode
```bash
# Ouvrir le workspace Xcode
open ios/Runner.xcworkspace
```
#### Dans Xcode :
**A. Vérifier le Team ID**
1. Sélectionner le target `Runner`
2. Onglet `Signing & Capabilities`
3. Team : `6WT84NWCTC`
**B. Vérifier Bundle Identifier**
- Bundle ID : `fr.geosector.app3`
**C. Vérifier les Capabilities**
- ✅ Near Field Communication Tag Reading
- ⚠️ Tap to Pay on iPhone (nécessite approbation Apple spéciale)
**D. Vérifier la version**
- Version : `3.3.6`
- Build : `336`
### 6⃣ Archive pour App Store
```bash
# Dans Xcode :
# Product > Clean Build Folder (Cmd+Shift+K)
# Product > Archive
```
**Durée estimée** : 5-10 minutes
---
## 🔧 Résolution de problèmes iOS
### Problème : Erreur SwiftPM / Flutter.h
**Symptôme** :
```
'Flutter/Flutter.h' file not found
```
**Causes possibles** :
1. Flutter 3.24.5 LTS avec packages récents (incompatibilité SwiftPM)
2. Transition SwiftPM incomplète dans l'écosystème Flutter
**Solutions documentées dans `README-IOS.md`** :
- Option A : Désactiver SwiftPM (forcer CocoaPods pur)
- Option B : Patcher manuellement les headers
- Option C : Attendre Flutter 3.28+ LTS avec SwiftPM stable
### Problème : Pods non installés
```bash
cd ios
rm -rf Pods Podfile.lock
pod install
cd ..
```
### Problème : Cache Flutter
```bash
flutter clean
rm -rf ios/Pods ios/Podfile.lock
flutter pub get
cd ios && pod install && cd ..
```
---
## 📊 État actuel du projet
| Plateforme | Statut | Notes |
|------------|--------|-------|
| **Web** | ✅ Compilé | Déployable immédiatement |
| **Android** | ✅ Compilé | Bundle prêt : `geosector-336.aab` |
| **iOS** | ⏳ En attente | Configuration Mac mini requise |
---
## 📂 Structure du projet transféré
```
app/
├── fix-nfc-manager.sh # Script de patch nfc_manager (Android uniquement)
├── android.sh # Build Android avec auto-patch
├── deploy-app.sh # Déploiement DEV avec auto-patch
├── pubspec.yaml # Configuration finale Flutter 3.24.5 LTS
├── README-IOS.md # Guide détaillé iOS (historique problèmes)
├── TRANSFERT-MAC.md # Ce fichier
├── docs/
│ └── TODO-APP.md # Documentation complète (Phase 8 Android complétée)
├── lib/
│ └── core/services/
│ └── app_info_service.dart # Remplace package_info_plus (auto-généré)
├── android/
│ └── app/build.gradle.kts # Configuration packaging BouncyCastle
└── ios/
├── Runner/
│ ├── Info.plist # Permissions iOS
│ └── Runner.entitlements # Entitlements Stripe Tap to Pay
└── Podfile # CocoaPods configuration
```
---
## 🎯 Objectif final iOS
**Créer l'archive App Store** :
1. ✅ Compilation iOS réussie
2. ✅ Validation de l'archive (Organizer)
3. ✅ Upload vers App Store Connect
4. ✅ Configuration métadonnées + captures d'écran
5. ✅ Soumission pour révision Apple
**Deadline** : Aucune urgence (Android fonctionnel pour tests)
---
## 📞 Support et documentation
**Documents de référence** :
- `README-IOS.md` - Guide complet iOS avec historique des tentatives
- `docs/TODO-APP.md` - Documentation technique complète (Phase 8 Android)
- Apple Developer : https://developer.apple.com
- App Store Connect : https://appstoreconnect.apple.com
**Configuration serveur** :
- DEV : dapp.geosector.fr
- REC : rapp.geosector.fr
- PROD : app3.geosector.fr
---
**✅ Le projet est prêt pour le transfert et la compilation iOS !**
**Prochaines étapes** :
1. Zipper le dossier `app/`
2. Transférer sur Mac mini (Samba/rsync)
3. Suivre les étapes 1-6 ci-dessus
4. Croiser les doigts pour la compilation iOS 🤞
**Bonne chance !** 🚀

View File

@@ -16,28 +16,28 @@ if (keystorePropertiesFile.exists()) {
}
android {
namespace = "fr.geosector.app2025"
compileSdk = flutter.compileSdkVersion
namespace = "fr.geosector.app3"
compileSdk = 35 // Requis par plusieurs plugins (flutter_local_notifications, stripe, etc.)
ndkVersion = "27.0.12077973"
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11.toString()
jvmTarget = "21"
}
defaultConfig {
// Application ID for Google Play Store
applicationId = "fr.geosector.app2025"
applicationId = "fr.geosector.app3"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
// Minimum SDK 28 requis pour Stripe Tap to Pay
minSdk = 28
targetSdk = flutter.targetSdkVersion
targetSdk = 35 // API 35 requise par Google Play (Oct 2024+)
versionCode = flutter.versionCode
versionName = flutter.versionName
}
@@ -58,7 +58,7 @@ android {
// Optimisations sans ProGuard pour éviter les problèmes
isMinifyEnabled = false
isShrinkResources = false
// Configuration de signature
if (keystorePropertiesFile.exists()) {
signingConfig = signingConfigs.getByName("release")
@@ -66,7 +66,7 @@ android {
signingConfig = signingConfigs.getByName("debug")
}
}
debug {
// Mode debug pour le développement
isDebuggable = true
@@ -74,6 +74,13 @@ android {
versionNameSuffix = "-DEBUG"
}
}
// Résolution des conflits de fichiers dupliqués (Stripe + BouncyCastle)
packaging {
resources {
pickFirst("org/bouncycastle/**")
}
}
}
flutter {

View File

@@ -1,4 +1,4 @@
package fr.geosector.app2025
package fr.geosector.app3
import io.flutter.embedding.android.FlutterActivity

View File

@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Forcer le mode clair uniquement (désactiver le mode sombre) -->
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
@@ -12,7 +13,7 @@
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -5,6 +5,26 @@ allprojects {
}
}
// FORCER Java 21 pour TOUS les projets et sous-projets
allprojects {
afterEvaluate {
// Configuration Android (pour les modules Android)
extensions.findByType<com.android.build.gradle.BaseExtension>()?.apply {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
}
// Configuration Kotlin (pour tous les modules Kotlin)
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = "21"
}
}
}
}
val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
rootProject.layout.buildDirectory.value(newBuildDir)

BIN
app/apple1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

BIN
app/assets/images/icons/icon-1024.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 222 KiB

View File

@@ -1,164 +0,0 @@
# 🔧 Claude Code - Analyse et Correction Flutter
## 📋 Mission
Tu es un expert Flutter/Dart chargé de nettoyer le code de l'application Geosector. Ta mission est d'analyser tous les fichiers Dart du projet et de corriger TOUTES les erreurs et avertissements détectés par `flutter analyze`.
## 🎯 Objectifs
1. **Exécuter l'analyse Flutter** sur l'ensemble du projet
2. **Corriger toutes les erreurs** (errors) en priorité
3. **Corriger tous les avertissements** (warnings)
4. **Corriger les informations** (info) si pertinent
5. **Documenter les changements** effectués
## 📝 Instructions détaillées
### Étape 1 : Analyse initiale
```bash
flutter analyze
```
- Capturer le nombre total d'issues
- Identifier les patterns d'erreurs récurrents
- Prioriser les corrections (errors → warnings → info)
### Étape 2 : Corrections par catégorie
#### 🔴 ERRORS (Priorité maximale)
Corriger en priorité toutes les erreurs qui empêchent la compilation :
- `undefined_named_parameter`
- `undefined_method`
- `undefined_getter`
- `argument_type_not_assignable`
- `return_of_invalid_type`
- `creation_with_non_type`
#### 🟠 WARNINGS (Priorité haute)
Corriger les avertissements qui peuvent causer des bugs :
- `must_be_immutable`
- `unused_element`
- `unused_element_parameter`
- `unused_local_variable`
- `invalid_use_of_protected_member`
- `invalid_use_of_visible_for_testing_member`
#### 🟡 INFO (Priorité moyenne)
Corriger les problèmes de qualité de code :
- `depend_on_referenced_packages` → Ajouter les dépendances manquantes dans pubspec.yaml
- `deprecated_member_use` → Remplacer `withOpacity` par `withValues()`
- `use_build_context_synchronously` → Ajouter `if (context.mounted)`
- `prefer_const_constructors`
- `prefer_const_literals_to_create_immutables`
### Étape 3 : Patterns de correction spécifiques
#### Pour `deprecated_member_use` (withOpacity)
```dart
// ❌ Ancien
color: Colors.blue.withOpacity(0.5)
// ✅ Nouveau
color: Colors.blue.withValues(alpha: 127) // 0.5 * 255 = 127
```
#### Pour `use_build_context_synchronously`
```dart
// ❌ Ancien
await someAsyncOperation();
Navigator.of(context).pop();
// ✅ Nouveau
await someAsyncOperation();
if (context.mounted) {
Navigator.of(context).pop();
}
```
#### Pour `must_be_immutable` avec HiveObject
```dart
// Pour les modèles Hive, ajouter une annotation pour ignorer
// ignore: must_be_immutable
@HiveType(typeId: X)
class MyModel extends HiveObject {
// ...
}
```
### Étape 4 : Modules à traiter
#### 🚫 Module Chat (À ignorer ou supprimer)
Le dossier `lib/chat/` contient de nombreuses erreurs car il n'est pas utilisé.
**Options** :
1. Supprimer complètement le dossier `lib/chat/` si non utilisé
2. OU corriger les dépendances manquantes (equatable dans pubspec.yaml)
3. OU exclure de l'analyse dans `analysis_options.yaml`
#### ✅ Modules prioritaires
Concentre-toi sur les modules actifs :
- `lib/core/` - Services, repositories, models
- `lib/presentation/` - UI widgets et pages
- `lib/shared/` - Composants partagés
### Étape 5 : Vérification finale
```bash
flutter analyze
```
- Vérifier qu'il n'y a plus d'erreurs
- Documenter les warnings restants qui ne peuvent pas être corrigés
- Tester que l'application compile et fonctionne
## 🛠️ Commandes utiles
```bash
# Analyse complète
flutter analyze
# Analyse d'un fichier spécifique
flutter analyze lib/presentation/widgets/dashboard_app_bar.dart
# Format du code
flutter format lib/
# Nettoyer et reconstruire
flutter clean && flutter pub get
# Générer les adapters Hive si nécessaire
flutter packages pub run build_runner build --delete-conflicting-outputs
```
## 📊 Rapport attendu
À la fin, fournir un rapport avec :
1. **Nombre d'issues avant** : X errors, Y warnings, Z info
2. **Nombre d'issues après** : 0 errors, Y warnings, Z info
3. **Liste des fichiers modifiés** avec le type de correction
4. **Décisions prises** (ex: suppression du module chat, ajout de dépendances)
5. **Problèmes non résolus** et pourquoi
## ⚠️ Points d'attention
1. **Ne pas casser le code existant** - Tester après chaque série de corrections
2. **Préserver la logique métier** - Ne pas modifier le comportement de l'app
3. **Respecter l'architecture** - Maintenir les patterns existants (Repository, Singleton, ValueListenableBuilder)
4. **Documenter les suppressions** - Si du code est supprimé, expliquer pourquoi
5. **Gérer les dépendances** - Ajouter dans pubspec.yaml si nécessaire
## 🎯 Résultat attendu
```bash
$ flutter analyze
Analyzing app...
No issues found!
```
## 📝 Notes spécifiques au projet Geosector
- **Architecture sans Provider** : Ne pas ajouter Provider
- **Hive pour le stockage** : Les warnings `must_be_immutable` sur HiveObject sont normaux
- **API First** : Maintenir le pattern de validation API avant sauvegarde locale
- **LoggerService** : Utiliser LoggerService au lieu de debugPrint direct
- **CurrentUserService/CurrentAmicaleService** : Services singleton à préserver
---
**Commence par exécuter `flutter analyze` et montre-moi le résultat pour que nous puissions prioriser les corrections ensemble.**

View File

@@ -9,20 +9,15 @@ workflows:
xcode: latest
cocoapods: default
ios_signing:
distribution_type: app_store
bundle_identifier: fr.geosector.app3
vars:
# Bundle ID et nom de l'app
BUNDLE_ID: "fr.geosector.app2"
BUNDLE_ID: "fr.geosector.app3"
APP_NAME: "GeoSector"
# Variables App Store Connect (à configurer dans Codemagic)
APP_STORE_CONNECT_ISSUER_ID: Encrypted(...)
APP_STORE_CONNECT_KEY_IDENTIFIER: Encrypted(...)
APP_STORE_CONNECT_PRIVATE_KEY: Encrypted(...)
CERTIFICATE_PRIVATE_KEY: Encrypted(...)
groups:
- appstore_credentials # Groupe contenant les secrets Apple
triggering:
events:
- push
@@ -63,14 +58,12 @@ workflows:
script: |
flutter analyze
- name: Set up code signing
- name: Build iOS with code signing
script: |
# Codemagic gère automatiquement la signature avec les certificats fournis
# CodeMagic gère automatiquement le code signing via ios_signing
# Export des variables pour Xcode
xcode-project use-profiles
- name: Build iOS
script: |
flutter build ios --release --no-codesign
flutter build ipa --release --export-options-plist=/Users/builder/export_options.plist
artifacts:
- build/ios/**/*.app
@@ -82,7 +75,7 @@ workflows:
publishing:
email:
recipients:
- votre.email@example.com # Remplacez par votre email
- contact@d6soft.com
notify:
success: true
failure: true

View File

@@ -24,11 +24,6 @@ cd /home/pierre/dev/geosector/app
# Paramètre optionnel pour l'environnement cible
TARGET_ENV=${1:-dev}
# Configuration Ramdisk pour build Flutter optimisé
RAMDISK_BASE="/mnt/ramdisk"
USE_RAMDISK=false
RAMDISK_PROJECT="${RAMDISK_BASE}/flutter-build/geosector"
# Configuration SSH
HOST_KEY="/home/pierre/.ssh/id_rsa_mbpi"
HOST_PORT="22"
@@ -152,22 +147,15 @@ if [ "$SOURCE_TYPE" = "local_build" ]; then
# DEV: Build Flutter et créer une archive
echo_step "Building Flutter app for DEV..."
# Vérifier la disponibilité du ramdisk
if [ -d "${RAMDISK_BASE}" ] && [ -w "${RAMDISK_BASE}" ]; then
echo_info "✓ Ramdisk disponible ($(df -h ${RAMDISK_BASE} | awk 'NR==2 {print $4}') libre)"
USE_RAMDISK=true
# Configuration du cache local (partagé web + iOS/Android)
echo_info "📦 Configuration du cache local pour builds web et mobile..."
export PUB_CACHE="$PWD/.pub-cache-local"
export GRADLE_USER_HOME="$PWD/.gradle-local"
mkdir -p "$PUB_CACHE" "$GRADLE_USER_HOME"
# Configurer les caches Flutter dans le ramdisk
export PUB_CACHE="${RAMDISK_BASE}/.pub-cache"
export GRADLE_USER_HOME="${RAMDISK_BASE}/.gradle"
mkdir -p "$PUB_CACHE" "$GRADLE_USER_HOME" "${RAMDISK_BASE}/flutter-build"
echo_info "🚀 Compilation optimisée avec ramdisk activée"
echo_info " Cache Pub: $PUB_CACHE"
echo_info " Cache Gradle: $GRADLE_USER_HOME"
else
echo_warning "Ramdisk non disponible, compilation standard"
fi
echo_info " Cache Pub: $PUB_CACHE"
echo_info " Cache Gradle: $GRADLE_USER_HOME"
echo_info " → Packages patchés seront prêts pour transfert iOS/Android"
# Charger les variables d'environnement
if [ ! -f .env-deploy-dev ]; then
@@ -195,29 +183,38 @@ if [ "$SOURCE_TYPE" = "local_build" ]; then
BUILD_NUMBER=$(echo $VERSION | tr -d '.')
FULL_VERSION="${VERSION}+${BUILD_NUMBER}"
echo_info "Full version: $FULL_VERSION"
sed -i "s/^version: .*/version: $FULL_VERSION/" pubspec.yaml || echo_error "Failed to update pubspec.yaml"
# Préparation du ramdisk si disponible
if [ "$USE_RAMDISK" = true ]; then
echo_info "📋 Copie du projet dans le ramdisk..."
# Nettoyer l'ancien build dans le ramdisk si existant
[ -d "$RAMDISK_PROJECT" ] && rm -rf "$RAMDISK_PROJECT"
# Génération automatique du fichier AppInfoService (remplace package_info_plus)
echo_info "Auto-generating app_info_service.dart with version $VERSION+$BUILD_NUMBER..."
cat > lib/core/services/app_info_service.dart <<EOF
// ⚠️ AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
// This file is automatically generated by deploy-app.sh script
// Last update: $(date '+%Y-%m-%d %H:%M:%S')
// Source: ../VERSION file
//
// GEOSECTOR App Version Service
// Provides application version and build information without external dependencies
# Copier le projet dans le ramdisk (sans les artefacts de build)
rsync -a --info=progress2 \
--exclude='build/' \
--exclude='.dart_tool/' \
--exclude='.pub-cache/' \
--exclude='*.apk' \
--exclude='*.aab' \
"$(pwd)/" "$RAMDISK_PROJECT/"
class AppInfoService {
// Version number (format: x.x.x)
static const String version = '$VERSION';
# Se déplacer dans le projet ramdisk
cd "$RAMDISK_PROJECT"
echo_info "📍 Compilation depuis: $RAMDISK_PROJECT"
fi
// Build number (version without dots: xxx)
static const String buildNumber = '$BUILD_NUMBER';
// Full version string (format: vx.x.x+xxx)
static String get fullVersion => 'v\$version+\$buildNumber';
// Application name
static const String appName = 'GeoSector';
// Package name
static const String packageName = 'fr.geosector.app3';
}
EOF
echo_info "✓ app_info_service.dart updated successfully"
# Mode de compilation en RELEASE (production)
echo_info "🏁 Mode RELEASE - Compilation optimisée pour production"
@@ -227,10 +224,14 @@ if [ "$SOURCE_TYPE" = "local_build" ]; then
echo_info "Cleaning previous builds..."
rm -rf .dart_tool build .packages pubspec.lock 2>/dev/null || true
flutter clean || echo_warning "Flutter clean partially failed"
# Build
echo_info "Getting dependencies..."
flutter pub get || echo_error "Flutter pub get failed"
# Patch nfc_manager 3.3.0 (AndroidManifest namespace)
echo_info "Applying nfc_manager 3.3.0 patch..."
./fastlane/scripts/commun/fix-nfc-manager.sh || echo_error "nfc_manager patch failed"
echo_info "Cleaning generated files..."
dart run build_runner clean || echo_error "Build runner clean failed"
@@ -250,17 +251,6 @@ if [ "$SOURCE_TYPE" = "local_build" ]; then
echo_info "[$(date '+%H:%M:%S.%3N')] Fin de la compilation Flutter"
echo_info "⏱️ Temps de compilation Flutter: ${BUILD_TIME} ms ($((BUILD_TIME/1000)) secondes)"
# Si on utilise le ramdisk, copier les artefacts vers le projet original
if [ "$USE_RAMDISK" = true ]; then
ORIGINAL_PROJECT="/home/pierre/dev/geosector/app"
echo_info "📦 Copie des artefacts de build vers le projet original..."
rsync -a "$RAMDISK_PROJECT/build/" "$ORIGINAL_PROJECT/build/"
# Retourner au répertoire original pour les scripts suivants
cd "$ORIGINAL_PROJECT"
fi
echo_info "Fixing web assets structure..."
./copy-web-images.sh || echo_error "Failed to fix web assets"
@@ -268,17 +258,6 @@ if [ "$SOURCE_TYPE" = "local_build" ]; then
echo_info "Creating archive from build..."
tar -czf "${TEMP_ARCHIVE}" -C ${FLUTTER_BUILD_DIR} . || echo_error "Failed to create archive"
# Afficher les statistiques du ramdisk si utilisé
if [ "$USE_RAMDISK" = true ]; then
echo_info "📊 Statistiques du ramdisk:"
echo_info " Espace utilisé: $(du -sh ${RAMDISK_BASE} 2>/dev/null | cut -f1)"
df -h ${RAMDISK_BASE}
# Optionnel: nettoyer le projet du ramdisk pour libérer la RAM
echo_info "🧹 Nettoyage du ramdisk..."
rm -rf "$RAMDISK_PROJECT"
fi
create_local_backup "${TEMP_ARCHIVE}" "dev"
elif [ "$SOURCE_TYPE" = "local_container" ]; then
@@ -314,8 +293,36 @@ elif [ "$SOURCE_TYPE" = "remote_container" ]; then
incus exec ${SOURCE_CONTAINER} -- rm -f /tmp/${ARCHIVE_NAME}
" || echo_error "Failed to extract archive from IN3 container"
# Copier l'archive vers la machine locale pour backup
scp ${SOURCE_HOST}:/tmp/${ARCHIVE_NAME} ${TEMP_ARCHIVE} || echo_error "Failed to copy archive from IN3"
# Télécharger l'archive vers la machine locale
if [[ "$TARGET_ENV" == "pra" ]]; then
# Pour PROD: télécharger directement vers /data/backup/geosector/
BACKUP_TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
BACKUP_FILE="${BACKUP_DIR}/app-to-pra-${BACKUP_TIMESTAMP}.tar.gz"
echo_info "Downloading archive to backup directory..."
mkdir -p "${BACKUP_DIR}" || echo_warning "Could not create backup directory ${BACKUP_DIR}"
scp ${SOURCE_HOST}:/tmp/${ARCHIVE_NAME} ${BACKUP_FILE} || echo_error "Failed to download archive from IN3"
# Nettoyer sur IN3
ssh ${SOURCE_HOST} "rm -f /tmp/${ARCHIVE_NAME}"
echo_info "Backup saved to: ${BACKUP_FILE}"
echo_info "Backup size: $(du -h \"${BACKUP_FILE}\" | cut -f1)"
# Nettoyer les anciens backups (garder les 10 derniers)
echo_info "Cleaning old backups (keeping last 10)..."
ls -t "${BACKUP_DIR}"/app-to-pra-*.tar.gz 2>/dev/null | tail -n +11 | xargs -r rm -f && {
REMAINING_BACKUPS=$(ls "${BACKUP_DIR}"/app-to-pra-*.tar.gz 2>/dev/null | wc -l)
echo_info "Kept ${REMAINING_BACKUPS} backup(s)"
}
# Utiliser le backup comme archive de travail
TEMP_ARCHIVE="${BACKUP_FILE}"
else
# Pour RCA: copier vers /tmp comme avant
scp ${SOURCE_HOST}:/tmp/${ARCHIVE_NAME} ${TEMP_ARCHIVE} || echo_error "Failed to copy archive from IN3"
create_local_backup "${TEMP_ARCHIVE}" "to-rca"
fi
else
ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST} "
incus project switch ${INCUS_PROJECT} &&
@@ -330,11 +337,6 @@ elif [ "$SOURCE_TYPE" = "remote_container" ]; then
# Copier l'archive vers la machine locale pour backup
scp -i ${HOST_KEY} -P ${HOST_PORT} ${HOST_USER}@${SOURCE_HOST}:/tmp/${ARCHIVE_NAME} ${TEMP_ARCHIVE} || echo_error "Failed to copy archive locally"
fi
if [[ "$SOURCE_HOST" == "IN3" && "$DEST_HOST" == "IN3" ]]; then
create_local_backup "${TEMP_ARCHIVE}" "to-rca"
else
create_local_backup "${TEMP_ARCHIVE}" "to-pra"
fi
fi
@@ -388,6 +390,16 @@ else
incus exec ${DEST_CONTAINER} -- cp -r ${APP_PATH} ${REMOTE_BACKUP_DIR} &&
echo 'Backup created: ${REMOTE_BACKUP_DIR}'
" || echo_warning "No existing installation to backup"
# Nettoyage automatique des anciens backups (garder les 2 derniers)
echo_info "Cleaning old remote backups (keeping last 2)..."
ssh ${DEST_HOST} "
incus exec ${DEST_CONTAINER} -- bash -c '
cd /var/www/geosector/ &&
ls -dt app_backup_* 2>/dev/null | tail -n +3 | xargs -r rm -rf &&
echo \"Remote backups: \$(ls -d app_backup_* 2>/dev/null | wc -l) kept\"
'
" || echo_warning "Could not clean old remote backups"
else
ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${DEST_HOST} "
incus project switch ${INCUS_PROJECT} &&
@@ -395,6 +407,16 @@ else
incus exec ${DEST_CONTAINER} -- cp -r ${APP_PATH} ${REMOTE_BACKUP_DIR} &&
echo 'Backup created: ${REMOTE_BACKUP_DIR}'
" || echo_warning "No existing installation to backup"
# Nettoyage automatique des anciens backups (garder les 2 derniers)
echo_info "Cleaning old remote backups (keeping last 2)..."
ssh -i ${HOST_KEY} -p ${HOST_PORT} ${HOST_USER}@${DEST_HOST} "
incus exec ${DEST_CONTAINER} -- bash -c '
cd /var/www/geosector/ &&
ls -dt app_backup_* 2>/dev/null | tail -n +3 | xargs -r rm -rf &&
echo \"Remote backups: \$(ls -d app_backup_* 2>/dev/null | wc -l) kept\"
'
" || echo_warning "Could not clean old remote backups"
fi
# Transférer l'archive vers le serveur de destination
@@ -415,14 +437,18 @@ else
scp -i ${HOST_KEY} -P ${HOST_PORT} ${TEMP_ARCHIVE} ${HOST_USER}@${DEST_HOST}:/tmp/${ARCHIVE_NAME} || echo_error "Failed to copy archive to destination"
fi
else
# Pour transferts entre containers distants (RCA: dva-geo vers rca-geo sur IN3)
# Pour transferts entre containers distants
if [[ "$SOURCE_HOST" == "IN3" && "$DEST_HOST" == "IN3" ]]; then
# Cas spécial : source et destination sur le même serveur IN3
# Cas spécial : source et destination sur le même serveur IN3 (RCA)
echo_info "Transfer within IN3 (${SOURCE_CONTAINER} to ${DEST_CONTAINER})"
# L'archive est déjà sur IN3, pas besoin de transfert réseau
# Elle a été créée lors de l'étape "remote_container" plus haut
elif [[ "$TARGET_ENV" == "pra" ]]; then
# Pour PROD: upload depuis le PC local (backup) vers IN4
echo_info "Uploading from local backup to IN4..."
scp -i ${HOST_KEY} -P ${HOST_PORT} ${TEMP_ARCHIVE} ${HOST_USER}@${DEST_HOST}:/tmp/${ARCHIVE_NAME} || echo_error "Failed to upload archive to IN4"
elif [[ "$SOURCE_HOST" == "IN3" ]]; then
# Source sur IN3, destination ailleurs
# Source sur IN3, destination ailleurs (cas théorique)
ssh ${SOURCE_HOST} "
scp -i ${HOST_KEY} -P ${HOST_PORT} /tmp/${ARCHIVE_NAME} ${HOST_USER}@${DEST_HOST}:/tmp/${ARCHIVE_NAME}
" || echo_error "Failed to transfer archive from IN3"
@@ -492,7 +518,11 @@ else
fi
# Nettoyage local
rm -f "${TEMP_ARCHIVE}"
# Pour PROD, on conserve l'archive dans /data/backup/geosector/
# Pour DEV et RCA, on supprime le fichier temporaire
if [[ "$TARGET_ENV" != "pra" ]]; then
rm -f "${TEMP_ARCHIVE}"
fi
# =====================================
# Résumé final

View File

@@ -828,6 +828,7 @@ if (kIsWeb)
// 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
```

View File

@@ -124,8 +124,8 @@ if (amicale == null || amicale.id == 0) {
"city": "Paris",
"country": "FR"
},
"url": "https://app.geosector.fr/stripe/return",
"refresh_url": "https://app.geosector.fr/stripe/refresh"
"url": "https://app3.geosector.fr/stripe/return",
"refresh_url": "https://app3.geosector.fr/stripe/refresh"
}
```
@@ -148,8 +148,8 @@ $account = \Stripe\Account::create([
// 2. Création du lien d'onboarding
$onboardingLink = \Stripe\AccountLink::create([
'account' => $account->id,
'refresh_url' => 'https://app.geosector.fr/stripe/refresh',
'return_url' => 'https://app.geosector.fr/stripe/return',
'refresh_url' => 'https://app3.geosector.fr/stripe/refresh',
'return_url' => 'https://app3.geosector.fr/stripe/return',
'type' => 'account_onboarding'
]);
@@ -529,6 +529,378 @@ $paymentIntent = \Stripe\PaymentIntent::create([
---
## 📱 FLOW PAIEMENT QR CODE (Web + Mobile)
### 🎯 Vue d'ensemble
Le paiement par QR Code permet aux clients de payer directement avec leur téléphone en scannant un code QR généré par l'application. Cette méthode fonctionne sur **Web et Mobile** et ne nécessite pas de matériel spécifique.
### 🔄 Diagramme de séquence complet
```
┌─────────────┐ ┌─────────────┐ ┌──────────┐ ┌─────────┐ ┌─────────┐
│ App Flutter │ │ API PHP │ │ Stripe │ │ Client │ │ Passage │
└──────┬──────┘ └──────┬──────┘ └────┬─────┘ └────┬────┘ └────┬────┘
│ │ │ │ │
[1] │ Validation form │ │ │ │
│ + montant CB │ │ │ │
│ │ │ │ │
[2] │ POST/PUT passage │ │ │ │
│──────────────────>│ │ │ │
│ │ │ │ │
[3] │<──────────────────│ │ │ │
│ Passage ID: 456 │ │ │ │
│ │ │ │ │
[4] │ Vérif Stripe │ │ │ │
│ chkStripe=true │ │ │ │
│ + stripeId rempli │ │ │ │
│ │ │ │ │
[5] │ Dialog Sélection │ │ │ │
│ "Règlement CB" │ │ │ │
│ [QRCode|TapToPay] │ │ │ │
│ │ │ │ │
[6] │ Clic "QR Code" │ │ │ │
│ │ │ │ │
[7] │ POST payment-links│ │ │ │
│──────────────────>│ (passage_id: 456)│ │ │
│ │ │ │ │
[8] │ │ Create PaymentLink │ │
│ │─────────────────>│ │ │
│ │ │ │ │
[9] │ │<─────────────────│ │ │
│ │ link_id + url │ │ │
│ │ │ │ │
[10] │<──────────────────│ │ │ │
│ PaymentLink data │ │ │ │
│ │ │ │ │
[11] │ Génération QR │ │ │ │
│ avec URL Stripe │ │ │ │
│ │ │ │ │
[12] │ Affichage dialog │ │ │ │
│ QR Code │ │ │ │
│ ┌──────────────┐ │ │ │ │
│ │ QR Code │ │ │ │ │
│ │ ▓▓▓▓▓▓▓▓ │ │ │ │ │
│ │ 20.00 € │ │ │ │ │
│ └──────────────┘ │ │ │ │
│ │ │ │ │
[13] │ │ │ Scan QR Code │ │
│ │ │<───────────────│ │
│ │ │ │ │
[14] │ │ │ Page paiement │ │
│ │ │───────────────>│ │
│ │ │ Stripe hosted │ │
│ │ │ │ │
[15] │ │ │ Saisie CB │ │
│ │ │<───────────────│ │
│ │ │ │ │
[16] │ │ │ Validation │ │
│ │ │───────────────>│ │
│ │ │ │ │
[17] │ │ Webhook │ │ │
│ │<─────────────────│ │ │
│ │ payment_succeeded│ │ │
│ │ │ │ │
[18] │ │ Update passage │ │ │
│ │────────────────────────────────────────────────>│
│ │ stripe_payment_id│ │ │
│ │ │ │ │
[19] │ │ │ Confirmation │ │
│ │ │───────────────>│ │
│ │ │ "Merci!" │ │
```
### 📋 Détail des étapes
#### Étape 1-3 : SAUVEGARDE DU PASSAGE
**Identique au flow Tap to Pay** - Le passage est toujours créé en premier pour obtenir un ID réel.
#### Étape 4 : VÉRIFICATION STRIPE
**Acteur:** Application Flutter
**Conditions vérifiées:**
```dart
final amicale = CurrentAmicaleService.instance.currentAmicale;
final stripeEnabled = amicale?.chkStripe == true &&
amicale?.stripeId != null &&
amicale!.stripeId.isNotEmpty;
if (stripeEnabled && fkTypeReglement == 3 && montant > 0) {
// Afficher dialog de sélection de méthode
}
```
#### Étape 5 : DIALOG DE SÉLECTION DE MÉTHODE
**Widget:** `PaymentMethodSelectionDialog`
**Interface affichée:**
```
┌────────────────────────────────┐
│ Règlement CB │
│ │
│ 👤 Jean Dupont │
│ 💰 20.00 € │
│ │
│ Sélectionnez une méthode : │
│ │
│ ┌──────────────────────────┐ │
│ │ 📱 Paiement par QR Code │ │
│ │ Le client scanne le code │ │
│ └──────────────────────────┘ │
│ │
│ ┌──────────────────────────┐ │ (Si compatible)
│ │ 💳 Tap to Pay │ │
│ │ Paiement sans contact │ │
│ └──────────────────────────┘ │
│ │
│ 🔒 Sécurisé par Stripe │
└────────────────────────────────┘
```
#### Étape 6-10 : CRÉATION DU PAYMENT LINK
**Requête:** `POST /api/stripe/payment-links`
**Payload:**
```json
{
"amount": 2000,
"currency": "eur",
"description": "Calendrier pompiers - Jean Dupont",
"passage_id": 456,
"metadata": {
"passage_id": "456",
"habitant_name": "Jean Dupont",
"adresse": "10 Rue de la Paix, Paris"
}
}
```
**Réponse:**
```json
{
"success": true,
"payment_link_id": "plink_1234567890",
"url": "https://buy.stripe.com/test_xxxxxxxxxxxxx",
"amount": 2000,
"passage_id": 456
}
```
**Code PHP Backend:**
```php
$paymentLink = \Stripe\PaymentLink::create([
'line_items' => [[
'price_data' => [
'currency' => 'eur',
'product_data' => [
'name' => 'Calendrier pompiers',
],
'unit_amount' => 2000,
],
'quantity' => 1,
]],
'metadata' => [
'passage_id' => '456',
'type' => 'qr_code_payment',
],
'after_completion' => [
'type' => 'hosted_confirmation',
'hosted_confirmation' => [
'custom_message' => 'Merci pour votre paiement !',
],
],
], [
'stripe_account' => $amicale->stripe_id,
]);
```
#### Étape 11-12 : AFFICHAGE DU QR CODE
**Widget:** `QRCodePaymentDialog`
**Interface:**
```
┌──────────────────────────────┐
│ Paiement par QR Code │
│ │
│ 💰 20.00 € │
│ │
│ ┌────────────────────────┐ │
│ │ │ │
│ │ ▓▓▓▓▓ ▓▓▓▓▓▓▓ │ │
│ │ ▓▓▓▓▓ ▓▓ ▓▓ │ │
│ │ ▓▓▓▓▓ ▓▓▓▓▓▓▓ │ │
│ │ QR CODE HERE │ │
│ │ │ │
│ └────────────────────────┘ │
│ │
│ Scannez ce QR code avec │
│ votre téléphone │
│ │
│ Vous serez redirigé vers │
│ une page sécurisée Stripe │
│ │
│ 🔒 Paiement sécurisé │
│ │
│ [Fermer] │
└──────────────────────────────┘
```
#### Étape 13-16 : PAIEMENT CLIENT
**Acteur:** Client final
**Actions:**
1. Scan du QR Code avec son smartphone
2. Ouverture automatique de l'URL Stripe dans le navigateur
3. Affichage de la page de paiement Stripe hébergée
4. Saisie des informations de carte bancaire
5. Validation 3D Secure si nécessaire
6. Confirmation du paiement
#### Étape 17-18 : WEBHOOK ET MISE À JOUR
**Requête Webhook:** `POST /api/stripe/webhook`
**Event:** `checkout.session.completed` ou `payment_intent.succeeded`
**Payload Stripe:**
```json
{
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_1234567890",
"amount": 2000,
"metadata": {
"passage_id": "456"
}
}
}
}
```
**Action Backend:**
```php
// Récupérer le passage
$passage = Passage::find($paymentIntent->metadata->passage_id);
// Mettre à jour avec le payment ID
$passage->stripe_payment_id = $paymentIntent->id;
$passage->save();
Log::info('Payment confirmed via QR Code', [
'passage_id' => $passage->id,
'payment_id' => $paymentIntent->id,
]);
```
### 🔄 Comparaison QR Code vs Tap to Pay
| Aspect | QR Code | Tap to Pay |
|--------|---------|------------|
| **Plateformes** | Web + Mobile | Mobile uniquement |
| **Matériel requis** | Aucun | NFC (iPhone XS+ / Android certifié) |
| **Client utilise** | Son propre téléphone | Le téléphone du pompier |
| **payment_method_types** | `["card"]` | `["card_present"]` |
| **Interface paiement** | Page Stripe hébergée | NFC sur l'app |
| **Délai confirmation** | Immédiat (webhook) | Immédiat (SDK) |
| **Expérience client** | Scan + saisie CB | Approche carte |
| **Sans contact physique** | ✅ Oui (COVID-safe) | ❌ Non (proximité requise) |
| **Montant minimum** | 0.50€ | 1.00€ |
| **Cas d'usage idéal** | Client à distance | Face à face |
### ✅ Conditions d'éligibilité
#### Affichage du bouton "QR Code"
```dart
// Conditions cumulatives :
final canShowQRCode =
amicale.chkStripe == true && // Stripe activé
amicale.stripeId.isNotEmpty && // Compte configuré
fkTypeReglement == 3 && // CB sélectionnée
montant > 0; // Montant valide
```
#### Différences avec Tap to Pay
- **Pas besoin de** `stripeLocationId` (spécifique Terminal)
- **Pas de vérification** device (fonctionne partout)
- **Pas de batterie** minimum requise
### 🎨 Widgets créés
#### 1. PaymentMethodSelectionDialog
**Fichier:** `lib/presentation/widgets/payment_method_selection_dialog.dart`
**Rôle:** Choisir entre QR Code et Tap to Pay
**Props:**
```dart
PaymentMethodSelectionDialog({
required PassageModel passage,
required double amount,
required String habitantName,
required StripeConnectService stripeConnectService,
VoidCallback? onTapToPaySelected,
})
```
#### 2. QRCodePaymentDialog
**Fichier:** `lib/presentation/widgets/qr_code_payment_dialog.dart`
**Rôle:** Afficher le QR Code généré
**Props:**
```dart
QRCodePaymentDialog({
required PaymentLinkResult paymentLink,
VoidCallback? onClose,
})
```
### 🔧 Services modifiés
#### StripeConnectService
**Nouvelle méthode:**
```dart
Future<PaymentLinkResult?> createPaymentLink({
required int amountInCents,
required int passageId,
String? description,
Map<String, dynamic>? metadata,
})
```
### 📊 Modèles créés
#### PaymentLinkResult
**Fichier:** `lib/core/data/models/payment_link_result.dart`
```dart
class PaymentLinkResult {
final String paymentLinkId;
final String url;
final int amount;
final int? passageId;
}
```
### 🔐 Sécurité
#### Validation Backend
```php
// Vérifications obligatoires
$request->validate([
'amount' => 'required|integer|min:50',
'passage_id' => 'required|integer|exists:ope_pass,id',
]);
// Vérifier Stripe activé
if (!$amicale->chk_stripe || empty($amicale->stripe_id)) {
return response()->json(['error' => 'Stripe non activé'], 403);
}
// Créer sur le compte Connect de l'amicale
\Stripe\PaymentLink::create([...], [
'stripe_account' => $amicale->stripe_id,
]);
```
### 📱 Package ajouté
**pubspec.yaml:**
```yaml
dependencies:
qr_flutter: ^4.1.0 # Génération de QR codes
```
---
## 💻 FLOW PAIEMENT WEB
### 🔄 Principales différences avec Tap to Pay
@@ -846,8 +1218,9 @@ Log::info('PaymentIntent created', [
| 1.0 | 28/09/2025 | Création documentation initiale |
| 1.1 | 28/09/2025 | Ajout flow complet Tap to Pay |
| 1.2 | 28/09/2025 | Intégration passage_id et metadata |
| 1.3 | 05/11/2025 | Ajout flow paiement par QR Code |
---
*Document technique - Flow Stripe GEOSECTOR*
*Dernière mise à jour : 28 septembre 2025*
*Dernière mise à jour : 5 novembre 2025*

View File

@@ -1,24 +1,24 @@
# Flutter Analyze Report - GEOSECTOR App
📅 **Date de génération** : 05/10/2025 - 10:00
📅 **Date de génération** : 09/11/2025 - 10:49
🔍 **Analyse complète de l'application Flutter**
📱 **Version en cours** : 3.3.4 (Build 334 - Release)
📱 **Version en cours** : 3.3.6 (Build 336 - Release)
---
## 📊 Résumé Exécutif
- **Total des problèmes détectés** : 32 issues (⬇️ **-185 depuis l'analyse du 29/09** | -85% 🎉)
- **Temps d'analyse** : 0.7s
- **Total des problèmes détectés** : 30 issues (⬇️ **-2 depuis le 05/10** | -6% 🎉)
- **Temps d'analyse** : 1.0s
- **État global** : ✅ **EXCELLENT** - Tous les warnings éliminés !
### Distribution des problèmes
| Type | Nombre | Évolution (vs 29/09) | Sévérité | Action recommandée |
| Type | Nombre | Évolution (vs 05/10) | Sévérité | Action recommandée |
|------|--------|-----------------------|----------|-------------------|
| **Errors** | 0 | ✅ Stable (0) | 🔴 Critique | - |
| **Warnings** | 0 | ✅ **-16 (-100%)** 🎉 | 🟠 Important | ✅ **TERMINÉ** |
| **Info** | 32 | ⬇️ -169 (-84%) 🎉 | 🔵 Informatif | Optimisations mineures |
| **Warnings** | 0 | ✅ Stable (0) | 🟠 Important | ✅ **MAINTENU** |
| **Info** | 30 | ⬇️ -2 (-6%) 🎉 | 🔵 Informatif | Optimisations mineures |
---
@@ -32,25 +32,24 @@
### 🎉 Accomplissement majeur : 100% des warnings éliminés
**Corrections effectuées le 05/10/2025 :**
**Corrections effectuées le 09/11/2025 :**
1.**Suppression de la classe `_RoomTile` non utilisée** (rooms_page_embedded.dart)
2.**Suppression du cast inutile `as int?`** (history_page.dart ligne 201)
3.**Suppression de 4 `.toList()` inutiles dans les spreads** (history_page.dart)
4.**Suppression du champ `_isFirstLoad` non utilisé** (map_page.dart)
5.**Suppression des méthodes `_loadUserSectors` et `_loadUserPassages` non référencées** (map_page.dart)
6.**Suppression de la variable `allSectors` non utilisée** (members_board_passages.dart)
7.**Correction des opérateurs null-aware inutiles** (passage_form_dialog.dart lignes 373, 376)
8.**Re-génération de room.g.dart** avec build_runner pour corriger l'opérateur null-aware
1.**Suppression des `!` inutiles sur savedPassage** (passage_form_dialog.dart lignes 503, 515)
- Création d'une variable locale `confirmedPassage` après la vérification null
- Élimination de 2 warnings `unnecessary_non_null_assertion`
2.**Correction de l'opérateur null-aware dans room.g.dart**
- Remplacement de `?.toList()` par `.toList()` (ligne 29)
- Élimination du warning `invalid_null_aware_operator`
**Impact** :
- 🎯 **-16 warnings** éliminés
- 🚀 Score de qualité du code : **10/10**
-Performance améliorée par suppression de code mort
- 🎯 **-3 warnings** éliminés depuis l'analyse précédente
- 🚀 Score de qualité du code : **10/10** (maintenu)
-Code plus propre et plus sûr
---
## 🔵 Problèmes Informatifs (32 issues) - Réduction massive -84%
## 🔵 Problèmes Informatifs (30 issues) - Réduction continue -6%
### 1. **Interpolation de chaînes** (6 occurrences)
@@ -59,72 +58,67 @@
**Fichiers concernés :**
```
lib/chat/services/chat_service.dart:577
lib/core/services/api_service.dart:344, 784, 810, 882
lib/presentation/dialogs/sector_dialog.dart:577
lib/core/services/api_service.dart:350, 804, 830, 902
lib/presentation/dialogs/sector_dialog.dart:708
```
**🔧 Solution** : Remplacer `"${variable}"` par `"$variable"` quand possible
### 2. **BuildContext async** (5 occurrences)
### 2. **BuildContext async** (7 occurrences)
- `use_build_context_synchronously` : 5 occurrences
- `use_build_context_synchronously` : 7 occurrences
**Fichiers concernés :**
```
lib/presentation/auth/login_page.dart:753
lib/presentation/auth/splash_page.dart:768, 771, 776
lib/presentation/widgets/amicale_form.dart:199
lib/presentation/auth/login_page.dart:733
lib/presentation/auth/register_page.dart:726
lib/presentation/auth/splash_page.dart:760, 763, 768
lib/presentation/widgets/payment_method_selection_dialog.dart:306
lib/presentation/widgets/user_form_dialog.dart:69
```
**🔧 Solution** : Vérifier `mounted` avant d'utiliser `context` dans les callbacks async
### 3. **Optimisations de code** (21 occurrences)
### 3. **Optimisations de code** (17 occurrences)
| Type | Nombre | Solution |
|------|--------|----------|
| `use_super_parameters` | 3 | Utiliser les super parameters (Flutter 3.0+) |
| `depend_on_referenced_packages` | 3 | Ajouter packages au pubspec.yaml |
| `unnecessary_library_name` | 2 | Supprimer directive `library` |
| `unintended_html_in_doc_comment` | 2 | Échapper les `<>` dans les commentaires |
| `sized_box_for_whitespace` | 2 | Utiliser `SizedBox` au lieu de `Container` vide |
| `prefer_interpolation_to_compose_strings` | 2 | Utiliser interpolation au lieu de `+` |
| `deprecated_member_use` | 2 | Remplacer `desiredAccuracy` par `LocationSettings` |
| `use_super_parameters` | 2 | Utiliser les super parameters (Flutter 3.0+) |
| `prefer_final_fields` | 2 | Marquer les champs privés non modifiés comme `final` |
| `unnecessary_to_list_in_spreads` | 1 | Supprimer `.toList()` dans les spreads |
| `sort_child_properties_last` | 1 | Mettre `child` en dernier paramètre |
| `deprecated_member_use` | 1 | Remplacer `isAvailable` par `checkAvailability` |
| `sized_box_for_whitespace` | 2 | Utiliser `SizedBox` au lieu de `Container` vide |
| `unnecessary_library_name` | 1 | Supprimer directive `library` |
| `dangling_library_doc_comments` | 1 | Ajouter `library` ou supprimer le commentaire |
| `curly_braces_in_flow_control_structures` | 1 | Ajouter accolades dans le `if` |
| `sort_child_properties_last` | 1 | Mettre `child` en dernier paramètre |
| `unnecessary_to_list_in_spreads` | 1 | Supprimer `.toList()` dans les spreads |
---
## 🆕 Changements depuis le 29/09/2025
## 🆕 Changements depuis le 05/10/2025
### Améliorations apportées ✅
1. **🎯 Correction complète des warnings** :
- Élimination de 16 warnings (100%)
- Suppression de 186 lignes de code mort
- Nettoyage de 7 fichiers
1. **🎯 Correction complète des nouveaux warnings** :
- Élimination de 3 warnings apparus après les corrections précédentes
- Amélioration de la gestion des types nullable
- Code plus sûr et plus maintenable
2. **🧹 Réduction drastique des infos** :
- De 201 → 32 infos (-84%)
- Élimination des problèmes graves
2. **🧹 Réduction continue des infos** :
- De 32 → 30 infos (-6%)
- Maintien de l'excellence du code
- Conservation uniquement des suggestions mineures
3. **📦 Qualité du code** :
- Score passé de 9.0 → 10/10
- Dette technique réduite de 2.5 → 0.8 jours
- Score maintenu à 10/10
- Dette technique stable à ~0.8 jours
- Maintenabilité excellente
### Fichiers modifiés le 05/10/2025
### Fichiers modifiés le 09/11/2025
```
✅ lib/chat/pages/rooms_page_embedded.dart - Suppression classe _RoomTile
✅ lib/presentation/pages/history_page.dart - Corrections multiples (cast, .toList())
✅ lib/presentation/pages/map_page.dart - Nettoyage code non utilisé
✅ lib/presentation/widgets/members_board_passages.dart - Suppression variable inutile
✅ lib/presentation/widgets/passage_form_dialog.dart - Correction null-aware operators
✅ lib/chat/models/room.g.dart - Re-génération avec build_runner
✅ lib/presentation/widgets/passage_form_dialog.dart - Ajout variable confirmedPassage
✅ lib/chat/models/room.g.dart - Correction opérateur null-aware
```
---
@@ -135,42 +129,42 @@ lib/presentation/widgets/amicale_form.dart:199
| Métrique | 04/09 (baseline) | Aujourd'hui | Évolution |
|----------|------------------|-------------|-----------|
| **Total issues** | 171 | 32 | ⬇️ -139 (-81%) |
| **Total issues** | 171 | 30 | ⬇️ -141 (-82%) |
| **Warnings** | 25 | 0 | ⬇️ -25 (-100%) 🎉 |
| **Infos** | 146 | 32 | ⬇️ -114 (-78%) |
| **Infos** | 146 | 30 | ⬇️ -116 (-79%) |
### Progression par rapport à l'origine (31/08)
| Métrique | 31/08 (origine) | Aujourd'hui | Réduction totale |
|----------|-----------------|-------------|------------------|
| **Total issues** | 551 | 32 | ⬇️ -519 (-94%) 🚀 |
| **Total issues** | 551 | 30 | ⬇️ -521 (-95%) 🚀 |
| **Warnings** | 28 | 0 | ⬇️ -28 (-100%) 🎉 |
| **Infos** | 523 | 32 | ⬇️ -491 (-94%) 🚀 |
| **Infos** | 523 | 30 | ⬇️ -493 (-94%) 🚀 |
---
## 📁 Analyse par Module
### Module Chat (~/lib/chat/)
| Métrique | Valeur | Évolution vs 29/09 |
| Métrique | Valeur | Évolution vs 05/10 |
|----------|--------|---------------------|
| Problèmes totaux | 2 | ⬇️ -66 (-97%) |
| Problèmes totaux | 1 | ⬇️ -1 (-50%) |
| Warnings | 0 | ⬇️ -1 |
| Info | 2 | ⬇️ -65 |
| Info | 1 | Stable |
### Module Core (~/lib/core/)
| Métrique | Valeur | Évolution vs 29/09 |
| Métrique | Valeur | Évolution vs 05/10 |
|----------|--------|---------------------|
| Problèmes totaux | 9 | ⬇️ -5 (-36%) |
| Problèmes totaux | 9 | Stable |
| Warnings | 0 | Stable |
| Info | 9 | ⬇️ -5 |
| Info | 9 | Stable |
### Module Presentation (~/lib/presentation/)
| Métrique | Valeur | Évolution vs 29/09 |
| Métrique | Valeur | Évolution vs 05/10 |
|----------|--------|---------------------|
| Problèmes totaux | 21 | ⬇️ -64 (-75%) |
| Warnings | 0 | ⬇️ -12 |
| Info | 21 | ⬇️ -52 |
| Problèmes totaux | 20 | ⬇️ -1 (-5%) |
| Warnings | 0 | ⬇️ -2 |
| Info | 20 | Stable |
---
@@ -180,10 +174,10 @@ lib/presentation/widgets/amicale_form.dart:199
| Métrique | Valeur actuelle | Objectif | Statut |
|----------|-----------------|----------|------------|
| **Code Health** | 10.0/10 ✨ | 9.0/10 | ✅ **DÉPASSÉ** |
| **Code Health** | 10.0/10 ✨ | 9.0/10 | ✅ **MAINTENU** |
| **Technical Debt** | 0.8 jours | < 2 jours | Excellent |
| **Warnings** | 0 | 0 | **OBJECTIF ATTEINT** |
| **Code Quality** | A+ | A | **DÉPASSÉ** |
| **Warnings** | 0 | 0 | **OBJECTIF MAINTENU** |
| **Code Quality** | A+ | A | **MAINTENU** |
### Historique des analyses
@@ -193,43 +187,39 @@ lib/presentation/widgets/amicale_form.dart:199
| 04/09/2025 | 171 | 0 | 25 | 146 | 3.2.3 | Nettoyage majeur |
| 25/09/2025 | 170 | 0 | 16 | 154 | 3.2.4 | Stable |
| 29/09/2025 | 217 | 0 | 16 | 201 | 3.3.0 | Régression module Chat |
| **05/10/2025** | **32** | **0** | **0** | **32** | **3.3.4** | ** EXCELLENCE ATTEINTE** 🎉 |
| 05/10/2025 | 32 | 0 | 0 | 32 | 3.3.4 | Excellence atteinte 🎉 |
| **09/11/2025** | **30** | **0** | **0** | **30** | **3.3.6** | ** EXCELLENCE MAINTENUE** 🎉 |
### Progression depuis le début (vs origine 31/08)
- **Total** : -519 issues (⬇ **94%**) 🚀
- **Total** : -521 issues (⬇ **95%**) 🚀
- **Warnings** : -28 issues (⬇ **100%**) 🎉
- **Infos** : -491 issues (⬇ **94%**) 🚀
- **Infos** : -493 issues (⬇ **94%**) 🚀
---
## 🎯 Accomplissements de cette session
### ✅ Travail effectué aujourd'hui (05/10/2025)
### ✅ Travail effectué aujourd'hui (09/11/2025)
1. **🎯 Élimination complète des warnings (16 0)**
- Correction de 8 warnings distincts
- Nettoyage de 7 fichiers
- 100% des warnings éliminés
1. **🎯 Maintien de l'excellence (0 warning, 0 error)**
- Correction des 3 nouveaux warnings détectés
- Amélioration de la gestion des types nullable
- Code plus sûr et maintenable
2. **🧹 Nettoyage massif du code**
- Suppression de 186 lignes de code mort
- Élimination des classes/méthodes/variables non utilisées
- Simplification de la logique dans plusieurs fichiers
2. **🧹 Optimisation du code**
- Suppression des `!` inutiles dans passage_form_dialog.dart
- Création de variable locale `confirmedPassage` pour type safety
- Correction de l'opérateur null-aware dans room.g.dart
3. ** Optimisation des performances**
- Suppression des `.toList()` redondants
- Correction des opérateurs null-aware inutiles
- Nettoyage des casts superflus
3. ** Performance et qualité**
- Build runner exécuté avec succès (28 fichiers générés)
- Vérification complète avec flutter analyze
- Réduction de 2 infos supplémentaires (-6%)
4. **📦 Re-génération des fichiers Hive**
- Build runner exécuté avec succès
- Correction automatique du fichier room.g.dart
- 30 fichiers générés/mis à jour
5. **📊 Amélioration drastique de la qualité**
- Score de code health : 9.0 10.0/10
- Dette technique : 2.5 0.8 jours
- Réduction de 85% des issues totales
4. **📊 Maintien du score parfait**
- Score de code health : 10.0/10 (maintenu)
- Dette technique : 0.8 jours (stable)
- 95% de réduction totale depuis l'origine
---
@@ -238,23 +228,22 @@ lib/presentation/widgets/amicale_form.dart:199
### Phase 1 : Optimisations mineures restantes (0.5 jour) - Optionnel
- [ ] Corriger 6 interpolations de chaînes (unnecessary_brace_in_string_interps)
- [ ] Améliorer 5 BuildContext async (use_build_context_synchronously)
- [ ] Appliquer 3 super parameters (use_super_parameters)
- [ ] Améliorer 7 BuildContext async (use_build_context_synchronously)
- [ ] Ajouter 3 packages au pubspec (depend_on_referenced_packages)
- [ ] Remplacer 2 desiredAccuracy deprecated (deprecated_member_use)
### Phase 2 : Perfectionnement (0.5 jour) - Optionnel
### Phase 2 : Perfectionnement (0.3 jour) - Optionnel
- [ ] Nettoyer 2 library names inutiles
- [ ] Corriger 2 commentaires HTML mal formatés
- [ ] Remplacer 2 Container par SizedBox
- [ ] Améliorer 2 concaténations de chaînes
- [ ] Appliquer 2 super parameters (use_super_parameters)
- [ ] Marquer 2 champs comme final (prefer_final_fields)
- [ ] Remplacer 2 Container par SizedBox (sized_box_for_whitespace)
- [ ] Supprimer 1 library name inutile
### Phase 3 : Polish final (0.2 jour) - Optionnel
### Phase 3 : Polish final (0.1 jour) - Optionnel
- [ ] Marquer 2 champs comme final
- [ ] Corriger 1 deprecated member
- [ ] Ajouter accolades dans 1 if
- [ ] Corriger 1 dangling library doc comment
- [ ] Déplacer 1 paramètre child en dernier
- [ ] Supprimer 1 .toList() dans spread
**💡 Note** : Ces optimisations sont toutes de niveau "info" (suggestions de style). Elles n'affectent ni la stabilité ni les performances de l'application.
@@ -266,16 +255,17 @@ lib/presentation/widgets/amicale_form.dart:199
- [x] Code compile sans erreur
- [x] **Tous les warnings corrigés (0/0)** 🎉
- [x] Réduction majeure des issues (-94% depuis origine)
- [x] Réduction majeure des issues (-95% depuis origine)
- [x] Technical debt < 1 jour (0.8 jours)
- [x] Score de maintenabilité 10/10
- [x] Navigation par sous-routes implémentée
- [x] Code mort éliminé
- [x] Optimisations de performance appliquées
- [x] Gestion sûre des types nullable
### En cours (optionnel)
- [ ] Suggestions de style (32 infos restantes)
- [ ] Suggestions de style (30 infos restantes)
- [ ] Tests unitaires (0% objectif 80%)
### À faire (long terme)
@@ -288,36 +278,37 @@ lib/presentation/widgets/amicale_form.dart:199
## 🔄 Prochaines Étapes
1. ** Terminé** : Éliminer tous les warnings **FAIT LE 05/10** 🎉
2. **Optionnel** : Appliquer les 32 suggestions de style (infos)
3. **Version 3.4.0** : Implémentation Stripe Tap to Pay complète
4. **Version 4.0.0** : Tests unitaires + CI/CD
1. ** Terminé** : Éliminer tous les warnings **MAINTENU** 🎉
2. ** Terminé** : Corriger les warnings apparus après corrections **FAIT LE 09/11** 🎉
3. **Optionnel** : Appliquer les 30 suggestions de style (infos)
4. **Version 3.4.0** : Implémentation Stripe Tap to Pay complète
5. **Version 4.0.0** : Tests unitaires + CI/CD
---
## 📊 Métriques Clés
- **Réduction depuis le 29/09** : -185 issues (-85%) 🚀
- **Réduction totale depuis origine** : -519 issues (-94%) 🚀
- **Code Health** : 10.0/10 ( +1.0 point)
- **Technical Debt** : 0.8 jours ( -1.7 jours)
- **Temps de correction estimé restant** : 1.2 jours (uniquement optimisations de style)
- **Réduction depuis le 05/10** : -2 issues (-6%)
- **Réduction totale depuis origine** : -521 issues (-95%) 🚀
- **Code Health** : 10.0/10 (maintenu)
- **Technical Debt** : 0.8 jours (stable)
- **Temps de correction estimé restant** : 0.9 jours (uniquement optimisations de style)
---
## 🏆 Points Positifs Majeurs
1. **🎉 EXCELLENCE ATTEINTE** : 0 warning, 0 error !
2. **🚀 Réduction massive** : -94% des issues depuis l'origine
3. ** Score parfait** : Code Health 10/10
1. **🎉 EXCELLENCE MAINTENUE** : 0 warning, 0 error !
2. **🚀 Réduction massive** : -95% des issues depuis l'origine
3. ** Score parfait maintenu** : Code Health 10/10
4. ** Performance optimale** : Dette technique minimal (0.8j)
5. **📦 Build stable** : Version 3.3.4 prête pour production
6. **🧹 Code propre** : Suppression de 186 lignes de code mort
7. **🎯 Objectifs dépassés** : Tous les warnings éliminés (objectif 100% atteint)
5. **📦 Build stable** : Version 3.3.6 prête pour production
6. **🧹 Code propre** : Gestion sûre des types nullable
7. **🎯 Objectifs maintenus** : Excellence préservée dans le temps
## ✅ Points d'Attention (mineurs)
1. **32 suggestions de style** : Purement cosmétiques, sans impact fonctionnel
1. **30 suggestions de style** : Purement cosmétiques, sans impact fonctionnel
2. **Tests unitaires** : À implémenter (optionnel pour cette phase)
3. **Documentation** : À compléter (long terme)
@@ -327,13 +318,19 @@ lib/presentation/widgets/amicale_form.dart:199
**État actuel : EXCELLENT**
L'application GEOSECTOR a atteint un niveau de qualité exceptionnel avec :
- **0 error, 0 warning** (objectif principal atteint)
- 🚀 **Réduction de 94% des issues** depuis l'origine
- **Score parfait 10/10** pour le code health
- **Dette technique minimale** (0.8 jours)
L'application GEOSECTOR maintient un niveau de qualité exceptionnel avec :
- **0 error, 0 warning** (objectif principal maintenu)
- 🚀 **Réduction de 95% des issues** depuis l'origine
- **Score parfait 10/10** pour le code health (maintenu)
- **Dette technique minimale** (0.8 jours, stable)
Les 32 infos restantes sont uniquement des **suggestions de style** sans impact sur la stabilité ou les performances. L'application est prête pour la production avec une qualité de code exceptionnelle.
Les 30 infos restantes sont uniquement des **suggestions de style** sans impact sur la stabilité ou les performances. L'application est prête pour la production avec une qualité de code exceptionnelle et maintenue dans le temps.
**Nouvelles corrections du 09/11/2025** :
- Amélioration de la gestion des types nullable
- Élimination des `!` inutiles grâce à des variables locales typées
- Correction des opérateurs null-aware dans les fichiers générés
- Maintien de l'excellence avec -2 infos supplémentaires
---

View File

@@ -964,7 +964,7 @@ GEOSECTOR utilise des **clés Stripe différentes** selon l'environnement pour s
|---------------|-----|-------------------|----------------|------|-------|
| **DEV** | `dapp.geosector.fr` | Test Pierre | `pk_test_51QwoVN...`<br>`sk_test_51QwoVN...` | `test` | Développement |
| **REC** | `rapp.geosector.fr` | Test Client | `CLIENT_PK_TEST_A_REMPLACER`<br>`CLIENT_SK_TEST_A_REMPLACER` | `test` | Recette |
| **PROD** | `app.geosector.fr` | Live Client | `CLIENT_PK_LIVE_A_REMPLACER`<br>`CLIENT_SK_LIVE_A_REMPLACER` | `live` | Production |
| **PROD** | `app3.geosector.fr` | Live Client | `CLIENT_PK_LIVE_A_REMPLACER`<br>`CLIENT_SK_LIVE_A_REMPLACER` | `live` | Production |
#### **Types de clés Stripe**
@@ -1014,7 +1014,7 @@ Pour configurer REC et PROD, le client doit fournir ses clés depuis son **Dashb
'mode' => 'test',
],
// Configuration PRODUCTION (app.geosector.fr)
// Configuration PRODUCTION (app3.geosector.fr)
'stripe' => [
'public_key_live' => 'CLIENT_PK_LIVE_A_REMPLACER', // À remplacer
'secret_key_live' => 'CLIENT_SK_LIVE_A_REMPLACER', // À remplacer

View File

@@ -0,0 +1,464 @@
# 🔧 Migration Backend Stripe - Option A (Tout en 1)
## 📋 Objectif
Optimiser la création de compte Stripe Connect en **1 seule requête** côté Flutter qui crée :
1. Le compte Stripe Connect
2. La Location Terminal
3. Le lien d'onboarding
---
## 🗄️ 1. Modification de la base de données
### **Ajouter la colonne `stripe_location_id`**
```sql
ALTER TABLE amicales
ADD COLUMN stripe_location_id VARCHAR(255) NULL
AFTER stripe_id;
```
**Vérification** :
```sql
DESCRIBE amicales;
```
Doit afficher :
```
+-------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+-------+
| stripe_id | varchar(255) | YES | | NULL | |
| stripe_location_id| varchar(255) | YES | | NULL | |
+-------------------+--------------+------+-----+---------+-------+
```
---
## 🔧 2. Modification de l'endpoint `POST /stripe/accounts`
### **Fichier** : `app/Http/Controllers/StripeController.php` (ou similaire)
### **Méthode** : `createAccount()` ou `store()`
### **Code proposé** :
```php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Models\Amicale;
/**
* Créer un compte Stripe Connect avec Location Terminal et lien d'onboarding
*
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function createStripeAccount(Request $request)
{
$request->validate([
'fk_entite' => 'required|integer|exists:amicales,id',
'return_url' => 'required|string|url',
'refresh_url' => 'required|string|url',
]);
$fkEntite = $request->fk_entite;
$amicale = Amicale::findOrFail($fkEntite);
// Vérifier si un compte existe déjà
if (!empty($amicale->stripe_id)) {
return $this->handleExistingAccount($amicale, $request);
}
DB::beginTransaction();
try {
// Configurer la clé Stripe (selon environnement)
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
// 1⃣ Créer le compte Stripe Connect Express
$account = \Stripe\Account::create([
'type' => 'express',
'country' => 'FR',
'email' => $amicale->email,
'business_type' => 'non_profit', // ou 'company' selon le cas
'business_profile' => [
'name' => $amicale->name,
'url' => config('app.url'),
],
'capabilities' => [
'card_payments' => ['requested' => true],
'transfers' => ['requested' => true],
],
]);
\Log::info('Stripe account created', [
'amicale_id' => $amicale->id,
'account_id' => $account->id,
]);
// 2⃣ Créer la Location Terminal pour Tap to Pay
$location = \Stripe\Terminal\Location::create([
'display_name' => $amicale->name,
'address' => [
'line1' => $amicale->adresse1 ?: 'Non renseigné',
'line2' => $amicale->adresse2,
'city' => $amicale->ville ?: 'Non renseigné',
'postal_code' => $amicale->code_postal ?: '00000',
'country' => 'FR',
],
], [
'stripe_account' => $account->id, // ← Important : Connect account
]);
\Log::info('Stripe Terminal Location created', [
'amicale_id' => $amicale->id,
'location_id' => $location->id,
]);
// 3⃣ Créer le lien d'onboarding
$accountLink = \Stripe\AccountLink::create([
'account' => $account->id,
'refresh_url' => $request->refresh_url,
'return_url' => $request->return_url,
'type' => 'account_onboarding',
]);
\Log::info('Stripe onboarding link created', [
'amicale_id' => $amicale->id,
'account_id' => $account->id,
]);
// 4⃣ Sauvegarder TOUT en base de données
$amicale->stripe_id = $account->id;
$amicale->stripe_location_id = $location->id;
$amicale->chk_stripe = true;
$amicale->save();
DB::commit();
// 5⃣ Retourner TOUTES les informations
return response()->json([
'success' => true,
'account_id' => $account->id,
'location_id' => $location->id,
'onboarding_url' => $accountLink->url,
'charges_enabled' => $account->charges_enabled,
'payouts_enabled' => $account->payouts_enabled,
'existing' => false,
'message' => 'Compte Stripe Connect créé avec succès',
], 201);
} catch (\Stripe\Exception\ApiErrorException $e) {
DB::rollBack();
\Log::error('Stripe API error', [
'amicale_id' => $amicale->id,
'error' => $e->getMessage(),
'type' => get_class($e),
]);
return response()->json([
'success' => false,
'message' => 'Erreur Stripe : ' . $e->getMessage(),
], 500);
} catch (\Exception $e) {
DB::rollBack();
\Log::error('Stripe account creation failed', [
'amicale_id' => $amicale->id,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
return response()->json([
'success' => false,
'message' => 'Erreur lors de la création du compte Stripe',
], 500);
}
}
/**
* Gérer le cas d'un compte Stripe existant
*/
private function handleExistingAccount(Amicale $amicale, Request $request)
{
try {
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
// Récupérer les infos du compte existant
$account = \Stripe\Account::retrieve($amicale->stripe_id);
// Si pas de location_id, la créer maintenant
if (empty($amicale->stripe_location_id)) {
$location = \Stripe\Terminal\Location::create([
'display_name' => $amicale->name,
'address' => [
'line1' => $amicale->adresse1 ?: 'Non renseigné',
'city' => $amicale->ville ?: 'Non renseigné',
'postal_code' => $amicale->code_postal ?: '00000',
'country' => 'FR',
],
], [
'stripe_account' => $amicale->stripe_id,
]);
$amicale->stripe_location_id = $location->id;
$amicale->save();
\Log::info('Location created for existing account', [
'amicale_id' => $amicale->id,
'location_id' => $location->id,
]);
}
// Si le compte est déjà complètement configuré
if ($account->charges_enabled && $account->payouts_enabled) {
return response()->json([
'success' => true,
'account_id' => $amicale->stripe_id,
'location_id' => $amicale->stripe_location_id,
'onboarding_url' => null,
'charges_enabled' => true,
'payouts_enabled' => true,
'existing' => true,
'message' => 'Compte Stripe déjà configuré et actif',
]);
}
// Compte existant mais configuration incomplète : générer un nouveau lien
$accountLink = \Stripe\AccountLink::create([
'account' => $amicale->stripe_id,
'refresh_url' => $request->refresh_url,
'return_url' => $request->return_url,
'type' => 'account_onboarding',
]);
return response()->json([
'success' => true,
'account_id' => $amicale->stripe_id,
'location_id' => $amicale->stripe_location_id,
'onboarding_url' => $accountLink->url,
'charges_enabled' => $account->charges_enabled,
'payouts_enabled' => $account->payouts_enabled,
'existing' => true,
'message' => 'Compte existant, configuration à finaliser',
]);
} catch (\Exception $e) {
\Log::error('Error handling existing account', [
'amicale_id' => $amicale->id,
'error' => $e->getMessage(),
]);
return response()->json([
'success' => false,
'message' => 'Erreur lors de la vérification du compte existant',
], 500);
}
}
```
---
## 📡 3. Modification de l'endpoint `GET /stripe/accounts/{id}/status`
Ajouter `location_id` dans la réponse :
```php
public function checkAccountStatus($amicaleId)
{
$amicale = Amicale::findOrFail($amicaleId);
if (empty($amicale->stripe_id)) {
return response()->json([
'has_account' => false,
'account_id' => null,
'location_id' => null,
'charges_enabled' => false,
'payouts_enabled' => false,
'onboarding_completed' => false,
]);
}
try {
\Stripe\Stripe::setApiKey(config('services.stripe.secret'));
$account = \Stripe\Account::retrieve($amicale->stripe_id);
return response()->json([
'has_account' => true,
'account_id' => $amicale->stripe_id,
'location_id' => $amicale->stripe_location_id, // ← Ajouté
'charges_enabled' => $account->charges_enabled,
'payouts_enabled' => $account->payouts_enabled,
'onboarding_completed' => $account->details_submitted,
]);
} catch (\Exception $e) {
return response()->json([
'has_account' => false,
'error' => $e->getMessage(),
], 500);
}
}
```
---
## 🗑️ 4. Endpoint à SUPPRIMER (devenu inutile)
### **❌ `POST /stripe/locations`**
Cet endpoint n'est plus nécessaire car la Location est créée automatiquement dans `POST /stripe/accounts`.
**Option 1** : Supprimer complètement
**Option 2** : Le garder pour compatibilité temporaire (si utilisé ailleurs)
---
## 📝 5. Modification du modèle Eloquent
### **Fichier** : `app/Models/Amicale.php`
Ajouter le champ `stripe_location_id` :
```php
protected $fillable = [
// ... autres champs
'stripe_id',
'stripe_location_id', // ← Ajouté
'chk_stripe',
];
protected $casts = [
'chk_stripe' => 'boolean',
];
```
---
## ✅ 6. Tests à effectuer
### **Test 1 : Nouvelle amicale**
```bash
curl -X POST http://localhost/api/stripe/accounts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {token}" \
-d '{
"fk_entite": 123,
"return_url": "https://app.geosector.fr/stripe/success",
"refresh_url": "https://app.geosector.fr/stripe/refresh"
}'
```
**Réponse attendue** :
```json
{
"success": true,
"account_id": "acct_xxxxxxxxxxxxx",
"location_id": "tml_xxxxxxxxxxxxx",
"onboarding_url": "https://connect.stripe.com/setup/...",
"charges_enabled": false,
"payouts_enabled": false,
"existing": false,
"message": "Compte Stripe Connect créé avec succès"
}
```
### **Test 2 : Amicale avec compte existant**
```bash
curl -X POST http://localhost/api/stripe/accounts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {token}" \
-d '{
"fk_entite": 456,
"return_url": "https://app.geosector.fr/stripe/success",
"refresh_url": "https://app.geosector.fr/stripe/refresh"
}'
```
**Réponse attendue** :
```json
{
"success": true,
"account_id": "acct_xxxxxxxxxxxxx",
"location_id": "tml_xxxxxxxxxxxxx",
"onboarding_url": null,
"charges_enabled": true,
"payouts_enabled": true,
"existing": true,
"message": "Compte Stripe déjà configuré et actif"
}
```
### **Test 3 : Vérifier la BDD**
```sql
SELECT id, name, stripe_id, stripe_location_id, chk_stripe
FROM amicales
WHERE id = 123;
```
**Résultat attendu** :
```
+-----+------------------+-------------------+-------------------+------------+
| id | name | stripe_id | stripe_location_id| chk_stripe |
+-----+------------------+-------------------+-------------------+------------+
| 123 | Pompiers Paris15 | acct_xxxxxxxxxxxxx| tml_xxxxxxxxxxxxx | 1 |
+-----+------------------+-------------------+-------------------+------------+
```
---
## 🚀 7. Déploiement
### **Étapes** :
1. ✅ Appliquer la migration SQL
2. ✅ Déployer le code Backend modifié
3. ✅ Tester avec Postman/curl
4. ✅ Déployer le code Flutter modifié
5. ✅ Tester le flow complet depuis l'app
---
## 📊 Comparaison Avant/Après
| Aspect | Avant | Après |
|--------|-------|-------|
| **Appels API Flutter → Backend** | 3 | 1 |
| **Appels Backend → Stripe** | 3 | 3 (mais atomiques) |
| **Latence totale** | ~3-5s | ~1-2s |
| **Gestion erreurs** | Complexe | Simplifié avec transaction |
| **Atomicité** | ❌ Non | ✅ Oui (DB transaction) |
| **Location ID sauvegardé** | ❌ Non | ✅ Oui |
---
## 🎯 Bénéfices
1.**Performance** : Latence divisée par 2-3
2.**Fiabilité** : Transaction BDD garantit la cohérence
3.**Simplicité** : Code Flutter plus simple
4.**Maintenance** : Moins de code à maintenir
5.**Traçabilité** : Logs centralisés côté Backend
6.**Tap to Pay prêt** : `location_id` disponible immédiatement
---
## ⚠️ Points d'attention
1. **Rollback** : Si la transaction échoue, rien n'est sauvegardé (bon comportement)
2. **Logs** : Bien logger chaque étape pour le debug
3. **Stripe Connect limitations** : Respecter les rate limits Stripe
4. **Tests** : Tester avec des comptes Stripe de test d'abord
---
## 📚 Ressources
- [Stripe Connect Express Accounts](https://stripe.com/docs/connect/express-accounts)
- [Stripe Terminal Locations](https://stripe.com/docs/terminal/fleet/locations)
- [Stripe Account Links](https://stripe.com/docs/connect/account-links)

View File

@@ -0,0 +1,212 @@
# ✅ Migration Stripe "Option A" - Résumé
## 📅 Date : 3 novembre 2025
---
## 🎯 Objectif
Optimiser la création de compte Stripe Connect en **1 seule requête** côté Flutter qui crée :
1. Le compte Stripe Connect
2. La Location Terminal (pour Tap to Pay)
3. Le lien d'onboarding
---
## ✅ Modifications Flutter APPLIQUÉES
### **1. Modèle `AmicaleModel`**
- ✅ Ajout du champ `stripeLocationId` (HiveField 27)
- ✅ Ajout dans le constructeur
- ✅ Ajout dans `fromJson()`
- ✅ Ajout dans `toJson()`
- ✅ Ajout dans `copyWith()`
- ✅ Adaptateurs Hive régénérés
### **2. Service `StripeTapToPayService`**
- ✅ Récupération du `location_id` depuis `amicale.stripeLocationId`
- ✅ Validation que le `location_id` existe avant initialisation
- ✅ Suppression de la méthode `_fetchConfiguration()` (inutile)
- ✅ Plus besoin de l'endpoint `GET /api/stripe/configuration`
### **3. Service `StripeConnectService`**
- ✅ Simplification de `createStripeAccount()` : 1 seule requête
- ✅ Ajout des URLs `return_url` et `refresh_url` dans la requête
- ✅ Récupération de `location_id` et `onboarding_url` dans la réponse
- ✅ Suppression de l'appel à `/stripe/locations`
- ✅ Ajout de `locationId` dans `StripeAccountStatus`
- ✅ Conservation de `getOnboardingLink()` (marqué déprécié)
---
## ⚠️ Modifications Backend REQUISES
### **1. Base de données**
```sql
ALTER TABLE amicales
ADD COLUMN stripe_location_id VARCHAR(255) NULL
AFTER stripe_id;
```
### **2. Endpoint `POST /stripe/accounts`**
**Modifications nécessaires** :
- Accepter `return_url` et `refresh_url` dans la requête
- Créer le compte Stripe Connect
- Créer la Location Terminal
- Créer le lien d'onboarding
- Sauvegarder `stripe_id`, `stripe_location_id`, `chk_stripe` en BDD
- Retourner : `account_id`, `location_id`, `onboarding_url`, `charges_enabled`, `payouts_enabled`, `existing`
**Voir le code complet** : `docs/STRIPE-BACKEND-MIGRATION.md`
### **3. Endpoint `GET /stripe/accounts/{id}/status`**
**Modification** :
- Ajouter `location_id` dans la réponse JSON
### **4. Endpoint `POST /stripe/locations`**
**Action** : À supprimer (devenu inutile) ou garder pour compatibilité temporaire
---
## 📊 Comparaison Avant/Après
| Aspect | Avant | Après |
|--------|-------|-------|
| **Appels API Flutter → Backend** | 3 | 1 |
| **Latence totale** | ~3-5s | ~1-2s |
| **Gestion erreurs** | Complexe (try/catch multiples) | Simplifié (transaction atomique) |
| **Atomicité BDD** | ❌ Non garantie | ✅ Oui (transaction) |
| **Location ID sauvegardé** | ❌ Non | ✅ Oui |
| **Code à maintenir** | Plus complexe | Plus simple |
---
## 🔄 Flow optimisé
```
Flutter (1 appel) Backend (3 appels Stripe) Stripe API
│ │ │
│ POST /stripe/accounts │ │
│ { │ │
│ fk_entite: 123, │ │
│ return_url: "...", │ │
│ refresh_url: "..." │ │
│ } │ │
├─────────────────────────────>│ │
│ │ 1. Create Account │
│ ├──────────────────────────>│
│ │<──────────────────────────┤
│ │ account_id: acct_xxx │
│ │ │
│ │ 2. Create Location │
│ ├──────────────────────────>│
│ │<──────────────────────────┤
│ │ location_id: tml_xxx │
│ │ │
│ │ 3. Create AccountLink │
│ ├──────────────────────────>│
│ │<──────────────────────────┤
│ │ onboarding_url │
│ │ │
│ │ (Sauvegarde en BDD) │
│ │ │
│<─────────────────────────────┤ │
│ { │ │
│ account_id: acct_xxx, │ │
│ location_id: tml_xxx, │ │
│ onboarding_url: "..." │ │
│ } │ │
```
---
## ✅ Tests à effectuer
### **Backend (après implémentation)**
1. [ ] Migration SQL appliquée
2. [ ] Test avec Postman : nouvelle amicale
3. [ ] Test avec Postman : amicale existante
4. [ ] Vérification BDD : `stripe_location_id` bien sauvegardé
5. [ ] Logs vérifiés (pas d'erreurs)
### **Flutter (maintenant)**
1. [ ] Compilation OK (déjà fait ✅)
2. [ ] Test création compte depuis l'app Web admin
3. [ ] Vérification que le `location_id` est bien dans l'amicale
4. [ ] Test paiement Tap to Pay avec le `location_id`
5. [ ] Vérification que l'erreur "Erreur inattendue" n'apparaît plus
---
## 🚨 Points d'attention
### **Backend**
- Utiliser une **transaction BDD** pour garantir l'atomicité
- Bien logger chaque étape pour le debug
- Gérer le cas des comptes existants (avec/sans `location_id`)
- Tester avec des clés Stripe de test d'abord
### **Flutter**
- Le backend doit être déployé **AVANT** de tester l'app
- Si le backend n'est pas prêt, l'app retournera une erreur 400/500
- Les anciens comptes sans `location_id` devront être migrés
---
## 📚 Documentation
- **Code Backend complet** : `docs/STRIPE-BACKEND-MIGRATION.md`
- **Code Flutter modifié** : `lib/core/services/stripe_connect_service.dart`
- **Modèle modifié** : `lib/core/data/models/amicale_model.dart`
- **Service Tap to Pay** : `lib/core/services/stripe_tap_to_pay_service.dart`
---
## 🎯 Prochaines étapes
### **Étape 1 : Backend**
1. Implémenter les modifications backend
2. Tester avec Postman
3. Valider que tout fonctionne
### **Étape 2 : Migration des données existantes**
Pour les amicales qui ont déjà un `stripe_id` mais pas de `stripe_location_id` :
```sql
-- Identifier les amicales concernées
SELECT id, name, stripe_id, stripe_location_id
FROM amicales
WHERE stripe_id IS NOT NULL
AND stripe_location_id IS NULL;
```
**Option A** : Les créer manuellement via l'API Stripe
**Option B** : Ajouter un endpoint de migration `POST /stripe/migrate-locations`
### **Étape 3 : Tests complets**
1. Test création nouvelle amicale
2. Test amicale existante avec compte
3. Test Tap to Pay avec paiement CB
4. Validation que l'erreur est corrigée
---
## ✅ État actuel
| Composant | État | Commentaire |
|-----------|------|-------------|
| **AmicaleModel** | ✅ Modifié | Champ `stripeLocationId` ajouté |
| **StripeTapToPayService** | ✅ Modifié | Utilise `amicale.stripeLocationId` |
| **StripeConnectService** | ✅ Modifié | 1 seule requête optimisée |
| **Build Runner** | ✅ Exécuté | Adaptateurs Hive régénérés |
| **Compilation Flutter** | ✅ OK | Aucune erreur |
| **Backend** | ⏳ En attente | À implémenter |
| **Tests** | ⏳ En attente | Après implémentation Backend |
---
## 📞 Support
- Documentation Stripe Connect : https://stripe.com/docs/connect
- Documentation Terminal Locations : https://stripe.com/docs/terminal/fleet/locations
- Documentation AccountLinks : https://stripe.com/docs/connect/account-links

File diff suppressed because it is too large Load Diff

View File

@@ -1,444 +0,0 @@
# GEOSECTOR v3.2.4
## Points à traiter
---
**Client** : GEOSECTOR
**Date** : 11 septembre 2025
**Deadline** : 08 octobre 2025 (Congrès)
**Version actuelle** : v3.2.4
**Version cible** : v3.4.4
---
<div style="page-break-after: always;"></div>
## SOMMAIRE
1. [Priorité 1 - Corrections critiques](#priorité-1---corrections-critiques)
2. [Priorité 2 - Améliorations fonctionnelles](#priorité-2---améliorations-fonctionnelles)
3. [Priorité 3 - Interface utilisateur](#priorité-3---interface-utilisateur)
4. [Restrictions d'accès](#restrictions-daccès)
5. [Mode Super Admin](#mode-super-admin)
6. [Processus d'inscription](#processus-dinscription)
7. [Module Stripe](#module-stripe)
8. [Planning prévisionnel](#planning-prévisionnel)
9. [Point financier](#point-financier)
---
<div style="page-break-after: always;"></div>
## PRIORITÉ 1 - Corrections critiques
### 🔐 Authentification et sécurité
**1. Problème de déconnexion intempestive**
- [x] **Symptôme** : Le rafraîchissement de la page (F5) déconnecte l'utilisateur (05/10/2025)
- [x] **Impact** : Perte de session et du travail en cours
- [x] **Correction** : Maintenir la session active lors du rafraîchissement via endpoint GET /api/user/session
**2. Gestion des mots de passe**
- [x] **Symptôme** : Le mot de passe généré automatiquement contient des espaces
- [x] **Impact** : Impossibilité de connexion avec le mot de passe fourni
- [x] **Correction** : Générer des mots de passe sans espaces
### 📝 Formulaires et saisie de données
**3. Saisie des passages**
- [x] **Symptôme** : Le champ "nom" est obligatoire lors de la saisie d'un passage
- [x] **Impact** : Blocage si le nom n'est pas connu
- [x] **Correction** : Rendre le champ nom optionnel
**4. Modification des secteurs**
- [x] **Symptôme** : Le changement de membre affecté à un secteur n'est pas sauvegardé
- [x] **Impact** : Incohérence dans l'attribution des secteurs
- [x] **Correction** : Corriger la sauvegarde de l'affectation
**5. Enregistrement des passages**
- [ ] **Symptôme** : L'enregistrement d'un nouveau passage ne fonctionne pas correctement
- [ ] **Impact** : Impossibilité d'enregistrer de nouveaux passages
- [ ] **Correction** : Vérifier et corriger le processus d'enregistrement
---
## PRIORITÉ 2 - Améliorations fonctionnelles
### 👥 Gestion des membres
**Liste des membres avec statistiques**
- [x] Afficher la liste des membres avec leurs statistiques (comme ancienne version)
- [x] Vue d'ensemble rapide des performances de chaque membre
**Filtres et organisation**
- [ ] Ajouter des filtres sur la liste des membres dans "Amicale et membres"
- [ ] Afficher les membres sélectionnés en haut de liste lors de modifications
**Gestion des identifiants**
- [ ] Permettre la modification de l'identifiant utilisateur
- [ ] Email non obligatoire si identifiant et mot de passe sont saisis manuellement
### 📊 Historique et reporting
**Sélection avancée**
- [x] Permettre le choix du membre dans l'historique
- [x] Ajouter des sélecteurs de dates (début/fin) dans l'historique
**Affichage et visibilité**
- [x] Corriger le problème de logo blanc sur blanc pour les passages "à finaliser" (04/10/2025)
- [ ] Historique en bas : 1-2 adresses seulement visibles, impossibilité de cliquer dessus
- [x] Ajouter une ligne avec les totaux dans l'historique
### 🗺️ Carte et géolocalisation
**Configuration de la carte**
- [x] Simplifier le système de zoom : zoom par défaut à 15, conservation du zoom utilisateur uniquement (05/10/2025)
- [x] Conservation du zoom lors de la sélection d'un secteur dans la combobox - Le zoom reste inchangé au lieu de s'ajuster automatiquement (05/10/2025)
- [x] Centrage GPS amicale au premier chargement - La carte se centre sur les coordonnées GPS de l'amicale au lieu des secteurs (05/10/2025)
- [x] Suppression du filtrage côté client - Élimination du double filtrage inutile des secteurs et passages (l'API filtre déjà selon le rôle) (05/10/2025)
- [x] Corriger l'affichage des passages par défaut en mode admin (filtre "Aucun passage" non respecté) (04/10/2025)
- [x] Stabiliser les labels de secteurs (nombre de passages/membres) lors de la sélection d'un secteur (04/10/2025)
- [ ] Définir un zoom maximal pour éviter le sur-zoom
- [ ] Étudier l'utilisation d'un style de carte type Snapchat
**Mode terrain**
- [ ] Optimiser la précision et la fiabilité du GPS
- [ ] Améliorer la géolocalisation en mode terrain
- [ ] Mode Web utilisateur : impossible de se déplacer sur la carte en mode terrain (retour automatique à la position)
**Divers**
**Synchronisation des données**
- [x] Membre rattaché à un secteur avec 15 passages visibles sur la carte mais affiche 0 passage à finaliser en mode utilisateur - Correction du filtrage des passages de type 2 (À finaliser) pour afficher tous les passages de ce type en mode utilisateur (05/10/2025)
**Performance et formulaires**
- [ ] Bloquer l'enregistrement à 1 seul lors de la création de membre (actuellement très long, plusieurs clics créent X membres en double)
- [x] Simplifier le script de déploiement (suppression du choix Fast/Release) (04/10/2025)
- [x] Optimiser le rechargement de la carte : secteurs chargés uniquement lors de création/modification, pas en temps réel (04/10/2025)
- [x] Nettoyage du code : réduction des warnings Flutter de 16 à 6 (-62.5%) via suppression des imports non utilisés (04/10/2025)
**Carte et navigation**
- [ ] Mode terrain smartphone : carte trop petite, le zoom revient automatiquement et empêche de dézoomer pour voir les points d'intérêt
- [ ] Points de carte affichés devant les textes (en admin et en utilisateur)
- [ ] Listing des rues invisible (le clavier se met devant)
- [ ] Recherche de rue : ne trouve pas si pas à proximité même si la rue est dans le secteur
- [x] Revoir la couleur des pointeurs sur la carte (04/10/2025)
- [x] Ajouter un filtre de type de passage sur la carte admin (04/10/2025)
- [x] Mode terrain : rayon d'action réduit à 500m pour affichage des passages (04/10/2025)
- [x] Mode terrain : afficher tous les types de passages (pas seulement "à finaliser") (04/10/2025)
- [x] Mode terrain : marqueurs carte avec couleurs selon type de passage (04/10/2025)
**Fonctionnalités utilisateur**
- [ ] Carte en mode utilisateur : actuellement consultable uniquement, affiche l'adresse au clic - évaluer la possibilité de valider un passage directement depuis la carte
- [ ] Désactiver temporairement l'envoi de reçu (ne doit pas encore être actif)
### 📋 Gestion des passages
**Interface et interaction**
- [x] Clic sur la card d'un passage dans list_widget pour le modifier directement (04/10/2025)
- [x] Mémoriser la dernière adresse saisie dans le formulaire de passage pour l'afficher à la prochaine création (04/10/2025)
**Actions groupées**
- [ ] Permettre la suppression de plusieurs passages en une seule fois
- [ ] Implémenter la possibilité de récupérer des passages supprimés (corbeille/historique)
**Statistiques et graphiques**
- [ ] Corriger l'affichage du règlement par chèque qui n'apparaît pas dans le graphe pie
- [x] Corriger l'affichage du graphique Pie qui affichait 100% effectués (filtre excluait les passages "à finaliser") (04/10/2025)
- [x] Corriger le bug de calcul du total des paiements dans l'historique (comptait les passages non payés au lieu de les ignorer) (04/10/2025)
- [x] Corriger le graphique pie de la home page admin qui affichait les passages utilisateur au lieu de tous les passages (04/10/2025)
---
<div style="page-break-after: always;"></div>
## PRIORITÉ 3 - Interface utilisateur
### 💬 Module de messagerie
**Visibilité des actions**
- [ ] Améliorer la visibilité du bouton "Envoyer un message"
- [ ] Augmenter l'épaisseur de la police pour une meilleure lisibilité
### 🎨 Ergonomie des formulaires
**Textes d'aide**
- [ ] Améliorer les textes d'aide (helpers) dans les fiches membres
- [ ] Rendre les textes plus clairs et explicites
### 🏗️ Architecture et refactoring
**Simplification du layout**
- [x] Corriger le fond dégradé qui affichait rouge en mode user pour les admins (05/10/2025)
- [ ] Simplifier l'architecture DashboardLayout et AppScaffold (actuellement redondants avec fonds dupliqués)
- [ ] Refactoriser pour séparer clairement les responsabilités (fond, navigation, restrictions d'accès)
---
## RESTRICTIONS D'ACCÈS
### Mode Admin
- [ ] L'accès administrateur doit être limité au web uniquement
- [ ] Pas d'accès admin sur mobile pour des raisons de sécurité
### Connexion multi-rôles
- [ ] Permettre à un utilisateur de choisir son rôle (admin/membre) à la connexion
- [ ] Un admin (fkRole==2) doit pouvoir se connecter en tant qu'utilisateur également
---
<div style="page-break-after: always;"></div>
## MODE SUPER ADMIN
### Gestion des amicales
**Performance**
- [ ] Corriger le ralentissement après 3 suppressions d'amicales consécutives
- [ ] Optimiser le processus de purge des données
**Filtres et visualisation**
- [ ] Ajouter des filtres sur la liste des amicales
- [ ] Implémenter un mode démo pour les présentations
- [ ] Distinguer visuellement les amicales actives (ayant réglé) des autres
### Gestion des opérations
- [ ] Si suppression de l'opération active, réactiver automatiquement l'opération précédente
---
## PROCESSUS D'INSCRIPTION
### Double envoi d'emails
Envoyer 2 emails séparés lors de l'inscription :
- [ ] **Email 1** : Identifiant de connexion
- [ ] **Email 2** : Mot de passe avec informations complémentaires
_Bénéfice : Sécurité renforcée et meilleure traçabilité_
---
<div style="page-break-after: always;"></div>
## MODULE STRIPE
### Paiement en ligne dans les passages
**Fonctionnalité principale**
- [ ] Intégrer la gestion du paiement en ligne directement dans le formulaire de passage
- [ ] Disponible uniquement si l'amicale a un compte Stripe actif
**Caractéristiques**
- [ ] Détection automatique du statut Stripe de l'amicale
- [ ] Option "Paiement par carte" dans les modes de règlement
- [ ] Interface de paiement sécurisée intégrée
- [ ] Génération automatique du reçu après paiement
### Mode hors connexion
- [ ] Étudier les possibilités de paiement Stripe en mode hors ligne
- [ ] Permettre les paiements même sans connexion internet stable
### Tests et développement
**Paiement sans contact (Tap to Pay)**
- [ ] Mettre en place un environnement de test pour le paiement sans contact
- [ ] Documenter la procédure de test pour Tap to Pay
- [ ] Vérifier la compatibilité des appareils de test disponibles
---
## PLANNING PRÉVISIONNEL
### 📅 Sprint 1 : 12-19 septembre 2025
**Priorité 1 - Corrections critiques**
| Date | Version | Tâches |
| ------------------------- | ------- | --------------------------------------------------- |
| Vendredi 12/09 | v3.2.5 | Analyse et priorisation des bugs critiques |
| Lundi 15 - Mardi 16/09 | v3.2.6 | Correction problème F5 et déconnexion |
| Mercredi 17/09 | v3.2.7 | Fix génération mots de passe et champs obligatoires |
| Jeudi 18 - Vendredi 19/09 | v3.2.8 | Correction sauvegarde secteurs + tests |
### 📅 Sprint 2 : 22-26 septembre 2025
**Priorité 2 - Fonctionnalités**
| Date | Version | Tâches |
| ---------------------- | ------- | --------------------------------------------------- |
| Lundi 22 - Mardi 23/09 | v3.2.9 | Liste membres avec statistiques + filtres |
| Mercredi 24/09 | v3.3.0 | Historique avec sélection membre et dates |
| Jeudi 25/09 | v3.3.1 | Carte (zoom max, géolocalisation terrain) |
| Vendredi 26/09 | v3.3.2 | Intégration paiement Stripe dans formulaire passage |
### 📅 Sprint 3 : 29 septembre - 03 octobre 2025
**Finalisation**
| Date | Version | Tâches |
| ------------------ | ---------- | ---------------------------------------- |
| Lundi 29/09 | v3.4.0 | Interface (chat, police, ergonomie) |
| Mardi 30/09 | v3.4.1 | Mode Super Admin (filtres, performances) |
| Mercredi 01/10 | v3.4.2 | Tests d'intégration complets |
| Jeudi 02/10 | v3.4.3 | Recette client et corrections finales |
| **Vendredi 03/10** | **v3.4.4** | **LIVRAISON FINALE** |
### 📅 08 octobre 2025 : CONGRÈS
- Version de production déployée et stable
- Formation utilisateurs effectuée
- Documentation finalisée
---
<div style="page-break-after: always;"></div>
## POINT FINANCIER
### COÛT TOTAL HT Hors maintenance : 36.000 euros HT
### Factures Réglées
| Date | Réglée | Montant Applicatif |
| ------------------------------------- | ------ | ------------------ |
| 08/04 | Oui | 4.200 € HT |
| 26/05 | Oui | 3.880 € HT |
| 30/06 | Oui | 3.880 € HT |
| 26/08 | Oui | 3.880 € HT |
| | | Total 15.840 € HT |
| ------------------------------------- |
### Prochaines Factures
| Date | Réglée | Montant Applicatif |
| ------------------------------------- | ------ | ------------------ |
| 12/09 | Non | 3.360 € HT |
| 10/10 | Non | 3.360 € HT |
| 08/11 | Non | 3.360 € HT |
| 06/12 | Non | 3.360 € HT |
| 04/01 | Non | 3.360 € HT |
| 02/02 | Non | 3.360 € HT |
| ------------------------------------- |
---
<div style="page-break-after: always;"></div>
## UPGRADES PACKAGES FLUTTER
### 📊 État des packages (Octobre 2025)
L'analyse `flutter pub outdated` a révélé plusieurs packages nécessitant des mises à jour, dont un package discontinué critique.
### 🔴 Phase 1 - Correction package discontinué (URGENT)
**Statut : ✅ TERMINÉ (06/10/2025)**
| Package | Action | Ancienne version | Nouvelle version |
|---------|--------|------------------|------------------|
| `dio_cache_interceptor_hive_store` | ❌ Suppression (discontinué) | 3.2.2 | - |
| `http_cache_hive_store` | ✅ Ajout (remplacement) | - | 5.0.0 |
| `flutter_map_cache` | ⬆️ Mise à jour | 1.5.2 | 2.0.0+1 |
**Fichiers modifiés :**
- `pubspec.yaml` : Remplacement des dépendances
- `lib/presentation/widgets/mapbox_map.dart` : Import mis à jour
**Tests requis :**
- [x] Affichage carte web
- [x] Affichage carte mobile
- [x] Cache des tuiles mobile
- [x] Mode terrain
### 🟡 Phase 2 - Mises à jour importantes (PLANIFIÉ)
**Statut : ⏳ EN ATTENTE**
#### Cartes et géolocalisation
| Package | Actuelle | Cible | Breaking Changes |
|---------|----------|-------|------------------|
| `flutter_map` | 6.2.1 | 8.2.2 | ⚠️ Oui (v7, v8) |
| `geolocator` | 12.0.0 | 14.0.2 | Possible |
#### Device Info & Permissions
| Package | Actuelle | Cible | Importance |
|---------|----------|-------|------------|
| `device_info_plus` | 9.1.2 | 12.1.0 | ⭐⭐⭐ Tap to Pay |
| `battery_plus` | 4.1.0 | 7.0.0 | ⭐⭐ |
| `connectivity_plus` | 5.0.2 | 7.0.0 | ⭐⭐ |
| `sensors_plus` | 3.1.0 | 7.0.0 | ⭐⭐⭐ Mode boussole |
| `permission_handler` | 11.4.0 | 12.0.1 | ⭐⭐⭐ |
**Points d'attention :**
- `flutter_map 8.x` : Breaking changes majeurs v6 → v8
- `device_info_plus` : Vérifier compatibilité DeviceInfoService
- Tests complets requis : cartes, géolocalisation, mode terrain
### 🟢 Phase 3 - Mises à jour secondaires (PLANIFIÉ)
**Statut : ⏳ EN ATTENTE**
| Package | Actuelle | Cible | Note |
|---------|----------|-------|------|
| `syncfusion_flutter_charts` | 30.2.7 | 31.1.22 | Mineure |
| `package_info_plus` | 4.2.0 | 8.3.1 | Vérifier compatibilité |
**Packages à jour :**
-`dio: 5.9.0`
-`go_router: 16.2.4`
-`hive: 2.2.3`
-`flutter_stripe: 12.0.2`
-`mek_stripe_terminal: 4.6.0`
### 📅 Planning des upgrades
| Phase | Période prévue | Priorité | Effort |
|-------|----------------|----------|--------|
| Phase 1 | ✅ 06/10/2025 | 🔴 Critique | 1h |
| Phase 2 | 10-15/10/2025 | 🟡 Important | 4-6h |
| Phase 3 | 20-25/10/2025 | 🟢 Mineur | 2-3h |
---
_Document généré le 11 septembre 2025_
_Dernière mise à jour le 06 octobre 2025_
_Ce document sera mis à jour régulièrement avec l'avancement des développements_
---
**GEOSECTOR** - Solution de gestion des distributions de calendriers Amicales de pompiers
© 2025 - Tous droits réservés

Binary file not shown.

View File

@@ -0,0 +1,578 @@
# TODO - Isolation complète des opérations
## 🎯 Objectif
Mettre en place une **isolation complète par opération** où chaque opération est totalement autonome et peut être supprimée indépendamment sans impacter les autres opérations ou la table centrale `users`.
## 📊 Architecture cible
```
operations (id: 850)
├── ope_users (id: 2500, fk_operation: 850, fk_user: 100)
│ ├── ope_users_sectors (fk_user: 2500 ← ope_users.id, fk_sector: 5400)
│ └── ope_pass (fk_user: 2500 ← ope_users.id, fk_sector: 5400)
└── ope_sectors (id: 5400, fk_operation: 850)
users (id: 100) ← table centrale (conservée même si opération supprimée)
```
---
## ✅ Tâche 1 : Modification du schéma SQL
### 📁 Fichier : `scripts/orga/fix_fk_constraints.sql`
### Actions
- [ ] **1.1** Tester le script SQL sur **dva_geo** (DEV)
```bash
incus exec dva-geo -- mysql rca_geo < /var/www/geosector/api/scripts/orga/fix_fk_constraints.sql
```
- [ ] **1.2** Vérifier les contraintes après exécution :
```sql
SELECT TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = 'rca_geo'
AND TABLE_NAME IN ('ope_users_sectors', 'ope_pass')
AND COLUMN_NAME = 'fk_user';
```
Résultat attendu :
- `ope_users_sectors.fk_user → ope_users.id`
- `ope_pass.fk_user → ope_users.id`
- [ ] **1.3** Appliquer sur **rca_geo** (RECETTE) après validation sur dva_geo
- [ ] **1.4** Appliquer sur **pra_geo** (PRODUCTION) après validation sur rca_geo
### ⚠️ Important
- Les données existantes doivent être **nettoyées avant** d'appliquer le script
- Ou bien : recréer toutes les données avec la nouvelle migration
- Les FK `ON DELETE CASCADE` supprimeront automatiquement `ope_users_sectors` et `ope_pass` quand `ope_users` est supprimé
---
## ✅ Tâche 2 : Correction du script de migration2
### 📁 Fichiers concernés
1. `scripts/migration2/php/lib/SectorMigrator.php`
2. `scripts/migration2/php/lib/PassageMigrator.php`
### Actions
#### 2.1 SectorMigrator.php - Migration de ope_users_sectors
- [ ] **Ligne 253** : Changer de `users.id` vers `ope_users.id`
```php
// ❌ AVANT
':fk_user' => $us['fk_user'], // ID de users (table centrale)
// ✅ APRÈS
':fk_user' => $userMapping[$us['fk_user']], // ID de ope_users (mapping)
```
#### 2.2 PassageMigrator.php - Migration de ope_pass
- [ ] **Ligne 64-67** : Vérifier le mapping existe
- [ ] **Ligne 77** : Passer `ope_users.id` au lieu de `users.id`
```php
// ❌ AVANT (ligne 77)
$newPassId = $this->insertPassage($passage, $newOperationId, $newOpeSectorId, $passage['fk_user']);
// ✅ APRÈS
$newOpeUserId = $userMapping[$passage['fk_user']];
$newPassId = $this->insertPassage($passage, $newOperationId, $newOpeSectorId, $newOpeUserId);
```
- [ ] **Ligne 164** : Utiliser le paramètre `$userId` qui sera maintenant `ope_users.id`
```php
// ❌ AVANT
':fk_user' => $userId, // ID de users (table centrale)
// ✅ APRÈS (le paramètre $userId contiendra déjà ope_users.id)
':fk_user' => $userId, // ID de ope_users
```
- [ ] **Ligne 71** : Corriger `verifyUserSectorAssociation` pour vérifier avec `ope_users.id`
```php
// ❌ AVANT
if (!$this->verifyUserSectorAssociation($newOperationId, $passage['fk_user'], $newOpeSectorId)) {
// ✅ APRÈS
if (!$this->verifyUserSectorAssociation($newOperationId, $newOpeUserId, $newOpeSectorId)) {
```
#### 2.3 Tester la migration complète
- [ ] **Sur dva_geo** : Vider les données d'une entité et relancer la migration
```bash
php php/migrate_from_backup.php --mode=entity --entity-id=5
```
- [ ] **Vérifier** dans la base que :
- `ope_users_sectors.fk_user` contient des IDs de `ope_users.id`
- `ope_pass.fk_user` contient des IDs de `ope_users.id`
- Les valeurs correspondent bien au mapping
- [ ] **Vérifier** qu'on peut supprimer une opération et que tout part avec (CASCADE)
```sql
DELETE FROM operations WHERE id = 850;
-- Doit supprimer automatiquement :
-- - ope_users (ON DELETE CASCADE depuis operations)
-- - ope_users_sectors (ON DELETE CASCADE depuis ope_users)
-- - ope_pass (ON DELETE CASCADE depuis ope_users)
-- - ope_sectors (ON DELETE CASCADE depuis operations)
```
---
## ✅ Tâche 3 : Vérifications API
### Impact sur les endpoints API
#### 3.1 Vérifier les requêtes utilisant `ope_pass.fk_user`
- [ ] **Rechercher** tous les endpoints qui lisent `ope_pass.fk_user`
```bash
grep -r "ope_pass.*fk_user" src/Controllers/
grep -r "fk_user.*ope_pass" src/Controllers/
```
- [ ] **Vérifier** que ces endpoints :
- Font-ils des JOIN avec `users` via `ope_pass.fk_user` ?
- Si OUI : Ajouter un JOIN via `ope_users` :
```sql
-- ❌ AVANT
SELECT op.*, u.encrypted_name
FROM ope_pass op
JOIN users u ON op.fk_user = u.id
-- ✅ APRÈS
SELECT op.*, u.encrypted_name
FROM ope_pass op
JOIN ope_users ou ON op.fk_user = ou.id
JOIN users u ON ou.fk_user = u.id
```
#### 3.2 Vérifier les requêtes utilisant `ope_users_sectors.fk_user`
- [ ] **Rechercher** tous les endpoints qui lisent `ope_users_sectors.fk_user`
```bash
grep -r "ope_users_sectors.*fk_user" src/Controllers/
```
- [ ] **Vérifier** la même chose : si JOIN avec `users`, ajouter passage par `ope_users`
#### 3.3 Endpoints probablement concernés
À vérifier :
- [ ] `OperationController` - Liste des utilisateurs d'une opération
- [ ] `PassageController` - Liste/détails des passages
- [ ] `SectorController` - Liste des secteurs avec utilisateurs affectés
- [ ] Tout endpoint retournant des statistiques par utilisateur
---
## ✅ Tâche 4 : Corrections API - Response JSON Login
### Impact sur la réponse JSON du login
#### 4.1 Groupe `users_sectors` - Ajouter `ope_user_id`
**Problème identifié** : Flutter reçoit `users_sectors` avec `id` (users.id) mais les `passages` ont `fk_user` (ope_users.id). Le mapping est impossible.
**Solution** : Modifier la requête dans `LoginController.php` (lignes 426 et 1181) pour retourner les deux IDs :
```sql
-- ✅ APRÈS
SELECT DISTINCT
u.id as user_id, -- users.id (table centrale, pour gestion membres)
ou.id as ope_user_id, -- ope_users.id (pour lier avec passages/sectors)
ou.first_name,
u.encrypted_name,
u.sect_name,
us.fk_sector
FROM users u
JOIN ope_users ou ON u.id = ou.fk_user
JOIN ope_users_sectors us ON ou.id = us.fk_user AND ou.fk_operation = us.fk_operation
WHERE us.fk_sector IN ($sectorIdsString)
AND us.fk_operation = ?
AND us.chk_active = 1
AND u.chk_active = 1
AND u.id != ?
```
**Résultat JSON attendu** :
```json
{
"user_id": 123, // users.id (pour gestion des membres dans l'interface)
"ope_user_id": 50, // ope_users.id (pour lier avec passages.fk_user et sectors)
"first_name": "Jane",
"name": "Jane Smith",
"sect_name": "Smith",
"fk_sector": 456
}
```
**Usage Flutter** :
```dart
// Trouver les passages d'un utilisateur
passages.where((p) => p.fkUser == usersSectors[i].opeUserId) // ✅ OK
```
- [ ] **Modifier** `LoginController.php` ligne 426 (méthode `login()`)
- [ ] **Modifier** `LoginController.php` ligne 1181 (méthode `checkSession()`)
- [ ] **Tester** la réponse JSON du login en mode admin
---
## ✅ Tâche 5 : Vérifications Flutter - Gestion des IDs
### Impact sur l'application mobile
#### 5.1 Modèles de données
- [x] **Vérifier** le modèle `UserSector` (ou équivalent)
- Ajouter le champ `opeUserId` (int) pour stocker `ope_users.id`
- Conserver `userId` (int) pour stocker `users.id`
- ✅ **Fait** : `UserSectorModel` modifié avec les champs `userId` et `opeUserId`
- ✅ **Fait** : Adaptateurs Hive régénérés avec `build_runner`
- [x] **Vérifier** le modèle `Passage` (ou équivalent)
- Le champ `fkUser` pointe maintenant vers `ope_users.id`
- ✅ **Fait** : `PassageModel.fkUser` pointe déjà vers `ope_users.id`
- [x] **Vérifier** le modèle `User`
- Ajouter le champ `opeUserId` (int?) pour stocker l'ID de l'utilisateur dans `ope_users`
- ✅ **Fait** : `UserModel` modifié avec `opeUserId` (@HiveField(20))
- ✅ **Fait** : `CurrentUserService` expose `opeUserId` via getter
#### 5.2 Gestion des secteurs (Mode Admin)
- [x] **Création de secteur**
- L'API crée dans `ope_sectors`
- Attribution des users : utiliser `ope_user_id` (pas `user_id`)
- Endpoint : `POST /api/sectors`
- Body : `{ ..., users: [50, 51, 52] }` ← IDs de `ope_users`
- ✅ **Fait** : `SectorDialog` utilise `userSector.opeUserId` pour l'attribution
- ✅ **Fait** : Liste dédupliquée des membres depuis `UserSectorModel`
- [x] **Modification de secteur**
- Attribution des users : utiliser `ope_user_id`
- Endpoint : `PUT /api/sectors/:id`
- Body : `{ ..., users: [50, 51, 52] }` ← IDs de `ope_users`
- ✅ **Fait** : `SectorDialog` utilise `userSector.opeUserId` pour l'attribution
- [ ] **Suppression de secteur**
- L'API supprime dans `ope_pass`, `ope_users_sectors` et `ope_sectors`
- CASCADE gère automatiquement les dépendances
- Endpoint : `DELETE /api/sectors/:id`
#### 5.3 Gestion des membres (Mode Admin)
- [ ] **Création de membre**
- L'API crée dans `users` (table centrale)
- L'API crée aussi dans `ope_users` pour l'opération active
- **Réponse attendue** :
```json
{
"status": "success",
"user": {
"id": 123, // users.id
"ope_user_id": 50, // ope_users.id (nouveau)
"first_name": "John",
"name": "John Doe",
...
}
}
```
- Endpoint : `POST /api/users`
- Flutter stocke les 2 IDs : `userId` et `opeUserId`
- [ ] **Modification de membre**
- L'API met à jour `users` (table centrale)
- L'API met à jour aussi `ope_users` pour l'opération active
- Endpoint : `PUT /api/users/:id`
- [ ] **Suppression de membre**
- L'API supprime de `ope_users` (opération active)
- L'API supprime de `users` (table centrale)
- CASCADE supprime automatiquement `ope_users_sectors` et `ope_pass`
- Endpoint : `DELETE /api/users/:id?transfer_to=XX`
#### 5.4 Gestion des passages (Mode Admin & User)
- [x] **Création de passage**
- Attribution automatique du `ope_sectors.id` le plus proche
- Attribution du `ope_users.id` (utilisateur connecté ou sélectionné)
- Endpoint : `POST /api/passages`
- Body : `{ ..., fk_user: 50, fk_sector: 456 }` ← IDs de `ope_users` et `ope_sectors`
- ✅ **Fait** : `PassageRepository.createPassage()` utilise `CurrentUserService.instance.opeUserId`
- [x] **Modification de passage**
- Attribution du `ope_users.id` si changement d'utilisateur
- Endpoint : `PUT /api/passages/:id`
- Body : `{ ..., fk_user: 50 }` ← ID de `ope_users`
- ✅ **Fait** : `PassageRepository.updatePassage()` utilise `CurrentUserService.instance.opeUserId`
- ✅ **Fait** : Mode offline et online correctement implémentés
- [ ] **Suppression de passage**
- L'API supprime dans `ope_pass`
- Endpoint : `DELETE /api/passages/:id`
#### 5.5 Interface Flutter - Mapping des IDs
**Scénarios à gérer** :
1. **Affichage des secteurs avec utilisateurs affectés** :
```dart
// Utiliser usersSectors[i].opeUserId pour lier avec passages
final userPassages = passages.where((p) =>
p.fkUser == usersSectors[i].opeUserId &&
p.fkSector == sector.id
).toList();
```
- ✅ **Fait** : `ActivityChart` filtre par secteurs assignés (pas par userId)
- ✅ **Fait** : `MapPage` utilise `userSector.opeUserId` pour filtrer les secteurs
2. **Attribution d'un passage à un utilisateur** :
```dart
// Envoyer ope_user_id dans la requête API
await apiService.createPassage({
...passageData,
'fk_user': userSector.opeUserId, // ope_users.id
'fk_sector': sector.id
});
```
- ✅ **Fait** : `PassageRepository` utilise `CurrentUserService.instance.opeUserId`
3. **Affichage du nom d'un utilisateur depuis un passage** :
```dart
// Chercher dans usersSectors avec ope_user_id
final userSector = usersSectors.firstWhere(
(us) => us.opeUserId == passage.fkUser,
orElse: () => null
);
final userName = userSector?.name ?? 'Inconnu';
```
- ✅ **Fait** : `PaymentSummaryCard` utilise `opeUserId` pour filtrer les règlements
- ✅ **Fait** : `HistoryPage` utilise `opeUserId` pour filtrer et vérifier les permissions
- ✅ **Fait** : `UserFieldModePage` compare `passage.fkUser` avec `opeUserId`
4. **Gestion des membres** :
```dart
// Conserver les 2 IDs lors de la création
final newMember = await apiService.createUser(userData);
membres.add(Member(
userId: newMember['id'], // users.id
opeUserId: newMember['ope_user_id'], // ope_users.id
...
));
```
- ⚠️ **À tester** : Vérifier la réception de `ope_user_id` dans les réponses API
5. **Statistiques par utilisateur** :
- ✅ **Fait** : `PassageRepository.getStatisticsByUser()` utilise `passage.fkUser` (ope_users.id)
- ✅ **Fait** : Variable renommée `opeUserId` pour clarté
6. **Services et chargement de données** :
- ✅ **Fait** : `DataLoadingService` utilise `opeUserId` pour les clés Hive des secteurs
- ✅ **Fait** : `CurrentUserService.opeUserId` accessible globalement
#### 5.6 Tests d'affichage
- [ ] Tester l'affichage des passages avec noms d'utilisateurs
- [ ] Tester l'affichage des secteurs avec utilisateurs affectés
- [ ] Tester la création d'un membre (vérifier que les 2 IDs sont reçus)
- [ ] Tester la suppression d'un membre (vérifier le transfert de passages)
- [ ] Tester la création d'un secteur avec attribution d'utilisateurs
- [ ] Tester la création d'un passage avec attribution d'utilisateur
- [ ] Tester la suppression d'une opération (doit tout nettoyer)
---
### 📝 Modifications Flutter effectuées (2025-01-23)
#### Fichiers modifiés
1. **`lib/core/data/models/user_sector_model.dart`** (lignes 11-50)
- Ajout du champ `opeUserId` (@HiveField(5))
- Renommage du champ `id` → `userId` (@HiveField(0))
- Mise à jour de `fromJson()` pour parser les deux IDs
- Mise à jour de `toJson()` et `copyWith()`
2. **`lib/core/data/models/user_model.dart`** (ligne 122)
- Ajout du champ `opeUserId` (@HiveField(20))
- Mise à jour de `fromJson()`, `toJson()` et `copyWith()`
3. **`lib/core/services/current_user_service.dart`** (ligne 24)
- Ajout du getter `opeUserId` pour accès global
4. **`lib/core/services/data_loading_service.dart`** (ligne 451)
- Utilisation de `userSector.opeUserId` pour les clés Hive
5. **`lib/presentation/dialogs/sector_dialog.dart`** (lignes 86, 538-542, 999-1007)
- Changement de source : `MembreModel` → `UserSectorModel`
- Utilisation de `opeUserId` pour la sélection des membres
- Déduplication des membres (un user peut être sur plusieurs secteurs)
6. **`lib/presentation/pages/history_page.dart`** (lignes 62-63, 126, 997-1009, 1023, 1608, 1629)
- Ajout de `currentOpeUserId` (ligne 62)
- Utilisation de `UserSectorModel` avec déduplication
- Comparaison `passage.fkUser == currentOpeUserId` pour filtrage et permissions
7. **`lib/presentation/user/user_field_mode_page.dart`** (ligne 999-1002)
- Correction : `passage.fkUser == userRepository.getCurrentUser()?.opeUserId`
8. **`lib/presentation/widgets/charts/payment_summary_card.dart`** (ligne 425, 428-430)
- Utilisation de `currentUser?.opeUserId` pour filtrer les règlements utilisateur
9. **`lib/core/repositories/passage_repository.dart`** (lignes 105, 384-388, 422-426, 577)
- Renommage du paramètre : `getPassagesByUser(int opeUserId)`
- Utilisation de `CurrentUserService.instance.opeUserId` pour création/modification
- Renommage de variable : `userId` → `opeUserId` dans les statistiques
10. **`lib/presentation/pages/map_page.dart`** (lignes 792-795)
- **ERREUR CRITIQUE CORRIGÉE** : `us.id` → `us.opeUserId`
- Utilisation de `CurrentUserService.instance.opeUserId`
11. **`lib/presentation/pages/home_page.dart`** (lignes 22-32)
- Suppression de variable inutilisée : `currentUserId`
#### Adaptateurs générés
- **`lib/core/data/models/user_sector_model.g.dart`** - Régénéré avec `build_runner`
- **`lib/core/data/models/user_model.g.dart`** - Régénéré avec `build_runner`
#### Widgets vérifiés (pas de modification nécessaire)
- `PassageSummaryCard` - Affiche tous les passages déjà filtrés par l'API
- `ActivityChart` - Filtre par secteurs assignés, pas par userId
- `SectorDistributionCard` - Affiche tous les secteurs sans filtrage utilisateur
- `MembersBoardPassages` - `membre.id` représente déjà `ope_users.id`
#### Analyse statique
```bash
flutter analyze
```
- ✅ **0 erreur de compilation**
- 33 avertissements de style (info uniquement)
---
## 📋 Ordre d'exécution recommandé
1. ✅ **Corriger le code de migration2** (PHP)
2. ✅ **Tester sur dva_geo** avec schéma modifié
3. ✅ **Vérifier l'API** sur dva_geo
4. ✅ **Vérifier Flutter** avec dva_geo
5. 🚀 **Déployer le schéma SQL** sur rca_geo
6. 🚀 **Déployer le code** sur rca_geo
7. ✅ **Tester en recette**
8. 🚀 **Déployer en production** (pra_geo)
---
## 🔍 Requêtes SQL utiles pour vérification
### Vérifier les contraintes FK actuelles
```sql
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND (TABLE_NAME = 'ope_pass' OR TABLE_NAME = 'ope_users_sectors')
AND COLUMN_NAME = 'fk_user';
```
### Vérifier l'intégrité des données après migration
```sql
-- Vérifier que tous les fk_user de ope_pass existent dans ope_users
SELECT COUNT(*) as orphans
FROM ope_pass op
LEFT JOIN ope_users ou ON op.fk_user = ou.id
WHERE ou.id IS NULL;
-- Résultat attendu : 0
-- Vérifier que tous les fk_user de ope_users_sectors existent dans ope_users
SELECT COUNT(*) as orphans
FROM ope_users_sectors ous
LEFT JOIN ope_users ou ON ous.fk_user = ou.id
WHERE ou.id IS NULL;
-- Résultat attendu : 0
```
### Tester la suppression en cascade
```sql
-- Compter avant suppression
SELECT
(SELECT COUNT(*) FROM ope_users WHERE fk_operation = 850) as ope_users_count,
(SELECT COUNT(*) FROM ope_users_sectors WHERE fk_operation = 850) as ope_users_sectors_count,
(SELECT COUNT(*) FROM ope_pass WHERE fk_operation = 850) as ope_pass_count,
(SELECT COUNT(*) FROM ope_sectors WHERE fk_operation = 850) as ope_sectors_count;
-- Supprimer l'opération
DELETE FROM operations WHERE id = 850;
-- Vérifier que tout a été supprimé (doit retourner 0 partout)
SELECT
(SELECT COUNT(*) FROM ope_users WHERE fk_operation = 850) as ope_users_count,
(SELECT COUNT(*) FROM ope_users_sectors WHERE fk_operation = 850) as ope_users_sectors_count,
(SELECT COUNT(*) FROM ope_pass WHERE fk_operation = 850) as ope_pass_count,
(SELECT COUNT(*) FROM ope_sectors WHERE fk_operation = 850) as ope_sectors_count;
```
---
## 📝 Notes importantes
### Avantages de cette architecture
✅ **Isolation complète** : Supprimer une opération supprime tout (ope_users, secteurs, passages)
✅ **Performance** : Pas de jointures complexes avec la table centrale `users`
✅ **Historique** : Les données d'une opération sont figées dans le temps
✅ **Simplicité** : Requêtes plus simples, moins de risques d'incohérences
### Implications
⚠️ **Duplication** : Un utilisateur travaillant sur 3 opérations aura 3 entrées dans `ope_users`
⚠️ **Taille** : La table `ope_users` sera plus volumineuse
⚠️ **Jointures** : Pour remonter aux infos de la table `users`, il faut passer par `ope_users.fk_user`
### Rétrocompatibilité
❌ Ce changement **CASSE** la compatibilité avec les données existantes
✅ Nécessite une **re-migration complète** de toutes les entités après modification du schéma
✅ Ou bien : script de transformation des données existantes (plus complexe)
---
## 🎯 Statut
- [ ] Schéma SQL modifié sur dva_geo
- [ ] Code migration2 corrigé
- [ ] API vérifiée et corrigée
- [x] **Flutter vérifié et corrigé** ✅ (2025-01-23)
- Modèles de données mis à jour (UserSectorModel, UserModel)
- Services mis à jour (CurrentUserService, DataLoadingService)
- Repositories mis à jour (PassageRepository)
- Pages et widgets mis à jour (11 fichiers)
- Adaptateurs Hive régénérés
- Analyse statique : 0 erreur
- [ ] Tests complets sur dva_geo (en attente API)
- [ ] Déploiement rca_geo
- [ ] Déploiement pra_geo

View File

@@ -0,0 +1,395 @@
# TODO - Cache Web pour tuiles Mapbox
## Contexte
**Problème** : En PROD, les admins travaillent intensivement sur la plateforme web et la carte. Actuellement, les tuiles Mapbox ne sont pas mises en cache sur le web, ce qui provoque :
- Téléchargements répétés des mêmes tuiles
- Consommation excessive de bande passante
- Navigation peu fluide
- Coûts API Mapbox potentiellement élevés
**Cause** : Mapbox envoie des headers `Cache-Control: no-cache` qui empêchent le cache navigateur par défaut, et `flutter_map_cache` ne supporte pas la plateforme web.
**Solution** : Implémenter un cache manuel des tuiles via IndexedDB en Dart, uniquement pour le web.
## Architecture technique
### Flux de données
```
flutter_map demande une tuile
CachedWebTileProvider (nouveau)
WebTileCacheService.getTile()
Vérifie IndexedDB
┌─────────────┴─────────────┐
│ │
Cache HIT Cache MISS
│ │
Retourne image Télécharge depuis Mapbox
depuis IndexedDB ↓
Stocke dans IndexedDB
Retourne image
```
### Composants
1. **WebTileCacheService** (Singleton)
- Gère IndexedDB pour stocker les tuiles
- Méthodes : `getTile()`, `storeTile()`, `clearCache()`, `clearExpiredTiles()`
- Durée de cache : 30 jours (aligné avec mobile/desktop)
2. **CachedWebTileProvider** (Custom TileProvider)
- Implémente `TileProvider` de `flutter_map`
- Utilise `WebTileCacheService` pour récupérer/stocker
- Fallback sur téléchargement direct si erreur
3. **MapboxMap** (Modifié)
- Utilise `CachedWebTileProvider` sur web
- Garde `HiveCacheStore` sur mobile/desktop
## Fichiers à créer/modifier
### ✅ Fichiers à créer
#### 1. `lib/core/services/web_tile_cache_service.dart`
Service singleton pour gérer le cache IndexedDB des tuiles Mapbox.
**Responsabilités** :
- Initialiser la base IndexedDB `mapbox_tiles_cache`
- Stocker les tuiles avec clé unique (URL de la tuile)
- Récupérer les tuiles depuis le cache
- Gérer l'expiration (30 jours)
- Nettoyer les tuiles expirées
**Structure IndexedDB** :
```
Database: mapbox_tiles_cache
ObjectStore: tiles
- key: String (URL de la tuile)
- value: Object {
data: Uint8List (bytes de l'image)
timestamp: int (millisecondsSinceEpoch)
}
```
**API publique** :
```dart
class WebTileCacheService {
static final instance = WebTileCacheService._();
Future<void> initialize();
Future<Uint8List?> getTile(String url);
Future<void> storeTile(String url, Uint8List data);
Future<void> clearCache();
Future<void> clearExpiredTiles();
}
```
**Dépendances** :
- `dart:indexed_db` (natif web)
- `dart:typed_data`
- `package:flutter/foundation.dart` (kIsWeb)
#### 2. `lib/presentation/widgets/cached_web_tile_provider.dart`
TileProvider custom qui utilise le cache IndexedDB.
**Responsabilités** :
- Implémenter `TileProvider` de `flutter_map`
- Vérifier le cache avant téléchargement
- Télécharger et stocker si absent du cache
- Fallback sur comportement par défaut si erreur
**API publique** :
```dart
class CachedWebTileProvider extends TileProvider {
final String accessToken;
final String styleId;
CachedWebTileProvider({
required this.accessToken,
required this.styleId,
});
@override
ImageProvider getImage(TileCoordinates coordinates, TileLayer options);
}
```
**Logique** :
1. Construire l'URL de la tuile
2. Appeler `WebTileCacheService.getTile(url)`
3. Si trouvée → `MemoryImage(cachedData)`
4. Sinon → Télécharger → Stocker → `MemoryImage(downloadedData)`
**Dépendances** :
- `flutter_map`
- `WebTileCacheService`
- `dart:typed_data`
- `package:http/http.dart` (ou `Dio` si préféré)
### ✅ Fichiers à modifier
#### 3. `lib/presentation/widgets/mapbox_map.dart`
Modifier pour utiliser le nouveau provider sur web.
**Modifications** :
- Lignes 96-139 : Refactoriser `_initializeCache()`
- Utiliser `CachedWebTileProvider` quand `kIsWeb == true`
- Garder `HiveCacheStore` pour mobile/desktop
- Initialiser `WebTileCacheService` au démarrage sur web
**Avant** (lignes 98-103) :
```dart
if (kIsWeb) {
// Pas de cache sur Web (non supporté)
setState(() {
_cacheInitialized = true;
});
return;
}
```
**Après** :
```dart
if (kIsWeb) {
// Cache manuel via IndexedDB
await WebTileCacheService.instance.initialize();
setState(() {
_cacheInitialized = true;
});
return;
}
```
**TileLayer config** (ligne ~180) :
```dart
TileLayer(
urlTemplate: 'https://api.mapbox.com/styles/v1/mapbox/$styleId/tiles/256/{z}/{x}/{y}@2x?access_token=$accessToken',
tileProvider: kIsWeb
? CachedWebTileProvider(
accessToken: accessToken,
styleId: styleId,
)
: (_cacheStore != null
? CachedTileProvider(store: _cacheStore!)
: NetworkTileProvider()),
// ...
),
```
## Étapes d'implémentation
### Phase 1 : Service de cache IndexedDB
**Tâche 1.1** : Créer `web_tile_cache_service.dart`
- [ ] Créer la classe singleton
- [ ] Implémenter `initialize()` avec création de la DB IndexedDB
- [ ] Implémenter `getTile(url)` avec vérification d'expiration
- [ ] Implémenter `storeTile(url, data)` avec timestamp
- [ ] Implémenter `clearCache()` pour vider toute la DB
- [ ] Implémenter `clearExpiredTiles()` pour le nettoyage automatique
- [ ] Ajouter des logs de debug (`debugPrint`)
**Tâche 1.2** : Gestion des erreurs
- [ ] Try/catch sur toutes les opérations IndexedDB
- [ ] Fallback gracieux si IndexedDB indisponible
- [ ] Logs d'erreur explicites
**Tâche 1.3** : Tests unitaires
- [ ] Tester `initialize()` crée bien la DB
- [ ] Tester `storeTile()` + `getTile()` roundtrip
- [ ] Tester expiration (mock timestamp)
- [ ] Tester `clearCache()`
### Phase 2 : TileProvider custom
**Tâche 2.1** : Créer `cached_web_tile_provider.dart`
- [ ] Créer la classe qui extend `TileProvider`
- [ ] Implémenter `getImage()` avec logique de cache
- [ ] Gérer le téléchargement des tuiles manquantes
- [ ] Stocker les tuiles téléchargées dans le cache
- [ ] Ajouter des logs de performance (cache hit/miss)
**Tâche 2.2** : Gestion des erreurs réseau
- [ ] Try/catch sur téléchargement
- [ ] Retry logic (3 tentatives max)
- [ ] Placeholder si échec total
- [ ] Logs d'erreur explicites
**Tâche 2.3** : Tests
- [ ] Tester avec tuile en cache → Pas de requête réseau
- [ ] Tester avec tuile absente → Téléchargement + stockage
- [ ] Tester avec erreur réseau → Fallback gracieux
### Phase 3 : Intégration dans MapboxMap
**Tâche 3.1** : Modifier `mapbox_map.dart`
- [ ] Importer `CachedWebTileProvider` et `WebTileCacheService`
- [ ] Modifier `_initializeCache()` pour initialiser le service web
- [ ] Modifier `TileLayer` pour utiliser le bon provider selon la plateforme
- [ ] Tester sur web que le nouveau provider est bien utilisé
**Tâche 3.2** : Validation visuelle
- [ ] Lancer l'app en mode web DEV
- [ ] Ouvrir DevTools → Console pour voir les logs
- [ ] Naviguer sur la carte → Vérifier logs "Cache MISS" au premier passage
- [ ] Revenir sur la même zone → Vérifier logs "Cache HIT"
- [ ] Vérifier dans DevTools → Application → IndexedDB que les tuiles sont stockées
**Tâche 3.3** : Tests de performance
- [ ] Mesurer le temps de chargement initial (sans cache)
- [ ] Mesurer le temps de chargement avec cache
- [ ] Vérifier qu'il n'y a plus de requêtes réseau pour les tuiles en cache
- [ ] Tester sur une session longue (plusieurs déplacements sur la carte)
### Phase 4 : Nettoyage et documentation
**Tâche 4.1** : Nettoyage automatique
- [ ] Appeler `clearExpiredTiles()` au démarrage de l'app (dans `initialize()`)
- [ ] Ajouter un bouton admin pour vider manuellement le cache (optionnel)
**Tâche 4.2** : Logs et monitoring
- [ ] Ajouter des statistiques de cache (hit rate, taille totale)
- [ ] Logger les performances (temps de chargement moyen)
**Tâche 4.3** : Documentation
- [ ] Commenter le code (dartdoc)
- [ ] Mettre à jour `FLOW-*.md` si nécessaire
- [ ] Ajouter section dans README technique
## Tests de validation
### Tests fonctionnels
1. **Cache vide → Premier chargement**
- [ ] Ouvrir l'app web en mode incognito
- [ ] Naviguer sur la carte
- [ ] Vérifier que les tuiles se chargent
- [ ] Vérifier les logs "Cache MISS" + "Storing tile"
2. **Cache rempli → Rechargement**
- [ ] Recharger la page (F5)
- [ ] Revenir sur la même zone de carte
- [ ] Vérifier que les tuiles se chargent instantanément
- [ ] Vérifier les logs "Cache HIT"
- [ ] Vérifier dans Network tab : pas de requêtes Mapbox pour les tuiles en cache
3. **Navigation étendue**
- [ ] Se déplacer sur plusieurs zones de la carte
- [ ] Revenir sur les zones précédentes
- [ ] Vérifier mix de "Cache HIT" et "Cache MISS"
4. **Gestion de l'expiration**
- [ ] Modifier temporairement l'expiration à 10 secondes (pour test)
- [ ] Charger des tuiles
- [ ] Attendre 15 secondes
- [ ] Recharger → Vérifier que les tuiles sont re-téléchargées
5. **Gestion d'erreur réseau**
- [ ] Désactiver le réseau en plein chargement
- [ ] Vérifier que les tuiles en cache s'affichent quand même
- [ ] Vérifier que les tuiles manquantes ne bloquent pas l'app
### Tests de performance
6. **Mesure de bande passante**
- [ ] Vider le cache
- [ ] Naviguer sur une zone avec ~100 tuiles visibles
- [ ] Noter la bande passante consommée (DevTools Network)
- [ ] Recharger la page et revenir sur la même zone
- [ ] Vérifier que la bande passante est ~0 KB
7. **Mesure de vitesse**
- [ ] Mesurer le temps de chargement initial : ____ ms
- [ ] Mesurer le temps de chargement avec cache : ____ ms
- [ ] Objectif : >50% de réduction
### Tests multi-plateformes
8. **Mobile/Desktop non régressé**
- [ ] Lancer sur Android → Vérifier que HiveCacheStore fonctionne toujours
- [ ] Lancer sur iOS → Vérifier que HiveCacheStore fonctionne toujours
- [ ] Vérifier les logs "Cache initialized with HiveCacheStore"
9. **Web multi-navigateurs**
- [ ] Tester sur Chrome
- [ ] Tester sur Firefox
- [ ] Tester sur Safari (si IndexedDB supporté)
- [ ] Tester sur Edge
## Checklist de validation finale
- [ ] Aucune nouvelle dépendance ajoutée au `pubspec.yaml`
- [ ] Code compatible web uniquement (guards `kIsWeb`)
- [ ] Mobile/Desktop non impactés (toujours HiveCacheStore)
- [ ] Logs de debug présents et clairs
- [ ] Gestion d'erreur complète (try/catch)
- [ ] Expiration automatique (30 jours)
- [ ] Performance mesurée et améliorée
- [ ] Tests manuels passés
- [ ] Code documenté (dartdoc)
- [ ] Pas de régression sur les autres plateformes
## Notes techniques
### Pourquoi IndexedDB et pas localStorage ?
- **localStorage** : Limite de 5-10 MB → Insuffisant pour des tuiles (1 tuile = ~60 KB)
- **IndexedDB** : Limite de ~50% de l'espace disque disponible → Largement suffisant
### Structure de la clé de cache
Format recommandé : `{styleId}_{z}_{x}_{y}@{scale}x`
Exemple : `streets-v11_15_16234_11378@2x`
Cela permet :
- Identification unique de chaque tuile
- Support multi-styles (streets, satellite, etc.)
- Support multi-résolutions (@1x, @2x)
### Taille estimée du cache
- 1 tuile Mapbox @2x : ~60 KB
- Carte complète niveau zoom 15 : ~500 tuiles
- Total pour une zone : ~30 MB
- IndexedDB peut stocker plusieurs GB → Pas de souci
### Maintenance du cache
Le nettoyage automatique (`clearExpiredTiles()`) s'exécute :
- Au démarrage de l'app
- Évite l'accumulation de vieilles tuiles
- Garde le cache sous contrôle
## Dépendances
### Packages Flutter (déjà présents)
- `flutter_map: ^7.0.2` → Fournit `TileProvider`
- `flutter_map_cache: ^1.5.1` → Pour mobile/desktop uniquement
### Bibliothèques Dart natives (aucun ajout)
- `dart:indexed_db` → Pour IndexedDB (web seulement)
- `dart:typed_data` → Pour manipuler les bytes
- `package:flutter/foundation.dart` → Pour `kIsWeb`
### Pas de nouvelle dépendance externe ✅
## Estimation
- **Temps de développement** : 2-3 heures
- **Complexité** : Moyenne
- **Risque** : Faible (fallback sur comportement actuel)
- **Gain** : Important pour les admins PROD
## Prochaine étape
**Attente de validation utilisateur** pour démarrer l'implémentation.

View File

@@ -1,602 +0,0 @@
-- -------------------------------------------------------------
-- TablePlus 6.4.8(608)
--
-- https://tableplus.com/
--
-- Database: geo_app
-- Generation Time: 2025-06-09 18:03:43.5140
-- -------------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE TABLE `chat_anonymous_users` (
`id` varchar(50) NOT NULL,
`device_id` varchar(100) NOT NULL,
`name` varchar(100) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`converted_to_user_id` int(10) unsigned DEFAULT NULL,
`metadata` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`metadata`)),
PRIMARY KEY (`id`),
KEY `idx_device_id` (`device_id`),
KEY `idx_converted_user` (`converted_to_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `chat_attachments` (
`id` varchar(50) NOT NULL,
`fk_message` varchar(50) NOT NULL,
`file_name` varchar(255) NOT NULL,
`file_path` varchar(500) NOT NULL,
`file_type` varchar(100) NOT NULL,
`file_size` int(10) unsigned NOT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `idx_message` (`fk_message`),
CONSTRAINT `fk_chat_attachments_message` FOREIGN KEY (`fk_message`) REFERENCES `chat_messages` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `chat_audience_targets` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_room` varchar(50) NOT NULL,
`target_type` enum('role','entity','all','combined') NOT NULL DEFAULT 'all',
`target_id` varchar(50) DEFAULT NULL,
`role_filter` varchar(20) DEFAULT NULL,
`entity_filter` varchar(50) DEFAULT NULL,
`date_creation` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `idx_room` (`fk_room`),
KEY `idx_type` (`target_type`),
CONSTRAINT `fk_chat_audience_targets_room` FOREIGN KEY (`fk_room`) REFERENCES `chat_rooms` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `chat_broadcast_lists` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_room` varchar(50) NOT NULL,
`name` varchar(100) NOT NULL,
`description` text DEFAULT NULL,
`fk_user_creator` int(10) unsigned NOT NULL,
`date_creation` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `idx_room` (`fk_room`),
KEY `idx_user_creator` (`fk_user_creator`),
CONSTRAINT `fk_chat_broadcast_lists_room` FOREIGN KEY (`fk_room`) REFERENCES `chat_rooms` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `chat_messages` (
`id` varchar(50) NOT NULL,
`fk_room` varchar(50) NOT NULL,
`fk_user` int(10) unsigned DEFAULT NULL,
`sender_type` enum('user','anonymous','system') NOT NULL DEFAULT 'user',
`content` text DEFAULT NULL,
`content_type` enum('text','image','file') NOT NULL DEFAULT 'text',
`date_sent` timestamp NOT NULL DEFAULT current_timestamp(),
`date_delivered` timestamp NULL DEFAULT NULL,
`date_read` timestamp NULL DEFAULT NULL,
`statut` enum('envoye','livre','lu','error') NOT NULL DEFAULT 'envoye',
`is_announcement` tinyint(1) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_room` (`fk_room`),
KEY `idx_user` (`fk_user`),
KEY `idx_date` (`date_sent`),
KEY `idx_status` (`statut`),
KEY `idx_messages_unread` (`fk_room`,`statut`),
CONSTRAINT `fk_chat_messages_room` FOREIGN KEY (`fk_room`) REFERENCES `chat_rooms` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `chat_notifications` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`fk_user` int(10) unsigned NOT NULL,
`fk_message` varchar(50) DEFAULT NULL,
`fk_room` varchar(50) DEFAULT NULL,
`type` varchar(50) NOT NULL,
`contenu` text DEFAULT NULL,
`date_creation` timestamp NOT NULL DEFAULT current_timestamp(),
`date_lecture` timestamp NULL DEFAULT NULL,
`statut` enum('non_lue','lue') NOT NULL DEFAULT 'non_lue',
PRIMARY KEY (`id`),
KEY `idx_user` (`fk_user`),
KEY `idx_message` (`fk_message`),
KEY `idx_room` (`fk_room`),
KEY `idx_statut` (`statut`),
KEY `idx_notifications_unread` (`fk_user`,`statut`),
CONSTRAINT `fk_chat_notifications_message` FOREIGN KEY (`fk_message`) REFERENCES `chat_messages` (`id`) ON DELETE SET NULL,
CONSTRAINT `fk_chat_notifications_room` FOREIGN KEY (`fk_room`) REFERENCES `chat_rooms` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `chat_offline_queue` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`operation_type` varchar(50) NOT NULL,
`operation_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`operation_data`)),
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`processed_at` timestamp NULL DEFAULT NULL,
`status` enum('pending','processing','completed','failed') NOT NULL DEFAULT 'pending',
`error_message` text DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_status` (`status`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `chat_participants` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id_room` varchar(50) NOT NULL,
`id_user` int(10) unsigned DEFAULT NULL,
`anonymous_id` varchar(50) DEFAULT NULL,
`role` enum('administrateur','participant','en_lecture_seule') NOT NULL DEFAULT 'participant',
`date_ajout` timestamp NOT NULL DEFAULT current_timestamp(),
`notification_activee` tinyint(1) unsigned NOT NULL DEFAULT 1,
`last_read_message_id` varchar(50) DEFAULT NULL,
`via_target` tinyint(1) unsigned NOT NULL DEFAULT 0,
`can_reply` tinyint(1) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uc_room_user` (`id_room`,`id_user`),
KEY `idx_room` (`id_room`),
KEY `idx_user` (`id_user`),
KEY `idx_anonymous_id` (`anonymous_id`),
KEY `idx_participants_active` (`id_room`,`id_user`,`notification_activee`),
CONSTRAINT `fk_chat_participants_room` FOREIGN KEY (`id_room`) REFERENCES `chat_rooms` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `chat_read_messages` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`fk_message` varchar(50) NOT NULL,
`fk_user` int(10) unsigned NOT NULL,
`date_read` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
UNIQUE KEY `uc_message_user` (`fk_message`,`fk_user`),
KEY `idx_message` (`fk_message`),
KEY `idx_user` (`fk_user`),
CONSTRAINT `fk_chat_read_messages_message` FOREIGN KEY (`fk_message`) REFERENCES `chat_messages` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `chat_rooms` (
`id` varchar(50) NOT NULL,
`type` enum('privee','groupe','liste_diffusion','broadcast','announcement') NOT NULL,
`title` varchar(100) DEFAULT NULL,
`date_creation` timestamp NOT NULL DEFAULT current_timestamp(),
`fk_user` int(10) unsigned NOT NULL,
`fk_entite` int(10) unsigned DEFAULT NULL,
`statut` enum('active','archive') NOT NULL DEFAULT 'active',
`description` text DEFAULT NULL,
`reply_permission` enum('all','admins_only','sender_only','none') NOT NULL DEFAULT 'all',
`is_pinned` tinyint(1) unsigned NOT NULL DEFAULT 0,
`expiry_date` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp(),
PRIMARY KEY (`id`),
KEY `idx_user` (`fk_user`),
KEY `idx_entite` (`fk_entite`),
KEY `idx_type` (`type`),
KEY `idx_statut` (`statut`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `email_counter` (
`id` int(10) unsigned NOT NULL DEFAULT 1,
`hour_start` timestamp NULL DEFAULT NULL,
`count` int(10) unsigned DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `email_queue` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_pass` int(10) unsigned NOT NULL DEFAULT 0,
`to_email` varchar(255) DEFAULT NULL,
`subject` varchar(255) DEFAULT NULL,
`body` text DEFAULT NULL,
`headers` text DEFAULT NULL,
`created_at` timestamp NULL DEFAULT current_timestamp(),
`status` enum('pending','sent','failed') DEFAULT 'pending',
`attempts` int(10) unsigned DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `entites` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`encrypted_name` varchar(255) DEFAULT NULL,
`adresse1` varchar(45) DEFAULT '',
`adresse2` varchar(45) DEFAULT '',
`code_postal` varchar(5) DEFAULT '',
`ville` varchar(45) DEFAULT '',
`fk_region` int(10) unsigned DEFAULT NULL,
`fk_type` int(10) unsigned DEFAULT 1,
`encrypted_phone` varchar(128) DEFAULT '',
`encrypted_mobile` varchar(128) DEFAULT '',
`encrypted_email` varchar(255) DEFAULT '',
`gps_lat` varchar(20) NOT NULL DEFAULT '',
`gps_lng` varchar(20) NOT NULL DEFAULT '',
`chk_stripe` tinyint(1) unsigned DEFAULT 0,
`encrypted_stripe_id` varchar(255) DEFAULT '',
`encrypted_iban` varchar(255) DEFAULT '',
`encrypted_bic` varchar(128) DEFAULT '',
`chk_demo` tinyint(1) unsigned DEFAULT 1,
`chk_mdp_manuel` tinyint(1) unsigned NOT NULL DEFAULT 1 COMMENT 'Gestion des mots de passe manuelle O/N',
`chk_copie_mail_recu` tinyint(1) unsigned NOT NULL DEFAULT 0,
`chk_accept_sms` tinyint(1) unsigned NOT NULL DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date de création',
`fk_user_creat` int(10) unsigned DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() COMMENT 'Date de modification',
`fk_user_modif` int(10) unsigned DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`),
KEY `entites_ibfk_1` (`fk_region`),
KEY `entites_ibfk_2` (`fk_type`),
CONSTRAINT `entites_ibfk_1` FOREIGN KEY (`fk_region`) REFERENCES `x_regions` (`id`) ON UPDATE CASCADE,
CONSTRAINT `entites_ibfk_2` FOREIGN KEY (`fk_type`) REFERENCES `x_entites_types` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1230 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `medias` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`support` varchar(45) NOT NULL DEFAULT '' COMMENT 'Type de support (entite, user, operation, passage)',
`support_id` int(10) unsigned NOT NULL DEFAULT 0 COMMENT 'ID de élément associé',
`fichier` varchar(250) NOT NULL DEFAULT '' COMMENT 'Nom du fichier stocké',
`file_type` varchar(50) DEFAULT NULL COMMENT 'Extension du fichier (pdf, jpg, xlsx, etc.)',
`file_category` varchar(50) DEFAULT NULL COMMENT 'export, logo, carte, etc.',
`file_size` int(10) unsigned DEFAULT NULL COMMENT 'Taille du fichier en octets',
`mime_type` varchar(100) DEFAULT NULL COMMENT 'Type MIME du fichier',
`original_name` varchar(255) DEFAULT NULL COMMENT 'Nom original du fichier uploadé',
`fk_entite` int(10) unsigned DEFAULT NULL COMMENT 'ID de entité propriétaire',
`fk_operation` int(10) unsigned DEFAULT NULL COMMENT 'ID de opération (pour passages)',
`file_path` varchar(500) DEFAULT NULL COMMENT 'Chemin complet du fichier',
`original_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur originale de image',
`original_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur originale de image',
`processed_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur après traitement',
`processed_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur après traitement',
`is_processed` tinyint(1) unsigned DEFAULT 0 COMMENT 'Image redimensionnée (1) ou originale (0)',
`description` varchar(100) NOT NULL DEFAULT '' COMMENT 'Description du fichier',
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
`fk_user_creat` int(10) unsigned NOT NULL DEFAULT 0,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp(),
`fk_user_modif` int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `idx_entite` (`fk_entite`),
KEY `idx_operation` (`fk_operation`),
KEY `idx_support_type` (`support`, `support_id`),
KEY `idx_file_type` (`file_type`),
KEY `idx_file_category` (`file_category`),
CONSTRAINT `fk_medias_entite` FOREIGN KEY (`fk_entite`) REFERENCES `entites` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT `fk_medias_operation` FOREIGN KEY (`fk_operation`) REFERENCES `operations` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `ope_pass` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_operation` int(10) unsigned NOT NULL DEFAULT 0,
`fk_sector` int(10) unsigned DEFAULT 0,
`fk_user` int(10) unsigned NOT NULL DEFAULT 0,
`fk_adresse` varchar(25) DEFAULT '' COMMENT 'adresses.cp??.id',
`passed_at` timestamp NULL DEFAULT NULL COMMENT 'Date du passage',
`fk_type` int(10) unsigned DEFAULT 0,
`numero` varchar(10) NOT NULL DEFAULT '',
`rue` varchar(75) NOT NULL DEFAULT '',
`rue_bis` varchar(1) NOT NULL DEFAULT '',
`ville` varchar(75) NOT NULL DEFAULT '',
`fk_habitat` int(10) unsigned DEFAULT 1,
`appt` varchar(5) DEFAULT '',
`niveau` varchar(5) DEFAULT '',
`residence` varchar(75) DEFAULT '',
`gps_lat` varchar(20) NOT NULL DEFAULT '',
`gps_lng` varchar(20) NOT NULL DEFAULT '',
`encrypted_name` varchar(255) NOT NULL DEFAULT '',
`montant` decimal(7,2) NOT NULL DEFAULT 0.00,
`fk_type_reglement` int(10) unsigned DEFAULT 1,
`remarque` text DEFAULT '',
`encrypted_email` varchar(255) DEFAULT '',
`nom_recu` varchar(50) DEFAULT NULL,
`date_recu` timestamp NULL DEFAULT NULL COMMENT 'Date de réception',
`date_creat_recu` timestamp NULL DEFAULT NULL COMMENT 'Date de création du reçu',
`date_sent_recu` timestamp NULL DEFAULT NULL COMMENT 'Date envoi du reçu',
`email_erreur` varchar(30) DEFAULT '',
`chk_email_sent` tinyint(1) unsigned NOT NULL DEFAULT 0,
`encrypted_phone` varchar(128) NOT NULL DEFAULT '',
`is_striped` tinyint(1) unsigned NOT NULL DEFAULT 0,
`docremis` tinyint(1) unsigned DEFAULT 0,
`date_repasser` timestamp NULL DEFAULT NULL COMMENT 'Date prévue pour repasser',
`nb_passages` int(11) DEFAULT 1 COMMENT 'Nb passages pour les a repasser',
`chk_gps_maj` tinyint(1) unsigned DEFAULT 0,
`chk_map_create` tinyint(1) unsigned DEFAULT 0,
`chk_mobile` tinyint(1) unsigned DEFAULT 0,
`chk_synchro` tinyint(1) unsigned DEFAULT 1 COMMENT 'chk synchro entre web et appli',
`chk_api_adresse` tinyint(1) unsigned DEFAULT 0,
`chk_maj_adresse` tinyint(1) unsigned DEFAULT 0,
`anomalie` tinyint(1) unsigned DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date de création',
`fk_user_creat` int(10) unsigned DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() COMMENT 'Date de modification',
`fk_user_modif` int(10) unsigned DEFAULT NULL,
`chk_active` tinyint(1) unsigned NOT NULL DEFAULT 1,
PRIMARY KEY (`id`),
KEY `fk_operation` (`fk_operation`),
KEY `fk_sector` (`fk_sector`),
KEY `fk_user` (`fk_user`),
KEY `fk_type` (`fk_type`),
KEY `fk_type_reglement` (`fk_type_reglement`),
KEY `email` (`encrypted_email`),
CONSTRAINT `ope_pass_ibfk_1` FOREIGN KEY (`fk_operation`) REFERENCES `operations` (`id`) ON UPDATE CASCADE,
CONSTRAINT `ope_pass_ibfk_2` FOREIGN KEY (`fk_sector`) REFERENCES `ope_sectors` (`id`) ON UPDATE CASCADE,
CONSTRAINT `ope_pass_ibfk_3` FOREIGN KEY (`fk_user`) REFERENCES `users` (`id`) ON UPDATE CASCADE,
CONSTRAINT `ope_pass_ibfk_4` FOREIGN KEY (`fk_type_reglement`) REFERENCES `x_types_reglements` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=19499566 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `ope_pass_histo` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_pass` int(10) unsigned NOT NULL DEFAULT 0,
`date_histo` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date historique',
`sujet` varchar(50) DEFAULT NULL,
`remarque` varchar(250) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `ope_pass_histo_fk_pass_IDX` (`fk_pass`) USING BTREE,
KEY `ope_pass_histo_date_histo_IDX` (`date_histo`) USING BTREE,
CONSTRAINT `ope_pass_histo_ibfk_1` FOREIGN KEY (`fk_pass`) REFERENCES `ope_pass` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=6752 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `ope_sectors` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_operation` int(10) unsigned NOT NULL DEFAULT 0,
`fk_old_sector` int(10) unsigned DEFAULT NULL,
`libelle` varchar(75) NOT NULL DEFAULT '',
`sector` text NOT NULL DEFAULT '',
`color` varchar(7) NOT NULL DEFAULT '#4B77BE',
`created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date de création',
`fk_user_creat` int(10) unsigned NOT NULL DEFAULT 0,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() COMMENT 'Date de modification',
`fk_user_modif` int(10) unsigned NOT NULL DEFAULT 0,
`chk_active` tinyint(1) unsigned NOT NULL DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
KEY `fk_operation` (`fk_operation`),
CONSTRAINT `ope_sectors_ibfk_1` FOREIGN KEY (`fk_operation`) REFERENCES `operations` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=27675 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `ope_users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_operation` int(10) unsigned NOT NULL DEFAULT 0,
`fk_user` int(10) unsigned NOT NULL DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date de création',
`fk_user_creat` int(10) unsigned DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() COMMENT 'Date de modification',
`fk_user_modif` int(10) unsigned DEFAULT NULL,
`chk_active` tinyint(1) unsigned NOT NULL DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `ope_users_ibfk_1` (`fk_operation`),
KEY `ope_users_ibfk_2` (`fk_user`),
CONSTRAINT `ope_users_ibfk_1` FOREIGN KEY (`fk_operation`) REFERENCES `operations` (`id`) ON UPDATE CASCADE,
CONSTRAINT `ope_users_ibfk_2` FOREIGN KEY (`fk_user`) REFERENCES `users` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=199006 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `ope_users_sectors` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_operation` int(10) unsigned NOT NULL DEFAULT 0,
`fk_user` int(10) unsigned NOT NULL DEFAULT 0,
`fk_sector` int(10) unsigned NOT NULL DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date de création',
`fk_user_creat` int(10) unsigned NOT NULL DEFAULT 0,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() COMMENT 'Date de modification',
`fk_user_modif` int(10) unsigned DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
KEY `fk_operation` (`fk_operation`),
KEY `fk_user` (`fk_user`),
KEY `fk_sector` (`fk_sector`),
CONSTRAINT `ope_users_sectors_ibfk_1` FOREIGN KEY (`fk_operation`) REFERENCES `operations` (`id`) ON UPDATE CASCADE,
CONSTRAINT `ope_users_sectors_ibfk_2` FOREIGN KEY (`fk_user`) REFERENCES `users` (`id`) ON UPDATE CASCADE,
CONSTRAINT `ope_users_sectors_ibfk_3` FOREIGN KEY (`fk_sector`) REFERENCES `ope_sectors` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=48082 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `operations` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_entite` int(10) unsigned NOT NULL DEFAULT 1,
`libelle` varchar(75) NOT NULL DEFAULT '',
`date_deb` date NOT NULL DEFAULT '0000-00-00',
`date_fin` date NOT NULL DEFAULT '0000-00-00',
`chk_distinct_sectors` tinyint(1) unsigned NOT NULL DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date de création',
`fk_user_creat` int(10) unsigned NOT NULL DEFAULT 0,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() COMMENT 'Date de modification',
`fk_user_modif` int(10) unsigned NOT NULL DEFAULT 0,
`chk_active` tinyint(1) unsigned NOT NULL DEFAULT 1,
PRIMARY KEY (`id`),
KEY `fk_entite` (`fk_entite`),
KEY `date_deb` (`date_deb`),
CONSTRAINT `operations_ibfk_1` FOREIGN KEY (`fk_entite`) REFERENCES `entites` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3121 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `params` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`libelle` varchar(35) NOT NULL DEFAULT '',
`valeur` varchar(255) NOT NULL DEFAULT '',
`aide` varchar(150) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `sectors_adresses` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_adresse` varchar(25) DEFAULT NULL COMMENT 'adresses.cp??.id',
`osm_id` int(10) unsigned NOT NULL DEFAULT 0,
`fk_sector` int(10) unsigned NOT NULL DEFAULT 0,
`osm_name` varchar(50) NOT NULL DEFAULT '',
`numero` varchar(5) NOT NULL DEFAULT '',
`rue_bis` varchar(5) NOT NULL DEFAULT '',
`rue` varchar(60) NOT NULL DEFAULT '',
`cp` varchar(5) NOT NULL DEFAULT '',
`ville` varchar(60) NOT NULL DEFAULT '',
`gps_lat` varchar(20) NOT NULL DEFAULT '',
`gps_lng` varchar(20) NOT NULL DEFAULT '',
`osm_date_creat` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date de création',
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() COMMENT 'Date de modification',
PRIMARY KEY (`id`),
KEY `sectors_adresses_fk_sector_index` (`fk_sector`),
KEY `sectors_adresses_numero_index` (`numero`),
KEY `sectors_adresses_rue_index` (`rue`),
KEY `sectors_adresses_ville_index` (`ville`),
CONSTRAINT `sectors_adresses_ibfk_1` FOREIGN KEY (`fk_sector`) REFERENCES `ope_sectors` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1562946 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_entite` int(10) unsigned DEFAULT 1,
`fk_role` int(10) unsigned DEFAULT 1,
`fk_titre` int(10) unsigned DEFAULT 1,
`encrypted_name` varchar(255) DEFAULT NULL,
`first_name` varchar(45) DEFAULT NULL,
`sect_name` varchar(60) DEFAULT '',
`encrypted_user_name` varchar(128) DEFAULT '',
`user_pass_hash` varchar(60) DEFAULT NULL,
`encrypted_phone` varchar(128) DEFAULT NULL,
`encrypted_mobile` varchar(128) DEFAULT NULL,
`encrypted_email` varchar(255) DEFAULT '',
`chk_alert_email` tinyint(1) unsigned DEFAULT 1,
`chk_suivi` tinyint(1) unsigned DEFAULT 0,
`date_naissance` date DEFAULT NULL,
`date_embauche` date DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT 'Date de création',
`fk_user_creat` int(10) unsigned DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp() COMMENT 'Date de modification',
`fk_user_modif` int(10) unsigned DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`),
KEY `fk_entite` (`fk_entite`),
KEY `username` (`encrypted_user_name`),
KEY `users_ibfk_2` (`fk_role`),
KEY `users_ibfk_3` (`fk_titre`),
CONSTRAINT `users_ibfk_1` FOREIGN KEY (`fk_entite`) REFERENCES `entites` (`id`) ON UPDATE CASCADE,
CONSTRAINT `users_ibfk_2` FOREIGN KEY (`fk_role`) REFERENCES `x_users_roles` (`id`) ON UPDATE CASCADE,
CONSTRAINT `users_ibfk_3` FOREIGN KEY (`fk_titre`) REFERENCES `x_users_titres` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=10027748 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `x_departements` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`code` varchar(3) DEFAULT NULL,
`fk_region` int(10) unsigned DEFAULT 1,
`libelle` varchar(45) DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `x_departements_ibfk_1` (`fk_region`),
CONSTRAINT `x_departements_ibfk_1` FOREIGN KEY (`fk_region`) REFERENCES `x_regions` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=105 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `x_devises` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`code` varchar(3) DEFAULT NULL,
`symbole` varchar(6) DEFAULT NULL,
`libelle` varchar(45) DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `x_entites_types` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`libelle` varchar(45) DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `x_pays` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`code` varchar(3) DEFAULT NULL,
`fk_continent` int(10) unsigned DEFAULT NULL,
`fk_devise` int(10) unsigned DEFAULT 1,
`libelle` varchar(45) DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `x_pays_ibfk_1` (`fk_devise`),
CONSTRAINT `x_pays_ibfk_1` FOREIGN KEY (`fk_devise`) REFERENCES `x_devises` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Table des pays avec leurs codes' `PAGE_COMPRESSED`='ON';
CREATE TABLE `x_regions` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_pays` int(10) unsigned DEFAULT 1,
`libelle` varchar(45) DEFAULT NULL,
`libelle_long` varchar(45) DEFAULT NULL,
`table_osm` varchar(45) DEFAULT NULL,
`departements` varchar(45) DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `x_regions_ibfk_1` (`fk_pays`),
CONSTRAINT `x_regions_ibfk_1` FOREIGN KEY (`fk_pays`) REFERENCES `x_pays` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `x_types_passages` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`libelle` varchar(10) DEFAULT NULL,
`color_button` varchar(15) DEFAULT NULL,
`color_mark` varchar(15) DEFAULT NULL,
`color_table` varchar(15) DEFAULT NULL,
`chk_active` tinyint(1) unsigned NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `x_types_reglements` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`libelle` varchar(45) DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `x_users_roles` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`libelle` varchar(45) DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Les différents rôles des utilisateurs' `PAGE_COMPRESSED`='ON';
CREATE TABLE `x_users_titres` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`libelle` varchar(45) DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Les différents titres des utilisateurs' `PAGE_COMPRESSED`='ON';
CREATE TABLE `x_villes` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`fk_departement` int(10) unsigned DEFAULT 1,
`libelle` varchar(65) DEFAULT NULL,
`code_postal` varchar(5) DEFAULT NULL,
`code_insee` varchar(5) DEFAULT NULL,
`chk_active` tinyint(1) unsigned DEFAULT 1,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `x_villes_ibfk_1` (`fk_departement`),
CONSTRAINT `x_villes_ibfk_1` FOREIGN KEY (`fk_departement`) REFERENCES `x_departements` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=38950 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE TABLE `z_sessions` (
`sid` text NOT NULL,
`fk_user` int(11) NOT NULL,
`role` varchar(10) DEFAULT NULL,
`date_modified` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`ip` varchar(50) NOT NULL,
`browser` varchar(150) NOT NULL,
`data` mediumtext DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `PAGE_COMPRESSED`='ON';
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `chat_conversations_unread` AS select `r`.`id` AS `id`,`r`.`type` AS `type`,`r`.`title` AS `title`,`r`.`date_creation` AS `date_creation`,`r`.`fk_user` AS `fk_user`,`r`.`fk_entite` AS `fk_entite`,`r`.`statut` AS `statut`,`r`.`description` AS `description`,`r`.`reply_permission` AS `reply_permission`,`r`.`is_pinned` AS `is_pinned`,`r`.`expiry_date` AS `expiry_date`,`r`.`updated_at` AS `updated_at`,count(distinct `m`.`id`) AS `total_messages`,count(distinct `rm`.`id`) AS `read_messages`,count(distinct `m`.`id`) - count(distinct `rm`.`id`) AS `unread_messages`,(select `geo_app`.`chat_messages`.`date_sent` from `chat_messages` where `geo_app`.`chat_messages`.`fk_room` = `r`.`id` order by `geo_app`.`chat_messages`.`date_sent` desc limit 1) AS `last_message_date` from ((`chat_rooms` `r` left join `chat_messages` `m` on(`r`.`id` = `m`.`fk_room`)) left join `chat_read_messages` `rm` on(`m`.`id` = `rm`.`fk_message`)) group by `r`.`id`;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

259
app/fastlane.log.ios Normal file
View File

@@ -0,0 +1,259 @@
pierre@MiniPi4 app_346 % fastlane ios build
[✔] 🚀
[14:54:38]: fastlane detected a Gemfile in the current directory
[14:54:38]: However, it seems like you didn't use `bundle exec`
[14:54:38]: To launch fastlane faster, please use
[14:54:38]:
[14:54:38]: $ bundle exec fastlane ios build
[14:54:38]:
[14:54:38]: Get started using a Gemfile for fastlane https://docs.fastlane.tools/getting-started/ios/setup/#use-a-gemfile
[14:54:38]: ------------------------------
[14:54:38]: --- Step: default_platform ---
[14:54:38]: ------------------------------
[14:54:38]: Driving the lane 'ios build' 🚀
[14:54:38]: -----------------------
[14:54:38]: --- 🍎 Build iOS IPA ---
[14:54:38]: -----------------------
[14:54:38]: 📦 [1/6] Vérification du cache local...
[14:54:38]: Cache local configuré: /Users/pierre/dev/geosector/app_346/.pub-cache-local
[14:54:38]: ⚠️ flutter pub get et patchs déjà appliqués sur Debian
[14:54:38]: 🧹 [2/6] Nettoyage des artefacts...
[14:54:38]: ---------------------------------------------------------------------
[14:54:38]: --- Step: cd .. && rm -rf build .dart_tool ios/Pods ios/.symlinks ---
[14:54:38]: ---------------------------------------------------------------------
[14:54:38]: $ cd .. && rm -rf build .dart_tool ios/Pods ios/.symlinks
[14:54:38]: Artefacts nettoyés
[14:54:38]: 📦 [3/6] Installation des CocoaPods...
[14:54:38]: --------------------------------------
[14:54:38]: --- Step: cd ../ios && pod install ---
[14:54:38]: --------------------------------------
[14:54:38]: $ cd ../ios && pod install
[14:54:38]: ▸ /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1421:in 'block in Gem::Specification#activate_dependencies': Could not find 'minitest' (>= 5.1) among 181 total gem(s) (Gem::MissingSpecError)
[14:54:38]: ▸ Checked in 'GEM_PATH=/Users/pierre/.local/share/fastlane/3.4.0:/opt/homebrew/Cellar/fastlane/2.228.0/libexec:/opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec' at: /opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec/specifications/activesupport-7.2.2.1.gemspec, execute `gem env` for more information
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1423:in 'block in Gem::Specification#activate_dependencies'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1423:in 'block in Gem::Specification#activate_dependencies'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:255:in 'block in Gem.find_and_activate_spec_for_exe'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:254:in 'Thread::Mutex#synchronize'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:254:in 'Gem.find_and_activate_spec_for_exe'
[14:54:38]: ▸ from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:334:in 'Gem.activate_bin_path'
[14:54:38]: ▸ from /opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec/bin/pod:25:in '<main>'
+------------------------------+
| Lane Context |
+------------------+-----------+
| DEFAULT_PLATFORM | android |
| PLATFORM_NAME | ios |
| LANE_NAME | ios build |
+------------------+-----------+
[14:54:38]: Called from Fastfile at line 199
[14:54:38]: ```
[14:54:38]: 197: # Étape 3 : Installation des pods
[14:54:38]: 198: UI.message("📦 [3/6] Installation des CocoaPods...")
[14:54:38]: => 199: sh("cd ../ios && pod install")
[14:54:38]: 200: UI.success("CocoaPods installés")
[14:54:38]: 201:
[14:54:38]: ```
[14:54:38]: Exit status of command 'cd ../ios && pod install' was 1 instead of 0.
/opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1421:in 'block in Gem::Specification#activate_dependencies': Could not find 'minitest' (>= 5.1) among 181 total gem(s) (Gem::MissingSpecError)
Checked in 'GEM_PATH=/Users/pierre/.local/share/fastlane/3.4.0:/opt/homebrew/Cellar/fastlane/2.228.0/libexec:/opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec' at: /opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec/specifications/activesupport-7.2.2.1.gemspec, execute `gem env` for more information
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1423:in 'block in Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1423:in 'block in Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:255:in 'block in Gem.find_and_activate_spec_for_exe'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:254:in 'Thread::Mutex#synchronize'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:254:in 'Gem.find_and_activate_spec_for_exe'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:334:in 'Gem.activate_bin_path'
from /opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec/bin/pod:25:in '<main>'
+-----------------------------------------------------------------+
| fastlane summary |
+------+--------------------------------------------+-------------+
| Step | Action | Time (in s) |
+------+--------------------------------------------+-------------+
| 1 | default_platform | 0 |
| 2 | cd .. && rm -rf build .dart_tool ios/Pods | 0 |
| | ios/.symlinks | |
| 💥 | cd ../ios && pod install | 0 |
+------+--------------------------------------------+-------------+
[14:54:38]: fastlane finished with errors
Looking for related GitHub issues on fastlane/fastlane...
/opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane_core/lib/fastlane_core/ui/interface.rb:153:in 'FastlaneCore::Interface#shell_error!': [!] Exit status of command 'cd ../ios && pod install' was 1 instead of 0. (FastlaneCore::Interface::FastlaneShellError)
/opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1421:in 'block in Gem::Specification#activate_dependencies': Could not find 'minitest' (>= 5.1) among 181 total gem(s) (Gem::MissingSpecError)
Checked in 'GEM_PATH=/Users/pierre/.local/share/fastlane/3.4.0:/opt/homebrew/Cellar/fastlane/2.228.0/libexec:/opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec' at: /opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec/specifications/activesupport-7.2.2.1.gemspec, execute `gem env` for more information
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1423:in 'block in Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1423:in 'block in Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:255:in 'block in Gem.find_and_activate_spec_for_exe'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:254:in 'Thread::Mutex#synchronize'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:254:in 'Gem.find_and_activate_spec_for_exe'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:334:in 'Gem.activate_bin_path'
from /opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec/bin/pod:25:in '<main>'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane_core/lib/fastlane_core/ui/ui.rb:17:in 'FastlaneCore::UI.method_missing'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/helper/sh_helper.rb:80:in 'Fastlane::Actions.sh_control_output'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/helper/sh_helper.rb:16:in 'Fastlane::Actions.sh_no_action'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/fast_file.rb:225:in 'block in Fastlane::FastFile.sh'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/actions/actions_helper.rb:69:in 'Fastlane::Actions.execute_action'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/fast_file.rb:224:in 'Fastlane::FastFile.sh'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/fast_file.rb:216:in 'Fastlane::FastFile#sh'
from Fastfile:199:in 'block (2 levels) in Fastlane::FastFile#parsing_binding'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/lane.rb:41:in 'Fastlane::Lane#call'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:49:in 'block in Fastlane::Runner#execute'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:45:in 'Dir.chdir'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:45:in 'Fastlane::Runner#execute'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/lane_manager.rb:46:in 'Fastlane::LaneManager.cruise_lane'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/command_line_handler.rb:34:in 'Fastlane::CommandLineHandler.handle'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:110:in 'block (2 levels) in Fastlane::CommandsGenerator#run'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/command.rb:187:in 'Commander::Command#call'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/command.rb:157:in 'Commander::Command#run'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/runner.rb:444:in 'Commander::Runner#run_active_command'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:124:in 'Commander::Runner#run!'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/delegates.rb:18:in 'Commander::Delegates#run!'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:363:in 'Fastlane::CommandsGenerator#run'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:43:in 'Fastlane::CommandsGenerator.start'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/cli_tools_distributor.rb:123:in 'Fastlane::CLIToolsDistributor.take_off'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/bin/fastlane:23:in '<top (required)>'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/bin/fastlane:25:in 'Kernel#load'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/bin/fastlane:25:in '<main>'
pierre@MiniPi4 ios % pod install
/opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1421:in 'block in Gem::Specification#activate_dependencies': Could not find 'ffi' (>= 1.15.0) among 121 total gem(s) (Gem::MissingSpecError)
Checked in 'GEM_PATH=/Users/pierre/.gem/ruby/3.4.0:/opt/homebrew/lib/ruby/gems/3.4.0:/opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/gems/3.4.0:/opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec' at: /opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec/specifications/ethon-0.16.0.gemspec, execute `gem env` for more information
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1423:in 'block in Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1423:in 'block in Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1423:in 'block in Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Array#each'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1407:in 'Gem::Specification#activate_dependencies'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems/specification.rb:1389:in 'Gem::Specification#activate'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:255:in 'block in Gem.find_and_activate_spec_for_exe'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:254:in 'Thread::Mutex#synchronize'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:254:in 'Gem.find_and_activate_spec_for_exe'
from /opt/homebrew/Cellar/ruby/3.4.7/lib/ruby/3.4.0/rubygems.rb:334:in 'Gem.activate_bin_path'
from /opt/homebrew/Cellar/cocoapods/1.16.2_1/libexec/bin/pod:25:in '<main>'
pierre@MiniPi4 ios % cd ..
pierre@MiniPi4 app_346 % gem install ffi
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/universal-darwin25/rbconfig.rb:21: warning: Insecure world writable dir /Users/pierre in PATH, mode 040777
Fetching ffi-1.17.2-x86_64-darwin.gem
ERROR: While executing gem ... (Gem::FilePermissionError)
You don't have write permissions for the /Library/Ruby/Gems/2.6.0 directory.
pierre@MiniPi4 app_346 %
pierre@MiniPi4 app_346 % /opt/homebrew/opt/ruby/bin/gem install ffi
Fetching ffi-1.17.2-arm64-darwin.gem
Successfully installed ffi-1.17.2-arm64-darwin
1 gem installed
pierre@MiniPi4 app_346 % cd ios
pierre@MiniPi4 ios % pod install
Ignoring ffi-1.17.0 because its extensions are not built. Try: gem pristine ffi --version 1.17.0
Ignoring ffi-1.17.0 because its extensions are not built. Try: gem pristine ffi --version 1.17.0
Ignoring ffi-1.17.0 because its extensions are not built. Try: gem pristine ffi --version 1.17.0
Ignoring ffi-1.17.0 because its extensions are not built. Try: gem pristine ffi --version 1.17.0
[!] Invalid `Podfile` file: cannot load such file -- /opt/flutter/packages/flutter_tools/bin/podhelper.
# from /Users/pierre/dev/geosector/app_346/ios/Podfile:26
# -------------------------------------------
#
> require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
#
# -------------------------------------------
pierre@MiniPi4 ios %
Unable to read contents of XCFileList '/Target Support Files/Pods-Runner/Pods-Runner-frameworks-Release-output-files.xcfilelist'
Unable to read contents of XCFileList '/Target Support Files/Pods-Runner/Pods-Runner-resources-Release-output-files.xcfilelist'
Unable to load contents of file list: '/Target Support Files/Pods-Runner/Pods-Runner-frameworks-Release-input-files.xcfilelist'
Unable to load contents of file list: '/Target Support Files/Pods-Runner/Pods-Runner-frameworks-Release-output-files.xcfilelist'
Run script build phase '[CP] Embed Pods Frameworks' will be run during every build because it does not specify any outputs. To address this issue, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase.
cd /Users/pierre/dev/geosector/app_346
# 1. Trouver Flutter
which flutter
# 2. Nettoyer tout
cd ios
rm -rf Pods Podfile.lock .symlinks/ Flutter/Flutter.framework Flutter/Flutter.podspec
cd ..
# 3. Laisser Flutter tout régénérer
export PUB_CACHE="$PWD/.pub-cache-local"
flutter clean
flutter pub get
# 4. Flutter build va générer les pods correctement
flutter build ios --release --no-codesign
Cette dernière commande va :
- Régénérer tous les fichiers Flutter iOS
- Créer le Podfile correct avec le bon chemin Flutter
- Installer les pods automatiquement
- Compiler le framework Flutter
---
⚡ Si flutter build ios échoue aussi
Vérifiez que Flutter est bien dans le PATH :
echo $PATH | grep -i flutter
which flutter
flutter doctor
Si Flutter n'est pas trouvé, ajoutez-le au PATH :
export PATH="$PATH:/chemin/vers/flutter/bin"
---
Lancez flutter build ios --release --no-codesign et envoyez-moi le résultat !
pierre@MiniPi4 app_346 % flutter build ios --release --no-codesign
Warning: Building for device with codesigning disabled. You will have to manually codesign before deploying to device.
Building fr.geosector.app3 for device (ios-release)...
Running pod install... 2354ms
Running Xcode build...
└─Compiling, linking and signing... 6,4s
Xcode build done. 75,8s
✓ Built build/ios/iphoneos/Runner.app (107.7MB)
pierre@MiniPi4 app_346 %

242
app/fastlane.logios Normal file
View File

@@ -0,0 +1,242 @@
[14:24:34]: Running lane `ios build`. Next time you can do this by directly typing `fastlane ios build` 🚀.
[14:24:34]: Driving the lane 'ios build' 🚀
[14:24:34]: -----------------------
[14:24:34]: --- 🍎 Build iOS IPA ---
[14:24:34]: -----------------------
[14:24:34]: 🧹 [1/8] Nettoyage du projet...
[14:24:34]: ------------------------------------
[14:24:34]: --- Step: cd .. && flutter clean ---
[14:24:34]: ------------------------------------
[14:24:34]: $ cd .. && flutter clean
[14:24:36]: ▸ Cleaning Xcode workspace... 906ms
[14:24:37]: ▸ Cleaning Xcode workspace... 1295ms
[14:24:37]: ▸ Deleting Generated.xcconfig... 0ms
[14:24:37]: ▸ Deleting flutter_export_environment.sh... 0ms
[14:24:37]: ▸ Deleting ephemeral... 0ms
[14:24:37]: ▸ Deleting ephemeral... 0ms
[14:24:37]: ▸ Deleting ephemeral... 0ms
[14:24:37]: ▸ Deleting .flutter-plugins-dependencies... 0ms
[14:24:37]: ▸ Deleting .flutter-plugins... 0ms
[14:24:37]: Projet nettoyé
[14:24:37]: 📦 [2/8] Récupération des dépendances...
[14:24:37]: --------------------------------------
[14:24:37]: --- Step: cd .. && flutter pub get ---
[14:24:37]: --------------------------------------
[14:24:37]: $ cd .. && flutter pub get
[14:24:37]: ▸ Resolving dependencies...
[14:24:40]: ▸ Downloading packages...
[14:24:40]: ▸ _fe_analyzer_shared 67.0.0 (92.0.0 available)
[14:24:40]: ▸ analyzer 6.4.1 (9.0.0 available)
[14:24:40]: ▸ async 2.11.0 (2.13.0 available)
[14:24:40]: ▸ battery_plus 6.0.3 (7.0.0 available)
[14:24:40]: ▸ boolean_selector 2.1.1 (2.1.2 available)
[14:24:40]: ▸ build 2.4.1 (4.0.2 available)
[14:24:40]: ▸ build_config 1.1.1 (1.2.0 available)
[14:24:40]: ▸ build_daemon 4.0.2 (4.1.0 available)
[14:24:40]: ▸ build_resolvers 2.4.2 (3.0.4 available)
[14:24:40]: ▸ build_runner 2.4.13 (2.10.1 available)
[14:24:40]: ▸ build_runner_core 7.3.2 (9.3.2 available)
[14:24:40]: ▸ characters 1.3.0 (1.4.1 available)
[14:24:40]: ▸ checked_yaml 2.0.3 (2.0.4 available)
[14:24:40]: ▸ class_to_string 1.0.0 (1.2.0 available)
[14:24:40]: ▸ clock 1.1.1 (1.1.2 available)
[14:24:40]: ▸ code_builder 4.10.1 (4.11.0 available)
[14:24:40]: ▸ collection 1.18.0 (1.19.1 available)
[14:24:40]: ▸ connectivity_plus 6.0.5 (7.0.0 available)
[14:24:40]: ▸ dart_style 2.3.6 (3.1.2 available)
[14:24:40]: ▸ device_info_plus 11.3.0 (12.2.0 available)
[14:24:40]: ▸ device_info_plus_platform_interface 7.0.2 (7.0.3 available)
[14:24:40]: ▸ dio_cache_interceptor 3.5.1 (4.0.5 available)
[14:24:40]: ▸ dio_cache_interceptor_hive_store 3.2.2 (discontinued replaced by http_cache_hive_store)
[14:24:40]: ▸ fake_async 1.3.1 (1.3.3 available)
[14:24:40]: ▸ ffi 2.1.3 (2.1.4 available)
[14:24:40]: ▸ file_selector_macos 0.9.4+2 (0.9.4+5 available)
[14:24:40]: ▸ flutter_lints 5.0.0 (6.0.0 available)
[14:24:40]: ▸ flutter_local_notifications 19.4.2 (19.5.0 available)
[14:24:40]: ▸ flutter_map 7.0.2 (8.2.2 available)
[14:24:40]: ▸ flutter_map_cache 1.5.1 (2.0.0+1 available)
[14:24:40]: ▸ flutter_plugin_android_lifecycle 2.0.26 (2.0.32 available)
[14:24:40]: ▸ flutter_stripe 11.5.0 (12.0.2 available)
[14:24:40]: ▸ flutter_svg 2.1.0 (2.2.1 available)
[14:24:40]: ▸ freezed_annotation 2.4.4 (3.1.0 available)
[14:24:40]: ▸ geolocator 13.0.4 (14.0.2 available)
[14:24:40]: ▸ geolocator_android 4.6.1 (5.0.2 available)
[14:24:40]: ▸ go_router 15.1.2 (16.3.0 available)
[14:24:40]: ▸ google_fonts 6.3.0 (6.3.2 available)
[14:24:40]: ▸ http_parser 4.0.2 (4.1.2 available)
[14:24:40]: ▸ image_picker 0.8.9 (1.2.0 available)
[14:24:40]: ▸ image_picker_android 0.8.12+21 (0.8.13+5 available)
[14:24:40]: ▸ image_picker_for_web 2.1.12 (3.1.0 available)
[14:24:40]: ▸ image_picker_ios 0.8.12+2 (0.8.13+1 available)
[14:24:40]: ▸ image_picker_linux 0.2.1+2 (0.2.2 available)
[14:24:40]: ▸ image_picker_macos 0.2.1+2 (0.2.2+1 available)
[14:24:40]: ▸ image_picker_platform_interface 2.10.1 (2.11.1 available)
[14:24:40]: ▸ image_picker_windows 0.2.1+1 (0.2.2 available)
[14:24:40]: ▸ intl 0.19.0 (0.20.2 available)
[14:24:40]: ▸ js 0.6.7 (0.7.2 available)
[14:24:40]: ▸ leak_tracker 10.0.5 (11.0.2 available)
[14:24:40]: ▸ leak_tracker_flutter_testing 3.0.5 (3.0.10 available)
[14:24:40]: ▸ leak_tracker_testing 3.0.1 (3.0.2 available)
[14:24:40]: ▸ lints 5.0.0 (6.0.0 available)
[14:24:40]: ▸ matcher 0.12.16+1 (0.12.17 available)
[14:24:40]: ▸ material_color_utilities 0.11.1 (0.13.0 available)
[14:24:40]: ▸ mek_data_class 1.4.0 (2.1.0 available)
[14:24:40]: ▸ mek_stripe_terminal 4.6.0 (4.6.2 available)
[14:24:40]: ▸ meta 1.15.0 (1.17.0 available)
[14:24:40]: ▸ nfc_manager 3.3.0 (4.1.1 available)
[14:24:40]: ▸ path 1.9.0 (1.9.1 available)
[14:24:40]: ▸ path_provider_android 2.2.15 (2.2.20 available)
[14:24:40]: ▸ path_provider_foundation 2.4.1 (2.4.3 available)
[14:24:40]: ▸ petitparser 6.0.2 (7.0.1 available)
[14:24:40]: ▸ pubspec_parse 1.4.0 (1.5.0 available)
[14:24:40]: ▸ shelf 1.4.1 (1.4.2 available)
[14:24:40]: ▸ shelf_web_socket 2.0.1 (3.0.0 available)
[14:24:40]: ▸ source_gen 1.5.0 (4.0.2 available)
[14:24:40]: ▸ source_helper 1.3.5 (1.3.8 available)
[14:24:40]: ▸ source_span 1.10.0 (1.10.1 available)
[14:24:40]: ▸ stack_trace 1.11.1 (1.12.1 available)
[14:24:40]: ▸ stream_channel 2.1.2 (2.1.4 available)
[14:24:40]: ▸ string_scanner 1.2.0 (1.4.1 available)
[14:24:40]: ▸ stripe_android 11.5.0 (12.0.1 available)
[14:24:40]: ▸ stripe_ios 11.5.0 (12.0.1 available)
[14:24:40]: ▸ stripe_platform_interface 11.5.0 (12.0.0 available)
[14:24:40]: ▸ syncfusion_flutter_charts 27.2.5 (31.2.3 available)
[14:24:40]: ▸ syncfusion_flutter_core 27.2.5 (31.2.3 available)
[14:24:40]: ▸ term_glyph 1.2.1 (1.2.2 available)
[14:24:40]: ▸ test_api 0.7.2 (0.7.7 available)
[14:24:40]: ▸ unicode 0.3.1 (1.1.8 available)
[14:24:40]: ▸ url_launcher 6.3.1 (6.3.2 available)
[14:24:40]: ▸ url_launcher_android 6.3.14 (6.3.24 available)
[14:24:40]: ▸ url_launcher_ios 6.3.3 (6.3.5 available)
[14:24:40]: ▸ url_launcher_macos 3.2.2 (3.2.4 available)
[14:24:40]: ▸ url_launcher_web 2.3.3 (2.4.1 available)
[14:24:40]: ▸ vector_graphics 1.1.18 (1.1.19 available)
[14:24:40]: ▸ vector_graphics_compiler 1.1.16 (1.1.19 available)
[14:24:40]: ▸ vector_math 2.1.4 (2.2.0 available)
[14:24:40]: ▸ vm_service 14.2.5 (15.0.2 available)
[14:24:40]: ▸ win32 5.10.1 (5.15.0 available)
[14:24:40]: ▸ win32_registry 1.1.5 (2.1.0 available)
[14:24:40]: ▸ xml 6.5.0 (6.6.1 available)
[14:24:40]: ▸ Got dependencies!
[14:24:40]: ▸ 1 package is discontinued.
[14:24:40]: ▸ 92 packages have newer versions incompatible with dependency constraints.
[14:24:40]: ▸ Try `flutter pub outdated` for more information.
[14:24:40]: Dépendances récupérées
[14:24:40]: 🔧 [3/8] Application des patchs iOS...
[14:24:40]: -----------------------------------------------------------------
[14:24:40]: --- Step: cd .. && ./fastlane/scripts/ios/fix-ios-packages.sh ---
[14:24:40]: -----------------------------------------------------------------
[14:24:40]: $ cd .. && ./fastlane/scripts/ios/fix-ios-packages.sh
[14:24:41]: ▸ 🚀 Fix iOS Packages - Correction automatique des packages problématiques
[14:24:41]: ▸ =========================================================================
[14:24:41]: ▸ 📦 [1/2] Correction de nfc_manager...
[14:24:41]: ▸ [INFO] ==========================================
[14:24:41]: ▸ [INFO] nfc_manager 3.3.0 - Android Patch
[14:24:41]: ▸ [INFO] ==========================================
[14:24:41]: ▸ [INFO] Fichiers trouvés:
[14:24:41]: ▸ [INFO] - AndroidManifest.xml: /Users/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/android/src/main/AndroidManifest.xml
[14:24:41]: ▸ [INFO] - build.gradle: /Users/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/android/build.gradle
[14:24:41]: ▸ [INFO] - Translator.kt: /Users/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/android/src/main/kotlin/io/flutter/plugins/nfcmanager/Translator.kt
[14:24:41]: ▸ [STEP] Étape 1/2 : Patch AndroidManifest.xml
[14:24:41]: ▸ [WARNING] Attribut 'package' détecté dans AndroidManifest.xml
[14:24:41]: ▸ sed: 1: "/Users/pierre/.pub-cach ...": extra characters at the end of p command
+------------------------------+
| Lane Context |
+------------------+-----------+
| DEFAULT_PLATFORM | android |
| PLATFORM_NAME | ios |
| LANE_NAME | ios build |
+------------------+-----------+
[14:24:41]: Called from Fastfile at line 189
[14:24:41]: ```
[14:24:41]: 187: # Étape 3 : Patch des packages iOS
[14:24:41]: 188: UI.message("🔧 [3/8] Application des patchs iOS...")
[14:24:41]: => 189: sh("cd .. && ./fastlane/scripts/ios/fix-ios-packages.sh")
[14:24:41]: 190: UI.success("Patchs iOS appliqués")
[14:24:41]: 191:
[14:24:41]: ```
[14:24:41]: Exit status of command 'cd .. && ./fastlane/scripts/ios/fix-ios-packages.sh' was 1 instead of 0.
🚀 Fix iOS Packages - Correction automatique des packages problématiques
=========================================================================
📦 [1/2] Correction de nfc_manager...
[INFO] ==========================================
[INFO] nfc_manager 3.3.0 - Android Patch
[INFO] ==========================================
[INFO] Fichiers trouvés:
[INFO] - AndroidManifest.xml: /Users/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/android/src/main/AndroidManifest.xml
[INFO] - build.gradle: /Users/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/android/build.gradle
[INFO] - Translator.kt: /Users/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/android/src/main/kotlin/io/flutter/plugins/nfcmanager/Translator.kt
[STEP] Étape 1/2 : Patch AndroidManifest.xml
[WARNING] Attribut 'package' détecté dans AndroidManifest.xml
sed: 1: "/Users/pierre/.pub-cach ...": extra characters at the end of p command
+-----------------------------------------------------------------+
| fastlane summary |
+------+--------------------------------------------+-------------+
| Step | Action | Time (in s) |
+------+--------------------------------------------+-------------+
| 1 | default_platform | 0 |
| 2 | cd .. && flutter clean | 2 |
| 3 | cd .. && flutter pub get | 2 |
| 💥 | cd .. && | 0 |
| | ./fastlane/scripts/ios/fix-ios-packages.s | |
| | h | |
+------+--------------------------------------------+-------------+
[14:24:41]: fastlane finished with errors
Looking for related GitHub issues on fastlane/fastlane...
/opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane_core/lib/fastlane_core/ui/interface.rb:153:in 'FastlaneCore::Interface#shell_error!': [!] Exit status of command 'cd .. && ./fastlane/scripts/ios/fix-ios-packages.sh' was 1 instead of 0. (FastlaneCore::Interface::FastlaneShellError)
🚀 Fix iOS Packages - Correction automatique des packages problématiques
=========================================================================
📦 [1/2] Correction de nfc_manager...
[INFO] ==========================================
[INFO] nfc_manager 3.3.0 - Android Patch
[INFO] ==========================================
[INFO] Fichiers trouvés:
[INFO] - AndroidManifest.xml: /Users/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/android/src/main/AndroidManifest.xml
[INFO] - build.gradle: /Users/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/android/build.gradle
[INFO] - Translator.kt: /Users/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/android/src/main/kotlin/io/flutter/plugins/nfcmanager/Translator.kt
[STEP] Étape 1/2 : Patch AndroidManifest.xml
[WARNING] Attribut 'package' détecté dans AndroidManifest.xml
sed: 1: "/Users/pierre/.pub-cach ...": extra characters at the end of p command
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane_core/lib/fastlane_core/ui/ui.rb:17:in 'FastlaneCore::UI.method_missing'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/helper/sh_helper.rb:80:in 'Fastlane::Actions.sh_control_output'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/helper/sh_helper.rb:16:in 'Fastlane::Actions.sh_no_action'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/fast_file.rb:225:in 'block in Fastlane::FastFile.sh'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/actions/actions_helper.rb:69:in 'Fastlane::Actions.execute_action'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/fast_file.rb:224:in 'Fastlane::FastFile.sh'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/fast_file.rb:216:in 'Fastlane::FastFile#sh'
from Fastfile:189:in 'block (2 levels) in Fastlane::FastFile#parsing_binding'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/lane.rb:41:in 'Fastlane::Lane#call'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:49:in 'block in Fastlane::Runner#execute'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:45:in 'Dir.chdir'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/runner.rb:45:in 'Fastlane::Runner#execute'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/lane_manager.rb:46:in 'Fastlane::LaneManager.cruise_lane'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/command_line_handler.rb:34:in 'Fastlane::CommandLineHandler.handle'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:110:in 'block (2 levels) in Fastlane::CommandsGenerator#run'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/command.rb:187:in 'Commander::Command#call'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/command.rb:157:in 'Commander::Command#run'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/runner.rb:444:in 'Commander::Runner#run_active_command'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:124:in 'Commander::Runner#run!'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/commander-4.6.0/lib/commander/delegates.rb:18:in 'Commander::Delegates#run!'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:363:in 'Fastlane::CommandsGenerator#run'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/commands_generator.rb:43:in 'Fastlane::CommandsGenerator.start'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/fastlane/lib/fastlane/cli_tools_distributor.rb:123:in 'Fastlane::CLIToolsDistributor.take_off'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/gems/fastlane-2.228.0/bin/fastlane:23:in '<top (required)>'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/bin/fastlane:25:in 'Kernel#load'
from /opt/homebrew/Cellar/fastlane/2.228.0/libexec/bin/fastlane:25:in '<main>'
pierre@MiniPi4 app_346 %

6
app/fastlane/Appfile Normal file
View File

@@ -0,0 +1,6 @@
app_identifier("fr.geosector.app3") # Bundle ID
apple_id("contact@d6soft.com") # Votre Apple ID
team_id("6WT84NWCTC")
# Pour Android
package_name("fr.geosector.app3")

381
app/fastlane/Fastfile Normal file
View File

@@ -0,0 +1,381 @@
# Fastfile pour GEOSECTOR Flutter App
# Version: 2.0
# Date: 2025-10-26
# Auteur: Pierre (avec l'aide de Claude)
#
# Usage depuis le Mac mini (après transfert depuis Debian):
# cd /Users/pierre/dev/geosector/app_346
# fastlane android build # Build seulement (test local)
# fastlane android release # Build + Upload vers Play Store
# fastlane ios build # Build iOS seulement (test local)
# fastlane ios release # Build + Upload vers TestFlight
default_platform(:android)
# =============================================================================
# ANDROID
# =============================================================================
platform :android do
desc "Build Android AAB (bundle) en mode release - sans upload"
lane :build do
UI.header("🤖 Build Android Bundle")
# Étape 1 : Nettoyer le projet
UI.message("🧹 [1/6] Nettoyage du projet...")
sh("cd .. && flutter clean")
UI.success("Projet nettoyé")
# Étape 2 : Récupérer les dépendances
UI.message("📦 [2/6] Récupération des dépendances...")
sh("cd .. && flutter pub get")
UI.success("Dépendances récupérées")
# Étape 3 : Patch nfc_manager
UI.message("🔧 [3/6] Application du patch nfc_manager...")
sh("cd .. && ./fastlane/scripts/commun/fix-nfc-manager.sh")
UI.success("Patch nfc_manager appliqué")
# Étape 4 : Analyser le code (non bloquant)
UI.message("🔍 [4/6] Analyse du code...")
begin
sh("cd .. && flutter analyze --no-fatal-infos --no-fatal-warnings")
UI.success("Analyse du code terminée")
rescue => ex
UI.important("⚠️ Des warnings détectés, mais on continue...")
end
# Étape 5 : Build du bundle AAB
UI.message("🏗️ [5/6] Build du bundle Android (RELEASE)...")
sh("cd .. && flutter build appbundle --release")
UI.success("Bundle AAB généré")
# Étape 6 : Copier le bundle avec version
UI.message("📋 [6/6] Copie du bundle avec version...")
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
version_code = version_info.split('+').last
final_name = "geosector-#{version_code}.aab"
sh("cd .. && cp build/app/outputs/bundle/release/app-release.aab #{final_name}")
bundle_size = sh("cd .. && du -h #{final_name} | cut -f1").strip
UI.success("✅ Build Android terminé avec succès!")
UI.success("📦 Bundle: #{final_name}")
UI.success("📊 Taille: #{bundle_size}")
end
desc "Build Android AAB + Upload vers Google Play Console (Internal Testing)"
lane :release do
UI.header("🚀 Build & Deploy Android vers Play Store")
# Étape 1 : Nettoyer le projet
UI.message("🧹 [1/7] Nettoyage du projet...")
sh("cd .. && flutter clean")
UI.success("Projet nettoyé")
# Étape 2 : Récupérer les dépendances
UI.message("📦 [2/7] Récupération des dépendances...")
sh("cd .. && flutter pub get")
UI.success("Dépendances récupérées")
# Étape 3 : Patch nfc_manager
UI.message("🔧 [3/7] Application du patch nfc_manager...")
sh("cd .. && ./fastlane/scripts/commun/fix-nfc-manager.sh")
UI.success("Patch nfc_manager appliqué")
# Étape 4 : Analyser le code (non bloquant)
UI.message("🔍 [4/7] Analyse du code...")
begin
sh("cd .. && flutter analyze --no-fatal-infos --no-fatal-warnings")
UI.success("Analyse du code terminée")
rescue => ex
UI.important("⚠️ Des warnings détectés, mais on continue...")
end
# Étape 5 : Build du bundle AAB
UI.message("🏗️ [5/7] Build du bundle Android (RELEASE)...")
sh("cd .. && flutter build appbundle --release")
UI.success("Bundle AAB généré")
# Étape 6 : Récupérer les informations de version
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
version_name = version_info.split('+').first
version_code = version_info.split('+').last
UI.message("📋 Version: #{version_name} (#{version_code})")
# Étape 7 : Upload vers Google Play Console
UI.message("📤 [6/7] Upload vers Google Play Console...")
upload_to_play_store(
json_key: '../android/google-play-api-key.json', # Credentials Google Play API
track: 'internal', # Track: internal, alpha, beta, ou production
aab: '../build/app/outputs/bundle/release/app-release.aab',
skip_upload_apk: true, # On n'upload que l'AAB
skip_upload_metadata: true, # On ne met pas à jour les métadonnées
skip_upload_images: true, # On ne met pas à jour les images
skip_upload_screenshots: true, # On ne met pas à jour les screenshots
release_status: 'completed', # completed = publié immédiatement sur le track
version_code: version_code.to_i, # Version code explicite
package_name: 'fr.geosector.app3' # Package name explicite
)
UI.success("✅ Déploiement Android terminé avec succès!")
UI.success("📦 Version: #{version_name} (Build #{version_code})")
UI.success("🎯 Track: Internal Testing")
UI.success("🌐 URL: https://play.google.com/console")
end
desc "Upload un AAB existant vers Google Play Console"
lane :upload do
UI.header("📤 Upload AAB vers Play Store")
# Vérifier que le bundle existe
aab_path = '../build/app/outputs/bundle/release/app-release.aab'
if File.exist?(aab_path)
# Récupérer la version
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
version_code = version_info.split('+').last
UI.message("📦 Upload du bundle existant...")
upload_to_play_store(
json_key: '../android/google-play-api-key.json',
track: 'internal',
aab: aab_path,
skip_upload_apk: true,
skip_upload_metadata: true,
skip_upload_images: true,
skip_upload_screenshots: true,
release_status: 'completed',
version_code: version_code.to_i,
package_name: 'fr.geosector.app3'
)
UI.success("✅ Upload terminé!")
else
UI.user_error!("❌ Bundle introuvable: #{aab_path}")
UI.message("💡 Lancez d'abord: fastlane android build")
end
end
end
# =============================================================================
# iOS
# =============================================================================
platform :ios do
desc "Build iOS IPA en mode release - sans upload"
lane :build do
UI.header("🍎 Build iOS IPA")
# Étape 1 : Vérifier le cache local (préparé sur Debian)
UI.message("📦 [1/6] Vérification du cache local...")
cache_path = File.expand_path("../.pub-cache-local")
if !Dir.exist?(cache_path)
UI.user_error!("❌ Cache local introuvable: #{cache_path}")
UI.message("💡 Exécutez './deploy-app.sh' sur Debian pour préparer le projet")
end
ENV['PUB_CACHE'] = cache_path
ENV['GRADLE_USER_HOME'] = File.expand_path("../.gradle-local")
UI.success("Cache local configuré: #{cache_path}")
UI.important("⚠️ flutter pub get et patchs déjà appliqués sur Debian")
# Étape 2 : Nettoyer les artefacts de build
UI.message("🧹 [2/6] Nettoyage des artefacts...")
sh("cd .. && rm -rf build .dart_tool ios/Pods ios/.symlinks")
UI.success("Artefacts nettoyés")
# Étape 3 : Installation des pods
UI.message("📦 [3/6] Installation des CocoaPods...")
sh("cd ../ios && pod install")
UI.success("CocoaPods installés")
# Étape 4 : Analyser le code (non bloquant)
UI.message("🔍 [4/6] Analyse du code...")
begin
sh("cd .. && flutter analyze --no-fatal-infos --no-fatal-warnings")
UI.success("Analyse du code terminée")
rescue => ex
UI.important("⚠️ Des warnings détectés, mais on continue...")
end
# Étape 5 : Build Flutter iOS
UI.message("🏗️ [5/6] Build Flutter iOS (RELEASE)...")
sh("cd .. && flutter build ios --release --no-codesign")
UI.success("Build Flutter iOS généré")
# Étape 6 : Archive Xcode (gym)
UI.message("📦 [6/6] Archive Xcode et export IPA...")
build_ios_app(
workspace: "./Runner.xcworkspace",
scheme: "Runner",
export_method: "app-store",
export_options: {
method: "app-store",
teamID: "6WT84NWCTC",
uploadBitcode: false,
uploadSymbols: true,
compileBitcode: false,
signingStyle: "automatic",
destination: "export",
provisioningProfiles: {
"fr.geosector.app3" => "match AppStore fr.geosector.app3"
}
},
output_directory: "../build/ios/ipa",
output_name: "Runner.ipa",
clean: false,
skip_profile_detection: true
)
UI.success("IPA généré")
# Afficher les informations de version
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
ipa_size = sh("cd .. && du -h build/ios/ipa/Runner.ipa | cut -f1").strip
UI.success("✅ Build iOS terminé avec succès!")
UI.success("📦 IPA: build/ios/ipa/Runner.ipa")
UI.success("📊 Version: #{version_info}")
UI.success("📊 Taille: #{ipa_size}")
end
desc "Build iOS IPA + Upload vers TestFlight"
lane :release do
UI.header("🚀 Build & Deploy iOS vers TestFlight")
# Étape 1 : Vérifier le cache local (préparé sur Debian)
UI.message("📦 [1/7] Vérification du cache local...")
cache_path = File.expand_path("../.pub-cache-local")
if !Dir.exist?(cache_path)
UI.user_error!("❌ Cache local introuvable: #{cache_path}")
UI.message("💡 Exécutez './deploy-app.sh' sur Debian pour préparer le projet")
end
ENV['PUB_CACHE'] = cache_path
ENV['GRADLE_USER_HOME'] = File.expand_path("../.gradle-local")
UI.success("Cache local configuré: #{cache_path}")
UI.important("⚠️ flutter pub get et patchs déjà appliqués sur Debian")
# Étape 2 : Nettoyer les artefacts de build
UI.message("🧹 [2/7] Nettoyage des artefacts...")
sh("cd .. && rm -rf build .dart_tool ios/Pods ios/.symlinks")
UI.success("Artefacts nettoyés")
# Étape 3 : Installation des pods
UI.message("📦 [3/7] Installation des CocoaPods...")
sh("cd ../ios && pod install")
UI.success("CocoaPods installés")
# Étape 4 : Récupérer les informations de version
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
version_name = version_info.split('+').first
version_code = version_info.split('+').last
UI.message("📋 Version: #{version_name} (#{version_code})")
# Étape 5 : Analyser le code (non bloquant)
UI.message("🔍 [4/7] Analyse du code...")
begin
sh("cd .. && flutter analyze --no-fatal-infos --no-fatal-warnings")
UI.success("Analyse du code terminée")
rescue => ex
UI.important("⚠️ Des warnings détectés, mais on continue...")
end
# Étape 6 : Build Flutter iOS
UI.message("🏗️ [5/7] Build Flutter iOS (RELEASE)...")
sh("cd .. && flutter build ios --release --no-codesign")
UI.success("Build Flutter iOS généré")
# Étape 7 : Archive Xcode
UI.message("📦 [6/7] Archive Xcode...")
build_ios_app(
workspace: "./Runner.xcworkspace",
scheme: "Runner",
export_method: "app-store",
export_options: {
method: "app-store",
teamID: "6WT84NWCTC",
uploadBitcode: false,
uploadSymbols: true,
compileBitcode: false,
signingStyle: "automatic",
provisioningProfiles: {
"fr.geosector.app3" => "match AppStore fr.geosector.app3"
}
},
output_directory: "../build/ios/ipa",
output_name: "Runner.ipa",
clean: false,
skip_profile_detection: true
)
UI.success("IPA généré")
# Étape 7 : Upload vers TestFlight
UI.message("📤 [7/7] Upload vers TestFlight...")
upload_to_testflight(
apple_id: "contact@d6soft.com",
app_identifier: "fr.geosector.app3",
team_id: "6WT84NWCTC",
ipa: "../build/ios/ipa/Runner.ipa",
skip_waiting_for_build_processing: true,
skip_submission: true,
distribute_external: false
)
UI.success("✅ Déploiement iOS terminé avec succès!")
UI.success("📦 Version: #{version_name} (Build #{version_code})")
UI.success("🎯 Track: TestFlight (Internal)")
UI.success("🌐 URL: https://appstoreconnect.apple.com")
end
desc "Upload un IPA existant vers TestFlight"
lane :upload do
UI.header("📤 Upload IPA vers TestFlight")
# Vérifier que l'IPA existe
ipa_path = '../build/ios/ipa/Runner.ipa'
if File.exist?(ipa_path)
# Récupérer la version
version_info = sh("cd .. && grep '^version:' pubspec.yaml | sed 's/version: //'").strip
version_name = version_info.split('+').first
version_code = version_info.split('+').last
UI.message("📦 Upload de l'IPA existant...")
upload_to_testflight(
apple_id: "contact@d6soft.com",
app_identifier: "fr.geosector.app3",
team_id: "6WT84NWCTC",
ipa: ipa_path,
skip_waiting_for_build_processing: true,
skip_submission: true,
distribute_external: false
)
UI.success("✅ Upload terminé!")
UI.success("📦 Version: #{version_name} (Build #{version_code})")
else
UI.user_error!("❌ IPA introuvable: #{ipa_path}")
UI.message("💡 Lancez d'abord: fastlane ios build")
end
end
end

View File

@@ -0,0 +1,211 @@
#!/bin/bash
# Script de génération du bundle Android pour GEOSECTOR
# Usage: ./android.sh
set -e # Arrêter le script en cas d'erreur
# Couleurs pour les messages
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Fonction pour afficher les messages
print_message() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
# Fonction pour gérer les erreurs
handle_error() {
print_error "Une erreur est survenue lors de l'exécution de la commande"
print_error "Ligne $1"
exit 1
}
# Trap pour capturer les erreurs
trap 'handle_error $LINENO' ERR
# Vérifier que nous sommes dans le bon dossier
if [ ! -f "pubspec.yaml" ]; then
print_error "Ce script doit être exécuté depuis le dossier racine de l'application Flutter"
print_error "Fichier pubspec.yaml introuvable"
exit 1
fi
print_message "========================================="
print_message " GEOSECTOR - Génération Bundle Android"
print_message "========================================="
echo
# Vérifier que Flutter est installé
if ! command -v flutter &> /dev/null; then
print_error "Flutter n'est pas installé ou n'est pas dans le PATH"
exit 1
fi
# Récupérer la version depuis pubspec.yaml
VERSION=$(grep "^version:" pubspec.yaml | sed 's/version: //' | sed 's/+/-/')
if [ -z "$VERSION" ]; then
print_error "Impossible de récupérer la version depuis pubspec.yaml"
exit 1
fi
# Extraire le version code
VERSION_CODE=$(echo $VERSION | cut -d'-' -f2)
if [ -z "$VERSION_CODE" ]; then
print_error "Impossible d'extraire le version code"
exit 1
fi
print_message "Version détectée : $VERSION"
print_message "Version code : $VERSION_CODE"
echo
# Vérifier la présence du keystore
if [ ! -f "android/app/geosector2025.jks" ]; then
print_error "Fichier keystore introuvable : android/app/geosector2025.jks"
exit 1
fi
# Vérifier la présence du fichier key.properties
if [ ! -f "android/key.properties" ]; then
print_error "Fichier key.properties introuvable"
print_error "Ce fichier est nécessaire pour signer l'application"
exit 1
fi
print_success "Configuration de signature vérifiée"
echo
# Étape 1 : Nettoyer le projet
print_message "Étape 1/4 : Nettoyage du projet..."
flutter clean
if [ $? -eq 0 ]; then
print_success "Projet nettoyé"
else
print_error "Échec du nettoyage du projet"
exit 1
fi
echo
# Étape 2 : Récupérer les dépendances
print_message "Étape 2/4 : Récupération des dépendances..."
flutter pub get
if [ $? -eq 0 ]; then
print_success "Dépendances récupérées"
else
print_error "Échec de la récupération des dépendances"
exit 1
fi
# Patch nfc_manager 3.3.0 (AndroidManifest namespace)
print_message "Application du patch nfc_manager 3.3.0..."
./fastlane/scripts/commun/fix-nfc-manager.sh || {
print_error "Échec du patch nfc_manager"
exit 1
}
echo
# Étape 3 : Analyser le code (optionnel mais recommandé)
print_message "Étape 3/4 : Analyse du code Dart..."
flutter analyze --no-fatal-infos --no-fatal-warnings || {
print_warning "Des avertissements ont été détectés dans le code"
read -p "Voulez-vous continuer malgré les avertissements ? (y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_message "Génération annulée par l'utilisateur"
exit 0
fi
}
print_success "Analyse du code terminée"
echo
# Étape 4 : Générer le bundle
print_message "Étape 4/4 : Génération du bundle Android..."
print_message "Cette opération peut prendre plusieurs minutes..."
flutter build appbundle --release
if [ $? -eq 0 ]; then
print_success "Bundle généré avec succès"
else
print_error "Échec de la génération du bundle"
exit 1
fi
echo
# Vérifier que le bundle a été créé
BUNDLE_PATH="build/app/outputs/bundle/release/app-release.aab"
if [ ! -f "$BUNDLE_PATH" ]; then
print_error "Bundle introuvable à l'emplacement attendu : $BUNDLE_PATH"
exit 1
fi
# Copier le bundle à la racine avec le nouveau nom
FINAL_NAME="geosector-$VERSION_CODE.aab"
print_message "Copie du bundle vers : $FINAL_NAME"
cp "$BUNDLE_PATH" "$FINAL_NAME"
if [ -f "$FINAL_NAME" ]; then
print_success "Bundle copié avec succès"
# Afficher la taille du fichier
FILE_SIZE=$(du -h "$FINAL_NAME" | cut -f1)
print_message "Taille du bundle : $FILE_SIZE"
else
print_error "Échec de la copie du bundle"
exit 1
fi
echo
print_message "========================================="
print_success " GÉNÉRATION TERMINÉE AVEC SUCCÈS !"
print_message "========================================="
echo
print_message "Bundle généré : ${GREEN}$FINAL_NAME${NC}"
print_message "Version : $VERSION"
print_message "Chemin : $(pwd)/$FINAL_NAME"
echo
print_message "Prochaines étapes :"
print_message "1. Tester le bundle sur un appareil Android"
print_message "2. Uploader sur Google Play Console"
print_message "3. Soumettre pour review"
echo
# Optionnel : Générer aussi l'APK
read -p "Voulez-vous aussi générer l'APK pour des tests ? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_message "Génération de l'APK..."
flutter build apk --release
if [ $? -eq 0 ]; then
APK_PATH="build/app/outputs/flutter-apk/app-release.apk"
if [ -f "$APK_PATH" ]; then
APK_NAME="geosector-$VERSION_CODE.apk"
cp "$APK_PATH" "$APK_NAME"
print_success "APK généré : $APK_NAME"
# Afficher la taille de l'APK
APK_SIZE=$(du -h "$APK_NAME" | cut -f1)
print_message "Taille de l'APK : $APK_SIZE"
fi
else
print_warning "Échec de la génération de l'APK (le bundle a été créé avec succès)"
fi
fi
echo
print_success "Script terminé !"

View File

@@ -0,0 +1,214 @@
#!/bin/bash
# ============================================================================
# Script de correction du package nfc_manager 3.3.0 pour Android Gradle Plugin 8+
# ============================================================================
#
# Problème :
# nfc_manager 3.3.0 utilise l'ancien format 'package="..."' dans AndroidManifest.xml
# et ne déclare pas de namespace dans build.gradle (requis par AGP 8+)
#
# Solution :
# 1. Supprime l'attribut package="io.flutter.plugins.nfcmanager" du AndroidManifest.xml
# 2. Ajoute namespace 'io.flutter.plugins.nfc_manager' dans build.gradle
#
# Usage :
# ./fix-nfc-manager.sh
#
# Historique :
# 14/10/2025 - Création du script pour résoudre compilation Android
# ============================================================================
set -e
# Détection de l'OS pour la syntaxe sed
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS (BSD sed)
SED_INPLACE="sed -i ''"
else
# Linux (GNU sed)
SED_INPLACE="sed -i"
fi
# Couleurs pour les messages
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
echo_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
echo_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
echo_step() {
echo -e "${BLUE}[STEP]${NC} $1"
}
# Chemins vers les fichiers de nfc_manager 3.3.0
# Utilise $PUB_CACHE si défini (cache local projet), sinon $HOME/.pub-cache
PUB_CACHE_BASE="${PUB_CACHE:-$HOME/.pub-cache}"
NFC_DIR="${PUB_CACHE_BASE}/hosted/pub.dev/nfc_manager-3.3.0/android"
NFC_MANIFEST="${NFC_DIR}/src/main/AndroidManifest.xml"
NFC_BUILD_GRADLE="${NFC_DIR}/build.gradle"
NFC_TRANSLATOR="${NFC_DIR}/src/main/kotlin/io/flutter/plugins/nfcmanager/Translator.kt"
echo_info "=========================================="
echo_info " nfc_manager 3.3.0 - Android Patch"
echo_info "=========================================="
echo ""
# Vérifier si les fichiers existent
if [ ! -f "$NFC_MANIFEST" ]; then
echo_error "Fichier AndroidManifest.xml introuvable"
echo_error "Chemin attendu: $NFC_MANIFEST"
echo ""
echo_info "Exécutez 'flutter pub get' d'abord"
exit 1
fi
if [ ! -f "$NFC_BUILD_GRADLE" ]; then
echo_error "Fichier build.gradle introuvable"
echo_error "Chemin attendu: $NFC_BUILD_GRADLE"
exit 1
fi
if [ ! -f "$NFC_TRANSLATOR" ]; then
echo_error "Fichier Translator.kt introuvable"
echo_error "Chemin attendu: $NFC_TRANSLATOR"
exit 1
fi
echo_info "Fichiers trouvés:"
echo_info " - AndroidManifest.xml: $NFC_MANIFEST"
echo_info " - build.gradle: $NFC_BUILD_GRADLE"
echo_info " - Translator.kt: $NFC_TRANSLATOR"
echo ""
# ===========================================
# ÉTAPE 1 : Patcher AndroidManifest.xml
# ===========================================
echo_step "Étape 1/2 : Patch AndroidManifest.xml"
echo ""
if grep -q 'package="io.flutter.plugins.nfcmanager"' "$NFC_MANIFEST"; then
echo_warning "Attribut 'package' détecté dans AndroidManifest.xml"
# Créer une sauvegarde
BACKUP_MANIFEST="${NFC_MANIFEST}.backup"
if [ ! -f "$BACKUP_MANIFEST" ]; then
cp "$NFC_MANIFEST" "$BACKUP_MANIFEST"
echo_info "Sauvegarde créée: ${BACKUP_MANIFEST}"
fi
# Appliquer le patch (compatible Linux + macOS)
eval "$SED_INPLACE 's/ package=\"io.flutter.plugins.nfcmanager\"//g' \"$NFC_MANIFEST\""
# Vérifier
if ! grep -q 'package="io.flutter.plugins.nfcmanager"' "$NFC_MANIFEST"; then
echo_info "✅ AndroidManifest.xml patché avec succès"
else
echo_error "❌ Échec du patch AndroidManifest.xml"
exit 1
fi
else
echo_info "✅ AndroidManifest.xml déjà patché"
fi
echo ""
# ===========================================
# ÉTAPE 2 : Patcher build.gradle
# ===========================================
echo_step "Étape 2/2 : Patch build.gradle"
echo ""
if grep -q "namespace 'io.flutter.plugins.nfc_manager'" "$NFC_BUILD_GRADLE"; then
echo_info "✅ build.gradle déjà patché (namespace présent)"
else
echo_warning "Namespace manquant dans build.gradle"
# Créer une sauvegarde
BACKUP_GRADLE="${NFC_BUILD_GRADLE}.backup"
if [ ! -f "$BACKUP_GRADLE" ]; then
cp "$NFC_BUILD_GRADLE" "$BACKUP_GRADLE"
echo_info "Sauvegarde créée: ${BACKUP_GRADLE}"
fi
# Appliquer le patch : ajouter namespace après "android {" (compatible Linux + macOS)
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS : nécessite un retour à la ligne explicite
sed -i '' "/^android {$/a\\
namespace 'io.flutter.plugins.nfc_manager'
" "$NFC_BUILD_GRADLE"
else
# Linux : syntaxe différente
sed -i "/^android {$/a\\ namespace 'io.flutter.plugins.nfc_manager'" "$NFC_BUILD_GRADLE"
fi
# Vérifier
if grep -q "namespace 'io.flutter.plugins.nfc_manager'" "$NFC_BUILD_GRADLE"; then
echo_info "✅ build.gradle patché avec succès (namespace ajouté)"
else
echo_error "❌ Échec du patch build.gradle"
# Restaurer le backup
mv "$BACKUP_GRADLE" "$NFC_BUILD_GRADLE"
exit 1
fi
fi
echo ""
# ===========================================
# ÉTAPE 3 : Patcher Translator.kt (Kotlin)
# ===========================================
echo_step "Étape 3/3 : Patch Translator.kt (fix Kotlin deprecated)"
echo ""
if grep -q '\.toLowerCase(' "$NFC_TRANSLATOR"; then
echo_warning "Méthode dépréciée 'toLowerCase()' détectée dans Translator.kt"
# Créer une sauvegarde
BACKUP_TRANSLATOR="${NFC_TRANSLATOR}.backup"
if [ ! -f "$BACKUP_TRANSLATOR" ]; then
cp "$NFC_TRANSLATOR" "$BACKUP_TRANSLATOR"
echo_info "Sauvegarde créée: ${BACKUP_TRANSLATOR}"
fi
# Appliquer le patch : remplacer toLowerCase par lowercase (compatible Linux + macOS)
eval "$SED_INPLACE 's/\\.toLowerCase(/\\.lowercase(/g' \"$NFC_TRANSLATOR\""
# Vérifier
if ! grep -q '\.toLowerCase(' "$NFC_TRANSLATOR"; then
echo_info "✅ Translator.kt patché avec succès (toLowerCase → lowercase)"
else
echo_error "❌ Échec du patch Translator.kt"
# Restaurer le backup
mv "$BACKUP_TRANSLATOR" "$NFC_TRANSLATOR"
exit 1
fi
else
echo_info "✅ Translator.kt déjà patché (pas de toLowerCase)"
fi
echo ""
echo_info "=========================================="
echo_info " ✅ Patch terminé avec succès!"
echo_info "=========================================="
echo ""
echo_info "Modifications appliquées:"
echo_info " 1. AndroidManifest.xml - Attribut 'package' supprimé"
echo_info " 2. build.gradle - Namespace ajouté"
echo_info " 3. Translator.kt - toLowerCase() → lowercase()"
echo ""
echo_info "Vous pouvez maintenant compiler Android:"
echo_info " ./android.sh"
echo ""
exit 0

View File

@@ -0,0 +1,87 @@
#!/bin/bash
# Script de correction automatique pour permission_handler_apple
# Problème : Le package embarque ses propres headers Flutter qui créent des conflits
# Solution : Supprimer le dossier Flutter/ et corriger les imports
# Date : 14/10/2025
# Usage : ./fix-permission-handler.sh
set -e # Arrêter en cas d'erreur
# Détection de l'OS pour la syntaxe sed
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS (BSD sed)
SED_INPLACE="sed -i ''"
else
# Linux (GNU sed)
SED_INPLACE="sed -i"
fi
echo "🔧 Fix permission_handler_apple - Correction des conflits Flutter headers"
echo ""
# Couleurs pour les messages
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# Trouver le chemin du package dans .pub-cache
# Utilise $PUB_CACHE si défini (cache local projet), sinon $HOME/.pub-cache
PUB_CACHE_BASE="${PUB_CACHE:-$HOME/.pub-cache}"
PERMISSION_HANDLER_PATH=$(find "${PUB_CACHE_BASE}/hosted/pub.dev" -maxdepth 1 -name "permission_handler_apple-*" -type d | sort -V | tail -n 1)
if [ -z "$PERMISSION_HANDLER_PATH" ]; then
echo -e "${RED}❌ Erreur : Package permission_handler_apple introuvable dans .pub-cache${NC}"
exit 1
fi
echo -e "${YELLOW}📦 Package trouvé : $PERMISSION_HANDLER_PATH${NC}"
echo ""
CLASSES_PATH="$PERMISSION_HANDLER_PATH/ios/Classes"
FLUTTER_DIR="$CLASSES_PATH/Flutter"
# Étape 1 : Vérifier si le dossier Flutter existe
if [ -d "$FLUTTER_DIR" ]; then
echo -e "${YELLOW}🗑️ Suppression du dossier Flutter embarqué...${NC}"
rm -rf "$FLUTTER_DIR"
echo -e "${GREEN}✅ Dossier Flutter supprimé${NC}"
else
echo -e "${GREEN}✅ Dossier Flutter déjà supprimé${NC}"
fi
# Étape 2 : Corriger les imports dans PermissionHandlerPlugin.h
PLUGIN_HEADER="$CLASSES_PATH/PermissionHandlerPlugin.h"
if [ -f "$PLUGIN_HEADER" ]; then
if grep -q '#import "Flutter/Flutter.h"' "$PLUGIN_HEADER"; then
echo -e "${YELLOW}📝 Correction de PermissionHandlerPlugin.h...${NC}"
eval "$SED_INPLACE 's|#import \"Flutter/Flutter.h\"|#import <Flutter/Flutter.h>|g' \"$PLUGIN_HEADER\""
echo -e "${GREEN}✅ PermissionHandlerPlugin.h corrigé${NC}"
else
echo -e "${GREEN}✅ PermissionHandlerPlugin.h déjà corrigé${NC}"
fi
else
echo -e "${RED}⚠️ Fichier PermissionHandlerPlugin.h introuvable${NC}"
fi
# Étape 3 : Corriger les imports dans PermissionManager.h
MANAGER_HEADER="$CLASSES_PATH/PermissionManager.h"
if [ -f "$MANAGER_HEADER" ]; then
if grep -q '#import "Flutter/Flutter.h"' "$MANAGER_HEADER"; then
echo -e "${YELLOW}📝 Correction de PermissionManager.h...${NC}"
eval "$SED_INPLACE 's|#import \"Flutter/Flutter.h\"|#import <Flutter/Flutter.h>|g' \"$MANAGER_HEADER\""
echo -e "${GREEN}✅ PermissionManager.h corrigé${NC}"
else
echo -e "${GREEN}✅ PermissionManager.h déjà corrigé${NC}"
fi
else
echo -e "${RED}⚠️ Fichier PermissionManager.h introuvable${NC}"
fi
echo ""
echo -e "${GREEN}🎉 Correction terminée avec succès !${NC}"
echo ""
echo -e "${YELLOW} Ce script doit être exécuté après chaque 'flutter pub get'${NC}"
echo -e "${YELLOW} Raison : Le package permission_handler_apple embarque des headers Flutter qui créent des conflits${NC}"
echo ""

View File

@@ -0,0 +1,65 @@
#!/bin/bash
# Script maître de correction des packages iOS problématiques
# Combine : fix-nfc-manager.sh + fix-permission-handler.sh
# Date : 14/10/2025
# Usage : ./fix-ios-packages.sh (à exécuter après chaque flutter pub get)
set -e # Arrêter en cas d'erreur
echo "🚀 Fix iOS Packages - Correction automatique des packages problématiques"
echo "========================================================================="
echo ""
# Couleurs pour les messages
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# =============================================================================
# 1. Fix nfc_manager (namespace Android + headers iOS)
# =============================================================================
echo -e "${BLUE}📦 [1/2] Correction de nfc_manager...${NC}"
echo ""
if [ -f "./fastlane/scripts/commun/fix-nfc-manager.sh" ]; then
./fastlane/scripts/commun/fix-nfc-manager.sh
echo ""
else
echo -e "${YELLOW}⚠️ Script fix-nfc-manager.sh introuvable, ignoré${NC}"
echo ""
fi
# =============================================================================
# 2. Fix permission_handler_apple (headers Flutter embarqués)
# =============================================================================
echo -e "${BLUE}📦 [2/2] Correction de permission_handler_apple...${NC}"
echo ""
if [ -f "./fastlane/scripts/commun/fix-permission-handler.sh" ]; then
./fastlane/scripts/commun/fix-permission-handler.sh
echo ""
else
echo -e "${YELLOW}⚠️ Script fix-permission-handler.sh introuvable, ignoré${NC}"
echo ""
fi
# =============================================================================
# Résumé
# =============================================================================
echo "========================================================================="
echo -e "${GREEN}✅ Tous les packages iOS ont été corrigés avec succès !${NC}"
echo ""
echo -e "${YELLOW}📋 Workflow de build iOS recommandé :${NC}"
echo " 1. flutter clean"
echo " 2. flutter pub get"
echo " 3. ./fix-ios-packages.sh ← Ce script"
echo " 4. cd ios && pod install && cd .."
echo " 5. flutter build ios --release --no-codesign"
echo ""
echo -e "${YELLOW}💡 Astuce : Vous pouvez ajouter ce script à votre .gitignore${NC}"
echo ""

View File

@@ -0,0 +1,152 @@
#!/bin/bash
# Script de compilation et archivage iOS sur Mac mini
# Ce script doit être exécuté SUR le Mac mini
# Usage: ./ios-build-mac.sh
set -e
# Couleurs pour les messages
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}=========================================${NC}"
echo -e "${BLUE} GEOSECTOR - Build iOS sur Mac mini${NC}"
echo -e "${BLUE}=========================================${NC}"
echo ""
# Vérifier que nous sommes sur macOS
if [[ "$OSTYPE" != "darwin"* ]]; then
echo -e "${RED}Erreur: Ce script doit être exécuté sur macOS (Mac mini)${NC}"
exit 1
fi
# Vérifier que nous sommes dans le bon dossier
if [ ! -f "pubspec.yaml" ]; then
echo -e "${RED}Erreur: Ce script doit être exécuté depuis le dossier racine de l'application Flutter${NC}"
echo -e "${RED}Fichier pubspec.yaml introuvable${NC}"
exit 1
fi
# Vérifier que Flutter est installé
if ! command -v flutter &> /dev/null; then
echo -e "${RED}Erreur: Flutter n'est pas installé ou n'est pas dans le PATH${NC}"
exit 1
fi
# Vérifier que Xcode est installé
if ! command -v xcodebuild &> /dev/null; then
echo -e "${RED}Erreur: Xcode Command Line Tools ne sont pas installés${NC}"
echo -e "${YELLOW}Installation: xcode-select --install${NC}"
exit 1
fi
# Récupérer la version depuis pubspec.yaml
VERSION=$(grep "^version:" pubspec.yaml | sed 's/version: //' | tr -d ' ')
VERSION_NAME=$(echo $VERSION | cut -d'+' -f1)
VERSION_CODE=$(echo $VERSION | cut -d'+' -f2)
if [ -z "$VERSION_CODE" ]; then
echo -e "${RED}Impossible de récupérer la version depuis pubspec.yaml${NC}"
exit 1
fi
echo -e "${YELLOW}Version détectée :${NC} $VERSION"
echo -e "${YELLOW}Version name :${NC} $VERSION_NAME"
echo -e "${YELLOW}Build number :${NC} $VERSION_CODE"
echo ""
# Afficher la version de Flutter
echo -e "${BLUE}Version Flutter :${NC}"
flutter --version
echo ""
# Étape 1 : Nettoyer le projet
echo -e "${BLUE}Étape 1/5 : Nettoyage du projet...${NC}"
flutter clean
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ Projet nettoyé${NC}"
else
echo -e "${RED}✗ Échec du nettoyage${NC}"
exit 1
fi
echo ""
# Étape 2 : Récupérer les dépendances Flutter
echo -e "${BLUE}Étape 2/5 : Récupération des dépendances Flutter...${NC}"
flutter pub get
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ Dépendances Flutter récupérées${NC}"
else
echo -e "${RED}✗ Échec de la récupération des dépendances${NC}"
exit 1
fi
echo ""
# Étape 3 : Installer les pods iOS
echo -e "${BLUE}Étape 3/5 : Installation des CocoaPods...${NC}"
cd ios
pod install
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ Pods installés${NC}"
cd ..
else
echo -e "${RED}✗ Échec de l'installation des pods${NC}"
cd ..
exit 1
fi
echo ""
# Étape 4 : Build iOS release
echo -e "${BLUE}Étape 4/5 : Compilation iOS (release)...${NC}"
echo -e "${YELLOW}Cette étape peut prendre 5-10 minutes...${NC}"
flutter build ios --release --no-codesign
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ Compilation iOS réussie${NC}"
else
echo -e "${RED}✗ Échec de la compilation iOS${NC}"
echo -e "${YELLOW}Consultez les logs ci-dessus pour plus de détails${NC}"
exit 1
fi
echo ""
# Étape 5 : Ouvrir Xcode pour l'archive
echo -e "${BLUE}Étape 5/5 : Ouverture de Xcode pour l'archive...${NC}"
echo ""
echo -e "${YELLOW}L'archive en ligne de commande peut échouer avec les certificats.${NC}"
echo -e "${YELLOW}Xcode gère mieux la signature automatique.${NC}"
echo ""
# Ouvrir Xcode
echo -e "${GREEN}Ouverture de Xcode...${NC}"
open ios/Runner.xcworkspace
echo ""
echo -e "${GREEN}=========================================${NC}"
echo -e "${GREEN} ✓ BUILD iOS TERMINÉ AVEC SUCCÈS !${NC}"
echo -e "${GREEN}=========================================${NC}"
echo ""
echo -e "${YELLOW}Version :${NC} $VERSION_NAME ($VERSION_CODE)"
echo ""
echo -e "${BLUE}📱 PROCHAINES ÉTAPES DANS XCODE :${NC}"
echo ""
echo -e " ${GREEN}1.${NC} Attendre que Xcode charge le projet (quelques secondes)"
echo -e " ${GREEN}2.${NC} Vérifier le Team : ${YELLOW}Runner > Signing & Capabilities > Team = 6WT84NWCTC${NC}"
echo -e " ${GREEN}3.${NC} Menu : ${YELLOW}Product > Clean Build Folder${NC} (Cmd+Shift+K)"
echo -e " ${GREEN}4.${NC} Menu : ${YELLOW}Product > Archive${NC}"
echo -e " ${GREEN}5.${NC} Attendre la fin de l'archive (5-10 minutes)"
echo -e " ${GREEN}6.${NC} Fenêtre Organizer s'ouvrira automatiquement"
echo -e " ${GREEN}7.${NC} Clic sur ${YELLOW}Distribute App${NC}"
echo -e " ${GREEN}8.${NC} Sélectionner ${YELLOW}App Store Connect${NC}"
echo -e " ${GREEN}9.${NC} Suivre l'assistant d'upload"
echo ""
echo -e "${BLUE}💡 CONSEILS :${NC}"
echo -e " • Si l'archive échoue, vérifier les certificats dans Signing & Capabilities"
echo -e " • Automatic signing doit être coché"
echo -e " • Team doit être 6WT84NWCTC (Pierre ROTROU)"
echo ""
echo -e "${YELLOW}Xcode est maintenant ouvert et prêt pour l'archive !${NC}"
echo ""

400
app/fastlane/scripts/ios/ios.sh Executable file
View File

@@ -0,0 +1,400 @@
#!/bin/bash
# Script de génération de l'application iOS pour GEOSECTOR
# Usage: ./ios.sh
# Options: ./ios.sh --skip-archive (build uniquement sans archive Xcode)
set -e # Arrêter le script en cas d'erreur
# Couleurs pour les messages
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color
# Options
SKIP_ARCHIVE=false
if [[ "$1" == "--skip-archive" ]]; then
SKIP_ARCHIVE=true
fi
# Fonction pour afficher les messages
print_message() {
echo -e "${BLUE}[INFO]${NC} $1"
}
print_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
print_step() {
echo -e "${MAGENTA}[STEP]${NC} $1"
}
# Fonction pour gérer les erreurs
handle_error() {
print_error "Une erreur est survenue lors de l'exécution de la commande"
print_error "Ligne $1"
exit 1
}
# Trap pour capturer les erreurs
trap 'handle_error $LINENO' ERR
# Vérifier que nous sommes dans le bon dossier
if [ ! -f "pubspec.yaml" ]; then
print_error "Ce script doit être exécuté depuis le dossier racine de l'application Flutter"
print_error "Fichier pubspec.yaml introuvable"
exit 1
fi
# Vérifier que nous sommes sur macOS
if [[ "$OSTYPE" != "darwin"* ]]; then
print_error "Ce script doit être exécuté sur macOS pour compiler iOS"
exit 1
fi
echo
print_message "========================================="
print_message " GEOSECTOR - Build iOS Application"
print_message "========================================="
echo
# Vérifier que Flutter est installé
if ! command -v flutter &> /dev/null; then
print_error "Flutter n'est pas installé ou n'est pas dans le PATH"
exit 1
fi
# Vérifier la version Flutter
FLUTTER_VERSION=$(flutter --version | head -n 1 | cut -d' ' -f2)
print_message "Flutter version : $FLUTTER_VERSION"
# Vérifier que c'est Flutter 3.24.5 (recommandé)
if [[ "$FLUTTER_VERSION" != "3.24.5" ]]; then
print_warning "Version Flutter détectée : $FLUTTER_VERSION"
print_warning "Version recommandée : 3.24.5 LTS"
read -p "Voulez-vous continuer ? (y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_message "Build annulé par l'utilisateur"
exit 0
fi
fi
# Vérifier que CocoaPods est installé
if ! command -v pod &> /dev/null; then
print_error "CocoaPods n'est pas installé"
print_error "Installation : sudo gem install cocoapods"
exit 1
fi
POD_VERSION=$(pod --version)
print_message "CocoaPods version : $POD_VERSION"
# Vérifier que Xcode est installé
if ! command -v xcodebuild &> /dev/null; then
print_error "Xcode n'est pas installé"
print_error "Installation : App Store > Xcode"
exit 1
fi
XCODE_VERSION=$(xcodebuild -version | head -n 1)
print_message "$XCODE_VERSION"
# Récupérer la version depuis pubspec.yaml
VERSION=$(grep "^version:" pubspec.yaml | sed 's/version: //' | sed 's/+/-/')
if [ -z "$VERSION" ]; then
print_error "Impossible de récupérer la version depuis pubspec.yaml"
exit 1
fi
# Extraire le version code
VERSION_CODE=$(echo $VERSION | cut -d'-' -f2)
if [ -z "$VERSION_CODE" ]; then
print_error "Impossible d'extraire le version code"
exit 1
fi
VERSION_NAME=$(echo $VERSION | cut -d'-' -f1)
print_message "Version détectée : $VERSION_NAME ($VERSION_CODE)"
echo
# Vérifier que le dossier ios existe
if [ ! -d "ios" ]; then
print_error "Dossier ios/ introuvable"
exit 1
fi
print_success "Vérifications préliminaires terminées"
echo
# =============================================================================
# ÉTAPE 1 : Nettoyage complet
# =============================================================================
print_step "Étape 1/7 : Nettoyage complet du projet..."
echo
print_message "Suppression du cache Flutter..."
flutter clean
print_message "Suppression du cache iOS (Pods, build, symlinks)..."
rm -rf ios/Pods
rm -rf ios/Podfile.lock
rm -rf ios/.symlinks
rm -rf build/ios
print_success "Nettoyage terminé"
echo
# =============================================================================
# ÉTAPE 2 : Récupération des dépendances Flutter
# =============================================================================
print_step "Étape 2/7 : Récupération des dépendances Flutter..."
echo
flutter pub get
if [ $? -eq 0 ]; then
print_success "Dépendances Flutter récupérées"
else
print_error "Échec de la récupération des dépendances Flutter"
exit 1
fi
echo
# Vérifier que Generated.xcconfig a été créé avec les bons chemins
if [ ! -f "ios/Flutter/Generated.xcconfig" ]; then
print_error "Fichier ios/Flutter/Generated.xcconfig non généré"
exit 1
fi
FLUTTER_ROOT=$(grep "FLUTTER_ROOT=" ios/Flutter/Generated.xcconfig | cut -d'=' -f2)
print_message "FLUTTER_ROOT configuré : $FLUTTER_ROOT"
if [[ "$FLUTTER_ROOT" == *"/opt/flutter"* ]] || [[ "$FLUTTER_ROOT" == *"/home/"* ]]; then
print_error "FLUTTER_ROOT contient un chemin Linux invalide : $FLUTTER_ROOT"
print_error "Régénération nécessaire..."
rm ios/Flutter/Generated.xcconfig
flutter pub get
fi
print_success "Configuration Flutter vérifiée"
echo
# =============================================================================
# ÉTAPE 3 : Patch permission_handler_apple (critique pour iOS)
# =============================================================================
print_step "Étape 3/7 : Application du patch permission_handler_apple..."
echo
if [ -f "./fastlane/scripts/commun/fix-permission-handler.sh" ]; then
./fastlane/scripts/commun/fix-permission-handler.sh
if [ $? -eq 0 ]; then
print_success "Patch permission_handler_apple appliqué"
else
print_error "Échec du patch permission_handler_apple"
exit 1
fi
else
print_warning "Script fix-permission-handler.sh introuvable"
print_warning "La compilation peut échouer sans ce patch"
read -p "Voulez-vous continuer malgré tout ? (y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_message "Build annulé par l'utilisateur"
exit 0
fi
fi
echo
# =============================================================================
# ÉTAPE 4 : Installation des pods CocoaPods
# =============================================================================
print_step "Étape 4/7 : Installation des pods CocoaPods..."
echo
cd ios
pod install
if [ $? -eq 0 ]; then
print_success "Pods installés avec succès"
# Compter le nombre de pods installés
POD_COUNT=$(grep -c "Installing" Podfile.lock 2>/dev/null || echo "0")
print_message "Nombre de pods installés : $POD_COUNT"
else
print_error "Échec de l'installation des pods"
exit 1
fi
cd ..
echo
# Vérifier que le workspace a été créé
if [ ! -d "ios/Runner.xcworkspace" ]; then
print_error "Workspace Xcode non créé : ios/Runner.xcworkspace"
exit 1
fi
print_success "Workspace Xcode créé : ios/Runner.xcworkspace"
echo
# =============================================================================
# ÉTAPE 5 : Analyse du code (optionnel)
# =============================================================================
print_step "Étape 5/7 : Analyse du code Dart..."
echo
flutter analyze --no-fatal-infos --no-fatal-warnings || {
print_warning "Des avertissements ont été détectés dans le code"
read -p "Voulez-vous continuer malgré les avertissements ? (y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_message "Build annulé par l'utilisateur"
exit 0
fi
}
print_success "Analyse du code terminée"
echo
# =============================================================================
# ÉTAPE 6 : Build iOS (sans signature)
# =============================================================================
print_step "Étape 6/7 : Compilation iOS (release, sans signature)..."
echo
print_message "Cette opération peut prendre plusieurs minutes..."
print_message "Compilation en cours..."
flutter build ios --release --no-codesign
if [ $? -eq 0 ]; then
print_success "Compilation iOS réussie !"
# Vérifier que l'app a été créée
if [ -d "build/ios/iphoneos/Runner.app" ]; then
APP_SIZE=$(du -sh build/ios/iphoneos/Runner.app | cut -f1)
print_message "Taille de l'app : $APP_SIZE"
print_message "Chemin : build/ios/iphoneos/Runner.app"
else
print_warning "Application générée mais introuvable à l'emplacement attendu"
fi
else
print_error "Échec de la compilation iOS"
print_error "Consultez les logs ci-dessus pour plus de détails"
exit 1
fi
echo
# =============================================================================
# ÉTAPE 7 : Archive Xcode (optionnel)
# =============================================================================
if [ "$SKIP_ARCHIVE" = false ]; then
print_step "Étape 7/7 : Création de l'archive Xcode..."
echo
print_message "L'archive Xcode nécessite une signature de code"
print_message "Cette étape ouvrira Xcode pour créer l'archive manuellement"
echo
read -p "Voulez-vous ouvrir Xcode pour créer l'archive ? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
print_message "Ouverture de Xcode..."
open ios/Runner.xcworkspace
echo
print_message "========================================="
print_message " Instructions pour l'archive Xcode"
print_message "========================================="
echo
print_message "1. Dans Xcode, sélectionner : Any iOS Device (arm64)"
print_message "2. Menu : Product > Clean Build Folder (Cmd+Shift+K)"
print_message "3. Menu : Product > Archive"
print_message "4. Attendre la fin de la compilation (~5-10 min)"
print_message "5. Organizer s'ouvre automatiquement"
print_message "6. Cliquer sur 'Validate App'"
print_message "7. Puis 'Distribute App' > 'App Store Connect' > 'Upload'"
echo
print_warning "Ne fermez pas ce terminal pendant l'archive Xcode"
echo
read -p "Appuyez sur Entrée quand l'archive est terminée..." -r
echo
print_success "Archive créée avec succès (si aucune erreur Xcode)"
else
print_message "Archive ignorée"
print_message "Vous pouvez créer l'archive plus tard avec :"
print_message " open ios/Runner.xcworkspace"
fi
else
print_message "Étape 7/7 : Archive Xcode ignorée (--skip-archive)"
fi
echo
# =============================================================================
# RÉSUMÉ FINAL
# =============================================================================
print_message "========================================="
print_success " BUILD iOS TERMINÉ AVEC SUCCÈS !"
print_message "========================================="
echo
print_message "Version : ${GREEN}$VERSION_NAME ($VERSION_CODE)${NC}"
print_message "Bundle ID : ${GREEN}fr.geosector.app3${NC}"
print_message "Application : ${GREEN}build/ios/iphoneos/Runner.app${NC}"
echo
if [ "$SKIP_ARCHIVE" = false ]; then
print_message "Prochaines étapes (dans Xcode) :"
print_message "1. ✅ Build iOS réussi"
print_message "2. ⏳ Créer l'archive (Product > Archive)"
print_message "3. ⏳ Valider l'archive (Organizer > Validate App)"
print_message "4. ⏳ Upload vers App Store Connect"
print_message "5. ⏳ Configurer les métadonnées"
print_message "6. ⏳ Soumettre pour révision Apple"
else
print_message "Prochaines étapes :"
print_message "1. Ouvrir Xcode : open ios/Runner.xcworkspace"
print_message "2. Créer l'archive : Product > Archive"
print_message "3. Upload vers App Store Connect"
fi
echo
print_message "Documentation :"
print_message " - BUILD-IOS-SUCCESS.md (guide complet)"
print_message " - SOLUTION-IOS.md (détails de la solution)"
print_message " - SCRIPTS-IOS.md (documentation des scripts)"
echo
print_success "Script terminé !"
echo
# Afficher un résumé des fichiers importants
print_message "Fichiers générés :"
print_message " - Runner.app : build/ios/iphoneos/Runner.app"
if [ -d "build/ios/archive" ]; then
print_message " - Archive : build/ios/archive/ (si créée)"
fi
echo

View File

@@ -1,125 +0,0 @@
#!/bin/bash
# Script de réinitialisation complète pour résoudre les problèmes de compilation iOS
# Spécialement conçu pour résoudre l'erreur "No such module 'Flutter'"
# Version 2.0 - Avec ajout automatique des chemins de recherche de frameworks
echo "🧹 Nettoyage complet de l'environnement iOS..."
# Se placer dans le répertoire du projet
cd "$(dirname "$0")"
# Supprimer les fichiers générés par Flutter
echo "📦 Nettoyage des fichiers Flutter..."
flutter clean
# Supprimer le cache pub
echo "🗑️ Suppression du cache pub pour les plugins problématiques..."
rm -rf ~/.pub-cache/hosted/pub.dev/connectivity_plus-*
# Supprimer les fichiers de CocoaPods
echo "🗂️ Nettoyage des fichiers CocoaPods..."
cd ios
rm -rf Pods
rm -rf .symlinks
rm -f Podfile.lock
rm -rf ~/Library/Developer/Xcode/DerivedData
# Supprimer le workspace Xcode (il sera recréé)
echo "🔄 Suppression du workspace Xcode..."
rm -rf Runner.xcworkspace
# Revenir au répertoire parent
cd ..
# Récupérer les dépendances Flutter
echo "📥 Récupération des dépendances Flutter..."
flutter pub get
# Régénérer les fichiers iOS
echo "🔨 Précaching des outils iOS..."
flutter precache --ios --force
# Forcer la génération des plugins
echo "🔌 Régénération des plugins..."
flutter pub cache repair
flutter pub get
# Réinstaller les pods avec des options supplémentaires
echo "📲 Réinstallation des pods..."
cd ios
pod deintegrate
pod cache clean --all
pod repo update
pod install --repo-update --verbose
# Ajouter automatiquement les chemins de recherche de frameworks
echo "🔍 Ajout des chemins de recherche de frameworks..."
# Créer un fichier temporaire pour stocker les chemins de recherche
cat > ios/add_framework_paths.rb << 'EOL'
#!/usr/bin/env ruby
require 'xcodeproj'
# Ouvrir le projet
project_path = 'Runner.xcodeproj'
project = Xcodeproj::Project.open(project_path)
# Trouver la cible Runner
target = project.targets.find { |t| t.name == 'Runner' }
# Parcourir toutes les configurations de build
target.build_configurations.each do |config|
# Obtenir les paramètres de build actuels
build_settings = config.build_settings
# Définir les chemins de recherche de frameworks
framework_search_paths = [
'$(inherited)',
'"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift"',
'"${PODS_CONFIGURATION_BUILD_DIR}/connectivity_plus"',
'"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation"',
'"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios"',
'"${PODS_ROOT}/Flutter"',
'"${PODS_XCFRAMEWORKS_BUILD_DIR}/Flutter"'
]
# Ajouter les chemins de recherche de frameworks
build_settings['FRAMEWORK_SEARCH_PATHS'] = framework_search_paths
# Ajouter les chemins de recherche d'en-têtes
header_search_paths = [
'$(inherited)',
'"${PODS_ROOT}/Flutter"',
'"${PODS_CONFIGURATION_BUILD_DIR}"'
]
build_settings['HEADER_SEARCH_PATHS'] = header_search_paths
# S'assurer que les modules sont activés
build_settings['DEFINES_MODULE'] = 'YES'
# Désactiver le bitcode
build_settings['ENABLE_BITCODE'] = 'NO'
# Inclure tous les assets d'icônes
build_settings['ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS'] = 'YES'
# Autres paramètres importants
build_settings['SWIFT_VERSION'] = '5.0'
build_settings['CLANG_ENABLE_MODULES'] = 'YES'
end
# Enregistrer les modifications
project.save
puts "✅ Chemins de recherche de frameworks ajoutés avec succès !"
EOL
# Exécuter le script Ruby pour ajouter les chemins de recherche
cd ios
ruby add_framework_paths.rb
cd ..
echo "✅ Réinitialisation iOS terminée ! Ouvrez le projet avec 'open ios/Runner.xcworkspace'"

View File

@@ -1,56 +0,0 @@
#!/bin/bash
# Script pour remplacer les fontSize hardcodés par AppTheme.r(context, X)
echo "🔧 Correction des fontSize hardcodés pour le responsive design..."
# Fonction pour traiter un fichier
fix_file() {
local file=$1
echo " Traitement de: $file"
# Vérifier si l'import AppTheme existe déjà
if ! grep -q "import 'package:geosector_app/core/theme/app_theme.dart';" "$file"; then
# Ajouter l'import après le premier import Flutter
sed -i "/^import 'package:flutter\//a import 'package:geosector_app/core/theme/app_theme.dart';" "$file"
fi
# Remplacer tous les fontSize: XX par fontSize: AppTheme.r(context, XX)
# Pattern pour fontSize: suivi d'un nombre
sed -i -E 's/fontSize: ([0-9]+(\.[0-9]+)?)/fontSize: AppTheme.r(context, \1)/g' "$file"
# Remplacer les const TextStyle qui contiennent fontSize
sed -i -E 's/const TextStyle\((.*fontSize: AppTheme\.r.*)\)/TextStyle(\1)/g' "$file"
}
# Fichiers prioritaires pour l'UI mobile
priority_files=(
"lib/presentation/widgets/passages/passage_form.dart"
"lib/presentation/widgets/passage_form_dialog.dart"
"lib/presentation/user/user_field_mode_page.dart"
"lib/presentation/user/user_dashboard_home_page.dart"
"lib/presentation/user/user_history_page.dart"
"lib/presentation/widgets/dashboard_layout.dart"
"lib/presentation/widgets/dashboard_app_bar.dart"
"lib/presentation/widgets/charts/payment_summary_card.dart"
"lib/presentation/widgets/charts/passage_summary_card.dart"
"lib/presentation/widgets/sector_distribution_card.dart"
)
# Traiter les fichiers prioritaires
echo "📱 Traitement des fichiers prioritaires pour mobile..."
for file in "${priority_files[@]}"; do
if [ -f "$file" ]; then
fix_file "$file"
else
echo " ⚠️ Fichier non trouvé: $file"
fi
done
echo "✅ Correction terminée!"
echo ""
echo "📊 Statistiques:"
echo " - Fichiers traités: ${#priority_files[@]}"
echo ""
echo "💡 Pour traiter TOUS les fichiers, exécutez:"
echo " find lib -name '*.dart' -exec grep -l 'fontSize: [0-9]' {} \; | while read f; do ./fix_responsive_fonts.sh \"\$f\"; done"

86
app/ios-build-mac.sh Executable file
View File

@@ -0,0 +1,86 @@
#!/bin/bash
# Script de build iOS sur Mac mini
# À exécuter sur macOS uniquement
# Usage: ./ios-build-mac.sh
set -e
# Couleurs pour les messages
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}=========================================${NC}"
echo -e "${BLUE} 🍎 Build iOS - GEOSECTOR${NC}"
echo -e "${BLUE}=========================================${NC}"
echo ""
# Vérifier que nous sommes sur macOS
if [[ "$OSTYPE" != "darwin"* ]]; then
echo -e "${RED}❌ Erreur: Ce script doit être exécuté sur macOS${NC}"
exit 1
fi
# Vérifier que nous sommes dans le bon dossier
if [ ! -f "pubspec.yaml" ]; then
echo -e "${RED}❌ Erreur: Ce script doit être exécuté depuis le dossier racine de l'application Flutter${NC}"
echo -e "${RED}Fichier pubspec.yaml introuvable${NC}"
exit 1
fi
# Récupérer la version depuis pubspec.yaml
VERSION=$(grep "^version:" pubspec.yaml | sed 's/version: //' | tr -d ' ')
echo -e "${YELLOW}📦 Version détectée :${NC} $VERSION"
echo ""
# Étape 1 : Clean
echo -e "${YELLOW}🧹 Étape 1/5 : Nettoyage du projet...${NC}"
flutter clean
echo -e "${GREEN}✓ Nettoyage terminé${NC}"
echo ""
# Étape 2 : Pub get
echo -e "${YELLOW}📥 Étape 2/5 : Récupération des dépendances Flutter...${NC}"
flutter pub get
echo -e "${GREEN}✓ Dépendances récupérées${NC}"
echo ""
# Étape 3 : Pod install
echo -e "${YELLOW}🔧 Étape 3/5 : Installation des CocoaPods...${NC}"
cd ios
rm -rf Pods Podfile.lock
pod install --repo-update
cd ..
echo -e "${GREEN}✓ CocoaPods installés${NC}"
echo ""
# Étape 4 : Build iOS Release
echo -e "${YELLOW}🏗️ Étape 4/5 : Compilation iOS en mode release...${NC}"
flutter build ios --release
echo -e "${GREEN}✓ Compilation terminée${NC}"
echo ""
# Étape 5 : Ouvrir Xcode
echo -e "${YELLOW}📱 Étape 5/5 : Ouverture de Xcode...${NC}"
echo ""
echo -e "${BLUE}=========================================${NC}"
echo -e "${GREEN} ✓ Préparation terminée !${NC}"
echo -e "${BLUE}=========================================${NC}"
echo ""
echo -e "${YELLOW}📋 Prochaines étapes dans Xcode :${NC}"
echo " 1. ⏳ Attendre le chargement complet de Xcode"
echo " 2. ✅ Vérifier Signing & Capabilities (Team: 6WT84NWCTC)"
echo " 3. 🧹 Product > Clean Build Folder (Cmd+Shift+K)"
echo " 4. 📦 Product > Archive"
echo " 5. ⏳ Attendre l'archive (5-10 minutes)"
echo " 6. 📤 Organizer > Distribute App > App Store Connect"
echo ""
# Ouvrir Xcode avec le workspace
open ios/Runner.xcworkspace
echo -e "${GREEN}🚀 Xcode ouvert !${NC}"
echo ""

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store</string>
<key>teamID</key>
<string>6WT84NWCTC</string>
<key>uploadBitcode</key>
<false/>
<key>uploadSymbols</key>
<true/>
<key>compileBitcode</key>
<false/>
<key>signingStyle</key>
<string>automatic</string>
<key>destination</key>
<string>upload</string>
<key>provisioningProfiles</key>
<dict>
<key>fr.geosector.app3</key>
<string>match AppStore fr.geosector.app3</string>
</dict>
</dict>
</plist>

2
app/ios/Flutter/AppFrameworkInfo.plist Executable file → Normal file
View File

@@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
<string>13.0</string>
</dict>
</plist>

2
app/ios/Flutter/Debug.xcconfig Executable file → Normal file
View File

@@ -1,2 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"

2
app/ios/Flutter/Release.xcconfig Executable file → Normal file
View File

@@ -1,2 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"

39
app/ios/Podfile Executable file → Normal file
View File

@@ -1,10 +1,6 @@
# Uncomment this line to define a global platform for your project
# Spécifier la version minimale d'iOS pour Stripe Tap to Pay
platform :ios, '15.4'
# Ignorer les avertissements des pods
install! 'cocoapods', :warn_for_unused_master_specs_repo => false
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@@ -32,11 +28,8 @@ require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelpe
flutter_ios_podfile_setup
target 'Runner' do
# Utiliser les frameworks dynamiques
use_frameworks!
# Désactiver les en-têtes modulaires pour éviter les conflits
# use_modular_headers!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
@@ -45,37 +38,11 @@ target 'Runner' do
end
post_install do |installer|
# Configuration post-installation
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
# Maintenir la version minimale iOS 15.4 pour Stripe Tap to Pay
# Ensure deployment target is set to 15.4
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.4'
# Désactiver Bitcode (recommandé par Flutter)
config.build_settings['ENABLE_BITCODE'] = 'NO'
# Paramètres pour la compatibilité avec Xcode récent
config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
config.build_settings['CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER'] = 'NO'
# Paramètres pour éviter les erreurs de module
config.build_settings['DEFINES_MODULE'] = 'YES'
config.build_settings['SWIFT_VERSION'] = '5.0'
# Désactiver le support Mac Catalyst
config.build_settings['SUPPORTS_MACCATALYST'] = 'NO'
# Paramètres de signature de code
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
# Ajout des permissions de géolocalisation
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_LOCATION=1',
]
end
end
# Flutter post install
flutter_post_install(installer) if defined?(flutter_post_install)
end

141
app/ios/Podfile.lock Executable file → Normal file
View File

@@ -1,42 +1,167 @@
PODS:
- battery_plus (1.0.0):
- Flutter
- connectivity_plus (0.0.1):
- Flutter
- ReachabilitySwift
- FlutterMacOS
- device_info_plus (0.0.1):
- Flutter
- Flutter (1.0.0)
- flutter_local_notifications (0.0.1):
- Flutter
- geolocator_apple (1.2.0):
- Flutter
- FlutterMacOS
- image_picker_ios (0.0.1):
- Flutter
- mek_stripe_terminal (1.0.0):
- Flutter
- StripeTerminal (~> 4.6.0)
- nfc_manager (0.0.1):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- ReachabilitySwift (5.2.4)
- permission_handler_apple (9.3.0):
- Flutter
- Stripe (24.7.0):
- StripeApplePay (= 24.7.0)
- StripeCore (= 24.7.0)
- StripePayments (= 24.7.0)
- StripePaymentsUI (= 24.7.0)
- StripeUICore (= 24.7.0)
- stripe_ios (0.0.1):
- Flutter
- Stripe (~> 24.7.0)
- stripe_ios/stripe_ios (= 0.0.1)
- stripe_ios/stripe_objc (= 0.0.1)
- StripeApplePay (~> 24.7.0)
- StripeFinancialConnections (~> 24.7.0)
- StripePayments (~> 24.7.0)
- StripePaymentSheet (~> 24.7.0)
- StripePaymentsUI (~> 24.7.0)
- stripe_ios/stripe_ios (0.0.1):
- Flutter
- Stripe (~> 24.7.0)
- stripe_ios/stripe_objc
- StripeApplePay (~> 24.7.0)
- StripeFinancialConnections (~> 24.7.0)
- StripePayments (~> 24.7.0)
- StripePaymentSheet (~> 24.7.0)
- StripePaymentsUI (~> 24.7.0)
- stripe_ios/stripe_objc (0.0.1):
- Flutter
- Stripe (~> 24.7.0)
- StripeApplePay (~> 24.7.0)
- StripeFinancialConnections (~> 24.7.0)
- StripePayments (~> 24.7.0)
- StripePaymentSheet (~> 24.7.0)
- StripePaymentsUI (~> 24.7.0)
- StripeApplePay (24.7.0):
- StripeCore (= 24.7.0)
- StripeCore (24.7.0)
- StripeFinancialConnections (24.7.0):
- StripeCore (= 24.7.0)
- StripeUICore (= 24.7.0)
- StripePayments (24.7.0):
- StripeCore (= 24.7.0)
- StripePayments/Stripe3DS2 (= 24.7.0)
- StripePayments/Stripe3DS2 (24.7.0):
- StripeCore (= 24.7.0)
- StripePaymentSheet (24.7.0):
- StripeApplePay (= 24.7.0)
- StripeCore (= 24.7.0)
- StripePayments (= 24.7.0)
- StripePaymentsUI (= 24.7.0)
- StripePaymentsUI (24.7.0):
- StripeCore (= 24.7.0)
- StripePayments (= 24.7.0)
- StripeUICore (= 24.7.0)
- StripeTerminal (4.6.1)
- StripeUICore (24.7.0):
- StripeCore (= 24.7.0)
- url_launcher_ios (0.0.1):
- Flutter
DEPENDENCIES:
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- battery_plus (from `.symlinks/plugins/battery_plus/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- Flutter (from `Flutter`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- mek_stripe_terminal (from `.symlinks/plugins/mek_stripe_terminal/ios`)
- nfc_manager (from `.symlinks/plugins/nfc_manager/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- stripe_ios (from `.symlinks/plugins/stripe_ios/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
SPEC REPOS:
trunk:
- ReachabilitySwift
- Stripe
- StripeApplePay
- StripeCore
- StripeFinancialConnections
- StripePayments
- StripePaymentSheet
- StripePaymentsUI
- StripeTerminal
- StripeUICore
EXTERNAL SOURCES:
battery_plus:
:path: ".symlinks/plugins/battery_plus/ios"
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/ios"
:path: ".symlinks/plugins/connectivity_plus/darwin"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
Flutter:
:path: Flutter
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
geolocator_apple:
:path: ".symlinks/plugins/geolocator_apple/darwin"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
mek_stripe_terminal:
:path: ".symlinks/plugins/mek_stripe_terminal/ios"
nfc_manager:
:path: ".symlinks/plugins/nfc_manager/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
stripe_ios:
:path: ".symlinks/plugins/stripe_ios/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
connectivity_plus: 481668c94744c30c53b8895afb39159d1e619bdf
battery_plus: 8df26ad5ade26110b2d22a4d1f582b5926983023
connectivity_plus: 3f6c9057f4cd64198dc826edfb0542892f825343
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
mek_stripe_terminal: d317573feabf753651c1c184c2dae07950d50030
nfc_manager: 9c40fe22528ab871ca11e52ea8b95790e9d92ca2
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
Stripe: 8a03a78bfa16b197f9fac51e42670ac563b34388
stripe_ios: 95bdf6ba58efd184fe1dfed194cd8692299d66ca
StripeApplePay: 3c1b43d9b5130f6b714863bf8c9482c24168ab27
StripeCore: 4955c2af14446db04818ad043d19d8f97b73c5fa
StripeFinancialConnections: 8cf97b04c2f354879a2a5473126efac38f11f406
StripePayments: 91820845bece6117809bcfdcaef39c84c2b4cae5
StripePaymentSheet: 1810187cbdbc73410b8fb86cecafaaa41c1481fc
StripePaymentsUI: 326376e23caa369d1f58041bdb858c89c2b17ed4
StripeTerminal: 542aee71cf148da0d30cf1a67bf19e8bf4e06567
StripeUICore: 17a4f3adb81ae05ab885e1b353022a430176eab1
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
PODFILE CHECKSUM: f0d28569a754ac33c3d750271af244edf72e3a3c
PODFILE CHECKSUM: 62c14ad6fe47d35b1a09046784d2f3034dea7052
COCOAPODS: 1.16.2

284
app/ios/Runner.xcodeproj/project.pbxproj Executable file → Normal file
View File

@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 77;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -11,11 +11,11 @@
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
7F9A286C388770C426158ACA /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9685746E8B2BFB310F37A783 /* Pods_Runner.framework */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
B29AD2EBEFD19B161772B50D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54642C142BC98D17D428B51D /* Pods_Runner.framework */; };
C89DA9B9EA30824E0E881287 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3EE1328CE0A8907C5568E72D /* Pods_RunnerTests.framework */; };
C47FDF143A48CF459008F277 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6A2D518FE9E5AF415867B67C /* Pods_RunnerTests.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -42,20 +42,21 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
132FE5584808793FE93F08F5 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
0AB6F48D965FD356477FE8F7 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
21F13E510138E0DBAAA0667E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3DE8EBA41425E2A096EE70CF /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
3EE1328CE0A8907C5568E72D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
54642C142BC98D17D428B51D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3C7D27EAD136F75B1735A6C1 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
465E7BC8117C45483EB85E62 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
61B200C4FE493211C62FB4B9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
6A2D518FE9E5AF415867B67C /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6B753299A1F44B3313BA8EFB /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
8814F9792D6E6BA0874B431C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
9685746E8B2BFB310F37A783 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -63,24 +64,23 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
CE8A95C455B844D61A15C99F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
FE152E3AEF93B264AE11B5E9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
C13B6CB89EDF19948426622C /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
9491A6C7DD10151C405FF968 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C89DA9B9EA30824E0E881287 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B29AD2EBEFD19B161772B50D /* Pods_Runner.framework in Frameworks */,
7F9A286C388770C426158ACA /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A33E0317BC5C498C4D1CF271 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C47FDF143A48CF459008F277 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -95,11 +95,24 @@
path = RunnerTests;
sourceTree = "<group>";
};
5301A26C8AA9F29008B3D808 /* Frameworks */ = {
5224E5B570644CF7707258CD /* Pods */ = {
isa = PBXGroup;
children = (
54642C142BC98D17D428B51D /* Pods_Runner.framework */,
3EE1328CE0A8907C5568E72D /* Pods_RunnerTests.framework */,
61B200C4FE493211C62FB4B9 /* Pods-Runner.debug.xcconfig */,
6B753299A1F44B3313BA8EFB /* Pods-Runner.release.xcconfig */,
3C7D27EAD136F75B1735A6C1 /* Pods-Runner.profile.xcconfig */,
465E7BC8117C45483EB85E62 /* Pods-RunnerTests.debug.xcconfig */,
C13B6CB89EDF19948426622C /* Pods-RunnerTests.release.xcconfig */,
0AB6F48D965FD356477FE8F7 /* Pods-RunnerTests.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
6AC50F3FC13928204FBA79C5 /* Frameworks */ = {
isa = PBXGroup;
children = (
9685746E8B2BFB310F37A783 /* Pods_Runner.framework */,
6A2D518FE9E5AF415867B67C /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -122,12 +135,10 @@
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
C67A4583967DEDA799C193DE /* Pods */,
5301A26C8AA9F29008B3D808 /* Frameworks */,
5224E5B570644CF7707258CD /* Pods */,
6AC50F3FC13928204FBA79C5 /* Frameworks */,
);
indentWidth = 2;
sourceTree = "<group>";
tabWidth = 2;
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
@@ -153,19 +164,6 @@
path = Runner;
sourceTree = "<group>";
};
C67A4583967DEDA799C193DE /* Pods */ = {
isa = PBXGroup;
children = (
8814F9792D6E6BA0874B431C /* Pods-Runner.debug.xcconfig */,
CE8A95C455B844D61A15C99F /* Pods-Runner.release.xcconfig */,
FE152E3AEF93B264AE11B5E9 /* Pods-Runner.profile.xcconfig */,
3DE8EBA41425E2A096EE70CF /* Pods-RunnerTests.debug.xcconfig */,
21F13E510138E0DBAAA0667E /* Pods-RunnerTests.release.xcconfig */,
132FE5584808793FE93F08F5 /* Pods-RunnerTests.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -173,10 +171,10 @@
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
04F44EDE70DDFF90BCE6241F /* [CP] Check Pods Manifest.lock */,
AC35C06ABD05264E158EC2C7 /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
9491A6C7DD10151C405FF968 /* Frameworks */,
A33E0317BC5C498C4D1CF271 /* Frameworks */,
);
buildRules = (
);
@@ -192,14 +190,15 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9413D06037CA6133CC0A13EB /* [CP] Check Pods Manifest.lock */,
0AD717A1EA4180F712263B0A /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
625AB1A439E96A5838DD474D /* [CP] Embed Pods Frameworks */,
BA9DC1BD724AE56F0A35BA5C /* [CP] Embed Pods Frameworks */,
6DEDB6ADD72C98843E973926 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -217,7 +216,7 @@
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1630;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
@@ -231,6 +230,7 @@
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
@@ -238,7 +238,6 @@
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
preferredProjectObjectVersion = 77;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -271,7 +270,7 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
04F44EDE70DDFF90BCE6241F /* [CP] Check Pods Manifest.lock */ = {
0AD717A1EA4180F712263B0A /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -286,7 +285,7 @@
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -309,43 +308,21 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
625AB1A439E96A5838DD474D /* [CP] Embed Pods Frameworks */ = {
6DEDB6ADD72C98843E973926 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9413D06037CA6133CC0A13EB /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
@@ -363,6 +340,45 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
AC35C06ABD05264E158EC2C7 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
BA9DC1BD724AE56F0A35BA5C /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -471,57 +487,40 @@
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = AppIcon;
CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 6WT84NWCTC;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 6WT84NWCTC;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/connectivity_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios\"",
"\"${PODS_ROOT}/Flutter\"",
"\"${PODS_XCFRAMEWORKS_BUILD_DIR}/Flutter\"",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_ROOT}/Flutter\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}\"",
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = GEOSECTOR;
INFOPLIST_KEY_CFBundleDisplayName = "GeoSector v3";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.business";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.2.1;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app2;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app3;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "GeoSector v3 App Store";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3DE8EBA41425E2A096EE70CF /* Pods-RunnerTests.debug.xcconfig */;
baseConfigurationReference = 465E7BC8117C45483EB85E62 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app2.RunnerTests;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app3.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -532,14 +531,14 @@
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 21F13E510138E0DBAAA0667E /* Pods-RunnerTests.release.xcconfig */;
baseConfigurationReference = C13B6CB89EDF19948426622C /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app2.RunnerTests;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app3.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -548,14 +547,14 @@
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 132FE5584808793FE93F08F5 /* Pods-RunnerTests.profile.xcconfig */;
baseConfigurationReference = 0AB6F48D965FD356477FE8F7 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app2.RunnerTests;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app3.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -680,44 +679,27 @@
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = AppIcon;
CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 6WT84NWCTC;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 6WT84NWCTC;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/connectivity_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios\"",
"\"${PODS_ROOT}/Flutter\"",
"\"${PODS_XCFRAMEWORKS_BUILD_DIR}/Flutter\"",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_ROOT}/Flutter\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}\"",
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = GEOSECTOR;
INFOPLIST_KEY_CFBundleDisplayName = "GeoSector v3";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.business";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.2.1;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app2;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app3;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "GeoSector v3 App Store";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
@@ -727,50 +709,26 @@
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = AppIcon;
CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 6WT84NWCTC;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 6WT84NWCTC;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/connectivity_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios\"",
"\"${PODS_ROOT}/Flutter\"",
"\"${PODS_XCFRAMEWORKS_BUILD_DIR}/Flutter\"",
);
"FRAMEWORK_SEARCH_PATHS[arch=*]" = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/connectivity_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_ios\"",
);
HEADER_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_ROOT}/Flutter\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}\"",
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = GEOSECTOR;
INFOPLIST_KEY_CFBundleDisplayName = "GeoSector v3";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.business";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 0.2.1;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app2;
PRODUCT_BUNDLE_IDENTIFIER = fr.geosector.app3;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "GeoSector v3 App Store";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;

0
app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata generated Executable file → Normal file
View File

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1630"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
@@ -54,6 +55,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

0
app/ios/Runner.xcworkspace/contents.xcworkspacedata generated Executable file → Normal file
View File

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

0
app/ios/Runner/AppDelegate.swift Executable file → Normal file
View File

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Some files were not shown because too many files have changed in this diff Show More