Implement message deletion functionality: add isDeleted flag to Message model, update deleteMessage method in MessageRepository, and adjust chat display for deleted messages.
This commit is contained in:
@@ -28,8 +28,9 @@ import '../../blocs/account/account_state.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:travel_mate/components/error/error_content.dart';
|
import 'package:travel_mate/components/error/error_content.dart';
|
||||||
import '../../blocs/user/user_state.dart' as user_state;
|
import '../../blocs/user/user_state.dart' as user_state;
|
||||||
import '../../repositories/group_repository.dart'; // Ajouter cet import
|
import '../../repositories/group_repository.dart';
|
||||||
import 'group_expenses_page.dart'; // Ajouter cet import
|
import '../widgets/user_state_widget.dart';
|
||||||
|
import 'group_expenses_page.dart';
|
||||||
|
|
||||||
/// Widget that displays the account content page with account management functionality.
|
/// Widget that displays the account content page with account management functionality.
|
||||||
class AccountContent extends StatefulWidget {
|
class AccountContent extends StatefulWidget {
|
||||||
@@ -132,33 +133,13 @@ class _AccountContentState extends State<AccountContent> {
|
|||||||
/// Widget representing the complete account page UI
|
/// Widget representing the complete account page UI
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<UserBloc, user_state.UserState>(
|
return UserStateWrapper(
|
||||||
builder: (context, userState) {
|
builder: (context, user) {
|
||||||
if (userState is user_state.UserLoading) {
|
|
||||||
return const Scaffold(
|
|
||||||
body: Center(child: CircularProgressIndicator()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userState is user_state.UserError) {
|
|
||||||
return ErrorContent(
|
|
||||||
message: 'User error: ${userState.message}',
|
|
||||||
onRetry: () {},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userState is! user_state.UserLoaded) {
|
|
||||||
return const Scaffold(
|
|
||||||
body: Center(child: Text('User not connected')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
final user = userState.user;
|
|
||||||
|
|
||||||
return BlocConsumer<AccountBloc, AccountState>(
|
return BlocConsumer<AccountBloc, AccountState>(
|
||||||
listener: (context, accountState) {
|
listener: (context, accountState) {
|
||||||
if (accountState is AccountError) {
|
if (accountState is AccountError) {
|
||||||
ErrorContent(
|
ErrorContent(
|
||||||
message: 'Account loading error: ${accountState.message}',
|
message: 'Erreur de chargement des comptes : ${accountState.message}',
|
||||||
onRetry: () {
|
onRetry: () {
|
||||||
context.read<AccountBloc>().add(LoadAccountsByUserId(user.id));
|
context.read<AccountBloc>().add(LoadAccountsByUserId(user.id));
|
||||||
},
|
},
|
||||||
@@ -167,11 +148,21 @@ class _AccountContentState extends State<AccountContent> {
|
|||||||
},
|
},
|
||||||
builder: (context, accountState) {
|
builder: (context, accountState) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: SafeArea(child: _buildContent(accountState, user.id))
|
body: SafeArea(child: _buildContent(accountState, user.id)),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
loadingWidget: const Scaffold(
|
||||||
|
body: Center(child: CircularProgressIndicator()),
|
||||||
|
),
|
||||||
|
errorWidget: ErrorContent(
|
||||||
|
message: 'User error',
|
||||||
|
onRetry: () {},
|
||||||
|
),
|
||||||
|
noUserWidget: const Scaffold(
|
||||||
|
body: Center(child: Text('Utilisateur non connecté')),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +187,7 @@ class _AccountContentState extends State<AccountContent> {
|
|||||||
children: [
|
children: [
|
||||||
CircularProgressIndicator(),
|
CircularProgressIndicator(),
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
Text('Loading accounts...'),
|
Text('Chargement des comptes...'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -204,7 +195,7 @@ class _AccountContentState extends State<AccountContent> {
|
|||||||
|
|
||||||
if (accountState is AccountError) {
|
if (accountState is AccountError) {
|
||||||
return ErrorContent(
|
return ErrorContent(
|
||||||
message: 'Account loading error...',
|
message: 'Erreur de chargement des comptes...',
|
||||||
onRetry: () {
|
onRetry: () {
|
||||||
context.read<AccountBloc>().add(LoadAccountsByUserId(userId));
|
context.read<AccountBloc>().add(LoadAccountsByUserId(userId));
|
||||||
},
|
},
|
||||||
@@ -222,13 +213,13 @@ class _AccountContentState extends State<AccountContent> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Text('Unknown state'),
|
const Text('État inconnu'),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.read<AccountBloc>().add(LoadAccountsByUserId(userId));
|
context.read<AccountBloc>().add(LoadAccountsByUserId(userId));
|
||||||
},
|
},
|
||||||
child: const Text('Load accounts'),
|
child: const Text('Charger les comptes'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -258,7 +249,7 @@ class _AccountContentState extends State<AccountContent> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
const Text(
|
const Text(
|
||||||
'Accounts are automatically created when you create a trip',
|
'Les comptes sont créés automatiquement lorsque vous créez des voyages.',
|
||||||
style: TextStyle(fontSize: 14, color: Colors.grey),
|
style: TextStyle(fontSize: 14, color: Colors.grey),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
@@ -289,18 +280,7 @@ class _AccountContentState extends State<AccountContent> {
|
|||||||
child: ListView(
|
child: ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
...accounts.map((account) {
|
||||||
'My accounts',
|
|
||||||
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
'Manage your travel accounts',
|
|
||||||
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
|
|
||||||
...accounts.map((account) {
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 12),
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
child: _buildSimpleAccountCard(account),
|
child: _buildSimpleAccountCard(account),
|
||||||
|
|||||||
@@ -476,8 +476,12 @@ class _ChatGroupContentState extends State<ChatGroupContent> {
|
|||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
],
|
],
|
||||||
Text(
|
Text(
|
||||||
message.text,
|
message.isDeleted ? 'a supprimé un message' : message.text,
|
||||||
style: TextStyle(fontSize: 15, color: textColor),
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
color: message.isDeleted ? textColor.withValues(alpha: 0.5) : textColor,
|
||||||
|
fontStyle: message.isDeleted ? FontStyle.italic : FontStyle.normal,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@@ -127,17 +127,6 @@ class _GroupContentState extends State<GroupContent> {
|
|||||||
child: ListView(
|
child: ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
|
||||||
'Mes groupes',
|
|
||||||
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
'Discutez avec les participants',
|
|
||||||
style: TextStyle(fontSize: 14, color: Colors.grey[600]),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
|
|
||||||
...groups.map((group) {
|
...groups.map((group) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 12),
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ class Message {
|
|||||||
final Map<String, String> reactions; // userId -> emoji
|
final Map<String, String> reactions; // userId -> emoji
|
||||||
final DateTime? editedAt;
|
final DateTime? editedAt;
|
||||||
final bool isEdited;
|
final bool isEdited;
|
||||||
|
final bool isDeleted;
|
||||||
|
|
||||||
Message({
|
Message({
|
||||||
this.id = '',
|
this.id = '',
|
||||||
@@ -21,6 +22,7 @@ class Message {
|
|||||||
this.reactions = const {},
|
this.reactions = const {},
|
||||||
this.editedAt,
|
this.editedAt,
|
||||||
this.isEdited = false,
|
this.isEdited = false,
|
||||||
|
this.isDeleted = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Message.fromFirestore(DocumentSnapshot doc) {
|
factory Message.fromFirestore(DocumentSnapshot doc) {
|
||||||
@@ -39,6 +41,7 @@ class Message {
|
|||||||
reactions: reactionsData?.map((key, value) => MapEntry(key, value.toString())) ?? {},
|
reactions: reactionsData?.map((key, value) => MapEntry(key, value.toString())) ?? {},
|
||||||
editedAt: editedAtTimestamp?.toDate(),
|
editedAt: editedAtTimestamp?.toDate(),
|
||||||
isEdited: data['isEdited'] ?? false,
|
isEdited: data['isEdited'] ?? false,
|
||||||
|
isDeleted: data['isDeleted'] ?? false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +55,7 @@ class Message {
|
|||||||
'reactions': reactions,
|
'reactions': reactions,
|
||||||
'editedAt': editedAt != null ? Timestamp.fromDate(editedAt!) : null,
|
'editedAt': editedAt != null ? Timestamp.fromDate(editedAt!) : null,
|
||||||
'isEdited': isEdited,
|
'isEdited': isEdited,
|
||||||
|
'isDeleted': isDeleted,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +69,7 @@ class Message {
|
|||||||
Map<String, String>? reactions,
|
Map<String, String>? reactions,
|
||||||
DateTime? editedAt,
|
DateTime? editedAt,
|
||||||
bool? isEdited,
|
bool? isEdited,
|
||||||
|
bool? isDeleted,
|
||||||
}) {
|
}) {
|
||||||
return Message(
|
return Message(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
@@ -76,6 +81,7 @@ class Message {
|
|||||||
reactions: reactions ?? this.reactions,
|
reactions: reactions ?? this.reactions,
|
||||||
editedAt: editedAt ?? this.editedAt,
|
editedAt: editedAt ?? this.editedAt,
|
||||||
isEdited: isEdited ?? this.isEdited,
|
isEdited: isEdited ?? this.isEdited,
|
||||||
|
isDeleted: isDeleted ?? this.isDeleted,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ class MessageRepository {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Supprimer un message
|
// Supprimer un message (marquer comme supprimé)
|
||||||
Future<void> deleteMessage({
|
Future<void> deleteMessage({
|
||||||
required String groupId,
|
required String groupId,
|
||||||
required String messageId,
|
required String messageId,
|
||||||
@@ -52,7 +52,10 @@ class MessageRepository {
|
|||||||
.doc(groupId)
|
.doc(groupId)
|
||||||
.collection('messages')
|
.collection('messages')
|
||||||
.doc(messageId)
|
.doc(messageId)
|
||||||
.delete();
|
.update({
|
||||||
|
'isDeleted': true,
|
||||||
|
'text': '',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modifier un message
|
// Modifier un message
|
||||||
|
|||||||
Reference in New Issue
Block a user