feat: implement right-click as mirror for long-click across shared UI

This commit introduces a new `Modifier.onRightClick` extension to improve desktop usability by mapping secondary mouse clicks to existing long-click actions. It also removes the legacy desktop `MenuBar` implementation in favor of this more consistent cross-platform UX approach.

Specific changes include:
- **Core UI**: Added `Modifier.onRightClick` in `ModifierExtensions.kt` using `PointerButton.Secondary` to detect right-clicks on desktop platforms.
- **Desktop**: Removed the `MenuBar` and associated keyboard shortcuts from the main entry point.
- **Messaging Feature**: Added right-click support to `MessageItem`, `Reaction`, and `ContactItem`.
- **Node Feature**:
    - Added right-click support to `NodeItem`, `NodeDetailsSection`, `NodeDetailComponents`, and `InfoCard` to trigger copy actions or context menus.
    - Updated `TracerouteLog`, `NeighborInfoLog`, and `NodeItem` to handle right-click events.
- **Connections Feature**: Updated `DeviceListItem` to support right-click for deletion/context actions.
- **Documentation**: Updated `roadmap.md` to reflect the completion of right-click UX integration.

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-03-22 11:48:46 -05:00
parent 5a287f7133
commit 0bc907ec32
13 changed files with 117 additions and 112 deletions

View file

@ -16,7 +16,12 @@
*/
package org.meshtastic.core.ui.util
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.PointerButton
import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.pointerInput
/**
* Conditionally applies the [action] to the receiver [Modifier] if [precondition] is true. Otherwise, returns the
@ -24,3 +29,18 @@ import androidx.compose.ui.Modifier
*/
inline fun Modifier.thenIf(precondition: Boolean, action: Modifier.() -> Modifier): Modifier =
if (precondition) action() else this
/**
* Adds a secondary (right) mouse-button click handler. On touch-only platforms the secondary button event never fires,
* so this is a safe no-op. Intended to mirror `onLongClick` behavior for desktop users who expect right-click context
* actions.
*/
@OptIn(ExperimentalComposeUiApi::class)
fun Modifier.onRightClick(action: () -> Unit): Modifier = pointerInput(action) {
awaitEachGesture {
val event = awaitPointerEvent()
if (event.type == PointerEventType.Press && event.button == PointerButton.Secondary) {
action()
}
}
}