define(['viewManager', 'appSettings', 'appStorage', 'apphost', 'datetime', 'itemHelper', 'mediaInfo', 'scroller', 'indicators', 'dom', 'browser', 'imageLoader', 'scrollStyles'], function (viewManager, appSettings, appStorage, appHost, datetime, itemHelper, mediaInfo, scroller, indicators, dom, browser) { function fadeInRight(elem) { var pct = browser.mobile ? '4%' : '0.5%'; var keyframes = [ { opacity: '0', transform: 'translate3d(' + pct + ', 0, 0)', offset: 0 }, { opacity: '1', transform: 'none', offset: 1 }]; elem.animate(keyframes, { duration: 160, iterations: 1, easing: 'ease-out' }); } var libraryBrowser = (function (window, document, screen) { var pageSizeKey = 'pagesize_v4'; var libraryBrowser = { getDefaultPageSize: function (key, defaultValue) { return 100; }, getSavedQueryKey: function (modifier) { return window.location.href.split('#')[0] + (modifier || ''); }, loadSavedQueryValues: function (key, query) { var values = appStorage.getItem(key + '_' + Dashboard.getCurrentUserId()); if (values) { values = JSON.parse(values); return Object.assign(query, values); } return query; }, saveQueryValues: function (key, query) { var values = {}; if (query.SortBy) { values.SortBy = query.SortBy; } if (query.SortOrder) { values.SortOrder = query.SortOrder; } try { appStorage.setItem(key + '_' + Dashboard.getCurrentUserId(), JSON.stringify(values)); } catch (e) { } }, saveViewSetting: function (key, value) { try { appStorage.setItem(key + '_' + Dashboard.getCurrentUserId() + '_view', value); } catch (e) { } }, getSavedView: function (key) { var val = appStorage.getItem(key + '_' + Dashboard.getCurrentUserId() + '_view'); return val; }, getSavedViewSetting: function (key) { return new Promise(function (resolve, reject) { var val = LibraryBrowser.getSavedView(key); resolve(val); }); }, allowSwipe: function (target) { function allowSwipeOn(elem) { if (dom.parentWithTag(elem, 'input')) { return false; } if (elem.classList) { return !elem.classList.contains('hiddenScrollX') && !elem.classList.contains('smoothScrollX') && !elem.classList.contains('libraryViewNav'); } return true; } var parent = target; while (parent != null) { if (!allowSwipeOn(parent)) { return false; } parent = parent.parentNode; } return true; }, configureSwipeTabs: function (ownerpage, tabs) { if (!browser.touch) { return; } var pageCount = ownerpage.querySelectorAll('.pageTabContent').length; var onSwipeLeft = function (e) { if (LibraryBrowser.allowSwipe(e.target) && ownerpage.contains(e.target)) { var selected = parseInt(tabs.selectedIndex() || '0'); if (selected < (pageCount - 1)) { tabs.selectedIndex(selected + 1); } } }; var onSwipeRight = function (e) { if (LibraryBrowser.allowSwipe(e.target) && ownerpage.contains(e.target)) { var selected = parseInt(tabs.selectedIndex() || '0'); if (selected > 0) { tabs.selectedIndex(selected - 1); } } }; require(['hammer-main'], function (hammertime) { hammertime.on('swipeleft', onSwipeLeft); hammertime.on('swiperight', onSwipeRight); ownerpage.addEventListener('viewdestroy', function () { hammertime.off('swipeleft', onSwipeLeft); hammertime.off('swiperight', onSwipeRight); }); }); }, configurePaperLibraryTabs: function (ownerpage, tabs, panels, animateTabs) { if (!browser.safari) { LibraryBrowser.configureSwipeTabs(ownerpage, tabs); } ownerpage.addEventListener('viewbeforeshow', function () { if (tabs.triggerBeforeTabChange && this.firstTabIndex == null) { tabs.triggerBeforeTabChange(); } }); ownerpage.addEventListener('viewshow', function () { if (this.firstTabIndex) { tabs.selectedIndex(this.firstTabIndex); this.firstTabIndex = null; } else { tabs.triggerTabChange(); } }); tabs.addEventListener('beforetabchange', function (e) { if (e.detail.previousIndex != null) { panels[e.detail.previousIndex].classList.remove('is-active'); } var newPanel = panels[e.detail.selectedTabIndex]; if (e.detail.previousIndex != null && e.detail.previousIndex != e.detail.selectedTabIndex) { if (newPanel.animate && (animateTabs || []).indexOf(e.detail.selectedTabIndex) != -1) { fadeInRight(newPanel); } } newPanel.classList.add('is-active'); }); }, showTab: function (url, index) { var afterNavigate = function () { document.removeEventListener('pageinit', afterNavigate); if (window.location.href.toLowerCase().indexOf(url.toLowerCase()) != -1) { this.firstTabIndex = index; } }; if (window.location.href.toLowerCase().indexOf(url.toLowerCase()) != -1) { afterNavigate.call(viewManager.currentView()); } else { pageClassOn('pageinit', 'page', afterNavigate); Dashboard.navigate(url); } }, getArtistLinksHtml: function (artists, cssClass) { var html = []; for (var i = 0, length = artists.length; i < length; i++) { var artist = artists[i]; var css = cssClass ? (' class="' + cssClass + '"') : ''; html.push('' + artist.Name + ''); } html = html.join(' / '); return html; }, playInExternalPlayer: function (id) { Dashboard.loadExternalPlayer().then(function () { ExternalPlayer.showMenu(id); }); }, getHref: function (item, context, topParentId) { var href = LibraryBrowser.getHrefInternal(item, context); if (context == 'tv') { if (!topParentId) { topParentId = LibraryMenu.getTopParentId(); } if (topParentId) { href += href.indexOf('?') == -1 ? "?topParentId=" : "&topParentId="; href += topParentId; } } return href; }, getHrefInternal: function (item, context) { if (!item) { throw new Error('item cannot be null'); } if (item.url) { return item.url; } // Handle search hints var id = item.Id || item.ItemId; if (item.CollectionType == 'livetv') { return 'livetv.html'; } if (item.CollectionType == 'channels') { return 'channels.html'; } if (context != 'folders') { if (item.CollectionType == 'movies') { return 'movies.html?topParentId=' + item.Id; } if (item.CollectionType == 'boxsets') { return 'itemlist.html?topParentId=' + item.Id + '&parentId=' + item.Id; } if (item.CollectionType == 'tvshows') { return 'tv.html?topParentId=' + item.Id; } if (item.CollectionType == 'music') { return 'music.html?topParentId=' + item.Id; } if (item.CollectionType == 'games') { return id ? "itemlist.html?parentId=" + id : "#"; //return 'gamesrecommended.html?topParentId=' + item.Id; } if (item.CollectionType == 'playlists') { return 'playlists.html?topParentId=' + item.Id; } if (item.CollectionType == 'photos') { return 'photos.html?topParentId=' + item.Id; } } else if (item.IsFolder) { return id ? "itemlist.html?parentId=" + id : "#"; } if (item.Type == 'CollectionFolder') { return 'itemlist.html?topParentId=' + item.Id + '&parentId=' + item.Id; } if (item.Type == "PhotoAlbum") { return "itemlist.html?context=photos&parentId=" + id; } if (item.Type == "Playlist") { return "itemdetails.html?id=" + id; } if (item.Type == "TvChannel") { return "itemdetails.html?id=" + id; } if (item.Type == "Channel") { return "channelitems.html?id=" + id; } if ((item.IsFolder && item.SourceType == 'Channel') || item.Type == 'ChannelFolderItem') { return "channelitems.html?id=" + item.ChannelId + '&folderId=' + item.Id; } if (item.Type == "Program") { return "itemdetails.html?id=" + id; } if (item.Type == "BoxSet") { return "itemdetails.html?id=" + id; } if (item.Type == "MusicAlbum") { return "itemdetails.html?id=" + id; } if (item.Type == "GameSystem") { return "itemdetails.html?id=" + id; } if (item.Type == "Genre") { return "itemdetails.html?id=" + id; } if (item.Type == "MusicGenre") { return "itemdetails.html?id=" + id; } if (item.Type == "GameGenre") { return "itemdetails.html?id=" + id; } if (item.Type == "Studio") { return "itemdetails.html?id=" + id; } if (item.Type == "Person") { return "itemdetails.html?id=" + id; } if (item.Type == "Recording") { return "itemdetails.html?id=" + id; } if (item.Type == "MusicArtist") { return "itemdetails.html?id=" + id; } var contextSuffix = context ? ('&context=' + context) : ''; if (item.Type == "Series" || item.Type == "Season" || item.Type == "Episode") { return "itemdetails.html?id=" + id + contextSuffix; } if (item.IsFolder) { return id ? "itemlist.html?parentId=" + id : "#"; } return "itemdetails.html?id=" + id; }, getListItemInfo: function (elem) { var elemWithAttributes = elem; while (!elemWithAttributes.getAttribute('data-id')) { elemWithAttributes = elemWithAttributes.parentNode; } var itemId = elemWithAttributes.getAttribute('data-id'); var index = elemWithAttributes.getAttribute('data-index'); var mediaType = elemWithAttributes.getAttribute('data-mediatype'); return { id: itemId, index: index, mediaType: mediaType, context: elemWithAttributes.getAttribute('data-context') }; }, getFutureDateText: function (date) { var weekday = []; weekday[0] = Globalize.translate('OptionSunday'); weekday[1] = Globalize.translate('OptionMonday'); weekday[2] = Globalize.translate('OptionTuesday'); weekday[3] = Globalize.translate('OptionWednesday'); weekday[4] = Globalize.translate('OptionThursday'); weekday[5] = Globalize.translate('OptionFriday'); weekday[6] = Globalize.translate('OptionSaturday'); var day = weekday[date.getDay()]; date = date.toLocaleDateString(); if (date.toLowerCase().indexOf(day.toLowerCase()) == -1) { return day + " " + date; } return date; }, renderName: function (item, nameElem, linkToElement, context) { var name = itemHelper.getDisplayName(item, { includeParentInfo: false }); Dashboard.setPageTitle(name); if (linkToElement) { nameElem.innerHTML = '' + name + ''; } else { nameElem.innerHTML = name; } }, renderParentName: function (item, parentNameElem, context) { var html = []; var contextParam = context ? ('&context=' + context) : ''; if (item.AlbumArtists) { html.push(LibraryBrowser.getArtistLinksHtml(item.AlbumArtists, "detailPageParentLink")); } else if (item.ArtistItems && item.ArtistItems.length && item.Type == "MusicVideo") { html.push(LibraryBrowser.getArtistLinksHtml(item.ArtistItems, "detailPageParentLink")); } else if (item.SeriesName && item.Type == "Episode") { html.push('' + item.SeriesName + ''); } if (item.SeriesName && item.Type == "Season") { html.push('' + item.SeriesName + ''); } else if (item.ParentIndexNumber != null && item.Type == "Episode") { html.push('' + item.SeasonName + ''); } else if (item.Album && item.Type == "Audio" && (item.AlbumId || item.ParentId)) { html.push('' + item.Album + ''); } else if (item.Album && item.Type == "MusicVideo" && item.AlbumId) { html.push('' + item.Album + ''); } else if (item.Album) { html.push(item.Album); } else if (item.Type == 'Program' && item.EpisodeTitle) { html.push(item.Name); } if (html.length) { parentNameElem.classList.remove('hide'); parentNameElem.innerHTML = html.join(' - '); } else { parentNameElem.classList.add('hide'); } }, showLayoutMenu: function (button, currentLayout, views) { var dispatchEvent = true; if (!views) { dispatchEvent = false; // Add banner and list once all screens support them views = button.getAttribute('data-layouts'); views = views ? views.split(',') : ['List', 'Poster', 'PosterCard', 'Thumb', 'ThumbCard']; } var menuItems = views.map(function (v) { return { name: Globalize.translate('Option' + v), id: v, selected: currentLayout == v }; }); require(['actionsheet'], function (actionsheet) { actionsheet.show({ items: menuItems, positionTo: button, callback: function (id) { button.dispatchEvent(new CustomEvent('layoutchange', { detail: { viewStyle: id }, bubbles: true, cancelable: false })); if (!dispatchEvent) { if (window.$) { $(button).trigger('layoutchange', [id]); } } } }); }); }, getQueryPagingHtml: function (options) { var startIndex = options.startIndex; var limit = options.limit; var totalRecordCount = options.totalRecordCount; if (limit && options.updatePageSizeSetting !== false) { try { appStorage.setItem(options.pageSizeKey || pageSizeKey, limit); } catch (e) { } } var html = ''; var recordsEnd = Math.min(startIndex + limit, totalRecordCount); // 20 is the minimum page size var showControls = totalRecordCount > 20 || limit < totalRecordCount; html += '