feat(config): unify mpv plugin options under main config and add CSS/Ani

- Replace subminer.conf plugin config with mpv.* fields in config.jsonc
- Add socketPath, backend, autoStartSubMiner, pauseUntilOverlayReady, aniskipEnabled/buttonKey, subminerBinaryPath to mpv config
- Add subtitleSidebar.css field; migrate legacy sidebar appearance fields
- Add paintOrder and WebkitTextStroke to subtitle style options
- Update default subtitle/sidebar fontFamily to CJK-first stack
- Fix overlay visible state surviving mpv y-r restart
- Fix live config saves applying subtitle CSS immediately to open overlays
- Migrate legacy primary/secondary subtitle appearance into subtitleStyle.css on load
- Switch AniSkip button key setting to click-to-learn key capture
This commit is contained in:
2026-05-17 18:01:39 -07:00
parent 81830b3372
commit 6ba91780c1
91 changed files with 2241 additions and 727 deletions
+25 -21
View File
@@ -161,29 +161,39 @@ const onKikuFieldGroupingRequestEvent =
IPC_CHANNELS.event.kikuFieldGroupingRequest,
(payload) => payload as KikuFieldGroupingRequestData,
);
const onSubtitleSetEvent = createQueuedIpcListenerWithPayload<SubtitleData>(
IPC_CHANNELS.event.subtitleSet,
(payload) => payload as SubtitleData,
);
const onSubtitleVisibilityEvent = createQueuedIpcListenerWithPayload<boolean>(
IPC_CHANNELS.event.subtitleVisibility,
(payload) => payload === true,
);
const onSubtitlePositionSetEvent = createQueuedIpcListenerWithPayload<SubtitlePosition | null>(
IPC_CHANNELS.event.subtitlePositionSet,
(payload) => payload as SubtitlePosition | null,
);
const onSecondarySubtitleSetEvent = createQueuedIpcListenerWithPayload<string>(
IPC_CHANNELS.event.secondarySubtitleSet,
(payload) => (typeof payload === 'string' ? payload : ''),
);
const onSecondarySubtitleModeEvent = createQueuedIpcListenerWithPayload<SecondarySubMode>(
IPC_CHANNELS.event.secondarySubtitleMode,
(payload) => payload as SecondarySubMode,
);
const electronAPI: ElectronAPI = {
getOverlayLayer: () => overlayLayer,
onSubtitle: (callback: (data: SubtitleData) => void) => {
ipcRenderer.on(IPC_CHANNELS.event.subtitleSet, (_event: IpcRendererEvent, data: SubtitleData) =>
callback(data),
);
onSubtitleSetEvent(callback);
},
onVisibility: (callback: (visible: boolean) => void) => {
ipcRenderer.on(
IPC_CHANNELS.event.subtitleVisibility,
(_event: IpcRendererEvent, visible: boolean) => callback(visible),
);
onSubtitleVisibilityEvent(callback);
},
onSubtitlePosition: (callback: (position: SubtitlePosition | null) => void) => {
ipcRenderer.on(
IPC_CHANNELS.event.subtitlePositionSet,
(_event: IpcRendererEvent, position: SubtitlePosition | null) => {
callback(position);
},
);
onSubtitlePositionSetEvent(callback);
},
getOverlayVisibility: (): Promise<boolean> =>
@@ -290,17 +300,11 @@ const electronAPI: ElectronAPI = {
},
onSecondarySub: (callback: (text: string) => void) => {
ipcRenderer.on(
IPC_CHANNELS.event.secondarySubtitleSet,
(_event: IpcRendererEvent, text: string) => callback(text),
);
onSecondarySubtitleSetEvent(callback);
},
onSecondarySubMode: (callback: (mode: SecondarySubMode) => void) => {
ipcRenderer.on(
IPC_CHANNELS.event.secondarySubtitleMode,
(_event: IpcRendererEvent, mode: SecondarySubMode) => callback(mode),
);
onSecondarySubtitleModeEvent(callback);
},
getSecondarySubMode: (): Promise<SecondarySubMode> =>