video: fix back-button loop when a 'More Like This' item is owned

Clicking a recommendation/cast/similar link to a title you OWN opens it via a
tmdb URL that redirects to the library detail — but the redirect PUSHED a new
history entry, so Back landed on the tmdb URL which redirected forward again =>
stuck loop + a self-referencing 'Back to <same movie>' label.

The redirect now REPLACES the redirecting entry (keeping its layer + origin)
instead of pushing, so Back unwinds cleanly to where you actually came from.
This commit is contained in:
BoulderBadgeDad 2026-06-15 12:18:05 -07:00
parent 2f3e4b128b
commit 3f439e4277
2 changed files with 12 additions and 3 deletions

View file

@ -917,9 +917,11 @@
}
// An owned title reached via a tmdb URL → bounce to the real library detail.
// _replace so it REPLACES the tmdb history entry (which would redirect again on
// Back) instead of pushing a new layer — otherwise Back loops on the redirect.
function reopen(rd) {
document.dispatchEvent(new CustomEvent('soulsync:video-open-detail',
{ detail: { kind: rd.kind, id: rd.id, source: rd.source || 'library' } }));
{ detail: { kind: rd.kind, id: rd.id, source: rd.source || 'library', _replace: true } }));
}
// Lazy: backfill a movie's cast/genres/art from TMDB on view if missing.

View file

@ -299,12 +299,19 @@
document.addEventListener('soulsync:video-open-detail', function (e) {
var d = e && e.detail; if (!d) return;
// Capture the origin BEFORE navigating away from the current page.
var origin = d._restore ? null : currentOrigin();
var origin = (d._restore || d._replace) ? null : currentOrigin();
if (d.kind === 'movie') navigate('video-movie-detail');
else if (d.kind === 'show') navigate('video-show-detail');
else if (d.kind === 'person') navigate('video-person-detail');
else return;
if (!d._restore) {
if (d._replace) {
// A redirect (e.g. a tmdb link that's actually owned) → replace the
// entry being redirected FROM, keeping its layer + origin, so Back
// doesn't bounce back onto the redirecting URL.
var rstate = { videoDetail: { kind: d.kind, id: d.id, source: d.source || 'library',
layer: _backStack.length } };
try { history.replaceState(rstate, '', buildDetailPath(d.source, d.kind, d.id)); } catch (e2) { /* ignore */ }
} else if (!d._restore) {
_backStack.push(origin);
var state = { videoDetail: { kind: d.kind, id: d.id, source: d.source || 'library',
layer: _backStack.length } };