feat: add standard macOS Window and Help menus

This commit is contained in:
Brad Groux 2026-08-30 02:49:21 -05:00
parent 45becddee9
commit 1db163d695
3 changed files with 87 additions and 1 deletions

View file

@ -44,7 +44,12 @@ describe('desktop native menu', () => {
it('exposes common actions with keyboard shortcuts', () => {
const dispatch = vi.fn();
const copyVersionInfo = vi.fn();
const template = createDesktopMenuTemplate({ status: status(), dispatch, copyVersionInfo });
const template = createDesktopMenuTemplate({
status: status(),
dispatch,
copyVersionInfo,
openHelp: vi.fn(),
});
const labels = template.flatMap((item) =>
Array.isArray(item.submenu) ? item.submenu.map((child) => child.label) : []
);
@ -80,6 +85,7 @@ describe('desktop native menu', () => {
status: status(),
dispatch: vi.fn(),
copyVersionInfo: vi.fn(),
openHelp: vi.fn(),
});
expect(template.some((item) => item.role === 'editMenu')).toBe(true);
@ -90,6 +96,7 @@ describe('desktop native menu', () => {
status: status('failed'),
dispatch: vi.fn(),
copyVersionInfo: vi.fn(),
openHelp: vi.fn(),
}).find((item) => item.label === 'Desktop');
const externalTest = Array.isArray(desktopMenu?.submenu)
? desktopMenu.submenu.find((item) => item.label === 'Test External Delivery')
@ -104,6 +111,7 @@ describe('desktop native menu', () => {
updateStatus: updateStatus('available'),
dispatch: vi.fn(),
copyVersionInfo: vi.fn(),
openHelp: vi.fn(),
}).find((item) => item.label === 'Veritas Kanban');
const downloadUpdate = Array.isArray(appMenu?.submenu)
? appMenu.submenu.find((item) => item.label === 'Download Update')
@ -115,4 +123,54 @@ describe('desktop native menu', () => {
expect(downloadUpdate?.enabled).toBe(true);
expect(installUpdate?.enabled).toBe(false);
});
it.each(['starting', 'ready', 'failed'] as const)(
'keeps the standard macOS Window and Help menus available while the server is %s',
(serverState) => {
const dispatch = vi.fn();
const openHelp = vi.fn();
const template = createDesktopMenuTemplate({
status: status(serverState),
dispatch,
copyVersionInfo: vi.fn(),
openHelp,
platform: 'darwin',
});
expect(template.map((item) => item.role ?? item.label)).toEqual([
'Veritas Kanban',
'File',
'editMenu',
'Navigate',
'Desktop',
'windowMenu',
'help',
]);
const helpMenu = template.find((item) => item.role === 'help');
const helpItems = Array.isArray(helpMenu?.submenu) ? helpMenu.submenu : [];
const productHelp = helpItems.find((item) => item.label === 'Veritas Kanban Help');
const onboarding = helpItems.find((item) => item.label === 'Show Setup & Diagnostics');
expect(productHelp?.enabled).not.toBe(false);
expect(onboarding?.enabled).toBe(true);
productHelp?.click?.(undefined as never, undefined as never, undefined as never);
onboarding?.click?.(undefined as never, undefined as never, undefined as never);
expect(openHelp).toHaveBeenCalledOnce();
expect(dispatch).toHaveBeenCalledWith('open-onboarding');
}
);
it('does not add macOS-only menus on other platforms', () => {
const template = createDesktopMenuTemplate({
status: status(),
dispatch: vi.fn(),
copyVersionInfo: vi.fn(),
openHelp: vi.fn(),
platform: 'linux',
});
expect(template.some((item) => item.role === 'windowMenu')).toBe(false);
expect(template.some((item) => item.role === 'help')).toBe(false);
});
});

View file

@ -40,6 +40,8 @@ import {
const require = createRequire(import.meta.url);
const { autoUpdater } = require('electron-updater') as typeof import('electron-updater');
const DESKTOP_HELP_URL =
'https://github.com/BradGroux/veritas-kanban/blob/main/docs/GETTING-STARTED.md';
let mainWindow: BrowserWindow | null = null;
let runtime: DesktopRuntime | null = null;
@ -184,6 +186,9 @@ function refreshDesktopMenu(): void {
status: runtime.snapshot(),
updateStatus: updateService?.snapshot(),
copyVersionInfo: () => clipboard.writeText(formatDesktopVersionInfo(appInfo)),
openHelp: () => {
void openValidatedExternalUrl(shell, DESKTOP_HELP_URL);
},
dispatch: (command) => {
if (commandDispatcher) {
dispatchDesktopMenuCommand(commandDispatcher, command);

View file

@ -14,8 +14,10 @@ import type {
export interface ConfigureDesktopMenuOptions {
dispatch(command: DesktopCommandName): void;
copyVersionInfo(): void;
openHelp(): void;
status: DesktopStatusSnapshot;
updateStatus?: DesktopUpdateStatus;
platform?: NodeJS.Platform;
}
export function configureDesktopMenu(options: ConfigureDesktopMenuOptions): void {
@ -35,6 +37,26 @@ export function createDesktopMenuTemplate(
};
};
const macosMenus: MenuItemConstructorOptions[] =
(options.platform ?? process.platform) === 'darwin'
? [
{ role: 'windowMenu' },
{
role: 'help',
submenu: [
{
label: 'Veritas Kanban Help',
click: () => options.openHelp(),
},
{
...command('open-onboarding'),
label: 'Show Setup & Diagnostics',
},
],
},
]
: [];
return [
{
label: 'Veritas Kanban',
@ -90,6 +112,7 @@ export function createDesktopMenuTemplate(
command('copy-redacted-diagnostics'),
],
},
...macosMenus,
];
}