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:
parent
445ab1adbc
commit
5236f002f1
35 changed files with 2308 additions and 123 deletions
|
|
@ -153,7 +153,7 @@ function AppCard({ r, icon, health, studio }: { r: CardRow; icon: string | null;
|
|||
const menu = useContextMenu();
|
||||
const [showIgnored] = useShowIgnored();
|
||||
return (
|
||||
<article className="pf-card" style={style} aria-label={name} {...menu(() => appMenu(app, d, nav, { showIgnored }))}>
|
||||
<article className="pf-card" style={style} aria-label={name} {...menu(() => appMenu(app, d, nav, { showIgnored }), `app:${app.key}`)}>
|
||||
<div className={`pf-shots${shots.length ? '' : ' empty'}`} aria-hidden="true">
|
||||
{shots.length ? shots.map((s, i) => <img key={i} src={s} alt="" draggable={false} loading="lazy" />) : <>
|
||||
<AppIcon name={app.name} src={icon} className="pf-hero-icon" />
|
||||
|
|
@ -373,7 +373,7 @@ export function Portfolio() {
|
|||
const ios = !!(app.ios || e?.app?.platforms.ios), android = !!(app.android || e?.app?.platforms.android);
|
||||
const sub = app.ios?.app.bundleId ?? e?.app?.platforms.ios?.bundleId ?? app.android?.app.id ?? e?.app?.platforms.android?.packageName ?? '';
|
||||
return (
|
||||
<tr key={app.key} className="clickable" onClick={() => open(app)} {...menu(() => appMenu(app, d, nav, { showIgnored }))}>
|
||||
<tr key={app.key} className="clickable" onClick={() => open(app)} {...menu(() => appMenu(app, d, nav, { showIgnored }), `app:${app.key}`)}>
|
||||
<td>
|
||||
<div className="cell-app">
|
||||
<AppIcon name={app.name} src={d.iconFor(app)} />
|
||||
|
|
@ -456,7 +456,7 @@ export function Portfolio() {
|
|||
<button className="link" aria-pressed={showIgnored} onClick={() => setShowIgnored(!showIgnored)}>{showIgnored ? t('ignored.hide', { count: ignoredApps.length }) : t('ignored.show', { count: ignoredApps.length })}</button>
|
||||
{showIgnored && ignoredApps.map(a => (
|
||||
<span key={a.key} className="row muted" style={{ gap: 4 }}>
|
||||
<button className="link" onClick={() => open(a)} {...menu(() => appMenu(a, d, nav, { showIgnored }))}>{a.name}</button>
|
||||
<button className="link" onClick={() => open(a)} {...menu(() => appMenu(a, d, nav, { showIgnored }), `app:${a.key}`)}>{a.name}</button>
|
||||
<button className="btn btn-sm btn-ghost btn-icon" onClick={() => d.updateOverrides(o => withIgnored(o, a.ignoreKeys, false))} aria-label={t('ignored.restore')} title={t('ignored.restore')}><Icon name="eye" /></button>
|
||||
</span>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue