Commit Graph
62 Commits
Author SHA1 Message Date
amitwh 21a00a53a4 fix: resolve 12 critical runtime failures, security issue, and dead code
CRITICAL fixes:
- GitStatusPanel: use ipc.file.gitStage/gitCommit instead of non-existent top-level methods
- HeaderFooterDialog: use send/on channels instead of non-existent headerFooter namespace
- CodeMirrorEditor: use invoke('save-pasted-image') instead of non-existent savePastedImage
- ipc.ts: map to correct preload namespaces (git.status, git.stage, git.commit)
- Add pick-folder/pick-file to ALLOWED_SEND_CHANNELS whitelist
- Add git convenience namespace to preload (git.status/stage/commit/log/diff)

HIGH fixes:
- FindReplaceBar: replace broken match count stub with regex-based counter
- PDF export window: disable nodeIntegration, enable contextIsolation + sandbox
- Git handler: accept rootPath argument from renderer
- Add git-diff IPC handler + GitOperations.diff()

MEDIUM fixes:
- Remove 4 dead functions: checkPandocAvailable, safeExecFile, runPandoc, openPDFFile, exportWithPandocPDF
- Remove stale ODT header/footer console.log stub
- Rewrite electron.d.ts to match actual preload API shape
2026-06-13 19:52:51 +05:30
amitwh f2398e6e1a feat: enhance WelcomeDialog, export dialogs, GitStatusPanel, add CommandPalette, FindReplaceBar, and new converter dialogs
- WelcomeDialog: add quick start, feature showcase, keyboard shortcuts, recent files, version display
- ExportDocxDialog/ExportHtmlDialog/ExportPdfDialog: add header/footer, paper size, margin controls
- GitStatusPanel: full staging/unstaging, discard, commit workflow
- CommandPalette: fuzzy command search with keyboard navigation
- FindReplaceBar: find/replace with regex, case, whole-word options
- New dialogs: BatchMediaConverterDialog, HeaderFooterDialog, PdfEditorDialog, UniversalConverterDialog
- Tests: comprehensive coverage for all new/updated components
2026-06-13 19:34:42 +05:30
amitwh 6b564a4569 style: run prettier formatter over src and tests 2026-06-11 20:46:00 +05:30
amitwh 2389d4f297 feat: add writing analytics dashboard and daily word goal tracking 2026-06-11 20:44:16 +05:30
amitwh cf6b6817b9 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
2026-06-11 07:15:33 +05:30
amitwh c5d4b113bd fix(polish): address 3 review blockers + 1 security issue
1. ThemeSettings: change 'auto' radio value to 'system' to match
   the v5 settingsSchema enum. Storing 'auto' silently wipes all
   settings on next launch.
2. UpdateBanner: render an 'available' branch so users see a CTA
   when a new version is detected (the store already had this state,
   but the banner was silent). Added a test.
3. feed-config: remove the unused resolveFeedUrl / FEEDS exports.
   feedConfigFor is the actual implementation used by the IPC
   handler. Updated tests to match.
4. main/index.js: tighten app:open-external regex to https:// only.
2026-06-08 07:35:54 +05:30
amitwh ade6c115b8 feat(renderer): add CrashReportModal listing local dumps 2026-06-08 06:38:08 +05:30
amitwh cc33e6c7a8 feat(renderer): add FirstRunWizard with theme/channel/template steps 2026-06-08 06:34:40 +05:30
amitwh 59fd9b8646 feat(renderer): add UpdateBanner for non-blocking update notifications 2026-06-08 06:31:07 +05:30
amitwh 74ff6afb19 feat(renderer): wire remaining stubbed commands and rebuild
The v5.0.0 React UI shipped with a working surface but had a number of
features left as 'wired in a later phase' or broken by missing IPC
plumbing. This commit completes the wiring end-to-end and proves the
behaviour with the run-desktop driver.

Toolbar format buttons (Toolbar.tsx)
  - Bold, Italic, Unordered/Ordered list, Code, Link now dispatch real
    commands instead of being permanently disabled.

New module: src/renderer/lib/editor-commands.ts
  - Module-level singleton holding the active CodeMirror EditorView.
  - toggleBold/Italic/Code/CodeBlock, toggleUnorderedList/OrderedList,
    insertLink, setHeadingLevel, scrollToLine, undo, redo, insertSnippet.
  - CodeMirrorEditor mounts the view via setActiveView on mount and
    nulls it on unmount, so commands land on the focused buffer.

