fix(chat): Correction race condition + Implémentation TODOs

## 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
This commit is contained in:
dahoud
2026-01-10 10:43:17 +00:00
parent 06031b01f2
commit 92612abbd7
321 changed files with 43137 additions and 4285 deletions

View File

@@ -1,6 +1,32 @@
import 'package:flutter/material.dart';
/// Widget d'interaction avec un événement (réagir, commenter, partager).
///
/// Ce widget affiche des boutons compacts pour interagir avec un événement,
/// avec compteurs et design moderne.
///
/// **Usage:**
/// ```dart
/// EventInteractionRow(
/// onReact: () => handleReact(),
/// onComment: () => handleComment(),
/// onShare: () => handleShare(),
/// reactionsCount: 10,
/// commentsCount: 5,
/// sharesCount: 2,
/// )
/// ```
class EventInteractionRow extends StatelessWidget {
const EventInteractionRow({
required this.onReact,
required this.onComment,
required this.onShare,
required this.reactionsCount,
required this.commentsCount,
required this.sharesCount,
super.key,
});
final VoidCallback onReact;
final VoidCallback onComment;
final VoidCallback onShare;
@@ -8,36 +34,82 @@ class EventInteractionRow extends StatelessWidget {
final int commentsCount;
final int sharesCount;
const EventInteractionRow({
Key? key,
required this.onReact,
required this.onComment,
required this.onShare,
required this.reactionsCount,
required this.commentsCount,
required this.sharesCount,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildIconButton(Icons.thumb_up_alt_outlined, 'Réagir', reactionsCount, onReact),
_buildIconButton(Icons.comment_outlined, 'Commenter', commentsCount, onComment),
_buildIconButton(Icons.share_outlined, 'Partager', sharesCount, onShare),
_buildInteractionButton(
context,
theme,
icon: Icons.thumb_up_outlined,
label: 'Réagir',
count: reactionsCount,
onPressed: onReact,
),
_buildInteractionButton(
context,
theme,
icon: Icons.comment_outlined,
label: 'Commenter',
count: commentsCount,
onPressed: onComment,
),
_buildInteractionButton(
context,
theme,
icon: Icons.share_outlined,
label: 'Partager',
count: sharesCount,
onPressed: onShare,
),
],
);
}
Widget _buildIconButton(IconData icon, String label, int count, VoidCallback onPressed) {
return TextButton.icon(
onPressed: onPressed,
icon: Icon(icon, color: const Color(0xFF1DBF73), size: 18),
label: Text(
'$label ($count)',
style: const TextStyle(color: Colors.white70, fontSize: 12),
/// Construit un bouton d'interaction compact.
Widget _buildInteractionButton(
BuildContext context,
ThemeData theme, {
required IconData icon,
required String label,
required int count,
required VoidCallback onPressed,
}) {
return InkWell(
onTap: onPressed,
borderRadius: BorderRadius.circular(8),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
icon,
size: 18,
color: theme.colorScheme.primary,
),
const SizedBox(width: 4),
Text(
_formatCount(count),
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.onSurface.withOpacity(0.7),
fontWeight: FontWeight.w500,
),
),
],
),
),
);
}
/// Formate le compteur avec format compact.
String _formatCount(int count) {
if (count >= 1000) {
return '${(count / 1000).toStringAsFixed(1)}k';
}
return count.toString();
}
}