From a3a075819f31b0539f706e18e4473c9c8e0d7b1f Mon Sep 17 00:00:00 2001 From: romeo Date: Sun, 19 Jul 2026 11:37:18 -0400 Subject: [PATCH] Add Send Message to Nodes long-press context menu Long-pressing a chat contact in the Nodes list showed Delete, Block/Unblock, and Favorite/Unfavorite, but no quick way to jump into the conversation without first opening Contact Detail. Adds a Send Message item at the top of the menu for chat-type, non-blocked contacts, reusing the same navigateToChat action and gating already used in Contact Detail's action row. See discussion: https://github.com/Avi0n/MeshCoreOne/issues/372 Co-Authored-By: Claude Sonnet 5 --- .../Contacts/ContactContextMenuModifier.swift | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/MC1/Views/Contacts/ContactContextMenuModifier.swift b/MC1/Views/Contacts/ContactContextMenuModifier.swift index cc1a8da1..259967f9 100644 --- a/MC1/Views/Contacts/ContactContextMenuModifier.swift +++ b/MC1/Views/Contacts/ContactContextMenuModifier.swift @@ -1,9 +1,9 @@ import MC1Services import SwiftUI -/// Long-press context-menu actions for a node row: delete, block/unblock, favorite/unfavorite, -/// matching the conversation list. Delete is gated while a removal is in flight so a rapid re-press -/// can't double-fire. +/// Long-press context-menu actions for a node row: send message (chat contacts only), delete, +/// block/unblock, favorite/unfavorite, matching the conversation list. Delete is gated while a +/// removal is in flight so a rapid re-press can't double-fire. struct ContactContextMenuModifier: ViewModifier { @Environment(\.appState) private var appState @@ -16,6 +16,15 @@ struct ContactContextMenuModifier: ViewModifier { func body(content: Content) -> some View { content.contextMenu { + if contact.type == .chat, !contact.isBlocked { + Button { + appState.navigation.navigateToChat(with: contact) + } label: { + Label(L10n.Contacts.Contacts.Detail.sendMessage, systemImage: "message.fill") + } + .disabled(!isConnected) + } + Button(role: .destructive) { Task { await viewModel.deleteContact(contact)