register-menu-commands.ts
  - file.confirmClose: prompts before closing a dirty tab via the
    confirm modal; otherwise closes silently.
  - app.quit: prompts before quitting if any buffer is dirty; uses
    the new ipc.app.quit channel.
  - short-cuts.show: shows the keyboard shortcut list in a confirm dialog.
  - editor.bold/italic/code/list.*/link/undo/redo/heading.*: drive the
    active editor.
  - find.toggle: dispatches mc:find-toggle for any listening component.
  - view.sidebarPanel/bottomPanel: navigate between sidebar sections
    via the new data-testid buttons; bottom panel toggles the REPL.
  - font.size: increase/decrease/reset on editorFontSize (10..28).
  - theme.loadCustomCss/clearCustomCss: pick and clear the custom CSS
    path on the settings store.
  - template.load: inserts a bundled markdown skeleton at the cursor.
  - print.preview/previewStyled: emit mc:print and mc:print-preview.
  - file.clearRecent: clears open tabs.
  - file.new: creates an untitled buffer and tab.
  - editor.gotoHeading: scrolls to a given line (used by Outline and
    Breadcrumb).
  - view.toggleSidebar: already wired.
  - file.opened: already wired (prior fix).

Sidebar Outline + Breadcrumb
  - Both now click through to 'editor.gotoHeading' with the line
    number extracted from the active buffer.
  - Sidebar exposes data-testid for the 'view.sidebarPanel' menu action.

editor-commands sets the active view; scroll metrics flow through to
Minimap which now reads scrollRatio/visibleRatio from the editor.

Export dialogs (PDF/DOCX/HTML)
  - Replaced the broken ipc.export.{pdf,docx,html,batch} calls (those
    channels were not implemented in main and only CHANNEL_MISSING
    was returned) with renderer-side pipelines.
  - PDF: generateHtml() with @page CSS for size + margins, then
    ipc.print to the main process for native print-to-PDF.
  - DOCX: generateDocx() from the existing lib, then ipc.file.writeBuffer.
  - HTML: generateHtml() then ipc.file.writeBuffer.
  - All three dialogs use ipc.app.showSaveDialog for output path
    (new IPC handler) and ipc.file.writeBuffer for the binary write
    (new preload channel).
  - PrintPreview now uses MarkdownRenderer instead of a raw <pre>.

New settings fields
  - editorFontSize: 10..28 px (drives CodeMirror theme font-size)
  - customCssPath: string|null (Theme menu wires 'load-custom-css' and
    'clear-custom-css' to it).

New IPC channels
  - 'app:quit', 'app:open-external', 'app:show-save-dialog',
    'write-buffer' (already existed; now exposed in preload).

Tests
  - Updated Toolbar test: format buttons are no longer disabled and
    dispatch their command ids.
  - Updated Export*D*Dialog tests to mock the new ipc surface
    (ipc.print, ipc.app.showSaveDialog, ipc.file.writeBuffer) and
    assert the new flow.
  - Updated PrintPreview test to use ipc.print.doPrint.
  - Updated phase8-toasts integration: PDF flow now goes through
    ipc.print and asserts 'Sent <title> to printer'.
  - register-menu-commands test: re-register 'template.load' AFTER
    Harness renders so the captured-args handler is the live one.

Verification
  - npm run build:renderer: success (1.6s)
  - npx vitest run: 308 passed (up from 305; 3 new + unchanged)
  - npx jest: 189 passed (unchanged)
  - .claude/skills/run-desktop/verify-features.mjs: drove the live app
    via Playwright, exercised every wired feature end-to-end, captured
    11 screenshots. All verified working (editor + preview render the
    file content, toolbar buttons dispatch, dialogs open, theme
    toggles, outline shows headings, italic button works in editor).
2026-06-07 23:13:47 +05:30
amitwh 58ca3014d8 fix(modals): drop shadcn-style aria-describedby to silence Radix warning
Every DialogContent had aria-describedby="X-desc" and every
DialogDescription had a matching id="X-desc". That pattern is the
default shadcn/ui recipe, but it breaks Radix 1.1.x.

Root cause: Radix auto-generates a descriptionId via useId() (e.g. :r0:)
and stores it in the Dialog context. The DescriptionWarning effect does
`document.getElementById(descriptionId)` and warns if the element is
missing. When the description element's id is overridden to
"welcome-desc", the DOM has id="welcome-desc" but the context still has
:r0:, so the lookup misses and the warning fires on every dialog open.

