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

@@ -140,6 +140,12 @@ class Urls {
static String getEventsByUserWithUserId(String userId) =>
'$eventsBase/user/$userId';
/// Retourne l'URL pour obtenir les événements de l'utilisateur et de ses amis
///
/// [userId] L'ID de l'utilisateur
static String getEventsByFriends(String userId) =>
'$eventsBase/friends/$userId';
/// Endpoint pour rechercher des événements
///
/// **Note:** Utilisez des paramètres de requête pour le mot-clé
@@ -244,6 +250,13 @@ class Urls {
static String rejectFriendRequestWithId(String friendshipId) =>
'$friendsBase/$friendshipId/reject';
/// Retourne l'URL pour récupérer les suggestions d'amis
///
/// [userId] L'ID de l'utilisateur
/// [limit] Nombre maximum de suggestions (optionnel, par défaut 10)
static String getFriendSuggestionsWithUserId(String userId, {int limit = 10}) =>
'$friendsBase/suggestions/$userId?limit=$limit';
// ============================================================================
// NOTIFICATIONS
// ============================================================================
@@ -320,6 +333,12 @@ class Urls {
static String commentSocialPostWithId(String postId) =>
'$postsBase/$postId/comment';
/// Retourne l'URL pour obtenir tous les commentaires d'un post
///
/// [postId] L'ID du post
static String getCommentsForPost(String postId) =>
'$postsBase/$postId/comments';
/// Retourne l'URL pour partager un post
///
/// [postId] L'ID du post
@@ -331,6 +350,124 @@ class Urls {
static String getSocialPostsByUserId(String userId) =>
'$postsBase/user/$userId';
/// Retourne l'URL pour obtenir les posts de l'utilisateur et de ses amis
///
/// [userId] L'ID de l'utilisateur
static String getSocialPostsByFriends(String userId) =>
'$postsBase/friends/$userId';
// ============================================================================
// STORIES
// ============================================================================
/// Endpoint de base pour les opérations sur les stories
static String get storiesBase => '$baseUrl/stories';
/// Retourne l'URL pour obtenir toutes les stories (actives)
static String get getAllStories => storiesBase;
/// Retourne l'URL pour obtenir les stories d'un utilisateur
///
/// [userId] L'ID de l'utilisateur
static String getStoriesByUserId(String userId) => '$storiesBase/user/$userId';
/// Retourne l'URL pour créer une nouvelle story
static String get createStory => storiesBase;
/// Retourne l'URL pour obtenir une story par son ID
///
/// [storyId] L'ID de la story
static String getStoryByIdWithId(String storyId) => '$storiesBase/$storyId';
/// Retourne l'URL pour supprimer une story
///
/// [storyId] L'ID de la story
static String deleteStoryWithId(String storyId) => '$storiesBase/$storyId';
/// Retourne l'URL pour marquer une story comme vue
///
/// [storyId] L'ID de la story
/// [userId] L'ID de l'utilisateur qui voit la story
static String markStoryAsViewedWithId(String storyId, String userId) =>
'$storiesBase/$storyId/view?userId=$userId';
/// Retourne l'URL pour obtenir les vues d'une story
///
/// [storyId] L'ID de la story
static String getStoryViewsWithId(String storyId) => '$storiesBase/$storyId/views';
// ============================================================================
// MESSAGERIE
// ============================================================================
/// Endpoint de base pour les opérations sur les messages
static String get messagesBase => '$baseUrl/messages';
/// Retourne l'URL pour envoyer un message
static String get sendMessage => messagesBase;
/// Retourne l'URL pour obtenir les conversations d'un utilisateur
///
/// [userId] L'ID de l'utilisateur
static String getUserConversations(String userId) =>
'$messagesBase/conversations/$userId';
/// Retourne l'URL pour obtenir les messages d'une conversation
///
/// [conversationId] L'ID de la conversation
/// [page] Le numéro de la page (optionnel)
/// [size] La taille de la page (optionnel)
static String getConversationMessages(String conversationId,
{int page = 0, int size = 50}) =>
'$messagesBase/conversation/$conversationId?page=$page&size=$size';
/// Retourne l'URL pour obtenir une conversation entre deux utilisateurs
///
/// [user1Id] L'ID du premier utilisateur
/// [user2Id] L'ID du deuxième utilisateur
static String getConversationBetweenUsers(String user1Id, String user2Id) =>
'$messagesBase/conversation/between/$user1Id/$user2Id';
/// Retourne l'URL pour marquer un message comme lu
///
/// [messageId] L'ID du message
static String markMessageAsRead(String messageId) =>
'$messagesBase/$messageId/read';
/// Retourne l'URL pour marquer tous les messages d'une conversation comme lus
///
/// [conversationId] L'ID de la conversation
/// [userId] L'ID de l'utilisateur
static String markAllMessagesAsRead(String conversationId, String userId) =>
'$messagesBase/conversation/$conversationId/read/$userId';
/// Retourne l'URL pour obtenir le nombre de messages non lus
///
/// [userId] L'ID de l'utilisateur
static String getUnreadMessagesCount(String userId) =>
'$messagesBase/unread/count/$userId';
/// Retourne l'URL pour supprimer un message
///
/// [messageId] L'ID du message
static String deleteMessage(String messageId) => '$messagesBase/$messageId';
/// Retourne l'URL pour supprimer une conversation
///
/// [conversationId] L'ID de la conversation
static String deleteConversation(String conversationId) =>
'$messagesBase/conversation/$conversationId';
/// Retourne l'URL WebSocket pour le chat en temps réel
///
/// [userId] L'ID de l'utilisateur
static String getChatWebSocketUrl(String userId) {
final wsUrl = baseUrl
.replaceFirst('http://', 'ws://')
.replaceFirst('https://', 'wss://');
return '$wsUrl/chat/ws/$userId';
}
// ============================================================================
// MÉTHODES UTILITAIRES
// ============================================================================