From b3ead71b7e82574a2db71a5c06eef8db1973f258 Mon Sep 17 00:00:00 2001 From: s8n Date: Sun, 10 May 2026 00:05:16 +0100 Subject: [PATCH] shim: shorten subtitle stream labels in detail dropdowns Stock Jellyfin renders subtitle stream entries as " - - (External|Internal|Embedded)[ - flag]". For ARRFLIX, which has at most one subtitle format per language, the codec and source suffix are noise. Add a small JS shim to web-overrides/index.html that matches that exact shape and collapses the label to "" (with "(Forced)" / "(SDH)" / "(Hearing Impaired)" if those flags are present; "Default" is dropped since it's redundant when there's only one stream of that language). Audio labels like "5.1Ch Surround Sound - English - AAC - Stereo - Default" have a different number of segments and don't match, so they pass through untouched. The shim runs after DOMContentLoaded and re-walks any nodes added later via MutationObserver (covers actionsheet dropdowns that mount lazily). Bracketed by /* SUB-LABEL-SHIM-BEGIN */ and /* SUB-LABEL-SHIM-END */ markers; bin/revert-sub-label-shim.sh deletes between the markers in one sed pass and saves a timestamped backup. No container restart needed (index.html is bind-mounted). --- bin/revert-sub-label-shim.sh | 37 +++++++++++++++++++++++++++++ web-overrides/index.html | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100755 bin/revert-sub-label-shim.sh diff --git a/bin/revert-sub-label-shim.sh b/bin/revert-sub-label-shim.sh new file mode 100755 index 0000000..2c6a429 --- /dev/null +++ b/bin/revert-sub-label-shim.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +# Revert the SUB-LABEL-SHIM injected into web-overrides/index.html on 2026-05-10. +# +# What it removes: +# /* SUB-LABEL-SHIM-BEGIN ... */ ... /* SUB-LABEL-SHIM-END */ +# +# Idempotent: safe to re-run. +# After reverting, hard-refresh the browser (Ctrl+Shift+R) so the cached +# index.html is fetched fresh. + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +TARGET="$REPO_ROOT/web-overrides/index.html" + +if [[ ! -f "$TARGET" ]]; then + echo "ERROR: $TARGET not found" >&2 + exit 1 +fi + +if ! grep -q "SUB-LABEL-SHIM-BEGIN" "$TARGET"; then + echo "shim already absent — nothing to do" + exit 0 +fi + +cp "$TARGET" "$TARGET.bak.$(date -u +%Y%m%dT%H%M%SZ)" + +# delete from BEGIN marker line through END marker line, inclusive +sed -i '/SUB-LABEL-SHIM-BEGIN/,/SUB-LABEL-SHIM-END/d' "$TARGET" + +if grep -q "SUB-LABEL-SHIM" "$TARGET"; then + echo "ERROR: revert left orphan markers in $TARGET" >&2 + exit 2 +fi + +echo "reverted. backup at $TARGET.bak.*" +echo "next: container needs no restart (index.html is bind-mounted); hard-refresh browser." diff --git a/web-overrides/index.html b/web-overrides/index.html index c312af2..c3d0e23 100644 --- a/web-overrides/index.html +++ b/web-overrides/index.html @@ -242,6 +242,52 @@ label[for="language"] { } catch(e){} } })(); + +/* SUB-LABEL-SHIM-BEGIN — 2026-05-10 + Shorten subtitle stream labels in detail-page dropdowns. + Stock Jellyfin renders e.g. "English - SUBRIP - External"; ARRFLIX library + has one format per language so the codec/source suffix is noise. Match + " - - (External|Internal|Embedded)[ - flag]" exactly and + collapse to "" (or " (Forced)"/" (SDH)" if flagged). + Audio labels like "5.1Ch Surround Sound - English - AAC - Stereo - Default" + have a different shape (more segments) so they stay untouched. + Revert: bin/revert-sub-label-shim.sh deletes between BEGIN/END markers. */ +(function(){ + var SUB_RE = /^([A-Za-z][A-Za-z\s'-]+?) - ([A-Z][A-Z0-9_]+) - (External|Internal|Embedded)( - (Default|Forced|SDH|Hearing Impaired))?$/; + function shorten(s){ + var m = s.match(SUB_RE); + if(!m) return null; + var flag = m[5]; + if(!flag || flag === 'Default') return m[1]; + return m[1] + ' (' + flag + ')'; + } + function walk(root){ + if(!root || !root.nodeType) return; + var w = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null); + var n, batch = []; + while((n = w.nextNode())) batch.push(n); + batch.forEach(function(t){ + var s = t.nodeValue; + if(!s || s.length < 12 || s.length > 96) return; + var trimmed = s.trim(); + var rep = shorten(trimmed); + if(rep && rep !== trimmed) t.nodeValue = s.replace(trimmed, rep); + }); + } + function init(){ + walk(document.body); + if(window.MutationObserver){ + new MutationObserver(function(muts){ + muts.forEach(function(m){ + m.addedNodes.forEach(function(node){ if(node.nodeType === 1) walk(node); }); + }); + }).observe(document.body, { childList:true, subtree:true }); + } + } + if(document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); + else init(); +})(); +/* SUB-LABEL-SHIM-END */ /* ARRFLIX-SHIM-END */ARRFLIX