Fixed a bug where a resumed recording wouldn't update the image Part 2
Template tests / tests (push) Successful in 1m51s
Template tests / tests (push) Successful in 1m51s
This commit is contained in:
+8
-3
@@ -24,6 +24,7 @@ const { encodePng } = require('../core/png');
|
|||||||
|
|
||||||
const CLICK_DEBOUNCE_MS = 700;
|
const CLICK_DEBOUNCE_MS = 700;
|
||||||
const CLICK_CAPTURE_CACHE_MS = 75;
|
const CLICK_CAPTURE_CACHE_MS = 75;
|
||||||
|
const CLICK_CAPTURE_CACHE_MAX_AGE_MS = 400;
|
||||||
const CLICK_CAPTURE_HIDE_DELAY_MS = 25;
|
const CLICK_CAPTURE_HIDE_DELAY_MS = 25;
|
||||||
|
|
||||||
function hasBinary(name) {
|
function hasBinary(name) {
|
||||||
@@ -257,9 +258,13 @@ class CaptureService {
|
|||||||
try {
|
try {
|
||||||
const mode = this.settings.get('capture.mode') || 'fullscreen';
|
const mode = this.settings.get('capture.mode') || 'fullscreen';
|
||||||
const grabMode = mode === 'region' ? 'fullscreen' : mode;
|
const grabMode = mode === 'region' ? 'fullscreen' : mode;
|
||||||
const cached = trigger === 'click' && this.captureCache && this.captureCache.mode === grabMode
|
// The background refresh loop (startClickCaptureCache) keeps this
|
||||||
? this.captureCache
|
// updated every ~75ms; if it's gone stale (refresh errors silently and
|
||||||
: null;
|
// stops updating, or the cache was never refreshed after a resume),
|
||||||
|
// fall back to a fresh shot rather than reusing an old background.
|
||||||
|
const cacheFresh = this.captureCache && this.captureCache.mode === grabMode
|
||||||
|
&& Date.now() - this.captureCache.capturedAt <= CLICK_CAPTURE_CACHE_MAX_AGE_MS;
|
||||||
|
const cached = trigger === 'click' && cacheFresh ? this.captureCache : null;
|
||||||
const finalResult = cached
|
const finalResult = cached
|
||||||
? this.storeFrameAsStep(this.session.guideId, grabMode, cached, clickPos)
|
? this.storeFrameAsStep(this.session.guideId, grabMode, cached, clickPos)
|
||||||
: await this.shoot({
|
: await this.shoot({
|
||||||
|
|||||||
+6
-4
@@ -92,10 +92,12 @@ Initial release.
|
|||||||
literal text "undefined" by an old bug); a corrupted file is now
|
literal text "undefined" by an old bug); a corrupted file is now
|
||||||
treated as empty instead of crashing the dialog, and is overwritten
|
treated as empty instead of crashing the dialog, and is overwritten
|
||||||
with valid JSON the next time settings are saved.
|
with valid JSON the next time settings are saved.
|
||||||
- Resuming a paused capture session no longer reuses the same stale
|
- Click captures no longer reuse the same stale background screenshot
|
||||||
background screenshot for every click capture (only the click marker
|
for every step (only the click marker moved). Pausing now fully resets
|
||||||
moved); pausing now fully resets the click-capture cache so resuming
|
the click-capture cache so resuming starts a fresh background refresh
|
||||||
starts a fresh background refresh loop.
|
loop, and a cached frame older than 400ms (e.g. if the background
|
||||||
|
refresh silently stops working) is now discarded in favor of a fresh
|
||||||
|
screenshot.
|
||||||
|
|
||||||
### Added (initial feature set)
|
### Added (initial feature set)
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,33 @@ test('click-triggered capture marks the click-time cursor position, not the cach
|
|||||||
assert.ok(Math.abs(marker.y - (0.5 - (d * 120 / 80) / 2)) < 1e-9);
|
assert.ok(Math.abs(marker.y - (0.5 - (d * 120 / 80) / 2)) < 1e-9);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('click-triggered session capture falls back to a fresh shot when the cached frame is stale', async () => {
|
||||||
|
const service = makeService();
|
||||||
|
service.session = { guideId: 'guide-stale', paused: false, count: 0, intervalSec: 0 };
|
||||||
|
// A frame that's well past the cache's max age — e.g. the background
|
||||||
|
// refresh loop died (errored silently, or never restarted after a
|
||||||
|
// pause/resume) and left a frozen, increasingly-stale frame behind.
|
||||||
|
service.captureCache = {
|
||||||
|
mode: 'fullscreen',
|
||||||
|
png: Buffer.from('stale-png'),
|
||||||
|
size: { width: 120, height: 80 },
|
||||||
|
display: { bounds: { x: 0, y: 0, width: 120, height: 80 } },
|
||||||
|
cursor: { x: 60, y: 40 },
|
||||||
|
capturedAt: Date.now() - 10_000,
|
||||||
|
};
|
||||||
|
|
||||||
|
let shootCalled = false;
|
||||||
|
service.shoot = async () => {
|
||||||
|
shootCalled = true;
|
||||||
|
return { ok: true, step: { stepId: 'fresh-step' } };
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await service.sessionCapture('click', { x: 1, y: 1 });
|
||||||
|
|
||||||
|
assert.equal(result.ok, true);
|
||||||
|
assert.equal(shootCalled, true, 'a stale cached frame must not be reused');
|
||||||
|
});
|
||||||
|
|
||||||
test('live-shot click capture also marks the click-time cursor position', async () => {
|
test('live-shot click capture also marks the click-time cursor position', async () => {
|
||||||
const service = makeService();
|
const service = makeService();
|
||||||
service.settings.get = (key) => {
|
service.settings.get = (key) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user