- capture.js: window-mode falls back to screen under WSLg; app window hides during capture (showInactive restore for hotkey path so focus is not stolen from the documented app); region capture hides too - editor: Blocks panel (text/code/table block editors), focused-view zoom/pan sliders, capture context menu, paste-image step, share as .sfgz, apply-style-across step/guide, annotation copy/paste, tool-key shortcuts (s/r/o/l/a/t/g/n/b/h/m/u/c), PageUp/Down step nav, Ctrl+=/-/0 zoom, Ctrl+Delete step delete, Shift-arrow fast nudge - prompt2.md: prescriptive handoff checklist for finishing remaining dialogs/topbar/IPC/polish work Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
8.0 KiB
prompt2.md — Finish StepForge (handoff checklist)
You are finishing a nearly-complete offline desktop app called StepForge
(an Electron + vanilla-JS clone of Folge, see prompt.md for the full spec).
Work through the unchecked boxes below in order, committing after each
section. Keep every change consistent with the existing code style.
Ground rules (do not skip)
- Run
bash tests/run_test.shafter every section. It must stay green. - The app must keep working: verify visually with the screenshot hook:
Then look at /tmp/x.png. Useful JS snippets:
rm -rf /tmp/sf-x && STEPFORGE_DATA_DIR=/tmp/sf-x \ STEPFORGE_SCREENSHOT=/tmp/x.png \ STEPFORGE_SCREENSHOT_JS="<js to run in page>" timeout 30 npm start- welcome: (no JS needed)
- library:
window.stepforgeApp.openExistingWorkspace() - editor:
window.stepforgeApp.startNewCapture()
- Renderer files (
app/renderer/*.js) are plain scripts wrapped in IIFEs. NEVER add top-levelconstoutside the IIFE — scripts share global scope and duplicate consts break the whole app with a SyntaxError. window.stepforge(fromapp/preload.js) is the ONLY way the renderer talks to the system. New IPC = add handler inapp/main.jssetupIpc()- matching entry in
app/preload.js.
- matching entry in
- Annotations/steps/guides are saved through
this.saveStepDebounced()/api.step.saveinapp/renderer/editor.js. Mutatethis.currentStep, setthis.pendingSave = true, call the debounced save. - No network code anywhere. No new npm dependencies.
- Commit messages end with:
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
State when this file was written
Done already (do not redo): core library (core/, exporters/, 57 unit
tests), Electron shell, library UI, three-pane editor with annotation
canvas, welcome screen (New Capture / Existing Workspace / Settings),
sample pipeline, .deb + tarball packaging, build report.
In flight (check git status / git log first — finish or fix anything
half-done): capture-service fixes and editor additions listed in sections
1–3 below may already be partially applied to app/capture.js and
app/renderer/editor.js.
Checklist
1. Capture service hardening (app/capture.js) — [x] DONE
grab('window')requests['window','screen']and falls back to the screen source when the compositor exposes no window sources (WSLg).withWindowHidden(fn, {refocus})hides the app window during capture (350 ms repaint pause), restores withshowInactive()whenrefocus:false(hotkey path must not steal focus).shoot()acceptshideWindow/refocus;regionCapturehides too.
2. Editor: blocks, focused view, shortcuts (app/renderer/editor.js) — [x] DONE
- Props panel "Blocks" section: add/edit/delete text blocks
(position/level/title/body), code blocks (language/code), table
blocks (pipe-separated rows). Buttons
+ Text block / + Code / + Table. - Focused-view sliders (zoom 1–3, panX/panY 0–1) shown when the
Focused checkbox is on; write to
step.focusedView.*. openCaptureMenu(event)context menu: full screen / window / region / 3 s delay / paste image / import images / start-finish session.pasteClipboardStep(),shareAsFile()(.sfgz viaapi.archive.export),openBackupsDialog(),openGuidePlaceholders(),openShortcutsHelp(),applyStyleAcross('step'|'guide')methods.- "Style → step" / "Style → guide" buttons in the annotation editor.
- Shortcuts in
onDocumentKeyDown(only when target not editable): tool keys s/r/o/l/a/t/g/n/b/h/m/u/c, PageUp/PageDown step nav, Ctrl+=/-/0 zoom, Ctrl+C/V annotation copy/paste (V falls back to OS-clipboard image -> new step), Ctrl+Delete delete step, Shift+arrows = 10px nudge.
3. Dialogs (app/renderer/dialogs.js) — add and export via
window.StepForgeDialogs:
showBackupsDialog({snapshots, onCreate, onRestore})— list of snapshot names with a Restore button each, "Create snapshot" button on top (onCreate returns the refreshed list; re-render it).showPlaceholdersDialog({title, hint, values, onSave})— key/value rows with add/remove, same pattern as the placeholder rows already insideshowSettingsDialog(copy that code).showShortcutsDialog()— static table of the shortcuts from section 2 plus Ctrl+S save, Ctrl+/ quick actions, Alt+arrows move step.- Extend
showExportDialog: a "Save as template…" button (prompts a name, calls newonSaveTemplate({format, name})), and a "Manage…" button listing templates with rename/duplicate/delete/ import (.sfglt)/export (useapi.templates.*, all already exist in preload).
4. Topbar rework (app/renderer/app.js, editor branch of renderTopbar)
- Buttons: Back | Capture (primary; onClick
this.editor.openCaptureMenu(e)) | Save | Export | Share (this.editor.shareAsFile()) | More ▾ | guide title text. - "More ▾" opens
contextMenuwith: Rename guide / Guide placeholders… / Backups & snapshots… / Linked guide… / Keyboard shortcuts… / Settings. - Remove the old Rename/Local/Quick/Settings buttons from the topbar (they move into More; Quick actions stays reachable via Ctrl+/).
5. Main process additions (app/main.js + app/preload.js)
export:previewflow: after writing the preview, the renderer should call a newshell.openPathon the produced file so PDF/GIF previews actually open (changeonPreviewineditor.openExportDialogto callapi.shell.openPath({target: preview.file})).- New IPC
export:defaults {format}returning the exporter's DEFAULT_TEMPLATE (require the exporter module, read its export) so the export dialog can show editable options. Wire into preload asapi.export.defaults. - Optional (only if simple): render checkboxes/number/text inputs in
the export dialog from the defaults object (booleans -> checkbox,
numbers -> number input, strings -> text input), pass the edited
object as
optionsto export/preview/save-as-template.
6. CSS (app/renderer/style.css)
- Ensure
.spacer { flex: 1; }exists (block cards use it). - Style
.focused-controls,.blocks-list .block-card textarea(full width), keep visual language consistent (existing vars:--panel,--panel-2,--border,--accent,--radius).
7. Verification tour + tests
- Screenshot tour: welcome, library, editor (with blocks panel visible), capture menu open, export dialog, backups dialog. Check each PNG looks right; fix what doesn't.
- Add a unit test
tests/unit/ipc-surface.test.jsthat requiresapp/preload.jsis impossible (electron); instead statically check: everyipcRenderer.invoke('X')channel string in preload.js has a matchingh('X'handler string in main.js (read both files with fs, regex out the channel names, assert set equality or subset). bash tests/run_test.shgreen;bash scripts/verify.shgreen.- Regenerate samples if exporter behavior changed
(
node scripts/make-sample-guide.js), commit changes.
8. Docs + final commit
- Update CHANGELOG.md (### Added: capture menu, block editors, focused-view controls, shortcuts, backups dialog, template management, apply-style-across; ### Fixed: window-capture fallback, app hides itself during capture).
- README: mention the capture button and shortcut list location.
- Update THIS file: tick every box you completed.
- Final commit.
Testing philosophy (from prompt.md — do not violate)
Tests must exercise real workflows and assert on actual output (parse the file that was produced, check the pixels/bytes/structure), NOT grep for magic strings in source code. The IPC-surface test above is the one allowed exception since it guards wiring, and even it should compare extracted channel sets, not match arbitrary words.