From 47b5903392c8e5c9e3a749a7831a095d26034ed2 Mon Sep 17 00:00:00 2001 From: sudacode Date: Thu, 13 Aug 2026 23:02:57 -0700 Subject: [PATCH] chore(release): prepare v0.19.3 --- CHANGELOG.md | 24 ++++++++++ changes/changelog-modal.md | 7 --- changes/character-dictionary-large-imports.md | 7 --- changes/stats-delete-responsiveness.md | 4 -- changes/styled-subtitle-cue-parsing.md | 5 -- changes/subtitle-tokenization-performance.md | 20 -------- changes/x11-backend-keeps-mpv-renderer.md | 4 -- changes/x11-overlay-display-scaling.md | 4 -- docs-site/changelog.md | 24 ++++++++++ package.json | 2 +- release/release-notes.md | 48 +++++++++++++++++++ 11 files changed, 97 insertions(+), 52 deletions(-) delete mode 100644 changes/changelog-modal.md delete mode 100644 changes/character-dictionary-large-imports.md delete mode 100644 changes/stats-delete-responsiveness.md delete mode 100644 changes/styled-subtitle-cue-parsing.md delete mode 100644 changes/subtitle-tokenization-performance.md delete mode 100644 changes/x11-backend-keeps-mpv-renderer.md delete mode 100644 changes/x11-overlay-display-scaling.md create mode 100644 release/release-notes.md diff --git a/CHANGELOG.md b/CHANGELOG.md index b43cc224..a32fa520 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## v0.19.3 (2026-08-13) + +### Added +- Changelog Modal: Adds an in-app changelog you can open from the tray ("View Changelog") or the "What's New" button on the update notification, so the notification stays reachable while you read. It shows the newest published release notes (falling back to the bundled changelog if that fetch fails), folds older versions while keeping the current one expanded, and supports keyboard navigation (`J`/`K`/arrows, `Enter`, `R`, `Esc`). + +### Changed +- Subtitle Tokenization Performance: Reworks subtitle dictionary lookups to cut per-line work roughly in half, cache repeated lookups across lines, and stop tokenization from competing with on-screen subtitle prefetching. Also fixes several accuracy issues along the way: dropped readings on trailing kana, character names being skipped after a dictionary sync, annotations not refreshing after mining a card, and halfwidth katakana character names losing their reading or being swallowed by other words. + +### Fixed +- Character Dictionary Large Imports: Large character dictionaries (e.g. One Piece) no longer fail to install from a fixed timeout budget; the import now scales its time budget to dictionary size and reports detailed progress (page/character counts, image download progress, elapsed time) instead of one static message. +- Stats Delete Responsiveness: Deleting sessions, episodes, or library entries no longer freezes the stats page or an active video player; deletes are now batched into a single transaction. +- Styled Subtitle Cue Parsing: Heavily typeset subtitles (karaoke, signs) no longer flood the subtitle sidebar with garbage; vector drawing commands are no longer shown as text, and duplicate/animation-burst cues now collapse into one. +- X11 mpv Renderer: Fixes an mpv crash on the first fullscreen toggle for X11/XWayland users with `gpu-next` shaders (e.g. ArtCNN), which was caused by X11 mode forcing the legacy OpenGL renderer. +- X11 Overlay Display Scaling: Fixes the overlay appearing oversized and offset from mpv on X11/XWayland under fractional or mixed-monitor display scaling. + +
+Internal changes + +### Internal +- Subtitle text is now decoded from ASS exactly once at ingest, so the renderer, timing tracker, and tokenizer all share one decoded value instead of each re-deriving it. +- Added per-stage debug timings (`scanMs`, `mecabMs`, `frequencyMs`, `annotateMs`) to the subtitle tokenization pipeline log. + +
+ ## v0.19.2 (2026-08-04) ### Changed diff --git a/changes/changelog-modal.md b/changes/changelog-modal.md deleted file mode 100644 index c4457f79..00000000 --- a/changes/changelog-modal.md +++ /dev/null @@ -1,7 +0,0 @@ -type: added -area: overlay - -- Added an in-app changelog modal, opened from the tray ("View Changelog") or the "What's New" button on the update-available notification, which now stays on screen so "Update" is still reachable after reading the notes. It renders inside the player bounds when a video is playing and in its own window otherwise, the same as the help modal. -- The changelog is fetched from the newest published release, so release notes for versions newer than the installed build are visible; a failed download falls back to the changelog bundled with the install and says so in the modal. -- Versions are foldable: the current `0.x` line is expanded and older lines are folded, matching the docs-site changelog. A badge marks the installed version and newer versions are tagged "New". -- Keyboard: `J`/`K` or arrows move between versions, `Enter` folds/unfolds, `R` refetches, `Esc` closes. diff --git a/changes/character-dictionary-large-imports.md b/changes/character-dictionary-large-imports.md deleted file mode 100644 index 4fe4e511..00000000 --- a/changes/character-dictionary-large-imports.md +++ /dev/null @@ -1,7 +0,0 @@ -type: fixed -area: character dictionary - -- A large character dictionary no longer fails to install. The Yomitan import (and the delete that precedes it) used a flat 7 second budget, so a series like One Piece failed with `importYomitanDictionary(merged.zip) timed out after 7000ms` while the import was still healthy. The budget is now sized from the merged ZIP (2 minutes plus 6 seconds per MB, capped at 30 minutes); the quick queries keep the 7 second budget. -- The "Generating character dictionary" notification now reports what it is doing instead of one static message for the whole run: the AniList page and character count while characters download (`page 12, 587 characters`), then `image 240/1220, ~4m left` per downloaded character/voice actor image, then `name 800/1220` for MeCab name splits and `saving snapshot` at the end. Updates are throttled to one per second, and every stage change and final item always reports. -- Every long phase also carries an elapsed clock (`· 1m 35s`), refreshed every 5 seconds even when nothing else moves, so a stalled step is visibly different from a frozen app. Long imports tick the same way. -- Image downloads are also logged every 100 files, and the import logs the timeout it computed. diff --git a/changes/stats-delete-responsiveness.md b/changes/stats-delete-responsiveness.md deleted file mode 100644 index 5bd00ef8..00000000 --- a/changes/stats-delete-responsiveness.md +++ /dev/null @@ -1,4 +0,0 @@ -type: fixed -area: stats - -- Kept the stats page and active video player responsive during deletes, and batched concurrent session, episode, and library deletes into one transaction and summary rebuild. diff --git a/changes/styled-subtitle-cue-parsing.md b/changes/styled-subtitle-cue-parsing.md deleted file mode 100644 index 47ac3a01..00000000 --- a/changes/styled-subtitle-cue-parsing.md +++ /dev/null @@ -1,5 +0,0 @@ -type: fixed -area: subtitles - -- Heavily typeset ASS scripts (karaoke OP/ED, sign work) no longer fill the subtitle sidebar with garbage. Vector drawing runs (`\p1` … `\p0`) are no longer shown as subtitle text (e.g. `m 20 0 b 10 0 0 10 0 20 …`), and duplicate events in a parsed subtitle file collapse into one cue: identical text over an identical span (layered "shadow" copies), and per-frame animation bursts. An ASS burst has to prove itself with authoring evidence — a temporal tag (`\t`, `\move`, karaoke timing), an animated `Effect` column, or override values that change from event to event — plus one shared style and actor, so three rapid `えっ` reactions from three characters, or a sign repeated with the same static `\clip`, stay separate. SRT and VTT carry no such metadata, so there the run has to be at least five contiguous events all shorter than 0.1s, which is where ASS-to-SRT conversion leaves karaoke frames. -- Subtitle text is now decoded from ASS exactly once, where it enters the app, and matches how mpv renders the same line (including `\N`, `\n`, `\h`, unclosed `{`, and the fact that `\{` is not an escape). Renderer, timing tracker, tokenizer and the tokenization cache take that decoded text as-is instead of each re-deriving it, so one authored line can no longer produce two different cache keys, and a cue that normalizes to nothing is no longer stored as subtitle text or cached under an empty key. diff --git a/changes/subtitle-tokenization-performance.md b/changes/subtitle-tokenization-performance.md deleted file mode 100644 index 5eeb38de..00000000 --- a/changes/subtitle-tokenization-performance.md +++ /dev/null @@ -1,20 +0,0 @@ -type: changed -area: subtitles - -- Subtitle tokenization no longer runs a duplicate full `parseText` pass per line: the termsFind scanner walk is now the only tokenizer and emits its own hoverable filler runs for unmatched text (parseText is kept only as an error fallback). This roughly halves the dictionary work per line. -- The Yomitan scanning helpers are now installed once per parser window (`__subminerYomitanScan`) instead of re-shipping and re-parsing a ~500-line script for every subtitle line; each line only evaluates a tiny call. -- termsFind lookups are cached across subtitle lines in a window-persistent LRU keyed by substring, so repeated particles and verb forms stop costing backend round trips. The cache invalidates on dictionary/settings changes and window reloads. -- The scanner walk now skips lookups at punctuation and whitespace positions (latin letters and digits still look up, e.g. Tシャツ). The shrinking-window retry ladder keeps following the consumed lengths the backend reports, and only blind guesses (windows the backend consumed whole, which tell it nothing) are capped at four per position. A line that hits that cap escalates to a single `parseText` for the whole line, so a hard line still resolves to dictionary tokens instead of an unparsed run, without letting the ladder run to one lookup per window length. -- Tokenizer runtime dependencies are built once instead of per line, fixing a JLPT lookup cache that never hit (it was keyed on a per-call closure identity and leaked a Map per line) and a `which mecab` availability check that re-ran synchronously on every line when MeCab is absent. -- Subtitle changes no longer restart the prefetch run per line (which discarded in-flight tokenization work); prefetch now only pauses for the live line and restarts on real seeks, cache invalidation, or option changes. Prefetch also stays paused for the whole time the subtitle processing controller is working on the line, including the provisional raw emit that precedes tokenization, so it never competes with the on-screen line for the parser window. The pause is released when the controller reports it has settled, which also covers the lines that finish without an emit (a suppressed duplicate or a failed tokenization) and used to leave prefetching paused indefinitely. -- Added per-stage debug timings (`scanMs`, `mecabMs`, `frequencyMs`, `annotateMs`) to the subtitle tokenization pipeline log. -- Fixed a reading that stopped covering its surface when an unmatched kana run extended the preceding token (for example a trailing る on 待ち合わせ), which silently disabled the known-word reading fallback for those tokens. -- Subtitle prefetching no longer stays paused for the rest of a cue when the same subtitle text is reported twice and there is nothing to tokenize. This covers the startup and overlay priming paths as well as ordinary subtitle changes. -- Character name and image lookups are now refreshed centrally whenever a character dictionary sync changes its content, so a newly added name can no longer be skipped by a stale candidate list. -- A subtitle that was on screen when its annotations were invalidated (by mining a card, for example) is now re-annotated instead of staying plain for the rest of the line. -- Character name annotations no longer cost a dictionary lookup at every position in a line. The scanner now knows which name forms the current title's character dictionary actually contains and only checks where one can start, which removes the whole overhead of having the character dictionary enabled (measured: 21 lookups per line down to 10, the same as with it disabled). Titles with no cached character data keep the previous exhaustive scan, so a missing snapshot costs speed rather than a missing name. -- The cross-line termsFind cache is now bounded by the number of retained dictionary entries as well as by key count, so a run of lookups that each carry hundreds of entries with full glossaries cannot grow the parser window's memory without limit. The budget is re-checked when a lookup resolves, so a single oversized response is dropped rather than parked in the cache and reused. -- The unnamed-mob disambiguator filter (Girl A / Girl B) now only drops a single letter or digit split off a name, instead of every one-character term: a name that is genuinely one character keeps its terms whatever the script (𠮷, あ, 별 김, ア・ベ). The character dictionary and the scanner's name pre-pass also share one Han code-point table now, so a name the dictionary accepts is a name the scanner will look for. -- A character name written in halfwidth katakana takes part in the greedy name pre-pass again, so a longer generic word can no longer swallow the start of it, and it now carries a reading (it used to come out blank, which disables known-word matching and frequency lookups for the token). Voiced halfwidth kana compose properly, so ガク reads ガク rather than ガク, and kana normalization folds halfwidth throughout so those tokens compare equal to the same word written fullwidth. Because the fold makes halfwidth text indexable, the character-name prefilter now judges halfwidth spellings like any other, and a position only bypasses it when an unfoldable voiced mark sits inside the lookup window. That covers a name that starts on a kanji and turns halfwidth later (山ガク), and one stretched out with emphatic characters in between (山ーーーーーーガク). -- Dictionary-entry classification (source dictionaries, character-dictionary media ids) is memoized per entry object for as long as the entry is cached, instead of being recomputed for every headword comparison and every retry window. -- Autoplay priming no longer broadcasts the plain subtitle twice: it tells the processing controller the line has already been painted, so the controller goes straight to the annotated payload. diff --git a/changes/x11-backend-keeps-mpv-renderer.md b/changes/x11-backend-keeps-mpv-renderer.md deleted file mode 100644 index 2e303c12..00000000 --- a/changes/x11-backend-keeps-mpv-renderer.md +++ /dev/null @@ -1,4 +0,0 @@ -type: fixed -area: playback - -- XWayland/X11 mode (`--backend=x11`, or the automatic fallback on non-Hyprland/Sway Wayland sessions) no longer forces mpv onto `--vo=gpu --gpu-api=opengl`. It now only pins the window context (`--gpu-context=x11vk,x11egl,x11`), so a `vo=gpu-next` config keeps its renderer, API, and user shaders. Forcing the legacy OpenGL renderer crashed mpv on the first fullscreen toggle for anyone using a gpu-next user shader that emits a 4-component LUMA hook (ArtCNN and friends), which asserts in mpv's old renderer (`copy_image: *offset + count < sizeof(dst)`) as soon as the shader's upscale-only condition turns on. diff --git a/changes/x11-overlay-display-scaling.md b/changes/x11-overlay-display-scaling.md deleted file mode 100644 index d07aa4f1..00000000 --- a/changes/x11-overlay-display-scaling.md +++ /dev/null @@ -1,4 +0,0 @@ -type: fixed -area: overlay - -- Fixed X11/XWayland overlays being oversized and offset from mpv under fractional or mixed-monitor display scaling. diff --git a/docs-site/changelog.md b/docs-site/changelog.md index 7dffad63..335aa870 100644 --- a/docs-site/changelog.md +++ b/docs-site/changelog.md @@ -1,5 +1,29 @@ # Changelog +## v0.19.3 (2026-08-13) + +**Added** +- Changelog Modal: Adds an in-app changelog you can open from the tray ("View Changelog") or the "What's New" button on the update notification, so the notification stays reachable while you read. It shows the newest published release notes (falling back to the bundled changelog if that fetch fails), folds older versions while keeping the current one expanded, and supports keyboard navigation (`J`/`K`/arrows, `Enter`, `R`, `Esc`). + +**Changed** +- Subtitle Tokenization Performance: Reworks subtitle dictionary lookups to cut per-line work roughly in half, cache repeated lookups across lines, and stop tokenization from competing with on-screen subtitle prefetching. Also fixes several accuracy issues along the way: dropped readings on trailing kana, character names being skipped after a dictionary sync, annotations not refreshing after mining a card, and halfwidth katakana character names losing their reading or being swallowed by other words. + +**Fixed** +- Character Dictionary Large Imports: Large character dictionaries (e.g. One Piece) no longer fail to install from a fixed timeout budget; the import now scales its time budget to dictionary size and reports detailed progress (page/character counts, image download progress, elapsed time) instead of one static message. +- Stats Delete Responsiveness: Deleting sessions, episodes, or library entries no longer freezes the stats page or an active video player; deletes are now batched into a single transaction. +- Styled Subtitle Cue Parsing: Heavily typeset subtitles (karaoke, signs) no longer flood the subtitle sidebar with garbage; vector drawing commands are no longer shown as text, and duplicate/animation-burst cues now collapse into one. +- X11 mpv Renderer: Fixes an mpv crash on the first fullscreen toggle for X11/XWayland users with `gpu-next` shaders (e.g. ArtCNN), which was caused by X11 mode forcing the legacy OpenGL renderer. +- X11 Overlay Display Scaling: Fixes the overlay appearing oversized and offset from mpv on X11/XWayland under fractional or mixed-monitor display scaling. + +
+Internal changes + +**Internal** +- Subtitle text is now decoded from ASS exactly once at ingest, so the renderer, timing tracker, and tokenizer all share one decoded value instead of each re-deriving it. +- Added per-stage debug timings (`scanMs`, `mecabMs`, `frequencyMs`, `annotateMs`) to the subtitle tokenization pipeline log. + +
+ ## v0.19.2 (2026-08-04) **Changed** diff --git a/package.json b/package.json index 3ee8ceec..1385b1ad 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "subminer", "productName": "SubMiner", "desktopName": "SubMiner.desktop", - "version": "0.19.2", + "version": "0.19.3", "description": "All-in-one sentence mining overlay with AnkiConnect and dictionary integration", "packageManager": "bun@1.3.5", "main": "dist/main-entry.js", diff --git a/release/release-notes.md b/release/release-notes.md new file mode 100644 index 00000000..742e3a14 --- /dev/null +++ b/release/release-notes.md @@ -0,0 +1,48 @@ +## Highlights +### Added +- **In-App Changelog** + - View release notes without leaving the app, from the tray menu ("View Changelog") or the "What's New" button on update notifications. + - Shows notes for the latest published release even when it's newer than your installed build, and falls back to the notes bundled with your install if the download fails. + - Older versions fold automatically, your installed version is badged, and newer ones are tagged "New"; navigate with `J`/`K` or the arrow keys, `Enter` to expand/collapse, `R` to refresh, and `Esc` to close. + +### Changed +- **Faster Subtitle Tokenization** + - Subtitle lines are parsed and looked up roughly twice as efficiently, with results cached across lines so repeated words and grammar no longer re-query the dictionary. + - Enabling a character dictionary no longer slows subtitle scanning as much, since name lookups now only check positions where a known name can actually start. + - Fixed related accuracy issues along the way: readings that could go missing on certain word endings, subtitle text that stayed unannotated after mining a card, character names that could drop out of disambiguation rules, and halfwidth-katakana character names that weren't recognized or read correctly. + +### Fixed +- **Large Character Dictionary Generation** + - Big character dictionaries (long-running series like One Piece) no longer fail to install with a timeout error; the import time budget now scales with dictionary size instead of using a fixed 7-second limit. + - The "Generating character dictionary" notification now shows real progress (character/page counts, image download progress with an ETA, name-processing progress) and an elapsed-time clock, so a long-running import no longer looks frozen. +- **Stats Deletion Responsiveness** + - Deleting sessions, episodes, or library entries on the stats page no longer freezes the page or an active video player; deletes are now batched into a single transaction. +- **Subtitle Sidebar Clutter from Styled Subtitles** + - Heavily typeset subtitles (karaoke openings/endings, stylized signs) no longer flood the subtitle sidebar with garbled vector-drawing text or duplicate "shadow" copies of the same line. + - Subtitle text is now decoded consistently in one place, matching what mpv actually renders on screen, so it can no longer diverge or get cached inconsistently. +- **X11/XWayland Playback and Overlay Fixes** + - Fixed a crash on the first fullscreen toggle when using an mpv `gpu-next` shader (e.g. ArtCNN) in X11/XWayland mode; SubMiner no longer forces mpv onto its older OpenGL renderer. + - Fixed the overlay appearing oversized and offset from the video under fractional or mixed-monitor display scaling in X11/XWayland mode. + +## What's Changed + +- perf(tokenizer): single-pass Yomitan scan with cross-line caching and prefetch fixes by @ksyasuda in #185 +- fix(subtitles): collapse duplicate ASS events and decode text once by @ksyasuda in #186 +- feat(overlay): add in-app changelog modal by @ksyasuda in #187 +- fix(playback): stop forcing legacy OpenGL renderer on X11 mpv backend by @ksyasuda in #188 +- fix(dictionary): stop large character dictionaries from timing out by @ksyasuda in #189 +- fix(overlay): handle X11 display scaling across monitors by @ksyasuda in #193 +- fix(stats): batch deletes off the main thread by @ksyasuda in #194 + +## Installation + +See the README and docs/installation guide for full setup steps. + +## Assets + +- Linux: `SubMiner.AppImage` +- macOS: `SubMiner-*.dmg` and `SubMiner-*.zip` +- Windows: `SubMiner-*.exe` and `SubMiner-*-win.zip` +- Optional extras: `subminer-assets.tar.gz` and the `subminer` launcher + +Note: the `subminer` wrapper script uses Bun (`#!/usr/bin/env bun`), so `bun` must be installed and on `PATH`.