From b5445515c8d6f82c4b074969dce411bacc7c916c Mon Sep 17 00:00:00 2001 From: Jacob Weiss Date: Sat, 27 Apr 2024 15:03:51 -0400 Subject: [PATCH] Modified legacy routes and added books controller to start working toward multi-part AudioBook support --- src/apps/stable/routes/legacyRoutes/user.ts | 6 + src/components/router/appRouter.js | 5 + src/controllers/books/books.html | 58 + src/controllers/books/booksmain.js | 1185 +++++++++++++++++++ 4 files changed, 1254 insertions(+) create mode 100644 src/controllers/books/books.html create mode 100644 src/controllers/books/booksmain.js diff --git a/src/apps/stable/routes/legacyRoutes/user.ts b/src/apps/stable/routes/legacyRoutes/user.ts index 19b87c7cd8..6ad1e8a5ae 100644 --- a/src/apps/stable/routes/legacyRoutes/user.ts +++ b/src/apps/stable/routes/legacyRoutes/user.ts @@ -67,6 +67,12 @@ export const LEGACY_USER_ROUTES: LegacyRoute[] = [ controller: 'user/subtitles/index', view: 'user/subtitles/index.html' } + }, { + path: 'books.html', + pageProps: { + controller: 'books/booksmain', + view: 'books/books.html' + } }, { path: 'tv.html', pageProps: { diff --git a/src/components/router/appRouter.js b/src/components/router/appRouter.js index de6b3c6871..4e516a2269 100644 --- a/src/components/router/appRouter.js +++ b/src/components/router/appRouter.js @@ -692,6 +692,11 @@ class AppRouter { return url; } + if (item.CollectionType == CollectionType.Books) { + let urlForList = '#/books.html?topParentId=' + item.Id; + + return urlForList; + } } const itemTypes = ['Playlist', 'TvChannel', 'Program', 'BoxSet', 'MusicAlbum', 'MusicGenre', 'Person', 'Recording', 'MusicArtist']; diff --git a/src/controllers/books/books.html b/src/controllers/books/books.html new file mode 100644 index 0000000000..a755ad1c9b --- /dev/null +++ b/src/controllers/books/books.html @@ -0,0 +1,58 @@ +
+
+
+
+
+
+ + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
diff --git a/src/controllers/books/booksmain.js b/src/controllers/books/booksmain.js new file mode 100644 index 0000000000..3ea6496f44 --- /dev/null +++ b/src/controllers/books/booksmain.js @@ -0,0 +1,1185 @@ +import globalize from '../../scripts/globalize'; +import listView from '../../components/listview/listview'; +import * as userSettings from '../../scripts/settings/userSettings'; +import focusManager from '../../components/focusManager'; +import cardBuilder from '../../components/cardbuilder/cardBuilder'; +import loading from '../../components/loading/loading'; +import AlphaNumericShortcuts from '../../scripts/alphanumericshortcuts'; +import libraryBrowser from '../../scripts/libraryBrowser'; +import { playbackManager } from '../../components/playback/playbackmanager'; +import AlphaPicker from '../../components/alphaPicker/alphaPicker'; +import '../../elements/emby-itemscontainer/emby-itemscontainer'; +import '../../elements/emby-scroller/emby-scroller'; +import ServerConnections from '../../components/ServerConnections'; +import LibraryMenu from '../../scripts/libraryMenu'; +import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type'; +import { ItemSortBy } from '@jellyfin/sdk/lib/generated-client/models/item-sort-by'; + + +function modifyQueryWithFilters(instance, query) { + const sortValues = instance.getSortValues(); + + if (!query.SortBy) { + query.SortBy = sortValues.sortBy; + query.SortOrder = sortValues.sortOrder; + } + + query.Fields = query.Fields ? query.Fields + ',PrimaryImageAspectRatio' : 'PrimaryImageAspectRatio'; + query.ImageTypeLimit = 1; + let hasFilters; + const queryFilters = []; + const filters = instance.getFilters(); + + if (filters.IsPlayed) { + queryFilters.push('IsPlayed'); + hasFilters = true; + } + + if (filters.IsUnplayed) { + queryFilters.push('IsUnplayed'); + hasFilters = true; + } + + if (filters.IsFavorite) { + queryFilters.push('IsFavorite'); + hasFilters = true; + } + + if (filters.IsResumable) { + queryFilters.push('IsResumable'); + hasFilters = true; + } + + if (filters.VideoTypes) { + hasFilters = true; + query.VideoTypes = filters.VideoTypes; + } + + if (filters.GenreIds) { + hasFilters = true; + query.GenreIds = filters.GenreIds; + } + + if (filters.Is4K) { + query.Is4K = true; + hasFilters = true; + } + + if (filters.IsHD) { + query.IsHD = true; + hasFilters = true; + } + + if (filters.IsSD) { + query.IsHD = false; + hasFilters = true; + } + + if (filters.Is3D) { + query.Is3D = true; + hasFilters = true; + } + + if (filters.HasSubtitles) { + query.HasSubtitles = true; + hasFilters = true; + } + + if (filters.HasTrailer) { + query.HasTrailer = true; + hasFilters = true; + } + + if (filters.HasSpecialFeature) { + query.HasSpecialFeature = true; + hasFilters = true; + } + + if (filters.HasThemeSong) { + query.HasThemeSong = true; + hasFilters = true; + } + + if (filters.HasThemeVideo) { + query.HasThemeVideo = true; + hasFilters = true; + } + + query.Filters = queryFilters.length ? queryFilters.join(',') : null; + instance.setFilterStatus(hasFilters); + + if (instance.alphaPicker) { + const newValue = instance.alphaPicker.value(); + if (newValue === '#') { + query.NameLessThan = 'A'; + delete query.NameStartsWith; + } else { + query.NameStartsWith = newValue; + delete query.NameLessThan; + } + } + + return query; +} + +function setSortButtonIcon(btnSortIcon, icon) { + btnSortIcon.classList.remove('arrow_downward'); + btnSortIcon.classList.remove('arrow_upward'); + btnSortIcon.classList.add(icon); +} + +function updateSortText(instance) { + const btnSortText = instance.btnSortText; + + if (btnSortText) { + const options = instance.getSortMenuOptions(); + const values = instance.getSortValues(); + const sortBy = values.sortBy; + + for (const option of options) { + if (sortBy === option.value) { + btnSortText.innerHTML = globalize.translate('SortByValue', option.name); + break; + } + } + + const btnSortIcon = instance.btnSortIcon; + + if (btnSortIcon) { + setSortButtonIcon(btnSortIcon, values.sortOrder === 'Descending' ? 'arrow_downward' : 'arrow_upward'); + } + } +} + +function updateItemsContainerForViewType(instance) { + if (instance.getViewSettings().imageType === 'list') { + instance.itemsContainer.classList.remove('vertical-wrap'); + instance.itemsContainer.classList.add('vertical-list'); + } else { + instance.itemsContainer.classList.add('vertical-wrap'); + instance.itemsContainer.classList.remove('vertical-list'); + } +} + +function updateAlphaPickerState(instance) { + if (instance.alphaPicker) { + const alphaPicker = instance.alphaPickerElement; + + if (alphaPicker) { + const values = instance.getSortValues(); + + if (values.sortBy.indexOf(ItemSortBy.SortName) !== -1) { + alphaPicker.classList.remove('hide'); + instance.itemsContainer.parentNode.classList.add('padded-right-withalphapicker'); + } else { + alphaPicker.classList.add('hide'); + instance.itemsContainer.parentNode.classList.remove('padded-right-withalphapicker'); + } + } + } +} + +function getItems(instance, params, item, sortBy, startIndex, limit) { + const apiClient = ServerConnections.currentApiClient(); + + instance.queryRecursive = false; + + if (!item) { + // console.log("I dont think this is right"); + instance.queryRecursive = true; + + return apiClient['getItems'](apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, { + StartIndex: startIndex, + Limit: limit, + Fields: 'PrimaryImageAspectRatio,SortName', + ImageTypeLimit: 1, + IncludeItemTypes: 'AudioBook,Book', + Recursive: true, + IsFavorite: params.IsFavorite === 'true' || null, + ArtistIds: params.artistId || null, + SortBy: sortBy + })); + } + + return apiClient.getItems(apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, { + StartIndex: startIndex, + Limit: limit, + Fields: 'PrimaryImageAspectRatio,SortName,Path,ChildCount,MediaSourceCount', + ImageTypeLimit: 1, + ParentId: item.Id, + SortBy: sortBy, + // IncludeItemTypes: 'AudioBook'? + })); +} + +function getItem(params) { + if (params.type === 'Recordings' || params.type === 'Programs' || params.type === 'nextup') { + return Promise.resolve(null); + } + + const apiClient = ServerConnections.currentApiClient(); + const itemId = params.genreId || params.musicGenreId || params.studioId || params.personId || params.parentId; + + if (itemId) { + return apiClient.getItem(apiClient.getCurrentUserId(), itemId); + } + + return Promise.resolve(null); +} + +function showViewSettingsMenu() { + const instance = this; + + import('../../components/viewSettings/viewSettings').then(({ default: ViewSettings }) => { + new ViewSettings().show({ + settingsKey: instance.getSettingsKey(), + settings: instance.getViewSettings(), + visibleSettings: instance.getVisibleViewSettings() + }).then(function () { + updateItemsContainerForViewType(instance); + instance.itemsContainer.refreshItems(); + }); + }); +} + +function showFilterMenu() { + const instance = this; + + import('../../components/filtermenu/filtermenu').then(({ default: FilterMenu }) => { + new FilterMenu().show({ + settingsKey: instance.getSettingsKey(), + settings: instance.getFilters(), + visibleSettings: instance.getVisibleFilters(), + onChange: instance.itemsContainer.refreshItems.bind(instance.itemsContainer), + parentId: instance.params.parentId, + itemTypes: instance.getItemTypes(), + serverId: instance.params.serverId, + filterMenuOptions: instance.getFilterMenuOptions() + }).then(function () { + instance.itemsContainer.refreshItems(); + }); + }); +} + +function showSortMenu() { + const instance = this; + + import('../../components/sortmenu/sortmenu').then(({ default: SortMenu }) => { + new SortMenu().show({ + settingsKey: instance.getSettingsKey(), + settings: instance.getSortValues(), + onChange: instance.itemsContainer.refreshItems.bind(instance.itemsContainer), + serverId: instance.params.serverId, + sortOptions: instance.getSortMenuOptions() + }).then(function () { + updateSortText(instance); + updateAlphaPickerState(instance); + instance.itemsContainer.refreshItems(); + }); + }); +} + +function onNewItemClick() { + const instance = this; + + import('../../components/playlisteditor/playlisteditor').then(({ default: PlaylistEditor }) => { + const playlistEditor = new PlaylistEditor(); + playlistEditor.show({ + items: [], + serverId: instance.params.serverId + }).catch(() => { + // Dialog closed + }); + }).catch(err => { + console.error('[onNewItemClick] failed to load playlist editor', err); + }); +} + +function hideOrShowAll(elems, hide) { + for (const elem of elems) { + if (hide) { + elem.classList.add('hide'); + } else { + elem.classList.remove('hide'); + } + } +} + +function bindAll(elems, eventName, fn) { + for (const elem of elems) { + elem.addEventListener(eventName, fn); + } +} + +class BooksView { + constructor(view, params) { + const query = { + StartIndex: 0, + Limit: undefined + }; + + if (userSettings.libraryPageSize() > 0) { + query['Limit'] = userSettings.libraryPageSize(); + } + + let isLoading = false; + + function onNextPageClick() { + if (!isLoading && query.Limit > 0) { + query.StartIndex += query.Limit; + self.itemsContainer.refreshItems().then(() => { + window.scrollTo(0, 0); + autoFocus(); + }); + } + } + + function onPreviousPageClick() { + if (!isLoading && query.Limit > 0) { + query.StartIndex = Math.max(0, query.StartIndex - query.Limit); + self.itemsContainer.refreshItems().then(() => { + window.scrollTo(0, 0); + autoFocus(); + }); + } + } + + function updatePaging(startIndex, totalRecordCount, limit) { + const pagingHtml = libraryBrowser.getQueryPagingHtml({ + startIndex, + limit, + totalRecordCount, + showLimit: false, + updatePageSizeSetting: false, + addLayoutButton: false, + sortButton: false, + filterButton: false + }); + + for (const elem of view.querySelectorAll('.paging')) { + elem.innerHTML = pagingHtml; + } + + for (const elem of view.querySelectorAll('.btnNextPage')) { + elem.addEventListener('click', onNextPageClick); + } + + for (const elem of view.querySelectorAll('.btnPreviousPage')) { + elem.addEventListener('click', onPreviousPageClick); + } + } + + function fetchData() { + isLoading = true; + + return getItems(self, params, self.currentItem, null, query.StartIndex, query.Limit).then(function (result) { + if (self.totalItemCount == null) { + self.totalItemCount = result.Items ? result.Items.length : result.length; + } + + updateAlphaPickerState(self); + updatePaging(result.StartIndex, result.TotalRecordCount, query.Limit); + return result; + }).finally(() => { + isLoading = false; + }); + } + + function getItemsHtml(items) { + const settings = self.getViewSettings(); + + if (settings.imageType === 'list') { + return listView.getListViewHtml({ + items: items + }); + } + + let shape; + let preferThumb; + let preferDisc; + let preferLogo; + let defaultShape; + const item = self.currentItem; + let lines = settings.showTitle ? 2 : 0; + + if (settings.imageType === 'banner') { + shape = 'banner'; + } else if (settings.imageType === 'disc') { + shape = 'square'; + preferDisc = true; + } else if (settings.imageType === 'logo') { + shape = 'backdrop'; + preferLogo = true; + } else if (settings.imageType === 'thumb') { + shape = 'backdrop'; + preferThumb = true; + } else if (params.type === 'nextup') { + shape = 'backdrop'; + preferThumb = settings.imageType === 'thumb'; + } else if (params.type === 'Programs' || params.type === 'Recordings') { + shape = params.IsMovie === 'true' ? 'portrait' : 'autoVertical'; + preferThumb = params.IsMovie !== 'true' ? 'auto' : false; + defaultShape = params.IsMovie === 'true' ? 'portrait' : 'backdrop'; + } else { + shape = 'autoVertical'; + } + + let posterOptions = { + shape: shape, + showTitle: settings.showTitle, + showYear: settings.showTitle, + centerText: true, + coverImage: true, + preferThumb: preferThumb, + preferDisc: preferDisc, + preferLogo: preferLogo, + overlayPlayButton: false, + overlayMoreButton: true, + overlayText: !settings.showTitle, + defaultShape: defaultShape, + action: params.type === 'Audio' ? 'playallfromhere' : null + }; + + if (params.type === 'nextup') { + posterOptions.showParentTitle = settings.showTitle; + } else if (params.type === 'Person') { + posterOptions.showYear = false; + posterOptions.showParentTitle = false; + lines = 1; + } else if (params.type === 'Audio') { + posterOptions.showParentTitle = settings.showTitle; + } else if (params.type === 'MusicAlbum') { + posterOptions.showParentTitle = settings.showTitle; + } else if (params.type === 'Episode') { + posterOptions.showParentTitle = settings.showTitle; + } else if (params.type === 'MusicArtist') { + posterOptions.showYear = false; + lines = 1; + } else if (params.type === 'Programs') { + lines = settings.showTitle ? 1 : 0; + const showParentTitle = settings.showTitle && params.IsMovie !== 'true'; + + if (showParentTitle) { + lines++; + } + + const showAirTime = settings.showTitle && params.type !== 'Recordings'; + + if (showAirTime) { + lines++; + } + + const showYear = settings.showTitle && params.IsMovie === 'true' && params.type === 'Recordings'; + + if (showYear) { + lines++; + } + + posterOptions = Object.assign(posterOptions, { + inheritThumb: params.type === 'Recordings', + context: 'livetv', + showParentTitle: showParentTitle, + showAirTime: showAirTime, + showAirDateTime: showAirTime, + overlayPlayButton: false, + overlayMoreButton: true, + showYear: showYear, + coverImage: true + }); + } else { + posterOptions.showParentTitle = settings.showTitle; + } + + posterOptions.lines = lines; + posterOptions.items = items; + + if (item && item.CollectionType === CollectionType.Folders) { + posterOptions.context = 'folders'; + } + + return cardBuilder.getCardsHtml(posterOptions); + } + + function initAlphaPicker() { + self.scroller = view.querySelector('.scrollFrameY'); + const alphaPickerElement = self.alphaPickerElement; + + alphaPickerElement.classList.add('alphaPicker-fixed-right'); + alphaPickerElement.classList.add('focuscontainer-right'); + self.itemsContainer.parentNode.classList.add('padded-right-withalphapicker'); + + self.alphaPicker = new AlphaPicker({ + element: alphaPickerElement, + valueChangeEvent: 'click' + }); + self.alphaPicker.on('alphavaluechanged', onAlphaPickerValueChanged); + } + + function onAlphaPickerValueChanged() { + query.StartIndex = 0; + self.itemsContainer.refreshItems(); + } + + function setTitle(item) { + LibraryMenu.setTitle(getTitle(item) || ''); + + if (item && item.CollectionType === CollectionType.Playlists) { + hideOrShowAll(view.querySelectorAll('.btnNewItem'), false); + } else { + hideOrShowAll(view.querySelectorAll('.btnNewItem'), true); + } + } + + function getTitle(item) { + if (params.type === 'Recordings') { + return globalize.translate('Recordings'); + } + + if (params.type === 'Programs') { + if (params.IsMovie === 'true') { + return globalize.translate('Movies'); + } + + if (params.IsSports === 'true') { + return globalize.translate('Sports'); + } + + if (params.IsKids === 'true') { + return globalize.translate('HeaderForKids'); + } + + if (params.IsAiring === 'true') { + return globalize.translate('HeaderOnNow'); + } + + if (params.IsSeries === 'true') { + return globalize.translate('Shows'); + } + + if (params.IsNews === 'true') { + return globalize.translate('News'); + } + + return globalize.translate('Programs'); + } + + if (params.type === 'nextup') { + return globalize.translate('NextUp'); + } + + if (params.type === 'favoritemovies') { + return globalize.translate('FavoriteMovies'); + } + + if (item) { + return item.Name; + } + + if (params.type === 'Movie') { + return globalize.translate('Movies'); + } + + if (params.type === 'Series') { + return globalize.translate('Shows'); + } + + if (params.type === 'Season') { + return globalize.translate('Seasons'); + } + + if (params.type === 'Episode') { + return globalize.translate('Episodes'); + } + + if (params.type === 'MusicArtist') { + return globalize.translate('Artists'); + } + + if (params.type === 'MusicAlbum') { + return globalize.translate('Albums'); + } + + if (params.type === 'Audio') { + return globalize.translate('Songs'); + } + + if (params.type === 'Video') { + return globalize.translate('Videos'); + } + } + + function play() { + const currentItem = self.currentItem; + + if (currentItem && !self.hasFilters) { + const values = self.getSortValues(); + playbackManager.play({ + items: [currentItem], + queryOptions: { + SortBy: values.sortBy, + SortOrder: values.sortOrder + }, + autoplay: true + }); + } else { + getItems(self, self.params, currentItem, null, 0, 300).then(function (result) { + playbackManager.play({ + items: result.Items, + autoplay: true + }); + }); + } + } + + function queue() { + const currentItem = self.currentItem; + + if (currentItem && !self.hasFilters) { + playbackManager.queue({ + items: [currentItem] + }); + } else { + getItems(self, self.params, currentItem, null, 0, 300).then(function (result) { + playbackManager.queue({ + items: result.Items + }); + }); + } + } + + function shuffle() { + const currentItem = self.currentItem; + + if (currentItem && !self.hasFilters) { + playbackManager.shuffle(currentItem); + } else { + getItems(self, self.params, currentItem, 'Random', 0, 300).then(function (result) { + playbackManager.play({ + items: result.Items, + autoplay: true + }); + }); + } + } + + function autoFocus() { + import('../../components/autoFocuser').then(({ default: autoFocuser }) => { + autoFocuser.autoFocus(view); + }); + } + + const self = this; + self.params = params; + this.itemsContainer = view.querySelector('.itemsContainer'); + + if (params.parentId) { + this.itemsContainer.setAttribute('data-parentid', params.parentId); + } else if (params.type === 'nextup') { + this.itemsContainer.setAttribute('data-monitor', 'videoplayback'); + } else if (params.type === 'favoritemovies') { + this.itemsContainer.setAttribute('data-monitor', 'markfavorite'); + } else if (params.type === 'Programs') { + this.itemsContainer.setAttribute('data-refreshinterval', '300000'); + } + + const btnViewSettings = view.querySelectorAll('.btnViewSettings'); + + for (const btnViewSetting of btnViewSettings) { + btnViewSetting.addEventListener('click', showViewSettingsMenu.bind(this)); + } + + const filterButtons = view.querySelectorAll('.btnFilter'); + this.filterButtons = filterButtons; + const hasVisibleFilters = this.getVisibleFilters().length; + + for (const btnFilter of filterButtons) { + btnFilter.addEventListener('click', showFilterMenu.bind(this)); + + if (hasVisibleFilters) { + btnFilter.classList.remove('hide'); + } else { + btnFilter.classList.add('hide'); + } + } + + const sortButtons = view.querySelectorAll('.btnSort'); + + this.sortButtons = sortButtons; + for (const sortButton of sortButtons) { + sortButton.addEventListener('click', showSortMenu.bind(this)); + + if (params.type !== 'nextup') { + sortButton.classList.remove('hide'); + } + } + + this.btnSortText = view.querySelector('.btnSortText'); + this.btnSortIcon = view.querySelector('.btnSortIcon'); + bindAll(view.querySelectorAll('.btnNewItem'), 'click', onNewItemClick.bind(this)); + this.alphaPickerElement = view.querySelector('.alphaPicker'); + self.itemsContainer.fetchData = fetchData; + self.itemsContainer.getItemsHtml = getItemsHtml; + view.addEventListener('viewshow', function (e) { + const isRestored = e.detail.isRestored; + + if (!isRestored) { + loading.show(); + updateSortText(self); + updateItemsContainerForViewType(self); + } + + setTitle(null); + getItem(params).then(function (item) { + setTitle(item); + self.currentItem = item; + const refresh = !isRestored; + self.itemsContainer.resume({ + refresh: refresh + }).then(function () { + loading.hide(); + + if (refresh) { + focusManager.autoFocus(self.itemsContainer); + } + }); + + if (!isRestored && item && item.Type !== 'PhotoAlbum') { + initAlphaPicker(); + } + + const itemType = item ? item.Type : null; + + if ((itemType === 'MusicGenre' || params.type !== 'Programs' && itemType !== 'Channel') + // Folder, Playlist views + && itemType !== 'UserView' + // Only Photo (homevideos) CollectionFolders are supported + && !(itemType === 'CollectionFolder' && item?.CollectionType !== CollectionType.Homevideos) + ) { + // Show Play All buttons + hideOrShowAll(view.querySelectorAll('.btnPlay'), false); + } else { + // Hide Play All buttons + hideOrShowAll(view.querySelectorAll('.btnPlay'), true); + } + + if ((itemType === 'MusicGenre' || params.type !== 'Programs' && params.type !== 'nextup' && itemType !== 'Channel') + // Folder, Playlist views + && itemType !== 'UserView' + // Only Photo (homevideos) CollectionFolders are supported + && !(itemType === 'CollectionFolder' && item?.CollectionType !== CollectionType.Homevideos) + ) { + // Show Shuffle buttons + hideOrShowAll(view.querySelectorAll('.btnShuffle'), false); + } else { + // Hide Shuffle buttons + hideOrShowAll(view.querySelectorAll('.btnShuffle'), true); + } + + if (item && playbackManager.canQueue(item)) { + // Show Queue button + hideOrShowAll(view.querySelectorAll('.btnQueue'), false); + } else { + // Hide Queue button + hideOrShowAll(view.querySelectorAll('.btnQueue'), true); + } + }); + + if (!isRestored) { + bindAll(view.querySelectorAll('.btnPlay'), 'click', play); + bindAll(view.querySelectorAll('.btnQueue'), 'click', queue); + bindAll(view.querySelectorAll('.btnShuffle'), 'click', shuffle); + } + + self.alphaNumericShortcuts = new AlphaNumericShortcuts({ + itemsContainer: self.itemsContainer + }); + }); + view.addEventListener('viewhide', function () { + const itemsContainer = self.itemsContainer; + + if (itemsContainer) { + itemsContainer.pause(); + } + + const alphaNumericShortcuts = self.alphaNumericShortcuts; + + if (alphaNumericShortcuts) { + alphaNumericShortcuts.destroy(); + self.alphaNumericShortcuts = null; + } + }); + view.addEventListener('viewdestroy', function () { + if (self.listController) { + self.listController.destroy(); + } + + if (self.alphaPicker) { + self.alphaPicker.off('alphavaluechanged', onAlphaPickerValueChanged); + self.alphaPicker.destroy(); + } + + self.currentItem = null; + self.scroller = null; + self.itemsContainer = null; + self.filterButtons = null; + self.sortButtons = null; + self.btnSortText = null; + self.btnSortIcon = null; + self.alphaPickerElement = null; + }); + } + + getFilters() { + const basekey = this.getSettingsKey(); + return { + IsPlayed: userSettings.getFilter(basekey + '-filter-IsPlayed') === 'true', + IsUnplayed: userSettings.getFilter(basekey + '-filter-IsUnplayed') === 'true', + IsFavorite: userSettings.getFilter(basekey + '-filter-IsFavorite') === 'true', + IsResumable: userSettings.getFilter(basekey + '-filter-IsResumable') === 'true', + Is4K: userSettings.getFilter(basekey + '-filter-Is4K') === 'true', + IsHD: userSettings.getFilter(basekey + '-filter-IsHD') === 'true', + IsSD: userSettings.getFilter(basekey + '-filter-IsSD') === 'true', + Is3D: userSettings.getFilter(basekey + '-filter-Is3D') === 'true', + VideoTypes: userSettings.getFilter(basekey + '-filter-VideoTypes'), + SeriesStatus: userSettings.getFilter(basekey + '-filter-SeriesStatus'), + HasSubtitles: userSettings.getFilter(basekey + '-filter-HasSubtitles'), + HasTrailer: userSettings.getFilter(basekey + '-filter-HasTrailer'), + HasSpecialFeature: userSettings.getFilter(basekey + '-filter-HasSpecialFeature'), + HasThemeSong: userSettings.getFilter(basekey + '-filter-HasThemeSong'), + HasThemeVideo: userSettings.getFilter(basekey + '-filter-HasThemeVideo'), + GenreIds: userSettings.getFilter(basekey + '-filter-GenreIds') + }; + } + + getSortValues() { + const basekey = this.getSettingsKey(); + return userSettings.getSortValuesLegacy(basekey, this.getDefaultSortBy()); + } + + getDefaultSortBy() { + const sortNameOption = this.getNameSortOption(this.params); + + if (this.params.type) { + return sortNameOption.value; + } + + return `${ItemSortBy.IsFolder},${sortNameOption.value}`; + } + + getSortMenuOptions() { + const sortBy = []; + + if (this.params.type === 'Programs') { + sortBy.push({ + name: globalize.translate('AirDate'), + value: [ItemSortBy.StartDate, ItemSortBy.SortName].join(',') + }); + } + + let option = this.getNameSortOption(this.params); + + if (option) { + sortBy.push(option); + } + + option = this.getCommunityRatingSortOption(); + + if (option) { + sortBy.push(option); + } + + option = this.getCriticRatingSortOption(); + + if (option) { + sortBy.push(option); + } + + if (this.params.type !== 'Programs') { + sortBy.push({ + name: globalize.translate('DateAdded'), + value: [ItemSortBy.DateCreated, ItemSortBy.SortName].join(',') + }); + } + + option = this.getDatePlayedSortOption(); + + if (option) { + sortBy.push(option); + } + + if (!this.params.type) { + option = this.getNameSortOption(this.params); + sortBy.push({ + name: globalize.translate('Folders'), + value: `${ItemSortBy.IsFolder},${option.value}` + }); + } + + sortBy.push({ + name: globalize.translate('ParentalRating'), + value: [ItemSortBy.OfficialRating, ItemSortBy.SortName].join(',') + }); + option = this.getPlayCountSortOption(); + + if (option) { + sortBy.push(option); + } + + sortBy.push({ + name: globalize.translate('ReleaseDate'), + value: [ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName].join(',') + }); + sortBy.push({ + name: globalize.translate('Runtime'), + value: [ItemSortBy.Runtime, ItemSortBy.SortName].join(',') + }); + return sortBy; + } + + getNameSortOption(params) { + if (params.type === 'Episode') { + return { + name: globalize.translate('Name'), + value: [ItemSortBy.SeriesSortName, ItemSortBy.SortName].join(',') + }; + } + + return { + name: globalize.translate('Name'), + value: ItemSortBy.SortName + }; + } + + getPlayCountSortOption() { + if (this.params.type === 'Programs') { + return null; + } + + return { + name: globalize.translate('PlayCount'), + value: [ItemSortBy.PlayCount, ItemSortBy.SortName].join(',') + }; + } + + getDatePlayedSortOption() { + if (this.params.type === 'Programs') { + return null; + } + + return { + name: globalize.translate('DatePlayed'), + value: [ItemSortBy.DatePlayed, ItemSortBy.SortName].join(',') + }; + } + + getCriticRatingSortOption() { + if (this.params.type === 'Programs') { + return null; + } + + return { + name: globalize.translate('CriticRating'), + value: [ItemSortBy.CriticRating, ItemSortBy.SortName].join(',') + }; + } + + getCommunityRatingSortOption() { + return { + name: globalize.translate('CommunityRating'), + value: [ItemSortBy.CommunityRating, ItemSortBy.SortName].join(',') + }; + } + + getVisibleFilters() { + const filters = []; + const params = this.params; + + if (params.type !== 'nextup') { + if (params.type === 'Programs') { + filters.push('Genres'); + } else { + filters.push('IsUnplayed'); + filters.push('IsPlayed'); + + if (!params.IsFavorite) { + filters.push('IsFavorite'); + } + + filters.push('IsResumable'); + filters.push('VideoType'); + filters.push('HasSubtitles'); + filters.push('HasTrailer'); + filters.push('HasSpecialFeature'); + filters.push('HasThemeSong'); + filters.push('HasThemeVideo'); + } + } + + return filters; + } + + setFilterStatus(hasFilters) { + this.hasFilters = hasFilters; + const filterButtons = this.filterButtons; + + if (filterButtons.length) { + for (const btnFilter of filterButtons) { + let bubble = btnFilter.querySelector('.filterButtonBubble'); + + if (!bubble) { + if (!hasFilters) { + continue; + } + + btnFilter.insertAdjacentHTML('afterbegin', '
!
'); + btnFilter.classList.add('btnFilterWithBubble'); + bubble = btnFilter.querySelector('.filterButtonBubble'); + } + + if (hasFilters) { + bubble.classList.remove('hide'); + } else { + bubble.classList.add('hide'); + } + } + } + } + + getFilterMenuOptions() { + const params = this.params; + return { + IsAiring: params.IsAiring, + IsMovie: params.IsMovie, + IsSports: params.IsSports, + IsKids: params.IsKids, + IsNews: params.IsNews, + IsSeries: params.IsSeries, + Recursive: this.queryRecursive + }; + } + + getVisibleViewSettings() { + const item = this.currentItem; + const fields = ['showTitle']; + + if (!item || item.Type !== 'PhotoAlbum' && item.Type !== 'ChannelFolderItem') { + fields.push('imageType'); + } + + fields.push('viewType'); + return fields; + } + + getViewSettings() { + const basekey = this.getSettingsKey(); + const params = this.params; + const item = this.currentItem; + let showTitle = userSettings.get(basekey + '-showTitle'); + + if (showTitle === 'true') { + showTitle = true; + } else if (showTitle === 'false') { + showTitle = false; + } else if (params.type === 'Programs' || params.type === 'Recordings' || params.type === 'Person' || params.type === 'nextup' || params.type === 'Audio' || params.type === 'MusicAlbum' || params.type === 'MusicArtist') { + showTitle = true; + } else if (item && item.Type !== 'PhotoAlbum') { + showTitle = true; + } + + let imageType = userSettings.get(basekey + '-imageType'); + + if (!imageType && params.type === 'nextup') { + if (userSettings.useEpisodeImagesInNextUpAndResume()) { + imageType = 'primary'; + } else { + imageType = 'thumb'; + } + } + + return { + showTitle: showTitle, + showYear: userSettings.get(basekey + '-showYear') !== 'false', + imageType: imageType || 'primary', + viewType: userSettings.get(basekey + '-viewType') || 'images' + }; + } + + getItemTypes() { + const params = this.params; + + if (params.type === 'nextup') { + return ['Episode']; + } + + if (params.type === 'Programs') { + return ['Program']; + } + + return []; + } + + getSettingsKey() { + const values = []; + values.push('items'); + const params = this.params; + + if (params.type) { + values.push(params.type); + } else if (params.parentId) { + values.push(params.parentId); + } + + if (params.IsAiring) { + values.push('IsAiring'); + } + + if (params.IsMovie) { + values.push('IsMovie'); + } + + if (params.IsKids) { + values.push('IsKids'); + } + + if (params.IsSports) { + values.push('IsSports'); + } + + if (params.IsNews) { + values.push('IsNews'); + } + + if (params.IsSeries) { + values.push('IsSeries'); + } + + if (params.IsFavorite) { + values.push('IsFavorite'); + } + + if (params.genreId) { + values.push('Genre'); + } + + if (params.musicGenreId) { + values.push('MusicGenre'); + } + + if (params.studioId) { + values.push('Studio'); + } + + if (params.personId) { + values.push('Person'); + } + + if (params.parentId) { + values.push('Folder'); + } + + return values.join('-'); + } +} + +export default BooksView; +