mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
refactor: extract overlay bridge runtime helpers
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
"docs:build": "vitepress build docs",
|
||||
"docs:preview": "vitepress preview docs --host 0.0.0.0 --port 4173 --strictPort",
|
||||
"test:config": "pnpm run build && node --test dist/config/config.test.js",
|
||||
"test:core": "pnpm run build && node --test dist/cli/args.test.js dist/cli/help.test.js dist/core/services/cli-command-service.test.js dist/core/services/numeric-shortcut-session-service.test.js dist/core/services/secondary-subtitle-service.test.js dist/core/services/mpv-render-metrics-service.test.js dist/core/services/mpv-runtime-service.test.js dist/core/services/runtime-options-runtime-service.test.js dist/core/services/overlay-modal-restore-service.test.js dist/core/services/runtime-config-service.test.js",
|
||||
"test:core": "pnpm run build && node --test dist/cli/args.test.js dist/cli/help.test.js dist/core/services/cli-command-service.test.js dist/core/services/numeric-shortcut-session-service.test.js dist/core/services/secondary-subtitle-service.test.js dist/core/services/mpv-render-metrics-service.test.js dist/core/services/mpv-runtime-service.test.js dist/core/services/runtime-options-runtime-service.test.js dist/core/services/overlay-modal-restore-service.test.js dist/core/services/runtime-config-service.test.js dist/core/services/overlay-bridge-runtime-service.test.js",
|
||||
"test:subtitle": "pnpm run build && node --test dist/subtitle/stages.test.js dist/subtitle/pipeline.test.js",
|
||||
"generate:config-example": "pnpm run build && node dist/generate-config-example.js",
|
||||
"start": "pnpm run build && electron . --start",
|
||||
|
||||
76
src/core/services/overlay-bridge-runtime-service.test.ts
Normal file
76
src/core/services/overlay-bridge-runtime-service.test.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { KikuFieldGroupingChoice } from "../../types";
|
||||
import {
|
||||
createFieldGroupingCallbackRuntimeService,
|
||||
sendToVisibleOverlayRuntimeService,
|
||||
} from "./overlay-bridge-runtime-service";
|
||||
|
||||
test("sendToVisibleOverlayRuntimeService restores visibility flag when opening hidden overlay modal", () => {
|
||||
const sent: unknown[][] = [];
|
||||
const restoreSet = new Set<"runtime-options" | "subsync">();
|
||||
let visibleOverlayVisible = false;
|
||||
|
||||
const ok = sendToVisibleOverlayRuntimeService({
|
||||
mainWindow: {
|
||||
isDestroyed: () => false,
|
||||
webContents: {
|
||||
send: (...args: unknown[]) => {
|
||||
sent.push(args);
|
||||
},
|
||||
},
|
||||
} as unknown as Electron.BrowserWindow,
|
||||
visibleOverlayVisible,
|
||||
setVisibleOverlayVisible: (visible) => {
|
||||
visibleOverlayVisible = visible;
|
||||
},
|
||||
channel: "runtime-options:open",
|
||||
restoreOnModalClose: "runtime-options",
|
||||
restoreVisibleOverlayOnModalClose: restoreSet,
|
||||
});
|
||||
|
||||
assert.equal(ok, true);
|
||||
assert.equal(visibleOverlayVisible, true);
|
||||
assert.equal(restoreSet.has("runtime-options"), true);
|
||||
assert.deepEqual(sent, [["runtime-options:open"]]);
|
||||
});
|
||||
|
||||
test("createFieldGroupingCallbackRuntimeService cancels when overlay request cannot be sent", async () => {
|
||||
let resolver: ((choice: KikuFieldGroupingChoice) => void) | null = null;
|
||||
const callback = createFieldGroupingCallbackRuntimeService<
|
||||
"runtime-options" | "subsync"
|
||||
>({
|
||||
getVisibleOverlayVisible: () => false,
|
||||
getInvisibleOverlayVisible: () => false,
|
||||
setVisibleOverlayVisible: () => {},
|
||||
setInvisibleOverlayVisible: () => {},
|
||||
getResolver: () => resolver,
|
||||
setResolver: (next) => {
|
||||
resolver = next;
|
||||
},
|
||||
sendToVisibleOverlay: () => false,
|
||||
});
|
||||
|
||||
const result = await callback({
|
||||
original: {
|
||||
noteId: 1,
|
||||
expression: "a",
|
||||
sentencePreview: "a",
|
||||
hasAudio: false,
|
||||
hasImage: false,
|
||||
isOriginal: true,
|
||||
},
|
||||
duplicate: {
|
||||
noteId: 2,
|
||||
expression: "b",
|
||||
sentencePreview: "b",
|
||||
hasAudio: false,
|
||||
hasImage: false,
|
||||
isOriginal: false,
|
||||
},
|
||||
});
|
||||
|
||||
assert.equal(result.cancelled, true);
|
||||
assert.equal(result.keepNoteId, 0);
|
||||
assert.equal(result.deleteNoteId, 0);
|
||||
});
|
||||
61
src/core/services/overlay-bridge-runtime-service.ts
Normal file
61
src/core/services/overlay-bridge-runtime-service.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import {
|
||||
KikuFieldGroupingChoice,
|
||||
KikuFieldGroupingRequestData,
|
||||
} from "../../types";
|
||||
import { addOverlayModalRestoreFlagService } from "./overlay-modal-restore-service";
|
||||
import { sendToVisibleOverlayService } from "./overlay-send-service";
|
||||
import { createFieldGroupingCallbackService } from "./field-grouping-service";
|
||||
import { BrowserWindow } from "electron";
|
||||
|
||||
export function sendToVisibleOverlayRuntimeService<T extends string>(options: {
|
||||
mainWindow: BrowserWindow | null;
|
||||
visibleOverlayVisible: boolean;
|
||||
setVisibleOverlayVisible: (visible: boolean) => void;
|
||||
channel: string;
|
||||
payload?: unknown;
|
||||
restoreOnModalClose?: T;
|
||||
restoreVisibleOverlayOnModalClose: Set<T>;
|
||||
}): boolean {
|
||||
return sendToVisibleOverlayService({
|
||||
mainWindow: options.mainWindow,
|
||||
visibleOverlayVisible: options.visibleOverlayVisible,
|
||||
setVisibleOverlayVisible: options.setVisibleOverlayVisible,
|
||||
channel: options.channel,
|
||||
payload: options.payload,
|
||||
restoreOnModalClose: options.restoreOnModalClose,
|
||||
addRestoreFlag: (modal) =>
|
||||
addOverlayModalRestoreFlagService(
|
||||
options.restoreVisibleOverlayOnModalClose,
|
||||
modal as T,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
export function createFieldGroupingCallbackRuntimeService<T extends string>(
|
||||
options: {
|
||||
getVisibleOverlayVisible: () => boolean;
|
||||
getInvisibleOverlayVisible: () => boolean;
|
||||
setVisibleOverlayVisible: (visible: boolean) => void;
|
||||
setInvisibleOverlayVisible: (visible: boolean) => void;
|
||||
getResolver: () => ((choice: KikuFieldGroupingChoice) => void) | null;
|
||||
setResolver: (
|
||||
resolver: ((choice: KikuFieldGroupingChoice) => void) | null,
|
||||
) => void;
|
||||
sendToVisibleOverlay: (
|
||||
channel: string,
|
||||
payload?: unknown,
|
||||
runtimeOptions?: { restoreOnModalClose?: T },
|
||||
) => boolean;
|
||||
},
|
||||
): (data: KikuFieldGroupingRequestData) => Promise<KikuFieldGroupingChoice> {
|
||||
return createFieldGroupingCallbackService({
|
||||
getVisibleOverlayVisible: options.getVisibleOverlayVisible,
|
||||
getInvisibleOverlayVisible: options.getInvisibleOverlayVisible,
|
||||
setVisibleOverlayVisible: options.setVisibleOverlayVisible,
|
||||
setInvisibleOverlayVisible: options.setInvisibleOverlayVisible,
|
||||
getResolver: options.getResolver,
|
||||
setResolver: options.setResolver,
|
||||
sendRequestToVisibleOverlay: (data) =>
|
||||
options.sendToVisibleOverlay("kiku:field-grouping-request", data),
|
||||
});
|
||||
}
|
||||
38
src/main.ts
38
src/main.ts
@@ -170,7 +170,6 @@ import {
|
||||
ensureOverlayWindowLevelService,
|
||||
updateOverlayBoundsService,
|
||||
} from "./core/services/overlay-window-service";
|
||||
import { createFieldGroupingCallbackService } from "./core/services/field-grouping-service";
|
||||
import { initializeOverlayRuntimeService } from "./core/services/overlay-runtime-init-service";
|
||||
import {
|
||||
setInvisibleOverlayVisibleService,
|
||||
@@ -185,11 +184,13 @@ import { applyMpvSubtitleRenderMetricsPatchService } from "./core/services/mpv-r
|
||||
import {
|
||||
handleMpvCommandFromIpcService,
|
||||
} from "./core/services/ipc-command-service";
|
||||
import { sendToVisibleOverlayService } from "./core/services/overlay-send-service";
|
||||
import {
|
||||
addOverlayModalRestoreFlagService,
|
||||
handleOverlayModalClosedService,
|
||||
} from "./core/services/overlay-modal-restore-service";
|
||||
import {
|
||||
createFieldGroupingCallbackRuntimeService,
|
||||
sendToVisibleOverlayRuntimeService,
|
||||
} from "./core/services/overlay-bridge-runtime-service";
|
||||
import {
|
||||
runSubsyncManualFromIpcRuntimeService,
|
||||
triggerSubsyncFromConfigRuntimeService,
|
||||
@@ -1235,9 +1236,36 @@ registerIpcHandlersService({
|
||||
* Create and show a desktop notification with robust icon handling.
|
||||
* Supports both file paths (preferred on Linux/Wayland) and data URLs (fallback).
|
||||
*/
|
||||
function createFieldGroupingCallback() { return createFieldGroupingCallbackService({ getVisibleOverlayVisible: () => visibleOverlayVisible, getInvisibleOverlayVisible: () => invisibleOverlayVisible, setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible), setInvisibleOverlayVisible: (visible) => setInvisibleOverlayVisible(visible), getResolver: () => fieldGroupingResolver, setResolver: (resolver) => { fieldGroupingResolver = resolver; }, sendRequestToVisibleOverlay: (data) => sendToVisibleOverlay("kiku:field-grouping-request", data) }); }
|
||||
function createFieldGroupingCallback() {
|
||||
return createFieldGroupingCallbackRuntimeService({
|
||||
getVisibleOverlayVisible: () => visibleOverlayVisible,
|
||||
getInvisibleOverlayVisible: () => invisibleOverlayVisible,
|
||||
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
||||
setInvisibleOverlayVisible: (visible) => setInvisibleOverlayVisible(visible),
|
||||
getResolver: () => fieldGroupingResolver,
|
||||
setResolver: (resolver) => {
|
||||
fieldGroupingResolver = resolver;
|
||||
},
|
||||
sendToVisibleOverlay: (
|
||||
channel,
|
||||
payload,
|
||||
runtimeOptions?: { restoreOnModalClose?: OverlayHostedModal },
|
||||
) =>
|
||||
sendToVisibleOverlay(channel, payload, runtimeOptions),
|
||||
});
|
||||
}
|
||||
|
||||
function sendToVisibleOverlay(channel: string, payload?: unknown, options?: { restoreOnModalClose?: OverlayHostedModal }): boolean { return sendToVisibleOverlayService({ mainWindow, visibleOverlayVisible, setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible), channel, payload, restoreOnModalClose: options?.restoreOnModalClose, addRestoreFlag: (modal) => addOverlayModalRestoreFlagService(restoreVisibleOverlayOnModalClose, modal as OverlayHostedModal) }); }
|
||||
function sendToVisibleOverlay(channel: string, payload?: unknown, options?: { restoreOnModalClose?: OverlayHostedModal }): boolean {
|
||||
return sendToVisibleOverlayRuntimeService({
|
||||
mainWindow,
|
||||
visibleOverlayVisible,
|
||||
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
||||
channel,
|
||||
payload,
|
||||
restoreOnModalClose: options?.restoreOnModalClose,
|
||||
restoreVisibleOverlayOnModalClose,
|
||||
});
|
||||
}
|
||||
|
||||
registerAnkiJimakuIpcRuntimeService({
|
||||
patchAnkiConnectEnabled: (enabled) => { configService.patchRawConfig({ ankiConnect: { enabled } }); },
|
||||
|
||||
Reference in New Issue
Block a user