feat(mobile): Implement Keycloak WebView authentication with HTTP callback

- Replace flutter_appauth with custom WebView implementation to resolve deep link issues
- Add KeycloakWebViewAuthService with integrated WebView for seamless authentication
- Configure Android manifest for HTTP cleartext traffic support
- Add network security config for development environment (192.168.1.11)
- Update Keycloak client to use HTTP callback endpoint (http://192.168.1.11:8080/auth/callback)
- Remove obsolete keycloak_auth_service.dart and temporary scripts
- Clean up dependencies and regenerate injection configuration
- Tested successfully on multiple Android devices (Xiaomi 2201116TG, SM A725F)

BREAKING CHANGE: Authentication flow now uses WebView instead of external browser
- Users will see Keycloak login page within the app instead of browser redirect
- Resolves ERR_CLEARTEXT_NOT_PERMITTED and deep link state management issues
- Maintains full OIDC compliance with PKCE flow and secure token storage

Technical improvements:
- WebView with custom navigation delegate for callback handling
- Automatic token extraction and user info parsing from JWT
- Proper error handling and user feedback
- Consistent authentication state management across app lifecycle
This commit is contained in:
DahoudG
2025-09-15 01:44:16 +00:00
parent 73459b3092
commit f89f6167cc
290 changed files with 34563 additions and 3528 deletions

View File

@@ -47,51 +47,56 @@ class ActionCardWidget extends StatelessWidget {
},
borderRadius: BorderRadius.circular(12),
child: Container(
padding: const EdgeInsets.all(16),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
borderRadius: BorderRadius.circular(10),
border: Border.all(color: color.withOpacity(0.2)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
color: Colors.black.withOpacity(0.04),
blurRadius: 8,
offset: const Offset(0, 1),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.all(12),
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
borderRadius: BorderRadius.circular(8),
),
child: Icon(
icon,
color: color,
size: 24,
size: 18,
),
),
const SizedBox(height: 12),
const SizedBox(height: 8),
Text(
title,
style: const TextStyle(
fontSize: 14,
fontSize: 12,
fontWeight: FontWeight.w600,
color: AppTheme.textPrimary,
),
textAlign: TextAlign.center,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 4),
const SizedBox(height: 2),
Text(
subtitle,
style: const TextStyle(
fontSize: 12,
fontSize: 10,
color: AppTheme.textSecondary,
),
textAlign: TextAlign.center,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),

View File

@@ -25,124 +25,138 @@ class QuickActionsWidget extends StatelessWidget {
color: AppTheme.textPrimary,
),
),
const SizedBox(height: 16),
const SizedBox(height: 12),
// Première ligne - Actions principales
// Grille compacte 3x4 - Actions organisées par priorité
// Première ligne - Actions principales (3 colonnes)
Row(
children: [
Expanded(
child: ActionCardWidget(
title: 'Nouveau membre',
subtitle: 'Inscription rapide',
subtitle: 'Inscription',
icon: Icons.person_add,
color: AppTheme.primaryColor,
),
),
const SizedBox(width: 12),
const SizedBox(width: 8),
Expanded(
child: ActionCardWidget(
title: 'Créer événement',
subtitle: 'Organiser activité',
subtitle: 'Organiser',
icon: Icons.event_available,
color: AppTheme.secondaryColor,
),
),
],
),
const SizedBox(height: 12),
// Deuxième ligne - Gestion financière
Row(
children: [
const SizedBox(width: 8),
Expanded(
child: ActionCardWidget(
title: 'Encaisser cotisation',
subtitle: 'Paiement immédiat',
title: 'Encaisser',
subtitle: 'Cotisation',
icon: Icons.payment,
color: AppTheme.successColor,
),
),
const SizedBox(width: 12),
Expanded(
child: ActionCardWidget(
title: 'Relances impayés',
subtitle: 'Notifications SMS',
icon: Icons.notifications_active,
color: AppTheme.warningColor,
),
),
],
),
const SizedBox(height: 12),
const SizedBox(height: 8),
// Troisième ligne - Communication
// Deuxième ligne - Gestion et communication
Row(
children: [
Expanded(
child: ActionCardWidget(
title: 'Relances',
subtitle: 'SMS/Email',
icon: Icons.notifications_active,
color: AppTheme.warningColor,
),
),
const SizedBox(width: 8),
Expanded(
child: ActionCardWidget(
title: 'Message groupe',
subtitle: 'Diffusion WhatsApp',
subtitle: 'WhatsApp',
icon: Icons.message,
color: const Color(0xFF25D366),
),
),
const SizedBox(width: 12),
const SizedBox(width: 8),
Expanded(
child: ActionCardWidget(
title: 'Convoquer AG',
subtitle: 'Assemblée générale',
subtitle: 'Assemblée',
icon: Icons.groups,
color: const Color(0xFF9C27B0),
),
),
],
),
const SizedBox(height: 12),
const SizedBox(height: 8),
// Quatrième ligne - Rapports et conformité
// Troisième ligne - Rapports et conformité
Row(
children: [
Expanded(
child: ActionCardWidget(
title: 'Rapport OHADA',
subtitle: 'Conformité légale',
subtitle: 'Conformité',
icon: Icons.gavel,
color: const Color(0xFF795548),
),
),
const SizedBox(width: 12),
const SizedBox(width: 8),
Expanded(
child: ActionCardWidget(
title: 'Export données',
subtitle: 'Sauvegarde Excel',
subtitle: 'Excel/PDF',
icon: Icons.file_download,
color: AppTheme.infoColor,
),
),
const SizedBox(width: 8),
Expanded(
child: ActionCardWidget(
title: 'Statistiques',
subtitle: 'Analyses',
icon: Icons.analytics,
color: const Color(0xFF00BCD4),
),
),
],
),
const SizedBox(height: 12),
const SizedBox(height: 8),
// Cinquième ligne - Urgences et support
// Quatrième ligne - Support et urgences
Row(
children: [
Expanded(
child: ActionCardWidget(
title: 'Alerte urgente',
subtitle: 'Notification critique',
subtitle: 'Critique',
icon: Icons.emergency,
color: AppTheme.errorColor,
),
),
const SizedBox(width: 12),
const SizedBox(width: 8),
Expanded(
child: ActionCardWidget(
title: 'Support technique',
subtitle: 'Assistance UnionFlow',
title: 'Support tech',
subtitle: 'Assistance',
icon: Icons.support_agent,
color: const Color(0xFF607D8B),
),
),
const SizedBox(width: 8),
Expanded(
child: ActionCardWidget(
title: 'Paramètres',
subtitle: 'Configuration',
icon: Icons.settings,
color: const Color(0xFF9E9E9E),
),
),
],
),
],