mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-12 12:06:16 -08:00
fix(playback): keep MPV/VLC rows of the live tab confirmable by URL
The live tab's session key can only be confirmed by its own inline players; MPV/VLC confirm the launched URL alone. A row that goes to an external player (also later, after a double-click) now defers by URL, and only rows played inline carry the session key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b0467791a4
commit
ba1b7a8d73
3 files changed
+41
-9
No files matched your search
@@ -1149,9 +1149,10 @@ reaches history.
|
||||
- Matching: a write deferred with a session key is confirmed only by that
|
||||
same key — the same URL in two playlists must not let playback in one
|
||||
(inline, or in MPV/VLC) record a failed attempt in the other. Writes
|
||||
without one (portal resolvers, collection tabs) match any confirmation of
|
||||
their stream URL. The global live tab defers with its own
|
||||
playlist-scoped session key, which also survives a switch to catch-up.
|
||||
without one (portal resolvers) match any confirmation of their stream URL.
|
||||
The global live tab defers with its own playlist-scoped session key, which
|
||||
also survives a switch to catch-up, when the row plays inline; a row that
|
||||
goes to MPV/VLC defers by URL, the only thing that launch confirms.
|
||||
- `WebPlayerViewComponent` confirms its `playbackSessionKey`, `streamUrl`
|
||||
and `playback.streamUrl` once the owned engine's reported position has
|
||||
advanced by 2 seconds while playing (`PlaybackProgressConfirmation`).
|
||||
|
||||
+12
-5
@@ -248,13 +248,20 @@ export function createUnifiedLiveSelection(options: {
|
||||
}
|
||||
|
||||
// Selecting a channel is not watching it: the row moves to the
|
||||
// top of Recently Viewed once its stream has really played. The
|
||||
// tab's playlist-scoped session key — the one its players confirm
|
||||
// with — survives a switch to catch-up and does not match the
|
||||
// same URL listed in another playlist.
|
||||
// top of Recently Viewed once its stream has really played. Played
|
||||
// inline, the tab's playlist-scoped session key — the one its
|
||||
// players confirm with — survives a switch to catch-up and does
|
||||
// not match the same URL in another playlist. MPV/VLC can only
|
||||
// confirm the launched URL, so an external row defers by URL.
|
||||
const playsInline = !options.shouldOpenExternalPlayback(
|
||||
detail,
|
||||
true
|
||||
);
|
||||
historyGate.defer(
|
||||
{
|
||||
sessionKey: createUnifiedLivePlaybackSessionKey(item),
|
||||
sessionKey: playsInline
|
||||
? createUnifiedLivePlaybackSessionKey(item)
|
||||
: null,
|
||||
streamUrls: [detail.playback.streamUrl],
|
||||
},
|
||||
() => void recordLivePlayback(item)
|
||||
|
||||
+25
-1
@@ -175,7 +175,8 @@ describe('UnifiedLiveTabComponent fullscreen channel panel', () => {
|
||||
}
|
||||
);
|
||||
|
||||
it('correlates a row with its session key, not its stream URL', async () => {
|
||||
it('correlates an inline row with its session key, not its stream URL', async () => {
|
||||
portalPlayer.isEmbeddedPlayer.mockReturnValue(true);
|
||||
const item = buildM3uLiveItem();
|
||||
streamResolver.resolveM3uPlaybackDetail.mockResolvedValue({
|
||||
epgMode: 'm3u',
|
||||
@@ -206,6 +207,29 @@ describe('UnifiedLiveTabComponent fullscreen channel panel', () => {
|
||||
expect(recentData.recordLivePlayback).toHaveBeenCalledWith(item);
|
||||
});
|
||||
|
||||
it('records a row played in MPV/VLC from the URL its launch confirms', async () => {
|
||||
const item = buildM3uLiveItem();
|
||||
streamResolver.resolveM3uPlaybackDetail.mockResolvedValue({
|
||||
epgMode: 'm3u',
|
||||
playback: { streamUrl: item.streamUrl, title: item.name },
|
||||
epgPrograms: [],
|
||||
});
|
||||
recentData.recordLivePlayback.mockResolvedValue(item);
|
||||
fixture.componentRef.setInput('items', [item]);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
await component.onChannelSelected(component.channelsForList()[0]);
|
||||
expect(portalPlayer.openResolvedPlayback).toHaveBeenCalled();
|
||||
|
||||
// The external session update carries only the launched URL.
|
||||
TestBed.inject(PlaybackHistoryGate).confirm({
|
||||
streamUrls: [item.streamUrl],
|
||||
});
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(recentData.recordLivePlayback).toHaveBeenCalledWith(item);
|
||||
});
|
||||
|
||||
it('moves a row that played to the top of Recently Viewed after another row was selected', async () => {
|
||||
const first = buildM3uLiveItem();
|
||||
const second: UnifiedCollectionItem = {
|
||||
|
||||
Reference in new issue
Block a user