diff --git a/lib/connector/meshcore_connector.dart b/lib/connector/meshcore_connector.dart index 634fd5b..fed5f57 100644 --- a/lib/connector/meshcore_connector.dart +++ b/lib/connector/meshcore_connector.dart @@ -1235,6 +1235,15 @@ class MeshCoreConnector extends ChangeNotifier { int timestampSeconds, ) async { if (!isConnected || text.isEmpty) return; + // Automatic retries route here without passing sendMessage — stop them + // too once the contact is blocked (#252). + if (_blockService?.isBlocked(contact.publicKeyHex) ?? false) { + appLogger.info( + 'Dropped outgoing DM retry to blocked contact', + tag: 'Connector', + ); + return; + } try { await _waitForRadioQuiet(lastInboundRxTime: _lastContactMsgRxTime); final outboundText = prepareContactOutboundText(contact, text); @@ -3080,7 +3089,13 @@ class MeshCoreConnector extends ChangeNotifier { if (!isConnected || text.isEmpty) return; // Outgoing DMs (incl. reactions and retries) to a blocked contact are // dropped — mirrors the incoming DM-drop so a block is symmetric (#252). - if (_blockService?.isBlocked(contact.publicKeyHex) ?? false) return; + if (_blockService?.isBlocked(contact.publicKeyHex) ?? false) { + appLogger.info( + 'Dropped outgoing DM to blocked contact', + tag: 'Connector', + ); + return; + } // Check if this is a reaction - apply locally with pending status and route through retry service final reactionInfo = ReactionHelper.parseReaction(text); diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart index 1449660..d8c743a 100644 --- a/lib/screens/chat_screen.dart +++ b/lib/screens/chat_screen.dart @@ -1789,6 +1789,13 @@ class _ChatScreenState extends State { void _retryMessage(Message message) { final connector = Provider.of(context, listen: false); + if (context.read().isBlocked(widget.contact.publicKeyHex)) { + showDismissibleSnackBar( + context, + content: Text(context.l10n.block_composerNotice), + ); + return; + } // Retry using the contact's current path override setting connector.sendMessage(_resolveContact(connector), message.text); showDismissibleSnackBar( @@ -1811,6 +1818,13 @@ class _ChatScreenState extends State { void _sendReaction(Message message, Contact senderContact, String emoji) { final connector = context.read(); + if (context.read().isBlocked(widget.contact.publicKeyHex)) { + showDismissibleSnackBar( + context, + content: Text(context.l10n.block_composerNotice), + ); + return; + } final emojiIndex = ReactionHelper.emojiToIndex(emoji); if (emojiIndex == null) return; // Unknown emoji, skip final timestampSecs = message.timestamp.millisecondsSinceEpoch ~/ 1000;