1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge pull request #6244 from thornbill/fix-playing-parts

This commit is contained in:
Bill Thornton 2024-10-24 13:34:14 -04:00 committed by GitHub
commit de87916c36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 59 additions and 32 deletions

View file

@ -27,10 +27,12 @@ const PlayAllButton: FC<PlayAllButtonProps> = ({ item, items, viewType, hasFilte
SortBy: [libraryViewSettings.SortBy], SortBy: [libraryViewSettings.SortBy],
SortOrder: [libraryViewSettings.SortOrder] SortOrder: [libraryViewSettings.SortOrder]
} }
}).catch(err => {
console.error('[PlayAllButton] failed to play', err);
}); });
} else { } else {
playbackManager.play({ playbackManager.play({
items: items, items,
autoplay: true, autoplay: true,
queryOptions: { queryOptions: {
ParentId: item?.Id ?? undefined, ParentId: item?.Id ?? undefined,
@ -38,7 +40,8 @@ const PlayAllButton: FC<PlayAllButtonProps> = ({ item, items, viewType, hasFilte
SortBy: [libraryViewSettings.SortBy], SortBy: [libraryViewSettings.SortBy],
SortOrder: [libraryViewSettings.SortOrder] SortOrder: [libraryViewSettings.SortOrder]
} }
}).catch(err => {
console.error('[PlayAllButton] failed to play', err);
}); });
} }
}, [hasFilters, item, items, libraryViewSettings, viewType]); }, [hasFilters, item, items, libraryViewSettings, viewType]);

View file

@ -17,10 +17,14 @@ const QueueButton: FC<QueueButtonProps> = ({ item, items, hasFilters }) => {
if (item && !hasFilters) { if (item && !hasFilters) {
playbackManager.queue({ playbackManager.queue({
items: [item] items: [item]
}).catch(err => {
console.error('[QueueButton] failed to add to queue', err);
}); });
} else { } else {
playbackManager.queue({ playbackManager.queue({
items: items items
}).catch(err => {
console.error('[QueueButton] failed to add to queue', err);
}); });
} }
}, [hasFilters, item, items]); }, [hasFilters, item, items]);

View file

@ -24,13 +24,15 @@ const ShuffleButton: FC<ShuffleButtonProps> = ({ item, items, viewType, hasFilte
playbackManager.shuffle(item); playbackManager.shuffle(item);
} else { } else {
playbackManager.play({ playbackManager.play({
items: items, items,
autoplay: true, autoplay: true,
queryOptions: { queryOptions: {
ParentId: item?.Id ?? undefined, ParentId: item?.Id ?? undefined,
...getFiltersQuery(viewType, libraryViewSettings), ...getFiltersQuery(viewType, libraryViewSettings),
SortBy: [ItemSortBy.Random] SortBy: [ItemSortBy.Random]
} }
}).catch(err => {
console.error('[ShuffleButton] failed to play', err);
}); });
} }
}, [hasFilters, item, items, libraryViewSettings, viewType]); }, [hasFilters, item, items, libraryViewSettings, viewType]);

View file

