diff --git a/package.json b/package.json index cac5ebb02d..8fb92cf4f0 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "src/components/imageUploader/imageUploader.js", "src/components/indicators/indicators.js", "src/components/itemContextMenu.js", + "src/components/itemHelper.js", "src/components/itemidentifier/itemidentifier.js", "src/components/itemMediaInfo/itemMediaInfo.js", "src/components/lazyLoader/lazyLoaderIntersectionObserver.js", @@ -199,6 +200,7 @@ "src/controllers/dashboard/users/userparentalcontrol.js", "src/controllers/dashboard/users/userpasswordpage.js", "src/controllers/dashboard/users/userprofilespage.js", + "src/controllers/itemDetails/index.js", "src/controllers/playback/queue/index.js", "src/controllers/playback/video/index.js", "src/controllers/searchpage.js", @@ -248,6 +250,7 @@ "src/plugins/youtubePlayer/plugin.js", "src/scripts/alphanumericshortcuts.js", "src/scripts/autoBackdrops.js", + "src/scripts/browser.js", "src/scripts/datetime.js", "src/scripts/deleteHelper.js", "src/scripts/dfnshelper.js", diff --git a/src/components/itemHelper.js b/src/components/itemHelper.js index 55e9e10062..7d1ac0e110 100644 --- a/src/components/itemHelper.js +++ b/src/components/itemHelper.js @@ -1,342 +1,350 @@ -define(['apphost', 'globalize'], function (appHost, globalize) { - 'use strict'; +import appHost from 'apphost'; +import globalize from 'globalize'; - function getDisplayName(item, options = {}) { - if (!item) { - throw new Error('null item passed into getDisplayName'); +export function getDisplayName(item, options = {}) { + if (!item) { + throw new Error('null item passed into getDisplayName'); + } + + if (item.Type === 'Timer') { + item = item.ProgramInfo || item; + } + + let name = ((item.Type === 'Program' || item.Type === 'Recording') && (item.IsSeries || item.EpisodeTitle) ? item.EpisodeTitle : item.Name) || ''; + + if (item.Type === 'TvChannel') { + if (item.ChannelNumber) { + return item.ChannelNumber + ' ' + name; } - - if (item.Type === 'Timer') { - item = item.ProgramInfo || item; - } - - var name = ((item.Type === 'Program' || item.Type === 'Recording') && (item.IsSeries || item.EpisodeTitle) ? item.EpisodeTitle : item.Name) || ''; - - if (item.Type === 'TvChannel') { - if (item.ChannelNumber) { - return item.ChannelNumber + ' ' + name; - } - return name; - } - if (item.Type === 'Episode' && item.ParentIndexNumber === 0) { - name = globalize.translate('ValueSpecialEpisodeName', name); - } else if ((item.Type === 'Episode' || item.Type === 'Program') && item.IndexNumber != null && item.ParentIndexNumber != null && options.includeIndexNumber !== false) { - var displayIndexNumber = item.IndexNumber; - - var number = displayIndexNumber; - var nameSeparator = ' - '; - - if (options.includeParentInfo !== false) { - number = 'S' + item.ParentIndexNumber + ':E' + number; - } else { - nameSeparator = '. '; - } - - if (item.IndexNumberEnd) { - displayIndexNumber = item.IndexNumberEnd; - number += '-' + displayIndexNumber; - } - - if (number) { - name = name ? (number + nameSeparator + name) : number; - } - } - return name; } + if (item.Type === 'Episode' && item.ParentIndexNumber === 0) { + name = globalize.translate('ValueSpecialEpisodeName', name); + } else if ((item.Type === 'Episode' || item.Type === 'Program') && item.IndexNumber != null && item.ParentIndexNumber != null && options.includeIndexNumber !== false) { + let displayIndexNumber = item.IndexNumber; - function supportsAddingToCollection(item) { - var invalidTypes = ['Genre', 'MusicGenre', 'Studio', 'UserView', 'CollectionFolder', 'Audio', 'Program', 'Timer', 'SeriesTimer']; + let number = displayIndexNumber; + let nameSeparator = ' - '; - if (item.Type === 'Recording') { - if (item.Status !== 'Completed') { - return false; - } + if (options.includeParentInfo !== false) { + number = 'S' + item.ParentIndexNumber + ':E' + number; + } else { + nameSeparator = '. '; } - return !item.CollectionType && invalidTypes.indexOf(item.Type) === -1 && item.MediaType !== 'Photo' && !isLocalItem(item); + if (item.IndexNumberEnd) { + displayIndexNumber = item.IndexNumberEnd; + number += '-' + displayIndexNumber; + } + + if (number) { + name = name ? (number + nameSeparator + name) : number; + } } - function supportsAddingToPlaylist(item) { - if (item.Type === 'Program') { - return false; - } - if (item.Type === 'TvChannel') { - return false; - } - if (item.Type === 'Timer') { - return false; - } - if (item.Type === 'SeriesTimer') { - return false; - } - if (item.MediaType === 'Photo') { - return false; - } + return name; +} - if (item.Type === 'Recording') { - if (item.Status !== 'Completed') { - return false; - } - } +export function supportsAddingToCollection(item) { + const invalidTypes = ['Genre', 'MusicGenre', 'Studio', 'UserView', 'CollectionFolder', 'Audio', 'Program', 'Timer', 'SeriesTimer']; - if (isLocalItem(item)) { + if (item.Type === 'Recording') { + if (item.Status !== 'Completed') { return false; } - if (item.CollectionType === 'livetv') { - return false; - } - - return item.MediaType || item.IsFolder || item.Type === 'Genre' || item.Type === 'MusicGenre' || item.Type === 'MusicArtist'; } - function canEdit(user, item) { - var itemType = item.Type; + return !item.CollectionType && invalidTypes.indexOf(item.Type) === -1 && item.MediaType !== 'Photo' && !isLocalItem(item); +} - if (itemType === 'UserRootFolder' || itemType === 'UserView') { - return false; - } - - if (itemType === 'Program') { - return false; - } - - if (itemType === 'Timer') { - return false; - } - - if (itemType === 'SeriesTimer') { - return false; - } - - if (item.Type === 'Recording') { - if (item.Status !== 'Completed') { - return false; - } - } - - if (isLocalItem(item)) { - return false; - } - - return user.Policy.IsAdministrator; +export function supportsAddingToPlaylist(item) { + if (item.Type === 'Program') { + return false; + } + if (item.Type === 'TvChannel') { + return false; + } + if (item.Type === 'Timer') { + return false; + } + if (item.Type === 'SeriesTimer') { + return false; + } + if (item.MediaType === 'Photo') { + return false; } - function isLocalItem(item) { - if (item && item.Id && item.Id.indexOf('local') === 0) { + if (item.Type === 'Recording') { + if (item.Status !== 'Completed') { + return false; + } + } + + if (isLocalItem(item)) { + return false; + } + if (item.CollectionType === 'livetv') { + return false; + } + + return item.MediaType || item.IsFolder || item.Type === 'Genre' || item.Type === 'MusicGenre' || item.Type === 'MusicArtist'; +} + +export function canEdit(user, item) { + const itemType = item.Type; + + if (itemType === 'UserRootFolder' || itemType === 'UserView') { + return false; + } + + if (itemType === 'Program') { + return false; + } + + if (itemType === 'Timer') { + return false; + } + + if (itemType === 'SeriesTimer') { + return false; + } + + if (item.Type === 'Recording') { + if (item.Status !== 'Completed') { + return false; + } + } + + if (isLocalItem(item)) { + return false; + } + + return user.Policy.IsAdministrator; +} + +export function isLocalItem(item) { + if (item && item.Id && item.Id.indexOf('local') === 0) { + return true; + } + + return false; +} + +export function canIdentify (user, item) { + const itemType = item.Type; + + if (itemType === 'Movie' || + itemType === 'Trailer' || + itemType === 'Series' || + itemType === 'BoxSet' || + itemType === 'Person' || + itemType === 'Book' || + itemType === 'MusicAlbum' || + itemType === 'MusicArtist' || + itemType === 'MusicVideo') { + if (user.Policy.IsAdministrator) { + if (!isLocalItem(item)) { + return true; + } + } + } + + return false; +} + +export function canEditImages (user, item) { + const itemType = item.Type; + + if (item.MediaType === 'Photo') { + return false; + } + + if (itemType === 'UserView') { + if (user.Policy.IsAdministrator) { return true; } return false; } - return { - getDisplayName: getDisplayName, - supportsAddingToCollection: supportsAddingToCollection, - supportsAddingToPlaylist: supportsAddingToPlaylist, - isLocalItem: isLocalItem, - - canIdentify: function (user, item) { - var itemType = item.Type; - - if (itemType === 'Movie' || - itemType === 'Trailer' || - itemType === 'Series' || - itemType === 'BoxSet' || - itemType === 'Person' || - itemType === 'Book' || - itemType === 'MusicAlbum' || - itemType === 'MusicArtist' || - itemType === 'MusicVideo') { - if (user.Policy.IsAdministrator) { - if (!isLocalItem(item)) { - return true; - } - } - } - + if (item.Type === 'Recording') { + if (item.Status !== 'Completed') { return false; - }, + } + } - canEdit: canEdit, + return itemType !== 'Timer' && itemType !== 'SeriesTimer' && canEdit(user, item) && !isLocalItem(item); +} - canEditImages: function (user, item) { - var itemType = item.Type; +export function canSync (user, item) { + if (user && !user.Policy.EnableContentDownloading) { + return false; + } - if (item.MediaType === 'Photo') { - return false; - } + if (isLocalItem(item)) { + return false; + } - if (itemType === 'UserView') { - if (user.Policy.IsAdministrator) { - return true; - } - - return false; - } - - if (item.Type === 'Recording') { - if (item.Status !== 'Completed') { - return false; - } - } - - return itemType !== 'Timer' && itemType !== 'SeriesTimer' && canEdit(user, item) && !isLocalItem(item); - }, - - canSync: function (user, item) { - if (user && !user.Policy.EnableContentDownloading) { - return false; - } - - if (isLocalItem(item)) { - return false; - } - - return item.SupportsSync; - }, - - canShare: function (item, user) { - if (item.Type === 'Program') { - return false; - } - if (item.Type === 'TvChannel') { - return false; - } - if (item.Type === 'Timer') { - return false; - } - if (item.Type === 'SeriesTimer') { - return false; - } - if (item.Type === 'Recording') { - if (item.Status !== 'Completed') { - return false; - } - } - if (isLocalItem(item)) { - return false; - } - return user.Policy.EnablePublicSharing && appHost.supports('sharing'); - }, - - enableDateAddedDisplay: function (item) { - return !item.IsFolder && item.MediaType && item.Type !== 'Program' && item.Type !== 'TvChannel' && item.Type !== 'Trailer'; - }, - - canMarkPlayed: function (item) { - if (item.Type === 'Program') { - return false; - } - - if (item.MediaType === 'Video') { - if (item.Type !== 'TvChannel') { - return true; - } - } else if (item.MediaType === 'Audio') { - if (item.Type === 'AudioPodcast') { - return true; - } - if (item.Type === 'AudioBook') { - return true; - } - } - - if (item.Type === 'Series' || - item.Type === 'Season' || - item.Type === 'BoxSet' || - item.MediaType === 'Book' || - item.MediaType === 'Recording') { - return true; - } + return item.SupportsSync; +} +export function canShare (item, user) { + if (item.Type === 'Program') { + return false; + } + if (item.Type === 'TvChannel') { + return false; + } + if (item.Type === 'Timer') { + return false; + } + if (item.Type === 'SeriesTimer') { + return false; + } + if (item.Type === 'Recording') { + if (item.Status !== 'Completed') { return false; - }, + } + } + if (isLocalItem(item)) { + return false; + } + return user.Policy.EnablePublicSharing && appHost.supports('sharing'); +} - canRate: function (item) { - if (item.Type === 'Program' - || item.Type === 'Timer' - || item.Type === 'SeriesTimer' - || item.Type === 'CollectionFolder' - || item.Type === 'UserView' - || item.Type === 'Channel' - || !item.UserData) { - return false; - } +export function enableDateAddedDisplay (item) { + return !item.IsFolder && item.MediaType && item.Type !== 'Program' && item.Type !== 'TvChannel' && item.Type !== 'Trailer'; +} - return true; - }, - - canConvert: function (item, user) { - if (!user.Policy.EnableMediaConversion) { - return false; - } - - if (isLocalItem(item)) { - return false; - } - - var mediaType = item.MediaType; - if (mediaType === 'Book' || mediaType === 'Photo' || mediaType === 'Audio') { - return false; - } - - var collectionType = item.CollectionType; - if (collectionType === 'livetv') { - return false; - } - - var type = item.Type; - if (type === 'Channel' || type === 'Person' || type === 'Year' || type === 'Program' || type === 'Timer' || type === 'SeriesTimer') { - return false; - } - - if (item.LocationType === 'Virtual' && !item.IsFolder) { - return false; - } - - if (item.IsPlaceHolder) { - return false; - } - - return true; - }, - - canRefreshMetadata: function (item, user) { - if (user.Policy.IsAdministrator) { - var collectionType = item.CollectionType; - if (collectionType === 'livetv') { - return false; - } - - if (item.Type !== 'Timer' && item.Type !== 'SeriesTimer' && item.Type !== 'Program' && item.Type !== 'TvChannel' && !(item.Type === 'Recording' && item.Status !== 'Completed')) { - if (!isLocalItem(item)) { - return true; - } - } - } - - return false; - }, - - supportsMediaSourceSelection: function (item) { - if (item.MediaType !== 'Video') { - return false; - } - if (item.Type === 'TvChannel') { - return false; - } - if (!item.MediaSources || (item.MediaSources.length === 1 && item.MediaSources[0].Type === 'Placeholder')) { - return false; - } - if (item.EnableMediaSourceDisplay === false) { - return false; - } - if (item.EnableMediaSourceDisplay == null && item.SourceType && item.SourceType !== 'Library') { - return false; - } +export function canMarkPlayed (item) { + if (item.Type === 'Program') { + return false; + } + if (item.MediaType === 'Video') { + if (item.Type !== 'TvChannel') { return true; } - }; -}); + } else if (item.MediaType === 'Audio') { + if (item.Type === 'AudioPodcast') { + return true; + } + if (item.Type === 'AudioBook') { + return true; + } + } + + if (item.Type === 'Series' || + item.Type === 'Season' || + item.Type === 'BoxSet' || + item.MediaType === 'Book' || + item.MediaType === 'Recording') { + return true; + } + + return false; +} + +export function canRate (item) { + if (item.Type === 'Program' + || item.Type === 'Timer' + || item.Type === 'SeriesTimer' + || item.Type === 'CollectionFolder' + || item.Type === 'UserView' + || item.Type === 'Channel' + || !item.UserData) { + return false; + } + + return true; +} + +export function canConvert (item, user) { + if (!user.Policy.EnableMediaConversion) { + return false; + } + + if (isLocalItem(item)) { + return false; + } + + const mediaType = item.MediaType; + if (mediaType === 'Book' || mediaType === 'Photo' || mediaType === 'Audio') { + return false; + } + + const collectionType = item.CollectionType; + if (collectionType === 'livetv') { + return false; + } + + const type = item.Type; + if (type === 'Channel' || type === 'Person' || type === 'Year' || type === 'Program' || type === 'Timer' || type === 'SeriesTimer') { + return false; + } + + if (item.LocationType === 'Virtual' && !item.IsFolder) { + return false; + } + + if (item.IsPlaceHolder) { + return false; + } + + return true; +} + +export function canRefreshMetadata (item, user) { + if (user.Policy.IsAdministrator) { + const collectionType = item.CollectionType; + if (collectionType === 'livetv') { + return false; + } + + if (item.Type !== 'Timer' && item.Type !== 'SeriesTimer' && item.Type !== 'Program' && item.Type !== 'TvChannel' && !(item.Type === 'Recording' && item.Status !== 'Completed')) { + if (!isLocalItem(item)) { + return true; + } + } + } + + return false; +} + +export function supportsMediaSourceSelection (item) { + if (item.MediaType !== 'Video') { + return false; + } + if (item.Type === 'TvChannel') { + return false; + } + if (!item.MediaSources || (item.MediaSources.length === 1 && item.MediaSources[0].Type === 'Placeholder')) { + return false; + } + if (item.EnableMediaSourceDisplay === false) { + return false; + } + if (item.EnableMediaSourceDisplay == null && item.SourceType && item.SourceType !== 'Library') { + return false; + } + + return true; +} + +export default { + getDisplayName: getDisplayName, + supportsAddingToCollection: supportsAddingToCollection, + supportsAddingToPlaylist: supportsAddingToPlaylist, + isLocalItem: isLocalItem, + canIdentify: canIdentify, + canEdit: canEdit, + canEditImages: canEditImages, + canSync: canSync, + canShare: canShare, + enableDateAddedDisplay: enableDateAddedDisplay, + canMarkPlayed: canMarkPlayed, + canRate: canRate, + canConvert: canConvert, + canRefreshMetadata: canRefreshMetadata, + supportsMediaSourceSelection: supportsMediaSourceSelection +}; diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index 992eaf0482..9b9b3a51ff 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -1,8 +1,36 @@ -define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSettings', 'cardBuilder', 'datetime', 'mediaInfo', 'backdrop', 'listView', 'itemContextMenu', 'itemHelper', 'dom', 'indicators', 'imageLoader', 'libraryMenu', 'globalize', 'browser', 'events', 'playbackManager', 'scrollStyles', 'emby-itemscontainer', 'emby-checkbox', 'emby-button', 'emby-playstatebutton', 'emby-ratingbutton', 'emby-scroller', 'emby-select'], function (loading, appRouter, layoutManager, connectionManager, userSettings, cardBuilder, datetime, mediaInfo, backdrop, listView, itemContextMenu, itemHelper, dom, indicators, imageLoader, libraryMenu, globalize, browser, events, playbackManager) { - 'use strict'; +import loading from 'loading'; +import appRouter from 'appRouter'; +import layoutManager from 'layoutManager'; +import connectionManager from 'connectionManager'; +import * as userSettings from 'userSettings'; +import cardBuilder from 'cardBuilder'; +import datetime from 'datetime'; +import mediaInfo from 'mediaInfo'; +import backdrop from 'backdrop'; +import listView from 'listView'; +import itemContextMenu from 'itemContextMenu'; +import itemHelper from 'itemHelper'; +import dom from 'dom'; +import indicators from 'indicators'; +import imageLoader from 'imageLoader'; +import libraryMenu from 'libraryMenu'; +import globalize from 'globalize'; +import browser from 'browser'; +import events from 'events'; +import playbackManager from 'playbackManager'; +import 'scrollStyles'; +import 'emby-itemscontainer'; +import 'emby-checkbox'; +import 'emby-button'; +import 'emby-playstatebutton'; +import 'emby-ratingbutton'; +import 'emby-scroller'; +import 'emby-select'; + +/* eslint-disable indent */ function getPromise(apiClient, params) { - var id = params.id; + const id = params.id; if (id) { return apiClient.getItem(apiClient.getCurrentUserId(), id); @@ -56,7 +84,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function getProgramScheduleHtml(items) { - var html = ''; + let html = ''; html += '
'; html += listView.getListViewHtml({ @@ -92,8 +120,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti result.Items = []; } - var html = getProgramScheduleHtml(result.Items); - var scheduleTab = page.querySelector('.seriesTimerSchedule'); + const html = getProgramScheduleHtml(result.Items); + const scheduleTab = page.querySelector('.seriesTimerSchedule'); scheduleTab.innerHTML = html; imageLoader.lazyChildren(scheduleTab); }); @@ -113,7 +141,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } if (user.Policy.EnableLiveTvManagement) { - require(['seriesRecordingEditor'], function (seriesRecordingEditor) { + import('seriesRecordingEditor').then(({default: seriesRecordingEditor}) => { seriesRecordingEditor.embed(item, apiClient.serverId(), { context: page.querySelector('.seriesRecordingEditor') }); @@ -129,7 +157,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderTrackSelections(page, instance, item, forceReload) { - var select = page.querySelector('.selectSource'); + const select = page.querySelector('.selectSource'); if (!item.MediaSources || !itemHelper.supportsMediaSourceSelection(item) || playbackManager.getSupportedCommands().indexOf('PlayMediaSource') === -1 || !playbackManager.canPlay(item)) { page.querySelector('.trackSelections').classList.add('hide'); @@ -140,17 +168,17 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti return; } - var mediaSources = item.MediaSources; + const mediaSources = item.MediaSources; instance._currentPlaybackMediaSources = mediaSources; page.querySelector('.trackSelections').classList.remove('hide'); select.setLabel(globalize.translate('LabelVersion')); - var currentValue = select.value; + const currentValue = select.value; - var selectedId = mediaSources[0].Id; + const selectedId = mediaSources[0].Id; select.innerHTML = mediaSources.map(function (v) { - var selected = v.Id === selectedId ? ' selected' : ''; + const selected = v.Id === selectedId ? ' selected' : ''; return ''; }).join(''); @@ -168,22 +196,22 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderVideoSelections(page, mediaSources) { - var mediaSourceId = page.querySelector('.selectSource').value; - var mediaSource = mediaSources.filter(function (m) { + const mediaSourceId = page.querySelector('.selectSource').value; + const mediaSource = mediaSources.filter(function (m) { return m.Id === mediaSourceId; })[0]; - var tracks = mediaSource.MediaStreams.filter(function (m) { + const tracks = mediaSource.MediaStreams.filter(function (m) { return m.Type === 'Video'; }); - var select = page.querySelector('.selectVideo'); + const select = page.querySelector('.selectVideo'); select.setLabel(globalize.translate('LabelVideo')); - var selectedId = tracks.length ? tracks[0].Index : -1; + const selectedId = tracks.length ? tracks[0].Index : -1; select.innerHTML = tracks.map(function (v) { - var selected = v.Index === selectedId ? ' selected' : ''; - var titleParts = []; - var resolutionText = mediaInfo.getResolutionText(v); + const selected = v.Index === selectedId ? ' selected' : ''; + const titleParts = []; + const resolutionText = mediaInfo.getResolutionText(v); if (resolutionText) { titleParts.push(resolutionText); @@ -205,18 +233,18 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderAudioSelections(page, mediaSources) { - var mediaSourceId = page.querySelector('.selectSource').value; - var mediaSource = mediaSources.filter(function (m) { + const mediaSourceId = page.querySelector('.selectSource').value; + const mediaSource = mediaSources.filter(function (m) { return m.Id === mediaSourceId; })[0]; - var tracks = mediaSource.MediaStreams.filter(function (m) { + const tracks = mediaSource.MediaStreams.filter(function (m) { return m.Type === 'Audio'; }); - var select = page.querySelector('.selectAudio'); + const select = page.querySelector('.selectAudio'); select.setLabel(globalize.translate('LabelAudio')); - var selectedId = mediaSource.DefaultAudioStreamIndex; + const selectedId = mediaSource.DefaultAudioStreamIndex; select.innerHTML = tracks.map(function (v) { - var selected = v.Index === selectedId ? ' selected' : ''; + const selected = v.Index === selectedId ? ' selected' : ''; return ''; }).join(''); @@ -234,24 +262,24 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderSubtitleSelections(page, mediaSources) { - var mediaSourceId = page.querySelector('.selectSource').value; - var mediaSource = mediaSources.filter(function (m) { + const mediaSourceId = page.querySelector('.selectSource').value; + const mediaSource = mediaSources.filter(function (m) { return m.Id === mediaSourceId; })[0]; - var tracks = mediaSource.MediaStreams.filter(function (m) { + const tracks = mediaSource.MediaStreams.filter(function (m) { return m.Type === 'Subtitle'; }); - var select = page.querySelector('.selectSubtitles'); + const select = page.querySelector('.selectSubtitles'); select.setLabel(globalize.translate('LabelSubtitles')); - var selectedId = mediaSource.DefaultSubtitleStreamIndex == null ? -1 : mediaSource.DefaultSubtitleStreamIndex; + const selectedId = mediaSource.DefaultSubtitleStreamIndex == null ? -1 : mediaSource.DefaultSubtitleStreamIndex; - var videoTracks = mediaSource.MediaStreams.filter(function (m) { + const videoTracks = mediaSource.MediaStreams.filter(function (m) { return m.Type === 'Video'; }); // This only makes sense on Video items if (videoTracks.length) { - var selected = selectedId === -1 ? ' selected' : ''; + let selected = selectedId === -1 ? ' selected' : ''; select.innerHTML = '' + tracks.map(function (v) { selected = v.Index === selectedId ? ' selected' : ''; return ''; @@ -271,10 +299,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function reloadPlayButtons(page, item) { - var canPlay = false; + let canPlay = false; if (item.Type == 'Program') { - var now = new Date(); + const now = new Date(); if (now >= datetime.parseISO8601Date(item.StartDate, true) && now < datetime.parseISO8601Date(item.EndDate, true)) { hideAll(page, 'btnPlay', true); @@ -288,9 +316,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti hideAll(page, 'btnShuffle'); } else if (playbackManager.canPlay(item)) { hideAll(page, 'btnPlay', true); - var enableInstantMix = ['Audio', 'MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type) !== -1; + const enableInstantMix = ['Audio', 'MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type) !== -1; hideAll(page, 'btnInstantMix', enableInstantMix); - var enableShuffle = item.IsFolder || ['MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type) !== -1; + const enableShuffle = item.IsFolder || ['MusicAlbum', 'MusicGenre', 'MusicArtist'].indexOf(item.Type) !== -1; hideAll(page, 'btnShuffle', enableShuffle); canPlay = true; @@ -313,12 +341,12 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function reloadUserDataButtons(page, item) { - var i; - var length; - var btnPlaystates = page.querySelectorAll('.btnPlaystate'); + let i; + let length; + const btnPlaystates = page.querySelectorAll('.btnPlaystate'); for (i = 0, length = btnPlaystates.length; i < length; i++) { - var btnPlaystate = btnPlaystates[i]; + const btnPlaystate = btnPlaystates[i]; if (itemHelper.canMarkPlayed(item)) { btnPlaystate.classList.remove('hide'); @@ -329,10 +357,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } } - var btnUserRatings = page.querySelectorAll('.btnUserRating'); + const btnUserRatings = page.querySelectorAll('.btnUserRating'); for (i = 0, length = btnUserRatings.length; i < length; i++) { - var btnUserRating = btnUserRatings[i]; + const btnUserRating = btnUserRatings[i]; if (itemHelper.canRate(item)) { btnUserRating.classList.remove('hide'); @@ -345,10 +373,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function getArtistLinksHtml(artists, serverId, context) { - var html = []; + let html = []; for (const artist of artists) { - var href = appRouter.getRouteUrl(artist, { + const href = appRouter.getRouteUrl(artist, { context: context, itemType: 'MusicArtist', serverId: serverId @@ -366,9 +394,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti * @param {Object} context - Application context. */ function renderName(item, container, context) { - var parentRoute; - var parentNameHtml = []; - var parentNameLast = false; + let parentRoute; + const parentNameHtml = []; + let parentNameLast = false; if (item.AlbumArtists) { parentNameHtml.push(getArtistLinksHtml(item.AlbumArtists, item.ServerId, context)); @@ -431,9 +459,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } // FIXME: This whole section needs some refactoring, so it becames easier to scale across all form factors. See GH #1022 - var html = ''; - var tvShowHtml = parentNameHtml[0]; - var tvSeasonHtml = parentNameHtml[1]; + let html = ''; + const tvShowHtml = parentNameHtml[0]; + const tvSeasonHtml = parentNameHtml[1]; if (parentNameHtml.length) { if (parentNameLast) { @@ -448,7 +476,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } } - var name = itemHelper.getDisplayName(item, { + const name = itemHelper.getDisplayName(item, { includeParentInfo: false }); @@ -494,9 +522,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderDetailPageBackdrop(page, item, apiClient) { - var imgUrl; - var hasbackdrop = false; - var itemBackdropElement = page.querySelector('#itemBackdrop'); + let imgUrl; + let hasbackdrop = false; + const itemBackdropElement = page.querySelector('#itemBackdrop'); if (!layoutManager.mobile && !userSettings.detailsBanner()) { return false; @@ -555,7 +583,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti renderSeriesTimerEditor(page, item, apiClient, user); renderTimerEditor(page, item, apiClient, user); setInitialCollapsibleState(page, item, apiClient, params.context, user); - var canPlay = reloadPlayButtons(page, item); + const canPlay = reloadPlayButtons(page, item); if ((item.LocalTrailerCount || item.RemoteTrailers && item.RemoteTrailers.length) && playbackManager.getSupportedCommands().indexOf('PlayTrailers') !== -1) { hideAll(page, 'btnPlayTrailer', true); @@ -572,7 +600,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } showRecordingFields(instance, page, item, user); - var groupedVersions = (item.MediaSources || []).filter(function (g) { + const groupedVersions = (item.MediaSources || []).filter(function (g) { return g.Type == 'Grouping'; }); @@ -588,11 +616,11 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti hideAll(page, 'btnMoreCommands'); } - var itemBirthday = page.querySelector('#itemBirthday'); + const itemBirthday = page.querySelector('#itemBirthday'); if (item.Type == 'Person' && item.PremiereDate) { try { - var birthday = datetime.parseISO8601Date(item.PremiereDate, true).toDateString(); + const birthday = datetime.parseISO8601Date(item.PremiereDate, true).toDateString(); itemBirthday.classList.remove('hide'); itemBirthday.innerHTML = globalize.translate('BirthDateValue', birthday); } catch (err) { @@ -602,11 +630,11 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti itemBirthday.classList.add('hide'); } - var itemDeathDate = page.querySelector('#itemDeathDate'); + const itemDeathDate = page.querySelector('#itemDeathDate'); if (item.Type == 'Person' && item.EndDate) { try { - var deathday = datetime.parseISO8601Date(item.EndDate, true).toDateString(); + const deathday = datetime.parseISO8601Date(item.EndDate, true).toDateString(); itemDeathDate.classList.remove('hide'); itemDeathDate.innerHTML = globalize.translate('DeathDateValue', deathday); } catch (err) { @@ -616,10 +644,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti itemDeathDate.classList.add('hide'); } - var itemBirthLocation = page.querySelector('#itemBirthLocation'); + const itemBirthLocation = page.querySelector('#itemBirthLocation'); if (item.Type == 'Person' && item.ProductionLocations && item.ProductionLocations.length) { - var gmap = '' + item.ProductionLocations[0] + ''; + const gmap = '' + item.ProductionLocations[0] + ''; itemBirthLocation.classList.remove('hide'); itemBirthLocation.innerHTML = globalize.translate('BirthPlaceValue', gmap); } else { @@ -633,7 +661,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti hideAll(page, 'btnDownload', true); } - require(['autoFocuser'], function (autoFocuser) { + import('autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); } @@ -656,9 +684,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderLogo(page, item, apiClient) { - var detailLogo = page.querySelector('.detailLogo'); + const detailLogo = page.querySelector('.detailLogo'); - var url = logoImageUrl(item, apiClient, {}); + const url = logoImageUrl(item, apiClient, {}); if (!layoutManager.mobile && !userSettings.enableBackdrops()) { detailLogo.classList.add('hide'); @@ -672,10 +700,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti function showRecordingFields(instance, page, item, user) { if (!instance.currentRecordingFields) { - var recordingFieldsElement = page.querySelector('.recordingFields'); + const recordingFieldsElement = page.querySelector('.recordingFields'); if (item.Type == 'Program' && user.Policy.EnableLiveTvManagement) { - require(['recordingFields'], function (recordingFields) { + import('recordingFields').then(({default: recordingFields}) => { instance.currentRecordingFields = new recordingFields({ parent: recordingFieldsElement, programId: item.Id, @@ -691,9 +719,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderLinks(page, item) { - var externalLinksElem = page.querySelector('.itemExternalLinks'); + const externalLinksElem = page.querySelector('.itemExternalLinks'); - var links = []; + const links = []; if (!layoutManager.tv && item.HomePageUrl) { links.push(`${globalize.translate('ButtonWebsite')}`); @@ -705,7 +733,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } } - var html = []; + const html = []; if (links.length) { html.push(links.join(', ')); } @@ -763,7 +791,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderNextUp(page, item, user) { - var section = page.querySelector('.nextUpSection'); + const section = page.querySelector('.nextUpSection'); if (item.Type != 'Series') { return void section.classList.add('hide'); @@ -779,7 +807,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti section.classList.add('hide'); } - var html = cardBuilder.getCardsHtml({ + const html = cardBuilder.getCardsHtml({ items: result.Items, shape: 'overflowBackdrop', showTitle: true, @@ -788,7 +816,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti centerText: true, overlayPlayButton: true }); - var itemsContainer = section.querySelector('.nextUpItems'); + const itemsContainer = section.querySelector('.nextUpItems'); itemsContainer.innerHTML = html; imageLoader.lazyChildren(itemsContainer); }); @@ -846,8 +874,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function toggleLineClamp(clampTarget, e) { - var expandButton = e.target; - var clampClassName = 'detail-clamp-text'; + const expandButton = e.target; + const clampClassName = 'detail-clamp-text'; if (clampTarget.classList.contains(clampClassName)) { clampTarget.classList.remove(clampClassName); @@ -860,7 +888,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti function renderOverview(page, item) { for (const overviewElemnt of page.querySelectorAll('.overview')) { - var overview = item.Overview || ''; + const overview = item.Overview || ''; if (overview) { overviewElemnt.innerHTML = overview; @@ -868,7 +896,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti overviewElemnt.classList.add('detail-clamp-text'); // Grab the sibling element to control the expand state - var expandButton = overviewElemnt.parentElement.querySelector('.overview-expand'); + const expandButton = overviewElemnt.parentElement.querySelector('.overview-expand'); // Detect if we have overflow of text. Based on this StackOverflow answer // https://stackoverflow.com/a/35157976 @@ -891,10 +919,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderGenres(page, item, context = inferContext(item)) { - var genres = item.GenreItems || []; - var type = context === 'music' ? 'MusicGenre' : 'Genre'; + const genres = item.GenreItems || []; + const type = context === 'music' ? 'MusicGenre' : 'Genre'; - var html = genres.map(function (p) { + const html = genres.map(function (p) { return '' + p.Name + ''; }).join(', '); - var genresLabel = page.querySelector('.genresLabel'); + const genresLabel = page.querySelector('.genresLabel'); genresLabel.innerHTML = globalize.translate(genres.length > 1 ? 'Genres' : 'Genre'); - var genresValue = page.querySelector('.genres'); + const genresValue = page.querySelector('.genres'); genresValue.innerHTML = html; - var genresGroup = page.querySelector('.genresGroup'); + const genresGroup = page.querySelector('.genresGroup'); if (genres.length) { genresGroup.classList.remove('hide'); } else { @@ -919,11 +947,11 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderWriter(page, item, context) { - var writers = (item.People || []).filter(function (person) { + const writers = (item.People || []).filter(function (person) { return person.Type === 'Writer'; }); - var html = writers.map(function (person) { + const html = writers.map(function (person) { return '' + person.Name + ''; }).join(', '); - var writersLabel = page.querySelector('.writersLabel'); + const writersLabel = page.querySelector('.writersLabel'); writersLabel.innerHTML = globalize.translate(writers.length > 1 ? 'Writers' : 'Writer'); - var writersValue = page.querySelector('.writers'); + const writersValue = page.querySelector('.writers'); writersValue.innerHTML = html; - var writersGroup = page.querySelector('.writersGroup'); + const writersGroup = page.querySelector('.writersGroup'); if (writers.length) { writersGroup.classList.remove('hide'); } else { @@ -948,11 +976,11 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderDirector(page, item, context) { - var directors = (item.People || []).filter(function (person) { + const directors = (item.People || []).filter(function (person) { return person.Type === 'Director'; }); - var html = directors.map(function (person) { + const html = directors.map(function (person) { return '' + person.Name + ''; }).join(', '); - var directorsLabel = page.querySelector('.directorsLabel'); + const directorsLabel = page.querySelector('.directorsLabel'); directorsLabel.innerHTML = globalize.translate(directors.length > 1 ? 'Directors' : 'Director'); - var directorsValue = page.querySelector('.directors'); + const directorsValue = page.querySelector('.directors'); directorsValue.innerHTML = html; - var directorsGroup = page.querySelector('.directorsGroup'); + const directorsGroup = page.querySelector('.directorsGroup'); if (directors.length) { directorsGroup.classList.remove('hide'); } else { @@ -1009,7 +1037,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderTagline(page, item) { - var taglineElement = page.querySelector('.tagline'); + const taglineElement = page.querySelector('.tagline'); if (item.Taglines && item.Taglines.length) { taglineElement.classList.remove('hide'); @@ -1057,14 +1085,14 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderMoreFromSeason(view, item, apiClient) { - var section = view.querySelector('.moreFromSeasonSection'); + const section = view.querySelector('.moreFromSeasonSection'); if (section) { if (item.Type !== 'Episode' || !item.SeasonId || !item.SeriesId) { return void section.classList.add('hide'); } - var userId = apiClient.getCurrentUserId(); + const userId = apiClient.getCurrentUserId(); apiClient.getEpisodes(item.SeriesId, { SeasonId: item.SeasonId, UserId: userId, @@ -1076,7 +1104,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti section.classList.remove('hide'); section.querySelector('h2').innerHTML = globalize.translate('MoreFromValue', item.SeasonName); - var itemsContainer = section.querySelector('.itemsContainer'); + const itemsContainer = section.querySelector('.itemsContainer'); cardBuilder.buildCards(result.Items, { parentContainer: section, itemsContainer: itemsContainer, @@ -1089,7 +1117,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti includeParentInfoInTitle: false, allowBottomPadding: false }); - var card = itemsContainer.querySelector('.card[data-id="' + item.Id + '"]'); + const card = itemsContainer.querySelector('.card[data-id="' + item.Id + '"]'); if (card) { setTimeout(function () { @@ -1101,7 +1129,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderMoreFromArtist(view, item, apiClient) { - var section = view.querySelector('.moreFromArtistSection'); + const section = view.querySelector('.moreFromArtistSection'); if (section) { if (item.Type === 'MusicArtist') { @@ -1112,7 +1140,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti return void section.classList.add('hide'); } - var query = { + const query = { IncludeItemTypes: 'MusicAlbum', Recursive: true, ExcludeItemIds: item.Id, @@ -1160,7 +1188,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderSimilarItems(page, item, context) { - var similarCollapsible = page.querySelector('#similarCollapsible'); + const similarCollapsible = page.querySelector('#similarCollapsible'); if (similarCollapsible) { if (item.Type != 'Movie' && item.Type != 'Trailer' && item.Type != 'Series' && item.Type != 'Program' && item.Type != 'Recording' && item.Type != 'MusicAlbum' && item.Type != 'MusicArtist' && item.Type != 'Playlist') { @@ -1168,8 +1196,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } similarCollapsible.classList.remove('hide'); - var apiClient = connectionManager.getApiClient(item.ServerId); - var options = { + const apiClient = connectionManager.getApiClient(item.ServerId); + const options = { userId: apiClient.getCurrentUserId(), limit: 12, fields: 'PrimaryImageAspectRatio,UserData,CanDelete' @@ -1185,7 +1213,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } similarCollapsible.classList.remove('hide'); - var html = ''; + let html = ''; html += cardBuilder.getCardsHtml({ items: result.Items, shape: 'autooverflow', @@ -1200,7 +1228,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti overlayText: false, showYear: item.Type === 'Movie' || item.Type === 'Trailer' || item.Type === 'Series' }); - var similarContent = similarCollapsible.querySelector('.similarContent'); + const similarContent = similarCollapsible.querySelector('.similarContent'); similarContent.innerHTML = html; imageLoader.lazyChildren(similarContent); }); @@ -1208,12 +1236,12 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderSeriesAirTime(page, item, isStatic) { - var seriesAirTime = page.querySelector('#seriesAirTime'); + const seriesAirTime = page.querySelector('#seriesAirTime'); if (item.Type != 'Series') { seriesAirTime.classList.add('hide'); return; } - var html = ''; + let html = ''; if (item.AirDays && item.AirDays.length) { if (item.AirDays.length == 7) { html += 'daily'; @@ -1230,8 +1258,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti if (isStatic) { html += ' on ' + item.Studios[0].Name; } else { - var context = inferContext(item); - var href = appRouter.getRouteUrl(item.Studios[0], { + const context = inferContext(item); + const href = appRouter.getRouteUrl(item.Studios[0], { context: context, itemType: 'Studio', serverId: item.ServerId @@ -1249,15 +1277,15 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderTags(page, item) { - var itemTags = page.querySelector('.itemTags'); - var tagElements = []; - var tags = item.Tags || []; + const itemTags = page.querySelector('.itemTags'); + const tagElements = []; + let tags = item.Tags || []; if (item.Type === 'Program') { tags = []; } - for (var i = 0, length = tags.length; i < length; i++) { + for (let i = 0, length = tags.length; i < length; i++) { tagElements.push(tags[i]); } @@ -1271,8 +1299,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderChildren(page, item) { - var fields = 'ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount'; - var query = { + let fields = 'ItemCounts,PrimaryImageAspectRatio,BasicSyncInfo,CanDelete,MediaSourceCount'; + const query = { ParentId: item.Id, Fields: fields }; @@ -1281,9 +1309,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti query.SortBy = 'SortName'; } - var promise; - var apiClient = connectionManager.getApiClient(item.ServerId); - var userId = apiClient.getCurrentUserId(); + let promise; + const apiClient = connectionManager.getApiClient(item.ServerId); + const userId = apiClient.getCurrentUserId(); if (item.Type == 'Series') { promise = apiClient.getSeasons(item.Id, { @@ -1303,10 +1331,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti promise = promise || apiClient.getItems(apiClient.getCurrentUserId(), query); promise.then(function (result) { - var html = ''; - var scrollX = false; - var isList = false; - var childrenItemsContainer = page.querySelector('.childrenItemsContainer'); + let html = ''; + let scrollX = false; + let isList = false; + const childrenItemsContainer = page.querySelector('.childrenItemsContainer'); if (item.Type == 'MusicAlbum') { html = listView.getListViewHtml({ @@ -1399,7 +1427,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti childrenItemsContainer.innerHTML = html; imageLoader.lazyChildren(childrenItemsContainer); if (item.Type == 'BoxSet') { - var collectionItemTypes = [{ + const collectionItemTypes = [{ name: globalize.translate('HeaderVideos'), mediaType: 'Video' }, { @@ -1435,25 +1463,25 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderItemsByName(page, item) { - require('scripts/itembynamedetailpage'.split(','), function () { + import('scripts/itembynamedetailpage').then(() => { window.ItemsByName.renderItems(page, item); }); } function renderPlaylistItems(page, item) { - require('scripts/playlistedit'.split(','), function () { + import('scripts/playlistedit').then(() => { PlaylistViewer.render(page, item); }); } function renderProgramsForChannel(page, result) { - var html = ''; - var currentItems = []; - var currentStartDate = null; + let html = ''; + let currentItems = []; + let currentStartDate = null; - for (var i = 0, length = result.Items.length; i < length; i++) { - var item = result.Items[i]; - var itemStartDate = datetime.parseISO8601Date(item.StartDate); + for (let i = 0, length = result.Items.length; i < length; i++) { + const item = result.Items[i]; + const itemStartDate = datetime.parseISO8601Date(item.StartDate); if (!(currentStartDate && currentStartDate.toDateString() === itemStartDate.toDateString())) { if (currentItems.length) { @@ -1521,7 +1549,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderSeriesSchedule(page, item) { - var apiClient = connectionManager.getApiClient(item.ServerId); + const apiClient = connectionManager.getApiClient(item.ServerId); apiClient.getLiveTvPrograms({ UserId: apiClient.getCurrentUserId(), HasAired: false, @@ -1585,9 +1613,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function canPlaySomeItemInCollection(items) { - var i = 0; + let i = 0; - for (var length = items.length; i < length; i++) { + for (let length = items.length; i < length; i++) { if (playbackManager.canPlay(items[i])) { return true; } @@ -1601,17 +1629,17 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti page.querySelector('.collectionItems').innerHTML = ''; for (const type of types) { - var typeItems = filterItemsByCollectionItemType(items, type); + const typeItems = filterItemsByCollectionItemType(items, type); if (typeItems.length) { renderCollectionItemType(page, parentItem, type, typeItems); } } - var otherType = { + const otherType = { name: globalize.translate('HeaderOtherItems') }; - var otherTypeItems = items.filter(function (curr) { + const otherTypeItems = items.filter(function (curr) { return !types.filter(function (t) { return filterItemsByCollectionItemType([curr], t).length > 0; }).length; @@ -1627,9 +1655,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti }, items); } - var containers = page.querySelectorAll('.collectionItemsContainer'); + const containers = page.querySelectorAll('.collectionItemsContainer'); - var notifyRefreshNeeded = function () { + const notifyRefreshNeeded = function () { renderChildren(page, parentItem); }; @@ -1645,13 +1673,13 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti // HACK: Call autoFocuser again because btnPlay may be hidden, but focused by reloadFromItem // FIXME: Sometimes focus does not move until all (?) sections are loaded - require(['autoFocuser'], function (autoFocuser) { + import('autoFocuser').then(({default: autoFocuser}) => { autoFocuser.autoFocus(page); }); } function renderCollectionItemType(page, parentItem, type, items) { - var html = ''; + let html = ''; html += '
'; html += '
'; html += '

'; @@ -1659,7 +1687,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti html += '

'; html += '
'; html += '
'; - var shape = type.type == 'MusicAlbum' ? getSquareShape(false) : getPortraitShape(false); + const shape = type.type == 'MusicAlbum' ? getSquareShape(false) : getPortraitShape(false); html += cardBuilder.getCardsHtml({ items: items, shape: shape, @@ -1675,7 +1703,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti }); html += '
'; html += '
'; - var collectionItems = page.querySelector('.collectionItems'); + const collectionItems = page.querySelector('.collectionItems'); collectionItems.insertAdjacentHTML('beforeend', html); imageLoader.lazyChildren(collectionItems); } @@ -1691,7 +1719,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti }).then(function (result) { if (result.Items.length) { page.querySelector('#musicVideosCollapsible').classList.remove('hide'); - var musicVideosContent = page.querySelector('.musicVideosContent'); + const musicVideosContent = page.querySelector('.musicVideosContent'); musicVideosContent.innerHTML = getVideosHtml(result.Items); imageLoader.lazyChildren(musicVideosContent); } else { @@ -1704,7 +1732,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti connectionManager.getApiClient(item.ServerId).getAdditionalVideoParts(user.Id, item.Id).then(function (result) { if (result.Items.length) { page.querySelector('#additionalPartsCollapsible').classList.remove('hide'); - var additionalPartsContent = page.querySelector('#additionalPartsContent'); + const additionalPartsContent = page.querySelector('#additionalPartsContent'); additionalPartsContent.innerHTML = getVideosHtml(result.Items); imageLoader.lazyChildren(additionalPartsContent); } else { @@ -1714,13 +1742,13 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function renderScenes(page, item) { - var chapters = item.Chapters || []; + let chapters = item.Chapters || []; if (chapters.length && !chapters[0].ImageTag && (chapters = []), chapters.length) { page.querySelector('#scenesCollapsible').classList.remove('hide'); - var scenesContent = page.querySelector('#scenesContent'); + const scenesContent = page.querySelector('#scenesContent'); - require(['chaptercardbuilder'], function (chaptercardbuilder) { + import('chaptercardbuilder').then(({default: chaptercardbuilder}) => { chaptercardbuilder.buildChapterCards(item, chapters, { itemsContainer: scenesContent, backdropShape: 'overflowBackdrop', @@ -1747,14 +1775,14 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti function renderSpecials(page, item, user) { connectionManager.getApiClient(item.ServerId).getSpecialFeatures(user.Id, item.Id).then(function (specials) { - var specialsContent = page.querySelector('#specialsContent'); + const specialsContent = page.querySelector('#specialsContent'); specialsContent.innerHTML = getVideosHtml(specials); imageLoader.lazyChildren(specialsContent); }); } function renderCast(page, item) { - var people = (item.People || []).filter(function (p) { + const people = (item.People || []).filter(function (p) { return p.Type === 'Actor'; }); @@ -1763,9 +1791,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } page.querySelector('#castCollapsible').classList.remove('hide'); - var castContent = page.querySelector('#castContent'); + const castContent = page.querySelector('#castContent'); - require(['peoplecardbuilder'], function (peoplecardbuilder) { + import('peoplecardbuilder').then(({default: peoplecardbuilder}) => { peoplecardbuilder.buildPeopleCards(people, { itemsContainer: castContent, coverImage: true, @@ -1777,14 +1805,14 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function itemDetailPage() { - var self = this; + const self = this; self.setInitialCollapsibleState = setInitialCollapsibleState; self.renderDetails = renderDetails; self.renderCast = renderCast; } function bindAll(view, selector, eventName, fn) { - var elems = view.querySelectorAll(selector); + const elems = view.querySelectorAll(selector); for (const elem of elems) { elem.addEventListener(eventName, fn); @@ -1797,11 +1825,12 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } window.ItemDetailPage = new itemDetailPage(); - return function (view, params) { + + export default function (view, params) { function reload(instance, page, params) { loading.show(); - var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; + const apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; Promise.all([getPromise(apiClient, params), apiClient.getCurrentUser()]).then(([item, user]) => { currentItem = item; @@ -1812,8 +1841,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function splitVersions(instance, page, apiClient, params) { - require(['confirm'], function (confirm) { - confirm.default('Are you sure you wish to split the media sources into separate items?', 'Split Media Apart').then(function () { + import('confirm').then(({default: confirm}) => { + confirm('Are you sure you wish to split the media sources into separate items?', 'Split Media Apart').then(function () { loading.show(); apiClient.ajax({ type: 'DELETE', @@ -1827,7 +1856,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function getPlayOptions(startPosition) { - var audioStreamIndex = view.querySelector('.selectAudio').value || null; + const audioStreamIndex = view.querySelector('.selectAudio').value || null; return { startPositionTicks: startPosition, mediaSourceId: view.querySelector('.selectSource').value, @@ -1837,7 +1866,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function playItem(item, startPosition) { - var playOptions = getPlayOptions(startPosition); + const playOptions = getPlayOptions(startPosition); playOptions.items = [item]; playbackManager.play(playOptions); } @@ -1847,10 +1876,10 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function playCurrentItem(button, mode) { - var item = currentItem; + const item = currentItem; if (item.Type === 'Program') { - var apiClient = connectionManager.getApiClient(item.ServerId); + const apiClient = connectionManager.getApiClient(item.ServerId); return void apiClient.getLiveTvChannel(item.ChannelId, apiClient.getCurrentUserId()).then(function (channel) { playbackManager.play({ items: [channel] @@ -1874,7 +1903,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function onCancelSeriesTimerClick() { - require(['recordingHelper'], function (recordingHelper) { + import('recordingHelper').then(({default: recordingHelper}) => { recordingHelper.cancelSeriesTimerWithConfirmation(currentItem.Id, currentItem.ServerId).then(function () { Dashboard.navigate('livetv.html'); }); @@ -1882,7 +1911,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function onCancelTimerClick() { - require(['recordingHelper'], function (recordingHelper) { + import('recordingHelper').then(({default: recordingHelper}) => { recordingHelper.cancelTimer(connectionManager.getApiClient(currentItem.ServerId), currentItem.TimerId).then(function () { reload(self, view, params); }); @@ -1894,8 +1923,8 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function onDownloadClick() { - require(['fileDownloader'], function (fileDownloader) { - var downloadHref = apiClient.getItemDownloadUrl(currentItem.Id); + import('fileDownloader').then(({default: fileDownloader}) => { + const downloadHref = apiClient.getItemDownloadUrl(currentItem.Id); fileDownloader.download([{ url: downloadHref, itemId: currentItem.Id, @@ -1905,7 +1934,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function onMoreCommandsClick() { - var button = this; + const button = this; apiClient.getCurrentUser().then(function (user) { itemContextMenu.show(getContextMenuOptions(currentItem, user, button)).then(function (result) { if (result.deleted) { @@ -1923,11 +1952,11 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } function onWebSocketMessage(e, data) { - var msg = data; + const msg = data; if (msg.MessageType === 'UserDataChanged' && currentItem && msg.Data.UserId == apiClient.getCurrentUserId()) { - var key = currentItem.UserData.Key; - var userData = msg.Data.UserDataList.filter(function (u) { + const key = currentItem.UserData.Key; + const userData = msg.Data.UserDataList.filter(function (u) { return u.Key == key; })[0]; @@ -1939,9 +1968,9 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti } } - var currentItem; - var self = this; - var apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; + let currentItem; + const self = this; + const apiClient = params.serverId ? connectionManager.getApiClient(params.serverId) : ApiClient; view.querySelectorAll('.btnPlay'); bindAll(view, '.btnPlay', 'click', onPlayClick); bindAll(view, '.btnResume', 'click', onPlayClick); @@ -1962,7 +1991,7 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti renderSubtitleSelections(view, self._currentPlaybackMediaSources); }); view.addEventListener('viewshow', function (e) { - var page = this; + const page = this; libraryMenu.setTransparentMenu(true); @@ -1988,5 +2017,6 @@ define(['loading', 'appRouter', 'layoutManager', 'connectionManager', 'userSetti self._currentPlaybackMediaSources = null; self.currentRecordingFields = null; }); - }; -}); + } + +/* eslint-enable indent */ diff --git a/src/plugins/bookPlayer/plugin.js b/src/plugins/bookPlayer/plugin.js index db6c344dad..be5beb98ed 100644 --- a/src/plugins/bookPlayer/plugin.js +++ b/src/plugins/bookPlayer/plugin.js @@ -222,7 +222,7 @@ export class BookPlayer { return new Promise((resolve, reject) => { import('epubjs').then(({default: epubjs}) => { let downloadHref = apiClient.getItemDownloadUrl(item.Id); - let book = epubjs.default(downloadHref, {openAs: 'epub'}); + let book = epubjs(downloadHref, {openAs: 'epub'}); let rendition = book.renderTo(elem, {width: '100%', height: '97%'}); this._currentSrc = downloadHref; diff --git a/src/scripts/browser.js b/src/scripts/browser.js index 41e95fa6b4..b10587cb09 100644 --- a/src/scripts/browser.js +++ b/src/scripts/browser.js @@ -1,260 +1,256 @@ -define([], function () { - 'use strict'; +function isTv() { + // This is going to be really difficult to get right + const userAgent = navigator.userAgent.toLowerCase(); - function isTv() { - // This is going to be really difficult to get right - var userAgent = navigator.userAgent.toLowerCase(); - - if (userAgent.indexOf('tv') !== -1) { - return true; - } - - if (userAgent.indexOf('samsungbrowser') !== -1) { - return true; - } - - if (userAgent.indexOf('viera') !== -1) { - return true; - } - - if (userAgent.indexOf('web0s') !== -1) { - return true; - } - - return false; + if (userAgent.indexOf('tv') !== -1) { + return true; } - function isMobile(userAgent) { - var terms = [ - 'mobi', - 'ipad', - 'iphone', - 'ipod', - 'silk', - 'gt-p1000', - 'nexus 7', - 'kindle fire', - 'opera mini' - ]; - - var lower = userAgent.toLowerCase(); - - for (var i = 0, length = terms.length; i < length; i++) { - if (lower.indexOf(terms[i]) !== -1) { - return true; - } - } - - return false; + if (userAgent.indexOf('samsungbrowser') !== -1) { + return true; } - function hasKeyboard(browser) { - if (browser.touch) { - return true; - } - - if (browser.xboxOne) { - return true; - } - - if (browser.ps4) { - return true; - } - - if (browser.edgeUwp) { - // This is OK for now, but this won't always be true - // Should we use this? - // https://gist.github.com/wagonli/40d8a31bd0d6f0dd7a5d - return true; - } - - if (browser.tv) { - return true; - } - - return false; + if (userAgent.indexOf('viera') !== -1) { + return true; } - function iOSversion() { - // MacIntel: Apple iPad Pro 11 iOS 13.1 - if (/iP(hone|od|ad)|MacIntel/.test(navigator.platform)) { - // supports iOS 2.0 and later: - var v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/); - return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)]; + if (userAgent.indexOf('web0s') !== -1) { + return true; + } + + return false; +} + +function isMobile(userAgent) { + const terms = [ + 'mobi', + 'ipad', + 'iphone', + 'ipod', + 'silk', + 'gt-p1000', + 'nexus 7', + 'kindle fire', + 'opera mini' + ]; + + const lower = userAgent.toLowerCase(); + + for (let i = 0, length = terms.length; i < length; i++) { + if (lower.indexOf(terms[i]) !== -1) { + return true; } } - var _supportsCssAnimation; - var _supportsCssAnimationWithPrefix; - function supportsCssAnimation(allowPrefix) { - // TODO: Assess if this is still needed, as all of our targets should natively support CSS animations. - if (allowPrefix) { - if (_supportsCssAnimationWithPrefix === true || _supportsCssAnimationWithPrefix === false) { - return _supportsCssAnimationWithPrefix; - } - } else { - if (_supportsCssAnimation === true || _supportsCssAnimation === false) { - return _supportsCssAnimation; - } - } + return false; +} - var animation = false; - var domPrefixes = ['Webkit', 'O', 'Moz']; - var elm = document.createElement('div'); +function hasKeyboard(browser) { + if (browser.touch) { + return true; + } - if (elm.style.animationName !== undefined) { - animation = true; - } + if (browser.xboxOne) { + return true; + } - if (animation === false && allowPrefix) { - for (var i = 0; i < domPrefixes.length; i++) { - if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) { - animation = true; - break; - } - } - } + if (browser.ps4) { + return true; + } - if (allowPrefix) { - _supportsCssAnimationWithPrefix = animation; + if (browser.edgeUwp) { + // This is OK for now, but this won't always be true + // Should we use this? + // https://gist.github.com/wagonli/40d8a31bd0d6f0dd7a5d + return true; + } + + if (browser.tv) { + return true; + } + + return false; +} + +function iOSversion() { + // MacIntel: Apple iPad Pro 11 iOS 13.1 + if (/iP(hone|od|ad)|MacIntel/.test(navigator.platform)) { + // supports iOS 2.0 and later: + const v = (navigator.appVersion).match(/OS (\d+)_(\d+)_?(\d+)?/); + return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)]; + } +} + +let _supportsCssAnimation; +let _supportsCssAnimationWithPrefix; +function supportsCssAnimation(allowPrefix) { + // TODO: Assess if this is still needed, as all of our targets should natively support CSS animations. + if (allowPrefix) { + if (_supportsCssAnimationWithPrefix === true || _supportsCssAnimationWithPrefix === false) { return _supportsCssAnimationWithPrefix; - } else { - _supportsCssAnimation = animation; + } + } else { + if (_supportsCssAnimation === true || _supportsCssAnimation === false) { return _supportsCssAnimation; } } - var uaMatch = function (ua) { - ua = ua.toLowerCase(); + let animation = false; + const domPrefixes = ['Webkit', 'O', 'Moz']; + const elm = document.createElement('div'); - var match = /(edg)[ \/]([\w.]+)/.exec(ua) || - /(edga)[ \/]([\w.]+)/.exec(ua) || - /(edgios)[ \/]([\w.]+)/.exec(ua) || - /(edge)[ \/]([\w.]+)/.exec(ua) || - /(opera)[ \/]([\w.]+)/.exec(ua) || - /(opr)[ \/]([\w.]+)/.exec(ua) || - /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(safari)[ \/]([\w.]+)/.exec(ua) || - /(firefox)[ \/]([\w.]+)/.exec(ua) || - ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; + if (elm.style.animationName !== undefined) { + animation = true; + } - var versionMatch = /(version)[ \/]([\w.]+)/.exec(ua); - - var platform_match = /(ipad)/.exec(ua) || - /(iphone)/.exec(ua) || - /(windows)/.exec(ua) || - /(android)/.exec(ua) || - []; - - var browser = match[1] || ''; - - if (browser === 'edge') { - platform_match = ['']; + if (animation === false && allowPrefix) { + for (let i = 0; i < domPrefixes.length; i++) { + if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) { + animation = true; + break; + } } - - if (browser === 'opr') { - browser = 'opera'; - } - - var version; - if (versionMatch && versionMatch.length > 2) { - version = versionMatch[2]; - } - - version = version || match[2] || '0'; - - var versionMajor = parseInt(version.split('.')[0]); - - if (isNaN(versionMajor)) { - versionMajor = 0; - } - - return { - browser: browser, - version: version, - platform: platform_match[0] || '', - versionMajor: versionMajor - }; - }; - - var userAgent = navigator.userAgent; - - var matched = uaMatch(userAgent); - var browser = {}; - - if (matched.browser) { - browser[matched.browser] = true; - browser.version = matched.version; - browser.versionMajor = matched.versionMajor; } - if (matched.platform) { - browser[matched.platform] = true; - } - - browser.edgeChromium = browser.edg || browser.edga || browser.edgios; - - if (!browser.chrome && !browser.edgeChromium && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf('webkit') !== -1) { - browser.safari = true; - } - - if (userAgent.toLowerCase().indexOf('playstation 4') !== -1) { - browser.ps4 = true; - browser.tv = true; - } - - if (isMobile(userAgent)) { - browser.mobile = true; - } - - if (userAgent.toLowerCase().indexOf('xbox') !== -1) { - browser.xboxOne = true; - browser.tv = true; - } - browser.animate = typeof document !== 'undefined' && document.documentElement.animate != null; - browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || self.tizen != null; - browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) !== -1; - browser.edgeUwp = browser.edge && (userAgent.toLowerCase().indexOf('msapphost') !== -1 || userAgent.toLowerCase().indexOf('webview') !== -1); - - if (!browser.tizen) { - browser.orsay = userAgent.toLowerCase().indexOf('smarthub') !== -1; + if (allowPrefix) { + _supportsCssAnimationWithPrefix = animation; + return _supportsCssAnimationWithPrefix; } else { - var v = (navigator.appVersion).match(/Tizen (\d+).(\d+)/); - browser.tizenVersion = parseInt(v[1]); + _supportsCssAnimation = animation; + return _supportsCssAnimation; + } +} + +const uaMatch = function (ua) { + ua = ua.toLowerCase(); + + const match = /(edg)[ \/]([\w.]+)/.exec(ua) || + /(edga)[ \/]([\w.]+)/.exec(ua) || + /(edgios)[ \/]([\w.]+)/.exec(ua) || + /(edge)[ \/]([\w.]+)/.exec(ua) || + /(opera)[ \/]([\w.]+)/.exec(ua) || + /(opr)[ \/]([\w.]+)/.exec(ua) || + /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(safari)[ \/]([\w.]+)/.exec(ua) || + /(firefox)[ \/]([\w.]+)/.exec(ua) || + ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + const versionMatch = /(version)[ \/]([\w.]+)/.exec(ua); + + let platform_match = /(ipad)/.exec(ua) || + /(iphone)/.exec(ua) || + /(windows)/.exec(ua) || + /(android)/.exec(ua) || + []; + + let browser = match[1] || ''; + + if (browser === 'edge') { + platform_match = ['']; } - if (browser.edgeUwp) { - browser.edge = true; + if (browser === 'opr') { + browser = 'opera'; } - browser.tv = isTv(); - browser.operaTv = browser.tv && userAgent.toLowerCase().indexOf('opr/') !== -1; - - if (browser.mobile || browser.tv) { - browser.slow = true; + let version; + if (versionMatch && versionMatch.length > 2) { + version = versionMatch[2]; } - if (typeof document !== 'undefined') { - /* eslint-disable-next-line compat/compat */ - if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0)) { - browser.touch = true; - } + version = version || match[2] || '0'; + + let versionMajor = parseInt(version.split('.')[0]); + + if (isNaN(versionMajor)) { + versionMajor = 0; } - browser.keyboard = hasKeyboard(browser); - browser.supportsCssAnimation = supportsCssAnimation; + return { + browser: browser, + version: version, + platform: platform_match[0] || '', + versionMajor: versionMajor + }; +}; - browser.osx = userAgent.toLowerCase().indexOf('os x') !== -1; - browser.iOS = browser.ipad || browser.iphone || browser.ipod; +const userAgent = navigator.userAgent; - if (browser.iOS) { - browser.iOSVersion = iOSversion(); +const matched = uaMatch(userAgent); +const browser = {}; - if (browser.iOSVersion && browser.iOSVersion.length >= 2) { - browser.iOSVersion = browser.iOSVersion[0] + (browser.iOSVersion[1] / 10); - } +if (matched.browser) { + browser[matched.browser] = true; + browser.version = matched.version; + browser.versionMajor = matched.versionMajor; +} + +if (matched.platform) { + browser[matched.platform] = true; +} + +browser.edgeChromium = browser.edg || browser.edga || browser.edgios; + +if (!browser.chrome && !browser.edgeChromium && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf('webkit') !== -1) { + browser.safari = true; +} + +if (userAgent.toLowerCase().indexOf('playstation 4') !== -1) { + browser.ps4 = true; + browser.tv = true; +} + +if (isMobile(userAgent)) { + browser.mobile = true; +} + +if (userAgent.toLowerCase().indexOf('xbox') !== -1) { + browser.xboxOne = true; + browser.tv = true; +} +browser.animate = typeof document !== 'undefined' && document.documentElement.animate != null; +browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || self.tizen != null; +browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) !== -1; +browser.edgeUwp = browser.edge && (userAgent.toLowerCase().indexOf('msapphost') !== -1 || userAgent.toLowerCase().indexOf('webview') !== -1); + +if (!browser.tizen) { + browser.orsay = userAgent.toLowerCase().indexOf('smarthub') !== -1; +} else { + const v = (navigator.appVersion).match(/Tizen (\d+).(\d+)/); + browser.tizenVersion = parseInt(v[1]); +} + +if (browser.edgeUwp) { + browser.edge = true; +} + +browser.tv = isTv(); +browser.operaTv = browser.tv && userAgent.toLowerCase().indexOf('opr/') !== -1; + +if (browser.mobile || browser.tv) { + browser.slow = true; +} + +if (typeof document !== 'undefined') { + /* eslint-disable-next-line compat/compat */ + if (('ontouchstart' in window) || (navigator.maxTouchPoints > 0)) { + browser.touch = true; } +} - return browser; -}); +browser.keyboard = hasKeyboard(browser); +browser.supportsCssAnimation = supportsCssAnimation; + +browser.osx = userAgent.toLowerCase().indexOf('os x') !== -1; +browser.iOS = browser.ipad || browser.iphone || browser.ipod; + +if (browser.iOS) { + browser.iOSVersion = iOSversion(); + + if (browser.iOSVersion && browser.iOSVersion.length >= 2) { + browser.iOSVersion = browser.iOSVersion[0] + (browser.iOSVersion[1] / 10); + } +} + +export default browser;