✨ Edit, delete message
This commit is contained in:
parent
6fd61b547e
commit
ee1fcd8752
@ -89,5 +89,6 @@
|
|||||||
"permissionModerator": "Moderator",
|
"permissionModerator": "Moderator",
|
||||||
"permissionMember": "Member",
|
"permissionMember": "Member",
|
||||||
"reply": "Reply",
|
"reply": "Reply",
|
||||||
"forward": "Forward"
|
"forward": "Forward",
|
||||||
|
"edited": "Edited"
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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: [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user