refactor: extract overlay bridge runtime helpers

This commit is contained in:
2026-02-09 23:35:39 -08:00
parent 53c2e6353a
commit 7715c1ddd2
4 changed files with 171 additions and 6 deletions

View 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);
});

View 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),
});
}