Skip to content

Item labels are not reactive (Open/Close text stays stale after state change) #434

Description

@kdroidFilter

Problem

CheckableItem(checked) is now reactive after #432 (live AtomicBoolean + updateMenuItemCheckedState). Item labels are not.

Changing Item(label = …) from Compose state does not update the native menu text until something else forces a full tray rebuild (e.g. the app wrapping Tray in key(label) and disposing NativeTray).

MenuContentHash / the composable-DSL fingerprint already include label. The native menu still keeps the text captured at last setupMenu. Unlike checkmarks, there is no updateMenuItemText / rebuild-on-label-change path.

Seen on Windows 11 with ComposeNativeTray dev (post-#433): a tray item that should read "Open Dashboard" / "Close Dashboard" depending on window visibility stayed on "Open Dashboard" after the window opened.

Expected

Opening the tray menu shows the current Item label. Toggling the same flag from a window (or from the item itself) updates the text on the next open, without the app disposing Tray.

Minimal reproduction

Painter Tray (the updateComposable path). Flip the switch, then open the tray menu.

fun main() = nucleusApplication(enableSingleInstance = false) {
    var dashboardOpen by remember { mutableStateOf(false) }

    Tray(
        icon = painterResource(Res.drawable.icon),
        tooltip = "Item label repro",
        primaryAction = { dashboardOpen = true },
    ) {
        Item(
            label = if (dashboardOpen) "Close Dashboard" else "Open Dashboard",
        ) {
            dashboardOpen = !dashboardOpen
        }
        Item(label = "Quit") { exitApplication() }
    }

    DecoratedWindow(
        onCloseRequest = ::exitApplication,
        title = "Item label repro",
        state = rememberWindowState(size = DpSize(280.dp, 120.dp)),
    ) {
        Row(Modifier.padding(12.dp), verticalAlignment = Alignment.CenterVertically) {
            Switch(checked = dashboardOpen, onCheckedChange = { dashboardOpen = it })
            Text(if (dashboardOpen) "dashboard open" else "dashboard closed")
        }
    }
}

Steps

  1. Run. Open the tray menu — item is "Open Dashboard".
  2. Turn the window Switch on (or click the tray item once).
  3. Open the tray menu again.

Actual

Step 3 still shows "Open Dashboard". Clicking it toggles state again (or no-ops depending on captured onClick), but the text does not follow.

Workaround used in apps: key(dashboardOpen) { Tray(…) }, which disposes and recreates the tray icon.

Suggested fix

Same class of fix as #432, for labels (and ideally isEnabled):

  • Include label in the structure that already triggers a native rebuild (menuHash / composable fingerprint — already there).
  • Make sure that rebuild actually runs and replaces menu item text, or add updateMenuItemLabel next to updateMenuItemCheckedState.
  • Do not require callers to key() / dispose NativeTray for a label change.

CheckableItem proving checkmarks can update without a full icon re-render is the model; Item text should be the same.

Tech

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions