Amélioration de la splash_page et du login

This commit is contained in:
d6soft
2025-06-04 16:51:40 +02:00
parent 8c9e9a21c4
commit 41f1db1169
228 changed files with 366459 additions and 6183 deletions

View File

@@ -1,9 +1,7 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:geosector_app/core/repositories/user_repository.dart';
import 'package:geosector_app/core/theme/app_theme.dart';
import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales
import 'package:geosector_app/core/services/app_info_service.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/core/data/models/user_model.dart';
import 'package:geosector_app/core/data/models/amicale_model.dart';
@@ -15,10 +13,11 @@ import 'package:geosector_app/core/data/models/membre_model.dart';
import 'package:geosector_app/core/data/models/user_sector_model.dart';
import 'package:geosector_app/chat/models/conversation_model.dart';
import 'package:geosector_app/chat/models/message_model.dart';
import 'package:geosector_app/core/services/hive_reset_state_service.dart';
import 'package:geosector_app/presentation/widgets/clear_cache_dialog.dart';
import 'dart:async';
import 'dart:math' as math;
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
class SplashPage extends StatefulWidget {
const SplashPage({super.key});
@@ -58,12 +57,28 @@ class _SplashPageState extends State<SplashPage>
String _statusMessage = "Initialisation...";
double _progress = 0.0;
bool _showButtons = false;
String _appVersion = '';
final List<String> _initializationSteps = [
"Initialisation des services...",
"Vérification de l'authentification...",
"Chargement des données..."
];
Future<void> _getAppVersion() async {
try {
final packageInfo = await PackageInfo.fromPlatform();
if (mounted) {
setState(() {
_appVersion = packageInfo.version;
});
}
} catch (e) {
debugPrint('Erreur lors de la récupération de la version: $e');
// Fallback sur la version du AppInfoService si elle existe
if (mounted) {
setState(() {
_appVersion = AppInfoService.fullVersion
.split(' ')
.last; // Extraire juste le numéro
});
}
}
}
@override
void initState() {
@@ -89,33 +104,12 @@ class _SplashPageState extends State<SplashPage>
// Démarrer l'animation immédiatement
_animationController.forward();
// Vérifier si Hive a été réinitialisé
_checkHiveReset();
_getAppVersion();
// Simuler le processus d'initialisation
_startInitialization();
}
// Méthode pour vérifier si Hive a été réinitialisé et afficher le dialogue si nécessaire
void _checkHiveReset() {
// Vérifier si Hive a été réinitialisé et si le dialogue n'a pas encore été affiché
if (hiveResetStateService.wasReset && !hiveResetStateService.dialogShown) {
// Attendre que le widget soit complètement construit
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
// Afficher le dialogue de nettoyage du cache
ClearCacheDialog.show(
context,
onClose: () {
// Marquer le dialogue comme ayant été affiché
hiveResetStateService.markDialogAsShown();
},
);
}
});
}
}
@override
void dispose() {
_animationController.dispose();
@@ -123,11 +117,11 @@ class _SplashPageState extends State<SplashPage>
}
void _startInitialization() async {
// Étape 1: Initialisation des services
// Étape 1: Initialisation des boîtes Hive (0% à 75%)
if (mounted) {
setState(() {
_statusMessage = _initializationSteps[0];
_progress = 0.2;
_statusMessage = "Initialisation des données...";
_progress = 0.0;
});
}
@@ -135,20 +129,11 @@ class _SplashPageState extends State<SplashPage>
await _initializeAllHiveBoxes();
await Future.delayed(const Duration(milliseconds: 500));
// Étape 2: Vérification de l'authentification
// Étape 2: Initialisation des services (75% à 100%)
if (mounted) {
setState(() {
_statusMessage = _initializationSteps[1];
_progress = 0.4;
});
}
await Future.delayed(const Duration(milliseconds: 500));
// Étape 3: Chargement des données
if (mounted) {
setState(() {
_statusMessage = _initializationSteps[2];
_progress = 1.0; // Directement à 100% après la 3ème étape
_statusMessage = "Préparation de l'application...";
_progress = 0.75;
});
}
await Future.delayed(const Duration(milliseconds: 500));
@@ -157,15 +142,8 @@ class _SplashPageState extends State<SplashPage>
setState(() {
_isInitializing = false;
_showButtons = true;
_progress = 1.0; // S'assurer que la barre est à 100%
});
// Attendre quelques secondes avant de rediriger automatiquement
// si l'utilisateur est déjà connecté
if (userRepository.isLoggedIn) {
Timer(const Duration(seconds: 2), () {
_redirectToAppropriateScreen();
});
}
}
}
@@ -202,8 +180,8 @@ class _SplashPageState extends State<SplashPage>
},
];
// Calculer l'incrément de progression pour chaque boîte
final progressIncrement = 0.2 / boxesToOpen.length;
// Calculer l'incrément de progression pour chaque boîte (0.75 / nombre de boîtes)
final progressIncrement = 0.75 / boxesToOpen.length;
double currentProgress = 0.0;
// Ouvrir chaque boîte si elle n'est pas déjà ouverte
@@ -212,12 +190,11 @@ class _SplashPageState extends State<SplashPage>
final displayName = boxesToOpen[i]['display'] as String;
// Mettre à jour la barre de progression et le message
currentProgress += progressIncrement;
currentProgress = progressIncrement * (i + 1);
if (mounted) {
setState(() {
_statusMessage = displayName;
_progress =
0.2 * (currentProgress / 0.2); // Normaliser entre 0 et 0.2
_progress = currentProgress;
});
}
@@ -266,10 +243,27 @@ class _SplashPageState extends State<SplashPage>
if (mounted) {
setState(() {
_statusMessage = 'Toutes les boîtes sont prêtes';
_progress = 0.2;
_progress = 0.8;
});
await Future.delayed(const Duration(milliseconds: 500));
}
if (mounted) {
setState(() {
_statusMessage = "Préparation de l'application...";
_progress = 0.9;
});
await Future.delayed(const Duration(milliseconds: 500));
}
// Finalisation
if (mounted) {
setState(() {
_isInitializing = false;
_showButtons = true;
_progress = 1.0;
});
}
debugPrint('Toutes les boîtes Hive sont maintenant ouvertes');
} catch (e) {
debugPrint('Erreur lors de l\'initialisation des boîtes Hive: $e');
@@ -283,33 +277,9 @@ class _SplashPageState extends State<SplashPage>
}
}
void _redirectToAppropriateScreen() {
if (!mounted) return;
// Utiliser l'instance globale de userRepository définie dans app.dart
if (userRepository.isLoggedIn) {
debugPrint('SplashPage: Redirection d\'utilisateur connecté');
// Récupérer directement le rôle utilisateur
final roleValue = userRepository.getUserRole();
debugPrint('SplashPage: Rôle utilisateur = $roleValue');
// Redirection simple basée sur le rôle
if (roleValue > 1) {
debugPrint('SplashPage: Redirection vers /admin (rôle $roleValue > 1)');
context.go('/admin');
} else {
debugPrint('SplashPage: Redirection vers /user (rôle $roleValue = 1)');
context.go('/user');
}
}
// Ne redirige plus vers la landing page
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final size = MediaQuery.of(context).size;
return Scaffold(
body: Stack(
@@ -424,7 +394,8 @@ class _SplashPageState extends State<SplashPage>
duration: const Duration(milliseconds: 500),
child: ElevatedButton(
onPressed: () {
context.go('/login', extra: {'type': 'user'});
context.go(
'/login/user'); // Utiliser la route spécifique
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
@@ -449,13 +420,14 @@ class _SplashPageState extends State<SplashPage>
),
const SizedBox(height: 16),
// Bouton Connexion Administrateur
// Bouton Connexion Administrateur
AnimatedOpacity(
opacity: _showButtons ? 1.0 : 0.0,
duration: const Duration(milliseconds: 500),
child: ElevatedButton(
onPressed: () {
context.go('/login', extra: {'type': 'admin'});
context.go(
'/login/admin'); // Utiliser la route spécifique
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
@@ -479,18 +451,74 @@ class _SplashPageState extends State<SplashPage>
),
),
const SizedBox(height: 16),
const SizedBox(
height: 32), // 2 espaces sous le bouton précédent
// Lien d'inscription
// Bouton d'inscription
AnimatedOpacity(
opacity: _showButtons ? 1.0 : 0.0,
duration: const Duration(milliseconds: 500),
child: TextButton(
child: ElevatedButton(
onPressed: () {
context.go('/register');
},
child: Text(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 40,
vertical: 16,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
elevation: 2,
),
child: const Text(
'Pas encore inscrit ?',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(height: 16),
// Lien vers le site web
AnimatedOpacity(
opacity: _showButtons ? 1.0 : 0.0,
duration: const Duration(milliseconds: 500),
child: TextButton.icon(
onPressed: () {
// Déterminer l'URL du site web en fonction de l'environnement
String webUrl = 'https://geosector.fr';
if (kIsWeb) {
final host = Uri.base.host;
if (host.startsWith('dapp.')) {
webUrl = 'https://dev.geosector.fr';
} else if (host.startsWith('rapp.')) {
webUrl = 'https://rec.geosector.fr';
} else if (host.startsWith('app.')) {
webUrl = 'https://geosector.fr';
}
}
// Ouvrir l'URL dans une nouvelle fenêtre/onglet
launchUrl(
Uri.parse(webUrl),
mode: LaunchMode.externalApplication,
);
},
icon: Icon(
Icons.language,
size: 18,
color: theme.colorScheme.primary,
),
label: Text(
'Site web Geosector',
style: TextStyle(
color: theme.colorScheme.primary,
fontWeight: FontWeight.w500,
@@ -506,6 +534,38 @@ class _SplashPageState extends State<SplashPage>
),
),
),
// Badge de version en bas à droite
if (_appVersion.isNotEmpty)
Positioned(
bottom: 16,
right: 16,
child: AnimatedOpacity(
opacity: _showButtons ? 0.7 : 0.5,
duration: const Duration(milliseconds: 500),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 4,
),
decoration: BoxDecoration(
color: theme.colorScheme.primary.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: theme.colorScheme.primary,
width: 1,
),
),
child: Text(
'v$_appVersion',
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.primary,
fontSize: 10,
fontWeight: FontWeight.w500,
),
),
),
),
),
],
),
);