desktop: tray menu panels and pinnable context menus

The tray's right-click menu is drawn by the app: one tree from tray.rs
(stable submenu keys), one frameless always-on-top menu-N window per
panel rendered by tray-menu.html with the design system, placed inside
the monitor's work area. A pure panel book keeps transient and pinned
panels apart; pinned panels (pin button, Ctrl+click, middle click) are
draggable, step aside from each other and are saved in state.json
(menuPins) and restored at start. tray_update pushes the tree to the
open panels, which update in place; closed panels are destroyed. The
native menu, rendered from the same tree, stays as the fallback and on
Linux. Only menu-* windows get the menu_* commands (menu.json).

In-app context menus get the same behaviour through a pure menu stack
(ui/menu-stack.ts): pin a menu, tear off a submenu, pinned panels
survive the next menu, are draggable and re-read their entries from
live sources so data changes update them in place.

Also drops a stray diff3 marker line from CHANGELOG.md.
This commit is contained in:
CRTkafa 2026-10-24 13:44:08 +08:00
parent 445ab1adbc
commit 5236f002f1
35 changed files with 2308 additions and 123 deletions

View file

@ -2059,6 +2059,12 @@ export const en = {
// context menus (ui/ContextMenu.tsx)
'cm.cut': "Cut",
'cm.pin': "Pin: keeps this menu open",
'cm.unpin': "Unpin",
'cm.closePanel': "Close",
'cm.gone': "Gone: what this menu was for is not on screen now.",
'cm.menu': "Menu",
'cm.tearOff': "Ctrl+click or middle-click: pin this submenu",
'cm.copy': "Copy",
'cm.paste': "Paste",
'cm.selectAll': "Select all",

View file

@ -2061,6 +2061,12 @@ export const tr: Record<keyof typeof en, string> = {
// context menus (ui/ContextMenu.tsx)
'cm.cut': "Kes",
'cm.pin': "Sabitle: menü açık kalır",
'cm.unpin': "Sabitlemeyi kaldır",
'cm.closePanel': "Kapat",
'cm.gone': "Yok: bu menünün ait olduğu şey şu an ekranda değil.",
'cm.menu': "Menü",
'cm.tearOff': "Ctrl+tık veya orta tık: bu alt menüyü sabitle",
'cm.copy': "Kopyala",
'cm.paste': "Yapıştır",
'cm.selectAll': "Tümünü seç",