From 2ac1f1f704d44e2b20f9598044f7e266ffae4d36 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Tue, 8 Sep 2026 02:17:00 +0200 Subject: fix(hub): stop badging every poster "unmatched" when TMDB is off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dashed warning outline and the "?" flag say a TMDB lookup ran and came back with nothing — that is how an operator finds the titles worth a "Fix match". With TMDB switched off for the group no lookup is made at all: media_meta_req answers confidence 0 for the whole library by design, so the poster grid drew every card as a failure of the very thing the operator chose, with no poster ever coming to clear it. Poster mode now shows the file's own thumbnail plainly in that case, the same as Flat does, and keeps the badge for what it was built for. - PosterCard takes tmdbEnabled and gates both the outline and the "?" on `tmdbEnabled && !confident`. The title still falls back to the parsed filename exactly as before, and the ready/imageReady anti-flash gating is untouched. - VideoDetailModal gates its "no confident match" paragraph the same way. A show still opens that modal with TMDB off — it is where the season list lives — so the card alone would have left the claim one click deeper. - Its operator-only "Fix match" / "Rematch" buttons are gated too: both act on a match that does not exist, one opening a search the node answers empty, the other dropping a cached match never made. Those buttons are the only entry points to TmdbSearchOverlay and doRematch. - Both props default to true, so a call site that forgets one keeps the badge rather than silently losing it. search-page.js is deliberately left passing `enabled: true`: a cross-group view has no single group's switch to read, and it never showed the operator buttons anyway (isNodeAdmin={false}). Recorded as §10.7 in docs/mediacenter.md. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01V8EDjk6pkYZrCbo63m2x87 --- .../src/meshbay_hub/static/video-app.js | 37 ++++++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'packages/meshbay-hub') diff --git a/packages/meshbay-hub/src/meshbay_hub/static/video-app.js b/packages/meshbay-hub/src/meshbay_hub/static/video-app.js index 57da9ff..f590d20 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/video-app.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/video-app.js @@ -321,7 +321,7 @@ function useSeasonMeta(transportRef, tmdbId, season, active) { function PosterCard({ title, subtitle, repEntry, transportRef, gekRef, onOpen, groupKey, onMetaResolved, onNeedConn, - sourceEntries, + sourceEntries, tmdbEnabled = true, }) { const tRef = repEntry._tRef || transportRef; const gRef = repEntry._gRef || gekRef; @@ -341,6 +341,16 @@ function PosterCard({ const confident = Boolean(meta && meta.confidence && meta.tmdb_id); const metaReady = meta !== null; + // "Unmatched" is a statement about a lookup that ran and came back with + // nothing — it tells an operator which titles are worth a "Fix match". + // With TMDB switched off for this group no lookup was ever made, so every + // card would carry the dashed outline and the "?" at once, flagging as a + // failure exactly the thing the operator chose. The poster grid then just + // shows what it does have — the file's own frame, presented plainly, the + // same as Flat does. Defaults to `true` so a caller that forgets the prop + // keeps the badge rather than silently losing it. + const flagUnmatched = tmdbEnabled && !confident; + // Reports this tile's own resolution upward so PosterGrid can notice two // differently-parsed folders (a show split across release groups that // named its seasons inconsistently, §3.4/V6) resolving to the same TMDB @@ -382,7 +392,7 @@ function PosterCard({ const ready = metaReady && imageReady; return html` -
+
${!ready && html`
`} @@ -398,7 +408,7 @@ function PosterCard({
${(confident && meta.title) || title} - ${!confident && html`?`} + ${flagUnmatched && html`?`}
${confident && meta.release_date ? yearOf(meta.release_date) : ''} @@ -690,6 +700,7 @@ function TmdbSearchOverlay({ function VideoDetailModal({ title, meta, repEntry, show, transportRef, gekRef, onClose, onPlay, isNodeAdmin, + tmdbEnabled = true, }) { const confident = Boolean(meta && meta.confidence && meta.tmdb_id); const [searching, setSearching] = useState(false); @@ -743,7 +754,12 @@ function VideoDetailModal({ <${Icon} name="close" />
- ${meta !== null && !confident && html` + ${/* Same reason as PosterCard's flagUnmatched: with TMDB off for + this group nothing was looked up, so "no confident match" is + not a fact about this title. A show still opens this modal + with TMDB off — it is where its season list lives — so the + notice has to be suppressed here too, not only on the card. */''} + ${tmdbEnabled && meta !== null && !confident && html`

${t('video.no_match')}

`}

@@ -760,7 +776,13 @@ function VideoDetailModal({

`} `} - ${isNodeAdmin && html` + ${/* Both of these act on a TMDB match, and with TMDB off for this + group there is none to act on: "Fix match" opens a search the + node answers with an empty result list (§5.7's silent + degradation), and "Rematch" drops a cached match that was + never made. Two buttons that cannot do anything, offered to + the one person who already knows why. */''} + ${isNodeAdmin && tmdbEnabled && html`