This commit is contained in:
+1
-51
@@ -2,7 +2,7 @@
|
||||
|
||||
const path = require('node:path');
|
||||
const { spawn, execFileSync } = require('node:child_process');
|
||||
const { desktopCapturer, screen, BrowserWindow, nativeImage, Tray, Menu, Notification } = require('electron');
|
||||
const { desktopCapturer, screen, BrowserWindow, nativeImage, Tray, Menu } = require('electron');
|
||||
const { expandPlaceholders } = require('../core/placeholders');
|
||||
const raster = require('../core/raster');
|
||||
const { encodePng } = require('../core/png');
|
||||
@@ -109,13 +109,11 @@ class CaptureService {
|
||||
getWindow,
|
||||
notify,
|
||||
screenApi = screen,
|
||||
dialogApi = null,
|
||||
}) {
|
||||
this.store = store;
|
||||
this.settings = settings;
|
||||
this.getWindow = getWindow;
|
||||
this.notify = notify;
|
||||
this.dialog = dialogApi;
|
||||
// Injectable for tests; the click/coordinate paths must never reach for
|
||||
// the global `screen` directly so coordinate handling stays testable.
|
||||
this.screen = screenApi;
|
||||
@@ -142,7 +140,6 @@ class CaptureService {
|
||||
// True only while a resume is warming up (window still visible, buffer
|
||||
// not yet primed). Clicks are ignored until it clears — see armRecording.
|
||||
this.warmingUp = false;
|
||||
this.sessionInstructionsShown = false;
|
||||
}
|
||||
|
||||
state() {
|
||||
@@ -193,8 +190,6 @@ class CaptureService {
|
||||
// the user explicitly presses "Start recording" in the capture bar, so
|
||||
// New Capture never makes the window vanish out from under them.
|
||||
this.session = { guideId, paused: true, count: 0, intervalSec: interval };
|
||||
this.sessionNotificationShown = false;
|
||||
this.sessionInstructionsShown = false;
|
||||
if (this.settings.get('capture.captureOutsideClicks') !== false) this.startClickWatcher();
|
||||
this.applyInterval();
|
||||
this.notify('capture:state', this.state());
|
||||
@@ -362,7 +357,6 @@ class CaptureService {
|
||||
const settleMs = Number(this.settings.get('capture.postHideSettleMs'));
|
||||
const run = async () => {
|
||||
if (!this.session || this.session.paused) { this.warmingUp = false; return; }
|
||||
const startedAt = Date.now();
|
||||
if (recorderWanted) {
|
||||
// Warm the recorder, but never let a slow backend start (it waits up
|
||||
// to several seconds for the capture stream) keep the window visible
|
||||
@@ -376,60 +370,18 @@ class CaptureService {
|
||||
if (capTimer) clearTimeout(capTimer);
|
||||
if (!this.session || this.session.paused) { this.warmingUp = false; return; }
|
||||
}
|
||||
// Keep the window visible briefly so the user sees the transition even
|
||||
// when warmup was instant; warmup time counts toward this.
|
||||
const minVisibleMs = wantHide ? 400 : 0;
|
||||
const elapsed = Date.now() - startedAt;
|
||||
if (elapsed < minVisibleMs) {
|
||||
await new Promise((r) => setTimeout(r, minVisibleMs - elapsed));
|
||||
if (!this.session || this.session.paused) { this.warmingUp = false; return; }
|
||||
}
|
||||
if (wantHide && win && !win.isDestroyed() && win.isVisible()) {
|
||||
if (!this.sessionInstructionsShown) {
|
||||
this.sessionInstructionsShown = true;
|
||||
await this.showRecordingInstructions(win);
|
||||
if (!this.session || this.session.paused) { this.warmingUp = false; return; }
|
||||
}
|
||||
win.hide();
|
||||
// Let a couple of frames of the now-unobscured screen land before
|
||||
// the user's first click, so that frame shows their work, not the
|
||||
// app window that was just dismissed.
|
||||
await new Promise((r) => setTimeout(r, Number.isFinite(settleMs) ? settleMs : 150));
|
||||
}
|
||||
// Window hidden and buffer primed — clicks now count.
|
||||
if (!process.env.STEPFORGE_SCREENSHOT && !this.sessionNotificationShown) {
|
||||
try {
|
||||
new Notification({
|
||||
title: 'StepForge is recording',
|
||||
body: 'Use the red tray icon to pause or finish capture.',
|
||||
}).show();
|
||||
this.sessionNotificationShown = true;
|
||||
} catch { /* notifications unavailable on this desktop */ }
|
||||
}
|
||||
this.warmingUp = false;
|
||||
};
|
||||
run().catch(() => { this.warmingUp = false; });
|
||||
}
|
||||
|
||||
async showRecordingInstructions(win) {
|
||||
if (!this.dialog || typeof this.dialog.showMessageBox !== 'function') return;
|
||||
try {
|
||||
await this.dialog.showMessageBox(win, {
|
||||
type: 'info',
|
||||
title: 'StepForge recording',
|
||||
message: 'Please go into the tray icon and select the red button to stop recording.',
|
||||
detail: 'Click OK to continue and hide this window.',
|
||||
buttons: ['OK'],
|
||||
defaultId: 0,
|
||||
cancelId: 0,
|
||||
noLink: true,
|
||||
});
|
||||
} catch {
|
||||
// If the dialog cannot be shown, keep the session moving instead of
|
||||
// leaving the user stuck on the start flow.
|
||||
}
|
||||
}
|
||||
|
||||
finishSession() {
|
||||
if (this.intervalTimer) {
|
||||
clearInterval(this.intervalTimer);
|
||||
@@ -441,8 +393,6 @@ class CaptureService {
|
||||
this.stopClickFrameBackend();
|
||||
this.destroySessionTray();
|
||||
this.session = null;
|
||||
this.sessionNotificationShown = false;
|
||||
this.sessionInstructionsShown = false;
|
||||
if (this.hiddenForSession) {
|
||||
this.hiddenForSession = false;
|
||||
this.showWindow();
|
||||
|
||||
Reference in New Issue
Block a user