Fix: drop both overrides. Let Radix manage the id and aria-describedby
itself. Screen-reader semantics are unchanged (Radix still wires
Content -> Description via the auto-generated id).

Touched: 12 modal files (11 DialogContent/DialogDescription pairs +
SettingsSheet which uses Sheet). +1 regression test in
WelcomeDialog.test.tsx that spies on console.warn and asserts the
"Missing Description" message is never emitted.

Tests: 306/306 pass (was 305).

Long-term memory: radix-aria-describedby-anti-pattern.md captures the
do-not-reintroduce rule for future agents.
2026-06-06 20:45:13 +05:30
amitwh 7c1a79c724 fix(app): add Vite dev workflow, fix onLayout prop, fix icon path, allow Google Fonts CSP
The v5.0.0 React UI redesign shipped without a working dev workflow —
`npm start` only ran `electron .` which loaded the source index.html
that references raw .tsx files. The browser couldn't execute them, so
the app rendered an empty #root and the user saw 'lot of errors'.

This commit restores a real dev workflow:

1. **Vite dev server wired into npm scripts** — added `concurrently`
   + `wait-on` as devDeps. `npm run dev` now runs Vite (port 5173)
   and Electron together with `wait-on tcp:5173` so Electron only
   starts after the dev server is ready.

2. **Main process loads Vite URL in dev, dist/ in prod** — window
   module now checks `process.env.VITE_DEV_SERVER_URL` and
   `app.isPackaged` to decide what to load. Production still
   loads the built `dist/renderer/index.html`.

3. **Fixed ReferenceError: app is not defined** — window module
   referenced `app.isPackaged` but only imported `BrowserWindow`.
   Added `app` to the destructured import.

