mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
Restore overlay keybindings
This commit is contained in:
@@ -128,7 +128,7 @@ src/renderer/
|
|||||||
The main process has three layers: `main.ts` delegates to composition modules that wire together domain services. Three overlay windows (visible, invisible, secondary) run in separate Electron renderer processes, connected through `preload.ts`. External runtimes (launcher CLI and mpv plugin) operate independently and communicate via IPC socket or CLI passthrough.
|
The main process has three layers: `main.ts` delegates to composition modules that wire together domain services. Three overlay windows (visible, invisible, secondary) run in separate Electron renderer processes, connected through `preload.ts`. External runtimes (launcher CLI and mpv plugin) operate independently and communicate via IPC socket or CLI passthrough.
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
flowchart TD
|
flowchart LR
|
||||||
classDef entry fill:#c6a0f6,stroke:#494d64,color:#24273a,stroke-width:2px,font-weight:bold
|
classDef entry fill:#c6a0f6,stroke:#494d64,color:#24273a,stroke-width:2px,font-weight:bold
|
||||||
classDef comp fill:#b7bdf8,stroke:#494d64,color:#24273a,stroke-width:1.5px
|
classDef comp fill:#b7bdf8,stroke:#494d64,color:#24273a,stroke-width:1.5px
|
||||||
classDef svc fill:#8aadf4,stroke:#494d64,color:#24273a,stroke-width:1.5px
|
classDef svc fill:#8aadf4,stroke:#494d64,color:#24273a,stroke-width:1.5px
|
||||||
@@ -137,94 +137,70 @@ flowchart TD
|
|||||||
classDef ext fill:#a6da95,stroke:#494d64,color:#24273a,stroke-width:1.5px
|
classDef ext fill:#a6da95,stroke:#494d64,color:#24273a,stroke-width:1.5px
|
||||||
classDef extrt fill:#eed49f,stroke:#494d64,color:#24273a,stroke-width:1.5px
|
classDef extrt fill:#eed49f,stroke:#494d64,color:#24273a,stroke-width:1.5px
|
||||||
|
|
||||||
Main["main.ts — composition root"]:::entry
|
subgraph ExtRt["External Runtimes"]
|
||||||
|
Launcher["launcher/<br/>CLI dispatch"]:::extrt
|
||||||
subgraph Comp["Composition — src/main/"]
|
Plugin["subminer.lua<br/>mpv plugin"]:::extrt
|
||||||
direction TB
|
|
||||||
Startup["Startup & Lifecycle<br/>startup · app-lifecycle · startup-lifecycle · state"]:::comp
|
|
||||||
Wiring["Runtime Wiring<br/>ipc-runtime · cli-runtime · overlay-runtime · subsync-runtime"]:::comp
|
|
||||||
Composers["Composers<br/>mpv-runtime · anilist-tracking · jellyfin-runtime"]:::comp
|
|
||||||
end
|
|
||||||
|
|
||||||
subgraph Svc["Services — src/core/services/"]
|
|
||||||
direction TB
|
|
||||||
subgraph SvcRow1[" "]
|
|
||||||
direction LR
|
|
||||||
Mpv["MPV Stack<br/>transport · protocol<br/>properties · render-metrics"]:::svc
|
|
||||||
Overlay["Overlay Manager<br/>window · geometry<br/>visibility · bridge"]:::svc
|
|
||||||
end
|
|
||||||
subgraph SvcRow2[" "]
|
|
||||||
direction LR
|
|
||||||
Mining["Mining & Subtitles<br/>mining · field-grouping<br/>subtitle-ws · tokenizer"]:::svc
|
|
||||||
Integrations["Integrations<br/>jimaku · subsync · texthooker<br/>yomitan · discord-presence"]:::svc
|
|
||||||
end
|
|
||||||
subgraph SvcRow3[" "]
|
|
||||||
direction LR
|
|
||||||
Tracking["Tracking<br/>anilist · jellyfin-remote<br/>immersion-tracker"]:::svc
|
|
||||||
Config["Config & Runtime<br/>config-hot-reload<br/>runtime-options"]:::svc
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Bridge(["preload.ts — Electron IPC bridge"]):::bridge
|
|
||||||
|
|
||||||
subgraph Rend["Renderer — src/renderer/"]
|
|
||||||
direction TB
|
|
||||||
subgraph Windows["Three overlay windows"]
|
|
||||||
direction LR
|
|
||||||
Visible["Visible<br/>interactive Yomitan lookups"]:::rend
|
|
||||||
Invisible["Invisible<br/>mpv-matched positioning"]:::rend
|
|
||||||
Secondary["Secondary<br/>secondary subtitle bar"]:::rend
|
|
||||||
end
|
|
||||||
UI["subtitle-render · positioning · handlers · modals"]:::rend
|
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph Ext["External Systems"]
|
subgraph Ext["External Systems"]
|
||||||
direction LR
|
|
||||||
mpvExt["mpv player"]:::ext
|
mpvExt["mpv player"]:::ext
|
||||||
AnkiExt["AnkiConnect"]:::ext
|
AnkiExt["AnkiConnect"]:::ext
|
||||||
JimakuExt["Jimaku API"]:::ext
|
JimakuExt["Jimaku API"]:::ext
|
||||||
TrackerExt["Window Tracker<br/>Hyprland · Sway · X11 · macOS"]:::ext
|
TrackerExt["Window Tracker<br/>Hyprland · Sway<br/>X11 · macOS"]:::ext
|
||||||
AnilistExt["AniList API"]:::ext
|
AnilistExt["AniList API"]:::ext
|
||||||
JellyfinExt["Jellyfin"]:::ext
|
JellyfinExt["Jellyfin"]:::ext
|
||||||
DiscordExt["Discord RPC"]:::ext
|
DiscordExt["Discord RPC"]:::ext
|
||||||
end
|
end
|
||||||
|
|
||||||
subgraph ExtRt["External Runtimes"]
|
Main["main.ts<br/>composition root"]:::entry
|
||||||
direction LR
|
|
||||||
Launcher["launcher/<br/>CLI command dispatch"]:::extrt
|
subgraph Comp["Composition — src/main/"]
|
||||||
Plugin["subminer.lua<br/>mpv plugin"]:::extrt
|
Startup["Startup & Lifecycle<br/>startup · app-lifecycle<br/>startup-lifecycle · state"]:::comp
|
||||||
|
Wiring["Runtime Wiring<br/>ipc-runtime · cli-runtime<br/>overlay-runtime"]:::comp
|
||||||
|
Composers["Composers<br/>mpv · anilist<br/>jellyfin"]:::comp
|
||||||
end
|
end
|
||||||
|
|
||||||
Main -->|"delegates"| Comp
|
subgraph Svc["Services — src/core/services/"]
|
||||||
Startup -->|"initializes"| Svc
|
Mpv["MPV Stack<br/>transport · protocol<br/>properties · metrics"]:::svc
|
||||||
Wiring -->|"dispatches to"| Svc
|
Overlay["Overlay Manager<br/>window · geometry<br/>visibility · bridge"]:::svc
|
||||||
Composers -->|"wires"| Svc
|
Mining["Mining & Subtitles<br/>mining · field-grouping<br/>subtitle-ws · tokenizer"]:::svc
|
||||||
|
Integrations["Integrations<br/>jimaku · subsync<br/>texthooker · yomitan"]:::svc
|
||||||
|
Tracking["Tracking<br/>anilist · jellyfin<br/>immersion · discord"]:::svc
|
||||||
|
Config["Config & Runtime<br/>hot-reload<br/>runtime-options"]:::svc
|
||||||
|
end
|
||||||
|
|
||||||
Overlay <-->Bridge
|
Bridge(["preload.ts<br/>Electron IPC"]):::bridge
|
||||||
Mining <--> Bridge
|
|
||||||
Bridge <--> Visible
|
|
||||||
Bridge <--> Invisible
|
|
||||||
Bridge <--> Secondary
|
|
||||||
Windows --> UI
|
|
||||||
|
|
||||||
Mpv <-->|"JSON IPC socket"| mpvExt
|
subgraph Rend["Renderer — src/renderer/"]
|
||||||
Mining -->|"HTTP"| AnkiExt
|
Visible["Visible window<br/>Yomitan lookups"]:::rend
|
||||||
Integrations -->|"HTTP"| JimakuExt
|
Invisible["Invisible window<br/>mpv positioning"]:::rend
|
||||||
Overlay -->|"platform API"| TrackerExt
|
Secondary["Secondary window<br/>subtitle bar"]:::rend
|
||||||
Tracking -->|"HTTP"| AnilistExt
|
UI["subtitle-render<br/>positioning<br/>handlers · modals"]:::rend
|
||||||
Tracking -->|"HTTP"| JellyfinExt
|
end
|
||||||
Integrations -->|"RPC"| DiscordExt
|
|
||||||
|
|
||||||
Launcher -->|"CLI passthrough"| Main
|
Launcher -->|"CLI"| Main
|
||||||
Plugin -->|"IPC socket"| mpvExt
|
Plugin -->|"IPC"| mpvExt
|
||||||
|
|
||||||
|
Main --> Comp
|
||||||
|
Comp --> Svc
|
||||||
|
|
||||||
|
mpvExt <-->|"JSON socket"| Mpv
|
||||||
|
AnkiExt <-->|"HTTP"| Mining
|
||||||
|
JimakuExt <-->|"HTTP"| Integrations
|
||||||
|
TrackerExt <-->|"platform"| Overlay
|
||||||
|
AnilistExt <-->|"HTTP"| Tracking
|
||||||
|
JellyfinExt <-->|"HTTP"| Tracking
|
||||||
|
DiscordExt <-->|"RPC"| Integrations
|
||||||
|
|
||||||
|
Overlay & Mining --> Bridge
|
||||||
|
Bridge --> Visible
|
||||||
|
Bridge --> Invisible
|
||||||
|
Bridge --> Secondary
|
||||||
|
Visible & Invisible & Secondary --> UI
|
||||||
|
|
||||||
style Comp fill:#363a4f,stroke:#494d64,color:#cad3f5
|
style Comp fill:#363a4f,stroke:#494d64,color:#cad3f5
|
||||||
style Svc fill:#363a4f,stroke:#494d64,color:#cad3f5
|
style Svc fill:#363a4f,stroke:#494d64,color:#cad3f5
|
||||||
style SvcRow1 fill:transparent,stroke:none
|
|
||||||
style SvcRow2 fill:transparent,stroke:none
|
|
||||||
style SvcRow3 fill:transparent,stroke:none
|
|
||||||
style Rend fill:#363a4f,stroke:#494d64,color:#cad3f5
|
style Rend fill:#363a4f,stroke:#494d64,color:#cad3f5
|
||||||
style Windows fill:#1e2030,stroke:#494d64,color:#cad3f5
|
|
||||||
style Ext fill:#363a4f,stroke:#494d64,color:#cad3f5
|
style Ext fill:#363a4f,stroke:#494d64,color:#cad3f5
|
||||||
style ExtRt fill:#363a4f,stroke:#494d64,color:#cad3f5
|
style ExtRt fill:#363a4f,stroke:#494d64,color:#cad3f5
|
||||||
```
|
```
|
||||||
|
|||||||
BIN
flow-diagram-fullview.png
Normal file
BIN
flow-diagram-fullview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 142 KiB |
BIN
flow-review-full.png
Normal file
BIN
flow-review-full.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 130 KiB |
BIN
lifecycle-diagram-fullview.png
Normal file
BIN
lifecycle-diagram-fullview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 208 KiB |
@@ -1595,10 +1595,7 @@ local function start_overlay_from_script_message(...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function stop_overlay()
|
local function stop_overlay()
|
||||||
if not is_subminer_app_running() then
|
if not ensure_binary_available() then
|
||||||
return
|
|
||||||
end
|
|
||||||
if not state.binary_available then
|
|
||||||
subminer_log("error", "binary", "SubMiner binary not found")
|
subminer_log("error", "binary", "SubMiner binary not found")
|
||||||
show_osd("Error: binary not found")
|
show_osd("Error: binary not found")
|
||||||
return
|
return
|
||||||
@@ -1626,10 +1623,7 @@ local function stop_overlay()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function toggle_overlay()
|
local function toggle_overlay()
|
||||||
if not is_subminer_app_running() then
|
if not ensure_binary_available() then
|
||||||
return
|
|
||||||
end
|
|
||||||
if not state.binary_available then
|
|
||||||
subminer_log("error", "binary", "SubMiner binary not found")
|
subminer_log("error", "binary", "SubMiner binary not found")
|
||||||
show_osd("Error: binary not found")
|
show_osd("Error: binary not found")
|
||||||
return
|
return
|
||||||
@@ -1653,10 +1647,7 @@ local function toggle_overlay()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function toggle_invisible_overlay()
|
local function toggle_invisible_overlay()
|
||||||
if not is_subminer_app_running() then
|
if not ensure_binary_available() then
|
||||||
return
|
|
||||||
end
|
|
||||||
if not state.binary_available then
|
|
||||||
subminer_log("error", "binary", "SubMiner binary not found")
|
subminer_log("error", "binary", "SubMiner binary not found")
|
||||||
show_osd("Error: binary not found")
|
show_osd("Error: binary not found")
|
||||||
return
|
return
|
||||||
@@ -1684,10 +1675,7 @@ local function toggle_invisible_overlay()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function show_invisible_overlay()
|
local function show_invisible_overlay()
|
||||||
if not is_subminer_app_running() then
|
if not ensure_binary_available() then
|
||||||
return
|
|
||||||
end
|
|
||||||
if not state.binary_available then
|
|
||||||
subminer_log("error", "binary", "SubMiner binary not found")
|
subminer_log("error", "binary", "SubMiner binary not found")
|
||||||
show_osd("Error: binary not found")
|
show_osd("Error: binary not found")
|
||||||
return
|
return
|
||||||
@@ -1715,10 +1703,7 @@ local function show_invisible_overlay()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function hide_invisible_overlay()
|
local function hide_invisible_overlay()
|
||||||
if not is_subminer_app_running() then
|
if not ensure_binary_available() then
|
||||||
return
|
|
||||||
end
|
|
||||||
if not state.binary_available then
|
|
||||||
subminer_log("error", "binary", "SubMiner binary not found")
|
subminer_log("error", "binary", "SubMiner binary not found")
|
||||||
show_osd("Error: binary not found")
|
show_osd("Error: binary not found")
|
||||||
return
|
return
|
||||||
@@ -1811,10 +1796,7 @@ local function show_menu()
|
|||||||
end
|
end
|
||||||
|
|
||||||
restart_overlay = function()
|
restart_overlay = function()
|
||||||
if not is_subminer_app_running() then
|
if not ensure_binary_available() then
|
||||||
return
|
|
||||||
end
|
|
||||||
if not state.binary_available then
|
|
||||||
subminer_log("error", "binary", "SubMiner binary not found")
|
subminer_log("error", "binary", "SubMiner binary not found")
|
||||||
show_osd("Error: binary not found")
|
show_osd("Error: binary not found")
|
||||||
return
|
return
|
||||||
|
|||||||
21
src/main.ts
21
src/main.ts
@@ -2926,11 +2926,30 @@ function handleMineSentenceDigit(count: number): void {
|
|||||||
handleMineSentenceDigitHandler(count);
|
handleMineSentenceDigitHandler(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ensureOverlayWindowsReadyForVisibilityActions(): void {
|
||||||
|
if (!appState.overlayRuntimeInitialized) {
|
||||||
|
initializeOverlayRuntime();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mainWindow = overlayManager.getMainWindow();
|
||||||
|
if (!mainWindow || mainWindow.isDestroyed()) {
|
||||||
|
createMainWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
const invisibleWindow = overlayManager.getInvisibleWindow();
|
||||||
|
if (!invisibleWindow || invisibleWindow.isDestroyed()) {
|
||||||
|
createInvisibleWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setVisibleOverlayVisible(visible: boolean): void {
|
function setVisibleOverlayVisible(visible: boolean): void {
|
||||||
|
ensureOverlayWindowsReadyForVisibilityActions();
|
||||||
setVisibleOverlayVisibleHandler(visible);
|
setVisibleOverlayVisibleHandler(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setInvisibleOverlayVisible(visible: boolean): void {
|
function setInvisibleOverlayVisible(visible: boolean): void {
|
||||||
|
ensureOverlayWindowsReadyForVisibilityActions();
|
||||||
setInvisibleOverlayVisibleHandler(visible);
|
setInvisibleOverlayVisibleHandler(visible);
|
||||||
if (visible) {
|
if (visible) {
|
||||||
subtitleProcessingController.refreshCurrentSubtitle(appState.currentSubText);
|
subtitleProcessingController.refreshCurrentSubtitle(appState.currentSubText);
|
||||||
@@ -2938,9 +2957,11 @@ function setInvisibleOverlayVisible(visible: boolean): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function toggleVisibleOverlay(): void {
|
function toggleVisibleOverlay(): void {
|
||||||
|
ensureOverlayWindowsReadyForVisibilityActions();
|
||||||
toggleVisibleOverlayHandler();
|
toggleVisibleOverlayHandler();
|
||||||
}
|
}
|
||||||
function toggleInvisibleOverlay(): void {
|
function toggleInvisibleOverlay(): void {
|
||||||
|
ensureOverlayWindowsReadyForVisibilityActions();
|
||||||
toggleInvisibleOverlayHandler();
|
toggleInvisibleOverlayHandler();
|
||||||
}
|
}
|
||||||
function setOverlayVisible(visible: boolean): void {
|
function setOverlayVisible(visible: boolean): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user