diff --git a/src/apiclient.d.ts b/src/apiclient.d.ts index a9f7f61ccd..1bda81641d 100644 --- a/src/apiclient.d.ts +++ b/src/apiclient.d.ts @@ -76,6 +76,7 @@ declare module 'jellyfin-apiclient' { accessToken(): string; addMediaPath(virtualFolderName: string, mediaPath: string, networkSharePath: string, refreshLibrary?: boolean): Promise; addVirtualFolder(name: string, type?: string, refreshLibrary?: boolean, libraryOptions?: any): Promise; + ajax(request: any): Promise; appName(): string; appVersion(): string; authenticateUserByName(name: string, password: string): Promise; diff --git a/src/components/playlisteditor/playlisteditor.ts b/src/components/playlisteditor/playlisteditor.ts index a85246a706..17a5966c14 100644 --- a/src/components/playlisteditor/playlisteditor.ts +++ b/src/components/playlisteditor/playlisteditor.ts @@ -1,53 +1,77 @@ import escapeHtml from 'escape-html'; -import dom from '../../scripts/dom'; +import type { ApiClient } from 'jellyfin-apiclient'; + +import dom from 'scripts/dom'; +import globalize from 'scripts/globalize'; +import * as userSettings from 'scripts/settings/userSettings'; +import { PluginType } from 'types/plugin'; + import dialogHelper from '../dialogHelper/dialogHelper'; import loading from '../loading/loading'; import layoutManager from '../layoutManager'; import { playbackManager } from '../playback/playbackmanager'; import { pluginManager } from '../pluginManager'; -import * as userSettings from '../../scripts/settings/userSettings'; import { appRouter } from '../router/appRouter'; -import globalize from '../../scripts/globalize'; -import { PluginType } from '../../types/plugin'; - -import '../../elements/emby-button/emby-button'; -import '../../elements/emby-input/emby-input'; -import '../../elements/emby-button/paper-icon-button-light'; -import '../../elements/emby-select/emby-select'; -import 'material-design-icons-iconfont'; -import '../formdialog.scss'; import ServerConnections from '../ServerConnections'; -let currentServerId; +import 'elements/emby-button/emby-button'; +import 'elements/emby-input/emby-input'; +import 'elements/emby-button/paper-icon-button-light'; +import 'elements/emby-select/emby-select'; -function onSubmit(e) { - const panel = dom.parentWithClass(this, 'dialog'); +import 'material-design-icons-iconfont'; +import '../formdialog.scss'; - const playlistId = panel.querySelector('#selectPlaylistToAddTo').value; - const apiClient = ServerConnections.getApiClient(currentServerId); +interface DialogElement extends HTMLDivElement { + submitted?: boolean +} - if (playlistId) { - userSettings.set('playlisteditor-lastplaylistid', playlistId); - addToPlaylist(apiClient, panel, playlistId); +interface PlaylistEditorOptions { + items: string[], + serverId: string, + enableAddToPlayQueue?: boolean, + defaultValue?: string +} + +let currentServerId: string; + +function onSubmit(this: HTMLElement, e: Event) { + const panel = dom.parentWithClass(this, 'dialog') as DialogElement | null; + + if (panel) { + const playlistId = panel.querySelector('#selectPlaylistToAddTo')?.value; + const apiClient = ServerConnections.getApiClient(currentServerId); + + if (playlistId) { + userSettings.set('playlisteditor-lastplaylistid', playlistId); + addToPlaylist(apiClient, panel, playlistId) + ?.catch(err => { + console.error('[PlaylistEditor] Failed to add to playlist %s', playlistId, err); + }); + } else { + createPlaylist(apiClient, panel) + ?.catch(err => { + console.error('[PlaylistEditor] Failed to create playlist', err); + }); + } } else { - createPlaylist(apiClient, panel); + console.error('[PlaylistEditor] Dialog element is missing!'); } e.preventDefault(); return false; } -function createPlaylist(apiClient, dlg) { +function createPlaylist(apiClient: ApiClient, dlg: DialogElement) { loading.show(); const url = apiClient.getUrl('Playlists', { - Name: dlg.querySelector('#txtNewPlaylistName').value, - Ids: dlg.querySelector('.fldSelectedItemIds').value || '', + Name: dlg.querySelector('#txtNewPlaylistName')?.value, + Ids: dlg.querySelector('.fldSelectedItemIds')?.value || '', userId: apiClient.getCurrentUserId() - }); - apiClient.ajax({ + return apiClient.ajax({ type: 'POST', url: url, dataType: 'json', @@ -62,12 +86,12 @@ function createPlaylist(apiClient, dlg) { }); } -function redirectToPlaylist(apiClient, id) { +function redirectToPlaylist(apiClient: ApiClient, id: string) { appRouter.showItem(id, apiClient.serverId()); } -function addToPlaylist(apiClient, dlg, id) { - const itemIds = dlg.querySelector('.fldSelectedItemIds').value || ''; +function addToPlaylist(apiClient: ApiClient, dlg: DialogElement, id: string) { + const itemIds = dlg.querySelector('.fldSelectedItemIds')?.value || ''; if (id === 'queue') { playbackManager.queue({ @@ -86,7 +110,7 @@ function addToPlaylist(apiClient, dlg, id) { userId: apiClient.getCurrentUserId() }); - apiClient.ajax({ + return apiClient.ajax({ type: 'POST', url: url @@ -98,16 +122,20 @@ function addToPlaylist(apiClient, dlg, id) { }); } -function triggerChange(select) { +function triggerChange(select: HTMLSelectElement) { select.dispatchEvent(new CustomEvent('change', {})); } -function populatePlaylists(editorOptions, panel) { - const select = panel.querySelector('#selectPlaylistToAddTo'); +function populatePlaylists(editorOptions: PlaylistEditorOptions, panel: DialogElement) { + const select = panel.querySelector('#selectPlaylistToAddTo'); loading.hide(); - panel.querySelector('.newPlaylistInfo').classList.add('hide'); + if (!select) { + return Promise.reject(new Error('Playlist