Complete the app: capture UI, dialogs, template manager, shortcuts help
Template tests / tests (push) Failing after 21s

- Editor topbar reworked: Back | Capture ▾ (full screen/window/region/
  delay/paste/import/session) | Save | Export | Share (.sfgz) | More ▾
  (rename, guide placeholders, backups, linked guide, shortcuts,
  settings)
- New dialogs: backups & snapshots (undoable restore), guide/global
  placeholder editor, keyboard-shortcuts reference, template manager
  (rename/duplicate/delete/share/import .sfglt)
- Export dialog: editable per-format options generated from exporter
  defaults, save-as-template, preview opens the file in the default
  viewer and keeps the dialog open for tweaking
- export:defaults IPC + preload entry
- CSS for blocks panel, focused-view sliders, export options, rows
- ipc-surface test: every preload channel has a main handler; renderer
  api.*/dialogs.* usage stays within the exposed surface (60 tests)
- CHANGELOG/README updated; prompt2.md checklist fully ticked

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Iisyourdad
2026-06-10 22:15:15 -05:00
parent 382dbc9717
commit 6e790832f5
10 changed files with 520 additions and 60 deletions
+44 -9
View File
@@ -1195,19 +1195,54 @@ class GuideEditor {
defaultFormat: 'pdf',
defaultOutDir: settings.exports?.lastOutputDirs?.pdf || '',
onChooseDir: async (format) => api.export.chooseDir({ format }),
onPreview: async ({ format, templateName, outDir }) => {
const options = templateName ? await api.templates.load({ format, name: templateName }) : {};
onLoadDefaults: async (format) => api.export.defaults({ format }),
onLoadTemplate: async (format, name) => api.templates.load({ format, name }),
onSaveTemplate: async (format, name, options) => {
await api.templates.save({ format, name, options });
this.onToast(`Template “${name}” saved.`);
},
onManageTemplates: async (format, mode) => {
if (mode === 'manage') {
await dialogs.showTemplateManager({
format,
names: await api.templates.list({ format }),
onRename: async (name, newName) => {
await api.templates.rename({ format, name, newName });
return api.templates.list({ format });
},
onDuplicate: async (name) => {
await api.templates.duplicate({ format, name });
return api.templates.list({ format });
},
onDelete: async (name) => {
await api.templates.delete({ format, name });
return api.templates.list({ format });
},
onImport: async () => {
const res = await api.templates.import();
if (res?.ok) this.onToast(`Imported template for ${res.format}.`);
return api.templates.list({ format });
},
onExport: async (name) => {
const res = await api.templates.export({ format, name });
if (res?.ok) this.onToast('Template shared as .sfglt.');
},
});
}
return api.templates.list({ format });
},
onPreview: async ({ format, options }) => {
const preview = await api.export.preview({ guideId: this.guideId, format, options });
if (preview && preview.file) await api.shell.showItemInFolder({ target: preview.file });
this.onToast(`Preview written to ${preview.file}`);
if (preview && preview.file) {
await api.shell.openPath({ target: preview.file }); // open in default viewer
this.onToast('Preview opened (first steps only).');
}
return true;
},
onExport: async ({ format, templateName, outDir }) => {
const options = templateName ? await api.templates.load({ format, name: templateName }) : {};
onExport: async ({ format, options, outDir }) => {
const result = await api.export.run({ guideId: this.guideId, format, options, outDir });
if (result && result.file) {
this.onToast(`Exported ${format}`);
}
if (result && result.ok === false) return false;
if (result && result.file) this.onToast(`Exported ${format}.`);
return true;
},
});