diff --git a/Makefile b/Makefile index d962b83..0c21764 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ .PHONY: help deps build build-launcher install build-linux build-macos build-macos-unsigned clean install-linux install-macos install-plugin uninstall uninstall-linux uninstall-macos print-dirs pretty ensure-bun generate-config generate-example-config docs-dev docs docs-preview dev-start dev-start-macos dev-toggle dev-stop APP_NAME := subminer +THEME_SOURCE := assets/themes/subminer.rasi THEME_FILE := subminer.rasi PLUGIN_LUA := plugin/subminer.lua PLUGIN_CONF := plugin/subminer.conf @@ -181,7 +182,7 @@ install-linux: build-launcher @install -d "$(BINDIR)" @install -m 0755 "./$(APP_NAME)" "$(BINDIR)/$(APP_NAME)" @install -d "$(LINUX_DATA_DIR)/themes" - @install -m 0644 "./$(THEME_FILE)" "$(LINUX_DATA_DIR)/themes/$(THEME_FILE)" + @install -m 0644 "./$(THEME_SOURCE)" "$(LINUX_DATA_DIR)/themes/$(THEME_FILE)" @if [ -n "$(APPIMAGE_SRC)" ]; then \ install -m 0755 "$(APPIMAGE_SRC)" "$(BINDIR)/SubMiner.AppImage"; \ else \ @@ -195,7 +196,7 @@ install-macos: build-launcher @install -d "$(BINDIR)" @install -m 0755 "./$(APP_NAME)" "$(BINDIR)/$(APP_NAME)" @install -d "$(MACOS_DATA_DIR)/themes" - @install -m 0644 "./$(THEME_FILE)" "$(MACOS_DATA_DIR)/themes/$(THEME_FILE)" + @install -m 0644 "./$(THEME_SOURCE)" "$(MACOS_DATA_DIR)/themes/$(THEME_FILE)" @install -d "$(MACOS_APP_DIR)" @if [ -n "$(MACOS_APP_SRC)" ]; then \ rm -rf "$(MACOS_APP_DEST)"; \ diff --git a/README.md b/README.md index d6a1e74..a6129e3 100644 --- a/README.md +++ b/README.md @@ -1,139 +1,95 @@
SubMiner logo

SubMiner

-

Immersion mining overlay for mpv — look up words, mine to Anki, and enrich cards with context without leaving the video.

+ Look up words, mine to Anki, and enrich cards with context — without leaving mpv. +

+ +[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[![Linux](https://img.shields.io/badge/platform-Linux%20%7C%20macOS-informational)]() +[![Docs](https://img.shields.io/badge/docs-docs.subminer.moe-blueviolet)](https://docs.subminer.moe) +
---- +
+ +
[![Demo](./assets/demo-poster.jpg)](https://github.com/user-attachments/assets/9235a554-ea51-4284-b14b-7bbf3defaf58) -## Features +_Click to watch the demo_ -- **Yomitan Integration** — Hover subtitle words to trigger dictionary lookups in the player -- **Anki Card Enrichment** — Fills sentence, audio, screenshot, and translation on new cards automatically -- **Dual-Layer Subtitles** — Interactive visible overlay + invisible click-through layer aligned with mpv rendering -- **N+1 Highlighting** — Marks known vocabulary from your Anki deck so you can spot new words at a glance -- **Texthooker & WebSocket** — Built-in texthooker page with WebSocket streaming for external tools -- **Subtitle Download & Sync** — Search Jimaku, sync with alass or ffsubsync — all from the player -- **Queue Control In-Player** — Drop videos on overlay to load/queue in mpv; `Ctrl/Cmd+A` appends clipboard path -- **Keyboard-Driven** — Mine, copy, cycle display modes, and navigate from configurable shortcuts -- **Config Hot Reload** — Apply subtitle style and shortcut updates from `config.jsonc` without restarting -- **Japanese Tokenization** — MeCab-powered word boundary detection with smart grouping +
-## Requirements +
-- `mpv` with IPC socket support -- `mecab` and `mecab-ipadic` -- Linux: Hyprland (`hyprctl`) or X11 (`xdotool` + `xwininfo`) -- macOS: Accessibility permission for window tracking +## What it does -Optional: `yt-dlp`, `fzf`, `rofi`, `chafa`, `ffmpegthumbnailer` +SubMiner is an Electron overlay that sits on top of mpv. It turns your video player into a full sentence-mining workstation: -## Install +- **Hover to look up** — Yomitan dictionary popups directly on subtitles +- **One-key mining** — Creates Anki cards with sentence, audio, screenshot, and translation +- **N+1 highlighting** — Marks known words from your Anki deck so unknown ones jump out +- **Subtitle tools** — Download from Jimaku, sync with alass/ffsubsync, all in-player +- **Immersion tracking** — SQLite-powered stats on your watch time and mining activity +- **Texthooker page built in** — WebSocket streaming to external tools, no extra setup -### Linux (AppImage) +## Quick start + +### 1. Install + +**Linux (AppImage):** ```bash -wget https://github.com/ksyasuda/SubMiner/releases/download/v0.1.0/SubMiner-0.1.0.AppImage -O ~/.local/bin/SubMiner.AppImage +wget https://github.com/ksyasuda/SubMiner/releases/latest/download/SubMiner-0.1.0.AppImage -O ~/.local/bin/SubMiner.AppImage chmod +x ~/.local/bin/SubMiner.AppImage -wget https://github.com/ksyasuda/SubMiner/releases/download/v0.1.0/subminer -O ~/.local/bin/subminer +wget https://github.com/ksyasuda/SubMiner/releases/latest/download/subminer -O ~/.local/bin/subminer chmod +x ~/.local/bin/subminer ``` -The `subminer` wrapper uses a [Bun](https://bun.sh) shebang, so `bun` must be on `PATH`. +> [!NOTE] +> The `subminer` wrapper uses a [Bun](https://bun.sh) shebang. Make sure `bun` is on your `PATH`. -### From Source +**From source** or **macOS** — see the [installation guide](https://docs.subminer.moe/installation#from-source). + +### 2. Install the mpv plugin and configuration file ```bash -git clone --recurse-submodules https://github.com/ksyasuda/SubMiner.git -cd SubMiner -bun install -cd vendor/texthooker-ui && pnpm install --frozen-lockfile && cd ../.. -make build -make install +wget https://github.com/ksyasuda/SubMiner/releases/latest/download/subminer-assets-0.1.0.tar.gz -O /tmp/subminer-assets.tar.gz +tar -xzf /tmp/subminer-assets.tar.gz -C /tmp +cp /tmp/plugin/subminer.lua ~/.config/mpv/scripts/ +cp /tmp/plugin/subminer.conf ~/.config/mpv/script-opts/ +mkdir -p ~/.config/SubMiner && cp /tmp/config.example.jsonc ~/.config/SubMiner/config.jsonc ``` -For macOS builds and platform details, see the [installation docs](docs/installation.md). - -## Quick Start - -1. Copy [`config.example.jsonc`](config.example.jsonc) to `~/.config/SubMiner/config.jsonc` - - Regenerate anytime from source: `make generate-example-config` or `bun run generate:config-example` -2. Start mpv with IPC: - ```bash - mpv --input-ipc-server=/tmp/subminer-socket video.mkv - ``` -3. Launch SubMiner: - ```bash - subminer --start video.mkv - SubMiner.AppImage --background # tray/background mode (desktop launcher default) - ``` - -Config tip: while SubMiner is running, safe config edits (subtitle style, keybindings, shortcuts, secondary subtitle default mode, and `ankiConnect.ai`) hot-reload automatically. +### 3. Set up Yomitan Dictionaries ```bash -subminer # pick video from cwd (fzf) -subminer -R # rofi picker -subminer -d ~/Videos # set source directory -subminer -r -d ~/Anime # recursive search -subminer -p gpu-hq video.mkv # override mpv profile -subminer -T video.mkv # disable texthooker -subminer https://youtu.be/... # YouTube playback -subminer jellyfin -d # Jellyfin cast discovery mode -subminer doctor # dependency/config/socket diagnostics -subminer config path # print active config file path -subminer mpv status # mpv socket readiness check +subminer app --start --yomitan ``` -### Launcher Subcommands - -- `subminer jellyfin` / `subminer jf` — Jellyfin workflows (`-d` discovery, `-p` play, `-l` login) -- `subminer yt` / `subminer youtube` — YouTube shorthand (`-o/--out-dir`, `-m/--mode`) -- `subminer doctor` — quick environment health checks -- `subminer config path|show` — inspect active config path/content -- `subminer mpv status|socket|idle` — mpv socket and idle-launch helpers -- `subminer texthooker` — texthooker-only shortcut - -Use `subminer -h` for command-specific help pages (for example `subminer jellyfin -h`). - -### CLI Logging and Dev Mode - -- Use `--log-level` to control logger verbosity (for example `--log-level debug`). -- Use `--dev` and `--debug` only for app/dev-mode behavior; they are not tied to logging level. -- Default logging is `info`, except `--background` mode defaults to `warn` unless `--log-level` is set. - -### Overlay Queue Controls - -- Drag/drop video file(s) onto overlay: - - default: replace current playback with first file, append remaining dropped files - - hold `Shift`: append all dropped files -- Press `Ctrl/Cmd+A` to append the clipboard path when it points to a readable local video file. - -## MPV Plugin +### 4. Mine ```bash -cp plugin/subminer.lua ~/.config/mpv/scripts/ -cp plugin/subminer.conf ~/.config/mpv/script-opts/ -# or: make install-plugin +subminer app --start --background +subminer video.mkv ``` -Default chord prefix: `y` (`y-y` menu, `y-s` start, `y-S` stop, `y-t` toggle overlay). -Jimaku shortcut: `Ctrl+Shift+J`. +## Requirements + +| Required | Optional | +| ------------------------------------------ | ---------------------------- | +| `mpv` with IPC socket | `yt-dlp` | +| `mecab` + `mecab-ipadic` | `fzf` / `rofi` | +| Linux: `hyprctl` or `xdotool` + `xwininfo` | `chafa`, `ffmpegthumbnailer` | +| macOS: Accessibility permission | | ## Documentation -Full guides at [**docs/**](docs/README.md): -[Installation](docs/installation.md) · [Usage](docs/usage.md) · [Mining Workflow](docs/mining-workflow.md) · [Configuration](docs/configuration.md) · [Anki Integration](docs/anki-integration.md) · [MPV Plugin](docs/mpv-plugin.md) · [Troubleshooting](docs/troubleshooting.md) · [Architecture](docs/architecture.md) +For full guides on configuration, Anki, Jellyfin, and more, see [docs.subminer.moe](https://docs.subminer.moe). ## Acknowledgments -- [GameSentenceMiner](https://github.com/bpwhelan/GameSentenceMiner) — Inspiration for the overlay and Yomitan integration -- [Jimaku.cc](https://jimaku.cc) — Japanese subtitle provider -- [mpvacious](https://github.com/Ajatt-Tools/mpvacious), [Anacreon-Script](https://github.com/friedrich-de/Anacreon-Script), [autosubsync-mpv](https://github.com/joaquintorres/autosubsync-mpv) — Mining and sync logic ported to TypeScript - -**Third-party:** -[Yomitan](https://github.com/yomidevs/yomitan) · [texthooker-ui](https://github.com/ksyasuda/texthooker-ui/tree/subminer) · [yomitan-jlpt-vocab](https://github.com/stephenmk/yomitan-jlpt-vocab) · [Jiten Frequency Dictionary](https://jiten.moe/) +Built on the shoulders of [GameSentenceMiner](https://github.com/bpwhelan/GameSentenceMiner), [mpvacious](https://github.com/Ajatt-Tools/mpvacious), [Anacreon-Script](https://github.com/friedrich-de/Anacreon-Script), and [autosubsync-mpv](https://github.com/joaquintorres/autosubsync-mpv). Subtitles powered by [Jimaku.cc](https://jimaku.cc). Dictionary lookups via [Yomitan](https://github.com/yomidevs/yomitan). ## License diff --git a/subminer.rasi b/assets/themes/subminer.rasi similarity index 70% rename from subminer.rasi rename to assets/themes/subminer.rasi index bae317b..fc90b82 100644 --- a/subminer.rasi +++ b/assets/themes/subminer.rasi @@ -26,7 +26,7 @@ mantle: #1e2030; crust: #181926; - background-color: @base; + background-color: @mantle; text-color: @text; accent: @mauve; } @@ -37,25 +37,26 @@ configuration { } window { - width: 88%; - height: 88%; - background-color: @base; - border: 2px; - border-color: @mauve; - border-radius: 8px; + width: 69%; + height: 69%; + background-color: @mantle; + border: 1px; + border-color: @surface1; + border-radius: 12px; } mainbox { children: [inputbar, listview-split]; background-color: transparent; + padding: 8px; } inputbar { children: [prompt, entry]; - background-color: @surface0; - padding: 12px; - border-radius: 4px; - margin: 8px; + background-color: @base; + padding: 14px 18px; + border-radius: 8px; + margin: 4px 4px 0px 4px; } prompt { @@ -73,53 +74,60 @@ entry { listview-split { orientation: horizontal; children: [listview]; - spacing: 8px; background-color: transparent; } listview { columns: 1; - lines: 12; + lines: 14; scrollbar: true; background-color: transparent; - padding: 4px; + padding: 6px 4px; fixed-columns: true; + spacing: 2px; } element { - padding: 4px 8px; + padding: 10px 14px; background-color: transparent; - border-radius: 4px; + border-radius: 6px; } element normal.normal { background-color: transparent; - text-color: @text; + text-color: @subtext1; +} + +element alternate.normal { + background-color: transparent; + text-color: @subtext1; } element selected.normal { - background-color: @surface1; - text-color: @mauve; - border: 2px; + background-color: @base; + text-color: @text; + border: 0px 0px 0px 3px; border-color: @mauve; - border-radius: 4px; + border-radius: 6px; } element-icon { - size: 128px; + size: 48px; background-color: transparent; - margin: 0px 4px; + margin: 0px 10px 0px 0px; } element-text { text-color: inherit; background-color: transparent; - margin: 50px 0 0 0; + vertical-align: 0.5; } scrollbar { - width: 4px; + width: 3px; handle-color: @surface2; - handle-width: 4px; - background-color: @surface0; + handle-width: 3px; + background-color: transparent; + margin: 4px 0px 4px 4px; + border-radius: 2px; } diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index f3e5040..3171944 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -63,6 +63,7 @@ export default { items: [ { text: 'Overview', link: '/' }, { text: 'Installation', link: '/installation' }, + { text: 'Launcher Script', link: '/launcher-script' }, { text: 'Usage', link: '/usage' }, { text: 'Mining Workflow', link: '/mining-workflow' }, ], @@ -88,6 +89,9 @@ export default { ], }, ], + search: { + provider: 'local', + }, socialLinks: [{ icon: 'github', link: 'https://github.com/ksyasuda/SubMiner' }], }, }; diff --git a/docs/launcher-script.md b/docs/launcher-script.md new file mode 100644 index 0000000..8232e34 --- /dev/null +++ b/docs/launcher-script.md @@ -0,0 +1,97 @@ +# Launcher Script + +The `subminer` wrapper script is an all-in-one launcher that handles video selection, mpv startup, and overlay management. It's a Bun script distributed alongside the AppImage. + +## Video Picker + +When you run `subminer` without specifying a file, it opens an interactive video picker. By default it uses **fzf** in the terminal; pass `-R` to use **rofi** instead. + +### fzf (default) + +```bash +subminer # pick from current directory +subminer -d ~/Videos # pick from a specific directory +subminer -r -d ~/Anime # recursive search +``` + +fzf shows video files in a fuzzy-searchable list. If `chafa` is installed, you get thumbnail previews in the right pane. Thumbnails are sourced from the freedesktop thumbnail cache first, then generated on the fly with `ffmpegthumbnailer` or `ffmpeg` as fallback. + +| Optional tool | Purpose | +| --------------------- | -------------------------------- | +| `chafa` | Render thumbnails in the terminal | +| `ffmpegthumbnailer` | Generate thumbnails on the fly | + +### rofi + +```bash +subminer -R # rofi picker, current directory +subminer -R -d ~/Videos # rofi picker, specific directory +subminer -R -r -d ~/Anime # rofi picker, recursive +``` + +rofi shows a GUI menu with icon thumbnails when available. SubMiner ships a custom rofi theme that can be installed from the release assets: + +```bash +mkdir -p ~/.local/share/SubMiner/themes +cp /tmp/assets/themes/subminer.rasi ~/.local/share/SubMiner/themes/subminer.rasi +``` + +The theme is auto-detected from these paths (first match wins): + +- `$SUBMINER_ROFI_THEME` environment variable (absolute path) +- `$XDG_DATA_HOME/SubMiner/themes/subminer.rasi` (default: `~/.local/share/SubMiner/themes/subminer.rasi`) +- `/usr/local/share/SubMiner/themes/subminer.rasi` +- `/usr/share/SubMiner/themes/subminer.rasi` +- macOS: `~/Library/Application Support/SubMiner/themes/subminer.rasi` + +Override with the `SUBMINER_ROFI_THEME` environment variable: + +```bash +SUBMINER_ROFI_THEME=/path/to/custom-theme.rasi subminer -R +``` + +## Common Commands + +```bash +subminer video.mkv # play a specific file +subminer --start video.mkv # play + explicitly start overlay +subminer https://youtu.be/... # YouTube playback (requires yt-dlp) +subminer ytsearch:"jp news" # YouTube search +``` + +## Subcommands + +| Subcommand | Purpose | +| ------------------------- | ---------------------------------------------- | +| `subminer jellyfin` / `jf` | Jellyfin workflows (`-d` discovery, `-p` play, `-l` login) | +| `subminer yt` / `youtube` | YouTube shorthand (`-o`, `-m`) | +| `subminer doctor` | Dependency + config + socket diagnostics | +| `subminer config path` | Print active config file path | +| `subminer config show` | Print active config contents | +| `subminer mpv status` | Check mpv socket readiness | +| `subminer mpv socket` | Print active socket path | +| `subminer mpv idle` | Launch detached idle mpv instance | +| `subminer texthooker` | Launch texthooker-only mode | +| `subminer app` | Pass arguments directly to SubMiner binary | + +Use `subminer -h` for command-specific help. + +## Options + +| Flag | Description | +| -------------------- | -------------------------------------------- | +| `-d, --directory` | Video search directory (default: cwd) | +| `-r, --recursive` | Search directories recursively | +| `-R, --rofi` | Use rofi instead of fzf | +| `-S, --start` | Start overlay after mpv launches | +| `-T, --no-texthooker`| Disable texthooker server | +| `-p, --profile` | mpv profile name (default: `subminer`) | +| `-b, --backend` | Force window backend (`hyprland`, `sway`, `x11`) | +| `--log-level` | Logger verbosity (`debug`, `info`, `warn`, `error`) | +| `--dev`, `--debug` | Enable app dev-mode (not tied to log level) | + +## Logging + +- Default log level is `info` +- `--background` mode defaults to `warn` unless `--log-level` is explicitly set +- `--dev` / `--debug` control app behavior, not logging verbosity — use `--log-level` for that diff --git a/docs/mining-workflow.md b/docs/mining-workflow.md index 089eae4..1c528d9 100644 --- a/docs/mining-workflow.md +++ b/docs/mining-workflow.md @@ -86,7 +86,24 @@ This is the most common flow. Yomitan creates a card in Anki, and SubMiner detec Configure which fields to fill in `ankiConnect.fields`. See [Anki Integration](/anki-integration) for details. -### 2. Mine Sentence (Hotkey) +### 2. Manual Update from Clipboard + +If you prefer a hands-on approach (animecards-style), you can copy the current subtitle to the clipboard and then paste it onto the last-added Anki card: + +1. Add a word via Yomitan as usual. +2. Press `Ctrl/Cmd+C` to copy the current subtitle line to the clipboard. + - For multiple lines: press `Ctrl/Cmd+Shift+C`, then a digit `1`–`9` to select how many recent subtitle lines to combine. The combined text is copied to the clipboard. +3. Press `Ctrl/Cmd+V` to update the last-added card with the clipboard contents plus audio, image, and translation — the same fields auto-update would fill. + +This is useful when auto-update polling is disabled or when you want explicit control over which subtitle line gets attached to the card. + +| Shortcut | Action | Config key | +| --------------------------- | ----------------------------------------- | ------------------------------------- | +| `Ctrl/Cmd+C` | Copy current subtitle | `shortcuts.copySubtitle` | +| `Ctrl/Cmd+Shift+C` + digit | Copy multiple recent lines | `shortcuts.copySubtitleMultiple` | +| `Ctrl/Cmd+V` | Update last card from clipboard | `shortcuts.updateLastCardFromClipboard` | + +### 3. Mine Sentence (Hotkey) Create a standalone sentence card without going through Yomitan: @@ -95,7 +112,7 @@ Create a standalone sentence card without going through Yomitan: The sentence card uses the note type configured in `isLapis.sentenceCardModel` and always maps sentence/audio to `Sentence` and `SentenceAudio`. -### 3. Mark as Audio Card +### 4. Mark as Audio Card After adding a word via Yomitan, press the audio card shortcut to overwrite the audio with a longer clip spanning the full subtitle timing. diff --git a/docs/shortcuts.md b/docs/shortcuts.md index 26c91c7..44e5de4 100644 --- a/docs/shortcuts.md +++ b/docs/shortcuts.md @@ -6,11 +6,11 @@ All shortcuts are configurable in `config.jsonc` under `shortcuts` and `keybindi These work system-wide regardless of which window has focus. -| Shortcut | Action | Configurable | -| -------- | ------ | ------------ | -| `Alt+Shift+O` | Toggle visible overlay | `shortcuts.toggleVisibleOverlayGlobal` | +| Shortcut | Action | Configurable | +| ------------- | ------------------------ | ---------------------------------------- | +| `Alt+Shift+O` | Toggle visible overlay | `shortcuts.toggleVisibleOverlayGlobal` | | `Alt+Shift+I` | Toggle invisible overlay | `shortcuts.toggleInvisibleOverlayGlobal` | -| `Alt+Shift+Y` | Open Yomitan settings | Fixed (not configurable) | +| `Alt+Shift+Y` | Open Yomitan settings | Fixed (not configurable) | ::: tip Global shortcuts are registered with the OS. If they conflict with another application, update them in `shortcuts` config and restart SubMiner. @@ -20,15 +20,15 @@ Global shortcuts are registered with the OS. If they conflict with another appli These work when the overlay window has focus. -| Shortcut | Action | Config key | -| -------- | ------ | ---------- | -| `Ctrl/Cmd+S` | Mine current subtitle as sentence card | `shortcuts.mineSentence` | -| `Ctrl/Cmd+Shift+S` | Mine multiple lines (press 1–9 to select count) | `shortcuts.mineSentenceMultiple` | -| `Ctrl/Cmd+C` | Copy current subtitle text | `shortcuts.copySubtitle` | -| `Ctrl/Cmd+Shift+C` | Copy multiple lines (press 1–9 to select count) | `shortcuts.copySubtitleMultiple` | -| `Ctrl/Cmd+V` | Update last Anki card from clipboard text | `shortcuts.updateLastCardFromClipboard` | -| `Ctrl/Cmd+G` | Trigger field grouping (Kiku merge check) | `shortcuts.triggerFieldGrouping` | -| `Ctrl/Cmd+Shift+A` | Mark last card as audio card | `shortcuts.markAudioCard` | +| Shortcut | Action | Config key | +| ------------------ | ----------------------------------------------- | --------------------------------------- | +| `Ctrl/Cmd+S` | Mine current subtitle as sentence card | `shortcuts.mineSentence` | +| `Ctrl/Cmd+Shift+S` | Mine multiple lines (press 1–9 to select count) | `shortcuts.mineSentenceMultiple` | +| `Ctrl/Cmd+C` | Copy current subtitle text | `shortcuts.copySubtitle` | +| `Ctrl/Cmd+Shift+C` | Copy multiple lines (press 1–9 to select count) | `shortcuts.copySubtitleMultiple` | +| `Ctrl/Cmd+V` | Update last Anki card from clipboard text | `shortcuts.updateLastCardFromClipboard` | +| `Ctrl/Cmd+G` | Trigger field grouping (Kiku merge check) | `shortcuts.triggerFieldGrouping` | +| `Ctrl/Cmd+Shift+A` | Mark last card as audio card | `shortcuts.markAudioCard` | The multi-line shortcuts open a digit selector with a 3-second timeout (`shortcuts.multiCopyTimeoutMs`). Press `1`–`9` to select how many recent subtitle lines to combine. @@ -36,74 +36,74 @@ The multi-line shortcuts open a digit selector with a 3-second timeout (`shortcu These control playback and subtitle display. They require overlay window focus. -| Shortcut | Action | -| -------- | ------ | -| `Space` | Toggle mpv pause | -| `ArrowRight` | Seek forward 5 seconds | -| `ArrowLeft` | Seek backward 5 seconds | -| `ArrowUp` | Seek forward 60 seconds | -| `ArrowDown` | Seek backward 60 seconds | -| `Shift+H` | Jump to previous subtitle | -| `Shift+L` | Jump to next subtitle | -| `Ctrl+Shift+H` | Replay current subtitle (play to end, then pause) | -| `Ctrl+Shift+L` | Play next subtitle (jump, play to end, then pause) | -| `Q` | Quit mpv | -| `Ctrl+W` | Quit mpv | -| `Right-click` | Toggle pause (outside subtitle area) | -| `Right-click + drag` | Reposition subtitles (on subtitle area) | -| `Ctrl/Cmd+A` | Append clipboard video path to mpv playlist | +| Shortcut | Action | +| -------------------- | -------------------------------------------------- | +| `Space` | Toggle mpv pause | +| `ArrowRight` | Seek forward 5 seconds | +| `ArrowLeft` | Seek backward 5 seconds | +| `ArrowUp` | Seek forward 60 seconds | +| `ArrowDown` | Seek backward 60 seconds | +| `Shift+H` | Jump to previous subtitle | +| `Shift+L` | Jump to next subtitle | +| `Ctrl+Shift+H` | Replay current subtitle (play to end, then pause) | +| `Ctrl+Shift+L` | Play next subtitle (jump, play to end, then pause) | +| `Q` | Quit mpv | +| `Ctrl+W` | Quit mpv | +| `Right-click` | Toggle pause (outside subtitle area) | +| `Right-click + drag` | Reposition subtitles (on subtitle area) | +| `Ctrl/Cmd+A` | Append clipboard video path to mpv playlist | These keybindings can be overridden or disabled via the `keybindings` config array. ## Subtitle & Feature Shortcuts -| Shortcut | Action | Config key | -| -------- | ------ | ---------- | +| Shortcut | Action | Config key | +| ------------------ | -------------------------------------------------------- | ------------------------------ | | `Ctrl/Cmd+Shift+V` | Cycle secondary subtitle mode (hidden → visible → hover) | `shortcuts.toggleSecondarySub` | -| `Ctrl/Cmd+Shift+O` | Open runtime options palette | `shortcuts.openRuntimeOptions` | -| `Ctrl+Shift+J` | Open Jimaku subtitle search modal | `shortcuts.openJimaku` | -| `Ctrl+Alt+S` | Open subtitle sync (subsync) modal | `shortcuts.triggerSubsync` | +| `Ctrl/Cmd+Shift+O` | Open runtime options palette | `shortcuts.openRuntimeOptions` | +| `Ctrl+Shift+J` | Open Jimaku subtitle search modal | `shortcuts.openJimaku` | +| `Ctrl+Alt+S` | Open subtitle sync (subsync) modal | `shortcuts.triggerSubsync` | ## Invisible Subtitle Position Edit Mode Enter edit mode to fine-tune invisible overlay alignment with mpv's native subtitles. -| Shortcut | Action | -| -------- | ------ | -| `Ctrl/Cmd+Shift+P` | Toggle position edit mode | -| `ArrowKeys` or `hjkl` | Nudge position by 1 px | -| `Shift+Arrow` | Nudge position by 4 px | -| `Enter` or `Ctrl+S` | Save position and exit edit mode | -| `Esc` | Cancel and discard changes | +| Shortcut | Action | +| --------------------- | -------------------------------- | +| `Ctrl/Cmd+Shift+P` | Toggle position edit mode | +| `ArrowKeys` or `hjkl` | Nudge position by 1 px | +| `Shift+Arrow` | Nudge position by 4 px | +| `Enter` or `Ctrl+S` | Save position and exit edit mode | +| `Esc` | Cancel and discard changes | ## MPV Plugin Chords When the mpv plugin is installed, all commands use a `y` chord prefix — press `y`, then the second key within 1 second. -| Chord | Action | -| ----- | ------ | -| `y-y` | Open SubMiner menu (OSD) | -| `y-s` | Start overlay | -| `y-S` | Stop overlay | -| `y-t` | Toggle visible overlay | -| `y-i` | Toggle invisible overlay | -| `y-I` | Show invisible overlay | -| `y-u` | Hide invisible overlay | -| `y-o` | Open Yomitan settings | -| `y-r` | Restart overlay | -| `y-c` | Check overlay status | +| Chord | Action | +| ----- | --------------------------------------- | +| `y-y` | Open SubMiner menu (OSD) | +| `y-s` | Start overlay | +| `y-S` | Stop overlay | +| `y-t` | Toggle visible overlay | +| `y-i` | Toggle invisible overlay | +| `y-I` | Show invisible overlay | +| `y-u` | Hide invisible overlay | +| `y-o` | Open Yomitan settings | +| `y-r` | Restart overlay | +| `y-c` | Check overlay status | | `y-d` | Toggle overlay DevTools (dev/debug use) | ## Drag-and-Drop -| Gesture | Action | -| ------- | ------ | -| Drop file(s) onto overlay | Replace current mpv playlist with dropped files | -| `Shift` + drop file(s) | Append all dropped files to current mpv playlist | +| Gesture | Action | +| ------------------------- | ------------------------------------------------ | +| Drop file(s) onto overlay | Replace current mpv playlist with dropped files | +| `Shift` + drop file(s) | Append all dropped files to current mpv playlist | ## Customizing Shortcuts -All `shortcuts.*` keys accept [Electron accelerator strings](https://www.electronjs.org/docs/latest/api/accelerator), for example `"CommandOrControl+Shift+M"`. Use `null` to disable a shortcut. +All `shortcuts.*` keys accept [Electron accelerator strings](https://www.electronjs.org/docs/latest/tutorial/keyboard-shortcuts), for example `"CommandOrControl+Shift+M"`. Use `null` to disable a shortcut. ```jsonc { @@ -112,8 +112,8 @@ All `shortcuts.*` keys accept [Electron accelerator strings](https://www.electro "copySubtitle": "CommandOrControl+C", "toggleVisibleOverlayGlobal": "Alt+Shift+O", "toggleInvisibleOverlayGlobal": "Alt+Shift+I", - "openJimaku": null // disabled - } + "openJimaku": null, // disabled + }, } ``` @@ -124,8 +124,8 @@ The `keybindings` array overrides or extends the overlay's built-in key handling "keybindings": [ { "key": "f", "command": ["cycle", "fullscreen"] }, { "key": "m", "command": ["cycle", "mute"] }, - { "key": "Space", "command": null } // disable default Space → pause - ] + { "key": "Space", "command": null }, // disable default Space → pause + ], } ``` diff --git a/docs/subagents/agents/codex-release-mpv-plugin-20260220T035757Z-d4yf.md b/docs/subagents/agents/codex-release-mpv-plugin-20260220T035757Z-d4yf.md new file mode 100644 index 0000000..f84a09a --- /dev/null +++ b/docs/subagents/agents/codex-release-mpv-plugin-20260220T035757Z-d4yf.md @@ -0,0 +1,24 @@ +# Agent Log — codex-release-mpv-plugin-20260220T035757Z-d4yf + +- alias: `codex-release-mpv-plugin` +- mission: `Package optional release assets bundle (mpv plugin + rofi theme), move theme to assets/themes, update install/docs` +- status: `completed` +- started_utc: `2026-02-20T03:57:57Z` +- planned_files: `.github/workflows/release.yml`, `Makefile`, `launcher/picker.ts`, `README.md`, `docs/installation.md`, `docs/mpv-plugin.md`, `assets/themes/subminer.rasi`, `docs/subagents/INDEX.md`, `docs/subagents/agents/codex-release-mpv-plugin-20260220T035757Z-d4yf.md` +- assumptions: + - `Backlog.md` not configured in repo root (no backlog ticket linkage required). + - change limited to release asset generation/upload; no app packaging behavior changes. +- notes: + - [2026-02-20T03:58:30Z] context loaded; proceeding with workflow-only patch. + - [2026-02-20T03:58:36Z] edit: added `Package mpv plugin` step to release job; emits `release/subminer-mpv-plugin-.tar.gz`. + - [2026-02-20T03:58:36Z] edit: checksum input now includes `release/*.tar.gz`; release upload globs now include `release/*.tar.gz`. + - [2026-02-20T03:58:36Z] edit: release body now includes optional mpv plugin install steps. + - [2026-02-20T03:58:36Z] validation: reviewed workflow diff only; no runtime tests executed (CI-config change). + - [2026-02-20T03:58:36Z] handoff: ready to merge; preserves existing AppImage/DMG/ZIP flow. + - [2026-02-20T04:00:49Z] scope expanded per user request: include default rofi theme, choose `assets/themes` location, update CI/install/docs/readme. + - [2026-02-20T04:00:49Z] edit: moved `subminer.rasi` -> `assets/themes/subminer.rasi`; patched Makefile theme install source. + - [2026-02-20T04:00:49Z] edit: patched launcher theme discovery to include `/assets/themes/subminer.rasi` before legacy fallback. + - [2026-02-20T04:00:49Z] edit: release bundle renamed to `subminer-assets-.tar.gz` including plugin + theme; release notes updated. + - [2026-02-20T04:00:49Z] edit: docs/readme install snippets updated for new assets bundle path. + - [2026-02-20T04:02:26Z] validation: `bun run build` pass. + - [2026-02-20T04:02:26Z] handoff: release/install/docs now align on `assets/themes/subminer.rasi` + `subminer-assets-.tar.gz`. diff --git a/launcher/picker.ts b/launcher/picker.ts index c26046d..7c00914 100644 --- a/launcher/picker.ts +++ b/launcher/picker.ts @@ -366,6 +366,8 @@ export function findRofiTheme(scriptPath: string): string | null { candidates.push(path.join('/usr/share/SubMiner/themes', ROFI_THEME_FILE)); } + candidates.push(path.join(scriptDir, 'assets', 'themes', ROFI_THEME_FILE)); + candidates.push(path.join(scriptDir, 'themes', ROFI_THEME_FILE)); candidates.push(path.join(scriptDir, ROFI_THEME_FILE)); for (const candidate of candidates) {