diff --git a/.eslintrc.js b/.eslintrc.js index 841a32643b..f3671e0faf 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,7 +6,6 @@ module.exports = { plugins: [ '@typescript-eslint', 'react', - 'promise', 'import', 'eslint-comments', 'sonarjs' @@ -20,7 +19,6 @@ module.exports = { extends: [ 'eslint:recommended', 'plugin:react/recommended', - // 'plugin:promise/recommended', 'plugin:import/errors', 'plugin:eslint-comments/recommended', 'plugin:compat/recommended', @@ -37,11 +35,18 @@ module.exports = { 'indent': ['error', 4, { 'SwitchCase': 1 }], 'jsx-quotes': ['error', 'prefer-single'], 'keyword-spacing': ['error'], - 'no-throw-literal': ['error'], 'max-statements-per-line': ['error'], 'max-params': ['error', 7], + 'new-cap': [ + 'error', + { + 'capIsNewExceptions': ['jQuery.Deferred'], + 'newIsCapExceptionPattern': '\\.default$' + } + ], 'no-duplicate-imports': ['error'], 'no-empty-function': ['error'], + 'no-extend-native': ['error'], 'no-floating-decimal': ['error'], 'no-multi-spaces': ['error'], 'no-multiple-empty-lines': ['error', { 'max': 1 }], @@ -54,6 +59,7 @@ module.exports = { 'no-sequences': ['error', { 'allowInParentheses': false }], 'no-shadow': ['off'], '@typescript-eslint/no-shadow': ['error'], + 'no-throw-literal': ['error'], 'no-trailing-spaces': ['error'], 'no-unused-expressions': ['off'], '@typescript-eslint/no-unused-expressions': ['error', { 'allowShortCircuit': true, 'allowTernary': true, 'allowTaggedTemplates': true }], @@ -68,6 +74,7 @@ module.exports = { 'padded-blocks': ['error', 'never'], 'prefer-const': ['error', { 'destructuring': 'all' }], '@typescript-eslint/prefer-for-of': ['error'], + '@typescript-eslint/prefer-optional-chain': ['error'], 'quotes': ['error', 'single', { 'avoidEscape': true, 'allowTemplateLiterals': false }], 'radix': ['error'], '@typescript-eslint/semi': ['error'], @@ -206,10 +213,7 @@ module.exports = { // JavaScript source files { files: [ - './src/**/*.js', - './src/**/*.jsx', - './src/**/*.ts', - './src/**/*.tsx' + './src/**/*.{js,jsx,ts,tsx}' ], parserOptions: { project: ['./tsconfig.json'] @@ -253,15 +257,13 @@ module.exports = { 'Windows': 'readonly' }, rules: { - '@typescript-eslint/no-floating-promises': ['warn'], '@typescript-eslint/prefer-string-starts-ends-with': ['error'] } }, // TypeScript source files { files: [ - './src/**/*.ts', - './src/**/*.tsx' + './src/**/*.{ts,tsx}' ], extends: [ 'eslint:recommended', diff --git a/package-lock.json b/package-lock.json index 1287735a17..b991d2d63a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -92,7 +92,6 @@ "eslint-plugin-eslint-comments": "3.2.0", "eslint-plugin-import": "2.27.5", "eslint-plugin-jsx-a11y": "6.7.1", - "eslint-plugin-promise": "6.1.1", "eslint-plugin-react": "7.32.2", "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-sonarjs": "0.19.0", @@ -7728,18 +7727,6 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, - "node_modules/eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, "node_modules/eslint-plugin-react": { "version": "7.32.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", @@ -26230,13 +26217,6 @@ } } }, - "eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "dev": true, - "requires": {} - }, "eslint-plugin-react": { "version": "7.32.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", diff --git a/package.json b/package.json index a138373fab..593428779d 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "eslint-plugin-eslint-comments": "3.2.0", "eslint-plugin-import": "2.27.5", "eslint-plugin-jsx-a11y": "6.7.1", - "eslint-plugin-promise": "6.1.1", "eslint-plugin-react": "7.32.2", "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-sonarjs": "0.19.0", diff --git a/src/apps/experimental/routes/home.tsx b/src/apps/experimental/routes/home.tsx index bf52b82137..3ab9c8bed7 100644 --- a/src/apps/experimental/routes/home.tsx +++ b/src/apps/experimental/routes/home.tsx @@ -65,12 +65,12 @@ const Home: FunctionComponent = () => { depends = 'favorites'; } - return import(/* webpackChunkName: "[request]" */ `../../../controllers/${depends}`).then(({ default: controllerFactory }) => { + return import(/* webpackChunkName: "[request]" */ `../../../controllers/${depends}`).then(({ default: ControllerFactory }) => { let controller = tabControllers[index]; if (!controller) { const tabContent = element.current?.querySelector(".tabContent[data-index='" + index + "']"); - controller = new controllerFactory(tabContent, null); + controller = new ControllerFactory(tabContent, null); tabControllers[index] = controller; } diff --git a/src/apps/stable/routes/user/userprofiles.tsx b/src/apps/stable/routes/user/userprofiles.tsx index b386533f4b..dc8a6e86fd 100644 --- a/src/apps/stable/routes/user/userprofiles.tsx +++ b/src/apps/stable/routes/user/userprofiles.tsx @@ -48,7 +48,7 @@ const UserProfiles: FunctionComponent = () => { const showUserMenu = (elem: HTMLElement) => { const card = dom.parentWithClass(elem, 'card'); - const userId = card.getAttribute('data-userid'); + const userId = card?.getAttribute('data-userid'); if (!userId) { console.error('Unexpected null user id'); diff --git a/src/components/appFooter/appFooter.js b/src/components/appFooter/appFooter.js index 3aaab8fe54..f599a0e0ea 100644 --- a/src/components/appFooter/appFooter.js +++ b/src/components/appFooter/appFooter.js @@ -9,7 +9,7 @@ function render() { return elem; } -class appFooter { +class AppFooter { constructor() { const self = this; @@ -33,4 +33,4 @@ class appFooter { } } -export default new appFooter(); +export default new AppFooter(); diff --git a/src/components/backdrop/backdrop.js b/src/components/backdrop/backdrop.js index 4cd481827f..46655777ff 100644 --- a/src/components/backdrop/backdrop.js +++ b/src/components/backdrop/backdrop.js @@ -37,7 +37,7 @@ class Backdrop { parent.appendChild(backdropImage); if (!enableAnimation()) { - if (existingBackdropImage && existingBackdropImage.parentNode) { + if (existingBackdropImage?.parentNode) { existingBackdropImage.parentNode.removeChild(existingBackdropImage); } internalBackdrop(true); @@ -51,7 +51,7 @@ class Backdrop { if (backdropImage === self.currentAnimatingElement) { self.currentAnimatingElement = null; } - if (existingBackdropImage && existingBackdropImage.parentNode) { + if (existingBackdropImage?.parentNode) { existingBackdropImage.parentNode.removeChild(existingBackdropImage); } }; diff --git a/src/components/cardbuilder/cardBuilder.js b/src/components/cardbuilder/cardBuilder.js index 5ad759002d..d5b19c0210 100644 --- a/src/components/cardbuilder/cardBuilder.js +++ b/src/components/cardbuilder/cardBuilder.js @@ -546,7 +546,7 @@ function getCardImageUrl(item, apiClient, options, shape) { imgType = 'Backdrop'; imgTag = item.ParentBackdropImageTags[0]; itemId = item.ParentBackdropItemId; - } else if (item.ImageTags && item.ImageTags.Primary && (item.Type !== 'Episode' || item.ChildCount !== 0)) { + } else if (item.ImageTags?.Primary && (item.Type !== 'Episode' || item.ChildCount !== 0)) { imgType = 'Primary'; imgTag = item.ImageTags.Primary; height = width && primaryImageAspectRatio ? Math.round(width / primaryImageAspectRatio) : null; @@ -591,10 +591,10 @@ function getCardImageUrl(item, apiClient, options, shape) { } else if (item.Type === 'Season' && item.ImageTags && item.ImageTags.Thumb) { imgType = 'Thumb'; imgTag = item.ImageTags.Thumb; - } else if (item.BackdropImageTags && item.BackdropImageTags.length) { + } else if (item.BackdropImageTags?.length) { imgType = 'Backdrop'; imgTag = item.BackdropImageTags[0]; - } else if (item.ImageTags && item.ImageTags.Thumb) { + } else if (item.ImageTags?.Thumb) { imgType = 'Thumb'; imgTag = item.ImageTags.Thumb; } else if (item.SeriesThumbImageTag && options.inheritThumb !== false) { @@ -605,7 +605,7 @@ function getCardImageUrl(item, apiClient, options, shape) { imgType = 'Thumb'; imgTag = item.ParentThumbImageTag; itemId = item.ParentThumbItemId; - } else if (item.ParentBackdropImageTags && item.ParentBackdropImageTags.length && options.inheritThumb !== false) { + } else if (item.ParentBackdropImageTags?.length && options.inheritThumb !== false) { imgType = 'Backdrop'; imgTag = item.ParentBackdropImageTags[0]; itemId = item.ParentBackdropItemId; @@ -634,7 +634,7 @@ function getCardImageUrl(item, apiClient, options, shape) { return { imgUrl: imgUrl, - blurhash: (blurHashes[imgType] || {})[imgTag], + blurhash: blurHashes[imgType]?.[imgTag], forceName: forceName, coverImage: coverImage }; @@ -1422,7 +1422,7 @@ function buildCard(index, item, apiClient, options) { className += ' card-withuserdata'; } - const positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (' data-positionticks="' + item.UserData.PlaybackPositionTicks + '"') : ''; + const positionTicksData = item.UserData?.PlaybackPositionTicks ? (' data-positionticks="' + item.UserData.PlaybackPositionTicks + '"') : ''; const collectionIdData = options.collectionId ? (' data-collectionid="' + options.collectionId + '"') : ''; const playlistIdData = options.playlistId ? (' data-playlistid="' + options.playlistId + '"') : ''; const mediaTypeData = item.MediaType ? (' data-mediatype="' + item.MediaType + '"') : ''; diff --git a/src/components/cardbuilder/chaptercardbuilder.js b/src/components/cardbuilder/chaptercardbuilder.js index 4a359cd9f4..21535adc89 100644 --- a/src/components/cardbuilder/chaptercardbuilder.js +++ b/src/components/cardbuilder/chaptercardbuilder.js @@ -26,7 +26,7 @@ function buildChapterCardsHtml(item, chapters, options) { } } - const mediaStreams = ((item.MediaSources || [])[0] || {}).MediaStreams || []; + const mediaStreams = (item.MediaSources || [])[0]?.MediaStreams || []; const videoStream = mediaStreams.filter(({ Type }) => { return Type === 'Video'; })[0] || {}; diff --git a/src/components/channelMapper/channelMapper.js b/src/components/channelMapper/channelMapper.js index 819fbfc3e6..a513d4ac03 100644 --- a/src/components/channelMapper/channelMapper.js +++ b/src/components/channelMapper/channelMapper.js @@ -12,7 +12,7 @@ import 'material-design-icons-iconfont'; import '../formdialog.scss'; import ServerConnections from '../ServerConnections'; -export default class channelMapper { +export default class ChannelMapper { constructor(options) { function mapChannel(button, channelId, providerChannelId) { loading.show(); diff --git a/src/components/guide/guide.js b/src/components/guide/guide.js index 907de76b88..9384ba2056 100644 --- a/src/components/guide/guide.js +++ b/src/components/guide/guide.js @@ -675,12 +675,12 @@ function Guide(options) { }); const activeElement = document.activeElement; - const itemId = activeElement && activeElement.getAttribute ? activeElement.getAttribute('data-id') : null; + const itemId = activeElement?.getAttribute ? activeElement.getAttribute('data-id') : null; let channelRowId = null; if (activeElement) { channelRowId = dom.parentWithClass(activeElement, 'channelPrograms'); - channelRowId = channelRowId && channelRowId.getAttribute ? channelRowId.getAttribute('data-channelid') : null; + channelRowId = channelRowId?.getAttribute ? channelRowId.getAttribute('data-channelid') : null; } renderChannelHeaders(context, channels, apiClient); diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index d5da017e2d..2bb9bb7928 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -76,7 +76,7 @@ export function loadSections(elem, apiClient, user, userSettings) { }); } else { let noLibDescription; - if (user['Policy'] && user['Policy']['IsAdministrator']) { + if (user.Policy?.IsAdministrator) { noLibDescription = globalize.translate('NoCreatedLibraries', '
', ''); } else { noLibDescription = globalize.translate('AskAdminToCreateLibrary'); diff --git a/src/components/htmlMediaHelper.js b/src/components/htmlMediaHelper.js index 124caa5e0a..f46885c79d 100644 --- a/src/components/htmlMediaHelper.js +++ b/src/components/htmlMediaHelper.js @@ -68,7 +68,7 @@ export function handleHlsJsMediaError(instance, reject) { let now = Date.now(); - if (window.performance && window.performance.now) { + if (window.performance?.now) { now = performance.now(); // eslint-disable-line compat/compat } diff --git a/src/components/imageUploader/imageUploader.js b/src/components/imageUploader/imageUploader.js index c2c70d32ec..c016075ba2 100644 --- a/src/components/imageUploader/imageUploader.js +++ b/src/components/imageUploader/imageUploader.js @@ -41,7 +41,7 @@ function onFileReaderError(evt) { function setFiles(page, files) { const file = files[0]; - if (!file || !file.type.match('image.*')) { + if (!file?.type.match('image.*')) { page.querySelector('#imageOutput').innerHTML = ''; page.querySelector('#fldUpload').classList.add('hide'); currentFile = null; diff --git a/src/components/images/imageLoader.js b/src/components/images/imageLoader.js index beb4bb31a5..178312a314 100644 --- a/src/components/images/imageLoader.js +++ b/src/components/images/imageLoader.js @@ -9,7 +9,7 @@ worker.addEventListener( 'message', ({ data: { pixels, hsh, width, height } }) => { const elems = targetDic[hsh]; - if (elems && elems.length) { + if (elems?.length) { for (const elem of elems) { drawBlurhash(elem, pixels, width, height); } diff --git a/src/components/indicators/indicators.js b/src/components/indicators/indicators.js index 9abfffd8e1..ec21ae3e7f 100644 --- a/src/components/indicators/indicators.js +++ b/src/components/indicators/indicators.js @@ -12,7 +12,7 @@ export function enableProgressIndicator(item) { export function getProgressHtml(pct, options) { let containerClass = 'itemProgressBar'; - if (options && options.containerClass) { + if (options?.containerClass) { containerClass += ' ' + options.containerClass; } @@ -21,7 +21,7 @@ export function getProgressHtml(pct, options) { function getAutoTimeProgressHtml(pct, options, isRecording, start, end) { let containerClass = 'itemProgressBar'; - if (options && options.containerClass) { + if (options?.containerClass) { containerClass += ' ' + options.containerClass; } @@ -36,7 +36,7 @@ function getAutoTimeProgressHtml(pct, options, isRecording, start, end) { export function getProgressBarHtml(item, options) { let pct; if (enableProgressIndicator(item) && item.Type !== 'Recording') { - const userData = options && options.userData ? options.userData : item.UserData; + const userData = options?.userData ? options.userData : item.UserData; if (userData) { pct = userData.PlayedPercentage; @@ -90,7 +90,7 @@ export function getPlayedIndicatorHtml(item) { } export function getChildCountIndicatorHtml(item, options) { - const minCount = options && options.minCount ? options.minCount : 0; + const minCount = options?.minCount ? options.minCount : 0; if (item.ChildCount && item.ChildCount > minCount) { return '
' + datetime.toLocaleString(item.ChildCount) + '
'; diff --git a/src/components/itemContextMenu.js b/src/components/itemContextMenu.js index b96ac14780..0ec982f15a 100644 --- a/src/components/itemContextMenu.js +++ b/src/components/itemContextMenu.js @@ -345,8 +345,8 @@ function executeCommand(item, id, options) { }); break; case 'addtoplaylist': - import('./playlisteditor/playlisteditor').then(({ default: playlistEditor }) => { - new playlistEditor({ + import('./playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { + new PlaylistEditor({ items: [itemId], serverId: serverId }).then(getResolveFunction(resolve, id, true), getResolveFunction(resolve, id)); @@ -630,8 +630,8 @@ function deleteItem(apiClient, item) { } function refresh(apiClient, item) { - import('./refreshdialog/refreshdialog').then(({ default: refreshDialog }) => { - new refreshDialog({ + import('./refreshdialog/refreshdialog').then(({ default: RefreshDialog }) => { + new RefreshDialog({ itemIds: [item.Id], serverId: apiClient.serverInfo().Id, mode: item.Type === 'CollectionFolder' ? 'scan' : null diff --git a/src/components/itemHelper.js b/src/components/itemHelper.js index b051fc74c4..ed5982051f 100644 --- a/src/components/itemHelper.js +++ b/src/components/itemHelper.js @@ -117,7 +117,7 @@ export function canEdit(user, item) { } export function isLocalItem(item) { - return item && item.Id && typeof item.Id === 'string' && item.Id.indexOf('local') === 0; + return item?.Id && typeof item.Id === 'string' && item.Id.indexOf('local') === 0; } export function canIdentify (user, item) { diff --git a/src/components/itemMediaInfo/itemMediaInfo.js b/src/components/itemMediaInfo/itemMediaInfo.js index 0eb1348760..a6ce545ee0 100644 --- a/src/components/itemMediaInfo/itemMediaInfo.js +++ b/src/components/itemMediaInfo/itemMediaInfo.js @@ -61,7 +61,7 @@ function getMediaSourceHtml(user, item, version) { if (version.Container) { html += `${createAttribute(globalize.translate('MediaInfoContainer'), version.Container)}
`; } - if (version.Formats && version.Formats.length) { + if (version.Formats?.length) { html += `${createAttribute(globalize.translate('MediaInfoFormat'), version.Formats.join(','))}
`; } if (version.Path && user && user.Policy.IsAdministrator) { diff --git a/src/components/itemidentifier/itemidentifier.js b/src/components/itemidentifier/itemidentifier.js index b1aa1a1b9b..a999f11086 100644 --- a/src/components/itemidentifier/itemidentifier.js +++ b/src/components/itemidentifier/itemidentifier.js @@ -79,7 +79,7 @@ function searchForIdentificationResults(page) { SearchInfo: lookupInfo }; - if (currentItem && currentItem.Id) { + if (currentItem?.Id) { lookupInfo.ItemId = currentItem.Id; } else { lookupInfo.IncludeDisabledProviders = true; diff --git a/src/components/itemsrefresher.js b/src/components/itemsrefresher.js index 4a784b91c9..5bac0621fa 100644 --- a/src/components/itemsrefresher.js +++ b/src/components/itemsrefresher.js @@ -134,7 +134,7 @@ class ItemsRefresher { } } - if (this.needsRefresh || (options && options.refresh)) { + if (this.needsRefresh || (options?.refresh)) { return this.refreshItems(); } diff --git a/src/components/libraryoptionseditor/libraryoptionseditor.js b/src/components/libraryoptionseditor/libraryoptionseditor.js index 9f25b6c3e6..36ee3c7978 100644 --- a/src/components/libraryoptionseditor/libraryoptionseditor.js +++ b/src/components/libraryoptionseditor/libraryoptionseditor.js @@ -495,7 +495,7 @@ function setImageFetchersIntoOptions(parent, options) { } function setImageOptionsIntoOptions(options) { - const originalTypeOptions = (currentLibraryOptions || {}).TypeOptions || []; + const originalTypeOptions = currentLibraryOptions?.TypeOptions || []; for (const originalTypeOption of originalTypeOptions) { let typeOptions = getTypeOptions(options, originalTypeOption.Type); diff --git a/src/components/listview/listview.js b/src/components/listview/listview.js index a6a588dc66..d35bdc3527 100644 --- a/src/components/listview/listview.js +++ b/src/components/listview/listview.js @@ -86,7 +86,7 @@ function getImageUrl(item, size) { type: 'Primary' }; - if (item.ImageTags && item.ImageTags.Primary) { + if (item.ImageTags?.Primary) { options.tag = item.ImageTags.Primary; itemId = item.Id; } else if (item.AlbumId && item.AlbumPrimaryImageTag) { @@ -235,7 +235,7 @@ export function getListViewHtml(options) { const playlistItemId = item.PlaylistItemId ? (` data-playlistitemid="${item.PlaylistItemId}"`) : ''; - const positionTicksData = item.UserData && item.UserData.PlaybackPositionTicks ? (` data-positionticks="${item.UserData.PlaybackPositionTicks}"`) : ''; + const positionTicksData = item.UserData?.PlaybackPositionTicks ? (` data-positionticks="${item.UserData.PlaybackPositionTicks}"`) : ''; const collectionIdData = options.collectionId ? (` data-collectionid="${options.collectionId}"`) : ''; const playlistIdData = options.playlistId ? (` data-playlistid="${options.playlistId}"`) : ''; const mediaTypeData = item.MediaType ? (` data-mediatype="${item.MediaType}"`) : ''; diff --git a/src/components/mediaLibraryCreator/mediaLibraryCreator.js b/src/components/mediaLibraryCreator/mediaLibraryCreator.js index 8fe961ce5a..6694e5b9a4 100644 --- a/src/components/mediaLibraryCreator/mediaLibraryCreator.js +++ b/src/components/mediaLibraryCreator/mediaLibraryCreator.js @@ -188,7 +188,7 @@ function initLibraryOptions(dlg) { }); } -export class showEditor { +export class MediaLibraryCreator { constructor(options) { return new Promise((resolve) => { currentOptions = options; @@ -224,4 +224,4 @@ let currentOptions; let hasChanges = false; let isCreating = false; -export default showEditor; +export default MediaLibraryCreator; diff --git a/src/components/mediaLibraryEditor/mediaLibraryEditor.js b/src/components/mediaLibraryEditor/mediaLibraryEditor.js index b1389552a8..72bedb2d11 100644 --- a/src/components/mediaLibraryEditor/mediaLibraryEditor.js +++ b/src/components/mediaLibraryEditor/mediaLibraryEditor.js @@ -93,7 +93,7 @@ function onListItemClick(e) { if (listItem) { const index = parseInt(listItem.getAttribute('data-index'), 10); - const pathInfos = (currentOptions.library.LibraryOptions || {}).PathInfos || []; + const pathInfos = currentOptions.library.LibraryOptions?.PathInfos || []; const pathInfo = index == null ? {} : pathInfos[index] || {}; const originalPath = pathInfo.Path || (index == null ? null : currentOptions.library.Locations[index]); const btnRemovePath = dom.parentWithClass(e.target, 'btnRemovePath'); @@ -139,7 +139,7 @@ function refreshLibraryFromServer(page) { } function renderLibrary(page, options) { - let pathInfos = (options.library.LibraryOptions || {}).PathInfos || []; + let pathInfos = options.library.LibraryOptions?.PathInfos || []; if (!pathInfos.length) { pathInfos = options.library.Locations.map(p => { @@ -197,7 +197,7 @@ function onDialogClosed() { currentDeferred.resolveWith(null, [hasChanges]); } -export class showEditor { +export class MediaLibraryEditor { constructor(options) { const deferred = jQuery.Deferred(); currentOptions = options; @@ -231,4 +231,4 @@ let currentOptions; let hasChanges = false; let isCreating = false; -export default showEditor; +export default MediaLibraryEditor; diff --git a/src/components/metadataEditor/metadataEditor.js b/src/components/metadataEditor/metadataEditor.js index b21c615cdd..9c15d316b7 100644 --- a/src/components/metadataEditor/metadataEditor.js +++ b/src/components/metadataEditor/metadataEditor.js @@ -759,7 +759,7 @@ function fillItemInfo(context, item, parentalRatingOptions) { context.querySelector('#txtName').value = item.Name || ''; context.querySelector('#txtOriginalName').value = item.OriginalTitle || ''; context.querySelector('#txtOverview').value = item.Overview || ''; - context.querySelector('#txtTagline').value = (item.Taglines && item.Taglines.length ? item.Taglines[0] : ''); + context.querySelector('#txtTagline').value = (item.Taglines?.length ? item.Taglines[0] : ''); context.querySelector('#txtSortName').value = item.ForcedSortName || ''; context.querySelector('#txtCommunityRating').value = item.CommunityRating || ''; @@ -826,7 +826,7 @@ function fillItemInfo(context, item, parentalRatingOptions) { context.querySelector('#txtAirTime').value = item.AirTime || ''; - const placeofBirth = item.ProductionLocations && item.ProductionLocations.length ? item.ProductionLocations[0] : ''; + const placeofBirth = item.ProductionLocations?.length ? item.ProductionLocations[0] : ''; context.querySelector('#txtPlaceOfBirth').value = placeofBirth; context.querySelector('#txtOriginalAspectRatio').value = item.AspectRatio || ''; diff --git a/src/components/multiSelect/multiSelect.js b/src/components/multiSelect/multiSelect.js index 989a421cdb..48cbce0e1f 100644 --- a/src/components/multiSelect/multiSelect.js +++ b/src/components/multiSelect/multiSelect.js @@ -6,7 +6,7 @@ import dom from '../../scripts/dom'; import './multiSelect.scss'; import ServerConnections from '../ServerConnections'; import alert from '../alert'; -import playlistEditor from '../playlisteditor/playlisteditor'; +import PlaylistEditor from '../playlisteditor/playlisteditor'; import confirm from '../confirm/confirm'; import itemHelper from '../itemHelper'; import datetime from '../../scripts/datetime'; @@ -269,7 +269,7 @@ function showMenuForSelectedItems(e) { dispatchNeedsRefresh(); break; case 'playlist': - new playlistEditor({ + new PlaylistEditor({ items: items, serverId: serverId }); @@ -299,8 +299,8 @@ function showMenuForSelectedItems(e) { dispatchNeedsRefresh(); break; case 'refresh': - import('../refreshdialog/refreshdialog').then(({ default: refreshDialog }) => { - new refreshDialog({ + import('../refreshdialog/refreshdialog').then(({ default: RefreshDialog }) => { + new RefreshDialog({ itemIds: items, serverId: serverId }).show(); diff --git a/src/components/nowPlayingBar/nowPlayingBar.js b/src/components/nowPlayingBar/nowPlayingBar.js index d0fbd7e6b4..239b366a31 100644 --- a/src/components/nowPlayingBar/nowPlayingBar.js +++ b/src/components/nowPlayingBar/nowPlayingBar.js @@ -233,7 +233,7 @@ function bindEvents(elem) { positionSlider.getBubbleText = function (value) { const state = lastPlayerState; - if (!state || !state.NowPlayingItem || !currentRuntimeTicks) { + if (!state?.NowPlayingItem || !currentRuntimeTicks) { return '--:--'; } @@ -476,7 +476,7 @@ function imageUrl(item, options) { options = options || {}; options.type = options.type || 'Primary'; - if (item.ImageTags && item.ImageTags[options.type]) { + if (item.ImageTags?.[options.type]) { options.tag = item.ImageTags[options.type]; return ServerConnections.getApiClient(item.ServerId).getScaledImageUrl(item.PrimaryImageItemId || item.Id, options); } diff --git a/src/components/playback/mediasession.js b/src/components/playback/mediasession.js index 3bfe44e37d..d7d2dcabbe 100644 --- a/src/components/playback/mediasession.js +++ b/src/components/playback/mediasession.js @@ -35,7 +35,7 @@ function seriesImageUrl(item, options = {}) { function imageUrl(item, options = {}) { options.type = options.type || 'Primary'; - if (item.ImageTags && item.ImageTags[options.type]) { + if (item.ImageTags?.[options.type]) { options.tag = item.ImageTags[options.type]; return ServerConnections.getApiClient(item.ServerId).getScaledImageUrl(item.Id, options); diff --git a/src/components/playback/nowplayinghelper.js b/src/components/playback/nowplayinghelper.js index a2b72ca84f..7c5dccaf35 100644 --- a/src/components/playback/nowplayinghelper.js +++ b/src/components/playback/nowplayinghelper.js @@ -23,7 +23,7 @@ export function getNowPlayingNames(nowPlayingItem, includeNonNameInfo) { let bottomText = ''; - if (nowPlayingItem.ArtistItems && nowPlayingItem.ArtistItems.length) { + if (nowPlayingItem.ArtistItems?.length) { bottomItem = { Id: nowPlayingItem.ArtistItems[0].Id, Name: nowPlayingItem.ArtistItems[0].Name, @@ -34,7 +34,7 @@ export function getNowPlayingNames(nowPlayingItem, includeNonNameInfo) { bottomText = nowPlayingItem.ArtistItems.map(function (a) { return a.Name; }).join(', '); - } else if (nowPlayingItem.Artists && nowPlayingItem.Artists.length) { + } else if (nowPlayingItem.Artists?.length) { bottomText = nowPlayingItem.Artists.join(', '); } else if (nowPlayingItem.SeriesName || nowPlayingItem.Album) { bottomText = topText; diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js index 77cdb4b6d5..308acd79f5 100644 --- a/src/components/playback/playbackmanager.js +++ b/src/components/playback/playbackmanager.js @@ -163,12 +163,12 @@ function backdropImageUrl(apiClient, item, options) { options.quality = 100; } - if (item.BackdropImageTags && item.BackdropImageTags.length) { + if (item.BackdropImageTags?.length) { options.tag = item.BackdropImageTags[0]; return apiClient.getScaledImageUrl(item.Id, options); } - if (item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) { + if (item.ParentBackdropImageTags?.length) { options.tag = item.ParentBackdropImageTags[0]; return apiClient.getScaledImageUrl(item.ParentBackdropItemId, options); } @@ -773,7 +773,7 @@ class PlaybackManager { self.setActivePlayer = function (player, targetInfo) { if (player === 'localplayer' || player.name === 'localplayer') { - if (self._currentPlayer && self._currentPlayer.isLocalPlayer) { + if (self._currentPlayer?.isLocalPlayer) { return; } setCurrentPlayerInternal(null, null); @@ -795,7 +795,7 @@ class PlaybackManager { self.trySetActivePlayer = function (player, targetInfo) { if (player === 'localplayer' || player.name === 'localplayer') { - if (self._currentPlayer && self._currentPlayer.isLocalPlayer) { + if (self._currentPlayer?.isLocalPlayer) { return; } return; @@ -967,7 +967,7 @@ class PlaybackManager { return player.isPlaying(); } - return player != null && player.currentSrc() != null; + return player?.currentSrc() != null; }; self.isPlayingMediaType = function (mediaType, player) { @@ -989,7 +989,7 @@ class PlaybackManager { self.isPlayingLocally = function (mediaTypes, player) { player = player || self._currentPlayer; - if (!player || !player.isLocalPlayer) { + if (!player?.isLocalPlayer) { return false; } @@ -1068,7 +1068,7 @@ class PlaybackManager { self.setAspectRatio = function (val, player) { player = player || self._currentPlayer; - if (player && player.setAspectRatio) { + if (player?.setAspectRatio) { player.setAspectRatio(val); } }; @@ -1076,7 +1076,7 @@ class PlaybackManager { self.getSupportedAspectRatios = function (player) { player = player || self._currentPlayer; - if (player && player.getSupportedAspectRatios) { + if (player?.getSupportedAspectRatios) { return player.getSupportedAspectRatios(); } @@ -1086,7 +1086,7 @@ class PlaybackManager { self.getAspectRatio = function (player) { player = player || self._currentPlayer; - if (player && player.getAspectRatio) { + if (player?.getAspectRatio) { return player.getAspectRatio(); } }; @@ -1131,7 +1131,7 @@ class PlaybackManager { self.getSupportedPlaybackRates = function (player) { player = player || self._currentPlayer; - if (player && player.getSupportedPlaybackRates) { + if (player?.getSupportedPlaybackRates) { return player.getSupportedPlaybackRates(); } return []; @@ -1351,7 +1351,7 @@ class PlaybackManager { self.getMaxStreamingBitrate = function (player) { player = player || self._currentPlayer; - if (player && player.getMaxStreamingBitrate) { + if (player?.getMaxStreamingBitrate) { return player.getMaxStreamingBitrate(); } @@ -1370,7 +1370,7 @@ class PlaybackManager { self.enableAutomaticBitrateDetection = function (player) { player = player || self._currentPlayer; - if (player && player.enableAutomaticBitrateDetection) { + if (player?.enableAutomaticBitrateDetection) { return player.enableAutomaticBitrateDetection(); } @@ -1386,7 +1386,7 @@ class PlaybackManager { self.setMaxStreamingBitrate = function (options, player) { player = player || self._currentPlayer; - if (player && player.setMaxStreamingBitrate) { + if (player?.setMaxStreamingBitrate) { return player.setMaxStreamingBitrate(options); } @@ -1443,7 +1443,7 @@ class PlaybackManager { document.webkitCancelFullscreen(); } else { const elem = document.querySelector('video'); - if (elem && elem.webkitEnterFullscreen) { + if (elem?.webkitEnterFullscreen) { elem.webkitEnterFullscreen(); } } @@ -2078,7 +2078,7 @@ class PlaybackManager { const mediaSource = self.currentMediaSource(player); - if (mediaSource && mediaSource.RunTimeTicks) { + if (mediaSource?.RunTimeTicks) { return mediaSource.RunTimeTicks; } @@ -2614,7 +2614,7 @@ class PlaybackManager { if (mediaSource.MediaStreams && player.useFullSubtitleUrls) { mediaSource.MediaStreams.forEach(stream => { - if (stream.DeliveryUrl && stream.DeliveryUrl.startsWith('/')) { + if (stream.DeliveryUrl?.startsWith('/')) { stream.DeliveryUrl = apiClient.getUrl(stream.DeliveryUrl); } }); @@ -3444,7 +3444,7 @@ class PlaybackManager { const streamInfo = getPlayerData(player).streamInfo; - if (streamInfo && streamInfo.started && !streamInfo.ended) { + if (streamInfo?.started && !streamInfo.ended) { reportPlayback(self, state, player, reportPlaylist, serverId, 'reportPlaybackProgress', progressEventName); } @@ -3515,7 +3515,7 @@ class PlaybackManager { const nextItem = this._playQueueManager.getNextItemInfo(); - if (!nextItem || !nextItem.item) { + if (!nextItem?.item) { return Promise.reject(); } @@ -3656,7 +3656,7 @@ class PlaybackManager { async playTrailers(item) { const player = this._currentPlayer; - if (player && player.playTrailers) { + if (player?.playTrailers) { return player.playTrailers(item); } @@ -3668,7 +3668,7 @@ class PlaybackManager { items = await apiClient.getLocalTrailers(apiClient.getCurrentUserId(), item.Id); } - if (!items || !items.length) { + if (!items?.length) { items = (item.RemoteTrailers || []).map((t) => { return { Name: t.Name || (item.Name + ' Trailer'), @@ -3750,7 +3750,7 @@ class PlaybackManager { } setPlaybackRate(value, player = this._currentPlayer) { - if (player && player.setPlaybackRate) { + if (player?.setPlaybackRate) { player.setPlaybackRate(value); // Save the new playback rate in the browser session, to restore when playing a new video. @@ -3759,7 +3759,7 @@ class PlaybackManager { } getPlaybackRate(player = this._currentPlayer) { - if (player && player.getPlaybackRate) { + if (player?.getPlaybackRate) { return player.getPlaybackRate(); } @@ -3767,7 +3767,7 @@ class PlaybackManager { } instantMix(item, player = this._currentPlayer) { - if (player && player.instantMix) { + if (player?.instantMix) { return player.instantMix(item); } @@ -3788,7 +3788,7 @@ class PlaybackManager { } shuffle(shuffleItem, player = this._currentPlayer) { - if (player && player.shuffle) { + if (player?.shuffle) { return player.shuffle(shuffleItem); } @@ -3805,7 +3805,7 @@ class PlaybackManager { const mediaSource = this.currentMediaSource(player); - const mediaStreams = (mediaSource || {}).MediaStreams || []; + const mediaStreams = mediaSource?.MediaStreams || []; return mediaStreams.filter(function (s) { return s.Type === 'Audio'; }).sort(itemHelper.sortTracks); @@ -3821,7 +3821,7 @@ class PlaybackManager { const mediaSource = this.currentMediaSource(player); - const mediaStreams = (mediaSource || {}).MediaStreams || []; + const mediaStreams = mediaSource?.MediaStreams || []; return mediaStreams.filter(function (s) { return s.Type === 'Subtitle'; }).sort(itemHelper.sortTracks); @@ -3960,7 +3960,7 @@ class PlaybackManager { } displayContent(options, player = this._currentPlayer) { - if (player && player.displayContent) { + if (player?.displayContent) { player.displayContent(options); } } diff --git a/src/components/playback/playbackorientation.js b/src/components/playback/playbackorientation.js index a4bd8324c6..b581801f9e 100644 --- a/src/components/playback/playbackorientation.js +++ b/src/components/playback/playbackorientation.js @@ -1,4 +1,3 @@ - import { playbackManager } from './playbackmanager'; import layoutManager from '../layoutManager'; import Events from '../../utils/events.ts'; @@ -19,7 +18,7 @@ Events.on(playbackManager, 'playbackstart', function (e, player) { if (isLocalVideo && layoutManager.mobile) { /* eslint-disable-next-line compat/compat */ - const lockOrientation = window.screen.lockOrientation || window.screen.mozLockOrientation || window.screen.msLockOrientation || (window.screen.orientation && window.screen.orientation.lock); + const lockOrientation = window.screen.lockOrientation || window.screen.mozLockOrientation || window.screen.msLockOrientation || (window.screen.orientation?.lock); if (lockOrientation) { try { @@ -40,7 +39,7 @@ Events.on(playbackManager, 'playbackstart', function (e, player) { Events.on(playbackManager, 'playbackstop', function (e, playbackStopInfo) { if (orientationLocked && !playbackStopInfo.nextMediaType) { /* eslint-disable-next-line compat/compat */ - const unlockOrientation = window.screen.unlockOrientation || window.screen.mozUnlockOrientation || window.screen.msUnlockOrientation || (window.screen.orientation && window.screen.orientation.unlock); + const unlockOrientation = window.screen.unlockOrientation || window.screen.mozUnlockOrientation || window.screen.msUnlockOrientation || (window.screen.orientation?.unlock); if (unlockOrientation) { try { diff --git a/src/components/playback/playersettingsmenu.js b/src/components/playback/playersettingsmenu.js index da3be20970..e0acde509b 100644 --- a/src/components/playback/playersettingsmenu.js +++ b/src/components/playback/playersettingsmenu.js @@ -248,7 +248,7 @@ export function show(options) { const player = options.player; const currentItem = playbackManager.currentItem(player); - if (!currentItem || !currentItem.ServerId) { + if (!currentItem?.ServerId) { return showWithUser(options, player, null); } diff --git a/src/components/playback/playmethodhelper.js b/src/components/playback/playmethodhelper.js index 1e7002b45d..5c9511adbc 100644 --- a/src/components/playback/playmethodhelper.js +++ b/src/components/playback/playmethodhelper.js @@ -3,9 +3,9 @@ export function getDisplayPlayMethod(session) { return null; } - if (session.TranscodingInfo && session.TranscodingInfo.IsVideoDirect && session.TranscodingInfo.IsAudioDirect) { + if (session.TranscodingInfo?.IsVideoDirect && session.TranscodingInfo.IsAudioDirect) { return 'Remux'; - } else if (session.TranscodingInfo && session.TranscodingInfo.IsVideoDirect) { + } else if (session.TranscodingInfo?.IsVideoDirect) { return 'DirectStream'; } else if (session.PlayState.PlayMethod === 'Transcode') { return 'Transcode'; diff --git a/src/components/playerstats/playerstats.js b/src/components/playerstats/playerstats.js index d03db1ef71..2d34723721 100644 --- a/src/components/playerstats/playerstats.js +++ b/src/components/playerstats/playerstats.js @@ -166,7 +166,7 @@ function getTranscodingStats(session, player, displayPlayMethod) { value: session.TranscodingInfo.Framerate + ' fps' }); } - if (session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) { + if (session.TranscodingInfo.TranscodeReasons?.length) { sessionStats.push({ label: globalize.translate('LabelReasonForTranscoding'), value: session.TranscodingInfo.TranscodeReasons.map(translateReason).join('
') diff --git a/src/components/playlisteditor/playlisteditor.js b/src/components/playlisteditor/playlisteditor.js index f0fef99aec..ee7cd2b41a 100644 --- a/src/components/playlisteditor/playlisteditor.js +++ b/src/components/playlisteditor/playlisteditor.js @@ -221,7 +221,7 @@ function centerFocus(elem, horiz, on) { }); } -export class showEditor { +export class PlaylistEditor { constructor(options) { const items = options.items || {}; currentServerId = options.serverId; @@ -280,4 +280,4 @@ export class showEditor { } } -export default showEditor; +export default PlaylistEditor; diff --git a/src/components/pluginManager.js b/src/components/pluginManager.js index d8aea5293c..948912cbd8 100644 --- a/src/components/pluginManager.js +++ b/src/components/pluginManager.js @@ -72,13 +72,13 @@ class PluginManager { throw new TypeError('Plugin definitions in window have to be an (async) function returning the plugin class'); } - const pluginClass = await pluginDefinition(); - if (typeof pluginClass !== 'function') { + const PluginClass = await pluginDefinition(); + if (typeof PluginClass !== 'function') { throw new TypeError(`Plugin definition doesn't return a class for '${pluginSpec}'`); } // init plugin and pass basic dependencies - plugin = new pluginClass({ + plugin = new PluginClass({ events: Events, loading, appSettings, diff --git a/src/components/recordingcreator/recordingcreator.js b/src/components/recordingcreator/recordingcreator.js index ac07e200b5..7bee9dccc7 100644 --- a/src/components/recordingcreator/recordingcreator.js +++ b/src/components/recordingcreator/recordingcreator.js @@ -6,7 +6,7 @@ import loading from '../loading/loading'; import scrollHelper from '../../scripts/scrollHelper'; import datetime from '../../scripts/datetime'; import imageLoader from '../images/imageLoader'; -import recordingFields from './recordingfields'; +import RecordingFields from './recordingfields'; import Events from '../../utils/events.ts'; import '../../elements/emby-button/emby-button'; import '../../elements/emby-button/paper-icon-button-light'; @@ -170,7 +170,7 @@ function showEditor(itemId, serverId) { Events.off(currentRecordingFields, 'recordingchanged', onRecordingChanged); executeCloseAction(closeAction, itemId, serverId); - if (currentRecordingFields && currentRecordingFields.hasChanged()) { + if (currentRecordingFields?.hasChanged()) { resolve(); } else { reject(); @@ -185,7 +185,7 @@ function showEditor(itemId, serverId) { reload(dlg, itemId, serverId); - currentRecordingFields = new recordingFields({ + currentRecordingFields = new RecordingFields({ parent: dlg.querySelector('.recordingFields'), programId: itemId, serverId: serverId diff --git a/src/components/remotecontrol/remotecontrol.js b/src/components/remotecontrol/remotecontrol.js index f6af1a864f..b790edded4 100644 --- a/src/components/remotecontrol/remotecontrol.js +++ b/src/components/remotecontrol/remotecontrol.js @@ -119,7 +119,7 @@ function imageUrl(item, options) { options = options || {}; options.type = options.type || 'Primary'; - if (item.ImageTags && item.ImageTags[options.type]) { + if (item.ImageTags?.[options.type]) { options.tag = item.ImageTags[options.type]; return ServerConnections.getApiClient(item.ServerId).getScaledImageUrl(item.PrimaryImageItemId || item.Id, options); } @@ -691,10 +691,10 @@ export default function () { } function savePlaylist() { - import('../playlisteditor/playlisteditor').then(({ default: playlistEditor }) => { + import('../playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { getSaveablePlaylistItems().then(function (items) { const serverId = items.length ? items[0].ServerId : ApiClient.serverId(); - new playlistEditor({ + new PlaylistEditor({ items: items.map(function (i) { return i.Id; }), @@ -800,7 +800,7 @@ export default function () { positionSlider.getBubbleText = function (value) { const state = lastPlayerState; - if (!state || !state.NowPlayingItem || !currentRuntimeTicks) { + if (!state?.NowPlayingItem || !currentRuntimeTicks) { return '--:--'; } diff --git a/src/components/router/appRouter.js b/src/components/router/appRouter.js index 9ea1d66ea8..253fdee922 100644 --- a/src/components/router/appRouter.js +++ b/src/components/router/appRouter.js @@ -321,7 +321,7 @@ class AppRouter { path: ctx.path }; }).catch((result) => { - if (!result || !result.cancelled) { + if (!result?.cancelled) { onNewViewNeeded(); } }); @@ -403,7 +403,7 @@ class AppRouter { const isCurrentRouteStartup = this.currentRouteInfo ? this.currentRouteInfo.route.startup : true; const shouldExitApp = ctx.isBack && route.isDefaultRoute && isCurrentRouteStartup; - if (!shouldExitApp && (!apiClient || !apiClient.isLoggedIn()) && !route.anonymous) { + if (!shouldExitApp && (!apiClient?.isLoggedIn()) && !route.anonymous) { console.debug('[appRouter] route does not allow anonymous access: redirecting to login'); this.#beginConnectionWizard(); return; @@ -417,7 +417,7 @@ class AppRouter { return; } - if (apiClient && apiClient.isLoggedIn()) { + if (apiClient?.isLoggedIn()) { console.debug('[appRouter] user is authenticated'); if (route.roles) { diff --git a/src/components/shortcuts.js b/src/components/shortcuts.js index 4dfbce8c5d..7dc840e8b6 100644 --- a/src/components/shortcuts.js +++ b/src/components/shortcuts.js @@ -33,7 +33,7 @@ function playAllFromHere(card, serverId, queue) { } const itemsContainer = dom.parentWithClass(card, 'itemsContainer'); - if (itemsContainer && itemsContainer.fetchData) { + if (itemsContainer?.fetchData) { const queryOptions = queue ? { StartIndex: startIndex } : {}; return itemsContainer.fetchData(queryOptions).then(result => { @@ -270,8 +270,8 @@ function executeAction(card, target, action) { } function addToPlaylist(item) { - import('./playlisteditor/playlisteditor').then(({ default: playlistEditor }) => { - new playlistEditor().show({ + import('./playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { + new PlaylistEditor().show({ items: [item.Id], serverId: item.ServerId diff --git a/src/components/slideshow/slideshow.js b/src/components/slideshow/slideshow.js index 5ec641b683..20307c9d18 100644 --- a/src/components/slideshow/slideshow.js +++ b/src/components/slideshow/slideshow.js @@ -41,7 +41,7 @@ function getImageUrl(item, options, apiClient) { return apiClient.getScaledImageUrl(item, options); } - if (item.ImageTags && item.ImageTags[options.type]) { + if (item.ImageTags?.[options.type]) { options.tag = item.ImageTags[options.type]; return apiClient.getScaledImageUrl(item.Id, options); } @@ -70,7 +70,7 @@ function getBackdropImageUrl(item, options, apiClient) { options.quality = 100; } - if (item.BackdropImageTags && item.BackdropImageTags.length) { + if (item.BackdropImageTags?.length) { options.tag = item.BackdropImageTags[0]; return apiClient.getScaledImageUrl(item.Id, options); } @@ -87,7 +87,7 @@ function getImgUrl(item, user) { const apiClient = ServerConnections.getApiClient(item.ServerId); const imageOptions = {}; - if (item.BackdropImageTags && item.BackdropImageTags.length) { + if (item.BackdropImageTags?.length) { return getBackdropImageUrl(item, imageOptions, apiClient); } else { if (item.MediaType === 'Photo' && user && user.Policy.EnableContentDownloading) { diff --git a/src/components/tabbedview/tabbedview.js b/src/components/tabbedview/tabbedview.js index 8c865ec9f6..2bb85db8c3 100644 --- a/src/components/tabbedview/tabbedview.js +++ b/src/components/tabbedview/tabbedview.js @@ -65,7 +65,7 @@ class TabbedView { const previousIndex = e.detail.previousIndex; const previousTabController = previousIndex == null ? null : self.tabControllers[previousIndex]; - if (previousTabController && previousTabController.onPause) { + if (previousTabController?.onPause) { previousTabController.onPause(); } @@ -93,7 +93,7 @@ class TabbedView { if (!currentTabController) { mainTabsManager.selectedTabIndex(this.initialTabIndex); - } else if (currentTabController && currentTabController.onResume) { + } else if (currentTabController?.onResume) { currentTabController.onResume({}); } } @@ -101,7 +101,7 @@ class TabbedView { onPause() { const currentTabController = this.currentTabController; - if (currentTabController && currentTabController.onPause) { + if (currentTabController?.onPause) { currentTabController.onPause(); } } diff --git a/src/components/themeMediaPlayer.js b/src/components/themeMediaPlayer.js index 9dea2a7770..bad76612ce 100644 --- a/src/components/themeMediaPlayer.js +++ b/src/components/themeMediaPlayer.js @@ -86,7 +86,7 @@ document.addEventListener('viewshow', function (e) { const state = e.detail.state || {}; const item = state.item; - if (item && item.ServerId) { + if (item?.ServerId) { loadThemeMedia(item); return; } diff --git a/src/components/tunerPicker.js b/src/components/tunerPicker.js index 68c6644092..5cb34addc7 100644 --- a/src/components/tunerPicker.js +++ b/src/components/tunerPicker.js @@ -120,7 +120,7 @@ function discoverDevices(view) { }); } -function tunerPicker() { +function TunerPicker() { this.show = function () { const dialogOptions = { removeOnClose: true, @@ -182,4 +182,4 @@ function tunerPicker() { let currentDevices = []; -export default tunerPicker; +export default TunerPicker; diff --git a/src/components/viewManager/ViewManagerPage.tsx b/src/components/viewManager/ViewManagerPage.tsx index 98cf0dcb01..8795e9edd2 100644 --- a/src/components/viewManager/ViewManagerPage.tsx +++ b/src/components/viewManager/ViewManagerPage.tsx @@ -47,7 +47,7 @@ const ViewManagerPage: FunctionComponent = ({ viewManager.tryRestoreView(viewOptions) .catch(async (result?: RestoreViewFailResponse) => { - if (!result || !result.cancelled) { + if (!result?.cancelled) { const [ controllerFactory, viewHtml ] = await Promise.all([ import(/* webpackChunkName: "[request]" */ `../../controllers/${controller}`), import(/* webpackChunkName: "[request]" */ `../../controllers/${view}`) diff --git a/src/components/viewManager/viewManager.js b/src/components/viewManager/viewManager.js index 12a5f1a9d6..9f02fe3042 100644 --- a/src/components/viewManager/viewManager.js +++ b/src/components/viewManager/viewManager.js @@ -21,6 +21,7 @@ viewContainer.setOnBeforeChange(function (newView, isRestored, options) { newView.initComplete = true; if (typeof options.controllerFactory === 'function') { + // eslint-disable-next-line new-cap new options.controllerFactory(newView, eventDetail.detail.params); } else if (options.controllerFactory && typeof options.controllerFactory.default === 'function') { new options.controllerFactory.default(newView, eventDetail.detail.params); diff --git a/src/controllers/dashboard/dashboard.js b/src/controllers/dashboard/dashboard.js index 95912a55d6..372000a685 100644 --- a/src/controllers/dashboard/dashboard.js +++ b/src/controllers/dashboard/dashboard.js @@ -47,7 +47,7 @@ function showPlaybackInfo(btn, session) { text.push(globalize.translate('MediaIsBeingConverted')); text.push(DashboardPage.getSessionNowPlayingStreamInfo(session)); - if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) { + if (session.TranscodingInfo?.TranscodeReasons?.length) { text.push('
'); text.push(globalize.translate('LabelReasonForTranscoding')); session.TranscodingInfo.TranscodeReasons.forEach(function (transcodeReason) { @@ -90,7 +90,7 @@ function showOptionsMenu(btn, session) { }); } - if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) { + if (session.TranscodingInfo?.TranscodeReasons?.length) { menuItems.push({ name: globalize.translate('ViewPlaybackInfo'), id: 'transcodinginfo' @@ -402,7 +402,7 @@ window.DashboardPage = { } else if (displayPlayMethod === 'DirectStream') { html += globalize.translate('DirectStreaming'); } else if (displayPlayMethod === 'Transcode') { - if (session.TranscodingInfo && session.TranscodingInfo.Framerate) { + if (session.TranscodingInfo?.Framerate) { html += `${globalize.translate('Framerate')}: ${session.TranscodingInfo.Framerate}fps`; } @@ -481,7 +481,7 @@ window.DashboardPage = { let topText = escapeHtml(itemHelper.getDisplayName(nowPlayingItem)); let bottomText = ''; - if (nowPlayingItem.Artists && nowPlayingItem.Artists.length) { + if (nowPlayingItem.Artists?.length) { bottomText = topText; topText = escapeHtml(nowPlayingItem.Artists[0]); } else { @@ -493,7 +493,7 @@ window.DashboardPage = { } } - if (nowPlayingItem.ImageTags && nowPlayingItem.ImageTags.Logo) { + if (nowPlayingItem.ImageTags?.Logo) { imgUrl = ApiClient.getScaledImageUrl(nowPlayingItem.Id, { tag: nowPlayingItem.ImageTags.Logo, maxHeight: 24, @@ -571,7 +571,7 @@ window.DashboardPage = { const btnSessionPlayPauseIcon = btnSessionPlayPause.querySelector('.material-icons'); btnSessionPlayPauseIcon.classList.remove('play_arrow', 'pause'); - btnSessionPlayPauseIcon.classList.add(session.PlayState && session.PlayState.IsPaused ? 'play_arrow' : 'pause'); + btnSessionPlayPauseIcon.classList.add(session.PlayState?.IsPaused ? 'play_arrow' : 'pause'); row.querySelector('.sessionNowPlayingTime').innerText = DashboardPage.getSessionNowPlayingTime(session); row.querySelector('.sessionUserName').innerHTML = DashboardPage.getUsersHtml(session); @@ -620,7 +620,7 @@ window.DashboardPage = { getNowPlayingImageUrl: function (item) { /* Screen width is multiplied by 0.2, as the there is currently no way to get the width of elements that aren't created yet. */ - if (item && item.BackdropImageTags && item.BackdropImageTags.length) { + if (item?.BackdropImageTags?.length) { return ApiClient.getScaledImageUrl(item.Id, { maxWidth: Math.round(dom.getScreenWidth() * 0.20), type: 'Backdrop', @@ -628,7 +628,7 @@ window.DashboardPage = { }); } - if (item && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) { + if (item?.ParentBackdropImageTags?.length) { return ApiClient.getScaledImageUrl(item.ParentBackdropItemId, { maxWidth: Math.round(dom.getScreenWidth() * 0.20), type: 'Backdrop', @@ -636,7 +636,7 @@ window.DashboardPage = { }); } - if (item && item.BackdropImageTag) { + if (item?.BackdropImageTag) { return ApiClient.getScaledImageUrl(item.BackdropItemId, { maxWidth: Math.round(dom.getScreenWidth() * 0.20), type: 'Backdrop', @@ -644,7 +644,7 @@ window.DashboardPage = { }); } - const imageTags = (item || {}).ImageTags || {}; + const imageTags = item?.ImageTags || {}; if (item && imageTags.Thumb) { return ApiClient.getScaledImageUrl(item.Id, { @@ -654,7 +654,7 @@ window.DashboardPage = { }); } - if (item && item.ParentThumbImageTag) { + if (item?.ParentThumbImageTag) { return ApiClient.getScaledImageUrl(item.ParentThumbItemId, { maxWidth: Math.round(dom.getScreenWidth() * 0.20), type: 'Thumb', @@ -662,7 +662,7 @@ window.DashboardPage = { }); } - if (item && item.ThumbImageTag) { + if (item?.ThumbImageTag) { return ApiClient.getScaledImageUrl(item.ThumbItemId, { maxWidth: Math.round(dom.getScreenWidth() * 0.20), type: 'Thumb', @@ -678,7 +678,7 @@ window.DashboardPage = { }); } - if (item && item.PrimaryImageTag) { + if (item?.PrimaryImageTag) { return ApiClient.getScaledImageUrl(item.PrimaryImageItemId, { maxWidth: Math.round(dom.getScreenWidth() * 0.20), type: 'Primary', @@ -686,7 +686,7 @@ window.DashboardPage = { }); } - if (item && item.AlbumPrimaryImageTag) { + if (item?.AlbumPrimaryImageTag) { return ApiClient.getScaledImageUrl(item.AlbumId, { maxWidth: Math.round(dom.getScreenWidth() * 0.20), type: 'Primary', diff --git a/src/controllers/dashboard/dlna/profile.js b/src/controllers/dashboard/dlna/profile.js index dd3e3ad957..47583f2510 100644 --- a/src/controllers/dashboard/dlna/profile.js +++ b/src/controllers/dashboard/dlna/profile.js @@ -415,7 +415,7 @@ function renderContainerProfiles(page, profiles) { html += ''; html += '

' + globalize.translate('ValueContainer', profile.Container || allText) + '

'; - if (profile.Conditions && profile.Conditions.length) { + if (profile.Conditions?.length) { html += '

'; html += globalize.translate('ValueConditions', profile.Conditions.map(function (c) { return c.Property; @@ -487,7 +487,7 @@ function renderCodecProfiles(page, profiles) { html += ''; html += '

' + globalize.translate('ValueCodec', profile.Codec || allText) + '

'; - if (profile.Conditions && profile.Conditions.length) { + if (profile.Conditions?.length) { html += '

'; html += globalize.translate('ValueConditions', profile.Conditions.map(function (c) { return c.Property; @@ -567,7 +567,7 @@ function renderResponseProfiles(page, profiles) { } } - if (profile.Conditions && profile.Conditions.length) { + if (profile.Conditions?.length) { html += '

'; html += globalize.translate('ValueConditions', profile.Conditions.map(function (c) { return c.Property; diff --git a/src/controllers/dashboard/library.js b/src/controllers/dashboard/library.js index f9d80fa3fc..08203b76f6 100644 --- a/src/controllers/dashboard/library.js +++ b/src/controllers/dashboard/library.js @@ -13,8 +13,8 @@ import confirm from '../../components/confirm/confirm'; import cardBuilder from '../../components/cardbuilder/cardBuilder'; function addVirtualFolder(page) { - import('../../components/mediaLibraryCreator/mediaLibraryCreator').then(({ default: medialibrarycreator }) => { - new medialibrarycreator({ + import('../../components/mediaLibraryCreator/mediaLibraryCreator').then(({ default: MediaLibraryCreator }) => { + new MediaLibraryCreator({ collectionTypeOptions: getCollectionTypeOptions().filter(function (f) { return !f.hidden; }), @@ -28,8 +28,8 @@ function addVirtualFolder(page) { } function editVirtualFolder(page, virtualFolder) { - import('../../components/mediaLibraryEditor/mediaLibraryEditor').then(({ default: medialibraryeditor }) => { - new medialibraryeditor({ + import('../../components/mediaLibraryEditor/mediaLibraryEditor').then(({ default: MediaLibraryEditor }) => { + new MediaLibraryEditor({ refresh: shouldRefreshLibraryAfterChanges(page), library: virtualFolder }).then(function (hasChanges) { @@ -62,8 +62,8 @@ function deleteVirtualFolder(page, virtualFolder) { } function refreshVirtualFolder(page, virtualFolder) { - import('../../components/refreshdialog/refreshdialog').then(({ default: refreshDialog }) => { - new refreshDialog({ + import('../../components/refreshdialog/refreshdialog').then(({ default: RefreshDialog }) => { + new RefreshDialog({ itemIds: [virtualFolder.ItemId], serverId: ApiClient.serverId(), mode: 'scan' diff --git a/src/controllers/dashboard/scheduledtasks/scheduledtask.js b/src/controllers/dashboard/scheduledtasks/scheduledtask.js index 5abb615001..215948205f 100644 --- a/src/controllers/dashboard/scheduledtasks/scheduledtask.js +++ b/src/controllers/dashboard/scheduledtasks/scheduledtask.js @@ -24,12 +24,6 @@ function fillTimeOfDay(select) { }).join(''); } -Array.prototype.remove = function (from, to) { - const rest = this.slice((to || from) + 1 || this.length); - this.length = from < 0 ? this.length + from : from; - return this.push.apply(this, rest); -}; - const ScheduledTaskPage = { refreshScheduledTask: function (view) { loading.show(); @@ -143,7 +137,7 @@ const ScheduledTaskPage = { loading.show(); const id = getParameterByName('id'); ApiClient.getScheduledTask(id).then(function (task) { - task.Triggers.remove(index); + task.Triggers.splice(index, 1); ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function () { ScheduledTaskPage.refreshScheduledTask(view); }); diff --git a/src/controllers/home.js b/src/controllers/home.js index 657d406f67..e85d4eb83a 100644 --- a/src/controllers/home.js +++ b/src/controllers/home.js @@ -49,11 +49,11 @@ class HomeView extends TabbedView { } const instance = this; - return import(/* webpackChunkName: "[request]" */ `../controllers/${depends}`).then(({ default: controllerFactory }) => { + return import(/* webpackChunkName: "[request]" */ `../controllers/${depends}`).then(({ default: ControllerFactory }) => { let controller = instance.tabControllers[index]; if (!controller) { - controller = new controllerFactory(instance.view.querySelector(".tabContent[data-index='" + index + "']"), instance.params); + controller = new ControllerFactory(instance.view.querySelector(".tabContent[data-index='" + index + "']"), instance.params); instance.tabControllers[index] = controller; } diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index 68d431b0c4..37f5d3108a 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -406,7 +406,7 @@ function renderName(item, container, context) { if (item.AlbumArtists) { parentNameHtml.push(getArtistLinksHtml(item.AlbumArtists, item.ServerId, context)); parentNameLast = true; - } else if (item.ArtistItems && item.ArtistItems.length && item.Type === 'MusicVideo') { + } else if (item.ArtistItems?.length && item.Type === 'MusicVideo') { parentNameHtml.push(getArtistLinksHtml(item.ArtistItems, item.ServerId, context)); parentNameLast = true; } else if (item.SeriesName && item.Type === 'Episode') { @@ -475,7 +475,7 @@ function renderName(item, container, context) { } function setTrailerButtonVisibility(page, item) { - if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && playbackManager.getSupportedCommands().indexOf('PlayTrailers') !== -1) { + if ((item.LocalTrailerCount || item.RemoteTrailers?.length) && playbackManager.getSupportedCommands().indexOf('PlayTrailers') !== -1) { hideAll(page, 'btnPlayTrailer', true); } else { hideAll(page, 'btnPlayTrailer'); @@ -505,7 +505,7 @@ function renderDetailPageBackdrop(page, item, apiClient) { let hasbackdrop = false; const itemBackdropElement = page.querySelector('#itemBackdrop'); - if (item.BackdropImageTags && item.BackdropImageTags.length) { + if (item.BackdropImageTags?.length) { imgUrl = apiClient.getScaledImageUrl(item.Id, { type: 'Backdrop', maxWidth: dom.getScreenWidth(), @@ -523,7 +523,7 @@ function renderDetailPageBackdrop(page, item, apiClient) { }); imageLoader.lazyImage(itemBackdropElement, imgUrl); hasbackdrop = true; - } else if (item.ImageTags && item.ImageTags.Primary) { + } else if (item.ImageTags?.Primary) { imgUrl = apiClient.getScaledImageUrl(item.Id, { type: 'Primary', maxWidth: dom.getScreenWidth(), @@ -660,7 +660,7 @@ function logoImageUrl(item, apiClient, options) { options = options || {}; options.type = 'Logo'; - if (item.ImageTags && item.ImageTags.Logo) { + if (item.ImageTags?.Logo) { options.tag = item.ImageTags.Logo; return apiClient.getScaledImageUrl(item.Id, options); } @@ -691,8 +691,8 @@ function showRecordingFields(instance, page, item, user) { const recordingFieldsElement = page.querySelector('.recordingFields'); if (item.Type == 'Program' && user.Policy.EnableLiveTvManagement) { - import('../../components/recordingcreator/recordingfields').then(({ default: recordingFields }) => { - instance.currentRecordingFields = new recordingFields({ + import('../../components/recordingcreator/recordingfields').then(({ default: RecordingFields }) => { + instance.currentRecordingFields = new RecordingFields({ parent: recordingFieldsElement, programId: item.Id, serverId: item.ServerId @@ -1054,7 +1054,7 @@ function renderMiscInfo(page, item) { function renderTagline(page, item) { const taglineElement = page.querySelector('.tagline'); - if (item.Taglines && item.Taglines.length) { + if (item.Taglines?.length) { taglineElement.classList.remove('hide'); taglineElement.innerHTML = '' + escapeHtml(item.Taglines[0]) + ''; } else { @@ -1263,7 +1263,7 @@ function renderSeriesAirTime(page, item) { return; } let html = ''; - if (item.AirDays && item.AirDays.length) { + if (item.AirDays?.length) { if (item.AirDays.length == 7) { html += 'daily'; } else { @@ -1826,7 +1826,7 @@ function renderCast(page, item) { }); } -function itemDetailPage() { +function ItemDetailPage() { const self = this; self.setInitialCollapsibleState = setInitialCollapsibleState; self.renderDetails = renderDetails; @@ -1846,7 +1846,7 @@ function onTrackSelectionsSubmit(e) { return false; } -window.ItemDetailPage = new itemDetailPage(); +window.ItemDetailPage = new ItemDetailPage(); export default function (view, params) { function getApiClient() { diff --git a/src/controllers/list.js b/src/controllers/list.js index 62ef3c12cb..0378a1025c 100644 --- a/src/controllers/list.js +++ b/src/controllers/list.js @@ -399,8 +399,8 @@ function showSortMenu() { function onNewItemClick() { const instance = this; - import('../components/playlisteditor/playlisteditor').then(({ default: playlistEditor }) => { - new playlistEditor({ + import('../components/playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { + new PlaylistEditor({ items: [], serverId: instance.params.serverId }); diff --git a/src/controllers/livetv/livetvguide.js b/src/controllers/livetv/livetvguide.js index c56d4ebd04..2d109b6bef 100644 --- a/src/controllers/livetv/livetvguide.js +++ b/src/controllers/livetv/livetvguide.js @@ -1,4 +1,4 @@ -import tvguide from '../../components/guide/guide'; +import Guide from '../../components/guide/guide'; export default function (view, params, tabContent) { let guideInstance; @@ -6,7 +6,7 @@ export default function (view, params, tabContent) { self.renderTab = function () { if (!guideInstance) { - guideInstance = new tvguide({ + guideInstance = new Guide({ element: tabContent, serverId: ApiClient.serverId() }); diff --git a/src/controllers/livetv/livetvsuggested.js b/src/controllers/livetv/livetvsuggested.js index eb604b2d29..d8325f7a2b 100644 --- a/src/controllers/livetv/livetvsuggested.js +++ b/src/controllers/livetv/livetvsuggested.js @@ -229,7 +229,7 @@ export default function (view, params) { function onTabChange(evt) { const previousTabController = tabControllers[parseInt(evt.detail.previousIndex, 10)]; - if (previousTabController && previousTabController.onHide) { + if (previousTabController?.onHide) { previousTabController.onHide(); } @@ -274,7 +274,7 @@ export default function (view, params) { break; } - import(`../livetv/${depends}`).then(({ default: controllerFactory }) => { + import(`../livetv/${depends}`).then(({ default: ControllerFactory }) => { let tabContent; if (index === 0) { @@ -290,7 +290,7 @@ export default function (view, params) { if (index === 0) { controller = self; } else { - controller = new controllerFactory(view, params, tabContent); + controller = new ControllerFactory(view, params, tabContent); } tabControllers[index] = controller; @@ -388,7 +388,7 @@ export default function (view, params) { inputManager.on(window, onInputCommand); }); view.addEventListener('viewbeforehide', function () { - if (currentTabController && currentTabController.onHide) { + if (currentTabController?.onHide) { currentTabController.onHide(); } diff --git a/src/controllers/livetvguideprovider.js b/src/controllers/livetvguideprovider.js index fbc77cc7b6..7a133945f2 100644 --- a/src/controllers/livetvguideprovider.js +++ b/src/controllers/livetvguideprovider.js @@ -9,8 +9,8 @@ function onListingsSubmitted() { } function init(page, type, providerId) { - import(`../components/tvproviders/${type}`).then(({ default: factory }) => { - const instance = new factory(page, providerId, {}); + import(`../components/tvproviders/${type}`).then(({ default: ProviderFactory }) => { + const instance = new ProviderFactory(page, providerId, {}); Events.on(instance, 'submitted', onListingsSubmitted); instance.init(); }); diff --git a/src/controllers/livetvstatus.js b/src/controllers/livetvstatus.js index 5eb13c9793..3c0e304939 100644 --- a/src/controllers/livetvstatus.js +++ b/src/controllers/livetvstatus.js @@ -165,8 +165,8 @@ function showProviderOptions(page, providerId, button) { } function mapChannels(page, providerId) { - import('../components/channelMapper/channelMapper').then(({ default: channelMapper }) => { - new channelMapper({ + import('../components/channelMapper/channelMapper').then(({ default: ChannelMapper }) => { + new ChannelMapper({ serverId: ApiClient.serverInfo().Id, providerId: providerId }).show(); diff --git a/src/controllers/livetvtuner.js b/src/controllers/livetvtuner.js index b15eea9d8a..7f6ec20270 100644 --- a/src/controllers/livetvtuner.js +++ b/src/controllers/livetvtuner.js @@ -106,8 +106,8 @@ function submitForm(page) { } function getDetectedDevice() { - return import('../components/tunerPicker').then(({ default: tunerPicker }) => { - return new tunerPicker().show({ + return import('../components/tunerPicker').then(({ default: TunerPicker }) => { + return new TunerPicker().show({ serverId: ApiClient.serverId() }); }); diff --git a/src/controllers/movies/movies.js b/src/controllers/movies/movies.js index 6ec5243715..0d89706cf8 100644 --- a/src/controllers/movies/movies.js +++ b/src/controllers/movies/movies.js @@ -289,8 +289,8 @@ export default function (view, params, tabContent, options) { query = userSettings.loadQuerySettings(savedQueryKey, query); this.showFilterMenu = function () { - import('../../components/filterdialog/filterdialog').then(({ default: filterDialogFactory }) => { - const filterDialog = new filterDialogFactory({ + import('../../components/filterdialog/filterdialog').then(({ default: FilterDialog }) => { + const filterDialog = new FilterDialog({ query: query, mode: 'movies', serverId: ApiClient.serverId() diff --git a/src/controllers/movies/moviesrecommended.js b/src/controllers/movies/moviesrecommended.js index 2d6aa223cb..1dc60c30e1 100644 --- a/src/controllers/movies/moviesrecommended.js +++ b/src/controllers/movies/moviesrecommended.js @@ -314,7 +314,7 @@ export default function (view, params) { break; } - import(`../movies/${depends}`).then(({ default: controllerFactory }) => { + import(`../movies/${depends}`).then(({ default: ControllerFactory }) => { let tabContent; if (index === suggestionsTabIndex) { @@ -330,11 +330,11 @@ export default function (view, params) { if (index === suggestionsTabIndex) { controller = this; } else if (index == 0 || index == 3) { - controller = new controllerFactory(view, params, tabContent, { + controller = new ControllerFactory(view, params, tabContent, { mode: index ? 'favorites' : 'movies' }); } else { - controller = new controllerFactory(view, params, tabContent); + controller = new ControllerFactory(view, params, tabContent); } tabControllers[index] = controller; diff --git a/src/controllers/movies/movietrailers.js b/src/controllers/movies/movietrailers.js index a96d7e51aa..81f9f8b149 100644 --- a/src/controllers/movies/movietrailers.js +++ b/src/controllers/movies/movietrailers.js @@ -182,8 +182,8 @@ export default function (view, params, tabContent) { let isLoading = false; this.showFilterMenu = function () { - import('../../components/filterdialog/filterdialog').then(({ default: filterDialogFactory }) => { - const filterDialog = new filterDialogFactory({ + import('../../components/filterdialog/filterdialog').then(({ default: FilterDialog }) => { + const filterDialog = new FilterDialog({ query: getQuery(), mode: 'movies', serverId: ApiClient.serverId() diff --git a/src/controllers/music/musicalbums.js b/src/controllers/music/musicalbums.js index 04ea17a983..6c0c45a0f0 100644 --- a/src/controllers/music/musicalbums.js +++ b/src/controllers/music/musicalbums.js @@ -189,8 +189,8 @@ export default function (view, params, tabContent) { let isLoading = false; this.showFilterMenu = function () { - import('../../components/filterdialog/filterdialog').then(({ default: filterDialogFactory }) => { - const filterDialog = new filterDialogFactory({ + import('../../components/filterdialog/filterdialog').then(({ default: FilterDialog }) => { + const filterDialog = new FilterDialog({ query: getQuery(), mode: 'albums', serverId: ApiClient.serverId() diff --git a/src/controllers/music/musicartists.js b/src/controllers/music/musicartists.js index 084f092db3..4126086ade 100644 --- a/src/controllers/music/musicartists.js +++ b/src/controllers/music/musicartists.js @@ -170,8 +170,8 @@ export default function (view, params, tabContent) { let isLoading = false; this.showFilterMenu = function () { - import('../../components/filterdialog/filterdialog').then(({ default: filterDialogFactory }) => { - const filterDialog = new filterDialogFactory({ + import('../../components/filterdialog/filterdialog').then(({ default: FilterDialog }) => { + const filterDialog = new FilterDialog({ query: getQuery(tabContent), mode: this.mode, serverId: ApiClient.serverId() diff --git a/src/controllers/music/musicrecommended.js b/src/controllers/music/musicrecommended.js index 3599ecedc8..dc32aca6f6 100644 --- a/src/controllers/music/musicrecommended.js +++ b/src/controllers/music/musicrecommended.js @@ -290,7 +290,7 @@ export default function (view, params) { break; } - import(`../music/${depends}`).then(({ default: controllerFactory }) => { + import(`../music/${depends}`).then(({ default: ControllerFactory }) => { let tabContent; if (index == 1) { @@ -306,7 +306,7 @@ export default function (view, params) { if (index === 1) { controller = this; } else { - controller = new controllerFactory(view, params, tabContent); + controller = new ControllerFactory(view, params, tabContent); } if (index == 2) { diff --git a/src/controllers/music/songs.js b/src/controllers/music/songs.js index 06af0b3081..5e5337d032 100644 --- a/src/controllers/music/songs.js +++ b/src/controllers/music/songs.js @@ -135,8 +135,8 @@ export default function (view, params, tabContent) { let isLoading = false; self.showFilterMenu = function () { - import('../../components/filterdialog/filterdialog').then(({ default: filterDialogFactory }) => { - const filterDialog = new filterDialogFactory({ + import('../../components/filterdialog/filterdialog').then(({ default: FilterDialog }) => { + const filterDialog = new FilterDialog({ query: getQuery(tabContent), mode: 'songs', serverId: ApiClient.serverId() diff --git a/src/controllers/playback/queue/index.js b/src/controllers/playback/queue/index.js index cf39aa145b..602135a794 100644 --- a/src/controllers/playback/queue/index.js +++ b/src/controllers/playback/queue/index.js @@ -1,9 +1,9 @@ -import remotecontrolFactory from '../../../components/remotecontrol/remotecontrol'; +import RemoteControl from '../../../components/remotecontrol/remotecontrol'; import libraryMenu from '../../../scripts/libraryMenu'; import '../../../elements/emby-button/emby-button'; export default function (view) { - const remoteControl = new remotecontrolFactory(); + const remoteControl = new RemoteControl(); remoteControl.init(view, view.querySelector('.remoteControlContent')); view.addEventListener('viewshow', function () { libraryMenu.setTransparentMenu(true); diff --git a/src/controllers/playback/video/index.js b/src/controllers/playback/video/index.js index cb237d3466..0feb6e3752 100644 --- a/src/controllers/playback/video/index.js +++ b/src/controllers/playback/video/index.js @@ -666,7 +666,7 @@ export default function (view) { if (item.Type === 'TvChannel') { const program = item.CurrentProgram; - if (program && program.EndDate) { + if (program?.EndDate) { try { const endDate = datetime.parseISO8601Date(program.EndDate); @@ -1685,7 +1685,7 @@ export default function (view) { ticks *= value; const item = currentItem; - if (item && item.Chapters && item.Chapters.length && item.Chapters[0].ImageTag) { + if (item?.Chapters?.length && item.Chapters[0].ImageTag) { const html = getChapterBubbleHtml(ServerConnections.getApiClient(item.ServerId), item, item.Chapters, ticks); if (html) { diff --git a/src/controllers/shows/episodes.js b/src/controllers/shows/episodes.js index 38b7d077c3..f2f6c605d7 100644 --- a/src/controllers/shows/episodes.js +++ b/src/controllers/shows/episodes.js @@ -171,8 +171,8 @@ export default function (view, params, tabContent) { let isLoading = false; self.showFilterMenu = function () { - import('../../components/filterdialog/filterdialog').then(({ default: filterDialogFactory }) => { - const filterDialog = new filterDialogFactory({ + import('../../components/filterdialog/filterdialog').then(({ default: FilterDialog }) => { + const filterDialog = new FilterDialog({ query: getQuery(tabContent), mode: 'episodes', serverId: ApiClient.serverId() diff --git a/src/controllers/shows/tvrecommended.js b/src/controllers/shows/tvrecommended.js index 68019511ba..d3673bf6ae 100644 --- a/src/controllers/shows/tvrecommended.js +++ b/src/controllers/shows/tvrecommended.js @@ -268,7 +268,7 @@ export default function (view, params) { break; } - import(`../shows/${depends}`).then(({ default: controllerFactory }) => { + import(`../shows/${depends}`).then(({ default: ControllerFactory }) => { let tabContent; if (index === 1) { @@ -284,7 +284,7 @@ export default function (view, params) { if (index === 1) { controller = self; } else { - controller = new controllerFactory(view, params, tabContent); + controller = new ControllerFactory(view, params, tabContent); } tabControllers[index] = controller; diff --git a/src/controllers/shows/tvshows.js b/src/controllers/shows/tvshows.js index d378cd34d5..3dea00f1b8 100644 --- a/src/controllers/shows/tvshows.js +++ b/src/controllers/shows/tvshows.js @@ -199,8 +199,8 @@ export default function (view, params, tabContent) { let isLoading = false; this.showFilterMenu = function () { - import('../../components/filterdialog/filterdialog').then(({ default: filterDialogFactory }) => { - const filterDialog = new filterDialogFactory({ + import('../../components/filterdialog/filterdialog').then(({ default: FilterDialog }) => { + const filterDialog = new FilterDialog({ query: getQuery(tabContent), mode: 'series', serverId: ApiClient.serverId() diff --git a/src/elements/emby-input/emby-input.js b/src/elements/emby-input/emby-input.js index 1b7067cef8..81b0c3b3ee 100644 --- a/src/elements/emby-input/emby-input.js +++ b/src/elements/emby-input/emby-input.js @@ -12,7 +12,7 @@ if (Object.getOwnPropertyDescriptor && Object.defineProperty) { const descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); // descriptor returning null in webos - if (descriptor && descriptor.configurable) { + if (descriptor?.configurable) { const baseSetMethod = descriptor.set; descriptor.set = function (value) { baseSetMethod.call(this, value); diff --git a/src/elements/emby-itemscontainer/emby-itemscontainer.js b/src/elements/emby-itemscontainer/emby-itemscontainer.js index d34cc25438..b951fa7d2f 100644 --- a/src/elements/emby-itemscontainer/emby-itemscontainer.js +++ b/src/elements/emby-itemscontainer/emby-itemscontainer.js @@ -37,7 +37,7 @@ function onContextMenu(e) { const card = dom.parentWithAttribute(target, 'data-id'); // check for serverId, it won't be present on selectserver - if (card && card.getAttribute('data-serverid')) { + if (card?.getAttribute('data-serverid')) { inputManager.handleCommand('menu', { sourceElement: card }); @@ -357,7 +357,7 @@ ItemsContainerPrototype.resume = function (options) { } } - if (this.needsRefresh || (options && options.refresh)) { + if (this.needsRefresh || (options?.refresh)) { return this.refreshItems(); } diff --git a/src/elements/emby-playstatebutton/emby-playstatebutton.js b/src/elements/emby-playstatebutton/emby-playstatebutton.js index 6e7756d902..6bc43b461a 100644 --- a/src/elements/emby-playstatebutton/emby-playstatebutton.js +++ b/src/elements/emby-playstatebutton/emby-playstatebutton.js @@ -132,7 +132,7 @@ EmbyPlaystateButtonPrototype.setItem = function (item) { this.setAttribute('data-serverid', item.ServerId); this.setAttribute('data-type', item.Type); - const played = item.UserData && item.UserData.Played; + const played = item.UserData?.Played; setState(this, played); bindEvents(this); } else { diff --git a/src/elements/emby-scroller/Scroller.tsx b/src/elements/emby-scroller/Scroller.tsx index 57349bad4c..cb3d5b75b4 100644 --- a/src/elements/emby-scroller/Scroller.tsx +++ b/src/elements/emby-scroller/Scroller.tsx @@ -5,7 +5,7 @@ import layoutManager from '../../components/layoutManager'; import dom from '../../scripts/dom'; import browser from '../../scripts/browser'; import focusManager from '../../components/focusManager'; -import scrollerFactory from '../../libraries/scroller'; +import ScrollerFactory from '../../libraries/scroller'; import ScrollButtons from '../emby-scrollbuttons/ScrollButtons'; import './emby-scroller.scss'; @@ -41,7 +41,7 @@ const Scroller: FC = ({ scrollPos: 0, scrollWidth: 0 }); - const scrollerFactoryRef = useRef(null); + const scrollerFactoryRef = useRef(null); const getScrollSlider = useCallback(() => { if (scrollerFactoryRef.current) { @@ -126,7 +126,7 @@ const Scroller: FC = ({ }); }, [getScrollPosition, getScrollSize, getScrollWidth]); - const initCenterFocus = useCallback((elem, scrollerInstance: scrollerFactory) => { + const initCenterFocus = useCallback((elem, scrollerInstance: ScrollerFactory) => { dom.addEventListener(elem, 'focus', function (e: FocusEvent) { const focused = focusManager.focusableParent(e.target); if (focused) { @@ -179,7 +179,7 @@ const Scroller: FC = ({ }; // If just inserted it might not have any height yet - yes this is a hack - scrollerFactoryRef.current = new scrollerFactory(scrollRef.current, options); + scrollerFactoryRef.current = new ScrollerFactory(scrollRef.current, options); scrollerFactoryRef.current.init(); scrollerFactoryRef.current.reload(); diff --git a/src/elements/emby-scroller/emby-scroller.js b/src/elements/emby-scroller/emby-scroller.js index eb5f3abfe4..cf716bed41 100644 --- a/src/elements/emby-scroller/emby-scroller.js +++ b/src/elements/emby-scroller/emby-scroller.js @@ -1,4 +1,4 @@ -import scroller from '../../libraries/scroller'; +import ScrollerFactory from '../../libraries/scroller'; import dom from '../../scripts/dom'; import layoutManager from '../../components/layoutManager'; import inputManager from '../../scripts/inputManager'; @@ -140,7 +140,7 @@ ScrollerPrototype.attachedCallback = function () { }; // If just inserted it might not have any height yet - yes this is a hack - this.scroller = new scroller(scrollFrame, options); + this.scroller = new ScrollerFactory(scrollFrame, options); this.scroller.init(); this.scroller.reload(); diff --git a/src/elements/emby-slider/emby-slider.js b/src/elements/emby-slider/emby-slider.js index 16c52f5863..ec93e61fd6 100644 --- a/src/elements/emby-slider/emby-slider.js +++ b/src/elements/emby-slider/emby-slider.js @@ -14,7 +14,7 @@ let supportsValueSetOverride = false; if (Object.getOwnPropertyDescriptor && Object.defineProperty) { const descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); // descriptor returning null in webos - if (descriptor && descriptor.configurable) { + if (descriptor?.configurable) { supportsValueSetOverride = true; } } @@ -167,7 +167,7 @@ function setMarker(range, valueMarker, marker, valueProgress) { } function updateMarkers(range, currentValue) { - if (range.markerInfo && range.markerInfo.length && range.markerElements && range.markerElements.length) { + if (range.markerInfo?.length && range.markerElements?.length) { for (let i = 0, length = range.markerElements.length; i < length; i++) { if (range.markerInfo.length > i) { setMarker(range, mapFractionToValue(range, range.markerInfo[i].progress), range.markerElements[i], currentValue); diff --git a/src/elements/emby-tabs/emby-tabs.js b/src/elements/emby-tabs/emby-tabs.js index 22d12e75af..b4b541a3dd 100644 --- a/src/elements/emby-tabs/emby-tabs.js +++ b/src/elements/emby-tabs/emby-tabs.js @@ -1,6 +1,6 @@ import 'webcomponents.js/webcomponents-lite'; import dom from '../../scripts/dom'; -import scroller from '../../libraries/scroller'; +import ScrollerFactory from '../../libraries/scroller'; import browser from '../../scripts/browser'; import focusManager from '../../components/focusManager'; import layoutManager from '../../components/layoutManager'; @@ -124,7 +124,7 @@ function initScroller(tabs) { const contentScrollSlider = tabs.querySelector('.emby-tabs-slider'); if (contentScrollSlider) { - tabs.scroller = new scroller(tabs, { + tabs.scroller = new ScrollerFactory(tabs, { horizontal: 1, itemNav: 0, mouseDragging: 1, diff --git a/src/elements/emby-textarea/emby-textarea.js b/src/elements/emby-textarea/emby-textarea.js index 04ce1a42d9..d186398a06 100644 --- a/src/elements/emby-textarea/emby-textarea.js +++ b/src/elements/emby-textarea/emby-textarea.js @@ -19,7 +19,7 @@ function calculateOffset(textarea) { return offset; } -function autoGrow(textarea, maxLines) { +function AutoGrow(textarea, maxLines) { const self = this; if (maxLines === undefined) { @@ -74,7 +74,7 @@ if (Object.getOwnPropertyDescriptor && Object.defineProperty) { const descriptor = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value'); // descriptor returning null in webos - if (descriptor && descriptor.configurable) { + if (descriptor?.configurable) { const baseSetMethod = descriptor.set; descriptor.set = function (value) { baseSetMethod.call(this, value); @@ -125,7 +125,7 @@ EmbyTextAreaPrototype.attachedCallback = function () { label.innerText = text; }; - new autoGrow(this); + new AutoGrow(this); }; document.registerElement('emby-textarea', { diff --git a/src/legacy/focusPreventScroll.js b/src/legacy/focusPreventScroll.js index ad2f12a4b7..f21cce2d40 100644 --- a/src/legacy/focusPreventScroll.js +++ b/src/legacy/focusPreventScroll.js @@ -33,7 +33,7 @@ if (HTMLElement.prototype.nativeFocus === undefined) { this.nativeFocus(); // Restore window scroll if preventScroll - if (options && options.preventScroll) { + if (options?.preventScroll) { window.scroll(scrollX, scrollY); } }; diff --git a/src/libraries/navdrawer/navdrawer.js b/src/libraries/navdrawer/navdrawer.js index 539682a076..ef6dd1e04f 100644 --- a/src/libraries/navdrawer/navdrawer.js +++ b/src/libraries/navdrawer/navdrawer.js @@ -131,7 +131,7 @@ class NavDrawer { if (this.isPeeking) { this.onMenuTouchMove(e); } else { - if (((getTouches(e)[0] || {}).clientX || 0) <= options.handleSize) { + if ((getTouches(e)[0]?.clientX || 0) <= options.handleSize) { this.isPeeking = true; if (e.type === 'touchstart') { diff --git a/src/libraries/scroller.js b/src/libraries/scroller.js index abfa30cdf0..01038fa0b4 100644 --- a/src/libraries/scroller.js +++ b/src/libraries/scroller.js @@ -904,6 +904,7 @@ scrollerFactory.prototype.toCenter = function (item, immediate) { }; scrollerFactory.create = function (frame, options) { + // eslint-disable-next-line new-cap const instance = new scrollerFactory(frame, options); return Promise.resolve(instance); }; diff --git a/src/plugins/bookPlayer/plugin.js b/src/plugins/bookPlayer/plugin.js index 8924d06951..6418d84e6b 100644 --- a/src/plugins/bookPlayer/plugin.js +++ b/src/plugins/bookPlayer/plugin.js @@ -384,7 +384,7 @@ export class BookPlayer { } canPlayItem(item) { - return item.Path && item.Path.endsWith('epub'); + return item.Path?.endsWith('epub'); } } diff --git a/src/plugins/chromecastPlayer/plugin.js b/src/plugins/chromecastPlayer/plugin.js index deb479c4b4..569e347cd2 100644 --- a/src/plugins/chromecastPlayer/plugin.js +++ b/src/plugins/chromecastPlayer/plugin.js @@ -2,7 +2,7 @@ import appSettings from '../../scripts/settings/appSettings'; import * as userSettings from '../../scripts/settings/userSettings'; import { playbackManager } from '../../components/playback/playbackmanager'; import globalize from '../../scripts/globalize'; -import castSenderApiLoader from './castSenderApi'; +import CastSenderApi from './castSenderApi'; import ServerConnections from '../../components/ServerConnections'; import alert from '../../components/alert'; import { PluginType } from '../../types/plugin.ts'; @@ -103,7 +103,7 @@ class CastPlayer { return; } - if (!chrome.cast || !chrome.cast.isAvailable) { + if (!chrome.cast?.isAvailable) { setTimeout(this.initializeCastPlayer.bind(this), 1000); return; } @@ -322,14 +322,14 @@ class CastPlayer { const session = player.session; - if (session && session.receiver && session.receiver.friendlyName) { + if (session?.receiver?.friendlyName) { receiverName = session.receiver.friendlyName; } let apiClient; - if (message.options && message.options.ServerId) { + if (message.options?.ServerId) { apiClient = ServerConnections.getApiClient(message.options.ServerId); - } else if (message.options && message.options.items && message.options.items.length) { + } else if (message.options?.items?.length) { apiClient = ServerConnections.getApiClient(message.options.items[0].ServerId); } else { apiClient = ServerConnections.currentApiClient(); @@ -350,7 +350,7 @@ class CastPlayer { message.maxBitrate = bitrateSetting; } - if (message.options && message.options.items) { + if (message.options?.items) { message.subtitleAppearance = userSettings.getSubtitleAppearanceSettings(); message.subtitleBurnIn = appSettings.get('subtitleburnin') || ''; } @@ -451,10 +451,10 @@ function onVolumeDownKeyDown() { } function normalizeImages(state) { - if (state && state.NowPlayingItem) { + if (state?.NowPlayingItem) { const item = state.NowPlayingItem; - if ((!item.ImageTags || !item.ImageTags.Primary) && item.PrimaryImageTag) { + if ((!item.ImageTags?.Primary) && item.PrimaryImageTag) { item.ImageTags = item.ImageTags || {}; item.ImageTags.Primary = item.PrimaryImageTag; } @@ -576,7 +576,7 @@ class ChromecastPlayer { this.isLocalPlayer = false; this.lastPlayerData = {}; - new castSenderApiLoader().load().then(initializeChromecast.bind(this)); + new CastSenderApi().load().then(initializeChromecast.bind(this)); } tryPair() { @@ -599,7 +599,7 @@ class ChromecastPlayer { getTargets() { const targets = []; - if (this._castPlayer && this._castPlayer.hasReceivers) { + if (this._castPlayer?.hasReceivers) { targets.push(this.getCurrentTargetInfo()); } @@ -612,7 +612,7 @@ class ChromecastPlayer { const castPlayer = this._castPlayer; - if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.receiver.friendlyName) { + if (castPlayer.session?.receiver?.friendlyName) { appName = castPlayer.session.receiver.friendlyName; } diff --git a/src/plugins/htmlAudioPlayer/plugin.js b/src/plugins/htmlAudioPlayer/plugin.js index a7c7be0c15..2d0c6cceb1 100644 --- a/src/plugins/htmlAudioPlayer/plugin.js +++ b/src/plugins/htmlAudioPlayer/plugin.js @@ -413,7 +413,7 @@ class HtmlAudioPlayer { const mediaElement = this._mediaElement; if (mediaElement) { const seekable = mediaElement.seekable; - if (seekable && seekable.length) { + if (seekable?.length) { let start = seekable.start(0); let end = seekable.end(0); diff --git a/src/plugins/htmlVideoPlayer/plugin.js b/src/plugins/htmlVideoPlayer/plugin.js index 0ec83d6363..b2410ed0ec 100644 --- a/src/plugins/htmlVideoPlayer/plugin.js +++ b/src/plugins/htmlVideoPlayer/plugin.js @@ -1010,7 +1010,7 @@ export class HtmlVideoPlayer { } if (elem.videoWidth === 0 && elem.videoHeight === 0) { - const mediaSource = (this._currentPlayOptions || {}).mediaSource; + const mediaSource = this._currentPlayOptions?.mediaSource; // Only trigger this if there is media info // Avoid triggering in situations where it might not actually have a video stream (audio only live tv channel) @@ -1490,8 +1490,8 @@ export class HtmlVideoPlayer { // add some cues to show the text // in safari, the cues need to be added before setting the track mode to showing for (const trackEvent of data.TrackEvents) { - const trackCueObject = window.VTTCue || window.TextTrackCue; - const cue = new trackCueObject(trackEvent.StartPositionTicks / 10000000, trackEvent.EndPositionTicks / 10000000, normalizeTrackEventText(trackEvent.Text, false)); + const TrackCue = window.VTTCue || window.TextTrackCue; + const cue = new TrackCue(trackEvent.StartPositionTicks / 10000000, trackEvent.EndPositionTicks / 10000000, normalizeTrackEventText(trackEvent.Text, false)); if (cue.line === 'auto') { cue.line = cueLine; @@ -1536,7 +1536,7 @@ export class HtmlVideoPlayer { } } - if (selectedTrackEvent && selectedTrackEvent.Text) { + if (selectedTrackEvent?.Text) { subtitleTextElement.innerHTML = DOMPurify.sanitize( normalizeTrackEventText(selectedTrackEvent.Text, true)); subtitleTextElement.classList.remove('hide'); @@ -1812,7 +1812,7 @@ export class HtmlVideoPlayer { Windows.UI.ViewManagement.ApplicationView.getForCurrentView().tryEnterViewModeAsync(Windows.UI.ViewManagement.ApplicationViewMode.default); } } else { - if (video && video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === 'function') { + if (video?.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === 'function') { video.webkitSetPresentationMode(isEnabled ? 'picture-in-picture' : 'inline'); } } @@ -1891,7 +1891,7 @@ export class HtmlVideoPlayer { const mediaElement = this.#mediaElement; if (mediaElement) { const seekable = mediaElement.seekable; - if (seekable && seekable.length) { + if (seekable?.length) { let start = seekable.start(0); let end = seekable.end(0); diff --git a/src/plugins/logoScreensaver/plugin.js b/src/plugins/logoScreensaver/plugin.js index fc999ccccf..9cd0e1a445 100644 --- a/src/plugins/logoScreensaver/plugin.js +++ b/src/plugins/logoScreensaver/plugin.js @@ -25,7 +25,7 @@ export default function () { const elem = document.querySelector('.logoScreenSaverImage'); - if (elem && elem.animate) { + if (elem?.animate) { const random = randomInt(0, animations.length - 1); animations[random](elem, 1); diff --git a/src/plugins/pdfPlayer/plugin.js b/src/plugins/pdfPlayer/plugin.js index 00625c2776..6a14a4a684 100644 --- a/src/plugins/pdfPlayer/plugin.js +++ b/src/plugins/pdfPlayer/plugin.js @@ -312,7 +312,7 @@ export class PdfPlayer { } canPlayItem(item) { - return item.Path && item.Path.endsWith('pdf'); + return item.Path?.endsWith('pdf'); } } diff --git a/src/plugins/sessionPlayer/plugin.js b/src/plugins/sessionPlayer/plugin.js index 98e0e843ab..6feef63575 100644 --- a/src/plugins/sessionPlayer/plugin.js +++ b/src/plugins/sessionPlayer/plugin.js @@ -157,7 +157,7 @@ function subscribeToPlayerUpdates(instance) { } function normalizeImages(state, apiClient) { - if (state && state.NowPlayingItem) { + if (state?.NowPlayingItem) { const item = state.NowPlayingItem; if (!item.ImageTags || !item.ImageTags.Primary && item.PrimaryImageTag) { diff --git a/src/plugins/syncPlay/core/Manager.js b/src/plugins/syncPlay/core/Manager.js index ee1e3e3ae7..9f25f44608 100644 --- a/src/plugins/syncPlay/core/Manager.js +++ b/src/plugins/syncPlay/core/Manager.js @@ -246,7 +246,7 @@ class Manager { /** * Handles a playback command from the server. - * @param {Object} cmd The playback command. + * @param {Object|null} cmd The playback command. */ processCommand(cmd) { if (cmd === null) return; @@ -294,7 +294,7 @@ class Manager { /** * Handles a group state change. - * @param {Object} update The group state update. + * @param {Object|null} update The group state update. */ processStateChange(update) { if (update === null || update.State === null || update.Reason === null) return; diff --git a/src/scripts/autocast.js b/src/scripts/autocast.js index 854403b4da..9ed7de5df7 100644 --- a/src/scripts/autocast.js +++ b/src/scripts/autocast.js @@ -12,7 +12,7 @@ export function enable(enabled) { if (enabled) { const currentPlayerInfo = playbackManager.getPlayerInfo(); - if (currentPlayerInfo && currentPlayerInfo.id) { + if (currentPlayerInfo?.id) { localStorage.setItem('autocastPlayerId', currentPlayerInfo.id); } } else { diff --git a/src/scripts/browserDeviceProfile.js b/src/scripts/browserDeviceProfile.js index c4623718bc..98be70a9b1 100644 --- a/src/scripts/browserDeviceProfile.js +++ b/src/scripts/browserDeviceProfile.js @@ -3,7 +3,7 @@ import * as userSettings from './settings/userSettings'; import browser from './browser'; function canPlayH264(videoTestElement) { - return !!(videoTestElement.canPlayType && videoTestElement.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, '')); + return !!(videoTestElement.canPlayType?.('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, '')); } function canPlayHevc(videoTestElement, options) { diff --git a/src/scripts/dom.js b/src/scripts/dom.js index 9488c7e16d..cd0fd71849 100644 --- a/src/scripts/dom.js +++ b/src/scripts/dom.js @@ -15,7 +15,7 @@ export function parentWithAttribute(elem, name, value) { while ((value ? elem.getAttribute(name) !== value : !elem.getAttribute(name))) { elem = elem.parentNode; - if (!elem || !elem.getAttribute) { + if (!elem?.getAttribute) { return null; } } @@ -65,7 +65,7 @@ function containsAnyClass(classList, classNames) { * Returns parent of element with one of specified class names. * @param {HTMLElement} elem - Element whose parent need to find. * @param {(string|Array)} classNames - Class name or array of class names. - * @returns {HTMLElement} Parent with one of specified class names. + * @returns {HTMLElement|null} Parent with one of specified class names. */ export function parentWithClass(elem, classNames) { // accept both string and array passed in diff --git a/src/scripts/gamepadtokey.js b/src/scripts/gamepadtokey.js index 847ef02a52..cfd6e3790c 100644 --- a/src/scripts/gamepadtokey.js +++ b/src/scripts/gamepadtokey.js @@ -349,7 +349,7 @@ function isGamepadConnected() { const gamepads = navigator.getGamepads(); /* eslint-disable-line compat/compat */ for (let i = 0, len = gamepads.length; i < len; i++) { const gamepad = gamepads[i]; - if (gamepad && gamepad.connected) { + if (gamepad?.connected) { return true; } } diff --git a/src/scripts/globalize.js b/src/scripts/globalize.js index 256207acec..21260e2be4 100644 --- a/src/scripts/globalize.js +++ b/src/scripts/globalize.js @@ -37,7 +37,7 @@ function getDefaultLanguage() { if (navigator.userLanguage) { return navigator.userLanguage; } - if (navigator.languages && navigator.languages.length) { + if (navigator.languages?.length) { return navigator.languages[0]; } @@ -217,12 +217,12 @@ function translateKey(key) { function translateKeyFromModule(key, module) { let dictionary = getDictionary(module, getCurrentLocale()); - if (dictionary && dictionary[key]) { + if (dictionary?.[key]) { return dictionary[key]; } dictionary = getDictionary(module, fallbackCulture); - if (dictionary && dictionary[key]) { + if (dictionary?.[key]) { return dictionary[key]; } diff --git a/src/scripts/libraryMenu.js b/src/scripts/libraryMenu.js index c49a8336d3..b77dfa92e1 100644 --- a/src/scripts/libraryMenu.js +++ b/src/scripts/libraryMenu.js @@ -71,7 +71,7 @@ function renderHeader() { } function getCurrentApiClient() { - if (currentUser && currentUser.localUser) { + if (currentUser?.localUser) { return ServerConnections.getApiClient(currentUser.localUser.ServerId); } @@ -127,7 +127,7 @@ function updateUserInHeader(user) { let hasImage; - if (user && user.name) { + if (user?.name) { if (user.imageUrl) { const url = user.imageUrl; updateHeaderUserButton(url); @@ -143,7 +143,7 @@ function updateUserInHeader(user) { updateHeaderUserButton(null); } - if (user && user.localUser) { + if (user?.localUser) { if (headerHomeButton) { headerHomeButton.classList.remove('hide'); } @@ -322,7 +322,7 @@ function refreshLibraryInfoInDrawer(user) { // libraries are added here html += '

'; - if (user.localUser && user.localUser.Policy.IsAdministrator) { + if (user.localUser?.Policy.IsAdministrator) { html += '
'; html += '

'; html += globalize.translate('HeaderAdmin'); diff --git a/src/scripts/playlists.js b/src/scripts/playlists.js index eb3fac9ece..aba0c389ae 100644 --- a/src/scripts/playlists.js +++ b/src/scripts/playlists.js @@ -189,9 +189,9 @@ export default function (view) { reloadItems(); }); view.querySelector('.btnNewPlaylist').addEventListener('click', function () { - import('../components/playlisteditor/playlisteditor').then(({ default: playlistEditor }) => { + import('../components/playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { const serverId = ApiClient.serverInfo().Id; - new playlistEditor({ + new PlaylistEditor({ items: [], serverId: serverId }); diff --git a/src/scripts/screensavermanager.js b/src/scripts/screensavermanager.js index c63d530685..a187da6ae2 100644 --- a/src/scripts/screensavermanager.js +++ b/src/scripts/screensavermanager.js @@ -94,7 +94,7 @@ function ScreenSaverManager() { let isLoggedIn; const apiClient = ServerConnections.currentApiClient(); - if (apiClient && apiClient.isLoggedIn()) { + if (apiClient?.isLoggedIn()) { isLoggedIn = true; } diff --git a/src/utils/fetchLocal.ts b/src/utils/fetchLocal.ts index cec934028f..8191e846e7 100644 --- a/src/utils/fetchLocal.ts +++ b/src/utils/fetchLocal.ts @@ -33,7 +33,7 @@ export default async function fetchLocal(url: string, options?: FetchOptions) { xhr.open('GET', url); - if (options && options.cache) { + if (options?.cache) { xhr.setRequestHeader('Cache-Control', options.cache); }