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:
commit
de87916c36
7 changed files with 59 additions and 32 deletions
|
@ -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]);
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue