## Corrections Critiques ### Race Condition - Statuts de Messages - Fix : Les icônes de statut (✓, ✓✓, ✓✓ bleu) ne s'affichaient pas - Cause : WebSocket delivery confirmations arrivaient avant messages locaux - Solution : Pattern Optimistic UI dans chat_bloc.dart - Création message temporaire immédiate - Ajout à la liste AVANT requête HTTP - Remplacement par message serveur à la réponse - Fichier : lib/presentation/state_management/chat_bloc.dart ## Implémentation TODOs (13/21) ### Social (social_header_widget.dart) - ✅ Copier lien du post dans presse-papiers - ✅ Partage natif via Share.share() - ✅ Dialogue de signalement avec 5 raisons ### Partage (share_post_dialog.dart) - ✅ Interface sélection d'amis avec checkboxes - ✅ Partage externe via Share API ### Média (media_upload_service.dart) - ✅ Parsing JSON réponse backend - ✅ Méthode deleteMedia() pour suppression - ✅ Génération miniature vidéo ### Posts (create_post_dialog.dart, edit_post_dialog.dart) - ✅ Extraction URL depuis uploads - ✅ Documentation chargement médias ### Chat (conversations_screen.dart) - ✅ Navigation vers notifications - ✅ ConversationSearchDelegate pour recherche ## Nouveaux Fichiers ### Configuration - build-prod.ps1 : Script build production avec dart-define - lib/core/constants/env_config.dart : Gestion environnements ### Documentation - TODOS_IMPLEMENTED.md : Documentation complète TODOs ## Améliorations ### Architecture - Refactoring injection de dépendances - Amélioration routing et navigation - Optimisation providers (UserProvider, FriendsProvider) ### UI/UX - Amélioration thème et couleurs - Optimisation animations - Meilleure gestion erreurs ### Services - Configuration API avec env_config - Amélioration datasources (events, users) - Optimisation modèles de données
168 lines
5.6 KiB
Dart
168 lines
5.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import '../../core/constants/colors.dart';
|
|
import '../../core/theme/theme_provider.dart';
|
|
import '../../core/utils/app_logger.dart';
|
|
|
|
void showEventOptions(BuildContext context, GlobalKey key) {
|
|
// Obtient la position de l'élément pour afficher le menu contextuel
|
|
final RenderBox renderBox =
|
|
key.currentContext!.findRenderObject() as RenderBox;
|
|
final Offset offset = renderBox.localToGlobal(Offset.zero);
|
|
final RelativeRect position = RelativeRect.fromLTRB(
|
|
offset.dx,
|
|
offset.dy,
|
|
offset.dx + renderBox.size.width,
|
|
offset.dy + renderBox.size.height,
|
|
);
|
|
|
|
// Affiche le menu contextuel avec des options personnalisées
|
|
showMenu(
|
|
context: context,
|
|
position: position,
|
|
items: [
|
|
_buildElegantMenuItem(
|
|
icon: Icons.info_outline,
|
|
label: 'Voir les détails',
|
|
color: AppColors.primary, // Utilise la couleur primaire dynamique
|
|
onTap: () {
|
|
AppLogger.d('Voir les détails', tag: 'EventMenu');
|
|
// Log d'action pour suivre l'interaction utilisateur
|
|
},
|
|
),
|
|
_buildElegantMenuItem(
|
|
icon: Icons.edit,
|
|
label: 'Modifier l\'événement',
|
|
color: AppColors.secondary, // Utilise la couleur secondaire dynamique
|
|
onTap: () {
|
|
AppLogger.d('Modifier l\'événement', tag: 'EventMenu');
|
|
},
|
|
),
|
|
_buildElegantMenuItem(
|
|
icon: Icons.delete_outline,
|
|
label: 'Supprimer l\'événement',
|
|
color: AppColors.errorColor, // Utilise la couleur d'erreur dynamique
|
|
onTap: () {
|
|
_showDeleteConfirmation(context);
|
|
},
|
|
),
|
|
],
|
|
elevation: 12, // Niveau d'élévation du menu pour une ombre modérée
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(20), // Coins arrondis pour un look moderne
|
|
),
|
|
color: AppColors.customBackgroundColor, // Surface dynamique selon le thème
|
|
).then((value) {
|
|
if (value != null) {
|
|
HapticFeedback.lightImpact(); // Retour haptique pour une meilleure UX
|
|
}
|
|
});
|
|
}
|
|
|
|
// Construction d'un élément de menu stylisé
|
|
PopupMenuItem _buildElegantMenuItem({
|
|
required IconData icon,
|
|
required String label,
|
|
required Color color,
|
|
required VoidCallback onTap,
|
|
}) {
|
|
return PopupMenuItem(
|
|
value: label,
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
onTap();
|
|
},
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(12),
|
|
color: AppColors.cardColor, // Couleur de fond dynamique du conteneur
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(icon, color: color, size: 15), // Icône avec couleur personnalisée
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Text(
|
|
label,
|
|
style: TextStyle(
|
|
color: color, // Couleur de texte dynamique
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 12,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showDeleteConfirmation(BuildContext context) {
|
|
// Récupère le thème sans écoute, car la fonction est appelée en dehors de l'arbre de widgets.
|
|
final themeProvider = Provider.of<ThemeProvider>(context, listen: false);
|
|
|
|
// Affiche une boîte de dialogue pour confirmer la suppression
|
|
showDialog(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return AlertDialog(
|
|
title: Row(
|
|
children: [
|
|
Icon(Icons.warning_amber_rounded, color: AppColors.errorColor),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
'Supprimer l\'événement',
|
|
style: TextStyle(
|
|
color: AppColors.errorColor, // Utilisation de la couleur d'erreur dynamique
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
content: Text(
|
|
'Voulez-vous vraiment supprimer cet événement ? Cette action est irréversible.',
|
|
style: TextStyle(
|
|
color: themeProvider.isDarkMode ? AppColors.lightOnPrimary : AppColors.darkPrimary, // Texte principal dynamique
|
|
fontSize: 15,
|
|
),
|
|
),
|
|
actions: <Widget>[
|
|
TextButton(
|
|
style: ButtonStyle(
|
|
overlayColor: WidgetStateProperty.all(Colors.grey.shade200),
|
|
),
|
|
child: Text('Annuler', style: TextStyle(color: Colors.grey.shade700)),
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
},
|
|
),
|
|
ElevatedButton.icon(
|
|
icon: Icon(Icons.delete, color: themeProvider.isDarkMode ? AppColors.darkPrimary : AppColors.lightOnPrimary, size: 18),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppColors.errorColor, // Bouton de suppression en couleur d'erreur
|
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
textStyle: const TextStyle(fontWeight: FontWeight.bold),
|
|
),
|
|
label: const Text('Supprimer'),
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
AppLogger.i('Événement supprimé', tag: 'EventMenu');
|
|
// Logique de suppression réelle ici
|
|
},
|
|
),
|
|
],
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(15),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|