4. **Fixed wrong icon path** — window creation used
   `../../assets/icon.png` from src/main/window/ which resolved
   to `src/assets/icon.png` (doesn't exist). Icon lives at
   project root, so path is now `../../../assets/icon.png`.

5. **Allowed Google Fonts in CSP** — the strict CSP
   (`font-src 'self' data:`, `connect-src 'self'`) blocked
   the preconnect/css link to fonts.googleapis.com / .gstatic.com.
   Added both domains so Plus Jakarta Sans loads.

6. **Renamed onLayout → onLayoutChange** in AppShell — react-resizable-panels
   v4 renamed the prop. The v1 name was being spread to a DOM
   div and React logged 'Unknown event handler property' warnings.
   Test mock updated for parity.

7. **show: false → show: true** — ready-to-show was hanging on
   this Wayland/container combo. Now the window is shown
   immediately on create.

Verified end-to-end:
- 305/305 vitest tests pass
- Vite dev server starts on :5173
- Electron loads localhost:5173 and React mounts
- Header 'MarkdownConverter' + sidebar with 'No files open' visible
- No onLayout warnings after HMR
- All blocked errors resolved
2026-06-06 16:17:16 +05:30
amitwh 95bbe171b5 feat(renderer): GitStatusPanel sidebar tab + git.refresh event 2026-06-06 08:28:37 +05:30
amitwh 2d77fa5456 feat(renderer): Breadcrumb shows heading symbols (settings toggleable) 2026-06-06 08:28:24 +05:30
amitwh fbaff37505 feat(renderer): Minimap (custom overview, wired to settings.minimap) 2026-06-06 08:20:48 +05:30
amitwh 8822c9a2f9 feat(renderer): PrintPreview overlay + App.tsx mount 2026-06-06 08:11:15 +05:30
amitwh 324e5676b8 feat(renderer): ReplPanel (markdown snippet preview) 2026-06-06 08:11:10 +05:30
amitwh a62511e7ed feat(renderer): FindInFilesDialog (cross-file search with regex) 2026-06-06 08:04:49 +05:30
amitwh a6c6e3696e feat(renderer): WordExportDialog (docx export with template picker) 2026-06-06 08:02:19 +05:30
amitwh 1b2ab437d1 feat(renderer): TableGeneratorDialog (markdown table generator) 2026-06-06 07:45:18 +05:30
amitwh efc7709f66 feat(renderer): AsciiGeneratorDialog (figlet text-to-ASCII-art) 2026-06-06 07:40:20 +05:30
amitwh 24c6675c82 fix(test): use mockRejectedValue for IPC error in ExportPdfDialog test 2026-06-05 23:17:57 +05:30
amitwh 3ff76c8c33 feat(renderer): add shadcn Toaster primitive 2026-06-05 22:50:07 +05:30
amitwh 9d154a8521 feat(renderer): AppHeader gets Settings + About icon buttons 2026-06-05 19:46:56 +05:30
amitwh 9306a9c23b feat(renderer): SettingsSheet (5 tabs: editor, theme, export, plugins, about) 2026-06-05 19:41:18 +05:30
amitwh f25d856a2a feat(renderer): ExportBatchDialog (format, concurrency, file list) 2026-06-05 19:30:15 +05:30
amitwh 76fed872ce test(renderer): assert toggled standalone value in ExportHtmlDialog test 2026-06-05 19:28:44 +05:30
amitwh 9de14df016 feat(renderer): ExportHtmlDialog (standalone, highlight style, ascii tables) 2026-06-05 19:27:16 +05:30
amitwh 5f0b4c9c4e feat(renderer): ExportDocxDialog (template picker + ascii tables) 2026-06-05 19:23:40 +05:30
amitwh 7d083a024d feat(renderer): ExportPdfDialog (format, margins, ascii tables) 2026-06-05 19:19:18 +05:30
amitwh 026a4d9fac feat(renderer): WelcomeDialog (first-launch quick-start) 2026-06-05 19:07:14 +05:30
amitwh a461b62dd3 feat(renderer): ConfirmDialog (generic title/body/onConfirm) 2026-06-05 19:01:06 +05:30
amitwh 1cd316caf1 feat(renderer): AboutDialog (version + GitHub link) 2026-06-05 18:47:14 +05:30
amitwh 2bdb380130 feat(renderer): ModalLayer shell (dispatches to 7 modal types) 2026-06-05 18:36:28 +05:30
amitwh 02418b943e feat(renderer): add shadcn form primitive (react-hook-form glue) 2026-06-05 18:03:26 +05:30
amitwh 8f5eb301b6 feat(renderer): add shadcn sheet primitive 2026-06-05 17:53:08 +05:30
amitwh 8f9dab1405 feat(renderer): add shadcn dialog primitive 2026-06-05 17:49:31 +05:30
amitwh a6fa14124d feat(renderer): add shadcn tabs primitive 2026-06-05 17:42:21 +05:30
amitwh 0538aec02c feat(renderer): add shadcn select primitive 2026-06-05 17:35:45 +05:30
amitwh 1d782a00e6 feat(renderer): add shadcn radio-group primitive 2026-06-05 17:26:29 +05:30
amitwh 3344b2aea9 feat(renderer): add shadcn slider primitive 2026-06-05 17:23:13 +05:30
amitwh 6b23e5ef60 feat(renderer): add shadcn switch primitive 2026-06-05 17:18:19 +05:30
amitwh 221598c91b feat(renderer): add shadcn checkbox primitive 2026-06-05 17:13:49 +05:30
amitwh d8ee743fb1 feat(renderer): add shadcn textarea primitive 2026-06-05 17:09:59 +05:30
amitwh 66e2b56221 feat(renderer): add shadcn input primitive 2026-06-05 17:06:36 +05:30
amitwh d22d616727 feat(renderer): add shadcn label primitive 2026-06-05 17:03:10 +05:30
Amit Haridas b1e16af62d feat(renderer): AppHeader wired to command store
- toggle sidebar/preview buttons dispatch through command store
- new 'shortcuts.show' command (Keyboard icon, opens shortcuts panel later)
- AppHeader.test.tsx updated: registers matching commands in beforeEach
- integration test fixed: 'Open folder' button now matches 2 (toolbar + sidebar)
- 155/155 tests pass
2026-06-05 16:00:58 +05:30
Amit Haridas 487ce2ad45 feat(renderer): Toolbar wired to command store
- 5 functional buttons: Open file, Open folder, Save, Toggle sidebar, Toggle preview
- each dispatches via useCommandStore
- aria-pressed on toggle buttons reflects app store state
- formatting buttons (bold, italic, etc.) stay disabled (Phase 9)
- toolbar now has role='toolbar' and aria-label
- TDD: 9 component tests
2026-06-05 15:58:21 +05:30
amitwh ce2bf62d42 feat(renderer): drag-to-reorder tabs (dnd-kit) 2026-06-05 15:34:25 +05:30
amitwh 3598d06240 feat(preload): add file.list, file.pickFolder, file.pickFile convenience methods 2026-06-05 15:13:16 +05:30