feat(renderer): register 9 modal-opening commands in command store

This commit is contained in:
2026-06-05 19:44:13 +05:30
parent 9306a9c23b
commit fe62c8814c
2 changed files with 123 additions and 32 deletions
@@ -12,9 +12,41 @@ import { useMenuAction } from '@/hooks/use-menu-action';
* Phase 7+ will add the dialog-driven commands (export, settings, etc.) * Phase 7+ will add the dialog-driven commands (export, settings, etc.)
* once the corresponding modals exist. * once the corresponding modals exist.
*/ */
export function useRegisterMenuCommands(): void { export function registerMenuCommands(): void {
// Register handlers in the command store. const { registerMany } = useCommandStore.getState();
useEffect(() => {
registerMany({
'settings.open': () => useAppStore.getState().openModal('settings'),
'help.about': () => useAppStore.getState().openModal('about'),
'help.welcome': () => useAppStore.getState().openModal('welcome'),
'file.exportPdf': () => {
const activeTabId = useFileStore.getState().activeTabId;
if (!activeTabId) return;
useAppStore.getState().openModal('export-pdf', { sourcePath: activeTabId });
},
'file.exportDocx': () => {
const activeTabId = useFileStore.getState().activeTabId;
if (!activeTabId) return;
useAppStore.getState().openModal('export-docx', { sourcePath: activeTabId });
},
'file.exportHtml': () => {
const activeTabId = useFileStore.getState().activeTabId;
if (!activeTabId) return;
useAppStore.getState().openModal('export-html', { sourcePath: activeTabId });
},
'file.exportBatch': () => {
const paths = useFileStore.getState().openTabs.map((t) => t.path);
if (paths.length === 0) return;
useAppStore.getState().openModal('export-batch', { sourcePaths: paths });
},
'file.confirmClose': () => {
/* stub — wired in later phase */
},
'app.quit': () => {
/* stub — wired in later phase */
},
});
const { register } = useCommandStore.getState(); const { register } = useCommandStore.getState();
register('file.open', () => { register('file.open', () => {
void useFileStore.getState().openFileDialog(); void useFileStore.getState().openFileDialog();
@@ -47,6 +79,12 @@ export function useRegisterMenuCommands(): void {
}); });
register('view.toggleSidebar', () => useAppStore.getState().toggleSidebar()); register('view.toggleSidebar', () => useAppStore.getState().toggleSidebar());
register('view.togglePreview', () => useAppStore.getState().togglePreview()); register('view.togglePreview', () => useAppStore.getState().togglePreview());
}
export function useRegisterMenuCommands(): void {
// Register handlers in the command store.
useEffect(() => {
registerMenuCommands();
}, []); }, []);
} }
@@ -0,0 +1,53 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { registerMenuCommands } from '@/lib/commands/register-menu-commands';
import { useCommandStore } from '@/stores/command-store';
import { useAppStore } from '@/stores/app-store';
import { useFileStore } from '@/stores/file-store';
import { useEditorStore } from '@/stores/editor-store';
describe('modal commands', () => {
beforeEach(() => {
localStorage.clear();
useCommandStore.setState({ handlers: {}, userBindings: {} } as any);
useAppStore.setState({ modal: { kind: null } } as any);
useFileStore.setState({ activeTabId: '/x.md', openTabs: [{ id: '/x.md', path: '/x.md', title: 'x.md', dirty: false }] } as any);
useEditorStore.setState({ buffers: new Map([['/x.md', { id: '/x.md', path: '/x.md', content: '# hi', dirty: false }]]) } as any);
});
it('settings.open opens settings modal', () => {
registerMenuCommands();
useCommandStore.getState().dispatch('settings.open');
expect(useAppStore.getState().modal).toEqual({ kind: 'settings' });
});
it('help.about opens about modal', () => {
registerMenuCommands();
useCommandStore.getState().dispatch('help.about');
expect(useAppStore.getState().modal).toEqual({ kind: 'about' });
});
it('help.welcome opens welcome modal', () => {
registerMenuCommands();
useCommandStore.getState().dispatch('help.welcome');
expect(useAppStore.getState().modal).toEqual({ kind: 'welcome' });
});
it('file.exportPdf opens export-pdf modal with active path', () => {
registerMenuCommands();
useCommandStore.getState().dispatch('file.exportPdf');
expect(useAppStore.getState().modal).toEqual({ kind: 'export-pdf', props: { sourcePath: '/x.md' } });
});
it('file.exportDocx opens export-docx modal', () => {
registerMenuCommands();
useCommandStore.getState().dispatch('file.exportDocx');
expect(useAppStore.getState().modal).toEqual({ kind: 'export-docx', props: { sourcePath: '/x.md' } });
});
it('file.exportBatch opens export-batch modal with all open files', () => {
useFileStore.setState({ activeTabId: '/x.md', openTabs: [{ id: '/x.md', path: '/x.md', title: 'x.md', dirty: false }, { id: '/y.md', path: '/y.md', title: 'y.md', dirty: false }] } as any);
registerMenuCommands();
useCommandStore.getState().dispatch('file.exportBatch');
expect(useAppStore.getState().modal).toEqual({ kind: 'export-batch', props: { sourcePaths: ['/x.md', '/y.md'] } });
});
});