- Show overlay loading OSD spinner during restart and keep it alive until overlay reports ready
- Route restart progress/completion through notify_playback_feedback so overlay/both modes display in overlay
- Delay "Restarted successfully" until show-visible-overlay completes
- Add test-plugin-restart-feedback.lua covering the restart feedback flow
- Add --playback-feedback CLI flag; overlay/both modes show AniSkip hint and skip result on overlay instead of raw OSD
- Wire notify_playback_feedback through process.lua and the full deps chain to showPlaybackFeedback
- Fallback to OSD when binary unavailable or osd_messages opt enabled
- Skip re-append for cards already in stack to avoid replaying enter animation
- Track enter animation end to remove `entering` class after first render
- Gate mouseenter interactive state on cards with explicit actions only
- Bind interactive hover only to action buttons and their close buttons
- Add regression tests for passive vs action-bearing notification hover
- Add openNoteInBrowser to AnkiConnectClient via guiBrowse IPC
- Add Open in Anki action button to mined-card overlay notifications and history entries
- Fall back to a direct AnkiConnectClient when the live integration is unavailable
- Embed notification images as base64 data URIs so history panel shows thumbnails
- Update same-id progress notifications in place to avoid spinner flicker
- Thread noteId through IPC overlay notification action payload
- Replaces Ctrl+N default with CommandOrControl+N so the binding works on macOS (Cmd+N) and Windows/Linux (Ctrl+N)
- Updates config example, docs, changelog, and default config to match
- Adds !important to notification stack z-index to prevent stacking-context overrides
- Default notificationType fallback changed from 'overlay' to 'osd'
- isVisibleOverlayContentReady guards on overlay visible + window ready
- All overlay hide paths dismiss loading OSD notification
- notifyConfiguredStatus falls back to desktop when overlay not ready
- anilist deps builder preserves undefined optional callbacks as undefined
- settingsEnumValues field added to ConfigOptionRegistryEntry
- Drop !important from z-index; lower yomitan popup z-index below notification stack
- manual:check and manual:install now tracked independently; install no longer reuses a check's in-flight promise
- add toggleNotificationHistory (Ctrl+N) shortcut to config example and docs
- Show mpv OSD spinner from start-file until subminer-overlay-loading-ready; force-shown for visible-overlay startup regardless of osd_messages setting
- Gate non-macOS overlay visibility on content-ready so first subtitle line is immediately hoverable and clickable
- Queue startup notifications in main process until overlay window finishes loading; upsert progress cards by id to avoid cold-start floods
- Defer background warmups until after overlay runtime init so queued notifications can deliver promptly
- Preserve character dictionary checking/building/importing/ready phases as distinct history entries; route building and importing to system notifications when notificationType is both
- New toggleNotificationHistory (Ctrl+N) session-scoped history panel; slides in from same edge as notification stack
- Overlay error/recovery toast follows notifications.overlayPosition; stack and history side seeded at startup
- Cold managed background startup initializes tray and visible overlay shell before tokenization warmups finish
- Add Update button to overlay update-available notifications
- Fix Ctrl+S sentence-card flow: only Anki progress notification, no duplicate status toast
- Fix overlay notification close/actions clickability above subtitle bars on Linux
- Increase pause-until-ready default timeout from 15s to 30s
- Send synthetic `__warm__` payload when no current subtitle exists so the gate can release without waiting for a subtitle event that can't fire while paused
- Visible-overlay readiness accepts `__warm__` once the overlay is content-ready, rejects it otherwise
- Autoplay gate self-retries via scheduled polling when signal target isn't ready, removing reliance on an external flush event
- Skip duplicate desktop notification when overlay or startup sequencer already delivered it
- Add onResolvedSubtitle callback to resolveCurrentSubtitleForRenderer so the startup overlay-ready gate fires after the initial subtitle resolves
- Guard scheduleCharacterDictionarySync behind a last-path check so duplicate MPV media-path events don't re-trigger sync for the same video
- add dismissOverlayLoadingOsd dep and call it on hide/show paths (macOS only)
- simplify notification card styles: remove accent bar, flatten gradient bg, tweak spacing
- fix test CSS path to use __dirname instead of process.cwd()
The thumbnail was 100px wide but its grid column only reserved 56px, so on
macOS the image spilled ~44px into the content column and overlapped the
title/body. Reserve a minmax(0, 100px) track for the image and make the
image fluid (width: 100%; max-width: 100px; aspect-ratio) so it shrinks to
fit on narrow notifications instead of overlapping the text.
- Direction-aware slide animations (right/left/top) on enter and leave
- Cards keyed by id so re-renders reuse elements; enter animation only plays once
- Exit animates via .leaving class then removes; fallback timer guards missing animationend
- Respects prefers-reduced-motion
- Share generated notification icon between overlay and system notification paths
- Add `image` field to OverlayNotificationPayload; render as IMG with has-image layout
- Widen overlay stack to 420px; enlarge card padding and min-height for image variant
- Show OSD message after successful anilist retry when attempt key already handled
- Extract shouldShowOsd/Overlay/Desktop into notification-routing.ts (was duplicated in 3 files)
- Add resolveOverlayReadinessNotificationType: preserves system channel when overlay not ready (both→osd-system, system→system, overlay→osd)
- Route overlay loading status through showConfiguredStatusNotification instead of raw OSD
- Add `submodules` target that runs `git submodule update --init --recursive`
- `deps` now depends on `submodules` so fresh checkouts work out of the box
- Update docs to replace manual install steps with `make deps`
- Fix Windows build-from-source steps to include stats and submodule init
Rewrite Hyprland overlay window-rule guidance with current Lua (hl.window_rule)
config and legacy hyprland.conf syntax, and note SubMiner's automatic hyprctl
placement. Add a Character Dictionary troubleshooting section (no AniList auth
required) and a See Also index linking each feature's own troubleshooting page.
- AniList auth not required for character dictionary; uses public GraphQL
- Document nameMatchImagesEnabled and inline portrait behavior
- Clarify AniList auth is only for watch-progress sync
- Delete stale release/release-notes.md
- Convert flat prose entries in CHANGELOG.md and docs-site/changelog.md to bold headers + sub-bullets
- Scope artifact uploads in release/prerelease workflows to `latest*.yml` instead of `*.yml`
- Update release-notes and RELEASING docs to match
- Adjust workflow tests for new nested bullet format
- Prompt now requests short top-level bullets with nested change/benefit/action sub-bullets in release-notes mode
- CHANGELOG mode keeps single-line bullets unchanged
- Tests assert new prompt constraints are present
* style: update subtitle text shadow, JLPT underlines, and frequency topX
- Replace directional text-shadow with 4-corner outline shadow for sharper readability
- Increase JLPT level border-bottom from 2px to 3px; add drop-shadow filter
- Add margin-left 0.18em to character image token
- Raise frequencyDictionary topX default from 1000 to 10000
* docs: add subtitle style changelog fragment
* docs: update generated config examples
* style: wrap long textShadow strings and add blank line in CSS
- Ignore markFailure calls while an item is still within its retry backoff window
- Prevent enqueue from re-adding keys already in the dead-letter queue
- Add `launchAppBackgroundDetached` that spawns with `--start --background` and `SUBMINER_BACKGROUND_CHILD=1`
- On darwin with empty appArgs, use detached background launch instead of inherited process
- Add `extraEnv` param to `launchAppCommandDetached` for env injection
- Inject deps into `runAppPassthroughCommand` for testability
- Bump vendor/subminer-yomitan submodule
* fix(jellyfin): show overlay, inject plugin, and fix stats title on playb
- Show visible overlay automatically during Jellyfin playback so subtitleStyle applies
- Inject bundled mpv plugin on auto-launch so keybindings work without overlay focus
- Group Jellyfin playback stats under item metadata (jellyfin://host/item/id) instead of stream URLs so episodes merge with matching local titles
- Mark ffsubsync unavailable in subsync modal for remote media paths
- Drain queued second-instance commands even when onReady throws
* fix(overlay): stabilize macOS focus handoff and sidebar Yomitan pause
- Keep overlay visible during macOS foreground probe after overlay blur
- Hold sidebar hover-pause while a Yomitan lookup popup remains open
* fix(jellyfin): fix discovery loop, device identity, tray state, and Disc
- Derive device identity from OS hostname; remove legacy configurable client/device fields
- Prevent discovery playback from reloading active item, misreporting pause state, and duplicate overlay restores
- Restart stale tray discovery sessions without re-login when server drops SubMiner cast target
- Sync tray discovery checkbox state on Linux after CLI/startup/remote-session changes
- Stop Discord presence falling back to stream URLs; prime title before tokenized stream loads
- Fix picker library discovery when log level is above info
- Fix config.example.jsonc trailing commas and array formatting
* docs(release): trim and consolidate prerelease notes for 0.15.0
- Remove breaking changes section and several redundant bullet points
- Consolidate per-platform updater notes into a single entry
- Normalize em-dash separators to hyphens in section headers
* fix(config): remove trailing commas from config.example.jsonc
- Strip trailing commas throughout both config.example.jsonc copies
- Reformat inline arrays to multi-line for JSON strictness
- Update Jellyfin subtitle preload and playback launch tests and impl
* fix(tokenizer): preserve known-word highlight when POS filters suppress
- Known-word cache matches now set isKnown=true even for tokens excluded by POS filters
- POS exclusion gate suppresses N+1, frequency, and JLPT only; known status is computed before the gate
- Jellyfin subtitle preload continues after cleanup failures instead of aborting
- Update config docs and option description to document the known-word bypass behavior
* fix(jellyfin): send explicit hide/show overlay instead of toggle
- Track overlay visibility in plugin state; y-t uses explicit hide/show commands when state is known
- Prevent paused Jellyfin playback from resuming on overlay hide
- Fix subtitle cache cleanup to only remove dirs after successful cleanup
* fix(jellyfin): fix remote progress sync, seek reporting, and startup sto
- arm active playback before loadfile with loadedMediaPath: null to suppress premature stop events
- force immediate progress report on seek-like position jumps at the mpv time-pos level
- send positionTicks and failed=false in reportStopped payload
- remove EventName from HTTP timeline payloads (websocket-only field)
- add startup grace window to drop stop events before media finishes loading
* fix(jellyfin): fix overlay toggle sync, redirect reload, and AppImage bi
- Sync visible-overlay state back to plugin via script messages to avoid toggle/hide drift
- Collapse duplicate toggle events within 250ms to prevent hide-then-show on single keypress
- Preserve manual hide across Jellyfin path-changing redirects even when media-title drops
- Rearm managed subtitle defaults on path-changing redirects
- Route toggleVisibleOverlay session binding through plugin toggle instead of app-side IPC
- Show Linux/Hyprland overlay passively (showInactive) to avoid stealing mpv keyboard focus
- Fix AppImage binary resolution to prefer $APPIMAGE env over mounted inner binary
- Add stats window layer management so delete/update dialogs appear above stats window
- Fix Jellyfin remote progress sync during Linux websocket reconnect windows
* Fix CodeRabbit review feedback
* fix(jellyfin): subtitle timing, resume progress, and overlay sync
- Add per-stream subtitle delay persistence and auto timeline-offset correction
- Strip server-selected subtitle stream from mpv load URL; suppress plugin subtitle rearm and auto-start during app-managed preload
- Fix resume position lost when mpv resets on stop; use last known position for final progress/stopped reports
- Keep Play vs Resume distinct to avoid early seek race on normal play
- Fix discovery resume when remote play sends StartPositionTicks=0 despite saved progress
- Deduplicate show/hide overlay commands using recorded visibility state
- Rewrite docs-site Jellyfin page around cast-to-device UX
* test: update lifecycle cleanup assertion
* fix: clear aborted playback state, fix overlay passthrough, and guard du
- Reset app_managed_playback_pending on lifecycle cleanup to prevent state leak into next item
- Record visible overlay action only after command succeeds, not before
- Non-native passive overlay now always click-through on re-show (fix isNonNativePassiveOverlay ordering)
- Defer activeParsedSubtitleMediaPath assignment until after prefetch completes
- Move autoplay gate release into the hide branch of toggleVisibleOverlay
- Clear active Jellyfin playback when stopping media that never loaded
- Reset managed subtitle delay and delay key when no external tracks are available
- Await async removeDir in subtitle cache cleanup
- Guard duplicate delete clicks in MediaDetailView and SessionsTab with refs
- Escape key in DeleteConfirmDialog now calls stopPropagation and stopImmediatePropagation
Cross-check every config key, shortcut, default, and command against the
current source and fix the drift (mpv.socketPath, auto_start_overlay
default, AniSkip TAB key, JLPT N4 color, secondary-sub font/defaults,
secondary-sub language behavior, modular mpv plugin layout, and more).
Add plain-language intros and first-use definitions across onboarding and
integration pages so non-technical readers can follow along.
Internal docs/: fix stale module paths in architecture/domains.md, add
missing contract entry points and catalog rows, and bump verified dates.
Remove the obsolete docs/plans/ directory (its only plan shipped in
0.15.0) and reframe planning.md so plans live with the work, not in docs/.
Add ankiConnect.deck, jimaku.apiKey, and jimaku.apiKeyCommand to the
defaults so they appear in the generated config.example.jsonc, and
change the static/animated image maxima (imageMaxWidth, imageMaxHeight,
animatedMaxHeight) from undefined to 0 so they render too. The resize
paths already treat 0 as "no limit", so this is behavior-neutral and
just improves discoverability of these previously-undocumented keys.
- Exits early with `SubMiner <version>` output, no app binary required
- Maps `-v` at root level without conflicting with `stats cleanup -v`
- Adds `version: boolean` to `Args` type and default args
- Documents flag in docs-site and adds changelog fragment
CI runners don't have Claude Code installed, so the regen step in the
prerelease workflow died on 'claude CLI not found'. Mirror the stable
release model: generate prerelease-notes.md locally (claude -p), commit
it, and have CI just verify and reference the committed file.