Merge branch 'master' into issue5486

This commit is contained in:
kevgrig
2025-07-10 21:40:51 -05:00
committed by GitHub
334 changed files with 14930 additions and 10715 deletions
@@ -1,5 +1,5 @@
import ServerConnections from 'components/ServerConnections';
import { getItemQuery } from 'hooks/useItem';
import { ServerConnections } from 'lib/jellyfin-apiclient';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import { queryClient } from 'utils/query/queryClient';
+22 -9
View File
@@ -1,3 +1,4 @@
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind.js';
import { PlaybackErrorCode } from '@jellyfin/sdk/lib/generated-client/models/playback-error-code.js';
import { getMediaInfoApi } from '@jellyfin/sdk/lib/utils/api/media-info-api';
import { MediaType } from '@jellyfin/sdk/lib/generated-client/models/media-type';
@@ -14,7 +15,6 @@ import * as userSettings from '../../scripts/settings/userSettings';
import globalize from '../../lib/globalize';
import loading from '../loading/loading';
import { appHost } from '../apphost';
import ServerConnections from '../ServerConnections';
import alert from '../alert';
import { PluginType } from '../../types/plugin.ts';
import { includesAny } from '../../utils/container.ts';
@@ -24,10 +24,11 @@ import { getItemBackdropImageUrl } from '../../utils/jellyfin-apiclient/backdrop
import { PlayerEvent } from 'apps/stable/features/playback/constants/playerEvent';
import { bindMediaSegmentManager } from 'apps/stable/features/playback/utils/mediaSegmentManager';
import { bindMediaSessionSubscriber } from 'apps/stable/features/playback/utils/mediaSessionSubscriber';
import { AppFeature } from 'constants/appFeature';
import { ServerConnections } from 'lib/jellyfin-apiclient';
import { MediaError } from 'types/mediaError';
import { getMediaError } from 'utils/mediaError';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind.js';
import { bindSkipSegment } from './skipsegment.ts';
const UNLIMITED_ITEMS = -1;
@@ -41,7 +42,7 @@ function enableLocalPlaylistManagement(player) {
}
function supportsPhysicalVolumeControl(player) {
return player.isLocalPlayer && appHost.supports('physicalvolumecontrol');
return player.isLocalPlayer && appHost.supports(AppFeature.PhysicalVolumeControl);
}
function bindToFullscreenChange(player) {
@@ -317,7 +318,7 @@ function getAudioStreamUrl(item, transcodingProfile, directPlayContainers, apiCl
PlaySessionId: startingPlaySession,
StartTimeTicks: startPosition || 0,
EnableRedirection: true,
EnableRemoteMedia: appHost.supports('remoteaudio'),
EnableRemoteMedia: appHost.supports(AppFeature.RemoteAudio),
EnableAudioVbrEncoding: transcodingProfile.EnableAudioVbrEncoding
});
}
@@ -598,7 +599,7 @@ function supportsDirectPlay(apiClient, item, mediaSource) {
const isFolderRip = mediaSource.VideoType === 'BluRay' || mediaSource.VideoType === 'Dvd' || mediaSource.VideoType === 'HdDvd';
if (mediaSource.SupportsDirectPlay || isFolderRip) {
if (mediaSource.IsRemote && !appHost.supports('remotevideo')) {
if (mediaSource.IsRemote && !appHost.supports(AppFeature.RemoteVideo)) {
return Promise.resolve(false);
}
@@ -1842,7 +1843,7 @@ export class PlaybackManager {
ArtistIds: firstItem.Id,
Filters: 'IsNotFolder',
Recursive: true,
SortBy: options.shuffle ? 'Random' : 'SortName',
SortBy: options.shuffle ? 'Random' : 'Album,ParentIndexNumber,IndexNumber,SortName',
MediaTypes: 'Audio'
}, queryOptions));
case 'PhotoAlbum':
@@ -1873,6 +1874,14 @@ export class PlaybackManager {
SortBy: options.shuffle ? 'Random' : 'SortName',
MediaTypes: 'Video'
}, queryOptions));
case 'Studio':
return getItemsForPlayback(serverId, mergePlaybackQueries({
StudioIds: firstItem.Id,
Filters: 'IsNotFolder',
Recursive: true,
SortBy: options.shuffle ? 'Random' : 'SortName',
MediaTypes: 'Video'
}, queryOptions));
case 'Series':
case 'Season':
return getSeriesOrSeasonPlaybackPromise(firstItem, options, items);
@@ -1923,7 +1932,11 @@ export class PlaybackManager {
if (options.shuffle) {
sortBy = 'Random';
} else if (firstItem.Type !== 'BoxSet') {
sortBy = 'SortName';
if (firstItem.CollectionType === 'music' || firstItem.MediaType === 'Audio') {
sortBy = 'Album,ParentIndexNumber,IndexNumber,SortName';
} else {
sortBy = 'SortName';
}
}
return getItemsForPlayback(serverId, mergePlaybackQueries({
@@ -3698,7 +3711,7 @@ export class PlaybackManager {
return streamInfo ? streamInfo.playbackStartTimeTicks : null;
};
if (appHost.supports('remotecontrol')) {
if (appHost.supports(AppFeature.RemoteControl)) {
import('../../scripts/serverNotifications').then(({ default: serverNotifications }) => {
Events.on(serverNotifications, 'ServerShuttingDown', self.setDefaultPlayerActive.bind(self));
Events.on(serverNotifications, 'ServerRestarting', self.setDefaultPlayerActive.bind(self));
@@ -4069,7 +4082,7 @@ export class PlaybackManager {
'PlayTrailers'
];
if (appHost.supports('fullscreenchange')) {
if (appHost.supports(AppFeature.Fullscreen)) {
list.push('ToggleFullscreen');
}
@@ -1,3 +1,4 @@
import { AppFeature } from 'constants/appFeature';
import Events from '../../utils/events.ts';
import browser from '../../scripts/browser';
import loading from '../loading/loading';
@@ -96,7 +97,7 @@ export function show(button) {
// Unfortunately we can't allow the url to change or chromecast will throw a security error
// Might be able to solve this in the future by moving the dialogs to hashbangs
if (!(!browser.chrome && !browser.edgeChromium || appHost.supports('castmenuhashchange'))) {
if (!(!browser.chrome && !browser.edgeChromium || appHost.supports(AppFeature.CastMenuHashChange))) {
menuOptions.enableHistory = false;
}
@@ -1,8 +1,8 @@
import actionsheet from '../actionSheet/actionSheet';
import { playbackManager } from '../playback/playbackmanager';
import globalize from '../../lib/globalize';
import globalize from 'lib/globalize';
import { ServerConnections } from 'lib/jellyfin-apiclient';
import qualityoptions from '../qualityOptions';
import ServerConnections from '../ServerConnections';
function showQualityMenu(player, btn) {
const videoStream = playbackManager.currentMediaSource(player).MediaStreams.filter(function (stream) {
+6 -11
View File
@@ -2,7 +2,7 @@
position: fixed;
left: 0;
right: 0;
bottom: 18%;
bottom: 8rem;
pointer-events: none;
z-index: 10000;
}
@@ -11,26 +11,21 @@
display: flex;
align-items: center;
margin-left: auto;
margin-right: 16%;
margin-right: 6rem;
z-index: 10000;
padding: 12px 20px;
color: black;
background-color: #303030;
color: rgba(255, 255, 255, 0.87);
border: none;
border-radius: 100px;
border-radius: 0.2em;
font-weight: bold;
font-size: 1.2em;
transition: opacity 200ms ease-out;
gap: 3px;
box-shadow: 7px 6px 15px -14px rgba(0, 0, 0, 0.65);
cursor: pointer;
pointer-events: auto;
}
@media (orientation: landscape) and (max-height: 500px) {
.skip-button {
bottom: 27%;
}
}
.no-transition {
transition: none;
}