Files
SubMiner/src/main/runtime/yomitan-extension-runtime.ts
T

93 lines
3.4 KiB
TypeScript

import {
createEnsureYomitanExtensionLoadedHandler,
createLoadYomitanExtensionHandler,
} from './yomitan-extension-loader';
import type { Extension } from 'electron';
import {
createBuildEnsureYomitanExtensionLoadedMainDepsHandler,
createBuildLoadYomitanExtensionMainDepsHandler,
} from './yomitan-extension-loader-main-deps';
type LoadYomitanExtensionMainDeps = Parameters<
typeof createBuildLoadYomitanExtensionMainDepsHandler
>[0];
type EnsureYomitanExtensionLoadedMainDeps = Omit<
Parameters<typeof createBuildEnsureYomitanExtensionLoadedMainDepsHandler>[0],
'loadYomitanExtension'
>;
export type YomitanExtensionRuntimeDeps = LoadYomitanExtensionMainDeps &
EnsureYomitanExtensionLoadedMainDeps & {
onYomitanExtensionLoaded?: (extension: Extension) => void | Promise<void>;
};
export function createYomitanExtensionRuntime(deps: YomitanExtensionRuntimeDeps) {
const buildLoadYomitanExtensionMainDepsHandler = createBuildLoadYomitanExtensionMainDepsHandler({
loadYomitanExtensionCore: deps.loadYomitanExtensionCore,
userDataPath: deps.userDataPath,
externalProfilePath: deps.externalProfilePath,
getYomitanParserWindow: deps.getYomitanParserWindow,
setYomitanParserWindow: deps.setYomitanParserWindow,
setYomitanParserReadyPromise: deps.setYomitanParserReadyPromise,
setYomitanParserInitPromise: deps.setYomitanParserInitPromise,
setYomitanExtension: deps.setYomitanExtension,
setYomitanSession: deps.setYomitanSession,
});
const loadYomitanExtensionHandler = createLoadYomitanExtensionHandler(
buildLoadYomitanExtensionMainDepsHandler(),
);
const buildEnsureYomitanExtensionLoadedMainDepsHandler =
createBuildEnsureYomitanExtensionLoadedMainDepsHandler({
getYomitanExtension: deps.getYomitanExtension,
getLoadInFlight: deps.getLoadInFlight,
setLoadInFlight: deps.setLoadInFlight,
loadYomitanExtension: () => loadYomitanExtensionHandler(),
});
const ensureYomitanExtensionLoadedHandler = createEnsureYomitanExtensionLoadedHandler(
buildEnsureYomitanExtensionLoadedMainDepsHandler(),
);
let lastNotifiedExtension: Extension | null = null;
let notifyingExtension: Extension | null = null;
let notificationPromise: Promise<void> | null = null;
async function notifyYomitanExtensionLoaded(extension: Extension | null): Promise<void> {
if (!extension || extension === lastNotifiedExtension) {
return;
}
if (extension === notifyingExtension && notificationPromise) {
await notificationPromise;
return;
}
notifyingExtension = extension;
notificationPromise = (async () => {
await deps.onYomitanExtensionLoaded?.(extension);
lastNotifiedExtension = extension;
})();
try {
await notificationPromise;
} finally {
if (notifyingExtension === extension) {
notifyingExtension = null;
notificationPromise = null;
}
}
}
return {
loadYomitanExtension: async (): Promise<ReturnType<typeof deps.getYomitanExtension>> => {
const extension = await loadYomitanExtensionHandler();
await notifyYomitanExtensionLoaded(extension);
return extension;
},
ensureYomitanExtensionLoaded: async (): Promise<
ReturnType<typeof deps.getYomitanExtension>
> => {
const extension = await ensureYomitanExtensionLoadedHandler();
await notifyYomitanExtensionLoaded(extension);
return extension;
},
};
}