TRACES: | DR-204
484 ungated `console.*` calls across 63 non-test frontend files shipped to
end users with no way to turn them off. Mechanical substitution, no control
flow, error handling or message semantics changed:
console.log / console.debug -> log.debug
console.info -> log.info
console.warn -> log.warn
console.error -> log.error
Hand-written `"[Scope] …"` prefixes are dropped where the logger's scope
now carries them; scope names that already existed are preserved verbatim
(`[Auth]`, `[VideoPlayer]`, `[PiP]`, …) and inferred from the filename
where a file had none. `src/routes/player/[id]/+page.svelte` keeps its
`NextEpisode` and `AutoPlay` sub-scopes as separate loggers rather than
flattening them into the page scope.
`grep -rn 'console\.' src/` now matches nothing outside the tests and the
facade itself.
Rust: PlayerMediaItem and MergedMediaItem gain image_id (dual-carry),
populated from primary_image_tag at every construction/conversion site.
Regenerated bindings.
Frontend: all catalog + player + merged readers now use imageId. The
NowPlayingItem->MediaItem bridge (player.ts) properly maps the remote
session's Jellyfin fields (Type, runTimeTicks, primaryImageTag) onto the
neutral kind/durationMs/imageId. Types that are genuinely out of scope
(Person, NowPlayingItem, PlayItemRequest) keep primaryImageTag.
Rust 456, frontend 644, check clean.
Playback reporting (position sync / resume-on-another-device):
- player_configure_jellyfin now builds a PlaybackReporter sharing the player
controller's Arc, so Start/Progress/Stopped actually reach Jellyfin on every
auth path (login/restore/reauth); previously they never did.
- The PlaybackReporterWrapper now shares the same Arc the controller and MPV
progress loop report through, instead of a dead parallel Option.
- Android position callbacks now emit throttled progress reports (30s/item),
mirroring the MPV backend.
Duration flash on pause:
- resolveDuration() prefers the live store duration for the already-loaded
track over the runTimeTicks estimate, so pausing no longer clobbers the
slider's max to 0 when runTimeTicks is missing.
Video leaking into audio mini player:
- isVideoItem() also checks the backend PlayerMediaItem mediaType
discriminator, so a video started via player_play_item (no Jellyfin `type`,
mediaType "video") no longer surfaces in the audio mini player.
Middle-truncation of long media names:
- New truncateMiddle util applied to track/episode/card/mini-player titles so
distinguishing tails (episode numbers, suffixes) stay visible.
Adds regression tests for the duration and mini-player fixes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the remaining ~155 untyped invoke() calls across stores, services,
components, and routes with the generated commands.* wrappers from
$lib/api/bindings, so every IPC call is compile-time-checked against the
command signatures.
- Register repository_get_subtitle_url and repository_get_video_download_url
in specta_builder() and the invoke_handler; regenerate bindings.ts.
- Source duplicated wire types (AutoplaySettings, CacheConfig, Session,
ConnectivityStatus, audio/video settings, etc.) from bindings.
- Fix two bugs surfaced by the typed wrappers:
- VideoDownloadButton passed an un-awaited Promise as the stream URL.
- setAutoplaySettings omitted the required userId argument.
- Update unit tests asserting the old invoke(name, args) shape.
- Remove the five param-naming guard tests; the compiler and codegen now
enforce what they checked.
svelte-check: 0 errors. vitest: green. cargo test --lib: green.