@ -39,7 +39,7 @@ function playAllFromHere(opts: PlayAllFromHereOptions) {
} }
if (!ids.length) { if (!ids.length) {
return; return Promise.resolve();
} }
if (queue) { if (queue) {
@ -168,6 +168,8 @@ const MoreCommandsButton: FC<MoreCommandsButtonProps> = ({
item: item || {}, item: item || {},
items: items || [], items: items || [],
serverId: item?.ServerId serverId: item?.ServerId
}).catch(err => {
console.error('[MoreCommandsButton] failed to play', err);
}); });
} else if (result.command === 'queueallfromhere') { } else if (result.command === 'queueallfromhere') {
playAllFromHere({ playAllFromHere({
@ -175,6 +177,8 @@ const MoreCommandsButton: FC<MoreCommandsButtonProps> = ({
items: items || [], items: items || [],
serverId: item?.ServerId, serverId: item?.ServerId,
queue: true queue: true
}).catch(err => {
console.error('[MoreCommandsButton] failed to play', err);
}); });
} else if (result.deleted) { } else if (result.deleted) {
if (result?.itemId !== itemId) { if (result?.itemId !== itemId) {

View file

@ -58,6 +58,8 @@ const PlayOrResumeButton: FC<PlayOrResumeButtonProps> = ({
); );
playbackManager.play({ playbackManager.play({
items: [channel] items: [channel]
}).catch(err => {
console.error('[PlayOrResumeButton] failed to play', err);
}); });
return; return;
} }
@ -65,6 +67,8 @@ const PlayOrResumeButton: FC<PlayOrResumeButtonProps> = ({
playbackManager.play({ playbackManager.play({
items: [item], items: [item],
...playOptions ...playOptions
}).catch(err => {
console.error('[PlayOrResumeButton] failed to play', err);
}); });
}, [apiContext, item, playOptions, queryClient]); }, [apiContext, item, playOptions, queryClient]);

View file

@ -2039,12 +2039,12 @@ export class PlaybackManager {
self.translateItemsForPlayback = translateItemsForPlayback; self.translateItemsForPlayback = translateItemsForPlayback;
self.getItemsForPlayback = getItemsForPlayback; self.getItemsForPlayback = getItemsForPlayback;
self.play = function (options) { self.play = async function (options) {
normalizePlayOptions(options); normalizePlayOptions(options);
if (self._currentPlayer) { if (self._currentPlayer) {
if (options.enableRemotePlayers === false && !self._currentPlayer.isLocalPlayer) { if (options.enableRemotePlayers === false && !self._currentPlayer.isLocalPlayer) {
return Promise.reject(); throw new Error('Remote players are disabled');
} }
if (!self._currentPlayer.isLocalPlayer) { if (!self._currentPlayer.isLocalPlayer) {
@ -2056,29 +2056,35 @@ export class PlaybackManager {
loading.show(); loading.show();
} }
if (options.items) { let { items } = options;
return translateItemsForPlayback(options.items, options) // If items were not passed directly, fetch them by ID
.then((items) => getAdditionalParts(items)) if (!items) {
.then(function (allItems) {
const flattened = allItems.flatMap(i => i);
return playWithIntros(flattened, options);
});
} else {
if (!options.serverId) { if (!options.serverId) {
throw new Error('serverId required!'); throw new Error('serverId required!');
} }
return getItemsForPlayback(options.serverId, { items = (await getItemsForPlayback(options.serverId, {
Ids: options.ids.join(',') Ids: options.ids.join(',')
}).then(function (result) { })).Items;
return translateItemsForPlayback(result.Items, options)
.then((items) => getAdditionalParts(items))
.then(function (allItems) {
const flattened = allItems.flatMap(i => i);
return playWithIntros(flattened, options);
});
});
} }
// Prepare the list of items
items = await translateItemsForPlayback(items, options);
// Add any additional parts for movies or episodes
items = await getAdditionalParts(items);
// Adjust the start index for additional parts added to the queue
if (options.startIndex) {
let adjustedStartIndex = 0;
for (let i = 0; i < options.startIndex; i++) {
adjustedStartIndex += items[i].length;
}
options.startIndex = adjustedStartIndex;
}
// getAdditionalParts returns an array of arrays of items, so flatten it
items = items.flat();
return playWithIntros(items, options);
}; };
function getPlayerData(player) { function getPlayerData(player) {
@ -2217,20 +2223,22 @@ export class PlaybackManager {
} }
const getAdditionalParts = async (items) => { const getAdditionalParts = async (items) => {
const getOneAdditionalPart = async function (item) { const getItemAndParts = async function (item) {
let retVal = [item]; if (
if (item.PartCount && item.PartCount > 1 && (item.Type === 'Movie' || item.Type === 'Episode')) { item.PartCount && item.PartCount > 1
&& [ BaseItemKind.Episode, BaseItemKind.Movie ].includes(item.Type)
) {
const client = ServerConnections.getApiClient(item.ServerId); const client = ServerConnections.getApiClient(item.ServerId);
const user = await client.getCurrentUser(); const user = await client.getCurrentUser();
const additionalParts = await client.getAdditionalVideoParts(user.Id, item.Id); const additionalParts = await client.getAdditionalVideoParts(user.Id, item.Id);
if (additionalParts.Items.length) { if (additionalParts.Items.length) {
retVal = [item, ...additionalParts.Items]; return [ item, ...additionalParts.Items ];
} }
} }
return retVal; return [ item ];
}; };
return Promise.all(items.flatMap(async (item) => getOneAdditionalPart(item))); return Promise.all(items.map(getItemAndParts));
}; };
function playWithIntros(items, options) { function playWithIntros(items, options) {
@ -3105,11 +3113,11 @@ export class PlaybackManager {
}; };
self.queue = function (options, player = this._currentPlayer) { self.queue = function (options, player = this._currentPlayer) {
queue(options, '', player); return queue(options, '', player);
}; };
self.queueNext = function (options, player = this._currentPlayer) { self.queueNext = function (options, player = this._currentPlayer) {
queue(options, 'next', player); return queue(options, 'next', player);
}; };
function queue(options, mode, player) { function queue(options, mode, player) {

View file

@ -145,6 +145,8 @@ function addToPlaylist(dlg: DialogElement, id: string) {
playbackManager.queue({ playbackManager.queue({
serverId: currentServerId, serverId: currentServerId,
ids: itemIds.split(',') ids: itemIds.split(',')
}).catch(err => {
console.error('[PlaylistEditor] failed to add to queue', err);
}); });
dlg.submitted = true; dlg.submitted = true;
dialogHelper.close(dlg); dialogHelper.close(dlg);