mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge branch 'master' into enable-airplay-audioplayer
This commit is contained in:
commit
e0d4aa6c77
227 changed files with 5818 additions and 2022 deletions
|
@ -384,7 +384,7 @@ export class BookPlayer {
|
|||
}
|
||||
|
||||
canPlayItem(item) {
|
||||
return item.Path && item.Path.endsWith('epub');
|
||||
return item.Path?.endsWith('epub');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import appSettings from '../../scripts/settings/appSettings';
|
|||
import * as userSettings from '../../scripts/settings/userSettings';
|
||||
import { playbackManager } from '../../components/playback/playbackmanager';
|
||||
import globalize from '../../scripts/globalize';
|
||||
import castSenderApiLoader from './castSenderApi';
|
||||
import CastSenderApi from './castSenderApi';
|
||||
import ServerConnections from '../../components/ServerConnections';
|
||||
import alert from '../../components/alert';
|
||||
import { PluginType } from '../../types/plugin.ts';
|
||||
|
@ -103,7 +103,7 @@ class CastPlayer {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!chrome.cast || !chrome.cast.isAvailable) {
|
||||
if (!chrome.cast?.isAvailable) {
|
||||
setTimeout(this.initializeCastPlayer.bind(this), 1000);
|
||||
return;
|
||||
}
|
||||
|
@ -322,14 +322,14 @@ class CastPlayer {
|
|||
|
||||
const session = player.session;
|
||||
|
||||
if (session && session.receiver && session.receiver.friendlyName) {
|
||||
if (session?.receiver?.friendlyName) {
|
||||
receiverName = session.receiver.friendlyName;
|
||||
}
|
||||
|
||||
let apiClient;
|
||||
if (message.options && message.options.ServerId) {
|
||||
if (message.options?.ServerId) {
|
||||
apiClient = ServerConnections.getApiClient(message.options.ServerId);
|
||||
} else if (message.options && message.options.items && message.options.items.length) {
|
||||
} else if (message.options?.items?.length) {
|
||||
apiClient = ServerConnections.getApiClient(message.options.items[0].ServerId);
|
||||
} else {
|
||||
apiClient = ServerConnections.currentApiClient();
|
||||
|
@ -350,7 +350,7 @@ class CastPlayer {
|
|||
message.maxBitrate = bitrateSetting;
|
||||
}
|
||||
|
||||
if (message.options && message.options.items) {
|
||||
if (message.options?.items) {
|
||||
message.subtitleAppearance = userSettings.getSubtitleAppearanceSettings();
|
||||
message.subtitleBurnIn = appSettings.get('subtitleburnin') || '';
|
||||
}
|
||||
|
@ -451,10 +451,10 @@ function onVolumeDownKeyDown() {
|
|||
}
|
||||
|
||||
function normalizeImages(state) {
|
||||
if (state && state.NowPlayingItem) {
|
||||
if (state?.NowPlayingItem) {
|
||||
const item = state.NowPlayingItem;
|
||||
|
||||
if ((!item.ImageTags || !item.ImageTags.Primary) && item.PrimaryImageTag) {
|
||||
if ((!item.ImageTags?.Primary) && item.PrimaryImageTag) {
|
||||
item.ImageTags = item.ImageTags || {};
|
||||
item.ImageTags.Primary = item.PrimaryImageTag;
|
||||
}
|
||||
|
@ -576,7 +576,7 @@ class ChromecastPlayer {
|
|||
this.isLocalPlayer = false;
|
||||
this.lastPlayerData = {};
|
||||
|
||||
new castSenderApiLoader().load().then(initializeChromecast.bind(this));
|
||||
new CastSenderApi().load().then(initializeChromecast.bind(this));
|
||||
}
|
||||
|
||||
tryPair() {
|
||||
|
@ -599,7 +599,7 @@ class ChromecastPlayer {
|
|||
getTargets() {
|
||||
const targets = [];
|
||||
|
||||
if (this._castPlayer && this._castPlayer.hasReceivers) {
|
||||
if (this._castPlayer?.hasReceivers) {
|
||||
targets.push(this.getCurrentTargetInfo());
|
||||
}
|
||||
|
||||
|
@ -612,7 +612,7 @@ class ChromecastPlayer {
|
|||
|
||||
const castPlayer = this._castPlayer;
|
||||
|
||||
if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.receiver.friendlyName) {
|
||||
if (castPlayer.session?.receiver?.friendlyName) {
|
||||
appName = castPlayer.session.receiver.friendlyName;
|
||||
}
|
||||
|
||||
|
|
|
@ -417,7 +417,7 @@ class HtmlAudioPlayer {
|
|||
const mediaElement = this._mediaElement;
|
||||
if (mediaElement) {
|
||||
const seekable = mediaElement.seekable;
|
||||
if (seekable && seekable.length) {
|
||||
if (seekable?.length) {
|
||||
let start = seekable.start(0);
|
||||
let end = seekable.end(0);
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import DOMPurify from 'dompurify';
|
||||
|
||||
import browser from '../../scripts/browser';
|
||||
import { appHost } from '../../components/apphost';
|
||||
import loading from '../../components/loading/loading';
|
||||
|
@ -434,6 +436,7 @@ export class HtmlVideoPlayer {
|
|||
const includeCorsCredentials = await getIncludeCorsCredentials();
|
||||
|
||||
const hls = new Hls({
|
||||
startPosition: options.playerStartPositionTicks / 10000000,
|
||||
manifestLoadingTimeOut: 20000,
|
||||
maxBufferLength: maxBufferLength,
|
||||
xhrSetup(xhr) {
|
||||
|
@ -1008,7 +1011,7 @@ export class HtmlVideoPlayer {
|
|||
}
|
||||
|
||||
if (elem.videoWidth === 0 && elem.videoHeight === 0) {
|
||||
const mediaSource = (this._currentPlayOptions || {}).mediaSource;
|
||||
const mediaSource = this._currentPlayOptions?.mediaSource;
|
||||
|
||||
// Only trigger this if there is media info
|
||||
// Avoid triggering in situations where it might not actually have a video stream (audio only live tv channel)
|
||||
|
@ -1269,13 +1272,13 @@ export class HtmlVideoPlayer {
|
|||
availableFonts: { 'liberation sans': `${appRouter.baseUrl()}/default.woff2` },
|
||||
// Disabled eslint compat, but is safe as corejs3 polyfills URL
|
||||
// eslint-disable-next-line compat/compat
|
||||
workerUrl: new URL('jassub/dist/jassub-worker.js', import.meta.url),
|
||||
workerUrl: new URL('jassub/dist/jassub-worker.js', import.meta.url).href,
|
||||
// eslint-disable-next-line compat/compat
|
||||
wasmUrl: new URL('jassub/dist/jassub-worker.wasm', import.meta.url),
|
||||
wasmUrl: new URL('jassub/dist/jassub-worker.wasm', import.meta.url).href,
|
||||
// eslint-disable-next-line compat/compat
|
||||
legacyWasmUrl: new URL('jassub/dist/jassub-worker.wasm.js', import.meta.url),
|
||||
legacyWasmUrl: new URL('jassub/dist/jassub-worker.wasm.js', import.meta.url).href,
|
||||
// eslint-disable-next-line compat/compat
|
||||
modernWasmUrl : new URL('jassub/dist/jassub-worker-modern.wasm', import.meta.url),
|
||||
modernWasmUrl : new URL('jassub/dist/jassub-worker-modern.wasm', import.meta.url).href,
|
||||
timeOffset: (this._currentPlayOptions.transcodingOffsetTicks || 0) / 10000000,
|
||||
// new jassub options; override all, even defaults
|
||||
blendMode: 'js',
|
||||
|
@ -1488,8 +1491,8 @@ export class HtmlVideoPlayer {
|
|||
// add some cues to show the text
|
||||
// in safari, the cues need to be added before setting the track mode to showing
|
||||
for (const trackEvent of data.TrackEvents) {
|
||||
const trackCueObject = window.VTTCue || window.TextTrackCue;
|
||||
const cue = new trackCueObject(trackEvent.StartPositionTicks / 10000000, trackEvent.EndPositionTicks / 10000000, normalizeTrackEventText(trackEvent.Text, false));
|
||||
const TrackCue = window.VTTCue || window.TextTrackCue;
|
||||
const cue = new TrackCue(trackEvent.StartPositionTicks / 10000000, trackEvent.EndPositionTicks / 10000000, normalizeTrackEventText(trackEvent.Text, false));
|
||||
|
||||
if (cue.line === 'auto') {
|
||||
cue.line = cueLine;
|
||||
|
@ -1534,8 +1537,9 @@ export class HtmlVideoPlayer {
|
|||
}
|
||||
}
|
||||
|
||||
if (selectedTrackEvent && selectedTrackEvent.Text) {
|
||||
subtitleTextElement.innerHTML = normalizeTrackEventText(selectedTrackEvent.Text, true);
|
||||
if (selectedTrackEvent?.Text) {
|
||||
subtitleTextElement.innerHTML = DOMPurify.sanitize(
|
||||
normalizeTrackEventText(selectedTrackEvent.Text, true));
|
||||
subtitleTextElement.classList.remove('hide');
|
||||
} else {
|
||||
subtitleTextElement.classList.add('hide');
|
||||
|
@ -1809,7 +1813,7 @@ export class HtmlVideoPlayer {
|
|||
Windows.UI.ViewManagement.ApplicationView.getForCurrentView().tryEnterViewModeAsync(Windows.UI.ViewManagement.ApplicationViewMode.default);
|
||||
}
|
||||
} else {
|
||||
if (video && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === 'function') {
|
||||
if (video?.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === 'function') {
|
||||
video.webkitSetPresentationMode(isEnabled ? 'picture-in-picture' : 'inline');
|
||||
}
|
||||
}
|
||||
|
@ -1888,7 +1892,7 @@ export class HtmlVideoPlayer {
|
|||
const mediaElement = this.#mediaElement;
|
||||
if (mediaElement) {
|
||||
const seekable = mediaElement.seekable;
|
||||
if (seekable && seekable.length) {
|
||||
if (seekable?.length) {
|
||||
let start = seekable.start(0);
|
||||
let end = seekable.end(0);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ export default function () {
|
|||
|
||||
const elem = document.querySelector('.logoScreenSaverImage');
|
||||
|
||||
if (elem && elem.animate) {
|
||||
if (elem?.animate) {
|
||||
const random = randomInt(0, animations.length - 1);
|
||||
|
||||
animations[random](elem, 1);
|
||||
|
|
|
@ -312,7 +312,7 @@ export class PdfPlayer {
|
|||
}
|
||||
|
||||
canPlayItem(item) {
|
||||
return item.Path && item.Path.endsWith('pdf');
|
||||
return item.Path?.endsWith('pdf');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ function subscribeToPlayerUpdates(instance) {
|
|||
}
|
||||
|
||||
function normalizeImages(state, apiClient) {
|
||||
if (state && state.NowPlayingItem) {
|
||||
if (state?.NowPlayingItem) {
|
||||
const item = state.NowPlayingItem;
|
||||
|
||||
if (!item.ImageTags || !item.ImageTags.Primary && item.PrimaryImageTag) {
|
||||
|
|
|
@ -246,7 +246,7 @@ class Manager {
|
|||
|
||||
/**
|
||||
* Handles a playback command from the server.
|
||||
* @param {Object} cmd The playback command.
|
||||
* @param {Object|null} cmd The playback command.
|
||||
*/
|
||||
processCommand(cmd) {
|
||||
if (cmd === null) return;
|
||||
|
@ -294,7 +294,7 @@ class Manager {
|
|||
|
||||
/**
|
||||
* Handles a group state change.
|
||||
* @param {Object} update The group state update.
|
||||
* @param {Object|null} update The group state update.
|
||||
*/
|
||||
processStateChange(update) {
|
||||
if (update === null || update.State === null || update.Reason === null) return;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue