Edit, delete message

This commit is contained in:
LittleSheep 2025-05-04 01:43:27 +08:00
parent 6fd61b547e
commit ee1fcd8752
4 changed files with 62 additions and 18 deletions

View File

@ -89,5 +89,6 @@
"permissionModerator": "Moderator", "permissionModerator": "Moderator",
"permissionMember": "Member", "permissionMember": "Member",
"reply": "Reply", "reply": "Reply",
"forward": "Forward" "forward": "Forward",
"edited": "Edited"
} }

View File

@ -441,6 +441,7 @@ class MessageRepository {
await _database.saveMessage(_database.messageToCompanion(message)); await _database.saveMessage(_database.messageToCompanion(message));
return message; return message;
} catch (e) { } catch (e) {
if (e is DioException) return null;
// Handle errors // Handle errors
rethrow; rethrow;
} }

View File

@ -16,6 +16,18 @@ abstract class UniversalFile with _$UniversalFile {
bool get isOnCloud => data is SnCloudFile; bool get isOnCloud => data is SnCloudFile;
bool get isOnDevice => !isOnCloud; bool get isOnDevice => !isOnCloud;
factory UniversalFile.fromAttachment(SnCloudFile attachment) {
return UniversalFile(
data: attachment,
type: switch (attachment.mimeType?.split('/').firstOrNull) {
'image' => UniversalFileType.image,
'audio' => UniversalFileType.audio,
'video' => UniversalFileType.video,
_ => UniversalFileType.file,
},
);
}
} }
@freezed @freezed

View File

@ -472,6 +472,22 @@ class ChatRoomScreen extends HookConsumerWidget {
case _MessageBubbleAction.edit: case _MessageBubbleAction.edit:
messageEditingTo.value = messageEditingTo.value =
message.toRemoteMessage(); message.toRemoteMessage();
messageController.text =
messageEditingTo
.value
?.content ??
'';
attachments.value =
messageEditingTo
.value!
.attachments
.map(
(e) =>
UniversalFile.fromAttachment(
e,
),
)
.toList();
case _MessageBubbleAction.forward: case _MessageBubbleAction.forward:
messageForwardingTo.value = messageForwardingTo.value =
message.toRemoteMessage(); message.toRemoteMessage();
@ -659,11 +675,14 @@ class _MessageBubble extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final messagesNotifier = ref.watch( final textColor =
messagesProvider(message.roomId).notifier, isCurrentUser
); ? Theme.of(context).colorScheme.onPrimaryContainer
: Theme.of(context).colorScheme.onSurfaceVariant;
final textColor = isCurrentUser ? Colors.white : Colors.black; final containerColor =
isCurrentUser
? Theme.of(context).colorScheme.primaryContainer.withOpacity(0.5)
: Theme.of(context).colorScheme.surfaceContainer;
return ContextMenuWidget( return ContextMenuWidget(
menuProvider: (_) { menuProvider: (_) {
@ -709,6 +728,7 @@ class _MessageBubble extends HookConsumerWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: mainAxisAlignment:
isCurrentUser ? MainAxisAlignment.end : MainAxisAlignment.start, isCurrentUser ? MainAxisAlignment.end : MainAxisAlignment.start,
children: [ children: [
@ -731,12 +751,7 @@ class _MessageBubble extends HookConsumerWidget {
vertical: 8, vertical: 8,
), ),
decoration: BoxDecoration( decoration: BoxDecoration(
color: color: containerColor,
isCurrentUser
? Theme.of(
context,
).colorScheme.primary.withOpacity(0.8)
: Colors.grey.shade200,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
), ),
child: Column( child: Column(
@ -760,15 +775,24 @@ class _MessageBubble extends HookConsumerWidget {
), ),
const Gap(4), const Gap(4),
Row( Row(
spacing: 4,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
DateFormat.Hm().format(message.createdAt.toLocal()), DateFormat.Hm().format(message.createdAt.toLocal()),
style: TextStyle(fontSize: 10, color: textColor), style: TextStyle(fontSize: 10, color: textColor),
), ),
const Gap(4), if (message.toRemoteMessage().editedAt != null)
Text(
'edited'.tr().toLowerCase(),
style: TextStyle(fontSize: 10, color: textColor),
),
if (isCurrentUser) if (isCurrentUser)
_buildStatusIcon(context, message.status), _buildStatusIcon(
context,
message.status,
textColor,
),
], ],
), ),
], ],
@ -794,12 +818,16 @@ class _MessageBubble extends HookConsumerWidget {
); );
} }
Widget _buildStatusIcon(BuildContext context, MessageStatus status) { Widget _buildStatusIcon(
BuildContext context,
MessageStatus status,
Color textColor,
) {
switch (status) { switch (status) {
case MessageStatus.pending: case MessageStatus.pending:
return const Icon(Icons.access_time, size: 12, color: Colors.white70); return Icon(Icons.access_time, size: 12, color: textColor);
case MessageStatus.sent: case MessageStatus.sent:
return const Icon(Icons.check, size: 12, color: Colors.white70); return Icon(Icons.check, size: 12, color: textColor);
case MessageStatus.failed: case MessageStatus.failed:
return Consumer( return Consumer(
builder: builder:
@ -850,7 +878,9 @@ class _MessageQuoteWidget extends HookConsumerWidget {
borderRadius: BorderRadius.all(Radius.circular(8)), borderRadius: BorderRadius.all(Radius.circular(8)),
child: Container( child: Container(
padding: EdgeInsets.symmetric(vertical: 4, horizontal: 6), padding: EdgeInsets.symmetric(vertical: 4, horizontal: 6),
color: Theme.of(context).colorScheme.surface.withOpacity(0.2), color: Theme.of(
context,
).colorScheme.primaryFixedDim.withOpacity(0.4),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [