diff --git a/dashboard-ui/bower_components/emby-apiclient/sync/contentuploader.js b/dashboard-ui/bower_components/emby-apiclient/sync/contentuploader.js index 9fa5d2ca74..5a1fbe294e 100644 --- a/dashboard-ui/bower_components/emby-apiclient/sync/contentuploader.js +++ b/dashboard-ui/bower_components/emby-apiclient/sync/contentuploader.js @@ -6,7 +6,7 @@ self.uploadImages = function (server) { - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); LocalAssetManager.getCameraPhotos().then(function (photos) { @@ -77,7 +77,7 @@ function uploadFile(file, apiClient) { - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); require(['fileupload', "cryptojs-sha1"], function () { diff --git a/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js b/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js index 5ee7a511fd..78d0c3e818 100644 --- a/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js +++ b/dashboard-ui/bower_components/emby-apiclient/sync/mediasync.js @@ -6,7 +6,7 @@ self.sync = function (apiClient, serverInfo, options) { - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); reportOfflineActions(apiClient, serverInfo).then(function () { @@ -36,7 +36,7 @@ console.log('Begin reportOfflineActions'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); require(['localassetmanager'], function () { @@ -67,7 +67,7 @@ console.log('Begin syncData'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); require(['localassetmanager'], function () { @@ -117,7 +117,7 @@ console.log('Begin removeLocalItems'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); removeNextLocalItem(syncDataResult.ItemIdsToRemove, 0, serverId, deferred); @@ -146,7 +146,7 @@ console.log('Begin removeLocalItem'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); require(['localassetmanager'], function () { @@ -164,7 +164,7 @@ console.log('Begin getNewMedia'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); apiClient.getReadySyncItems(apiClient.deviceId()).then(function (jobItems) { @@ -201,7 +201,7 @@ console.log('Begin getNewItem'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); require(['localassetmanager'], function () { @@ -240,7 +240,7 @@ function downloadMedia(apiClient, jobItem, localItem, options) { console.log('Begin downloadMedia'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); require(['localassetmanager'], function () { @@ -276,7 +276,7 @@ function getImages(apiClient, jobItem, localItem) { console.log('Begin getImages'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); getNextImage(0, apiClient, localItem, deferred); @@ -348,7 +348,7 @@ function downloadImage(apiClient, serverId, itemId, imageTag, imageType) { console.log('Begin downloadImage'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); require(['localassetmanager'], function () { @@ -380,7 +380,7 @@ function getSubtitles(apiClient, jobItem, localItem) { console.log('Begin getSubtitles'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); require(['localassetmanager'], function () { @@ -424,7 +424,7 @@ function getItemSubtitle(file, apiClient, jobItem, localItem, mediaSource) { console.log('Begin getItemSubtitle'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); var subtitleStream = mediaSource.MediaStreams.filter(function (m) { return m.Type == 'Subtitle' && m.Index == file.Index; @@ -461,7 +461,7 @@ function syncUserItemAccess(syncDataResult, serverId) { console.log('Begin syncUserItemAccess'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); var itemIds = []; for (var id in syncDataResult.ItemUserAccess) { @@ -494,7 +494,7 @@ function syncUserAccessForItem(itemId, syncDataResult) { console.log('Begin syncUserAccessForItem'); - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); require(['localassetmanager'], function () { diff --git a/dashboard-ui/components/directorybrowser/directorybrowser.js b/dashboard-ui/components/directorybrowser/directorybrowser.js index d2283bc5f7..21cf94b7a4 100644 --- a/dashboard-ui/components/directorybrowser/directorybrowser.js +++ b/dashboard-ui/components/directorybrowser/directorybrowser.js @@ -3,7 +3,7 @@ var systemInfo; function getSystemInfo() { - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); if (systemInfo) { deferred.resolveWith(null, [systemInfo]); diff --git a/dashboard-ui/components/imagedownloader/imagedownloader.js b/dashboard-ui/components/imagedownloader/imagedownloader.js index 27baed54be..5b115347cc 100644 --- a/dashboard-ui/components/imagedownloader/imagedownloader.js +++ b/dashboard-ui/components/imagedownloader/imagedownloader.js @@ -324,7 +324,7 @@ return { show: function (itemId, itemType, imageType) { - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); currentDeferred = deferred; hasChanges = false; diff --git a/dashboard-ui/components/imageeditor/imageeditor.js b/dashboard-ui/components/imageeditor/imageeditor.js index 89752aee65..d3945a4521 100644 --- a/dashboard-ui/components/imageeditor/imageeditor.js +++ b/dashboard-ui/components/imageeditor/imageeditor.js @@ -297,7 +297,7 @@ return { show: function (itemId, options) { - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); currentDeferred = deferred; hasChanges = false; diff --git a/dashboard-ui/components/imageuploader/imageuploader.js b/dashboard-ui/components/imageuploader/imageuploader.js index 1dbb5062c5..d4489c50d7 100644 --- a/dashboard-ui/components/imageuploader/imageuploader.js +++ b/dashboard-ui/components/imageuploader/imageuploader.js @@ -185,7 +185,7 @@ return { show: function (itemId, options) { - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); currentDeferred = deferred; hasChanges = false; diff --git a/dashboard-ui/components/itemidentifier/itemidentifier.js b/dashboard-ui/components/itemidentifier/itemidentifier.js index cc5c00cf1f..bdfa4ae810 100644 --- a/dashboard-ui/components/itemidentifier/itemidentifier.js +++ b/dashboard-ui/components/itemidentifier/itemidentifier.js @@ -336,7 +336,7 @@ return { show: function (itemId) { - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); currentDeferred = deferred; hasChanges = false; diff --git a/dashboard-ui/components/medialibrarycreator/medialibrarycreator.js b/dashboard-ui/components/medialibrarycreator/medialibrarycreator.js index 1dcc85d7cd..b9e3005656 100644 --- a/dashboard-ui/components/medialibrarycreator/medialibrarycreator.js +++ b/dashboard-ui/components/medialibrarycreator/medialibrarycreator.js @@ -180,7 +180,7 @@ self.show = function (options) { - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); currentOptions = options; currentDeferred = deferred; diff --git a/dashboard-ui/components/medialibraryeditor/medialibraryeditor.js b/dashboard-ui/components/medialibraryeditor/medialibraryeditor.js index 9357e97ae5..a6700126e0 100644 --- a/dashboard-ui/components/medialibraryeditor/medialibraryeditor.js +++ b/dashboard-ui/components/medialibraryeditor/medialibraryeditor.js @@ -134,7 +134,7 @@ self.show = function (options) { - var deferred = DeferredBuilder.Deferred(); + var deferred = jQuery.Deferred(); currentOptions = options; currentDeferred = deferred; diff --git a/dashboard-ui/css/card.css b/dashboard-ui/css/card.css index 91dd2650db..c0f9a23d6b 100644 --- a/dashboard-ui/css/card.css +++ b/dashboard-ui/css/card.css @@ -55,7 +55,7 @@ } .defaultBackground .cardImage { - background-color: #333; + background-color: #303030; } .homeTopViews .defaultBackground .cardImage { @@ -109,7 +109,7 @@ } .ui-body-b .visualCardBox { - background: rgba(40,40,40,.85); + background: rgba(56,56,56,.85); border-radius: 3px; } diff --git a/dashboard-ui/css/librarymenu.css b/dashboard-ui/css/librarymenu.css index 031beca8e8..49eaba4118 100644 --- a/dashboard-ui/css/librarymenu.css +++ b/dashboard-ui/css/librarymenu.css @@ -200,11 +200,11 @@ } .viewMenuBar, .libraryViewNav { - background-color: #101010; + background-color: #080808; } .viewMenuBar.semiTransparent { - background-color: rgba(18, 18, 18, .55); + background-color: rgba(15, 15, 15, .3); } .paperLibraryViewNav { diff --git a/dashboard-ui/devices/android/android.css b/dashboard-ui/devices/android/android.css index 0c79a2940d..f36baba19e 100644 --- a/dashboard-ui/devices/android/android.css +++ b/dashboard-ui/devices/android/android.css @@ -1,31 +1,7 @@ -.viewMenuBar, .libraryViewNav:not(.paperLibraryViewNav), paper-tabs { - background-color: #080808; -} - - .viewMenuBar.semiTransparent { - background-color: rgba(15, 15, 15, .3); - } - -.background-theme-b, paper-dialog.background-theme-b { - background-color: #1A1A1A; -} - -.defaultBackground .cardImage { - background-color: #303030; -} - -.ui-body-b .visualCardBox { - background: rgba(56,56,56,.85); -} - -.libraryViewNav { +.libraryViewNav { box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.2); } - .libraryViewNav a { + .libraryViewNav a, paper-tab { font-weight: 500 !important; - } - -paper-tab { - font-weight: 500 !important; -} + } \ No newline at end of file diff --git a/dashboard-ui/devices/windowsphone/wp.css b/dashboard-ui/devices/windowsphone/wp.css new file mode 100644 index 0000000000..f3842e9d89 --- /dev/null +++ b/dashboard-ui/devices/windowsphone/wp.css @@ -0,0 +1,22 @@ +html, body, .ui-btn, .pageTitle { + font-family: 'Segoe UI', Arial, sans-serif; +} + +.viewMenuBar { + background-color: #000; +} + +.libraryViewNav, .libraryViewNav paper-tabs { + background-color: transparent; + box-shadow: none; + text-transform: lowercase; + font-size: 240%; +} + + .libraryViewNav a, paper-tab { + font-weight: 400 !important; + } + +.background-theme-b, paper-dialog.background-theme-b { + background: #161616; +} diff --git a/dashboard-ui/legacy/deferred.js b/dashboard-ui/legacy/deferred.js deleted file mode 100644 index e5632d538e..0000000000 --- a/dashboard-ui/legacy/deferred.js +++ /dev/null @@ -1,16 +0,0 @@ -(function (globalScope) { - - globalScope.DeferredBuilder = { - - Deferred: function () { - return jQuery.Deferred(); - }, - - when: function (promises) { - - return jQuery.when(promises); - } - - }; - -})(window); \ No newline at end of file diff --git a/dashboard-ui/scripts/librarybrowser.js b/dashboard-ui/scripts/librarybrowser.js index 750ddcba43..32e79ef411 100644 --- a/dashboard-ui/scripts/librarybrowser.js +++ b/dashboard-ui/scripts/librarybrowser.js @@ -1,3704 +1,3714 @@ -var LibraryBrowser = (function (window, document, screen) { +define(['playlistManager'], function (playlistManager) { - // Regular Expressions for parsing tags and attributes - var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, - // Match everything outside of normal chars and " (quote character) - NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; + var libraryBrowser = (function (window, document, screen) { - /** - * Escapes all potentially dangerous characters, so that the - * resulting string can be safely inserted into attribute or - * element text. - * @param value - * @returns {string} escaped text - */ - function htmlEncode(value) { - return value. - replace(/&/g, '&'). - replace(SURROGATE_PAIR_REGEXP, function (value) { - var hi = value.charCodeAt(0); - var low = value.charCodeAt(1); - return '' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';'; - }). - replace(NON_ALPHANUMERIC_REGEXP, function (value) { - return '' + value.charCodeAt(0) + ';'; - }). - replace(//g, '>'); - } + // Regular Expressions for parsing tags and attributes + var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + // Match everything outside of normal chars and " (quote character) + NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; - var pageSizeKey = 'pagesize_v4'; - - function getDesiredAspect(shape) { - - if (shape) { - shape = shape.toLowerCase(); - if (shape.indexOf('portrait') != -1) { - return (2 / 3); - } - if (shape.indexOf('backdrop') != -1) { - return (16 / 9); - } - if (shape.indexOf('square') != -1) { - return 1; - } + /** + * Escapes all potentially dangerous characters, so that the + * resulting string can be safely inserted into attribute or + * element text. + * @param value + * @returns {string} escaped text + */ + function htmlEncode(value) { + return value. + replace(/&/g, '&'). + replace(SURROGATE_PAIR_REGEXP, function (value) { + var hi = value.charCodeAt(0); + var low = value.charCodeAt(1); + return '' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';'; + }). + replace(NON_ALPHANUMERIC_REGEXP, function (value) { + return '' + value.charCodeAt(0) + ';'; + }). + replace(//g, '>'); } - return null; - } - var libraryBrowser = { - getDefaultPageSize: function (key, defaultValue) { + var pageSizeKey = 'pagesize_v4'; - return 100; - var saved = appStorage.getItem(key || pageSizeKey); + function getDesiredAspect(shape) { - if (saved) { - return parseInt(saved); + if (shape) { + shape = shape.toLowerCase(); + if (shape.indexOf('portrait') != -1) { + return (2 / 3); + } + if (shape.indexOf('backdrop') != -1) { + return (16 / 9); + } + if (shape.indexOf('square') != -1) { + return 1; + } } + return null; + } - if (defaultValue) { - return defaultValue; - } + var libraryBrowser = { + getDefaultPageSize: function (key, defaultValue) { - return 100; - }, + return 100; + var saved = appStorage.getItem(key || pageSizeKey); - getDefaultItemsView: function (view, mobileView) { + if (saved) { + return parseInt(saved); + } - return browserInfo.mobile ? mobileView : view; + if (defaultValue) { + return defaultValue; + } - }, + return 100; + }, - getSavedQueryKey: function (modifier) { + getDefaultItemsView: function (view, mobileView) { - return window.location.href.split('#')[0] + (modifier || ''); - }, + return browserInfo.mobile ? mobileView : view; - loadSavedQueryValues: function (key, query) { + }, - var values = appStorage.getItem(key + '_' + Dashboard.getCurrentUserId()); + getSavedQueryKey: function (modifier) { - if (values) { + return window.location.href.split('#')[0] + (modifier || ''); + }, - values = JSON.parse(values); + loadSavedQueryValues: function (key, query) { - return $.extend(query, values); - } + var values = appStorage.getItem(key + '_' + Dashboard.getCurrentUserId()); - return query; - }, + if (values) { - saveQueryValues: function (key, query) { + values = JSON.parse(values); - var values = {}; + return $.extend(query, values); + } - if (query.SortBy) { - values.SortBy = query.SortBy; - } - if (query.SortOrder) { - values.SortOrder = query.SortOrder; - } + return query; + }, - try { - appStorage.setItem(key + '_' + Dashboard.getCurrentUserId(), JSON.stringify(values)); - } catch (e) { + saveQueryValues: function (key, query) { - } - }, + var values = {}; - saveViewSetting: function (key, value) { + if (query.SortBy) { + values.SortBy = query.SortBy; + } + if (query.SortOrder) { + values.SortOrder = query.SortOrder; + } - try { - appStorage.setItem(key + '_' + Dashboard.getCurrentUserId() + '_view', value); - } catch (e) { + try { + appStorage.setItem(key + '_' + Dashboard.getCurrentUserId(), JSON.stringify(values)); + } catch (e) { - } - }, + } + }, - getSavedView: function (key) { + saveViewSetting: function (key, value) { - var val = appStorage.getItem(key + '_' + Dashboard.getCurrentUserId() + '_view'); + try { + appStorage.setItem(key + '_' + Dashboard.getCurrentUserId() + '_view', value); + } catch (e) { - return val; - }, + } + }, - getSavedViewSetting: function (key) { + getSavedView: function (key) { - return new Promise(function (resolve, reject) { + var val = appStorage.getItem(key + '_' + Dashboard.getCurrentUserId() + '_view'); - var val = LibraryBrowser.getSavedView(key); - resolve(val); - }); - }, + return val; + }, - needsRefresh: function (elem) { + getSavedViewSetting: function (key) { - var last = parseInt(elem.getAttribute('data-lastrefresh') || '0'); + return new Promise(function (resolve, reject) { - if (!last) { - return true; - } + var val = LibraryBrowser.getSavedView(key); + resolve(val); + }); + }, - if (NavHelper.isBack()) { - console.log('Not refreshing data because IsBack=true'); - return false; - } + needsRefresh: function (elem) { - var now = new Date().getTime(); - var cacheDuration; + var last = parseInt(elem.getAttribute('data-lastrefresh') || '0'); - if (AppInfo.isNativeApp) { - cacheDuration = 300000; - } else if (browserInfo.ipad || browserInfo.iphone || browserInfo.android) { - cacheDuration = 10000; - } else { - cacheDuration = 30000; - } + if (!last) { + return true; + } - if ((now - last) < cacheDuration) { - console.log('Not refreshing data due to age'); - return false; - } - - return true; - }, - - setLastRefreshed: function (elem) { - - elem.setAttribute('data-lastrefresh', new Date().getTime()); - elem.classList.add('hasrefreshtime'); - }, - - enableFullPaperTabs: function () { - - if (browserInfo.animate && !browserInfo.mobile) { - //return true; - } - - return AppInfo.isNativeApp; - }, - - animatePaperTabs: function () { - - if (!LibraryBrowser.enableFullPaperTabs()) { - return false; - } - - if (!browserInfo.animate) { - return false; - } - - if (browserInfo.mobile) { - return false; - } - - return true; - }, - - allowSwipe: function (target) { - - function allowSwipeOn(elem) { - - if (elem.tagName == 'PAPER-SLIDER') { + if (NavHelper.isBack()) { + console.log('Not refreshing data because IsBack=true'); return false; } - if (elem.classList) { - return !elem.classList.contains('hiddenScrollX') && !elem.classList.contains('smoothScrollX'); + var now = new Date().getTime(); + var cacheDuration; + + if (AppInfo.isNativeApp) { + cacheDuration = 300000; + } else if (browserInfo.ipad || browserInfo.iphone || browserInfo.android) { + cacheDuration = 10000; + } else { + cacheDuration = 30000; + } + + if ((now - last) < cacheDuration) { + console.log('Not refreshing data due to age'); + return false; } return true; - } + }, - var parent = target; - while (parent != null) { - if (!allowSwipeOn(parent)) { + setLastRefreshed: function (elem) { + + elem.setAttribute('data-lastrefresh', new Date().getTime()); + elem.classList.add('hasrefreshtime'); + }, + + enableFullPaperTabs: function () { + + if (browserInfo.animate && !browserInfo.mobile) { + //return true; + } + + return AppInfo.isNativeApp; + }, + + animatePaperTabs: function () { + + if (!LibraryBrowser.enableFullPaperTabs()) { return false; } - parent = parent.parentNode; - } - return true; - }, - - getTabsAnimationConfig: function (elem, reverse) { - - if (browserInfo.mobile) { - - } - - return { - // scale up - 'entry': { - name: 'fade-in-animation', - node: elem, - timing: { duration: 160, easing: 'ease-out' } - }, - // fade out - 'exit': { - name: 'fade-out-animation', - node: elem, - timing: { duration: 200, easing: 'ease-out' } + if (!browserInfo.animate) { + return false; } - }; - }, + if (browserInfo.mobile) { + return false; + } - configureSwipeTabs: function (ownerpage, tabs, pages) { + return true; + }, + + allowSwipe: function (target) { + + function allowSwipeOn(elem) { + + if (elem.tagName == 'PAPER-SLIDER') { + return false; + } + + if (elem.classList) { + return !elem.classList.contains('hiddenScrollX') && !elem.classList.contains('smoothScrollX'); + } + + return true; + } + + var parent = target; + while (parent != null) { + if (!allowSwipeOn(parent)) { + return false; + } + parent = parent.parentNode; + } + + return true; + }, + + getTabsAnimationConfig: function (elem, reverse) { - if (LibraryBrowser.animatePaperTabs()) { if (browserInfo.mobile) { - require(['slide-left-animation', 'slide-from-right-animation'], function () { - pages.entryAnimation = 'slide-from-right-animation'; - pages.exitAnimation = 'slide-left-animation'; - }); - } else { - - require(['fade-in-animation', 'fade-out-animation'], function () { - pages.entryAnimation = 'fade-in-animation'; - pages.exitAnimation = 'fade-out-animation'; - }); - } - } - - var pageCount = pages.querySelectorAll('neon-animatable').length; - - require(['hammer'], function (Hammer) { - - var hammertime = new Hammer(pages); - hammertime.get('swipe').set({ direction: Hammer.DIRECTION_HORIZONTAL }); - - hammertime.on('swipeleft', function (e) { - if (LibraryBrowser.allowSwipe(e.target)) { - var selected = parseInt(pages.selected || '0'); - if (selected < (pageCount - 1)) { - if (LibraryBrowser.animatePaperTabs()) { - pages.entryAnimation = 'slide-from-right-animation'; - pages.exitAnimation = 'slide-left-animation'; - } - tabs.selectNext(); - } - } - }); - - hammertime.on('swiperight', function (e) { - if (LibraryBrowser.allowSwipe(e.target)) { - var selected = parseInt(pages.selected || '0'); - if (selected > 0) { - if (LibraryBrowser.animatePaperTabs()) { - pages.entryAnimation = 'slide-from-left-animation'; - pages.exitAnimation = 'slide-right-animation'; - } - tabs.selectPrevious(); - } - } - }); - }); - }, - - navigateOnLibraryTabSelect: function () { - return !LibraryBrowser.enableFullPaperTabs(); - }, - - configurePaperLibraryTabs: function (ownerpage, tabs, pages) { - - // Causing iron-select to not fire in IE and safari - if (browserInfo.chrome) { - tabs.noink = true; - } - - if (LibraryBrowser.enableFullPaperTabs()) { - - if (browserInfo.safari) { - tabs.noSlide = true; - tabs.noBar = true; - } else { - LibraryBrowser.configureSwipeTabs(ownerpage, tabs, pages); } - $('.libraryViewNav', ownerpage).addClass('paperLibraryViewNav').removeClass('libraryViewNavWithMinHeight'); - - } else { - - tabs.noSlide = true; - tabs.noBar = true; - - var legacyTabs = $('.legacyTabs', ownerpage); - - pages.addEventListener('iron-select', function (e) { - - var selected = pages.selected; - $('a', legacyTabs).removeClass('ui-btn-active')[selected].classList.add('ui-btn-active'); - }); - - $('.libraryViewNav', ownerpage).removeClass('libraryViewNavWithMinHeight'); - } - - $(ownerpage).on('pagebeforeshow', LibraryBrowser.onTabbedpagebeforeshow); - - pages.addEventListener('iron-select', function () { - // When transition animations are used, add a content loading delay to allow the animations to finish - // Otherwise with both operations happening at the same time, it can cause the animation to not run at full speed. - var pgs = this; - var delay = LibraryBrowser.animatePaperTabs() || !tabs.noSlide ? 300 : 0; - - setTimeout(function () { - pgs.dispatchEvent(new CustomEvent("tabchange", {})); - }, delay); - }); - - function fadeOutLeft(elem, iterations) { - var keyframes = [{ opacity: '1', transform: 'none', offset: 0 }, - { opacity: '0', transform: 'translate3d(-100%, 0, 0)', offset: 1 }]; - var timing = { duration: 300, iterations: iterations }; - return elem.animate(keyframes, timing); - } - if (!LibraryBrowser.navigateOnLibraryTabSelect()) { - tabs.addEventListener('iron-select', function () { - - var animateTab = !browserInfo.safari; - animateTab = false; - - var selected = pages.selected; - if (selected != null && animateTab) { - var newValue = this.selected; - var currentTab = pages.querySelectorAll('.pageTabContent')[selected]; - - fadeOutLeft(currentTab, 1).onfinish = function () { - pages.selected = newValue; - }; + return { + // scale up + 'entry': { + name: 'fade-in-animation', + node: elem, + timing: { duration: 160, easing: 'ease-out' } + }, + // fade out + 'exit': { + name: 'fade-out-animation', + node: elem, + timing: { duration: 200, easing: 'ease-out' } } - else { - pages.selected = this.selected; + }; + + }, + + configureSwipeTabs: function (ownerpage, tabs, pages) { + + if (LibraryBrowser.animatePaperTabs()) { + if (browserInfo.mobile) { + + require(['slide-left-animation', 'slide-from-right-animation'], function () { + pages.entryAnimation = 'slide-from-right-animation'; + pages.exitAnimation = 'slide-left-animation'; + }); + } else { + + require(['fade-in-animation', 'fade-out-animation'], function () { + pages.entryAnimation = 'fade-in-animation'; + pages.exitAnimation = 'fade-out-animation'; + }); } + } + + var pageCount = pages.querySelectorAll('neon-animatable').length; + + require(['hammer'], function (Hammer) { + + var hammertime = new Hammer(pages); + hammertime.get('swipe').set({ direction: Hammer.DIRECTION_HORIZONTAL }); + + hammertime.on('swipeleft', function (e) { + if (LibraryBrowser.allowSwipe(e.target)) { + var selected = parseInt(pages.selected || '0'); + if (selected < (pageCount - 1)) { + if (LibraryBrowser.animatePaperTabs()) { + pages.entryAnimation = 'slide-from-right-animation'; + pages.exitAnimation = 'slide-left-animation'; + } + tabs.selectNext(); + } + } + }); + + hammertime.on('swiperight', function (e) { + if (LibraryBrowser.allowSwipe(e.target)) { + var selected = parseInt(pages.selected || '0'); + if (selected > 0) { + if (LibraryBrowser.animatePaperTabs()) { + pages.entryAnimation = 'slide-from-left-animation'; + pages.exitAnimation = 'slide-right-animation'; + } + tabs.selectPrevious(); + } + } + }); }); - } - }, + }, - onTabbedpagebeforeshow: function () { + navigateOnLibraryTabSelect: function () { + return !LibraryBrowser.enableFullPaperTabs(); + }, - var page = this; - var delay = 0; - var isFirstLoad = false; + configurePaperLibraryTabs: function (ownerpage, tabs, pages) { - if (!page.getAttribute('data-firstload')) { - delay = 300; - isFirstLoad = true; - page.setAttribute('data-firstload', '1'); - } - - if (delay) { - setTimeout(function () { - - LibraryBrowser.onTabbedpagebeforeshowInternal(page, isFirstLoad); - }, delay); - } else { - LibraryBrowser.onTabbedpagebeforeshowInternal(page, isFirstLoad); - } - }, - - onTabbedpagebeforeshowInternal: function (page, isFirstLoad) { - - if (isFirstLoad) { - - console.log('selected tab is null, checking query string'); - - var selected = parseInt(getParameterByName('tab') || '0'); - - console.log('selected tab will be ' + selected); + // Causing iron-select to not fire in IE and safari + if (browserInfo.chrome) { + tabs.noink = true; + } if (LibraryBrowser.enableFullPaperTabs()) { - var tabs = page.querySelector('paper-tabs'); - if (tabs.selected) { - // showTab was called - return; + if (browserInfo.safari) { + tabs.noSlide = true; + tabs.noBar = true; + } else { + LibraryBrowser.configureSwipeTabs(ownerpage, tabs, pages); } - tabs.selected = selected; + + $('.libraryViewNav', ownerpage).addClass('paperLibraryViewNav').removeClass('libraryViewNavWithMinHeight'); } else { - page.querySelector('neon-animated-pages').selected = selected; + + tabs.noSlide = true; + tabs.noBar = true; + + var legacyTabs = $('.legacyTabs', ownerpage); + + pages.addEventListener('iron-select', function (e) { + + var selected = pages.selected; + $('a', legacyTabs).removeClass('ui-btn-active')[selected].classList.add('ui-btn-active'); + }); + + $('.libraryViewNav', ownerpage).removeClass('libraryViewNavWithMinHeight'); } - } else { + $(ownerpage).on('pagebeforeshow', LibraryBrowser.onTabbedpagebeforeshow); - var pages = page.querySelector('neon-animated-pages'); + pages.addEventListener('iron-select', function () { + // When transition animations are used, add a content loading delay to allow the animations to finish + // Otherwise with both operations happening at the same time, it can cause the animation to not run at full speed. + var pgs = this; + var delay = LibraryBrowser.animatePaperTabs() || !tabs.noSlide ? 300 : 0; - // Go back to the first tab - if (LibraryBrowser.enableFullPaperTabs() && !NavHelper.isBack()) { - if (pages.selected) { + setTimeout(function () { + pgs.dispatchEvent(new CustomEvent("tabchange", {})); + }, delay); + }); - var entryAnimation = pages.entryAnimation; - var exitAnimation = pages.exitAnimation; - pages.entryAnimation = null; - pages.exitAnimation = null; + function fadeOutLeft(elem, iterations) { + var keyframes = [{ opacity: '1', transform: 'none', offset: 0 }, + { opacity: '0', transform: 'translate3d(-100%, 0, 0)', offset: 1 }]; + var timing = { duration: 300, iterations: iterations }; + return elem.animate(keyframes, timing); + } + if (!LibraryBrowser.navigateOnLibraryTabSelect()) { + tabs.addEventListener('iron-select', function () { - page.querySelector('paper-tabs').selected = 0; + var animateTab = !browserInfo.safari; + animateTab = false; - pages.entryAnimation = entryAnimation; - pages.exitAnimation = exitAnimation; + var selected = pages.selected; + if (selected != null && animateTab) { + var newValue = this.selected; + var currentTab = pages.querySelectorAll('.pageTabContent')[selected]; - return; + fadeOutLeft(currentTab, 1).onfinish = function () { + pages.selected = newValue; + }; + } + else { + pages.selected = this.selected; + } + }); + } + }, + + onTabbedpagebeforeshow: function () { + + var page = this; + var delay = 0; + var isFirstLoad = false; + + if (!page.getAttribute('data-firstload')) { + delay = 300; + isFirstLoad = true; + page.setAttribute('data-firstload', '1'); + } + + if (delay) { + setTimeout(function () { + + LibraryBrowser.onTabbedpagebeforeshowInternal(page, isFirstLoad); + }, delay); + } else { + LibraryBrowser.onTabbedpagebeforeshowInternal(page, isFirstLoad); + } + }, + + onTabbedpagebeforeshowInternal: function (page, isFirstLoad) { + + if (isFirstLoad) { + + console.log('selected tab is null, checking query string'); + + var selected = parseInt(getParameterByName('tab') || '0'); + + console.log('selected tab will be ' + selected); + + if (LibraryBrowser.enableFullPaperTabs()) { + + var tabs = page.querySelector('paper-tabs'); + if (tabs.selected) { + // showTab was called + return; + } + tabs.selected = selected; + + } else { + page.querySelector('neon-animated-pages').selected = selected; } - } - pages.dispatchEvent(new CustomEvent("tabchange", {})); - } - }, - showTab: function (url, index) { + } else { - if (!LibraryBrowser.enableFullPaperTabs()) { + var pages = page.querySelector('neon-animated-pages'); - if (index) { - url = replaceQueryString(url, 'tab', index); - } - Dashboard.navigate(url); - return; - } + // Go back to the first tab + if (LibraryBrowser.enableFullPaperTabs() && !NavHelper.isBack()) { + if (pages.selected) { - var afterNavigate = function () { - if (window.location.href.toLowerCase().indexOf(url.toLowerCase()) != -1) { + var entryAnimation = pages.entryAnimation; + var exitAnimation = pages.exitAnimation; + pages.entryAnimation = null; + pages.exitAnimation = null; - var pages = this.querySelector('neon-animated-pages'); - - if (pages) { - - var entryAnimation = pages.entryAnimation; - var exitAnimation = pages.exitAnimation; - pages.entryAnimation = null; - pages.exitAnimation = null; - - var tabs = this.querySelector('paper-tabs'); - - // For some reason the live tv page will not switch tabs in IE and safari - var delay = browserInfo.chrome ? 0 : 100; - - setTimeout(function () { - var noSlide = tabs.noSlide; - tabs.noSlide = true; - tabs.selected = index; + page.querySelector('paper-tabs').selected = 0; pages.entryAnimation = entryAnimation; pages.exitAnimation = exitAnimation; - tabs.noSlide = noSlide; - }, delay); - } - } - }; - - if (window.location.href.toLowerCase().indexOf(url.toLowerCase()) != -1) { - - afterNavigate.call($($.mobile.activePage)[0]); - } else { - $(document).one('pagebeforeshow', '.page', afterNavigate); - Dashboard.navigate(url); - } - }, - - canShare: function (item, user) { - - return user.Policy.EnablePublicSharing; - }, - - getDateParamValue: function (date) { - - function formatDigit(i) { - return i < 10 ? "0" + i : i; - } - - var d = date; - - return "" + d.getFullYear() + formatDigit(d.getMonth() + 1) + formatDigit(d.getDate()) + formatDigit(d.getHours()) + formatDigit(d.getMinutes()) + formatDigit(d.getSeconds()); - }, - - playAllFromHere: function (fn, index) { - - fn(index, 100, "MediaSources,Chapters").then(function (result) { - - MediaController.play({ - items: result.Items - }); - }); - }, - - queueAllFromHere: function (query, index) { - - fn(index, 100, "MediaSources,Chapters").then(function (result) { - - MediaController.queue({ - items: result.Items - }); - }); - }, - - getItemCountsHtml: function (options, item) { - - var counts = []; - - var childText; - - if (item.Type == 'Playlist') { - - childText = ''; - - if (item.CumulativeRunTimeTicks) { - - var minutes = item.CumulativeRunTimeTicks / 600000000; - - minutes = minutes || 1; - - childText += Globalize.translate('ValueMinutes', Math.round(minutes)); - - } else { - childText += Globalize.translate('ValueMinutes', 0); - } - - counts.push(childText); - - } - else if (options.context == "movies") { - - if (item.MovieCount) { - - childText = item.MovieCount == 1 ? - Globalize.translate('ValueOneMovie') : - Globalize.translate('ValueMovieCount', item.MovieCount); - - counts.push(childText); - } - if (item.TrailerCount) { - - childText = item.TrailerCount == 1 ? - Globalize.translate('ValueOneTrailer') : - Globalize.translate('ValueTrailerCount', item.TrailerCount); - - counts.push(childText); - } - - } else if (options.context == "tv") { - - if (item.SeriesCount) { - - childText = item.SeriesCount == 1 ? - Globalize.translate('ValueOneSeries') : - Globalize.translate('ValueSeriesCount', item.SeriesCount); - - counts.push(childText); - } - if (item.EpisodeCount) { - - childText = item.EpisodeCount == 1 ? - Globalize.translate('ValueOneEpisode') : - Globalize.translate('ValueEpisodeCount', item.EpisodeCount); - - counts.push(childText); - } - - } else if (options.context == "games") { - - if (item.GameCount) { - - childText = item.GameCount == 1 ? - Globalize.translate('ValueOneGame') : - Globalize.translate('ValueGameCount', item.GameCount); - - counts.push(childText); - } - } else if (options.context == "music") { - - if (item.AlbumCount) { - - childText = item.AlbumCount == 1 ? - Globalize.translate('ValueOneAlbum') : - Globalize.translate('ValueAlbumCount', item.AlbumCount); - - counts.push(childText); - } - if (item.SongCount) { - - childText = item.SongCount == 1 ? - Globalize.translate('ValueOneSong') : - Globalize.translate('ValueSongCount', item.SongCount); - - counts.push(childText); - } - if (item.MusicVideoCount) { - - childText = item.MusicVideoCount == 1 ? - Globalize.translate('ValueOneMusicVideo') : - Globalize.translate('ValueMusicVideoCount', item.MusicVideoCount); - - counts.push(childText); - } - } - - return counts.join(' • '); - }, - - 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); - }); - }, - - showPlayMenu: function (positionTo, itemId, itemType, isFolder, mediaType, resumePositionTicks) { - - var externalPlayers = AppInfo.supportsExternalPlayers && AppSettings.enableExternalPlayers(); - - if (!resumePositionTicks && mediaType != "Audio" && !isFolder) { - - if (!externalPlayers || mediaType != "Video") { - - MediaController.play(itemId); - return; - } - } - - var menuItems = []; - - if (resumePositionTicks) { - menuItems.push({ - name: Globalize.translate('ButtonResume'), - id: 'resume', - ironIcon: 'play-arrow' - }); - } - - menuItems.push({ - name: Globalize.translate('ButtonPlay'), - id: 'play', - ironIcon: 'play-arrow' - }); - - if (!isFolder && externalPlayers && mediaType != "Audio") { - menuItems.push({ - name: Globalize.translate('ButtonPlayExternalPlayer'), - id: 'externalplayer', - ironIcon: 'airplay' - }); - } - - if (MediaController.canQueueMediaType(mediaType, itemType)) { - menuItems.push({ - name: Globalize.translate('ButtonQueue'), - id: 'queue', - ironIcon: 'playlist-add' - }); - } - - if (itemType == "Audio" || itemType == "MusicAlbum" || itemType == "MusicArtist" || itemType == "MusicGenre") { - menuItems.push({ - name: Globalize.translate('ButtonInstantMix'), - id: 'instantmix', - ironIcon: 'shuffle' - }); - } - - if (isFolder || itemType == "MusicArtist" || itemType == "MusicGenre") { - menuItems.push({ - name: Globalize.translate('ButtonShuffle'), - id: 'shuffle', - ironIcon: 'shuffle' - }); - } - - require(['actionsheet'], function (actionsheet) { - - actionsheet.show({ - items: menuItems, - positionTo: positionTo, - callback: function (id) { - - switch (id) { - - case 'play': - MediaController.play(itemId); - break; - case 'externalplayer': - LibraryBrowser.playInExternalPlayer(itemId); - break; - case 'resume': - MediaController.play({ - ids: [itemId], - startPositionTicks: resumePositionTicks - }); - break; - case 'queue': - MediaController.queue(itemId); - break; - case 'instantmix': - MediaController.instantMix(itemId); - break; - case 'shuffle': - MediaController.shuffle(itemId); - break; - default: - break; + return; } } + pages.dispatchEvent(new CustomEvent("tabchange", {})); + } + }, + + showTab: function (url, index) { + + if (!LibraryBrowser.enableFullPaperTabs()) { + + if (index) { + url = replaceQueryString(url, 'tab', index); + } + Dashboard.navigate(url); + return; + } + + var afterNavigate = function () { + if (window.location.href.toLowerCase().indexOf(url.toLowerCase()) != -1) { + + var pages = this.querySelector('neon-animated-pages'); + + if (pages) { + + var entryAnimation = pages.entryAnimation; + var exitAnimation = pages.exitAnimation; + pages.entryAnimation = null; + pages.exitAnimation = null; + + var tabs = this.querySelector('paper-tabs'); + + // For some reason the live tv page will not switch tabs in IE and safari + var delay = browserInfo.chrome ? 0 : 100; + + setTimeout(function () { + var noSlide = tabs.noSlide; + tabs.noSlide = true; + tabs.selected = index; + + pages.entryAnimation = entryAnimation; + pages.exitAnimation = exitAnimation; + tabs.noSlide = noSlide; + + }, delay); + } + } + }; + + if (window.location.href.toLowerCase().indexOf(url.toLowerCase()) != -1) { + + afterNavigate.call($($.mobile.activePage)[0]); + } else { + $(document).one('pagebeforeshow', '.page', afterNavigate); + Dashboard.navigate(url); + } + }, + + canShare: function (item, user) { + + return user.Policy.EnablePublicSharing; + }, + + getDateParamValue: function (date) { + + function formatDigit(i) { + return i < 10 ? "0" + i : i; + } + + var d = date; + + return "" + d.getFullYear() + formatDigit(d.getMonth() + 1) + formatDigit(d.getDate()) + formatDigit(d.getHours()) + formatDigit(d.getMinutes()) + formatDigit(d.getSeconds()); + }, + + playAllFromHere: function (fn, index) { + + fn(index, 100, "MediaSources,Chapters").then(function (result) { + + MediaController.play({ + items: result.Items + }); + }); + }, + + queueAllFromHere: function (query, index) { + + fn(index, 100, "MediaSources,Chapters").then(function (result) { + + MediaController.queue({ + items: result.Items + }); + }); + }, + + getItemCountsHtml: function (options, item) { + + var counts = []; + + var childText; + + if (item.Type == 'Playlist') { + + childText = ''; + + if (item.CumulativeRunTimeTicks) { + + var minutes = item.CumulativeRunTimeTicks / 600000000; + + minutes = minutes || 1; + + childText += Globalize.translate('ValueMinutes', Math.round(minutes)); + + } else { + childText += Globalize.translate('ValueMinutes', 0); + } + + counts.push(childText); + + } + else if (options.context == "movies") { + + if (item.MovieCount) { + + childText = item.MovieCount == 1 ? + Globalize.translate('ValueOneMovie') : + Globalize.translate('ValueMovieCount', item.MovieCount); + + counts.push(childText); + } + if (item.TrailerCount) { + + childText = item.TrailerCount == 1 ? + Globalize.translate('ValueOneTrailer') : + Globalize.translate('ValueTrailerCount', item.TrailerCount); + + counts.push(childText); + } + + } else if (options.context == "tv") { + + if (item.SeriesCount) { + + childText = item.SeriesCount == 1 ? + Globalize.translate('ValueOneSeries') : + Globalize.translate('ValueSeriesCount', item.SeriesCount); + + counts.push(childText); + } + if (item.EpisodeCount) { + + childText = item.EpisodeCount == 1 ? + Globalize.translate('ValueOneEpisode') : + Globalize.translate('ValueEpisodeCount', item.EpisodeCount); + + counts.push(childText); + } + + } else if (options.context == "games") { + + if (item.GameCount) { + + childText = item.GameCount == 1 ? + Globalize.translate('ValueOneGame') : + Globalize.translate('ValueGameCount', item.GameCount); + + counts.push(childText); + } + } else if (options.context == "music") { + + if (item.AlbumCount) { + + childText = item.AlbumCount == 1 ? + Globalize.translate('ValueOneAlbum') : + Globalize.translate('ValueAlbumCount', item.AlbumCount); + + counts.push(childText); + } + if (item.SongCount) { + + childText = item.SongCount == 1 ? + Globalize.translate('ValueOneSong') : + Globalize.translate('ValueSongCount', item.SongCount); + + counts.push(childText); + } + if (item.MusicVideoCount) { + + childText = item.MusicVideoCount == 1 ? + Globalize.translate('ValueOneMusicVideo') : + Globalize.translate('ValueMusicVideoCount', item.MusicVideoCount); + + counts.push(childText); + } + } + + return counts.join(' • '); + }, + + 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); + }); + }, + + showPlayMenu: function (positionTo, itemId, itemType, isFolder, mediaType, resumePositionTicks) { + + var externalPlayers = AppInfo.supportsExternalPlayers && AppSettings.enableExternalPlayers(); + + if (!resumePositionTicks && mediaType != "Audio" && !isFolder) { + + if (!externalPlayers || mediaType != "Video") { + + MediaController.play(itemId); + return; + } + } + + var menuItems = []; + + if (resumePositionTicks) { + menuItems.push({ + name: Globalize.translate('ButtonResume'), + id: 'resume', + ironIcon: 'play-arrow' + }); + } + + menuItems.push({ + name: Globalize.translate('ButtonPlay'), + id: 'play', + ironIcon: 'play-arrow' }); - }); - }, - - supportsEditing: function (itemType) { - - if (itemType == "UserRootFolder" || /*itemType == "CollectionFolder" ||*/ itemType == "UserView") { - return false; - } - - return true; - }, - - getMoreCommands: function (item, user) { - - var commands = []; - - if (LibraryBrowser.supportsAddingToCollection(item)) { - commands.push('addtocollection'); - } - - if (PlaylistManager.supportsPlaylists(item)) { - commands.push('playlist'); - } - - if (item.Type == 'BoxSet' || item.Type == 'Playlist') { - commands.push('delete'); - } - else if (item.CanDelete) { - commands.push('delete'); - } - - if (user.Policy.IsAdministrator) { - - if (LibraryBrowser.supportsEditing(item.Type)) { - commands.push('edit'); + if (!isFolder && externalPlayers && mediaType != "Audio") { + menuItems.push({ + name: Globalize.translate('ButtonPlayExternalPlayer'), + id: 'externalplayer', + ironIcon: 'airplay' + }); } - if (item.MediaType == 'Video' && item.Type != 'TvChannel' && item.Type != 'Program' && item.LocationType != 'Virtual') { - commands.push('editsubtitles'); + if (MediaController.canQueueMediaType(mediaType, itemType)) { + menuItems.push({ + name: Globalize.translate('ButtonQueue'), + id: 'queue', + ironIcon: 'playlist-add' + }); } - commands.push('editimages'); - } - if (user.Policy.IsAdministrator) { - - commands.push('refresh'); - } - - if (SyncManager.isAvailable(item, user)) { - commands.push('sync'); - } - - if (item.CanDownload) { - if (AppInfo.supportsDownloading) { - commands.push('download'); + if (itemType == "Audio" || itemType == "MusicAlbum" || itemType == "MusicArtist" || itemType == "MusicGenre") { + menuItems.push({ + name: Globalize.translate('ButtonInstantMix'), + id: 'instantmix', + ironIcon: 'shuffle' + }); } - } - if (LibraryBrowser.canShare(item, user)) { - commands.push('share'); - } + if (isFolder || itemType == "MusicArtist" || itemType == "MusicGenre") { + menuItems.push({ + name: Globalize.translate('ButtonShuffle'), + id: 'shuffle', + ironIcon: 'shuffle' + }); + } - if (item.Type == "Movie" || - item.Type == "Trailer" || - item.Type == "Series" || - item.Type == "Game" || - item.Type == "BoxSet" || - item.Type == "Person" || - item.Type == "Book" || - item.Type == "MusicAlbum" || - item.Type == "MusicArtist") { + require(['actionsheet'], function (actionsheet) { + + actionsheet.show({ + items: menuItems, + positionTo: positionTo, + callback: function (id) { + + switch (id) { + + case 'play': + MediaController.play(itemId); + break; + case 'externalplayer': + LibraryBrowser.playInExternalPlayer(itemId); + break; + case 'resume': + MediaController.play({ + ids: [itemId], + startPositionTicks: resumePositionTicks + }); + break; + case 'queue': + MediaController.queue(itemId); + break; + case 'instantmix': + MediaController.instantMix(itemId); + break; + case 'shuffle': + MediaController.shuffle(itemId); + break; + default: + break; + } + } + }); + + }); + }, + + supportsEditing: function (itemType) { + + if (itemType == "UserRootFolder" || /*itemType == "CollectionFolder" ||*/ itemType == "UserView") { + return false; + } + + return true; + }, + + getMoreCommands: function (item, user) { + + var commands = []; + + if (LibraryBrowser.supportsAddingToCollection(item)) { + commands.push('addtocollection'); + } + + if (playlistManager.supportsPlaylists(item)) { + commands.push('playlist'); + } + + if (item.Type == 'BoxSet' || item.Type == 'Playlist') { + commands.push('delete'); + } + else if (item.CanDelete) { + commands.push('delete'); + } if (user.Policy.IsAdministrator) { - commands.push('identify'); - } - } + if (LibraryBrowser.supportsEditing(item.Type)) { + commands.push('edit'); + } - return commands; - }, - - refreshItem: function (itemId) { - - ApiClient.refreshItem(itemId, { - - Recursive: true, - ImageRefreshMode: 'FullRefresh', - MetadataRefreshMode: 'FullRefresh', - ReplaceAllImages: false, - ReplaceAllMetadata: true - - }); - - Dashboard.alert(Globalize.translate('MessageRefreshQueued')); - }, - - deleteItems: function (itemIds) { - - return new Promise(function (resolve, reject) { - - var msg = Globalize.translate('ConfirmDeleteItem'); - var title = Globalize.translate('HeaderDeleteItem'); - - if (itemIds.length > 1) { - msg = Globalize.translate('ConfirmDeleteItems'); - title = Globalize.translate('HeaderDeleteItems'); + if (item.MediaType == 'Video' && item.Type != 'TvChannel' && item.Type != 'Program' && item.LocationType != 'Virtual') { + commands.push('editsubtitles'); + } + commands.push('editimages'); } - Dashboard.confirm(msg, title, function (result) { + if (user.Policy.IsAdministrator) { - if (result) { + commands.push('refresh'); + } - var promises = itemIds.map(function (itemId) { - ApiClient.deleteItem(itemId); - Events.trigger(LibraryBrowser, 'itemdeleting', [itemId]); + if (SyncManager.isAvailable(item, user)) { + commands.push('sync'); + } + + if (item.CanDownload) { + if (AppInfo.supportsDownloading) { + commands.push('download'); + } + } + + if (LibraryBrowser.canShare(item, user)) { + commands.push('share'); + } + + if (item.Type == "Movie" || + item.Type == "Trailer" || + item.Type == "Series" || + item.Type == "Game" || + item.Type == "BoxSet" || + item.Type == "Person" || + item.Type == "Book" || + item.Type == "MusicAlbum" || + item.Type == "MusicArtist") { + + if (user.Policy.IsAdministrator) { + + commands.push('identify'); + } + } + + return commands; + }, + + refreshItem: function (itemId) { + + ApiClient.refreshItem(itemId, { + + Recursive: true, + ImageRefreshMode: 'FullRefresh', + MetadataRefreshMode: 'FullRefresh', + ReplaceAllImages: false, + ReplaceAllMetadata: true + + }); + + Dashboard.alert(Globalize.translate('MessageRefreshQueued')); + }, + + deleteItems: function (itemIds) { + + return new Promise(function (resolve, reject) { + + var msg = Globalize.translate('ConfirmDeleteItem'); + var title = Globalize.translate('HeaderDeleteItem'); + + if (itemIds.length > 1) { + msg = Globalize.translate('ConfirmDeleteItems'); + title = Globalize.translate('HeaderDeleteItems'); + } + + Dashboard.confirm(msg, title, function (result) { + + if (result) { + + var promises = itemIds.map(function (itemId) { + ApiClient.deleteItem(itemId); + Events.trigger(LibraryBrowser, 'itemdeleting', [itemId]); + }); + + resolve(); + + } else { + reject(); + } + }); + }); + }, + + editImages: function (itemId) { + + require(['components/imageeditor/imageeditor'], function (ImageEditor) { + + ImageEditor.show(itemId); + }); + }, + + editSubtitles: function (itemId) { + + require(['components/subtitleeditor/subtitleeditor'], function (SubtitleEditor) { + + SubtitleEditor.show(itemId); + }); + }, + + editMetadata: function (itemId) { + + require(['components/metadataeditor/metadataeditor'], function (metadataeditor) { + + metadataeditor.show(itemId); + }); + }, + + showMoreCommands: function (positionTo, itemId, commands) { + + var items = []; + + if (commands.indexOf('addtocollection') != -1) { + items.push({ + name: Globalize.translate('ButtonAddToCollection'), + id: 'addtocollection', + ironIcon: 'add' + }); + } + + if (commands.indexOf('playlist') != -1) { + items.push({ + name: Globalize.translate('ButtonAddToPlaylist'), + id: 'playlist', + ironIcon: 'playlist-add' + }); + } + + if (commands.indexOf('delete') != -1) { + items.push({ + name: Globalize.translate('ButtonDelete'), + id: 'delete', + ironIcon: 'delete' + }); + } + + if (commands.indexOf('download') != -1) { + items.push({ + name: Globalize.translate('ButtonDownload'), + id: 'download', + ironIcon: 'file-download' + }); + } + + if (commands.indexOf('edit') != -1) { + items.push({ + name: Globalize.translate('ButtonEdit'), + id: 'edit', + ironIcon: 'mode-edit' + }); + } + + if (commands.indexOf('editimages') != -1) { + items.push({ + name: Globalize.translate('ButtonEditImages'), + id: 'editimages', + ironIcon: 'photo' + }); + } + + if (commands.indexOf('editsubtitles') != -1) { + items.push({ + name: Globalize.translate('ButtonEditSubtitles'), + id: 'editsubtitles', + ironIcon: 'closed-caption' + }); + } + + if (commands.indexOf('identify') != -1) { + items.push({ + name: Globalize.translate('ButtonIdentify'), + id: 'identify', + ironIcon: 'info' + }); + } + + if (commands.indexOf('refresh') != -1) { + items.push({ + name: Globalize.translate('ButtonRefresh'), + id: 'refresh', + ironIcon: 'refresh' + }); + } + + if (commands.indexOf('share') != -1) { + items.push({ + name: Globalize.translate('ButtonShare'), + id: 'share', + ironIcon: 'share' + }); + } + + require(['actionsheet'], function (actionsheet) { + + actionsheet.show({ + items: items, + positionTo: positionTo, + callback: function (id) { + + switch (id) { + + case 'share': + require(['sharingmanager'], function () { + SharingManager.showMenu(Dashboard.getCurrentUserId(), itemId); + }); + break; + case 'addtocollection': + require(['collectioneditor'], function (collectioneditor) { + + new collectioneditor().show([itemId]); + }); + break; + case 'playlist': + require(['playlistManager'], function (playlistManager) { + + playlistManager.showPanel([itemId]); + }); + break; + case 'delete': + LibraryBrowser.deleteItems([itemId]); + break; + case 'download': + { + var downloadHref = ApiClient.getUrl("Items/" + itemId + "/Download", { + api_key: ApiClient.accessToken() + }); + window.location.href = downloadHref; + + break; + } + case 'edit': + LibraryBrowser.editMetadata(itemId); + break; + case 'editsubtitles': + LibraryBrowser.editSubtitles(itemId); + break; + case 'editimages': + LibraryBrowser.editImages(itemId); + break; + case 'identify': + LibraryBrowser.identifyItem(itemId); + break; + case 'refresh': + ApiClient.refreshItem(itemId, { + + Recursive: true, + ImageRefreshMode: 'FullRefresh', + MetadataRefreshMode: 'FullRefresh', + ReplaceAllImages: false, + ReplaceAllMetadata: true + }); + break; + default: + break; + } + } + }); + + }); + }, + + identifyItem: function (itemId) { + + require(['components/itemidentifier/itemidentifier'], function (itemidentifier) { + + itemidentifier.show(itemId); + }); + }, + + 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 'collections.html?topParentId=' + 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 '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; + } + } + 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.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; + }, + + getImageUrl: function (item, type, index, options) { + + options = options || {}; + options.type = type; + options.index = index; + + if (type == 'Backdrop') { + options.tag = item.BackdropImageTags[index]; + } else if (type == 'Screenshot') { + options.tag = item.ScreenshotImageTags[index]; + } else if (type == 'Primary') { + options.tag = item.PrimaryImageTag || item.ImageTags[type]; + } else { + options.tag = item.ImageTags[type]; + } + + // For search hints + return ApiClient.getScaledImageUrl(item.Id || item.ItemId, options); + + }, + + getListViewIndex: function (item, options) { + + if (options.index == 'disc') { + + return item.ParentIndexNumber == null ? '' : Globalize.translate('ValueDiscNumber', item.ParentIndexNumber); + } + + var sortBy = (options.sortBy || '').toLowerCase(); + var code, name; + + if (sortBy.indexOf('sortname') == 0) { + + if (item.Type == 'Episode') return ''; + + // SortName + name = (item.SortName || item.Name || '?')[0].toUpperCase(); + + code = name.charCodeAt(0); + if (code < 65 || code > 90) { + return '#'; + } + + return name.toUpperCase(); + } + if (sortBy.indexOf('officialrating') == 0) { + + return item.OfficialRating || Globalize.translate('HeaderUnrated'); + } + if (sortBy.indexOf('communityrating') == 0) { + + if (item.CommunityRating == null) { + return Globalize.translate('HeaderUnrated'); + } + + return Math.floor(item.CommunityRating); + } + if (sortBy.indexOf('criticrating') == 0) { + + if (item.CriticRating == null) { + return Globalize.translate('HeaderUnrated'); + } + + return Math.floor(item.CriticRating); + } + if (sortBy.indexOf('metascore') == 0) { + + if (item.Metascore == null) { + return Globalize.translate('HeaderUnrated'); + } + + return Math.floor(item.Metascore); + } + if (sortBy.indexOf('albumartist') == 0) { + + // SortName + if (!item.AlbumArtist) return ''; + + name = item.AlbumArtist[0].toUpperCase(); + + code = name.charCodeAt(0); + if (code < 65 || code > 90) { + return '#'; + } + + return name.toUpperCase(); + } + return ''; + }, + + getUserDataCssClass: function (key) { + + if (!key) return ''; + + return 'libraryItemUserData' + key.replace(new RegExp(' ', 'g'), ''); + }, + + getListViewHtml: function (options) { + + require(['paper-icon-item', 'paper-item-body']); + + var outerHtml = ""; + + if (options.title) { + outerHtml += '