2020-08-14 08:46:34 +02:00
|
|
|
import dom from '../../scripts/dom';
|
2020-08-16 20:24:45 +02:00
|
|
|
import { playbackManager } from '../playback/playbackmanager';
|
2020-09-08 02:05:02 -04:00
|
|
|
import { Events } from 'jellyfin-apiclient';
|
2020-08-14 08:46:34 +02:00
|
|
|
import mediaInfo from '../mediainfo/mediainfo';
|
|
|
|
import layoutManager from '../layoutManager';
|
|
|
|
import focusManager from '../focusManager';
|
|
|
|
import globalize from '../../scripts/globalize';
|
|
|
|
import itemHelper from '../itemHelper';
|
2021-01-26 16:25:38 -05:00
|
|
|
import './upnextdialog.scss';
|
2020-08-14 08:46:34 +02:00
|
|
|
import '../../elements/emby-button/emby-button';
|
2020-11-06 00:00:34 +00:00
|
|
|
import '../../assets/css/flexstyles.scss';
|
2020-07-27 10:26:09 +01:00
|
|
|
|
|
|
|
/* eslint-disable indent */
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-27 10:30:24 +01:00
|
|
|
const transitionEndEventName = dom.whichTransitionEvent();
|
2018-10-23 01:05:09 +03:00
|
|
|
|
|
|
|
function getHtml() {
|
2020-07-27 10:30:24 +01:00
|
|
|
let html = '';
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
html += '<div class="flex flex-direction-column flex-grow">';
|
|
|
|
|
|
|
|
html += '<h2 class="upNextDialog-nextVideoText" style="margin:.25em 0;"> </h2>';
|
|
|
|
|
|
|
|
html += '<h3 class="upNextDialog-title" style="margin:.25em 0 .5em;"></h3>';
|
|
|
|
|
|
|
|
html += '<div class="flex flex-direction-row upNextDialog-mediainfo">';
|
|
|
|
html += '</div>';
|
|
|
|
|
|
|
|
html += '<div class="flex flex-direction-row upNextDialog-buttons" style="margin-top:1em;">';
|
|
|
|
|
|
|
|
html += '<button type="button" is="emby-button" class="raised raised-mini btnStartNow upNextDialog-button">';
|
2019-02-03 02:41:16 +09:00
|
|
|
html += globalize.translate('HeaderStartNow');
|
2019-01-10 15:39:37 +03:00
|
|
|
html += '</button>';
|
|
|
|
|
|
|
|
html += '<button type="button" is="emby-button" class="raised raised-mini btnHide upNextDialog-button">';
|
2019-02-03 02:41:16 +09:00
|
|
|
html += globalize.translate('Hide');
|
2019-01-10 15:39:37 +03:00
|
|
|
html += '</button>';
|
|
|
|
|
|
|
|
// buttons
|
|
|
|
html += '</div>';
|
|
|
|
|
|
|
|
// main
|
|
|
|
html += '</div>';
|
|
|
|
|
|
|
|
return html;
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function setNextVideoText() {
|
2020-07-27 10:30:24 +01:00
|
|
|
const instance = this;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-27 10:30:24 +01:00
|
|
|
const elem = instance.options.parent;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-27 10:30:24 +01:00
|
|
|
const secondsRemaining = Math.max(Math.round(getTimeRemainingMs(instance) / 1000), 0);
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-02-16 03:44:43 +01:00
|
|
|
console.debug('up next seconds remaining: ' + secondsRemaining);
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-27 10:30:24 +01:00
|
|
|
const timeText = '<span class="upNextDialog-countdownText">' + globalize.translate('HeaderSecondsValue', secondsRemaining) + '</span>';
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-27 10:30:24 +01:00
|
|
|
const nextVideoText = instance.itemType === 'Episode' ?
|
2019-02-03 02:41:16 +09:00
|
|
|
globalize.translate('HeaderNextEpisodePlayingInValue', timeText) :
|
|
|
|
globalize.translate('HeaderNextVideoPlayingInValue', timeText);
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
elem.querySelector('.upNextDialog-nextVideoText').innerHTML = nextVideoText;
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function fillItem(item) {
|
2020-07-27 10:30:24 +01:00
|
|
|
const instance = this;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-27 10:30:24 +01:00
|
|
|
const elem = instance.options.parent;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
elem.querySelector('.upNextDialog-mediainfo').innerHTML = mediaInfo.getPrimaryMediaInfoHtml(item, {
|
2020-08-20 20:39:33 +02:00
|
|
|
criticRating: false,
|
|
|
|
originalAirDate: false,
|
|
|
|
starRating: false,
|
|
|
|
subtitles: false
|
2019-01-10 15:39:37 +03:00
|
|
|
});
|
|
|
|
|
2020-07-27 10:30:24 +01:00
|
|
|
let title = itemHelper.getDisplayName(item);
|
2019-01-10 15:39:37 +03:00
|
|
|
if (item.SeriesName) {
|
|
|
|
title = item.SeriesName + ' - ' + title;
|
|
|
|
}
|
|
|
|
|
2022-01-30 00:27:26 +03:00
|
|
|
elem.querySelector('.upNextDialog-title').innerText = title || '';
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
instance.itemType = item.Type;
|
|
|
|
|
|
|
|
instance.show();
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function clearCountdownTextTimeout(instance) {
|
2019-01-10 15:39:37 +03:00
|
|
|
if (instance._countdownTextTimeout) {
|
|
|
|
clearInterval(instance._countdownTextTimeout);
|
|
|
|
instance._countdownTextTimeout = null;
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2021-04-07 22:36:22 -04:00
|
|
|
async function onStartNowClick() {
|
2020-07-27 10:30:24 +01:00
|
|
|
const options = this.options;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2018-10-23 01:05:09 +03:00
|
|
|
if (options) {
|
2020-07-27 10:30:24 +01:00
|
|
|
const player = options.player;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2021-04-07 22:36:22 -04:00
|
|
|
await this.hide();
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
playbackManager.nextTrack(player);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function init(instance, options) {
|
2019-01-10 15:39:37 +03:00
|
|
|
options.parent.innerHTML = getHtml();
|
|
|
|
|
|
|
|
options.parent.classList.add('hide');
|
|
|
|
options.parent.classList.add('upNextDialog');
|
|
|
|
options.parent.classList.add('upNextDialog-hidden');
|
|
|
|
|
|
|
|
fillItem.call(instance, options.nextItem);
|
|
|
|
|
|
|
|
options.parent.querySelector('.btnHide').addEventListener('click', instance.hide.bind(instance));
|
|
|
|
options.parent.querySelector('.btnStartNow').addEventListener('click', onStartNowClick.bind(instance));
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function clearHideAnimationEventListeners(instance, elem) {
|
2020-07-27 10:30:24 +01:00
|
|
|
const fn = instance._onHideAnimationComplete;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
if (fn) {
|
|
|
|
dom.removeEventListener(elem, transitionEndEventName, fn, {
|
|
|
|
once: true
|
|
|
|
});
|
|
|
|
}
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function onHideAnimationComplete(e) {
|
2020-07-27 10:30:24 +01:00
|
|
|
const instance = this;
|
|
|
|
const elem = e.target;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
elem.classList.add('hide');
|
|
|
|
|
|
|
|
clearHideAnimationEventListeners(instance, elem);
|
2020-09-08 02:05:02 -04:00
|
|
|
Events.trigger(instance, 'hide');
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2021-04-07 22:36:22 -04:00
|
|
|
async function hideComingUpNext() {
|
2020-07-27 10:30:24 +01:00
|
|
|
const instance = this;
|
2019-01-10 15:39:37 +03:00
|
|
|
clearCountdownTextTimeout(this);
|
|
|
|
|
|
|
|
if (!instance.options) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-27 10:30:24 +01:00
|
|
|
const elem = instance.options.parent;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
if (!elem) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
clearHideAnimationEventListeners(this, elem);
|
|
|
|
|
|
|
|
if (elem.classList.contains('upNextDialog-hidden')) {
|
|
|
|
return;
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-27 10:30:24 +01:00
|
|
|
const fn = onHideAnimationComplete.bind(instance);
|
2019-01-10 15:39:37 +03:00
|
|
|
instance._onHideAnimationComplete = fn;
|
|
|
|
|
2021-06-24 17:50:39 -04:00
|
|
|
const transitionEvent = await new Promise((resolve) => {
|
2021-04-07 22:36:22 -04:00
|
|
|
dom.addEventListener(elem, transitionEndEventName, resolve, {
|
|
|
|
once: true
|
|
|
|
});
|
|
|
|
|
|
|
|
// trigger a reflow to force it to animate again
|
|
|
|
void elem.offsetWidth;
|
|
|
|
|
|
|
|
elem.classList.add('upNextDialog-hidden');
|
2019-01-10 15:39:37 +03:00
|
|
|
});
|
2021-04-07 22:36:22 -04:00
|
|
|
|
2021-06-24 17:50:39 -04:00
|
|
|
instance._onHideAnimationComplete(transitionEvent);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function getTimeRemainingMs(instance) {
|
2020-07-27 10:30:24 +01:00
|
|
|
const options = instance.options;
|
2018-10-23 01:05:09 +03:00
|
|
|
if (options) {
|
2020-07-27 10:30:24 +01:00
|
|
|
const runtimeTicks = playbackManager.duration(options.player);
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2018-10-23 01:05:09 +03:00
|
|
|
if (runtimeTicks) {
|
2020-08-15 11:30:36 -04:00
|
|
|
const timeRemainingTicks = runtimeTicks - playbackManager.currentTime(options.player) * 10000;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
return Math.round(timeRemainingTicks / 10000);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
}
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
return 0;
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
function startComingUpNextHideTimer(instance) {
|
2020-07-27 10:30:24 +01:00
|
|
|
const timeRemainingMs = getTimeRemainingMs(instance);
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
if (timeRemainingMs <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
setNextVideoText.call(instance);
|
|
|
|
clearCountdownTextTimeout(instance);
|
|
|
|
|
|
|
|
instance._countdownTextTimeout = setInterval(setNextVideoText.bind(instance), 400);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
|
|
|
|
2020-07-27 10:26:09 +01:00
|
|
|
class UpNextDialog {
|
|
|
|
constructor(options) {
|
2019-01-10 15:39:37 +03:00
|
|
|
this.options = options;
|
|
|
|
|
|
|
|
init(this, options);
|
2018-10-23 01:05:09 +03:00
|
|
|
}
|
2020-07-27 10:26:09 +01:00
|
|
|
show() {
|
2020-07-27 10:30:24 +01:00
|
|
|
const elem = this.options.parent;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
|
|
|
clearHideAnimationEventListeners(this, elem);
|
|
|
|
|
|
|
|
elem.classList.remove('hide');
|
|
|
|
|
|
|
|
// trigger a reflow to force it to animate again
|
|
|
|
void elem.offsetWidth;
|
|
|
|
|
|
|
|
elem.classList.remove('upNextDialog-hidden');
|
|
|
|
|
|
|
|
if (layoutManager.tv) {
|
|
|
|
setTimeout(function () {
|
|
|
|
focusManager.focus(elem.querySelector('.btnStartNow'));
|
|
|
|
}, 50);
|
|
|
|
}
|
|
|
|
|
|
|
|
startComingUpNextHideTimer(this);
|
2020-07-27 10:26:09 +01:00
|
|
|
}
|
2021-04-07 22:36:22 -04:00
|
|
|
async hide() {
|
|
|
|
await hideComingUpNext.bind(this)();
|
2020-07-27 10:26:09 +01:00
|
|
|
}
|
|
|
|
destroy() {
|
2019-01-10 15:39:37 +03:00
|
|
|
hideComingUpNext.call(this);
|
|
|
|
|
|
|
|
this.options = null;
|
|
|
|
this.itemType = null;
|
2020-07-27 10:26:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default UpNextDialog;
|
2019-01-10 15:39:37 +03:00
|
|
|
|
2020-07-27 10:26:09 +01:00
|
|
|
/* eslint-enable indent */
|