mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-28 00:55:16 -07:00
Compare commits
32 Commits
7e86c4ea3d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| eed0a6a243 | |||
| d33009d4a3 | |||
| 8d0535f3ca | |||
|
75f9b8a803
|
|||
|
c30cce0a14
|
|||
| 3e6591e390 | |||
| f033f87329 | |||
|
29cb8c7fb4
|
|||
| 1dcfed86ab | |||
| efe50ed1e4 | |||
| 5b44981688 | |||
|
2add95d541
|
|||
|
f62fff2585
|
|||
| 11c196821d | |||
|
43ebc7d371
|
|||
| 639e331f24 | |||
|
78be72e32f
|
|||
| 3932e53ced | |||
| 097b619d71 | |||
|
f7abcedd75
|
|||
| 807c0ff3db | |||
| 7e6f9672cf | |||
|
9fe13601fb
|
|||
| 920cbab1bc | |||
| 17d97f0b7e | |||
|
10463e7348
|
|||
|
e9abbd5f05
|
|||
|
d6ff50455a
|
|||
| b1bdeabca8 | |||
| da3c971ee6 | |||
|
c02edc90cc
|
|||
|
4d1a20d69b
|
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: jellyfin
|
||||
|
||||
- Fixed the Jellyfin setup popup login path on Windows by using an IPC bridge, showing immediate login progress, and timing out unreachable server login attempts with an inline error.
|
||||
@@ -34,11 +34,13 @@ Rules:
|
||||
How fragments turn into a release:
|
||||
|
||||
- At release time, `bun run changelog:build` (and `bun run changelog:prerelease-notes`) pipes every pending fragment through `claude -p` to merge related items, drop noise, and rewrite into a clean user-facing release body. Write fragments as raw, informative notes — don't worry about polished prose, deduping across PRs, or line-by-line phrasing. The polish step handles all of that.
|
||||
- The polish step treats pending fragments as the final release outcome, not prerelease history. If a feature is added and then renamed or fixed before the stable cut, ship the final feature bullet instead of separate prerelease-only breaking/fix entries.
|
||||
- `internal` fragments stay in `CHANGELOG.md` (inside a collapsed `<details>` block) but are dropped from the GitHub release notes entirely.
|
||||
- The polished `CHANGELOG.md` and `release/release-notes.md` are committed and reviewed before tagging — edit the Markdown by hand if Claude misses something.
|
||||
|
||||
Prerelease notes:
|
||||
|
||||
- prerelease tags like `v0.11.3-beta.1` and `v0.11.3-rc.1` reuse the current pending fragments to generate `release/prerelease-notes.md`
|
||||
- existing prerelease notes are a reviewed baseline; later prerelease runs should replace stale beta/RC wording with the current outcome instead of appending fix churn
|
||||
- prerelease note generation does not consume fragments and does not update `CHANGELOG.md` or `docs-site/changelog.md`
|
||||
- the final stable release is the point where `bun run changelog:build` consumes fragments into the stable changelog and release notes
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
type: fixed
|
||||
area: anilist
|
||||
|
||||
- Used fresh mpv time-position, duration, and subtitle timing events for AniList post-watch threshold checks so progress updates still fire when playback reaches or skips past the watched threshold.
|
||||
- Prefer season-specific AniList search results for multi-season files before falling back to the base title, and show a clear message when the matched season is not in Planning or Watching instead of silently queueing an impossible update.
|
||||
- Prevent repeated missing-token checks from rapidly exhausting AniList retry attempts or duplicating dead-letter entries for the same episode.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- Settings: Changed the AniSkip button key setting to use click-to-learn key capture instead of raw text entry.
|
||||
@@ -0,0 +1,10 @@
|
||||
type: fixed
|
||||
area: anki
|
||||
|
||||
- Made sentence-audio padding opt-in by default, and kept animated AVIF freeze-frame duration aligned to the word audio length without double-counting sentence audio padding.
|
||||
- Kept multi-line sentence mining aligned when repeated subtitle text appears in the selected history range.
|
||||
- Fixed Kiku duplicate-card detection so local duplicate sentence cards trigger the manual modal or auto merge, modal-open acknowledgement races no longer cancel the flow, and merged fields follow Kiku's group ordering, sentence-audio, furigana, and tag semantics.
|
||||
- Fixed manual clipboard card updates from YouTube playback so generated audio and images use mpv's resolved stream URLs instead of the YouTube page URL.
|
||||
- Sentence cards now refresh the current secondary subtitle before saving, so the translation field uses the loaded subtitle instead of repeating the primary text.
|
||||
- Fixed immediate known-word cache append when no default Anki mining deck is configured but multiple known-word deck field mappings are present.
|
||||
- Added an AnkiConnect deck dropdown at the top of Mining & Anki settings that auto-fills from Yomitan's current mining deck when available.
|
||||
@@ -1,4 +1,4 @@
|
||||
type: added
|
||||
area: updater
|
||||
|
||||
- Added tray and `subminer -u` update checks for SubMiner releases, including app update prompts, launcher updates, Linux rofi theme updates, checksum verification, configurable update notifications, and an opt-in prerelease update channel for beta/RC testing.
|
||||
- Added tray and `subminer -u` update checks for SubMiner releases, including app update prompts, launcher and Linux rofi theme updates, checksum verification, configurable update notifications, and an opt-in prerelease channel. Set `updates.channel` to `"prerelease"` to receive beta/RC builds.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: launcher
|
||||
|
||||
- Reused an already-running background SubMiner app for launcher-opened videos, closed launcher-owned tray apps after playback ends, and reapplied preferred subtitles for warm launches.
|
||||
@@ -0,0 +1,8 @@
|
||||
type: fixed
|
||||
area: character-dictionary
|
||||
|
||||
- Reused cached character-dictionary media matches so loading a title with an existing snapshot no longer sends another AniList search request.
|
||||
- Block the character dictionary manager when annotations are disabled, with a notice through the configured OSD/system notification surfaces.
|
||||
- Added surname honorific matches for Japanese localized character aliases embedded in AniList alternative names (e.g. Korean-source characters with Japanese names in parentheses), and refresh cached snapshots so those aliases are regenerated.
|
||||
- Use `subtitleStyle.nameMatchEnabled` as the only switch for character-dictionary sync/builds, hiding the legacy `anilist.characterDictionary.enabled` option.
|
||||
- Forward character dictionary manager session-action keybindings to the mpv plugin.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: character-dictionary
|
||||
|
||||
- Reused cached character-dictionary media matches so loading a title with an existing snapshot no longer sends another AniList search request.
|
||||
@@ -0,0 +1,6 @@
|
||||
type: changed
|
||||
area: character-dictionary
|
||||
|
||||
- Character dictionary entries are now scoped to the current AniList media for name matching and inline portraits, and generate Japanese name aliases only so raw romanized/English aliases no longer surface as separate results.
|
||||
- Added a `Ctrl/Cmd+D` manager modal to remove, reorder, or override loaded dictionary entries.
|
||||
- The in-app AniList selector now waits for an explicit title search, with the search box prefilled from the current filename guess so you can edit it before choosing an override.
|
||||
@@ -0,0 +1,7 @@
|
||||
type: added
|
||||
area: subtitles
|
||||
|
||||
- Added optional inline AniList portraits for character-name subtitle matches, including automatic refresh of cached character dictionary snapshots that do not contain portrait data.
|
||||
- Scoped manual AniList overrides by parent media directory, so separate season folders can keep separate character dictionary selections.
|
||||
- Fixed large character dictionary imports by serving the merged ZIP through a local URL when supported, with a base64 fallback for older bundled Yomitan builds.
|
||||
- Allowed subtitle overlay data image sources so inline character portraits render instead of showing a broken image icon.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: config
|
||||
|
||||
- Updated the generated example config to use the same CSS declaration paths written by the Settings window for subtitle and sidebar appearance.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: config
|
||||
|
||||
- Preserved user config files during legacy config compatibility handling.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- Reorganized the Settings window into clearer Appearance, Behavior, Anki, input, and integration sections with learned keybinding controls and AnkiConnect-backed deck, field, and note-type pickers.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: changed
|
||||
area: settings
|
||||
|
||||
- Simplified configuration option rows by hiding raw config paths and placing the live/restart status beside each option title.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: config
|
||||
|
||||
- Fixed Settings window search so it searches across all categories, narrows on multi-word terms, hides settings owned by richer editors, and no longer shows the Open File button.
|
||||
@@ -1,8 +0,0 @@
|
||||
type: added
|
||||
area: config
|
||||
|
||||
- Added a dedicated Settings window with launcher entry points via `subminer --settings` and `subminer settings`.
|
||||
- Fixed the Settings window preload so launcher-opened windows can initialize even when Electron sandboxing is active.
|
||||
- Kept settings-window startup lightweight by skipping AniList token refresh and automatic update polling.
|
||||
- Marked safe live config options in the Settings window and expanded hot reload for stats keys, logging level, Jimaku, Subsync, YouTube language defaults, Anki media/sentence/misc field mappings, sentence card model, and selected Anki annotation/runtime options.
|
||||
- Hid AI and translation fields from the Settings window while keeping them supported in config files.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: docs
|
||||
area: docs
|
||||
|
||||
- Published stable docs at the site root with current development docs under `/main/`.
|
||||
@@ -0,0 +1,6 @@
|
||||
type: docs
|
||||
area: docs
|
||||
|
||||
- Published stable docs at the site root with current development docs under `/main/`, and fixed versioned docs navigation so archived pages keep local links under the selected version, the version switcher no longer nests paths incorrectly, local dev version routes serve warmed archive files, and internal README files no longer break archived builds.
|
||||
- Documented all previously undocumented config options, including `subtitleStyle.primaryDefaultMode`, `stats.markWatchedKey`, `immersionTracking.lifetimeSummaries.*`, and all seven `mpv.*` launcher options.
|
||||
- Added a Playback Startup Flow diagram and a Runtime Sockets section/diagram to the architecture docs, with cross-reference pointers in the MPV Plugin and Troubleshooting pages.
|
||||
@@ -1,5 +0,0 @@
|
||||
type: added
|
||||
area: setup
|
||||
|
||||
- Added optional first-run setup controls to install Bun and the `subminer` command-line launcher on Linux, macOS, and Windows.
|
||||
- Added a Windows `subminer.cmd` user PATH shim so users can type `subminer` without adding `SubMiner.exe` to PATH.
|
||||
@@ -1,6 +0,0 @@
|
||||
type: fixed
|
||||
area: anilist
|
||||
|
||||
- Used fresh mpv time-position, duration, and subtitle timing events for AniList post-watch threshold checks so progress updates still fire when playback reaches or skips past the watched threshold.
|
||||
- Prefer season-specific AniList search results for multi-season files before falling back to the base title.
|
||||
- Show a clear AniList message when the matched season is not in Planning or Watching instead of silently queueing an impossible progress update.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Primed the first startup subtitle before autoplay resumes so the overlay can render text before video playback begins.
|
||||
@@ -1,5 +0,0 @@
|
||||
type: fixed
|
||||
area: launcher
|
||||
|
||||
- Kept launcher-opened videos paused when attaching to an already-running background app until subtitle priming and tokenization readiness complete.
|
||||
- Moved mpv plugin subtitle auto-selection to pre-load so launch-time subtitle choices are not reset after the video opens.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: subtitles
|
||||
|
||||
- Kept frequency highlighting for determiner-led noun compounds like `その場` while still filtering standalone determiners.
|
||||
@@ -0,0 +1,4 @@
|
||||
type: fixed
|
||||
area: integrations
|
||||
|
||||
- Prevented Discord Rich Presence from falling back to Jellyfin stream URLs, and primed Jellyfin playback titles before loading tokenized streams so presence shows the show/episode title
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Refreshed Linux overlay placement after leaving mpv fullscreen so Hyprland keeps the visible overlay aligned to the player.
|
||||
@@ -1,5 +0,0 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Kept the Hyprland visible overlay stacked above mpv after mpv receives focus from clicks or overlay movement.
|
||||
- Suspended the visible overlay while the in-player stats window is open, then restored it mouse-passive after stats closes.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- Reorganized each known-words deck row in the Settings window into a card with the deck name on its own header line so longer deck names stay readable instead of being truncated.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: launcher
|
||||
|
||||
- Suppressed Electron macOS menu diagnostics from `subminer settings` launcher output.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: shortcuts
|
||||
|
||||
- Disabled native mpv menu shortcuts during managed macOS playback so configured SubMiner shortcuts also work while mpv has focus.
|
||||
@@ -1,10 +0,0 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Hid the macOS visible overlay when mpv is no longer the foreground target so other apps and Spaces are not covered by SubMiner subtitles.
|
||||
- Kept the macOS overlay layered above active mpv while stats mouse passthrough is enabled, and treated the frontmost mpv app as the focus signal.
|
||||
- Opened the stats overlay inactive on macOS so it appears over fullscreen mpv instead of switching back to SubMiner's original desktop.
|
||||
- Preserved the active mpv focus state through transient macOS helper misses so subtitles do not flicker while mpv remains foreground.
|
||||
- Kept fullscreen macOS overlays stable when mpv remains frontmost but window geometry temporarily disappears from the macOS window APIs.
|
||||
- Released the macOS overlay when the helper reports mpv is no longer foreground so other apps are no longer covered.
|
||||
- Reduced macOS window-tracker background work by preferring the compiled helper and slowing polls while mpv is stably focused.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Fixed macOS overlay tracking so transient mpv window misses no longer hide the overlay; minimizing mpv still hides it.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Fixed macOS overlay passthrough so mpv controls remain clickable before hovering subtitle bars.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: playback
|
||||
|
||||
- Fixed managed mpv startup so launcher-owned videos quit SubMiner when playback ends, background/tray sessions stay alive, and pause-until-ready waits for the overlay and tokenization readiness before playback resumes.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Fixed subtitle sync modal opens so macOS no longer flashes and hides the first modal attempt or leaves stale modal state after syncing.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: docs
|
||||
|
||||
- Fixed versioned docs navigation so archived pages keep local links under the selected version, the version switcher no longer nests targets under the current archive path, local dev version routes serve warmed archive files instead of redirecting to production or falling through to VitePress 404s, and internal README files do not break archived builds.
|
||||
@@ -0,0 +1,6 @@
|
||||
type: fixed
|
||||
area: jellyfin
|
||||
|
||||
- Fixed Jellyfin discovery playback: the active item is no longer reloaded on startup, paused mpv is no longer misreported as playing, startup unpause no longer repeats after a manual pause or `y-t` toggle, duplicate ready signals no longer re-show the overlay, delayed Japanese subtitle selection is handled correctly, later-loading foreign tracks no longer steal the active Japanese track, and long-lived sidebar ffmpeg extractors no longer run against stream URLs.
|
||||
- Fixed discovery resume when a remote play command sends `StartPositionTicks: 0` despite saved progress on the item.
|
||||
- Kept Jellyfin picker library discovery working when the app log level is above info.
|
||||
@@ -0,0 +1,8 @@
|
||||
type: fixed
|
||||
area: jellyfin
|
||||
|
||||
- Keep the discovery tray checkbox in sync on Linux after tray, CLI, or startup remote-session changes, and restart stale discovery sessions when the server no longer lists the SubMiner cast target.
|
||||
- Fixed remote controller visibility and progress sync for mpv/SubMiner seek jumps, stopped sessions, startup path changes, and Linux websocket reconnect windows.
|
||||
- Kept Play and Resume distinct: Play starts from the beginning while Resume starts at the saved position, and final progress reports reuse SubMiner's last known position when mpv resets during stop.
|
||||
- Derived cast device identity from the OS hostname and always report the client as SubMiner, ignoring legacy configurable identity fields so multiple installs no longer share a remote-session identity.
|
||||
- Fixed the Windows setup login flow with an IPC bridge, immediate progress feedback, and a timeout with an inline error for unreachable servers.
|
||||
@@ -0,0 +1,6 @@
|
||||
type: fixed
|
||||
area: jellyfin
|
||||
|
||||
- Show the visible subtitle overlay automatically during Jellyfin playback so `subtitleStyle` appearance applies, and inject the bundled mpv plugin when SubMiner auto-launches mpv so mpv-side keybindings work without overlay focus.
|
||||
- Made the `y-t` overlay toggle reliable and sticky across stream redirects that change mpv's path, re-arming managed subtitle defaults on redirect so Japanese primary subtitles load, collapsing duplicate toggle events on Hyprland, and keeping passive Linux/Hyprland overlay shows from stealing keyboard focus from mpv.
|
||||
- Improved subtitle timing by preferring default embedded streams over external sidecars, stripping Jellyfin's server-selected stream from playback URLs, suppressing mpv auto-selection while SubMiner stages managed tracks, correcting clear Japanese-vs-English cue offsets, and restoring per-stream subtitle delay shifts. Track selection tolerates transient `track-list` read failures and numeric string track IDs on Linux.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- Config: Moved known-word and N+1 annotation colors to `subtitleStyle.knownWordColor` and `subtitleStyle.nPlusOneColor`; legacy Anki color keys are still accepted with warnings.
|
||||
@@ -0,0 +1,8 @@
|
||||
type: fixed
|
||||
area: launcher
|
||||
|
||||
- Launcher-opened videos reuse an already-running background SubMiner instance, reapply preferred subtitles on warm launches, and close launcher-owned tray apps after playback ends.
|
||||
- Videos stay paused when attaching to a running background app until subtitle priming and tokenization readiness complete, with mpv plugin subtitle auto-selection moved to pre-load so launch-time choices are not reset.
|
||||
- `subminer settings` on macOS no longer emits Electron menu diagnostics and exits cleanly when the window is closed.
|
||||
- `subminer app` on Linux returns control to the terminal immediately, and Linux first-run launcher installs build with a valid Bun shebang.
|
||||
- `subminer app --setup` opens the setup flow when SubMiner is already running in the background.
|
||||
@@ -0,0 +1,6 @@
|
||||
type: added
|
||||
area: launcher
|
||||
|
||||
- Added `subminer --version` / `subminer -v` to print the installed app version.
|
||||
- Added `mpv.profile` config and Settings support for passing an mpv profile to SubMiner-managed mpv launches.
|
||||
- Made bundled mpv plugin startup options configurable from SubMiner config.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: added
|
||||
area: launcher
|
||||
|
||||
- Added `subminer --version` and `subminer -v` to print the installed SubMiner app version.
|
||||
@@ -1,5 +0,0 @@
|
||||
type: fixed
|
||||
area: updater
|
||||
|
||||
- Made Linux `subminer -u` perform release updates from the launcher, independent of any running tray app instance, while reporting `up to date` without downloading assets when the latest release is not newer.
|
||||
- Limited support asset updates to the Linux rofi theme.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: launcher
|
||||
|
||||
- Fixed Linux first-run launcher installs by building the packaged launcher with a valid Bun shebang.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: updater
|
||||
|
||||
- Fixed Linux automatic update checks to avoid Electron networking, preventing native Electron network-service crashes during video startup.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: updater
|
||||
|
||||
- Stopped Linux tray update checks from invoking the native Electron updater, using GitHub release metadata/assets instead so checks do not crash the tray app.
|
||||
@@ -0,0 +1,4 @@
|
||||
type: added
|
||||
area: logs
|
||||
|
||||
- Add sanitized log ZIP exports from the tray menu and `subminer logs -e`, with home-directory usernames redacted from exported log contents.
|
||||
@@ -0,0 +1,7 @@
|
||||
type: fixed
|
||||
area: logging
|
||||
|
||||
- Forward SubMiner `logging.level` into launcher-started and Windows shortcut-started mpv sessions, covering mpv log verbosity, plugin script logging, and plugin-launched app logging.
|
||||
- Added numeric `logging.rotation` (default 7 days of retained daily app, launcher, and mpv logs) and `logging.files` toggles per component, with mpv logs disabled by default unless explicitly enabled for debugging.
|
||||
- Added Windows mpv launch, IPC socket, subtitle track, and Yomitan/dictionary diagnostics, including expected/active IPC socket values when plugin auto-start skips on a socket mismatch.
|
||||
- Stop repeated mpv IPC socket warning spam while the app waits in the background for mpv to recreate the socket.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: launcher
|
||||
|
||||
- macOS `subminer settings` launches now exit cleanly after the settings window is closed, returning control to the terminal without requiring Ctrl+C.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: setup
|
||||
|
||||
- First-run setup now recognizes installed macOS launchers in Homebrew or user PATH dirs, while manual setup installs avoid Homebrew-owned directories.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: updater
|
||||
|
||||
- Fixed tray update checks for builds that cannot install native app updates, showing a manual install message instead of a restart prompt that cannot apply the update.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: updater
|
||||
|
||||
- macOS update dialogs triggered by `subminer -u` now reliably appear in the foreground. SubMiner now shows the dock icon and activates itself via `osascript` (LaunchServices) before opening the modal alert; `app.focus({ steal: true })` alone was unreliable when SubMiner was reached through single-instance forwarding from the CLI-spawned child, leaving the dialog stranded behind other apps with a bouncing dock icon.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: updater
|
||||
|
||||
- Bring macOS update dialogs to the front when `subminer --update` is run from the launcher.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: updater
|
||||
|
||||
- Routed macOS supplemental GitHub release lookups through `/usr/bin/curl` instead of Electron `net.fetch`, eliminating the last Electron-networking path from background update checks and avoiding the network-service crashes seen in earlier prereleases.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: build
|
||||
|
||||
- Fixed one-shot `make clean build install` flows so install picks up the AppImage built earlier in the same make invocation.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: added
|
||||
area: launcher
|
||||
|
||||
- Managed bundled mpv plugin startup options from SubMiner config.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: added
|
||||
area: launcher
|
||||
|
||||
- Added `mpv.profile` config and settings support for passing an mpv profile to SubMiner-managed mpv launches.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Wired configured session shortcuts, including `stats.markWatchedKey`, through mpv so custom add/remove changes work while mpv has focus.
|
||||
@@ -1,6 +0,0 @@
|
||||
type: fixed
|
||||
area: updates
|
||||
|
||||
- Restored the standard macOS `electron-updater`/Squirrel update path and routed supplemental GitHub updater requests through Electron networking instead of Node fetch.
|
||||
- macOS update checks now skip local build-output apps outside Applications before touching Squirrel, and macOS tray checks no longer perform the supplemental GitHub asset lookup.
|
||||
- macOS `electron-updater` metadata and full ZIP downloads now use `/usr/bin/curl` under the hood to avoid the Electron network crash seen during tray update checks while preserving Squirrel installation.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: config
|
||||
|
||||
- Defaulted the note-fields note type picker to the configured Anki deck's note type when available, then exact `Kiku`, then exact `Lapis`, otherwise leaving it blank for manual selection.
|
||||
@@ -0,0 +1,5 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- `ankiConnect.nPlusOne.enabled` is no longer implicitly set to `true` when known-word highlighting is enabled; existing configs that already had N+1 highlighting keep it, but new configs leave it disabled unless `ankiConnect.nPlusOne.enabled` is set explicitly.
|
||||
- Updated known-word cache docs and examples to recommend expression/word fields and removed legacy-option references from user-facing config docs.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- Config: Preserved N+1 subtitle highlighting for existing configs that already enabled known-word highlighting, while keeping N+1 disabled by default for new configs unless `ankiConnect.nPlusOne.enabled` is set.
|
||||
@@ -0,0 +1,8 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Primed the first startup subtitle before autoplay resumes so the overlay renders text before video playback begins.
|
||||
- Kept the visible overlay and subtitle stream alive after restarting SubMiner from the mpv `y-r` shortcut, with correct Linux bounds reapplication and user-paused playback preserved through readiness gates.
|
||||
- Fixed managed mpv startup so launcher-owned videos quit SubMiner when playback ends while background/tray sessions stay alive, with pause-until-ready waiting for overlay and tokenization readiness.
|
||||
- Fixed the subtitle sync modal on macOS so it no longer flashes and hides on the first attempt or leaves stale state after syncing.
|
||||
- Fixed Windows managed mpv launches from a background instance so the warm app receives the start command, retargets the new mpv socket, binds to the player window, and receives startup overlay options.
|
||||
@@ -0,0 +1,7 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Refreshed overlay placement after leaving mpv fullscreen so the visible overlay stays aligned to the player on Hyprland.
|
||||
- Kept the visible overlay stacked above mpv after mpv regains focus from clicks or overlay movement, and suspended it while the in-player stats window is open, restoring it mouse-passive afterward.
|
||||
- Promoted SubMiner and Yomitan settings windows above the subtitle overlay on Hyprland instead of opening behind it, without hiding subtitles.
|
||||
- Hid the visible overlay as soon as the character dictionary modal opens, including while AniList lookup is loading or returns no results.
|
||||
@@ -0,0 +1,7 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Hid the macOS visible overlay when mpv loses focus, is minimized, or is no longer the foreground target so other apps and Spaces are not covered, treating the frontmost mpv app as the focus signal.
|
||||
- Kept the overlay stable through transient window-tracking misses, when mpv remains frontmost but window geometry temporarily disappears from macOS APIs, and when clicking from the overlay back into mpv.
|
||||
- Kept the overlay correctly layered during stats mouse passthrough, opened the stats overlay inactive so it appears over fullscreen mpv without switching Spaces, and fixed passthrough so mpv controls stay clickable before hovering a subtitle bar.
|
||||
- Reduced window-tracker background work by preferring the compiled helper and slowing polls while mpv is stably focused.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Kept the visible overlay and subtitle stream alive after restarting SubMiner from the mpv `y-r` shortcut by transporting Linux AppImage control args safely, restoring mpv subtitle visibility during shutdown, snapshotting subtitles before overlay suppression resumes, reapplying Linux overlay bounds after the restarted window maps, allowing Hyprland to resize the visible overlay window, and preserving user-paused playback while readiness gates clear.
|
||||
@@ -0,0 +1,6 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Kept playback paused for Yomitan lookup popups opened from the subtitle sidebar when popup auto-pause is enabled.
|
||||
- Fixed Yomitan popups not opening when playback/overlay startup races the Yomitan extension load.
|
||||
- Fixed subtitle sidebar mining so Yomitan-enriched cards use audio and images from the clicked sidebar line instead of the current primary subtitle line.
|
||||
@@ -0,0 +1,5 @@
|
||||
type: fixed
|
||||
area: release
|
||||
|
||||
- Fixed macOS packaging so the compiled mpv window helper is built into `dist/scripts` and bundled, preventing the overlay from falling back to slow Swift source startup, and removed a stale Windows helper resource entry that produced harmless missing-file warnings.
|
||||
- Fixed one-shot `make clean build install` flows so install picks up the AppImage built earlier in the same make invocation.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: changed
|
||||
area: release
|
||||
|
||||
- Prerelease note generation now reuses existing reviewed prerelease notes and asks Claude to merge only new fragment material, while `make clean` preserves `release/prerelease-notes.md`.
|
||||
@@ -0,0 +1,4 @@
|
||||
type: added
|
||||
area: config
|
||||
|
||||
- Added `subtitleStyle.primaryVisibleOnYomitanPopup` to keep hover-mode primary subtitles visible while a Yomitan popup is open.
|
||||
@@ -0,0 +1,5 @@
|
||||
type: internal
|
||||
area: release
|
||||
|
||||
- Release-note polishing treats pending fragments and reviewed prerelease notes as a cumulative final outcome, collapsing prerelease-only fixes or breakages into the final user-facing change.
|
||||
- Prerelease note generation reuses existing reviewed notes and merges only new fragment material, and `make clean` preserves `release/prerelease-notes.md`.
|
||||
@@ -1,7 +0,0 @@
|
||||
type: changed
|
||||
area: launcher
|
||||
breaking: true
|
||||
|
||||
- Renamed the SubMiner Configuration window to the Settings window across the UI, tray menu, docs, and CLI verbiage.
|
||||
- Replaced the `--config` flag and `subminer config` (no action) entry points with `--settings` and `subminer settings`. The `subminer config` subcommand now only accepts `path` or `show`.
|
||||
- Removed the `--settings` alias that previously opened the bundled Yomitan settings popup. Use `--yomitan` to open Yomitan settings.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- Settings: reorganized playback, shortcut, WebSocket, tracking, Jellyfin, character dictionary, and Discord presence controls in the settings modal.
|
||||
@@ -0,0 +1,8 @@
|
||||
type: added
|
||||
area: config
|
||||
|
||||
- Added a dedicated Settings window via `subminer --settings` or `subminer settings`, organized into Appearance, Behavior, Anki, Input, and Integration sections with click-to-learn keybinding controls (including the AniSkip button key) and AnkiConnect-backed deck, field, and note-type pickers.
|
||||
- Expanded live reload so Settings saves apply immediately for stats keys, logging level, Jimaku, Subsync, YouTube language defaults, Anki field mappings, sentence card model, and selected annotation/runtime options.
|
||||
- Settings search works across all categories, narrows on multi-word terms, and hides settings owned by richer editors.
|
||||
- The note-fields note type picker defaults to the configured Anki deck's note type, then exact `Kiku`, then exact `Lapis`, leaving it blank for manual selection otherwise.
|
||||
- AI and translation settings remain config-file only.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: launcher
|
||||
|
||||
- Fixed `subminer app --setup` so it opens the setup flow when SubMiner is already running in the background.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: setup
|
||||
|
||||
- Quit standalone setup app launches after first-run setup finishes, returning the terminal instead of leaving the app process open.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: added
|
||||
area: setup
|
||||
|
||||
- Setup: Added an Open SubMiner Settings button to first-run setup and moved Finish setup to the right-side action slot.
|
||||
@@ -0,0 +1,7 @@
|
||||
type: added
|
||||
area: setup
|
||||
|
||||
- Added optional first-run setup controls to install Bun and the `subminer` command-line launcher on Linux, macOS, and Windows, with a Windows `subminer.cmd` PATH shim so `subminer` works without manually adding `SubMiner.exe` to PATH.
|
||||
- Added an Open SubMiner Settings button to first-run setup and moved Finish to the right-side action slot.
|
||||
- First-run setup recognizes existing `subminer` installs in Homebrew or user PATH directories, while manual setup avoids writing into Homebrew-owned paths.
|
||||
- The standalone setup app quits after completing first-run setup, returning the terminal instead of leaving the process open.
|
||||
@@ -0,0 +1,6 @@
|
||||
type: fixed
|
||||
area: shortcuts
|
||||
|
||||
- Disabled native mpv menu shortcuts during managed macOS playback so configured SubMiner shortcuts work while mpv has focus.
|
||||
- Wired configured session shortcuts, including `stats.markWatchedKey`, through mpv so custom changes work while mpv has focus.
|
||||
- Focus the visible overlay when entering multi-line copy/mine selection so number keys choose the line count on macOS and Windows.
|
||||
@@ -0,0 +1,5 @@
|
||||
type: fixed
|
||||
area: stats
|
||||
|
||||
- Fixed in-player stats layering so delete confirmations, overlay modals, and update-check dialogs appear above the stats window.
|
||||
- Grouped Jellyfin playback stats under item metadata instead of stream URLs, so watched episodes merge with matching local library titles and keep clean display names.
|
||||
@@ -0,0 +1,8 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- Primary and secondary subtitle appearance now use color controls plus CSS declaration editors, saved as `subtitleStyle.css` and `subtitleStyle.secondary.css`; sidebar appearance uses `subtitleSidebar.css`.
|
||||
- Moved known-word and N+1 annotation colors to `subtitleStyle.knownWordColor` and `subtitleStyle.nPlusOneColor`; legacy Anki color keys are still accepted with deprecation warnings.
|
||||
- Updated subtitle font defaults to `Hiragino Sans, M PLUS 1, Source Han Sans JP, Noto Sans CJK JP`.
|
||||
- Existing configs are migrated automatically: legacy primary/secondary appearance options and hover token colors fold into `subtitleStyle.css`, and user config files are preserved during legacy compatibility handling.
|
||||
- Live Settings saves apply subtitle CSS declarations immediately to open video overlays, and the generated example config uses the same CSS declaration paths.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- Config: Primary and secondary subtitle appearance now use color controls plus CSS declaration editors, saved as `subtitleStyle.css` and `subtitleStyle.secondary.css`.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: config
|
||||
|
||||
- Migrated legacy subtitle hover token colors into `subtitleStyle.css` instead of leaving `hoverTokenColor` or `hoverTokenBackgroundColor` behind.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: config
|
||||
|
||||
- Migrated legacy primary and secondary subtitle appearance options into `subtitleStyle.css` automatically when loading config files.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: config
|
||||
|
||||
- Fixed live Settings window saves so primary and secondary subtitle CSS declarations apply immediately to open video overlays.
|
||||
@@ -0,0 +1,5 @@
|
||||
type: fixed
|
||||
area: subtitles
|
||||
|
||||
- Kept frequency highlighting for determiner-led noun compounds like `その場` while still filtering standalone determiners.
|
||||
- Fixed frequency annotations for Yomitan single-token compounds with internal particles such as `目の前`, while keeping pure grammar/kana helper spans unannotated.
|
||||
@@ -0,0 +1,4 @@
|
||||
type: fixed
|
||||
area: subtitles
|
||||
|
||||
- Improved subtitle annotation prefetching so cached colored annotations and character images are ready for more live subtitle changes without delaying raw subtitle display.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: changed
|
||||
area: config
|
||||
|
||||
- Added `subtitleSidebar.css`, migrated legacy sidebar appearance fields into it, and updated subtitle font defaults to `Hiragino Sans, M PLUS 1, Source Han Sans JP, Noto Sans CJK JP`.
|
||||
@@ -0,0 +1,4 @@
|
||||
type: changed
|
||||
area: subtitles
|
||||
|
||||
- Updated subtitle defaults with a stronger outline-style text shadow, thicker JLPT underlines, and a `topX` frequency highlighting default of `10000`.
|
||||
@@ -1,10 +0,0 @@
|
||||
type: fixed
|
||||
area: tray
|
||||
|
||||
- Kept the tray app running when closing tray-launched Yomitan settings.
|
||||
- Kept tray-launched Yomitan settings loading from blocking other tray actions.
|
||||
- Replaced the default native Yomitan settings menu with a close-only menu so closing settings does not quit the tray app.
|
||||
- Added an in-page close button for Yomitan settings on Hyprland, where native window controls are not available.
|
||||
- Disabled Yomitan's embedded popup preview in the tray-launched settings window to avoid renderer hangs during normal sidebar navigation.
|
||||
- Serialized copied Yomitan extension refreshes so startup cannot race itself and leave extension loading in an error state.
|
||||
- Fixed tray-launched session help focus handling so the modal can close without mpv running.
|
||||
@@ -0,0 +1,7 @@
|
||||
type: fixed
|
||||
area: tray
|
||||
|
||||
- Kept the tray app running when closing tray-launched Yomitan settings, with a close-only menu so closing settings does not quit the tray, and an in-page close button on Hyprland where native window controls are unavailable.
|
||||
- Kept settings loading from blocking other tray actions, serialized copied Yomitan extension refreshes at startup, and disabled the embedded popup preview to avoid renderer hangs during sidebar navigation.
|
||||
- Fixed session help focus handling so the modal can close without mpv running.
|
||||
- Fixed the Windows tray "Open SubMiner Setup" action so it opens the setup window after first-run setup is complete.
|
||||
@@ -0,0 +1,6 @@
|
||||
type: fixed
|
||||
area: updater
|
||||
|
||||
- Linux: `subminer -u` performs release updates independently of any running tray app (reporting `up to date` without downloading when not newer), and update checks use GitHub release metadata/assets instead of the native Electron updater to avoid network-service crashes during startup.
|
||||
- macOS: update dialogs from `subminer -u` reliably appear in the foreground; builds that cannot apply native updates show a manual-install message instead of a restart prompt; `electron-updater` metadata and ZIP downloads route through `/usr/bin/curl` to avoid Electron network crashes while preserving the Squirrel install path; and metadata mismatches from conflicting ZIP filenames are resolved.
|
||||
- Windows: automatic updates keep the native `electron-updater`/NSIS install path while routing updater HTTP through main-process fetch, avoiding the delayed app exit after launch.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: updates
|
||||
|
||||
- Windows automatic updates now keep the native `electron-updater`/NSIS install path enabled while routing updater HTTP through main-process fetch, avoiding the delayed app exit seen shortly after launch without requiring `curl.exe`.
|
||||
@@ -1,4 +0,0 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Fixed Yomitan popups not opening when playback/overlay startup races the Yomitan extension load.
|
||||
@@ -0,0 +1,6 @@
|
||||
type: fixed
|
||||
area: youtube
|
||||
|
||||
- Downloaded selected YouTube primary subtitles to temporary local files so the primary bar and sidebar read the same source, with cleanup on reload and quit, and suppressed false load-failure notifications by re-checking live mpv subtitle state.
|
||||
- Launcher-managed playback commands create the tray icon even when attaching to an already-running process, and app-owned YouTube playback no longer lets the mpv plugin start a second SubMiner instance.
|
||||
- Logged Linux tray registration failures with a StatusNotifier/AppIndicator hint and documented the Hyprland tray-host requirement.
|
||||
+27
-20
@@ -46,10 +46,16 @@
|
||||
// Logging
|
||||
// Controls logging verbosity.
|
||||
// Set to debug for full runtime diagnostics.
|
||||
// Hot-reload: logging.level applies live while SubMiner is running.
|
||||
// Hot-reload: logging.level and logging.files apply live while SubMiner is running.
|
||||
// ==========================================
|
||||
"logging": {
|
||||
"level": "info" // Minimum log level for runtime logging. Values: debug | info | warn | error
|
||||
"level": "warn", // Minimum log level for runtime logging. Values: debug | info | warn | error
|
||||
"rotation": 7, // Number of days of app, launcher, and mpv logs to retain.
|
||||
"files": {
|
||||
"app": true, // Write SubMiner app runtime logs. Values: true | false
|
||||
"launcher": true, // Write launcher command logs. Values: true | false
|
||||
"mpv": false // Write mpv player logs. Enable temporarily when debugging mpv/plugin startup. Values: true | false
|
||||
} // Files setting.
|
||||
}, // Controls logging verbosity.
|
||||
|
||||
// ==========================================
|
||||
@@ -83,7 +89,7 @@
|
||||
"rightStickPress": 10, // Raw button index used for controller R3 input.
|
||||
"leftTrigger": 6, // Raw button index used for controller L2 input.
|
||||
"rightTrigger": 7 // Raw button index used for controller R2 input.
|
||||
}, // Semantic button-name reference mapping used for legacy configs and debug output. Updating it does not rewrite existing raw binding descriptors.
|
||||
}, // Semantic button-name reference mapping used for debug output. Updating it does not rewrite existing raw binding descriptors.
|
||||
"bindings": {
|
||||
"toggleLookup": {
|
||||
"kind": "button", // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||||
@@ -187,7 +193,7 @@
|
||||
"multiCopyTimeoutMs": 3000, // Timeout for multi-copy/mine modes.
|
||||
"toggleSecondarySub": "CommandOrControl+Shift+V", // Accelerator that toggles the secondary subtitle bar visibility.
|
||||
"markAudioCard": "CommandOrControl+Shift+A", // Accelerator that marks the last mined card as an audio card.
|
||||
"openCharacterDictionary": "CommandOrControl+Alt+A", // Accelerator that opens the character dictionary modal.
|
||||
"openCharacterDictionaryManager": "CommandOrControl+D", // Accelerator that opens the character dictionary manager modal.
|
||||
"openRuntimeOptions": "CommandOrControl+Shift+O", // Accelerator that opens the runtime options modal.
|
||||
"openJimaku": "Ctrl+Shift+J", // Accelerator that opens the Jimaku subtitle search modal.
|
||||
"openSessionHelp": "CommandOrControl+Slash", // Accelerator that opens the session help / keybinding cheatsheet.
|
||||
@@ -374,7 +380,7 @@
|
||||
"word-spacing": "0", // Word spacing setting.
|
||||
"font-kerning": "normal", // Font kerning setting.
|
||||
"text-rendering": "geometricPrecision", // Text rendering setting.
|
||||
"text-shadow": "0 2px 6px rgba(0,0,0,0.9), 0 0 12px rgba(0,0,0,0.55)", // Text shadow setting.
|
||||
"text-shadow": "-1px -1px 2px rgba(0,0,0,0.95), 1px -1px 2px rgba(0,0,0,0.95), -1px 1px 2px rgba(0,0,0,0.95), 1px 1px 2px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.5)", // Text shadow setting.
|
||||
"backdrop-filter": "blur(6px)", // Backdrop filter setting.
|
||||
"--subtitle-hover-token-color": "#f4dbd6", // Subtitle hover token color setting.
|
||||
"--subtitle-hover-token-background-color": "transparent" // Subtitle hover token background color setting.
|
||||
@@ -383,7 +389,9 @@
|
||||
"preserveLineBreaks": false, // Preserve line breaks in visible overlay subtitle rendering. When false, line breaks are flattened to spaces for a single-line flow. Values: true | false
|
||||
"autoPauseVideoOnHover": true, // Automatically pause mpv playback while hovering subtitle text, then resume on leave. Values: true | false
|
||||
"autoPauseVideoOnYomitanPopup": true, // Automatically pause mpv playback while Yomitan popup is open, then resume when popup closes. Values: true | false
|
||||
"nameMatchEnabled": false, // Enable subtitle token coloring for matches from the SubMiner character dictionary. Values: true | false
|
||||
"primaryVisibleOnYomitanPopup": true, // Keep the primary subtitle bar visible while a Yomitan popup is open when primary subtitles are in hover mode. Values: true | false
|
||||
"nameMatchEnabled": false, // Enable character dictionary sync and subtitle token coloring for character-name matches. Values: true | false
|
||||
"nameMatchImagesEnabled": false, // Show small character portraits beside subtitle tokens matched from the SubMiner character dictionary. Values: true | false
|
||||
"nameMatchColor": "#f5bde6", // Hex color used when a subtitle token matches an entry from the SubMiner character dictionary.
|
||||
"nPlusOneColor": "#c6a0f6", // Color used for the single N+1 target token subtitle highlight.
|
||||
"knownWordColor": "#a6da95", // Color used for known-word subtitle highlights.
|
||||
@@ -397,7 +405,7 @@
|
||||
"frequencyDictionary": {
|
||||
"enabled": false, // Enable frequency-dictionary-based highlighting based on token rank. Values: true | false
|
||||
"sourcePath": "", // Optional absolute path to a frequency dictionary directory. If empty, built-in discovery search paths are used.
|
||||
"topX": 1000, // Only color tokens with frequency rank <= topX (default: 1000).
|
||||
"topX": 10000, // Only color tokens with frequency rank <= topX (default: 10000).
|
||||
"mode": "single", // single: use one color for all matching tokens. banded: use color ramp by frequency band. Values: single | banded
|
||||
"matchMode": "headword", // headword: frequency lookup uses dictionary form. surface: lookup uses subtitle-visible token text. Values: headword | surface
|
||||
"singleColor": "#f5a97f", // Color used when frequencyDictionary.mode is `single`.
|
||||
@@ -422,7 +430,7 @@
|
||||
"word-spacing": "0", // Word spacing setting.
|
||||
"font-kerning": "normal", // Font kerning setting.
|
||||
"text-rendering": "geometricPrecision", // Text rendering setting.
|
||||
"text-shadow": "0 2px 6px rgba(0,0,0,0.9), 0 0 12px rgba(0,0,0,0.55)", // Text shadow setting.
|
||||
"text-shadow": "-1px -1px 2px rgba(0,0,0,0.95), 1px -1px 2px rgba(0,0,0,0.95), -1px 1px 2px rgba(0,0,0,0.95), 1px 1px 2px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.5)", // Text shadow setting.
|
||||
"backdrop-filter": "blur(6px)" // Backdrop filter setting.
|
||||
} // CSS declaration object applied to secondary subtitles after normal subtitle style defaults.
|
||||
} // Secondary setting.
|
||||
@@ -488,6 +496,7 @@
|
||||
"tags": [
|
||||
"SubMiner"
|
||||
], // Tags to add to cards mined or updated by SubMiner. Provide an empty array to disable automatic tagging.
|
||||
"deck": "", // Restrict duplicate detection and card enrichment to this Anki deck. Leave empty to search all decks.
|
||||
"fields": {
|
||||
"word": "Expression", // Card field for the mined word or expression text.
|
||||
"audio": "ExpressionAudio", // Card field that receives generated sentence audio.
|
||||
@@ -507,11 +516,14 @@
|
||||
"imageType": "static", // Image capture type: "static" for a single still frame, "avif" for an animated AVIF. Values: static | avif
|
||||
"imageFormat": "jpg", // Encoding format used when imageType is "static". Values: jpg | png | webp
|
||||
"imageQuality": 92, // Quality (0-100) used for lossy static image encoders.
|
||||
"imageMaxWidth": 0, // Maximum width for static images, in pixels. Set to 0 to preserve the source resolution.
|
||||
"imageMaxHeight": 0, // Maximum height for static images, in pixels. Set to 0 to preserve the source resolution.
|
||||
"animatedFps": 10, // Target frame rate for animated AVIF captures.
|
||||
"animatedMaxWidth": 640, // Maximum width applied to animated AVIF captures.
|
||||
"animatedMaxHeight": 0, // Maximum height for animated AVIF captures, in pixels. Set to 0 to preserve aspect ratio.
|
||||
"animatedCrf": 35, // Animated AVIF CRF quality target. Lower values produce larger, higher-quality files.
|
||||
"syncAnimatedImageToWordAudio": true, // For animated AVIF images, prepend a frozen first frame matching the existing word-audio duration so motion starts with sentence audio. Values: true | false
|
||||
"audioPadding": 0.5, // Seconds of padding appended to both ends of generated sentence audio.
|
||||
"audioPadding": 0, // Seconds of padding appended to both ends of generated sentence audio and animated AVIF clips.
|
||||
"fallbackDuration": 3, // Fallback clip duration in seconds when subtitle timing data is unavailable.
|
||||
"maxMediaDuration": 30 // Maximum allowed media clip duration in seconds.
|
||||
}, // Media setting.
|
||||
@@ -519,8 +531,8 @@
|
||||
"highlightEnabled": false, // Enable fast local highlighting for words already known in Anki. Values: true | false
|
||||
"refreshMinutes": 1440, // Minutes between known-word cache refreshes.
|
||||
"addMinedWordsImmediately": true, // Immediately append newly mined card words into the known-word cache. Values: true | false
|
||||
"matchMode": "headword", // Known-word matching strategy for subtitle annotations. Values: headword | surface
|
||||
"decks": {} // Decks and fields for known-word cache. Object mapping deck names to arrays of field names to extract, e.g. { "Kaishi 1.5k": ["Word", "Word Reading"] }.
|
||||
"matchMode": "headword", // Known-word matching strategy for subtitle annotations. Cache matches always receive known-word highlighting even when POS filters suppress other annotation types. Values: headword | surface
|
||||
"decks": {} // Decks and expression/word fields for known-word cache. Object mapping deck names to arrays of field names to extract, e.g. { "Kaishi 1.5k": ["Word"] }.
|
||||
}, // Known words setting.
|
||||
"behavior": {
|
||||
"overwriteAudio": true, // When updating an existing card, overwrite the audio field instead of skipping it. Values: true | false
|
||||
@@ -555,6 +567,8 @@
|
||||
// ==========================================
|
||||
"jimaku": {
|
||||
"apiBaseUrl": "https://jimaku.cc", // Base URL of the Jimaku subtitle search API.
|
||||
"apiKey": "", // Jimaku API key. Optional but recommended for higher rate limits. Get one for free at https://jimaku.cc.
|
||||
"apiKeyCommand": "", // Shell command that prints the Jimaku API key to stdout. Used instead of apiKey to avoid storing the key in plain text.
|
||||
"languagePreference": "ja", // Preferred language used in Jimaku search. Values: ja | en | none
|
||||
"maxEntryResults": 10 // Maximum Jimaku search results returned.
|
||||
}, // Jimaku API configuration and defaults.
|
||||
@@ -581,11 +595,8 @@
|
||||
"enabled": false, // Enable AniList post-watch progress updates. Values: true | false
|
||||
"accessToken": "", // Optional explicit AniList access token override; leave empty to use locally stored token from setup.
|
||||
"characterDictionary": {
|
||||
"enabled": false, // Enable automatic Yomitan character dictionary sync for currently watched AniList media. Values: true | false
|
||||
"refreshTtlHours": 168, // Legacy setting; merged character dictionary retention is now usage-based and this value is ignored.
|
||||
"maxLoaded": 3, // Maximum number of most-recently-used anime snapshots included in the merged Yomitan character dictionary.
|
||||
"evictionPolicy": "delete", // Legacy setting; merged character dictionary eviction is usage-based and this value is ignored. Values: disable | delete
|
||||
"profileScope": "all", // Yomitan profile scope for dictionary enable/disable updates. Values: all | active
|
||||
"profileScope": "all", // Yomitan profile scope for character dictionary settings updates. Values: all | active
|
||||
"collapsibleSections": {
|
||||
"description": false, // Open the Description section by default in character dictionary glossary entries. Values: true | false
|
||||
"characterInformation": false, // Open the Character Information section by default in character dictionary glossary entries. Values: true | false
|
||||
@@ -618,7 +629,7 @@
|
||||
"executablePath": "", // Optional absolute path to mpv.exe for Windows launch flows. Leave empty to auto-discover from SUBMINER_MPV_PATH or PATH.
|
||||
"launchMode": "normal", // Default window state for SubMiner-managed mpv launches. Values: normal | maximized | fullscreen
|
||||
"profile": "", // Optional mpv profile name passed to SubMiner-managed mpv launches. Leave empty to pass no profile.
|
||||
"socketPath": "/tmp/subminer-socket", // mpv IPC socket path used by SubMiner-managed playback and the bundled mpv plugin.
|
||||
"socketPath": "\\\\.\\pipe\\subminer-socket", // mpv IPC socket path used by SubMiner-managed playback and the bundled mpv plugin.
|
||||
"backend": "auto", // Window tracking backend passed to the bundled mpv plugin. Auto detects the current platform. Values: auto | hyprland | sway | x11 | macos | windows
|
||||
"autoStartSubMiner": true, // Start SubMiner in the background when SubMiner-managed mpv loads a file. Values: true | false
|
||||
"pauseUntilOverlayReady": true, // Pause mpv on visible-overlay auto-start until SubMiner signals subtitle tokenization readiness. Values: true | false
|
||||
@@ -638,14 +649,10 @@
|
||||
"serverUrl": "", // Base Jellyfin server URL (for example: http://localhost:8096).
|
||||
"recentServers": [], // Recently authenticated Jellyfin server URLs shown in setup.
|
||||
"username": "", // Default Jellyfin username used during CLI login.
|
||||
"deviceId": "subminer", // Stable device identifier sent on the Jellyfin authentication handshake; primarily internal.
|
||||
"clientName": "SubMiner", // Client name sent on the Jellyfin authentication handshake; primarily internal.
|
||||
"clientVersion": "0.1.0", // Client version sent on the Jellyfin authentication handshake; primarily internal.
|
||||
"defaultLibraryId": "", // Optional default Jellyfin library ID for item listing.
|
||||
"remoteControlEnabled": true, // Enable Jellyfin remote cast control mode. Values: true | false
|
||||
"remoteControlAutoConnect": true, // Auto-connect to the configured remote control target. Values: true | false
|
||||
"autoAnnounce": false, // When enabled, automatically trigger remote announce/visibility check on websocket connect. Values: true | false
|
||||
"remoteControlDeviceName": "SubMiner", // Device name reported for Jellyfin remote control sessions.
|
||||
"pullPictures": false, // Enable Jellyfin poster/icon fetching for launcher menus. Values: true | false
|
||||
"iconCacheDir": "/tmp/subminer-jellyfin-icons", // Directory used by launcher for cached Jellyfin poster icons.
|
||||
"directPlayPreferred": true, // Try direct play before server-managed transcoding when possible. Values: true | false
|
||||
|
||||
@@ -19,18 +19,26 @@ type VersionManifest = {
|
||||
versions: Array<{ version: string; path: string }>;
|
||||
};
|
||||
|
||||
const base = normalizeBase(process.env.SUBMINER_DOCS_BASE ?? '/');
|
||||
const outDir = process.env.SUBMINER_DOCS_OUT_DIR;
|
||||
const docsSourceDir = process.env.SUBMINER_DOCS_SOURCE_DIR ?? process.cwd();
|
||||
const localArchiveDir = resolve(
|
||||
process.env.SUBMINER_DOCS_LOCAL_ARCHIVE_DIR ??
|
||||
join(docsSourceDir, '..', '.tmp/docs-versioned-site'),
|
||||
);
|
||||
const channel = normalizeChannel(process.env.SUBMINER_DOCS_CHANNEL);
|
||||
const docsVersion = process.env.SUBMINER_DOCS_VERSION;
|
||||
const latestStable = process.env.SUBMINER_DOCS_LATEST_STABLE ?? 'v0.14.0';
|
||||
function optionalEnv(value: string | undefined): string | undefined {
|
||||
return value && value !== 'undefined' ? value : undefined;
|
||||
}
|
||||
|
||||
const base = normalizeBase(optionalEnv(process.env.SUBMINER_DOCS_BASE) ?? '/');
|
||||
const outDir = optionalEnv(process.env.SUBMINER_DOCS_OUT_DIR);
|
||||
const docsSourceDir = optionalEnv(process.env.SUBMINER_DOCS_SOURCE_DIR) ?? process.cwd();
|
||||
const channel = normalizeChannel(optionalEnv(process.env.SUBMINER_DOCS_CHANNEL));
|
||||
const docsVersion = optionalEnv(process.env.SUBMINER_DOCS_VERSION);
|
||||
const latestStable = optionalEnv(process.env.SUBMINER_DOCS_LATEST_STABLE) ?? 'v0.14.0';
|
||||
const versionManifest = parseVersionManifest(process.env.SUBMINER_DOCS_VERSION_MANIFEST);
|
||||
const versionLinkOrigin = process.env.SUBMINER_DOCS_VERSION_LINK_ORIGIN ?? 'production';
|
||||
const versionLinkOrigin =
|
||||
optionalEnv(process.env.SUBMINER_DOCS_VERSION_LINK_ORIGIN) ?? 'production';
|
||||
|
||||
function getLocalArchiveDir(): string {
|
||||
return resolve(
|
||||
optionalEnv(process.env.SUBMINER_DOCS_LOCAL_ARCHIVE_DIR) ??
|
||||
join(docsSourceDir, '..', '.tmp/docs-versioned-site'),
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeBase(value: string): string {
|
||||
if (!value || value === '/') return '/';
|
||||
@@ -43,7 +51,7 @@ function normalizeChannel(value: string | undefined): DocsChannel {
|
||||
}
|
||||
|
||||
function parseVersionManifest(value: string | undefined): VersionManifest {
|
||||
if (!value) {
|
||||
if (!value || value === 'undefined') {
|
||||
return {
|
||||
latestStable,
|
||||
channels: [
|
||||
@@ -218,6 +226,7 @@ function isFile(path: string): boolean {
|
||||
function archiveFileForPathname(pathname: string): string | null {
|
||||
if (!shouldHandleLocalVersionRoute(pathname)) return null;
|
||||
|
||||
const localArchiveDir = getLocalArchiveDir();
|
||||
const routePath = decodeURIComponent(pathname).replace(/^\/+/, '');
|
||||
const filePath = resolve(localArchiveDir, routePath);
|
||||
if (filePath !== localArchiveDir && !filePath.startsWith(`${localArchiveDir}${sep}`)) {
|
||||
@@ -234,7 +243,11 @@ function archiveFileForPathname(pathname: string): string | null {
|
||||
}
|
||||
|
||||
function serveLocalArchiveRoute(pathname: string, response: DevServerResponse): boolean {
|
||||
if (versionLinkOrigin !== 'local') return false;
|
||||
if (
|
||||
(optionalEnv(process.env.SUBMINER_DOCS_VERSION_LINK_ORIGIN) ?? versionLinkOrigin) !== 'local'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const filePath = archiveFileForPathname(pathname);
|
||||
if (!filePath) return false;
|
||||
|
||||
@@ -4,6 +4,8 @@ SubMiner can sync your watch progress to [AniList](https://anilist.co) automatic
|
||||
|
||||
AniList data also powers two additional features: [cover art](#cover-art) for the stats dashboard and the [Character Dictionary](/character-dictionary) for in-overlay name lookup.
|
||||
|
||||
[AniList](https://anilist.co) is a free website for tracking which anime you have watched. An **access token** is a private key SubMiner stores so it can update your list on your behalf — you approve it once during setup, and you never paste a password into SubMiner.
|
||||
|
||||
## Setup
|
||||
|
||||
AniList integration is opt-in. To enable it:
|
||||
@@ -96,12 +98,11 @@ All AniList API calls go through a shared rate limiter that enforces a sliding w
|
||||
| ------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| `enabled` | `true`, `false` | Enable AniList post-watch progress updates (default: `false`) |
|
||||
| `accessToken` | string | Explicit AniList access token override; when blank, SubMiner uses the stored encrypted token (default: `""`) |
|
||||
| `characterDictionary.enabled` | `true`, `false` | Enable auto-sync of the merged character dictionary from AniList (default: `false`) |
|
||||
| `characterDictionary.maxLoaded` | number | Number of recent media snapshots kept in the merged dictionary (default: `3`) |
|
||||
| `characterDictionary.profileScope` | `"all"`, `"active"` | Apply dictionary to all Yomitan profiles or only the active one |
|
||||
| `characterDictionary.collapsibleSections.*` | `true`, `false` | Control which dictionary entry sections start expanded |
|
||||
|
||||
See the [Character Dictionary](/character-dictionary) page for full details on the character dictionary feature, including name generation, matching, auto-sync lifecycle, and dictionary entry format.
|
||||
See the [Character Dictionary](/character-dictionary) page for full details on the character dictionary feature, including name generation, matching, auto-sync lifecycle, and dictionary entry format. Character dictionary sync follows `subtitleStyle.nameMatchEnabled`.
|
||||
|
||||
## CLI Commands
|
||||
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
SubMiner uses the [AnkiConnect](https://ankiweb.net/shared/info/2055492159) add-on to create and update Anki cards with sentence context, audio, and screenshots.
|
||||
This project is built primarily for [Kiku](https://kiku.youyoumu.my.id/) and [Lapis](https://github.com/donkuri/lapis) note types, including sentence-card and field-grouping behavior.
|
||||
|
||||
::: tip New to these terms?
|
||||
- **Anki** is the flashcard app where your study cards live.
|
||||
- **AnkiConnect** is a free add-on that lets other programs (like SubMiner) talk to Anki over a local connection. SubMiner needs it installed to add or edit cards.
|
||||
- A **note type** (also called a "model") is the template that defines what a card looks like — for example the Kiku or Lapis templates many Japanese learners use.
|
||||
- A **field** is one labeled slot in that template, such as `Sentence`, `Expression`, or `Picture`. SubMiner fills these fields when it mines a card.
|
||||
:::
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Install [Anki](https://apps.ankiweb.net/).
|
||||
@@ -15,9 +22,9 @@ AnkiConnect listens on `http://127.0.0.1:8765` by default. If you changed the po
|
||||
|
||||
When you add a word via Yomitan, SubMiner detects the new card and fills in the sentence, audio, image, and translation fields automatically. Two detection methods are available:
|
||||
|
||||
**Proxy mode** — SubMiner runs a local AnkiConnect-compatible proxy and intercepts card creation instantly. Recommended when possible.
|
||||
**Proxy mode** (default) — SubMiner runs a local *proxy*: a small middleman server that sits between Yomitan and Anki. Yomitan sends new cards to SubMiner, SubMiner enriches them, then passes them along to Anki. This makes enrichment instant.
|
||||
|
||||
**Polling mode** (default) — SubMiner polls AnkiConnect every few seconds for newly added cards. Simpler setup, but with a short delay (~3 seconds).
|
||||
**Polling mode** (fallback, when the proxy is disabled) — SubMiner asks AnkiConnect every few seconds whether any new cards were added, then enriches them. Simpler setup, but with a short delay (~3 seconds).
|
||||
|
||||
Use proxy mode if you want immediate enrichment. Use polling mode if your Yomitan instance is external (browser-based) or you prefer minimal configuration.
|
||||
|
||||
@@ -29,8 +36,8 @@ In both modes, the enrichment workflow is the same:
|
||||
4. Fills the translation field from the secondary subtitle or AI.
|
||||
5. Writes metadata to the miscInfo field.
|
||||
|
||||
Polling mode uses the query `"deck:<ankiConnect.deck>" added:1` to find recently added cards. If no deck is configured, it searches all decks.
|
||||
Known-word sync scope is controlled by `ankiConnect.knownWords.decks` (object map), with `ankiConnect.deck` used as legacy fallback.
|
||||
Polling mode uses the query `"deck:<ankiConnect.deck>" added:1` to find recently added cards. If no deck is configured, it searches all decks. In Settings, the AnkiConnect deck dropdown auto-fills from Yomitan's current mining deck when available, then falls back to the decks reported by AnkiConnect.
|
||||
Known-word sync scope is controlled by `ankiConnect.knownWords.decks`.
|
||||
|
||||
### Proxy Mode Setup (Yomitan / Texthooker)
|
||||
|
||||
@@ -147,13 +154,13 @@ SubMiner uses FFmpeg to generate audio and image media from the video. FFmpeg mu
|
||||
|
||||
### Audio
|
||||
|
||||
Audio is extracted from the video file using the subtitle's start and end timestamps, with configurable padding added before and after.
|
||||
Audio is extracted from the video file using the subtitle's start and end timestamps. Padding is opt-in; keep it at `0` when you want sentence audio to start exactly at the mined sentence.
|
||||
|
||||
```jsonc
|
||||
"ankiConnect": {
|
||||
"media": {
|
||||
"generateAudio": true,
|
||||
"audioPadding": 0.5, // seconds before and after subtitle timing
|
||||
"audioPadding": 0, // optional seconds before and after subtitle timing
|
||||
"maxMediaDuration": 30 // cap total duration in seconds
|
||||
}
|
||||
}
|
||||
@@ -322,6 +329,7 @@ When you mine the same word multiple times, SubMiner can merge the cards instead
|
||||
"upstreamUrl": "http://127.0.0.1:8765",
|
||||
},
|
||||
"fields": {
|
||||
"word": "Expression",
|
||||
"audio": "ExpressionAudio",
|
||||
"image": "Picture",
|
||||
"sentence": "Sentence",
|
||||
@@ -334,7 +342,7 @@ When you mine the same word multiple times, SubMiner can merge the cards instead
|
||||
"imageType": "static",
|
||||
"imageFormat": "jpg",
|
||||
"imageQuality": 92,
|
||||
"audioPadding": 0.5,
|
||||
"audioPadding": 0,
|
||||
"maxMediaDuration": 30,
|
||||
},
|
||||
"behavior": {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user