mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-13 12:36:15 -08:00
fix(portals): keep the playing row when the refined year rejects it
Follow-on from keeping the session across a rediscovery. The rerun can legitimately drop the row that is playing: enrichment supplies the release year, and the year gate then rejects a copy the yearless search had admitted — "Dune" 1984 while the user is watching the 2021 film. Off the list is right; it is not the same film. Off the screen is not. It is what is streaming, so it stays as a row and keeps the playing badge, rather than letting the caption name a playlist that is not sending any bytes. Also covers the new session key directly in the identity spec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
93caa1c5a6
commit
6cce35274a
4 files changed
+66
-7
No files matched your search
@@ -144,6 +144,13 @@ actually streaming, and hand failover a clean slate for sources it has already
|
||||
spent. Only a different film resets — including the tried set, which is what
|
||||
makes failover terminate.
|
||||
|
||||
A rerun can also legitimately *drop* the playing row: the year the enrichment
|
||||
supplies makes the year gate reject a copy the yearless search had admitted
|
||||
("Dune" 1984 while watching the 2021 film). Off the list is right — it is not
|
||||
the same film. Off the screen is not, so `applyDiscoveredSources` keeps it as a
|
||||
row and leaves it active; a caption naming a playlist that is not streaming
|
||||
anything would be a lie about the one thing this feature exists to state.
|
||||
|
||||
## The candidate window
|
||||
|
||||
Both queries take a bounded number of rows, so what fills that window decides
|
||||
|
||||
@@ -156,6 +156,20 @@ describe('VodMultiSourceHostService — session lifecycle', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps the playing row when the refined year rejects it', async () => {
|
||||
await loadMovie([ALT_TWO]);
|
||||
await expect(service.play(ALT_TWO.id)).resolves.toBe(true);
|
||||
|
||||
// Enrichment supplies the release year, and the year gate now rejects
|
||||
// the copy the yearless search had admitted. Off the LIST is right —
|
||||
// it is a different film. Off the SCREEN is not: it is the one
|
||||
// streaming, and the caption must not name a playlist that is not.
|
||||
await loadMovie([], { ...MOVIE_A, year: 2021 });
|
||||
|
||||
expect(rowFor(ALT_TWO.id)?.isActive).toBe(true);
|
||||
expect(rowFor(CURRENT_A_ID)?.isActive).toBe(false);
|
||||
});
|
||||
|
||||
it('resets the failover session when a new movie loads', async () => {
|
||||
await loadMovie([ALT_TWO]);
|
||||
vodAutoFailover.set(true);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
resolveVodMultiSourceMovie,
|
||||
vodMultiSourceMovieKey,
|
||||
vodMultiSourceSessionKey,
|
||||
type VodMultiSourceMovie,
|
||||
} from './vod-multi-source-identity';
|
||||
|
||||
@@ -106,3 +107,26 @@ describe('vodMultiSourceMovieKey', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('vodMultiSourceSessionKey', () => {
|
||||
it('ignores everything enrichment can change', () => {
|
||||
// The whole point of the second key: the movie key SHOULD react to a
|
||||
// year and a TMDB id arriving, so discovery reruns — but that rerun
|
||||
// must not be mistaken for a different film and reset the session
|
||||
// out from under the source that is playing.
|
||||
expect(
|
||||
vodMultiSourceSessionKey(
|
||||
movie({ title: 'Dune (2021)', year: 2021, tmdbId: 438631 })
|
||||
)
|
||||
).toBe(vodMultiSourceSessionKey(movie()));
|
||||
});
|
||||
|
||||
it('separates two movies and two playlists', () => {
|
||||
expect(vodMultiSourceSessionKey(movie({ contentId: 202 }))).not.toBe(
|
||||
vodMultiSourceSessionKey(movie())
|
||||
);
|
||||
expect(
|
||||
vodMultiSourceSessionKey(movie({ playlistId: 'playlist-2' }))
|
||||
).not.toBe(vodMultiSourceSessionKey(movie()));
|
||||
});
|
||||
});
|
||||
@@ -43,17 +43,31 @@ export function applyDiscoveredSources(
|
||||
? controller.findSource(activeId)
|
||||
: null;
|
||||
|
||||
controller.setSources([current, ...discovered], matchKind);
|
||||
|
||||
const playing = switchedTo && controller.findSource(switchedTo.id);
|
||||
if (!playing) {
|
||||
if (!switchedTo) {
|
||||
controller.setSources([current, ...discovered], matchKind);
|
||||
controller.setActiveSource(current.id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Catalog rows only ever carry guesses parsed off the title. Whatever the
|
||||
// resolve turned into facts for the playing source stays fact.
|
||||
controller.updateSource(switchedTo);
|
||||
// The rerun can legitimately drop the playing row: enrichment supplies the
|
||||
// release year, and the year gate then rejects a copy that a yearless
|
||||
// search had admitted ("Dune" 1984 while watching the 2021 film). Dropping
|
||||
// it from the LIST is right — it is not the same film. Dropping it from
|
||||
// the SCREEN is not: it is what the user is watching, so it stays as a row
|
||||
// and keeps the playing badge rather than letting the caption name a
|
||||
// playlist that is not streaming anything.
|
||||
const isDiscovered = discovered.some(
|
||||
(source) => source.id === switchedTo.id
|
||||
);
|
||||
// Catalog rows only ever carry guesses parsed off the title, so the row
|
||||
// that a real resolve turned into facts wins over its rediscovered twin.
|
||||
const sources = isDiscovered
|
||||
? discovered.map((source) =>
|
||||
source.id === switchedTo.id ? switchedTo : source
|
||||
)
|
||||
: [...discovered, switchedTo];
|
||||
|
||||
controller.setSources([current, ...sources], matchKind);
|
||||
controller.setActiveSource(switchedTo.id);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user