Desktop: custom context menus everywhere, never the browser's menu

One ContextMenu in the design system (keyboard, type-ahead, submenus, check items,
disabled reasons, Shift+F10 / Menu key, viewport placement, light and dark). The
native menu is prevented globally; text fields keep Cut / Copy / Paste / Select all.
Menus on sidebar and portfolio apps, app hero, releases, store art, live art,
reviews, checks, editor fields, catalog, prices, accounts, app folders, ignored.
This commit is contained in:
CRTkafa 2026-10-23 08:59:14 +08:00
parent 944b24fe59
commit dece83c3e8
23 changed files with 839 additions and 28 deletions

View file

@ -1,6 +1,9 @@
// One app across both stores: header (icon, studio, ids, store state, pairing), then the tabs. A store-only app (no
// app folder) shows its store reads (releases, health, reviews, TestFlight) read-only, with "Link a folder" and
// "Start an app folder here" to make it a full app.
import { useContextMenu } from '../ui/ContextMenu';
import { appMenu } from '../ui/app-menu';
import { useShowIgnored } from '../lib/show-ignored';
import { useState } from 'react';
import { api, errorText } from '../api';
import { type Key, t } from '../i18n';
@ -122,10 +125,13 @@ export function AppView({ app, tab }: { app: UnifiedApp; tab: AppTab }) {
const iosNow = l ? storeNow(all, 'ios').now : null, androidNow = l ? storeNow(all, 'android').now : null;
const att = attention(app.key, app.name, e, l);
const open = (url: string) => { api.openExternal(url).catch(() => {}); };
const cm = useContextMenu();
const [showIgnored] = useShowIgnored();
return (
<div className="page ds-app">
<Hero name={name} icon={d.iconFor(app)} projectId={app.project && !app.project.missing ? app.project.id : null}
{...cm(() => appMenu(app, d, nav, { showIgnored }))}
badges={<>
{e?.summary?.profile && app.project && <Chip tone="outline">{t(`profile.${e.summary.profile}` as 'profile.app')}</Chip>}
{!app.project && <StoreOnlyTag />}