diff --git a/src/apiclient.d.ts b/src/apiclient.d.ts index fcb949fd2f..30fed07ed4 100644 --- a/src/apiclient.d.ts +++ b/src/apiclient.d.ts @@ -136,6 +136,7 @@ declare module 'jellyfin-apiclient' { getInstantMixFromItem(itemId: string, options?: any): Promise; getIntros(itemId: string): Promise; getItemCounts(userId?: string): Promise; + /** @deprecated This function returns a URL with a legacy auth parameter.*/ getItemDownloadUrl(itemId: string): string; getItemImageInfos(itemId: string): Promise; getItems(userId: string, options?: any): Promise; diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index 7f07c203e4..53e09fcf24 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -1,4 +1,8 @@ import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind'; +import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api'; + +import { AppFeature } from 'constants/appFeature'; +import { toApi } from 'utils/jellyfin-apiclient/compat'; import browser from '../scripts/browser'; import { copy } from '../scripts/clipboard'; @@ -12,7 +16,6 @@ import itemHelper, { canEditPlaylist } from './itemHelper'; import { playbackManager } from './playback/playbackmanager'; import toast from './toast/toast'; import * as userSettings from '../scripts/settings/userSettings'; -import { AppFeature } from 'constants/appFeature'; /** Item types that support downloading all children. */ const DOWNLOAD_ALL_TYPES = [ @@ -387,6 +390,7 @@ function executeCommand(item, id, options) { const itemId = item.Id; const serverId = item.ServerId; const apiClient = ServerConnections.getApiClient(serverId); + const api = toApi(apiClient); return new Promise(function (resolve, reject) { // eslint-disable-next-line sonarjs/max-switch-cases @@ -411,9 +415,9 @@ function executeCommand(item, id, options) { break; case 'download': import('../scripts/fileDownloader').then((fileDownloader) => { - const downloadHref = apiClient.getItemDownloadUrl(itemId); + const url = getLibraryApi(api).getDownloadUrl({ itemId }); fileDownloader.download([{ - url: downloadHref, + url, item, itemId, serverId, @@ -429,9 +433,9 @@ function executeCommand(item, id, options) { const downloads = items .filter(i => i.CanDownload) .map(i => { - const downloadHref = apiClient.getItemDownloadUrl(i.Id); + const url = getLibraryApi(api).getDownloadUrl({ itemId: i.Id }); return { - url: downloadHref, + url, item: i, itemId: i.Id, serverId, @@ -478,7 +482,7 @@ function executeCommand(item, id, options) { break; } case 'copy-stream': { - const downloadHref = apiClient.getItemDownloadUrl(itemId); + const downloadHref = getLibraryApi(api).getDownloadUrl({ itemId }); copy(downloadHref).then(() => { toast(globalize.translate('CopyStreamURLSuccess')); }).catch(() => { diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js index 3702db9aba..7953727990 100644 --- a/src/components/slideshow/slideshow.js +++ b/src/components/slideshow/slideshow.js @@ -2,9 +2,15 @@ * Image viewer component * @module components/slideshow/slideshow */ +import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api'; +import screenfull from 'screenfull'; + import { AppFeature } from 'constants/appFeature'; -import dialogHelper from '../dialogHelper/dialogHelper'; import { ServerConnections } from 'lib/jellyfin-apiclient'; +import { toApi } from 'utils/jellyfin-apiclient/compat'; +import { randomInt } from 'utils/number'; + +import dialogHelper from '../dialogHelper/dialogHelper'; import inputManager from '../../scripts/inputManager'; import layoutManager from '../layoutManager'; import focusManager from '../focusManager'; @@ -15,8 +21,6 @@ import dom from '../../utils/dom'; import './style.scss'; import 'material-design-icons-iconfont'; import '../../elements/emby-button/paper-icon-button-light'; -import screenfull from 'screenfull'; -import { randomInt } from '../../utils/number.ts'; /** * Name of transition event. @@ -88,14 +92,15 @@ function getBackdropImageUrl(item, options, apiClient) { * @returns {string} URL of the item's image. */ function getImgUrl(item, user) { - const apiClient = ServerConnections.getApiClient(item.ServerId); + const apiClient = ServerConnections.getApiClient(item); + const api = toApi(apiClient); const imageOptions = {}; if (item.BackdropImageTags?.length) { return getBackdropImageUrl(item, imageOptions, apiClient); } else { if (item.MediaType === 'Photo' && user?.Policy.EnableContentDownloading) { - return apiClient.getItemDownloadUrl(item.Id); + return getLibraryApi(api).getDownloadUrl({ itemId: item.Id }); } imageOptions.type = 'Primary'; return getImageUrl(item, imageOptions, apiClient); diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index 4e37a057aa..0c7c52ec80 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -1,5 +1,6 @@ import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind'; import { PersonKind } from '@jellyfin/sdk/lib/generated-client/models/person-kind'; +import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api'; import { intervalToDuration } from 'date-fns'; import DOMPurify from 'dompurify'; import escapeHtml from 'escape-html'; @@ -35,6 +36,7 @@ import { getPortraitShape, getSquareShape } from 'utils/card'; import Dashboard from 'utils/dashboard'; import Events from 'utils/events'; import { getItemBackdropImageUrl } from 'utils/jellyfin-apiclient/backdropImage'; +import { toApi } from 'utils/jellyfin-apiclient/compat'; import 'elements/emby-itemscontainer/emby-itemscontainer'; import 'elements/emby-checkbox/emby-checkbox'; @@ -2027,9 +2029,10 @@ export default function (view, params) { } function onDownloadClick() { - const downloadHref = getApiClient().getItemDownloadUrl(currentItem.Id); + const api = toApi(getApiClient()); + const url = getLibraryApi(api).getDownloadUrl({ itemId: currentItem.Id }); download([{ - url: downloadHref, + url, item: currentItem, itemId: currentItem.Id, serverId: currentItem.ServerId, diff --git a/src/plugins/bookPlayer/plugin.js b/src/plugins/bookPlayer/plugin.js index 880a31a38d..ccd3ba0e17 100644 --- a/src/plugins/bookPlayer/plugin.js +++ b/src/plugins/bookPlayer/plugin.js @@ -1,18 +1,21 @@ -import 'material-design-icons-iconfont'; +import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api'; +import Screenfull from 'screenfull'; + +import { ServerConnections } from 'lib/jellyfin-apiclient'; +import browser from 'scripts/browser'; +import TouchHelper from 'scripts/touchHelper'; +import { toApi } from 'utils/jellyfin-apiclient/compat'; import loading from '../../components/loading/loading'; import keyboardnavigation from '../../scripts/keyboardNavigation'; import dialogHelper from '../../components/dialogHelper/dialogHelper'; -import Screenfull from 'screenfull'; import TableOfContents from './tableOfContents'; import { translateHtml } from '../../lib/globalize'; -import { ServerConnections } from 'lib/jellyfin-apiclient'; -import browser from 'scripts/browser'; import * as userSettings from '../../scripts/settings/userSettings'; -import TouchHelper from 'scripts/touchHelper'; import { PluginType } from '../../types/plugin.ts'; import Events from '../../utils/events.ts'; +import 'material-design-icons-iconfont'; import '../../elements/emby-button/paper-icon-button-light'; import html from './template.html'; @@ -324,16 +327,14 @@ export class BookPlayer { } }; - const serverId = item.ServerId; - const apiClient = ServerConnections.getApiClient(serverId); - if (!Screenfull.isEnabled) { document.getElementById('btnBookplayerFullscreen').display = 'none'; } return new Promise((resolve, reject) => { import('epubjs').then(({ default: epubjs }) => { - const downloadHref = apiClient.getItemDownloadUrl(item.Id); + const api = toApi(ServerConnections.getApiClient(item)); + const downloadHref = getLibraryApi(api).getDownloadUrl({ itemId: item.Id }); const book = epubjs(downloadHref, { openAs: 'epub' }); // We need to calculate the height of the window beforehand because using 100% is not accurate when the dialog is opening. diff --git a/src/plugins/comicsPlayer/plugin.js b/src/plugins/comicsPlayer/plugin.js index 073a9ee8b8..6108a7ea37 100644 --- a/src/plugins/comicsPlayer/plugin.js +++ b/src/plugins/comicsPlayer/plugin.js @@ -1,9 +1,13 @@ +import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api'; import { Archive } from 'libarchive.js'; + +import { ServerConnections } from 'lib/jellyfin-apiclient'; +import { toApi } from 'utils/jellyfin-apiclient/compat'; + import loading from '../../components/loading/loading'; import dialogHelper from '../../components/dialogHelper/dialogHelper'; import keyboardnavigation from '../../scripts/keyboardNavigation'; import { appRouter } from '../../components/router/appRouter'; -import { ServerConnections } from 'lib/jellyfin-apiclient'; import * as userSettings from '../../scripts/settings/userSettings'; import { PluginType } from '../../types/plugin.ts'; @@ -287,14 +291,12 @@ export class ComicsPlayer { loading.show(); - const serverId = item.ServerId; - const apiClient = ServerConnections.getApiClient(serverId); - Archive.init({ workerUrl: appRouter.baseUrl() + '/libraries/worker-bundle.js' }); - const downloadUrl = apiClient.getItemDownloadUrl(item.Id); + const api = toApi(ServerConnections.getApiClient(item)); + const downloadUrl = getLibraryApi(api).getDownloadUrl({ itemId: item.Id }); this.archiveSource = new ArchiveSource(downloadUrl); //eslint-disable-next-line import/no-unresolved diff --git a/src/plugins/pdfPlayer/plugin.js b/src/plugins/pdfPlayer/plugin.js index 456a53382d..c0c5cd1356 100644 --- a/src/plugins/pdfPlayer/plugin.js +++ b/src/plugins/pdfPlayer/plugin.js @@ -1,3 +1,7 @@ +import { getLibraryApi } from '@jellyfin/sdk/lib/utils/api/library-api'; + +import { toApi } from 'utils/jellyfin-apiclient/compat'; + import loading from '../../components/loading/loading'; import keyboardnavigation from '../../scripts/keyboardNavigation'; import dialogHelper from '../../components/dialogHelper/dialogHelper'; @@ -205,11 +209,9 @@ export class PdfPlayer { } }; - const serverId = item.ServerId; - const apiClient = ServerConnections.getApiClient(serverId); - return import('pdfjs-dist').then(({ GlobalWorkerOptions, getDocument }) => { - const downloadHref = apiClient.getItemDownloadUrl(item.Id); + const api = toApi(ServerConnections.getApiClient(item)); + const downloadHref = getLibraryApi(api).getDownloadUrl({ itemId: item.Id }); this.bindEvents(); GlobalWorkerOptions.workerSrc = appRouter.baseUrl() + '/libraries/pdf.worker.js';