mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Add reply shortcut for messages
This commit is contained in:
@@ -304,6 +304,51 @@ class _MessagesTabState extends State<MessagesTab> {
|
|||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _replyToMessage(Message message) async {
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
final contactsProvider = context.read<ContactsProvider>();
|
||||||
|
|
||||||
|
String destinationType;
|
||||||
|
Contact? recipient;
|
||||||
|
|
||||||
|
if (message.isChannelMessage) {
|
||||||
|
final channelIdx = message.channelIdx ?? 0;
|
||||||
|
destinationType = MessageDestinationPreferences.destinationTypeChannel;
|
||||||
|
|
||||||
|
if (channelIdx != 0) {
|
||||||
|
recipient = contactsProvider.channels.where((contact) {
|
||||||
|
return contact.publicKey.length > 1 &&
|
||||||
|
contact.publicKey[1] == channelIdx;
|
||||||
|
}).firstOrNull;
|
||||||
|
|
||||||
|
if (recipient == null) {
|
||||||
|
ToastLogger.error(context, l10n.cannotReplyContactNotFound);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final senderPrefix = message.senderPublicKeyPrefix;
|
||||||
|
if (senderPrefix == null || senderPrefix.length < 6) {
|
||||||
|
ToastLogger.error(context, l10n.cannotReplySenderMissing);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
recipient = contactsProvider.findContactByPrefix(senderPrefix);
|
||||||
|
if (recipient == null) {
|
||||||
|
ToastLogger.error(context, l10n.cannotReplyContactNotFound);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
destinationType = recipient.isRoom
|
||||||
|
? MessageDestinationPreferences.destinationTypeRoom
|
||||||
|
: MessageDestinationPreferences.destinationTypeContact;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _onRecipientSelected(destinationType, recipient);
|
||||||
|
if (!mounted) return;
|
||||||
|
_focusNode.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
/// Get icon for current destination type
|
/// Get icon for current destination type
|
||||||
IconData _getDestinationIcon() {
|
IconData _getDestinationIcon() {
|
||||||
if (_destinationType ==
|
if (_destinationType ==
|
||||||
@@ -1538,6 +1583,7 @@ class _MessagesTabState extends State<MessagesTab> {
|
|||||||
onRefresh: _handleRefresh,
|
onRefresh: _handleRefresh,
|
||||||
onNavigateToMap: widget.onNavigateToMap,
|
onNavigateToMap: widget.onNavigateToMap,
|
||||||
onMessageTap: _handleMessageTap,
|
onMessageTap: _handleMessageTap,
|
||||||
|
onReplyToMessage: _replyToMessage,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import 'system_message_bubble.dart';
|
|||||||
class MessageBubble extends StatefulWidget {
|
class MessageBubble extends StatefulWidget {
|
||||||
final Message message;
|
final Message message;
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onTap;
|
||||||
|
final VoidCallback? onReply;
|
||||||
final bool isHighlighted;
|
final bool isHighlighted;
|
||||||
final VoidCallback? onNavigateToMap;
|
final VoidCallback? onNavigateToMap;
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ class MessageBubble extends StatefulWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.message,
|
required this.message,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
|
this.onReply,
|
||||||
this.isHighlighted = false,
|
this.isHighlighted = false,
|
||||||
this.onNavigateToMap,
|
this.onNavigateToMap,
|
||||||
this.isCompact = false,
|
this.isCompact = false,
|
||||||
@@ -209,6 +211,15 @@ class _MessageBubbleState extends State<MessageBubble> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
if (!isOwnMessage && widget.onReply != null)
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.reply),
|
||||||
|
title: Text(AppLocalizations.of(context)!.reply),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
widget.onReply?.call();
|
||||||
|
},
|
||||||
|
),
|
||||||
// Copy text option
|
// Copy text option
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.copy),
|
leading: const Icon(Icons.copy),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class MessagesContent extends StatelessWidget {
|
|||||||
final Future<void> Function() onRefresh;
|
final Future<void> Function() onRefresh;
|
||||||
final VoidCallback? onNavigateToMap;
|
final VoidCallback? onNavigateToMap;
|
||||||
final ValueChanged<Message>? onMessageTap;
|
final ValueChanged<Message>? onMessageTap;
|
||||||
|
final ValueChanged<Message>? onReplyToMessage;
|
||||||
|
|
||||||
const MessagesContent({
|
const MessagesContent({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -24,6 +25,7 @@ class MessagesContent extends StatelessWidget {
|
|||||||
required this.onRefresh,
|
required this.onRefresh,
|
||||||
this.onNavigateToMap,
|
this.onNavigateToMap,
|
||||||
this.onMessageTap,
|
this.onMessageTap,
|
||||||
|
this.onReplyToMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -86,6 +88,9 @@ class MessagesContent extends StatelessWidget {
|
|||||||
onTap: onMessageTap == null
|
onTap: onMessageTap == null
|
||||||
? null
|
? null
|
||||||
: () => onMessageTap!(message),
|
: () => onMessageTap!(message),
|
||||||
|
onReply: onReplyToMessage == null
|
||||||
|
? null
|
||||||
|
: () => onReplyToMessage!(message),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user