TV subtitle changes now honor the same transcode guard as the mobile menu
(switching to/from a burned-in image sub re-negotiates the stream instead of a
no-op track change). Menu-listed tracks the player can't select (server-burned
Encode, sidecars never sub-added) fall back to replacePlayer so the server
delivers them. Freshly downloaded local subs move the live index to the local
sentinel before the sub-add so onTracksReady doesn't clobber them. Shares the
external-URL builder and the LOCAL_SUBTITLE_INDEX_START constant.
- Unify external detection: isExternalSubtitle drops the bare-DeliveryUrl case
(an Hls-delivered sub has a DeliveryUrl but isn't sub-add-ed) so sorting,
loading and resolution agree; compareTracksForMenu now uses it.
- applyMpvSubtitleSelection wraps player calls in try/catch — fire-and-forget
call sites no longer risk unhandled rejections.
- VideoContext offline-transcoded branch: treat missing IsTextSubtitleStream as
text (use !isImageBasedSubtitle), matching the shared helper.
- ItemContent.tv refreshSubtitleTracks: apply compareTracksForMenu like the
initial list.
- Tests: use the @/ alias; rework the embedded cases to actually exercise
identity (reversed player order) and the ordinal fallback (same-language,
no title).
The detail-page selector (MediaSourceButton, the #1176 replacement for
TrackSheet) and the TV detail/refresh paths (ItemContent.tv, Controls.tv
refreshSubtitleTracks) still listed subtitles in raw MediaStreams order
(externals first). Apply compareTracksForMenu there too so every menu
matches web. The in-player TV modal was already covered (fed from the
sorted VideoContext tracks).