From 9b269296fe565c6a6590a1ab01ac05fefcd567ee Mon Sep 17 00:00:00 2001 From: viown <48097677+viown@users.noreply.github.com> Date: Sat, 19 Oct 2024 20:08:27 +0300 Subject: [PATCH] Use UpNextDialog for outro segments --- .../playback/constants/playerEvent.ts | 1 + .../playback/utils/mediaSegmentManager.ts | 2 +- .../playback/utils/playbackSubscriber.ts | 3 +++ src/components/playback/playbackmanager.js | 6 ++++-- src/components/playback/skipsegment.ts | 21 +++++++++---------- src/controllers/playback/video/index.js | 18 +++++++++++++--- src/strings/en-us.json | 1 - 7 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/apps/stable/features/playback/constants/playerEvent.ts b/src/apps/stable/features/playback/constants/playerEvent.ts index c2364753831..ad9d558a139 100644 --- a/src/apps/stable/features/playback/constants/playerEvent.ts +++ b/src/apps/stable/features/playback/constants/playerEvent.ts @@ -14,6 +14,7 @@ export enum PlayerEvent { PlaylistItemAdd = 'playlistitemadd', PlaylistItemMove = 'playlistitemmove', PlaylistItemRemove = 'playlistitemremove', + PromptSkip = 'promptskip', RepeatModeChange = 'repeatmodechange', ShuffleModeChange = 'shufflequeuemodechange', Stopped = 'stopped', diff --git a/src/apps/stable/features/playback/utils/mediaSegmentManager.ts b/src/apps/stable/features/playback/utils/mediaSegmentManager.ts index faf75f9c7f8..6a79838aa8c 100644 --- a/src/apps/stable/features/playback/utils/mediaSegmentManager.ts +++ b/src/apps/stable/features/playback/utils/mediaSegmentManager.ts @@ -62,7 +62,7 @@ class MediaSegmentManager extends PlaybackSubscriber { promptToSkip(mediaSegment: MediaSegmentDto) { if (mediaSegment.StartTicks && mediaSegment.EndTicks && mediaSegment.EndTicks - mediaSegment.StartTicks < TICKS_PER_SECOND * 3) { - console.info('[MediaSegmentManager] ignoring skipping segment with duration <3s', mediaSegment); + console.info('[MediaSegmentManager] ignoring segment prompt with duration <3s', mediaSegment); this.isLastSegmentIgnored = true; return; } diff --git a/src/apps/stable/features/playback/utils/playbackSubscriber.ts b/src/apps/stable/features/playback/utils/playbackSubscriber.ts index d492469f715..ccbbfb2c003 100644 --- a/src/apps/stable/features/playback/utils/playbackSubscriber.ts +++ b/src/apps/stable/features/playback/utils/playbackSubscriber.ts @@ -11,6 +11,7 @@ import Events, { type Event } from 'utils/events'; import { PlaybackManagerEvent } from '../constants/playbackManagerEvent'; import { PlayerEvent } from '../constants/playerEvent'; import type { ManagedPlayerStopInfo, MovedItem, PlayerError, PlayerErrorCode, PlayerStopInfo, RemovedItems } from '../types/callbacks'; +import { MediaSegmentDto } from '@jellyfin/sdk/lib/generated-client'; export interface PlaybackSubscriber { onPlaybackCancelled?(e: Event): void @@ -18,6 +19,7 @@ export interface PlaybackSubscriber { onPlaybackStart?(e: Event, player: Plugin, state: PlayerState): void onPlaybackStop?(e: Event, info: PlaybackStopInfo): void onPlayerChange?(e: Event, player: Plugin, target: PlayTarget, previousPlayer: Plugin): void + onPromptSkip?(e: Event, mediaSegment: MediaSegmentDto): void onPlayerError?(e: Event, error: PlayerError): void onPlayerFullscreenChange?(e: Event): void onPlayerItemStarted?(e: Event, item?: BaseItemDto, mediaSource?: MediaSourceInfo): void @@ -62,6 +64,7 @@ export abstract class PlaybackSubscriber { [PlayerEvent.PlaylistItemAdd]: this.onPlayerPlaylistItemAdd?.bind(this), [PlayerEvent.PlaylistItemMove]: this.onPlayerPlaylistItemMove?.bind(this), [PlayerEvent.PlaylistItemRemove]: this.onPlayerPlaylistItemRemove?.bind(this), + [PlayerEvent.PromptSkip]: this.onPromptSkip?.bind(this), [PlayerEvent.RepeatModeChange]: this.onPlayerRepeatModeChange?.bind(this), [PlayerEvent.ShuffleModeChange]: this.onPlayerShuffleModeChange?.bind(this), [PlayerEvent.Stopped]: this.onPlayerStopped?.bind(this), diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index a7a5ca4bb9d..35001ad9da1 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -935,9 +935,11 @@ export class PlaybackManager { return Promise.resolve(self._playQueueManager.getPlaylist()); }; - self.promptToSkip = function (mediaSegment) { + self.promptToSkip = function (mediaSegment, player) { + player = player || self._currentPlayer; + if (mediaSegment && this._skipSegment) { - this._skipSegment.onPromptSkip(mediaSegment); + Events.trigger(player, 'promptskip', [mediaSegment]); } }; diff --git a/src/components/playback/skipsegment.ts b/src/components/playback/skipsegment.ts index 10d9e32248e..9169e81b8c0 100644 --- a/src/components/playback/skipsegment.ts +++ b/src/components/playback/skipsegment.ts @@ -56,16 +56,7 @@ class SkipSegment extends PlaybackSubscriber { setButtonText() { if (this.skipElement && this.currentSegment) { - if (this.player && this.currentSegment.EndTicks - && this.currentSegment.Type === MediaSegmentType.Outro - && this.currentSegment.EndTicks >= this.playbackManager.currentItem(this.player).RunTimeTicks - && this.playbackManager.getNextItem() - ) { - // Display "Next Episode" if it's an outro segment, exceeds or is equal to the runtime, and if there is a next track. - this.skipElement.innerHTML += globalize.translate('MediaSegmentNextEpisode'); - } else { - this.skipElement.innerHTML = globalize.translate('MediaSegmentSkipPrompt', globalize.translate(`MediaSegmentType.${this.currentSegment.Type}`)); - } + this.skipElement.innerHTML = globalize.translate('MediaSegmentSkipPrompt', globalize.translate(`MediaSegmentType.${this.currentSegment.Type}`)); this.skipElement.innerHTML += ''; } } @@ -132,7 +123,15 @@ class SkipSegment extends PlaybackSubscriber { } } - onPromptSkip(segment: MediaSegmentDto) { + onPromptSkip(e: Event, segment: MediaSegmentDto) { + if (this.player && segment.EndTicks != null + && segment.Type === MediaSegmentType.Outro + && segment.EndTicks >= this.playbackManager.currentItem(this.player).RunTimeTicks + && this.playbackManager.getNextItem() + ) { + // Don't display button when UpNextDialog is expected. + return; + } if (!this.currentSegment) { this.currentSegment = segment; diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js index 779b68f9f60..fb7cad1f9a7 100644 --- a/src/controllers/playback/video/index.js +++ b/src/controllers/playback/video/index.js @@ -29,9 +29,8 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components import { pluginManager } from '../../../components/pluginManager'; import { PluginType } from '../../../types/plugin.ts'; import { EventType } from 'types/eventType'; - -const TICKS_PER_MINUTE = 600000000; -const TICKS_PER_SECOND = 10000000; +import { MediaSegmentType } from '@jellyfin/sdk/lib/generated-client'; +import { TICKS_PER_MINUTE, TICKS_PER_SECOND } from 'constants/time'; function getOpenedDialog() { return document.querySelector('.dialogContainer .dialog.opened'); @@ -579,6 +578,7 @@ export default function (view) { }, state); Events.on(player, 'playbackstart', onPlaybackStart); Events.on(player, 'playbackstop', onPlaybackStopped); + Events.on(player, 'promptskip', onPromptSkip); Events.on(player, 'volumechange', onVolumeChanged); Events.on(player, 'pause', onPlayPauseStateChanged); Events.on(player, 'unpause', onPlayPauseStateChanged); @@ -603,6 +603,7 @@ export default function (view) { if (player) { Events.off(player, 'playbackstart', onPlaybackStart); Events.off(player, 'playbackstop', onPlaybackStopped); + Events.off(player, 'promptskip', onPromptSkip); Events.off(player, 'volumechange', onVolumeChanged); Events.off(player, 'pause', onPlayPauseStateChanged); Events.off(player, 'unpause', onPlayPauseStateChanged); @@ -631,6 +632,17 @@ export default function (view) { } } + function onPromptSkip(e, mediaSegment) { + const player = this; + if (mediaSegment && player && mediaSegment.EndTicks != null + && mediaSegment.Type === MediaSegmentType.Outro + && mediaSegment.EndTicks >= playbackManager.duration(player) + && playbackManager.getNextItem() + ) { + showComingUpNext(player); + } + } + function showComingUpNextIfNeeded(player, currentItem, currentTimeTicks, runtimeTicks) { if (runtimeTicks && currentTimeTicks && !comingUpNextDisplayed && !currentVisibleMenu && currentItem.Type === 'Episode' && userSettings.enableNextVideoInfoOverlay()) { let showAtSecondsLeft = 30; diff --git a/src/strings/en-us.json b/src/strings/en-us.json index d06e7797710..c58225bc238 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -1074,7 +1074,6 @@ "MediaSegmentAction.None": "None", "MediaSegmentAction.AskToSkip": "Ask To Skip", "MediaSegmentAction.Skip": "Skip", - "MediaSegmentNextEpisode": "Next Episode", "MediaSegmentSkipPrompt": "Skip {0}", "MediaSegmentType.Commercial": "Commercial", "MediaSegmentType.Intro": "Intro",