diff --git a/apps/desktop/src/screens/Accounts.tsx b/apps/desktop/src/screens/Accounts.tsx index c0af2d0..64aa20b 100644 --- a/apps/desktop/src/screens/Accounts.tsx +++ b/apps/desktop/src/screens/Accounts.tsx @@ -3,7 +3,7 @@ // issuer id, .p8). Keys live in the machine's credential profiles (~/.storebound, shared with the CLI); // the app keeps a label, the studio and the profile name only. Per account: a health // check (key works / permission missing / revoked, with the fix) and "Import apps" (every app the key can see). -import { useContextMenu } from '../ui/ContextMenu'; +import { type MenuInput, useContextMenu, useMenuButton } from '../ui/ContextMenu'; import { copyToast } from '../ui/app-menu'; import { type FormEvent, useEffect, useState } from 'react'; import { type Account, type AccountCheck, api, errorText, STUDIO_COLORS, type Studio, type StudioColor } from '../api'; @@ -59,8 +59,8 @@ function AccountRow({ a, busy, setBusy, onError }: { a: Account; busy: string | const save = (e: FormEvent) => { e.preventDefault(); run(`ed-${a.id}`, async () => { await api.updateAccount(a.id, label, studio || null); if (a.kind === 'play' && a.profile && dev.trim() !== (a.developerId ?? '')) await api.setPlayDeveloper(a.id, dev.trim() || null); await d.reload(); setEdit(false); }); }; const check = h?.check; const cm = useContextMenu(); - return ( -
[ + const more = useMenuButton(); + const menu = (): MenuInput => [ { label: t('acct.test'), icon: 'shield', disabled: busy ? t('cm.busy') : false, onSelect: () => run(`ck-${a.id}`, () => d.checkAccount(a.id)) }, { label: t('acct.import'), icon: 'download', disabled: busy || d.importBusy ? t('cm.busy') : false, onSelect: () => run(`im-${a.id}`, () => d.importApps(a.id)) }, { label: t('acct.edit'), icon: 'edit', onSelect: () => setEdit(true) }, @@ -73,7 +73,9 @@ function AccountRow({ a, busy, setBusy, onError }: { a: Account; busy: string | 'sep', { label: ignored ? t('acct.unignore') : t('acct.ignore'), icon: ignored ? 'eye' : 'eyeOff', onSelect: () => { void d.updateOverrides(o => withIgnored(o, [`account:${a.id}`], !ignored)); } }, { label: t('accounts.remove'), icon: 'trash', danger: true, disabled: busy ? t('cm.busy') : false, onSelect: () => run(`rm-${a.id}`, async () => { await api.removeAccount(a.id); await d.reload(); }) }, - ])}> + ]; + return ( +
@@ -91,8 +93,7 @@ function AccountRow({ a, busy, setBusy, onError }: { a: Account; busy: string | - - +
{edit && ( @@ -132,6 +133,7 @@ function StudioCard({ s, accounts, focus }: { s: Studio | null; accounts: Accoun const storeOnly = apps.filter(a => !a.project).length; const act = async (key: string, fn: () => Promise) => { setBusy(key); setError(null); try { await fn(); await d.reload(); } catch (e) { setError(errorText(e)); } finally { setBusy(null); } }; const id = s ? `studio-${s.id}` : 'studio-none'; + const more = useMenuButton(); useEffect(() => { if (focus) document.getElementById(id)?.scrollIntoView({ block: 'start' }); }, [focus, id]); return (
@@ -146,9 +148,12 @@ function StudioCard({ s, accounts, focus }: { s: Studio | null; accounts: Accoun {s && (
- - {s.logo && } - +
)}
diff --git a/apps/desktop/src/screens/AppFolders.tsx b/apps/desktop/src/screens/AppFolders.tsx index bbfd2fe..4a59ae2 100644 --- a/apps/desktop/src/screens/AppFolders.tsx +++ b/apps/desktop/src/screens/AppFolders.tsx @@ -85,9 +85,7 @@ export function AppFolders() { return (
- - - } /> + {t('action.addFolder')}} /> {error && {error}} {!d.projects.length ? ( diff --git a/apps/desktop/src/screens/Portfolio.tsx b/apps/desktop/src/screens/Portfolio.tsx index 1f6781f..31cdfbb 100644 --- a/apps/desktop/src/screens/Portfolio.tsx +++ b/apps/desktop/src/screens/Portfolio.tsx @@ -401,7 +401,7 @@ export function Portfolio() {

{t('portfolio.subStudios', { count: visible.length, stores, studios: d.studios.length })}{d.live ? ` ยท ${t('pf.readAgo', { when: ago(d.live.at) })}` : ''}

- + {neverImported === 0 && }