mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
small fixes
This commit is contained in:
@@ -117,7 +117,7 @@ export function createOverlayWindow(
|
|||||||
|
|
||||||
window.webContents.on('before-input-event', (event, input) => {
|
window.webContents.on('before-input-event', (event, input) => {
|
||||||
if (kind === 'modal') return;
|
if (kind === 'modal') return;
|
||||||
if (!options.isOverlayVisible(kind)) return;
|
if (!window.isVisible()) return;
|
||||||
if (!options.tryHandleOverlayShortcutLocalFallback(input)) return;
|
if (!options.tryHandleOverlayShortcutLocalFallback(input)) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -225,6 +225,27 @@ test('handleOverlayModalClosed hides modal window only after all pending modals
|
|||||||
assert.equal(window.getHideCount(), 1);
|
assert.equal(window.getHideCount(), 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('sendToActiveOverlayWindow prefers visible main overlay window for modal open', () => {
|
||||||
|
const mainWindow = createMockWindow();
|
||||||
|
mainWindow.visible = true;
|
||||||
|
const runtime = createOverlayModalRuntimeService({
|
||||||
|
getMainWindow: () => mainWindow as never,
|
||||||
|
getModalWindow: () => null,
|
||||||
|
createModalWindow: () => {
|
||||||
|
throw new Error('modal window should not be created when main overlay is visible');
|
||||||
|
},
|
||||||
|
getModalGeometry: () => ({ x: 0, y: 0, width: 400, height: 300 }),
|
||||||
|
setModalWindowBounds: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const sent = runtime.sendToActiveOverlayWindow('runtime-options:open', undefined, {
|
||||||
|
restoreOnModalClose: 'runtime-options',
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(sent, true);
|
||||||
|
assert.deepEqual(mainWindow.sent, [['runtime-options:open']]);
|
||||||
|
});
|
||||||
|
|
||||||
test('modal runtime notifies callers when modal input state becomes active/inactive', () => {
|
test('modal runtime notifies callers when modal input state becomes active/inactive', () => {
|
||||||
const window = createMockWindow();
|
const window = createMockWindow();
|
||||||
const state: boolean[] = [];
|
const state: boolean[] = [];
|
||||||
@@ -249,6 +270,8 @@ test('modal runtime notifies callers when modal input state becomes active/inact
|
|||||||
runtime.sendToActiveOverlayWindow('subsync:open-manual', { sourceTracks: [] }, {
|
runtime.sendToActiveOverlayWindow('subsync:open-manual', { sourceTracks: [] }, {
|
||||||
restoreOnModalClose: 'subsync',
|
restoreOnModalClose: 'subsync',
|
||||||
});
|
});
|
||||||
|
assert.deepEqual(state, []);
|
||||||
|
runtime.notifyOverlayModalOpened('runtime-options');
|
||||||
assert.deepEqual(state, [true]);
|
assert.deepEqual(state, [true]);
|
||||||
|
|
||||||
runtime.handleOverlayModalClosed('runtime-options');
|
runtime.handleOverlayModalClosed('runtime-options');
|
||||||
@@ -258,6 +281,32 @@ test('modal runtime notifies callers when modal input state becomes active/inact
|
|||||||
assert.deepEqual(state, [true, false]);
|
assert.deepEqual(state, [true, false]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('handleOverlayModalClosed resets modal state even when modal window does not exist', () => {
|
||||||
|
const state: boolean[] = [];
|
||||||
|
const runtime = createOverlayModalRuntimeService(
|
||||||
|
{
|
||||||
|
getMainWindow: () => null,
|
||||||
|
getModalWindow: () => null,
|
||||||
|
createModalWindow: () => null,
|
||||||
|
getModalGeometry: () => ({ x: 0, y: 0, width: 400, height: 300 }),
|
||||||
|
setModalWindowBounds: () => {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onModalStateChange: (active: boolean): void => {
|
||||||
|
state.push(active);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
runtime.sendToActiveOverlayWindow('runtime-options:open', undefined, {
|
||||||
|
restoreOnModalClose: 'runtime-options',
|
||||||
|
});
|
||||||
|
runtime.notifyOverlayModalOpened('runtime-options');
|
||||||
|
runtime.handleOverlayModalClosed('runtime-options');
|
||||||
|
|
||||||
|
assert.deepEqual(state, [true, false]);
|
||||||
|
});
|
||||||
|
|
||||||
test('handleOverlayModalClosed hides modal window for single kiku modal', () => {
|
test('handleOverlayModalClosed hides modal window for single kiku modal', () => {
|
||||||
const window = createMockWindow();
|
const window = createMockWindow();
|
||||||
const runtime = createOverlayModalRuntimeService({
|
const runtime = createOverlayModalRuntimeService({
|
||||||
|
|||||||
@@ -65,13 +65,19 @@ export function createOverlayModalRuntimeService(
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isWindowReadyForIpc = (window: BrowserWindow): boolean => {
|
const isWindowReadyForIpc = (window: BrowserWindow): boolean => {
|
||||||
if (window.webContents.isLoading()) {
|
if (window.webContents.isLoading()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const currentURL = window.webContents.getURL();
|
const currentURL = window.webContents.getURL();
|
||||||
return currentURL !== '' && currentURL !== 'about:blank';
|
return currentURL !== '' && currentURL !== 'about:blank';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const elevateModalWindow = (window: BrowserWindow): void => {
|
||||||
|
if (window.isDestroyed()) return;
|
||||||
|
window.setAlwaysOnTop(true, 'screen-saver', 1);
|
||||||
|
window.moveTop();
|
||||||
|
};
|
||||||
|
|
||||||
const sendOrQueueForWindow = (
|
const sendOrQueueForWindow = (
|
||||||
window: BrowserWindow,
|
window: BrowserWindow,
|
||||||
@@ -95,7 +101,10 @@ const isWindowReadyForIpc = (window: BrowserWindow): boolean => {
|
|||||||
passThroughMouseEvents: boolean;
|
passThroughMouseEvents: boolean;
|
||||||
} = { passThroughMouseEvents: false },
|
} = { passThroughMouseEvents: false },
|
||||||
): void => {
|
): void => {
|
||||||
window.show();
|
if (!window.isVisible()) {
|
||||||
|
window.show();
|
||||||
|
}
|
||||||
|
elevateModalWindow(window);
|
||||||
if (options.passThroughMouseEvents) {
|
if (options.passThroughMouseEvents) {
|
||||||
window.setIgnoreMouseEvents(true, { forward: true });
|
window.setIgnoreMouseEvents(true, { forward: true });
|
||||||
} else {
|
} else {
|
||||||
@@ -107,6 +116,22 @@ const isWindowReadyForIpc = (window: BrowserWindow): boolean => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ensureModalWindowInteractive = (window: BrowserWindow): void => {
|
||||||
|
if (window.isVisible()) {
|
||||||
|
window.setIgnoreMouseEvents(false);
|
||||||
|
if (!window.isFocused()) {
|
||||||
|
window.focus();
|
||||||
|
}
|
||||||
|
if (!window.webContents.isFocused()) {
|
||||||
|
window.webContents.focus();
|
||||||
|
}
|
||||||
|
elevateModalWindow(window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showModalWindow(window);
|
||||||
|
};
|
||||||
|
|
||||||
const showOverlayWindowForModal = (window: BrowserWindow): void => {
|
const showOverlayWindowForModal = (window: BrowserWindow): void => {
|
||||||
window.show();
|
window.show();
|
||||||
if (!window.isFocused()) {
|
if (!window.isFocused()) {
|
||||||
@@ -137,7 +162,7 @@ const isWindowReadyForIpc = (window: BrowserWindow): boolean => {
|
|||||||
if (!targetWindow || targetWindow.isDestroyed() || targetWindow.isVisible()) {
|
if (!targetWindow || targetWindow.isDestroyed() || targetWindow.isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
showModalWindow(targetWindow, { passThroughMouseEvents: true });
|
showModalWindow(targetWindow, { passThroughMouseEvents: false });
|
||||||
}, MODAL_REVEAL_FALLBACK_DELAY_MS);
|
}, MODAL_REVEAL_FALLBACK_DELAY_MS);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -149,6 +174,7 @@ const isWindowReadyForIpc = (window: BrowserWindow): boolean => {
|
|||||||
const restoreOnModalClose = runtimeOptions?.restoreOnModalClose;
|
const restoreOnModalClose = runtimeOptions?.restoreOnModalClose;
|
||||||
|
|
||||||
const sendNow = (window: BrowserWindow): void => {
|
const sendNow = (window: BrowserWindow): void => {
|
||||||
|
ensureModalWindowInteractive(window);
|
||||||
if (payload === undefined) {
|
if (payload === undefined) {
|
||||||
window.webContents.send(channel);
|
window.webContents.send(channel);
|
||||||
} else {
|
} else {
|
||||||
@@ -157,17 +183,24 @@ const isWindowReadyForIpc = (window: BrowserWindow): boolean => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (restoreOnModalClose) {
|
if (restoreOnModalClose) {
|
||||||
|
restoreVisibleOverlayOnModalClose.add(restoreOnModalClose);
|
||||||
|
const mainWindow = getTargetOverlayWindow();
|
||||||
|
if (mainWindow && !mainWindow.isDestroyed() && mainWindow.isVisible()) {
|
||||||
|
sendOrQueueForWindow(mainWindow, (window) => {
|
||||||
|
if (payload === undefined) {
|
||||||
|
window.webContents.send(channel);
|
||||||
|
} else {
|
||||||
|
window.webContents.send(channel, payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const modalWindow = resolveModalWindow();
|
const modalWindow = resolveModalWindow();
|
||||||
if (!modalWindow) return false;
|
if (!modalWindow) return false;
|
||||||
|
|
||||||
deps.setModalWindowBounds(deps.getModalGeometry());
|
deps.setModalWindowBounds(deps.getModalGeometry());
|
||||||
const wasVisible = modalWindow.isVisible();
|
const wasVisible = modalWindow.isVisible();
|
||||||
const wasModalActive = restoreVisibleOverlayOnModalClose.size > 0;
|
|
||||||
restoreVisibleOverlayOnModalClose.add(restoreOnModalClose);
|
|
||||||
if (!wasModalActive) {
|
|
||||||
notifyModalStateChange(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wasVisible) {
|
if (!wasVisible) {
|
||||||
scheduleModalWindowReveal(modalWindow);
|
scheduleModalWindowReveal(modalWindow);
|
||||||
} else if (!modalWindow.isFocused()) {
|
} else if (!modalWindow.isFocused()) {
|
||||||
@@ -199,17 +232,21 @@ const isWindowReadyForIpc = (window: BrowserWindow): boolean => {
|
|||||||
const handleOverlayModalClosed = (modal: OverlayHostedModal): void => {
|
const handleOverlayModalClosed = (modal: OverlayHostedModal): void => {
|
||||||
if (!restoreVisibleOverlayOnModalClose.has(modal)) return;
|
if (!restoreVisibleOverlayOnModalClose.has(modal)) return;
|
||||||
restoreVisibleOverlayOnModalClose.delete(modal);
|
restoreVisibleOverlayOnModalClose.delete(modal);
|
||||||
const modalWindow = deps.getModalWindow();
|
|
||||||
if (!modalWindow || modalWindow.isDestroyed()) return;
|
|
||||||
if (restoreVisibleOverlayOnModalClose.size === 0) {
|
if (restoreVisibleOverlayOnModalClose.size === 0) {
|
||||||
clearPendingModalWindowReveal();
|
clearPendingModalWindowReveal();
|
||||||
notifyModalStateChange(false);
|
notifyModalStateChange(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const modalWindow = deps.getModalWindow();
|
||||||
|
if (!modalWindow || modalWindow.isDestroyed()) return;
|
||||||
|
if (restoreVisibleOverlayOnModalClose.size === 0) {
|
||||||
modalWindow.hide();
|
modalWindow.hide();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const notifyOverlayModalOpened = (modal: OverlayHostedModal): void => {
|
const notifyOverlayModalOpened = (modal: OverlayHostedModal): void => {
|
||||||
if (!restoreVisibleOverlayOnModalClose.has(modal)) return;
|
if (!restoreVisibleOverlayOnModalClose.has(modal)) return;
|
||||||
|
notifyModalStateChange(true);
|
||||||
const targetWindow = deps.getModalWindow();
|
const targetWindow = deps.getModalWindow();
|
||||||
clearPendingModalWindowReveal();
|
clearPendingModalWindowReveal();
|
||||||
if (!targetWindow || targetWindow.isDestroyed()) {
|
if (!targetWindow || targetWindow.isDestroyed()) {
|
||||||
@@ -218,6 +255,7 @@ const isWindowReadyForIpc = (window: BrowserWindow): boolean => {
|
|||||||
|
|
||||||
if (targetWindow.isVisible()) {
|
if (targetWindow.isVisible()) {
|
||||||
targetWindow.setIgnoreMouseEvents(false);
|
targetWindow.setIgnoreMouseEvents(false);
|
||||||
|
elevateModalWindow(targetWindow);
|
||||||
if (!targetWindow.isFocused()) {
|
if (!targetWindow.isFocused()) {
|
||||||
targetWindow.focus();
|
targetWindow.focus();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,5 +41,5 @@ test('overlay runtime bootstrap runs core init and applies post-init state', ()
|
|||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
assert.equal(initialized, true);
|
assert.equal(initialized, true);
|
||||||
assert.deepEqual(calls, ['options', 'core', 'initialized:yes', 'warmups']);
|
assert.deepEqual(calls, ['options', 'initialized:yes', 'core', 'warmups']);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -41,8 +41,14 @@ export function createInitializeOverlayRuntimeHandler(deps: {
|
|||||||
}) {
|
}) {
|
||||||
return (): void => {
|
return (): void => {
|
||||||
if (deps.isOverlayRuntimeInitialized()) return;
|
if (deps.isOverlayRuntimeInitialized()) return;
|
||||||
deps.initializeOverlayRuntimeCore(deps.buildOptions());
|
const options = deps.buildOptions();
|
||||||
deps.setOverlayRuntimeInitialized(true);
|
deps.setOverlayRuntimeInitialized(true);
|
||||||
|
try {
|
||||||
|
deps.initializeOverlayRuntimeCore(options);
|
||||||
|
} catch (error) {
|
||||||
|
deps.setOverlayRuntimeInitialized(false);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
deps.startBackgroundWarmups();
|
deps.startBackgroundWarmups();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user