mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Use UpNextDialog for outro segments
This commit is contained in:
parent
7ad7f07b7c
commit
9b269296fe
7 changed files with 34 additions and 18 deletions
|
@ -14,6 +14,7 @@ export enum PlayerEvent {
|
|||
PlaylistItemAdd = 'playlistitemadd',
|
||||
PlaylistItemMove = 'playlistitemmove',
|
||||
PlaylistItemRemove = 'playlistitemremove',
|
||||
PromptSkip = 'promptskip',
|
||||
RepeatModeChange = 'repeatmodechange',
|
||||
ShuffleModeChange = 'shufflequeuemodechange',
|
||||
Stopped = 'stopped',
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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 += '<span class="material-icons skip_next" aria-hidden="true"></span>';
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue