Fix new-capture auto-hide, library capture bar, step delete, and click-capture timing
Template tests / tests (push) Successful in 1m49s
Template tests / tests (push) Successful in 1m49s
- New Capture sessions now start paused; the window only tucks away once the user clicks "Start recording" in the capture bar instead of hiding ~1.2s after starting. - The capture status bar is shown only in the editor view, not over the library. - Fix openModal/confirmDialog resolving as cancelled when an action button is clicked, which made the step "Delete" button (and other modal actions) silently no-op. - Click-triggered captures now use the click-time cursor position for the marker and arm the capture cache as soon as recording starts, so the first click is captured instantly and accurately placed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+20
-9
@@ -137,6 +137,9 @@ class StepForgeApp {
|
||||
this.editorHost.classList.toggle('hidden', view !== 'editor');
|
||||
this.searchInput.classList.toggle('hidden', view !== 'library');
|
||||
this.renderTopbar();
|
||||
// The capture bar is editor-only; re-evaluate its visibility now that
|
||||
// the view changed.
|
||||
this.updateCaptureState(this.captureState);
|
||||
}
|
||||
|
||||
showWelcome() {
|
||||
@@ -188,13 +191,15 @@ class StepForgeApp {
|
||||
const state = await api.capture.session({ action: 'start', guideId: guide.guideId });
|
||||
this.updateCaptureState(state);
|
||||
const hotkey = this.state.settings?.capture?.hotkeyCapture;
|
||||
let how;
|
||||
if (state.clickCapture) {
|
||||
toast('Recording — every click grabs a step. StepForge tucks away; use the red tray icon to pause or finish.');
|
||||
how = 'every click will grab a step';
|
||||
} else if (state.intervalSec > 0) {
|
||||
toast(`Recording — a step every ${state.intervalSec}s. StepForge tucks away; use the red tray icon to pause or finish.`);
|
||||
how = `a step will be grabbed every ${state.intervalSec}s`;
|
||||
} else {
|
||||
toast(hotkey ? `Recording — press ${hotkey} to grab steps. Use the red tray icon to pause or finish.` : 'Capture session started.');
|
||||
how = hotkey ? `press ${hotkey} to grab steps` : 'use Shoot to grab steps';
|
||||
}
|
||||
toast(`Click "Start recording" in the red bar when you're ready — ${how}. StepForge tucks away; use the red tray icon to pause or finish.`);
|
||||
}
|
||||
|
||||
async openExistingWorkspace() {
|
||||
@@ -231,7 +236,10 @@ class StepForgeApp {
|
||||
updateCaptureState(state) {
|
||||
this.captureState = state || { active: false };
|
||||
clearNode(this.captureStatus);
|
||||
if (!this.captureState.active) {
|
||||
// The capture bar only makes sense alongside the editor it's recording
|
||||
// into — hide it everywhere else (e.g. the library) even if a session
|
||||
// is still active in the background.
|
||||
if (!this.captureState.active || this.state.view !== 'editor') {
|
||||
this.captureStatus.classList.add('hidden');
|
||||
return;
|
||||
}
|
||||
@@ -240,10 +248,12 @@ class StepForgeApp {
|
||||
const send = (payload) => api.capture.session(payload).then((next) => this.updateCaptureState(next));
|
||||
|
||||
// What is currently triggering captures, so the user knows what to do.
|
||||
const trigger = s.paused ? 'paused'
|
||||
: s.clickCapture ? 'on click'
|
||||
: s.intervalSec > 0 ? `every ${s.intervalSec}s`
|
||||
: 'hotkey only';
|
||||
const notStarted = s.paused && !s.count;
|
||||
const trigger = notStarted ? 'ready'
|
||||
: s.paused ? 'paused'
|
||||
: s.clickCapture ? 'on click'
|
||||
: s.intervalSec > 0 ? `every ${s.intervalSec}s`
|
||||
: 'hotkey only';
|
||||
|
||||
const shootBtn = el('button', {
|
||||
type: 'button',
|
||||
@@ -261,8 +271,9 @@ class StepForgeApp {
|
||||
|
||||
const pauseBtn = el('button', {
|
||||
type: 'button',
|
||||
title: notStarted ? 'StepForge tucks away and starts capturing' : '',
|
||||
onClick: () => send({ action: s.paused ? 'resume' : 'pause' }),
|
||||
}, s.paused ? 'Resume' : 'Pause');
|
||||
}, notStarted ? 'Start recording' : s.paused ? 'Resume' : 'Pause');
|
||||
|
||||
const finishBtn = el('button', {
|
||||
type: 'button',
|
||||
|
||||
@@ -1146,7 +1146,7 @@ class GuideEditor {
|
||||
|
||||
async startCaptureSession() {
|
||||
await api.capture.session({ action: 'start', guideId: this.guideId });
|
||||
this.onToast('Capture session started.');
|
||||
this.onToast('Capture session ready — click "Start recording" in the red bar when you\'re set.');
|
||||
this.emitMeta();
|
||||
}
|
||||
|
||||
|
||||
+10
-3
@@ -56,23 +56,30 @@ function toast(message, { error = false, ms = 2600 } = {}) {
|
||||
function openModal({ title, body, footer, wide = false, onClose }) {
|
||||
const root = document.getElementById('modal-root');
|
||||
clearNode(root);
|
||||
// `close` just tears down the modal. Buttons that already resolve the
|
||||
// dialog's promise themselves call this. `dismiss` additionally fires
|
||||
// `onClose`, for ways of leaving the dialog that didn't pick an option
|
||||
// (Esc, the ✕, or clicking the backdrop) and need a default resolution.
|
||||
const close = () => {
|
||||
clearNode(root);
|
||||
document.removeEventListener('keydown', escHandler, true);
|
||||
};
|
||||
const dismiss = () => {
|
||||
close();
|
||||
if (onClose) onClose();
|
||||
};
|
||||
const escHandler = (e) => {
|
||||
if (e.key === 'Escape') { e.stopPropagation(); close(); }
|
||||
if (e.key === 'Escape') { e.stopPropagation(); dismiss(); }
|
||||
};
|
||||
document.addEventListener('keydown', escHandler, true);
|
||||
const modal = el('div.modal', { className: `modal${wide ? ' wide' : ''}` },
|
||||
el('header', {}, title, el('span.close', { onClick: close, title: 'Close (Esc)' }, '✕')),
|
||||
el('header', {}, title, el('span.close', { onClick: dismiss, title: 'Close (Esc)' }, '✕')),
|
||||
el('div.body', {}, body),
|
||||
footer ? el('footer', {}, footer) : null,
|
||||
);
|
||||
modal.addEventListener('click', (e) => e.stopPropagation());
|
||||
root.append(modal);
|
||||
root.onclick = close;
|
||||
root.onclick = dismiss;
|
||||
return { close, node: modal };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user