fix: wire orphaned IPC channels, fix data-loss bug, print preview events, sidebar navigation

- Fix file.clearRecent sending IPC to main process instead of clearing openTabs
- Wire show-batch-converter, show-document-compare, open-header-footer-dialog IPC channels
- Add print preview event listeners (mc:print-preview, mc:print-preview-styled) in App.tsx
- Fix sidebar hidden bridge buttons toggling sidebar closed after scroll
- Update sidebar menu labels to match actual sections (Files, Outline, Git)
- Fix ipc.print to be an object with show/doPrint methods (was bare function)
- Update callers: ExportPdfDialog, pdf-export, PrintPreview
- Add 7 regression tests for all fixes
- Clean 2 obsolete snapshots
- Build Linux packages (deb, AppImage, snap) — 549 tests passing
This commit is contained in:
2026-06-11 07:15:33 +05:30
parent e25a5e1d75
commit cf6b6817b9
11 changed files with 179 additions and 24 deletions
@@ -143,4 +143,49 @@ describe('useRegisterMenuCommands + useBridgeNativeMenu', () => {
act(() => fireMenu('load-template-menu', 'blog-post.md'));
expect(captured).toBe('blog-post.md');
});
it('file.clearRecent does NOT clear openTabs', () => {
useFileStore.setState({
openTabs: [
{ id: '/a.md', path: '/a.md', title: 'a.md', dirty: false },
],
activeTabId: '/a.md',
});
render(<Harness />);
const sendSpy = vi.fn();
(window as any).electronAPI = { send: sendSpy };
act(() => useCommandStore.getState().dispatch('file.clearRecent'));
expect(useFileStore.getState().openTabs).toHaveLength(1);
expect(sendSpy).toHaveBeenCalledWith('clear-recent-files');
});
it('show-batch-converter IPC event dispatches batch.showConverter', () => {
let captured: unknown;
render(<Harness />);
useCommandStore.getState().register('batch.showConverter', (args) => {
captured = args;
});
act(() => fireMenu('show-batch-converter', 'image'));
expect(captured).toBe('image');
});
it('show-document-compare IPC event dispatches tools.documentCompare', () => {
let called = false;
render(<Harness />);
useCommandStore.getState().register('tools.documentCompare', () => {
called = true;
});
act(() => fireMenu('show-document-compare'));
expect(called).toBe(true);
});
it('open-header-footer-dialog IPC event dispatches settings.headerFooter', () => {
let called = false;
render(<Harness />);
useCommandStore.getState().register('settings.headerFooter', () => {
called = true;
});
act(() => fireMenu('open-header-footer-dialog'));
expect(called).toBe(true);
});
});