fix(overlay): fall back to did-finish-load when ready-to-show never fires

A hidden overlay window stops producing frames once it is explicitly
hidden and then reloaded (the Yomitan content-script reload right after
startup), so ready-to-show never fires and the content-ready gate keeps
the window hidden forever behind the Overlay loading spinner. Mark
content ready from did-finish-load after a 1.5s grace period so the
overlay always becomes showable; ready-to-show still wins when it fires.
This commit is contained in:
2026-08-01 01:31:48 -07:00
parent f32dc6c49e
commit 65a280fe60
3 changed files with 108 additions and 8 deletions
+62 -1
View File
@@ -1,6 +1,11 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { ensureOverlayWindowLevel, updateOverlayWindowBounds } from './overlay-window';
import {
ensureOverlayWindowLevel,
updateOverlayWindowBounds,
scheduleOverlayContentReadyFallback,
OVERLAY_CONTENT_READY_FALLBACK_DELAY_MS,
} from './overlay-window';
import {
handleOverlayWindowBeforeInputEvent,
handleOverlayWindowBlurred,
@@ -322,3 +327,59 @@ test('updateOverlayWindowBounds aligns Linux overlay content bounds to mpv geome
assert.deepEqual(calls, [{ x: 0, y: -14, width: 3440, height: 1454 }]);
});
test('scheduleOverlayContentReadyFallback marks content ready when ready-to-show never fired', () => {
const events: string[] = [];
const scheduled: Array<() => void> = [];
scheduleOverlayContentReadyFallback({
isContentReady: () => false,
isDestroyed: () => false,
markContentReady: () => events.push('mark'),
setTimeoutFn: (callback, delayMs) => {
events.push(`schedule:${delayMs}`);
scheduled.push(callback);
return null;
},
});
assert.deepEqual(events, [`schedule:${OVERLAY_CONTENT_READY_FALLBACK_DELAY_MS}`]);
scheduled[0]?.();
assert.deepEqual(events, [`schedule:${OVERLAY_CONTENT_READY_FALLBACK_DELAY_MS}`, 'mark']);
});
test('scheduleOverlayContentReadyFallback no-ops once content is already ready', () => {
const scheduled: Array<() => void> = [];
const events: string[] = [];
scheduleOverlayContentReadyFallback({
isContentReady: () => true,
isDestroyed: () => false,
markContentReady: () => events.push('mark'),
setTimeoutFn: (callback) => {
scheduled.push(callback);
return null;
},
});
scheduled[0]?.();
assert.deepEqual(events, []);
});
test('scheduleOverlayContentReadyFallback no-ops after the window is destroyed', () => {
const scheduled: Array<() => void> = [];
const events: string[] = [];
scheduleOverlayContentReadyFallback({
isContentReady: () => false,
isDestroyed: () => true,
markContentReady: () => events.push('mark'),
setTimeoutFn: (callback) => {
scheduled.push(callback);
return null;
},
});
scheduled[0]?.();
assert.deepEqual(events, []);
});