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

410 lines
13 KiB
JavaScript
Raw Normal View History

2020-06-09 22:14:24 +03:00
/**
* Module shortcuts.
* @module components/shortcuts
*/
2020-08-16 20:24:45 +02:00
import { playbackManager } from './playback/playbackmanager';
2020-08-14 08:46:34 +02:00
import inputManager from '../scripts/inputManager';
2023-05-01 10:04:13 -04:00
import { appRouter } from './router/appRouter';
2020-08-14 08:46:34 +02:00
import globalize from '../scripts/globalize';
import dom from '../scripts/dom';
import recordingHelper from './recordingcreator/recordinghelper';
import ServerConnections from './ServerConnections';
2020-10-18 14:19:41 +01:00
import toast from './toast/toast';
import * as userSettings from '../scripts/settings/userSettings';
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
function playAllFromHere(card, serverId, queue) {
const parent = card.parentNode;
const className = card.classList.length ? (`.${card.classList[0]}`) : '';
const cards = parent.querySelectorAll(`${className}[data-id]`);
2023-04-19 01:56:05 -04:00
const ids = [];
2023-04-19 01:56:05 -04:00
let foundCard = false;
let startIndex;
2023-04-19 01:56:05 -04:00
for (let i = 0, length = cards.length; i < length; i++) {
if (cards[i] === card) {
foundCard = true;
startIndex = i;
}
2023-04-19 01:56:05 -04:00
if (foundCard || !queue) {
ids.push(cards[i].getAttribute('data-id'));
}
2023-04-19 01:56:05 -04:00
}
2023-04-19 01:56:05 -04:00
const itemsContainer = dom.parentWithClass(card, 'itemsContainer');
2023-07-06 13:39:48 -04:00
if (itemsContainer?.fetchData) {
2023-04-19 01:56:05 -04:00
const queryOptions = queue ? { StartIndex: startIndex } : {};
2023-04-19 01:56:05 -04:00
return itemsContainer.fetchData(queryOptions).then(result => {
if (queue) {
return playbackManager.queue({
items: result.Items
});
} else {
return playbackManager.play({
items: result.Items,
startIndex: startIndex
});
}
});
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
if (!ids.length) {
return;
}
if (queue) {
return playbackManager.queue({
ids: ids,
serverId: serverId
});
} else {
return playbackManager.play({
ids: ids,
serverId: serverId,
startIndex: startIndex
});
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
function showProgramDialog(item) {
import('./recordingcreator/recordingcreator').then(({ default:recordingCreator }) => {
recordingCreator.show(item.Id, item.ServerId);
});
}
2023-04-19 01:56:05 -04:00
function getItem(button) {
button = dom.parentWithAttribute(button, 'data-id');
const serverId = button.getAttribute('data-serverid');
const id = button.getAttribute('data-id');
const type = button.getAttribute('data-type');
2023-04-19 01:56:05 -04:00
const apiClient = ServerConnections.getApiClient(serverId);
if (type === 'Timer') {
return apiClient.getLiveTvTimer(id);
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
if (type === 'SeriesTimer') {
return apiClient.getLiveTvSeriesTimer(id);
}
return apiClient.getItem(apiClient.getCurrentUserId(), id);
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
function notifyRefreshNeeded(childElement, itemsContainer) {
itemsContainer = itemsContainer || dom.parentWithAttribute(childElement, 'is', 'emby-itemscontainer');
2023-04-19 01:56:05 -04:00
if (itemsContainer) {
itemsContainer.notifyRefreshNeeded(true);
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
function showContextMenu(card, options) {
getItem(card).then(item => {
const playlistId = card.getAttribute('data-playlistid');
const collectionId = card.getAttribute('data-collectionid');
2023-04-19 01:56:05 -04:00
if (playlistId) {
const elem = dom.parentWithAttribute(card, 'data-playlistitemid');
item.PlaylistItemId = elem ? elem.getAttribute('data-playlistitemid') : null;
}
2023-04-19 01:56:05 -04:00
import('./itemContextMenu').then((itemContextMenu) => {
ServerConnections.getApiClient(item.ServerId).getCurrentUser().then(user => {
itemContextMenu.show(Object.assign({
item: item,
play: true,
queue: true,
playAllFromHere: !item.IsFolder,
queueAllFromHere: !item.IsFolder,
playlistId: playlistId,
collectionId: collectionId,
user: user
}, options || {}))
.then(result => {
if (result.command === 'playallfromhere' || result.command === 'queueallfromhere') {
executeAction(card, options.positionTo, result.command);
} else if (result.updated || result.deleted) {
notifyRefreshNeeded(card, options.itemsContainer);
}
})
2023-10-25 23:32:49 +02:00
.catch(() => { /* no-op */ });
});
});
2023-04-19 01:56:05 -04:00
});
}
function getItemInfoFromCard(card) {
return {
Type: card.getAttribute('data-type'),
Id: card.getAttribute('data-id'),
TimerId: card.getAttribute('data-timerid'),
CollectionType: card.getAttribute('data-collectiontype'),
ChannelId: card.getAttribute('data-channelid'),
SeriesId: card.getAttribute('data-seriesid'),
ServerId: card.getAttribute('data-serverid'),
MediaType: card.getAttribute('data-mediatype'),
Path: card.getAttribute('data-path'),
IsFolder: card.getAttribute('data-isfolder') === 'true',
StartDate: card.getAttribute('data-startdate'),
EndDate: card.getAttribute('data-enddate'),
UserData: {
PlaybackPositionTicks: parseInt(card.getAttribute('data-positionticks') || '0', 10)
}
};
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
function showPlayMenu(card, target) {
const item = getItemInfoFromCard(card);
2023-04-19 01:56:05 -04:00
import('./playmenu').then((playMenu) => {
playMenu.show({
2023-04-19 01:56:05 -04:00
item: item,
positionTo: target
});
2023-04-19 01:56:05 -04:00
});
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
function executeAction(card, target, action) {
target = target || card;
2023-04-19 01:56:05 -04:00
let id = card.getAttribute('data-id');
2023-04-19 01:56:05 -04:00
if (!id) {
card = dom.parentWithAttribute(card, 'data-id');
id = card.getAttribute('data-id');
}
const item = getItemInfoFromCard(card);
const itemsContainer = dom.parentWithClass(card, 'itemsContainer');
const sortParentId = 'items-' + (item.IsFolder ? item.Id : itemsContainer?.getAttribute('data-parentid')) + '-Folder';
2023-04-19 01:56:05 -04:00
const serverId = item.ServerId;
const type = item.Type;
2023-04-19 01:56:05 -04:00
const playableItemId = type === 'Program' ? item.ChannelId : item.Id;
2023-04-19 01:56:05 -04:00
if (item.MediaType === 'Photo' && action === 'link') {
action = 'play';
}
if (action === 'link') {
appRouter.showItem(item, {
context: card.getAttribute('data-context'),
parentId: card.getAttribute('data-parentid')
});
} else if (action === 'programdialog') {
showProgramDialog(item);
} else if (action === 'instantmix') {
playbackManager.instantMix({
Id: playableItemId,
ServerId: serverId
});
} else if (action === 'play' || action === 'resume') {
const startPositionTicks = parseInt(card.getAttribute('data-positionticks') || '0', 10);
const sortValues = userSettings.getSortValuesLegacy(sortParentId, 'SortName');
2023-04-19 01:56:05 -04:00
if (playbackManager.canPlay(item)) {
playbackManager.play({
ids: [playableItemId],
startPositionTicks: startPositionTicks,
serverId: serverId,
queryOptions: {
SortBy: sortValues.sortBy,
SortOrder: sortValues.sortOrder
}
});
2023-04-19 01:56:05 -04:00
} else {
console.warn('Unable to play item', item);
}
} else if (action === 'queue') {
if (playbackManager.isPlaying()) {
playbackManager.queue({
ids: [playableItemId],
serverId: serverId
});
2023-04-19 01:56:05 -04:00
toast(globalize.translate('MediaQueued'));
} else {
playbackManager.queue({
ids: [playableItemId],
serverId: serverId
});
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
} else if (action === 'playallfromhere') {
playAllFromHere(card, serverId);
} else if (action === 'queueallfromhere') {
playAllFromHere(card, serverId, true);
} else if (action === 'setplaylistindex') {
playbackManager.setCurrentPlaylistItem(card.getAttribute('data-playlistitemid'));
} else if (action === 'record') {
onRecordCommand(serverId, id, type, card.getAttribute('data-timerid'), card.getAttribute('data-seriestimerid'));
} else if (action === 'menu') {
const options = target.getAttribute('data-playoptions') === 'false' ?
{
shuffle: false,
instantMix: false,
play: false,
playAllFromHere: false,
queue: false,
queueAllFromHere: false
} :
{};
options.positionTo = target;
showContextMenu(card, options);
} else if (action === 'playmenu') {
showPlayMenu(card, target);
} else if (action === 'edit') {
getItem(target).then(itemToEdit => {
editItem(itemToEdit, serverId);
});
} else if (action === 'playtrailer') {
getItem(target).then(playTrailer);
} else if (action === 'addtoplaylist') {
getItem(target).then(addToPlaylist);
} else if (action === 'custom') {
const customAction = target.getAttribute('data-customaction');
card.dispatchEvent(new CustomEvent(`action-${customAction}`, {
detail: {
playlistItemId: card.getAttribute('data-playlistitemid')
},
cancelable: false,
bubbles: true
}));
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
function addToPlaylist(item) {
2023-07-06 11:49:55 -04:00
import('./playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => {
new PlaylistEditor().show({
2023-04-19 01:56:05 -04:00
items: [item.Id],
serverId: item.ServerId
});
2023-04-19 01:56:05 -04:00
});
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
function playTrailer(item) {
const apiClient = ServerConnections.getApiClient(item.ServerId);
2023-04-19 01:56:05 -04:00
apiClient.getLocalTrailers(apiClient.getCurrentUserId(), item.Id).then(trailers => {
playbackManager.play({ items: trailers });
});
}
function editItem(item, serverId) {
const apiClient = ServerConnections.getApiClient(serverId);
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
return new Promise((resolve, reject) => {
const currentServerId = apiClient.serverInfo().Id;
if (item.Type === 'Timer') {
if (item.ProgramId) {
import('./recordingcreator/recordingcreator').then(({ default: recordingCreator }) => {
recordingCreator.show(item.ProgramId, currentServerId).then(resolve, reject);
});
} else {
2023-04-19 01:56:05 -04:00
import('./recordingcreator/recordingeditor').then(({ default: recordingEditor }) => {
recordingEditor.show(item.Id, currentServerId).then(resolve, reject);
});
}
2023-04-19 01:56:05 -04:00
} else {
import('./metadataEditor/metadataEditor').then(({ default: metadataEditor }) => {
metadataEditor.show(item.Id, currentServerId).then(resolve, reject);
});
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
});
}
function onRecordCommand(serverId, id, type, timerId, seriesTimerId) {
if (type === 'Program' || timerId || seriesTimerId) {
const programId = type === 'Program' ? id : null;
recordingHelper.toggleRecording(serverId, programId, timerId, seriesTimerId);
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
export function onClick(e) {
const card = dom.parentWithClass(e.target, 'itemAction');
2023-04-19 01:56:05 -04:00
if (card) {
let actionElement = card;
let action = actionElement.getAttribute('data-action');
if (!action) {
actionElement = dom.parentWithAttribute(actionElement, 'data-action');
if (actionElement) {
action = actionElement.getAttribute('data-action');
}
2023-04-19 01:56:05 -04:00
}
2023-04-19 01:56:05 -04:00
if (action) {
executeAction(card, actionElement, action);
2023-04-19 01:56:05 -04:00
e.preventDefault();
e.stopPropagation();
return false;
2018-10-23 01:05:09 +03:00
}
}
2023-04-19 01:56:05 -04:00
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
function onCommand(e) {
const cmd = e.detail.command;
2023-04-19 01:56:05 -04:00
if (cmd === 'play' || cmd === 'resume' || cmd === 'record' || cmd === 'menu' || cmd === 'info') {
const target = e.target;
const card = dom.parentWithClass(target, 'itemAction') || dom.parentWithAttribute(target, 'data-id');
2023-04-19 01:56:05 -04:00
if (card) {
e.preventDefault();
e.stopPropagation();
executeAction(card, card, cmd);
2018-10-23 01:05:09 +03:00
}
}
2023-04-19 01:56:05 -04:00
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
export function on(context, options) {
options = options || {};
2023-04-19 01:56:05 -04:00
if (options.click !== false) {
context.addEventListener('click', onClick);
}
2023-04-19 01:56:05 -04:00
if (options.command !== false) {
inputManager.on(context, onCommand);
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
export function off(context, options) {
options = options || {};
2023-04-19 01:56:05 -04:00
context.removeEventListener('click', onClick);
2023-04-19 01:56:05 -04:00
if (options.command !== false) {
inputManager.off(context, onCommand);
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
}
2018-10-23 01:05:09 +03:00
2023-04-19 01:56:05 -04:00
export function getShortcutAttributesHtml(item, serverId) {
let html = `data-id="${item.Id}" data-serverid="${serverId || item.ServerId}" data-type="${item.Type}" data-mediatype="${item.MediaType}" data-channelid="${item.ChannelId}" data-isfolder="${item.IsFolder}"`;
2023-04-19 01:56:05 -04:00
const collectionType = item.CollectionType;
if (collectionType) {
html += ` data-collectiontype="${collectionType}"`;
2018-10-23 01:05:09 +03:00
}
2023-04-19 01:56:05 -04:00
return html;
}
2020-06-09 22:14:24 +03:00
export default {
on: on,
off: off,
onClick: onClick,
getShortcutAttributesHtml: getShortcutAttributesHtml
};