diff --git a/dashboard-ui/scripts/registrationservices.js b/dashboard-ui/scripts/registrationservices.js index 4caedba51..0d44b7f8d 100644 --- a/dashboard-ui/scripts/registrationservices.js +++ b/dashboard-ui/scripts/registrationservices.js @@ -132,7 +132,7 @@ document.body.appendChild(dlg); // Has to be assigned a z-index after the call to .open() - dlg.addEventListener('iron-overlay-closed', function(e) { + dlg.addEventListener('iron-overlay-closed', function (e) { appStorage.setItem(supporterPlaybackKey, new Date().getTime()); dlg.parentNode.removeChild(dlg); deferred.resolve(); @@ -168,11 +168,15 @@ Dashboard.alert({ message: Globalize.translate('HeaderSyncRequiresSupporterMembership') + '

' + Globalize.translate('ButtonLearnMore') + '

', - title: Globalize.translate('HeaderSync') + title: Globalize.translate('HeaderSync'), + callback: function () { + deferred.reject(); + } }); }, function () { + deferred.reject(); Dashboard.hideLoadingMsg(); Dashboard.alert({ @@ -234,7 +238,12 @@ var url = "http://mb3admin.com/admin/service/user/getPayPalEmail?id=" + pkg.owner; - $.getJSON(url).done(function (dev) { + fetch(url, { mode: 'no-cors' }).then(function (response) { + + return response.json(); + + }).then(function (dev) { + if (dev.payPalEmail) { $('#payPalEmail', page).val(dev.payPalEmail); diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index c1826bd61..f729159e2 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -1,60 +1,18 @@ (function () { - $.ajaxSetup({ - crossDomain: true - }); + function onOneDocumentClick() { - if ($.browser.msie || $.browser.edge) { + document.removeEventListener('click', onOneDocumentClick); - // This is unfortunately required due to IE's over-aggressive caching. - // https://github.com/MediaBrowser/MediaBrowser/issues/179 - $.ajaxSetup({ - cache: false - }); + if (window.Notification) { + Notification.requestPermission(); + } } + document.addEventListener('click', onOneDocumentClick); + })(); -$.support.cors = true; - -$(document).one('click', WebNotifications.requestPermission); - var Dashboard = { - jQueryMobileInit: function () { - - // Page - //$.mobile.page.prototype.options.theme = "a"; - //$.mobile.page.prototype.options.headerTheme = "a"; - //$.mobile.page.prototype.options.contentTheme = "a"; - //$.mobile.page.prototype.options.footerTheme = "a"; - - //$.mobile.button.prototype.options.theme = "c"; - //$.mobile.listview.prototype.options.dividerTheme = "b"; - - //$.mobile.popup.prototype.options.theme = "c"; - //$.mobile.popup.prototype.options.transition = "none"; - - if ($.browser.mobile) { - $.mobile.defaultPageTransition = "none"; - } else { - $.mobile.defaultPageTransition = "none"; - } - //$.mobile.collapsible.prototype.options.contentTheme = "a"; - - // Make panels a little larger than the defaults - - //$.event.special.swipe.verticalDistanceThreshold = 40; - //$.mobile.page.prototype.options.domCache = true; - - $.mobile.hideUrlBar = false; - $.mobile.autoInitializePage = false; - $.mobile.changePage.defaults.showLoadMsg = false; - - // These are not needed. Nulling them out can help reduce dom querying when pages are loaded - $.mobile.nojs = null; - $.mobile.degradeInputsWithin = null; - - $.mobile.filterHtml = Dashboard.filterHtml; - }, filterHtml: function (html) { @@ -77,7 +35,7 @@ var Dashboard = { return true; } - var url = getWindowUrl().toLowerCase(); + var url = window.location.href.toLowerCase(); return url.indexOf('mediabrowser.tv') != -1 || url.indexOf('emby.media') != -1; @@ -145,23 +103,7 @@ var Dashboard = { getCurrentUser: function () { - if (!Dashboard.getUserPromise) { - - Dashboard.getUserPromise = window.ApiClient.getCurrentUser().fail(function () { - Dashboard.getUserPromise = null; - }); - } - - return Dashboard.getUserPromise; - }, - - validateCurrentUser: function () { - - Dashboard.getUserPromise = null; - - if (Dashboard.getCurrentUserId()) { - Dashboard.getCurrentUser(); - } + return window.ApiClient.getCurrentUser(); }, serverAddress: function () { @@ -178,7 +120,7 @@ var Dashboard = { // Try to get the server address from the browser url // This will preserve protocol, hostname, port and subdirectory - var urlLower = getWindowUrl().toLowerCase(); + var urlLower = window.location.href.toLowerCase(); var index = urlLower.indexOf('/web'); if (index == -1) { index = urlLower.indexOf('/dashboard'); @@ -216,8 +158,6 @@ var Dashboard = { apiClient = apiClient || window.ApiClient; window.ApiClient = apiClient; - - Dashboard.getUserPromise = null; }, logout: function (logoutWithServer) { @@ -238,7 +178,7 @@ var Dashboard = { if (logoutWithServer === false) { onLogoutDone(); } else { - ConnectionManager.logout().done(onLogoutDone); + ConnectionManager.logout().then(onLogoutDone); } }, @@ -277,11 +217,6 @@ var Dashboard = { } }, - showError: function (message) { - - Dashboard.alert(message); - }, - updateSystemInfo: function (info) { Dashboard.lastSystemInfo = info; @@ -296,7 +231,7 @@ var Dashboard = { Dashboard.hideDashboardVersionWarning(); - Dashboard.getCurrentUser().done(function (currentUser) { + Dashboard.getCurrentUser().then(function (currentUser) { if (currentUser.Policy.IsAdministrator) { Dashboard.showServerRestartWarning(info); @@ -362,7 +297,7 @@ var Dashboard = { cancelInstallation: function (id) { - ApiClient.cancelPackageInstallation(id).always(Dashboard.refreshSystemInfoFromServer); + ApiClient.cancelPackageInstallation(id).then(Dashboard.refreshSystemInfoFromServer, Dashboard.refreshSystemInfoFromServer); }, @@ -396,7 +331,7 @@ var Dashboard = { reloadPage: function () { - var currentUrl = getWindowUrl().toLowerCase(); + var currentUrl = window.location.href.toLowerCase(); var newUrl; // If they're on a plugin config page just go back to the dashboard @@ -404,7 +339,7 @@ var Dashboard = { if (currentUrl.indexOf('configurationpage') != -1) { newUrl = "dashboard.html"; } else { - newUrl = getWindowUrl(); + newUrl = window.location.href; } window.location.href = newUrl; @@ -430,6 +365,17 @@ var Dashboard = { options.id = options.id || "notification" + new Date().getTime() + parseInt(Math.random()); + if (!document.querySelector(".footer")) { + + var footerHtml = ''; + + $(document.body).append(footerHtml); + + } + var footer = $(".footer").css("top", "initial").show(); var parentElem = $('#footerNotifications', footer); @@ -513,14 +459,11 @@ var Dashboard = { } else { - // IE renders it incorrectly - if (!$.browser.msie && !$.browser.edge) { - elem = document.createElement("paper-spinner"); - elem.classList.add('docspinner'); + elem = document.createElement("paper-spinner"); + elem.classList.add('docspinner'); - document.body.appendChild(elem); - elem.active = true; - } + document.body.appendChild(elem); + elem.active = true; } }, @@ -531,20 +474,19 @@ var Dashboard = { if (elem) { elem.active = false; - - setTimeout(function () { - elem.active = false; - }, 100); } }, getModalLoadingMsg: function () { - var elem = $('.modalLoading'); + var elem = document.querySelector('.modalLoading'); - if (!elem.length) { + if (!elem) { - elem = $('').appendTo(document.body); + elem = document.createElement('modalLoading'); + elem.classList.add('modalLoading'); + elem.classList.add('hide'); + document.body.appendChild(elem); } @@ -552,12 +494,12 @@ var Dashboard = { }, showModalLoadingMsg: function () { - Dashboard.getModalLoadingMsg().show(); + Dashboard.getModalLoadingMsg().classList.remove('hide'); Dashboard.showLoadingMsg(); }, hideModalLoadingMsg: function () { - Dashboard.getModalLoadingMsg().hide(); + Dashboard.getModalLoadingMsg().classList.add('hide'); Dashboard.hideLoadingMsg(); }, @@ -565,11 +507,9 @@ var Dashboard = { Dashboard.hideLoadingMsg(); - Dashboard.alert("Settings saved."); + Dashboard.alert(Globalize.translate('MessageSettingsSaved')); }, - defaultErrorMessage: Globalize.translate('DefaultErrorMessage'), - processServerConfigurationUpdateResult: function (result) { Dashboard.hideLoadingMsg(); @@ -581,29 +521,27 @@ var Dashboard = { if (typeof options == "string") { - require(['paperbuttonstyle'], function () { - var message = options; + var message = options; - Dashboard.toastId = Dashboard.toastId || 0; + Dashboard.toastId = Dashboard.toastId || 0; - var id = 'toast' + (Dashboard.toastId++); + var id = 'toast' + (Dashboard.toastId++); - var elem = document.createElement("paper-toast"); - elem.setAttribute('text', message); - elem.id = id; + var elem = document.createElement("paper-toast"); + elem.setAttribute('text', message); + elem.id = id; - document.body.appendChild(elem); + document.body.appendChild(elem); + + // This timeout is obviously messy but it's unclear how to determine when the webcomponent is ready for use + // element onload never fires + setTimeout(function () { + elem.show(); - // This timeout is obviously messy but it's unclear how to determine when the webcomponent is ready for use - // element onload never fires setTimeout(function () { - elem.show(); - - setTimeout(function () { - elem.parentNode.removeChild(elem); - }, 5000); - }, 300); - }); + elem.parentNode.removeChild(elem); + }, 5000); + }, 300); return; } @@ -677,9 +615,9 @@ var Dashboard = { }); // Has to be assigned a z-index after the call to .open() - $(dlg).on('iron-overlay-closed', function (e) { + dlg.addEventListener('iron-overlay-closed', function (e) { - this.parentNode.removeChild(this); + dlg.parentNode.removeChild(dlg); }); dlg.open(); @@ -732,9 +670,10 @@ var Dashboard = { var dlg = document.getElementById(id); // Has to be assigned a z-index after the call to .open() - $(dlg).on('iron-overlay-closed', function (e) { - var confirmed = this.closingReason.confirmed; - this.parentNode.removeChild(this); + dlg.addEventListener('iron-overlay-closed', function (e) { + + var confirmed = dlg.closingReason.confirmed; + dlg.parentNode.removeChild(dlg); if (callback) { callback(confirmed); @@ -752,7 +691,7 @@ var Dashboard = { if (apiClient && apiClient.accessToken()) { if (AppInfo.enableFooterNotifications) { - apiClient.getSystemInfo().done(function (info) { + apiClient.getSystemInfo().then(function (info) { Dashboard.updateSystemInfo(info); }); @@ -767,13 +706,13 @@ var Dashboard = { Dashboard.suppressAjaxErrors = true; Dashboard.showLoadingMsg(); - ApiClient.restartServer().done(function () { + ApiClient.restartServer().then(function () { setTimeout(function () { Dashboard.reloadPageWhenServerAvailable(); }, 250); - }).fail(function () { + }, function () { Dashboard.suppressAjaxErrors = false; }); }, @@ -781,7 +720,7 @@ var Dashboard = { reloadPageWhenServerAvailable: function (retryCount) { // Don't use apiclient method because we don't want it reporting authentication under the old version - ApiClient.getJSON(ApiClient.getUrl("System/Info")).done(function (info) { + ApiClient.getJSON(ApiClient.getUrl("System/Info")).then(function (info) { // If this is back to false, the restart completed if (!info.HasPendingRestart) { @@ -790,7 +729,7 @@ var Dashboard = { Dashboard.retryReload(retryCount); } - }).fail(function () { + }, function () { Dashboard.retryReload(retryCount); }); }, @@ -829,13 +768,16 @@ var Dashboard = { $(document.body).append(html); - var elem = $('#userFlyout').panel({}).lazyChildren().trigger('create').panel("open").on("panelclose", function () { + var userFlyout = document.querySelector('#userFlyout'); + ImageLoader.lazyChildren(userFlyout); + + $(userFlyout).panel({}).panel("open").on("panelclose", function () { $(this).off("panelclose").remove(); }); - ConnectionManager.user(window.ApiClient).done(function (user) { - Dashboard.updateUserFlyout(elem, user); + ConnectionManager.user(window.ApiClient).then(function (user) { + Dashboard.updateUserFlyout(userFlyout, user); }); }); }, @@ -856,7 +798,9 @@ var Dashboard = { } html += user.name; - $('.userHeader', elem).html(html).lazyChildren(); + var userHeader = elem.querySelector('.userHeader'); + userHeader.innerHTML = html; + ImageLoader.lazyChildren(userHeader); html = ''; @@ -892,7 +836,7 @@ var Dashboard = { // Don't show normal dashboard errors } - }).done(function (result) { + }).then(function (result) { deferred.resolveWith(null, [result]); }); @@ -1141,7 +1085,7 @@ var Dashboard = { Dashboard.onBrowseCommand(cmd.Arguments); break; case 'GoToSearch': - Search.showSearchPanel($.mobile.activePage); + Search.showSearchPanel(); break; case 'DisplayMessage': { @@ -1186,27 +1130,14 @@ var Dashboard = { else if (msg.MessageType === "ServerRestarting") { Dashboard.hideServerRestartWarning(); } - else if (msg.MessageType === "UserDeleted") { - Dashboard.validateCurrentUser(); - } else if (msg.MessageType === "SystemInfo") { Dashboard.updateSystemInfo(msg.Data); } else if (msg.MessageType === "RestartRequired") { Dashboard.updateSystemInfo(msg.Data); } - else if (msg.MessageType === "UserUpdated" || msg.MessageType === "UserConfigurationUpdated") { - var user = msg.Data; - - if (user.Id == Dashboard.getCurrentUserId()) { - - Dashboard.validateCurrentUser(); - $('.currentUsername').html(user.Name); - } - - } else if (msg.MessageType === "PackageInstallationCompleted") { - Dashboard.getCurrentUser().done(function (currentUser) { + Dashboard.getCurrentUser().then(function (currentUser) { if (currentUser.Policy.IsAdministrator) { Dashboard.showPackageInstallNotification(msg.Data, "completed"); @@ -1215,7 +1146,7 @@ var Dashboard = { }); } else if (msg.MessageType === "PackageInstallationFailed") { - Dashboard.getCurrentUser().done(function (currentUser) { + Dashboard.getCurrentUser().then(function (currentUser) { if (currentUser.Policy.IsAdministrator) { Dashboard.showPackageInstallNotification(msg.Data, "failed"); @@ -1224,7 +1155,7 @@ var Dashboard = { }); } else if (msg.MessageType === "PackageInstallationCancelled") { - Dashboard.getCurrentUser().done(function (currentUser) { + Dashboard.getCurrentUser().then(function (currentUser) { if (currentUser.Policy.IsAdministrator) { Dashboard.showPackageInstallNotification(msg.Data, "cancelled"); @@ -1233,7 +1164,7 @@ var Dashboard = { }); } else if (msg.MessaapiclientcgeType === "PackageInstalling") { - Dashboard.getCurrentUser().done(function (currentUser) { + Dashboard.getCurrentUser().then(function (currentUser) { if (currentUser.Policy.IsAdministrator) { Dashboard.showPackageInstallNotification(msg.Data, "progress"); @@ -1279,7 +1210,7 @@ var Dashboard = { return; } - ApiClient.getItem(Dashboard.getCurrentUserId(), cmd.ItemId).done(function (item) { + ApiClient.getItem(Dashboard.getCurrentUserId(), cmd.ItemId).then(function (item) { Dashboard.navigate(LibraryBrowser.getHref(item, null, '')); @@ -1350,7 +1281,7 @@ var Dashboard = { var newItems = data.ItemsAdded; - if (!newItems.length || AppInfo.isNativeApp) { + if (!newItems.length || AppInfo.isNativeApp || !window.Notification) { return; } @@ -1364,7 +1295,7 @@ var Dashboard = { ImageTypes: "Primary", Ids: newItems.join(',') - }).done(function (result) { + }).then(function (result) { var items = result.Items; @@ -1375,7 +1306,8 @@ var Dashboard = { var notification = { title: "New " + item.Type, body: item.Name, - timeout: 5000 + timeout: 5000, + vibrate: true }; var imageTags = item.ImageTags || {}; @@ -1389,6 +1321,26 @@ var Dashboard = { }); } + if (Notification.permission === "granted") { + + var notif = new Notification(notification.title, notification); + + if (notif.show) { + notif.show(); + } + + if (notification.timeout) { + setTimeout(function () { + + if (notif.close) { + notif.close(); + } + else if (notif.cancel) { + notif.cancel(); + } + }, notification.timeout); + } + } WebNotifications.show(notification); } }); @@ -1424,10 +1376,6 @@ var Dashboard = { html += ''; $(parent).prepend(html); - - if (helpUrl) { - require(['paperbuttonstyle']); - } }, setPageTitle: function (title) { @@ -1485,38 +1433,6 @@ var Dashboard = { return parts.join(':'); }, - populateLanguages: function (select, languages) { - - var html = ""; - - html += ""; - - for (var i = 0, length = languages.length; i < length; i++) { - - var culture = languages[i]; - - html += ""; - } - - $(select).html(html); - }, - - populateCountries: function (select, allCountries) { - - var html = ""; - - html += ""; - - for (var i = 0, length = allCountries.length; i < length; i++) { - - var culture = allCountries[i]; - - html += ""; - } - - $(select).html(html); - }, - getSupportedRemoteCommands: function () { // Full list @@ -1541,7 +1457,7 @@ var Dashboard = { }, isServerlessPage: function () { - var url = getWindowUrl().toLowerCase(); + var url = window.location.href.toLowerCase(); return url.indexOf('connectlogin.html') != -1 || url.indexOf('selectserver.html') != -1 || url.indexOf('login.html') != -1 || url.indexOf('forgotpassword.html') != -1 || url.indexOf('forgotpasswordpin.html') != -1; }, @@ -1559,7 +1475,7 @@ var Dashboard = { SupportedLiveMediaTypes: ['Audio', 'Video'] }; - if (Dashboard.isRunningInCordova() && !$.browser.safari) { + if (Dashboard.isRunningInCordova() && !browserInfo.safari) { caps.SupportsOfflineAccess = true; caps.SupportsSync = true; caps.SupportsContentUploading = true; @@ -1590,16 +1506,6 @@ var Dashboard = { } } - if (typeof ($.browser.androidVersion) == 'number' && !isNaN($.browser.androidVersion)) { - if ($.browser.androidVersion < 5) { - quality -= 10; - - if ($.browser.androidVersion < 4.4) { - quality -= 10; - } - } - } - return quality; }, @@ -1620,31 +1526,29 @@ var Dashboard = { function generateDeviceName() { - var name = "Web Browser"; + var name; - if ($.browser.chrome) { + if (browserInfo.chrome) { name = "Chrome"; - } else if ($.browser.safari) { - name = "Safari"; - } else if ($.browser.msie) { - name = "Internet Explorer"; - } else if ($.browser.opera) { - name = "Opera"; - } else if ($.browser.mozilla) { - name = "Firefox"; - } else if ($.browser.edge) { + } else if (browserInfo.edge) { name = "Edge"; + } else if (browserInfo.mozilla) { + name = "Firefox"; + } else if (browserInfo.msie) { + name = "Internet Explorer"; + } else { + name = "Web Browser"; } - if ($.browser.version) { - name += " " + $.browser.version; + if (browserInfo.version) { + name += " " + browserInfo.version; } - if ($.browser.ipad) { + if (browserInfo.ipad) { name += " Ipad"; - } else if ($.browser.iphone) { + } else if (browserInfo.iphone) { name += " Iphone"; - } else if ($.browser.android) { + } else if (browserInfo.android) { name += " Android"; } return name; @@ -1685,12 +1589,7 @@ var Dashboard = { ready: function (fn) { - if (Dashboard.initPromiseDone) { - fn(); - return; - } - - Dashboard.initPromise.done(fn); + Dashboard.initPromise.then(fn); }, loadExternalPlayer: function () { @@ -1718,17 +1617,6 @@ var Dashboard = { exit: function () { Dashboard.logout(); - }, - - loadDragula: function (callback) { - - require(['dragula'], function (dragula) { - - Dashboard.importCss('bower_components/dragula.js/dist/dragula.min.css'); - - callback(dragula); - }); - } }; @@ -1762,15 +1650,13 @@ var AppInfo = {}; AppInfo.enableAppStorePolicy = isCordova; - var isIOS = $.browser.safari || $.browser.ipad || $.browser.iphone; - var isAndroid = $.browser.android; - var isMobile = $.browser.mobile; + var isIOS = browserInfo.ipad || browserInfo.iphone; + var isAndroid = browserInfo.android; + var isMobile = browserInfo.mobile; if (isIOS) { - if (isMobile) { - AppInfo.hasLowImageBandwidth = true; - } + AppInfo.hasLowImageBandwidth = true; if (isCordova) { //AppInfo.enableSectionTransitions = true; @@ -1786,15 +1672,12 @@ var AppInfo = {}; } } else { - if (isMobile) { + AppInfo.enableDetailPageChapters = false; + AppInfo.enableDetailsMenuImages = false; + AppInfo.enableMovieHomeSuggestions = false; + AppInfo.cardMargin = 'largeCardMargin'; - AppInfo.enableDetailPageChapters = false; - AppInfo.enableDetailsMenuImages = false; - AppInfo.enableMovieHomeSuggestions = false; - AppInfo.cardMargin = 'largeCardMargin'; - - AppInfo.forcedImageFormat = 'jpg'; - } + AppInfo.forcedImageFormat = 'jpg'; } } @@ -1804,10 +1687,16 @@ var AppInfo = {}; AppInfo.enableMovieTrailersTab = true; } + AppInfo.supportsExternalPlayers = true; + if (isCordova) { AppInfo.enableAppLayouts = true; - AppInfo.hasKnownExternalPlayerSupport = true; + AppInfo.supportsExternalPlayerMenu = true; AppInfo.isNativeApp = true; + + if (isIOS) { + AppInfo.supportsExternalPlayers = false; + } } else { AppInfo.enableFooterNotifications = true; @@ -1818,14 +1707,10 @@ var AppInfo = {}; } } - if (!$.browser.tv && !isIOS) { + // This doesn't perform well on iOS + AppInfo.enableHeadRoom = !isIOS; - // Don't enable headroom on mobile chrome when the address bar is visible - // With two bars hiding and showing it gets a little awkward - if (AppInfo.isNativeApp || window.navigator.standalone || !$.browser.mobile) { - AppInfo.enableHeadRoom = true; - } - } + AppInfo.supportsDownloading = !(AppInfo.isNativeApp && isIOS); AppInfo.enableUserImage = true; AppInfo.hasPhysicalVolumeButtons = isCordova || isMobile; @@ -1864,45 +1749,45 @@ var AppInfo = {}; window.ConnectionManager = new MediaBrowser.ConnectionManager(Logger, credentialProvider, AppInfo.appName, AppInfo.appVersion, AppInfo.deviceName, AppInfo.deviceId, capabilities); - if (getWindowUrl().toLowerCase().indexOf('wizardstart.html') != -1) { + if (window.location.href.toLowerCase().indexOf('wizardstart.html') != -1) { window.ConnectionManager.clearData(); } - $(ConnectionManager).on('apiclientcreated', function (e, newApiClient) { + Events.on(ConnectionManager, 'apiclientcreated', function (e, newApiClient) { initializeApiClient(newApiClient); }); - var deferred = DeferredBuilder.Deferred(); + return new Promise(function (resolve, reject) { - if (Dashboard.isConnectMode()) { + if (Dashboard.isConnectMode()) { - var server = ConnectionManager.getLastUsedServer(); + var server = ConnectionManager.getLastUsedServer(); - if (!Dashboard.isServerlessPage()) { + if (!Dashboard.isServerlessPage()) { - if (server && server.UserId && server.AccessToken) { - ConnectionManager.connectToServer(server).done(function (result) { - if (result.State == MediaBrowser.ConnectionState.SignedIn) { - window.ApiClient = result.ApiClient; - } - deferred.resolve(); - }); - return deferred.promise(); + if (server && server.UserId && server.AccessToken) { + ConnectionManager.connectToServer(server).then(function (result) { + if (result.State == MediaBrowser.ConnectionState.SignedIn) { + window.ApiClient = result.ApiClient; + } + resolve(); + }); + return; + } } + resolve(); + + } else { + + var apiClient = new MediaBrowser.ApiClient(Logger, Dashboard.serverAddress(), AppInfo.appName, AppInfo.appVersion, AppInfo.deviceName, AppInfo.deviceId); + apiClient.enableAutomaticNetworking = false; + ConnectionManager.addApiClient(apiClient); + Dashboard.importCss(apiClient.getUrl('Branding/Css')); + window.ApiClient = apiClient; + resolve(); } - deferred.resolve(); - - } else { - - var apiClient = new MediaBrowser.ApiClient(Logger, Dashboard.serverAddress(), AppInfo.appName, AppInfo.appVersion, AppInfo.deviceName, AppInfo.deviceId); - apiClient.enableAutomaticNetworking = false; - ConnectionManager.addApiClient(apiClient); - Dashboard.importCss(apiClient.getUrl('Branding/Css')); - window.ApiClient = apiClient; - deferred.resolve(); - } - return deferred.promise(); + }); } function initFastClick() { @@ -1913,9 +1798,26 @@ var AppInfo = {}; tapDelay: 0 }); + function parentWithClass(elem, className) { + + while (!elem.classList || !elem.classList.contains(className)) { + elem = elem.parentNode; + + if (!elem) { + return null; + } + } + + return elem; + } + // Have to work around this issue of fast click breaking the panel dismiss - $(document.body).on('touchstart', '.ui-panel-dismiss', function () { - $(this).trigger('click'); + document.body.addEventListener('touchstart', function (e) { + + var tgt = parentWithClass(e.target, 'ui-panel-dismiss'); + if (tgt) { + $(tgt).click(); + } }); }); @@ -1976,98 +1878,10 @@ var AppInfo = {}; } } - function onDocumentReady() { - - if ($.browser.msie) { - require(['devices/ie/ie']); - } - - // Do these now to prevent a flash of content - if (AppInfo.isNativeApp) { - if ($.browser.android) { - Dashboard.importCss('devices/android.css'); - } else if ($.browser.safari) { - Dashboard.importCss('devices/ios/ios.css'); - } - } else { - loadTheme(); - } - - if ($.browser.safari && $.browser.mobile) { - initFastClick(); - } - - var footerHtml = ''; - - $(document.body).append(footerHtml); - - $(window).on("beforeunload", function () { - - var apiClient = window.ApiClient; - - // Close the connection gracefully when possible - if (apiClient && apiClient.isWebSocketOpen()) { - - var localActivePlayers = MediaController.getPlayers().filter(function (p) { - - return p.isLocalPlayer && p.isPlaying(); - }); - - if (!localActivePlayers.length) { - Logger.log('Sending close web socket command'); - apiClient.closeWebSocket(); - } - } - }); - - $(document).on('contextmenu', '.ui-popup-screen', function (e) { - - $('.ui-popup').popup('close'); - - e.preventDefault(); - return false; - }); - - if (Dashboard.isRunningInCordova()) { - require(['cordova/connectsdk', 'scripts/registrationservices', 'cordova/back']); - - if ($.browser.android) { - require(['cordova/android/androidcredentials', 'cordova/android/immersive', 'cordova/android/mediasession']); - } else { - require(['cordova/volume']); - } - - if ($.browser.safari) { - require(['cordova/ios/orientation']); - } - - } else { - if ($.browser.chrome) { - require(['scripts/chromecast']); - } - } - - if (AppInfo.enableNowPlayingBar) { - require(['scripts/nowplayingbar']); - Dashboard.importCss('css/nowplayingbar.css'); - } - - if (navigator.splashscreen) { - navigator.splashscreen.hide(); - } - } - - function init(deferred, capabilities, appName, appVersion, deviceId, deviceName) { + function initRequire() { var urlArgs = "v=" + window.dashboardVersion; - if ($.browser.msie || $.browser.edge) { - urlArgs += new Date().getTime(); - } - var paths = { velocity: "bower_components/velocity/velocity.min", tvguide: 'components/tvguide/tvguide', @@ -2077,7 +1891,12 @@ var AppInfo = {}; medialibrarycreator: 'components/medialibrarycreator/medialibrarycreator', medialibraryeditor: 'components/medialibraryeditor/medialibraryeditor', howler: 'bower_components/howler.js/howler.min', - sortable: 'bower_components/Sortable/Sortable.min' + sortable: 'bower_components/Sortable/Sortable.min', + isMobile: 'bower_components/isMobile/isMobile.min', + headroom: 'bower_components/headroom.js/dist/headroom.min', + masonry: 'bower_components/masonry/dist/masonry.pkgd.min', + humanedate: 'components/humanedate', + jQuery: 'bower_components/jquery/dist/jquery.min' }; if (Dashboard.isRunningInCordova()) { @@ -2086,20 +1905,22 @@ var AppInfo = {}; paths.prompt = "components/prompt"; } - paths.masonry = "bower_components/masonry/dist/masonry.pkgd.min"; - requirejs.config({ + map: { + '*': { + 'css': 'components/requirecss' + } + }, urlArgs: urlArgs, paths: paths }); - // Required since jQuery is loaded before requireJs - define('jquery', [], function () { - return jQuery; - }); + } - if (Dashboard.isRunningInCordova() && $.browser.android) { + function init(promiseResolve, capabilities, appName, appVersion, deviceId, deviceName) { + + if (Dashboard.isRunningInCordova() && browserInfo.android) { define("appstorage", ["cordova/android/appstorage"]); } else { define('appstorage', [], function () { @@ -2120,15 +1941,15 @@ var AppInfo = {}; define("localassetmanager", ["apiclient/localassetmanager"]); } - if (Dashboard.isRunningInCordova() && $.browser.android) { + if (Dashboard.isRunningInCordova() && browserInfo.android) { define("nativedirectorychooser", ["cordova/android/nativedirectorychooser"]); } - if (Dashboard.isRunningInCordova() && $.browser.android) { + if (Dashboard.isRunningInCordova() && browserInfo.android) { define("audiorenderer", ["cordova/android/vlcplayer"]); define("videorenderer", ["cordova/android/vlcplayer"]); } - else if (Dashboard.isRunningInCordova() && $.browser.safari) { + else if (Dashboard.isRunningInCordova() && browserInfo.safari) { define("audiorenderer", ["cordova/ios/vlcplayer"]); define("videorenderer", ["scripts/htmlmediarenderer"]); } @@ -2137,7 +1958,7 @@ var AppInfo = {}; define("videorenderer", ["scripts/htmlmediarenderer"]); } - if (Dashboard.isRunningInCordova() && $.browser.android) { + if (Dashboard.isRunningInCordova() && browserInfo.android) { define("localsync", ["cordova/android/localsync"]); } else { @@ -2145,29 +1966,16 @@ var AppInfo = {}; } define("connectservice", ["apiclient/connectservice"]); - define("paperbuttonstyle", [], function () { - return {}; - }); - define("jqmicons", [], function () { - Dashboard.importCss('thirdparty/jquerymobile-1.4.5/jquery.mobile.custom.icons.css'); - return {}; - }); + define("livetvcss", [], function () { Dashboard.importCss('css/livetv.css'); return {}; }); - define("fontawesome", [], function () { - Dashboard.importCss('thirdparty/fontawesome/css/font-awesome.min.css'); - return {}; - }); define("detailtablecss", [], function () { Dashboard.importCss('css/detailtable.css'); return {}; }); - define("tileitemcss", [], function () { - Dashboard.importCss('css/tileitem.css'); - return {}; - }); + define("tileitemcss", ['css!/css/tileitem.css']); if (Dashboard.isRunningInCordova()) { define("actionsheet", ["cordova/actionsheet"]); @@ -2183,54 +1991,30 @@ var AppInfo = {}; define("sharingwidget", ["scripts/sharingwidget"]); } - if (Dashboard.isRunningInCordova() && $.browser.safari) { + if (Dashboard.isRunningInCordova() && browserInfo.safari) { define("searchmenu", ["cordova/searchmenu"]); } else { define("searchmenu", ["scripts/searchmenu"]); } - define("jqmtable", ["thirdparty/jquerymobile-1.4.5/jqm.table"], function () { - Dashboard.importCss('thirdparty/jquerymobile-1.4.5/jqm.table.css'); - return {}; - }); + define("jqmicons", ['css!thirdparty/jquerymobile-1.4.5/jquery.mobile.custom.icons.css']); + define("jqmtable", ["thirdparty/jquerymobile-1.4.5/jqm.table", 'css!thirdparty/jquerymobile-1.4.5/jqm.table.css']); - define("jqmslider", ["thirdparty/jquerymobile-1.4.5/jqm.slider"], function () { - Dashboard.importCss('thirdparty/jquerymobile-1.4.5/jqm.slider.css'); - return {}; - }); + define("jqmwidget", ["thirdparty/jquerymobile-1.4.5/jqm.widget"]); - define("jqmpopup", ["thirdparty/jquerymobile-1.4.5/jqm.popup"], function () { - Dashboard.importCss('thirdparty/jquerymobile-1.4.5/jqm.popup.css'); - return {}; - }); + define("jqmslider", ["thirdparty/jquerymobile-1.4.5/jqm.slider", 'css!thirdparty/jquerymobile-1.4.5/jqm.slider.css']); - define("jqmlistview", ["thirdparty/jquerymobile-1.4.5/jqm.listview"], function () { - Dashboard.importCss('thirdparty/jquerymobile-1.4.5/jqm.listview.css'); - return {}; - }); + define("jqmpopup", ["thirdparty/jquerymobile-1.4.5/jqm.popup", 'css!thirdparty/jquerymobile-1.4.5/jqm.popup.css']); - define("jqmcontrolgroup", ["thirdparty/jquerymobile-1.4.5/jqm.controlgroup"], function () { - Dashboard.importCss('thirdparty/jquerymobile-1.4.5/jqm.controlgroup.css'); - return {}; - }); + define("jqmlistview", ["thirdparty/jquerymobile-1.4.5/jqm.listview", 'css!thirdparty/jquerymobile-1.4.5/jqm.listview.css']); - define("jqmcollapsible", ["jqmicons", "thirdparty/jquerymobile-1.4.5/jqm.collapsible"], function () { - Dashboard.importCss('thirdparty/jquerymobile-1.4.5/jqm.collapsible.css'); - return {}; - }); + define("jqmcontrolgroup", ["thirdparty/jquerymobile-1.4.5/jqm.controlgroup", 'css!thirdparty/jquerymobile-1.4.5/jqm.controlgroup.css']); - define("jqmcheckbox", ["jqmicons", "thirdparty/jquerymobile-1.4.5/jqm.checkbox"], function () { - Dashboard.importCss('thirdparty/jquerymobile-1.4.5/jqm.checkbox.css'); - return {}; - }); + define("jqmcollapsible", ["jqmicons", "thirdparty/jquerymobile-1.4.5/jqm.collapsible", 'css!thirdparty/jquerymobile-1.4.5/jqm.collapsible.css']); - define("jqmpanel", ["thirdparty/jquerymobile-1.4.5/jqm.panel"], function () { - $.mobile.panel.prototype.options.classes.modalOpen = "largePanelModalOpen ui-panel-dismiss-open"; - $.mobile.panel.prototype.options.classes.panel = "largePanel ui-panel"; + define("jqmcheckbox", ["jqmicons", "thirdparty/jquerymobile-1.4.5/jqm.checkbox", 'css!thirdparty/jquerymobile-1.4.5/jqm.checkbox.css']); - Dashboard.importCss('thirdparty/jquerymobile-1.4.5/jqm.panel.css'); - return {}; - }); + define("jqmpanel", ["thirdparty/jquerymobile-1.4.5/jqm.panel", 'css!thirdparty/jquerymobile-1.4.5/jqm.panel.css']); define("hammer", ["bower_components/hammerjs/hammer.min"], function (Hammer) { return Hammer; @@ -2250,20 +2034,36 @@ var AppInfo = {}; define("fileupload", ["apiclient/fileupload"]); } + define("buttonenabled", ["components/buttonenabled"]); + var deps = []; if (!deviceId) { deps.push('cryptojs-sha1'); } - require(deps, function () { - $.extend(AppInfo, Dashboard.getAppInfo(appName, appVersion, deviceId, deviceName)); + if (!window.fetch) { + deps.push('bower_components/fetch/fetch'); + } - initAfterDependencies(deferred, capabilities); + deps.push('scripts/mediacontroller'); + deps.push('scripts/globalize'); + deps.push('apiclient/events'); + + deps.push('jQuery'); + + require(deps, function () { + + var baseInfo = Dashboard.getAppInfo(appName, appVersion, deviceId, deviceName); + for (var i in baseInfo) { + AppInfo[i] = baseInfo[i]; + } + + initAfterDependencies(promiseResolve, capabilities); }); } - function initAfterDependencies(deferred, capabilities) { + function initAfterDependencies(promiseResolve, capabilities) { var drawer = document.querySelector('.mainDrawerPanel'); drawer.classList.remove('mainDrawerPanelPreInit'); @@ -2276,21 +2076,44 @@ var AppInfo = {}; drawer.drawerWidth = drawerWidth + "px"; - if ($.browser.safari) { + if (browserInfo.safari) { drawer.disableEdgeSwipe = true; } var deps = []; - if (AppInfo.isNativeApp && $.browser.android) { - deps.push('cordova/android/logging'); + if (AppInfo.isNativeApp && browserInfo.android) { + require(['cordova/android/logging']); } + deps.push('scripts/librarybrowser'); deps.push('appstorage'); + deps.push('scripts/mediaplayer'); + deps.push('scripts/appsettings'); + deps.push('apiclient/apiclient'); + deps.push('apiclient/connectionmanager'); + deps.push('apiclient/deferred'); + deps.push('apiclient/credentials'); + deps.push('apiclient/md5'); + + deps.push('thirdparty/jquerymobile-1.4.5/jquery.mobile.custom.js'); require(deps, function () { - if (Dashboard.isRunningInCordova() && $.browser.android) { + // TODO: This needs to be deprecated, but it's used heavily + $.fn.checked = function (value) { + if (value === true || value === false) { + // Set the value of the checkbox + return $(this).each(function () { + this.checked = value; + }); + } else { + // Return check state + return this.length && this[0].checked; + } + }; + + if (Dashboard.isRunningInCordova() && browserInfo.android) { AppInfo.directPlayAudioContainers = "aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus".split(','); // TODO: This is going to exclude it from both playback and sync, so improve on this @@ -2300,7 +2123,7 @@ var AppInfo = {}; AppInfo.directPlayVideoContainers = "m4v,3gp,ts,mpegts,mov,xvid,vob,mkv,wmv,asf,ogm,ogv,m2v,avi,mpg,mpeg,mp4,webm".split(','); } - else if (Dashboard.isRunningInCordova() && $.browser.safari) { + else if (Dashboard.isRunningInCordova() && browserInfo.safari) { AppInfo.directPlayAudioContainers = "aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus".split(','); @@ -2311,18 +2134,12 @@ var AppInfo = {}; } capabilities.DeviceProfile = MediaPlayer.getDeviceProfile(Math.max(screen.height, screen.width)); - createConnectionManager(capabilities).done(function () { onConnectionManagerCreated(deferred); }); - //$(document.body).append('
'); - }); - } + var connectionManagerPromise = createConnectionManager(capabilities); - function onConnectionManagerCreated(deferred) { + Promise.all([Globalize.ensure(), connectionManagerPromise]).then(function () { - Globalize.ensure().done(function () { - document.title = Globalize.translateDocument(document.title, 'html'); - - $(function () { + document.title = Globalize.translateDocument(document.title, 'html'); var mainDrawerPanelContent = document.querySelector('.mainDrawerPanelContent'); @@ -2351,28 +2168,66 @@ var AppInfo = {}; depends.push('jqmcollapsible'); depends.push('jqmcontrolgroup'); depends.push('jqmcheckbox'); + depends.push('scripts/notifications'); } require(depends, function () { // Don't like having to use jQuery here, but it takes care of making sure that embedded script executes $(mainDrawerPanelContent).html(Globalize.translateDocument(newHtml, 'html')); - onAppReady(deferred); + onAppReady(promiseResolve); }); return; } - onAppReady(deferred); + onAppReady(promiseResolve); }); }); } - function onAppReady(deferred) { - onDocumentReady(); + function onAppReady(promiseResolve) { + + if (browserInfo.msie) { + require(['devices/ie/ie']); + } + + // Do these now to prevent a flash of content + if (AppInfo.isNativeApp && browserInfo.android) { + Dashboard.importCss('devices/android/android.css'); + } else if (AppInfo.isNativeApp && browserInfo.safari) { + Dashboard.importCss('devices/ios/ios.css'); + } else if (!browserInfo.android) { + Dashboard.importCss('devices/android/android.css'); + } + + loadTheme(); + + if (browserInfo.safari && browserInfo.mobile) { + initFastClick(); + } + + if (Dashboard.isRunningInCordova()) { + require(['cordova/connectsdk', 'scripts/registrationservices', 'cordova/back']); + + if (browserInfo.android) { + require(['cordova/android/androidcredentials', 'cordova/android/immersive', 'cordova/android/mediasession']); + } else { + require(['cordova/volume']); + } + + if (browserInfo.safari) { + require(['cordova/ios/orientation']); + } + + } else { + if (browserInfo.chrome) { + require(['scripts/chromecast']); + } + } var deps = []; - if (AppInfo.isNativeApp && $.browser.safari) { + if (AppInfo.isNativeApp && browserInfo.safari) { if (Dashboard.capabilities().SupportsSync) { deps.push('cordova/ios/backgroundfetch'); @@ -2380,27 +2235,51 @@ var AppInfo = {}; deps.push('cordova/ios/tabbar'); } - if (AppInfo.isNativeApp && $.browser.android) { - deps.push('cordova/android/newapp'); - } + + deps.push('scripts/search'); + deps.push('scripts/librarylist'); + deps.push('scripts/alphapicker'); + deps.push('thirdparty/jquery.unveil-custom.js'); + deps.push('scripts/playlistmanager'); + deps.push('scripts/sync'); + deps.push('scripts/backdrops'); + deps.push('scripts/librarymenu'); require(deps, function () { - Dashboard.initPromiseDone = true; + $.mobile.filterHtml = Dashboard.filterHtml; + $.mobile.initializePage(); - deferred.resolve(); + promiseResolve(); + + var postInitDependencies = []; + + if (navigator.webkitPersistentStorage) { + postInitDependencies.push('components/imagestore'); + } + else if (Dashboard.isRunningInCordova()) { + postInitDependencies.push('cordova/imagestore'); + } + + postInitDependencies.push('scripts/thememediaplayer'); + postInitDependencies.push('scripts/remotecontrol'); + require(postInitDependencies); + + Dashboard.importCss('css/notifications.css'); + Dashboard.importCss('css/chromecast.css'); }); - //require(['localsync']); + + if (AppInfo.enableNowPlayingBar) { + require(['scripts/nowplayingbar']); + } } function initCordovaWithDeviceId(deferred, deviceId) { - require(['cordova/imagestore']); - cordova.getAppVersion.getVersionNumber(function (appVersion) { var capablities = Dashboard.capabilities(); - var name = $.browser.android ? "Emby for Android" : ($.browser.safari ? "Emby for iOS" : "Emby Mobile"); + var name = browserInfo.android ? "Emby for Android Mobile" : (browserInfo.safari ? "Emby for iOS" : "Emby Mobile"); // Remove special characters var cleanDeviceName = device.model.replace(/[^\w\s]/gi, ''); @@ -2425,28 +2304,127 @@ var AppInfo = {}; }, false); } - var initDeferred = $.Deferred(); - Dashboard.initPromise = initDeferred.promise(); + function setBrowserInfo(isMobile) { - setAppInfo(); - setDocumentClasses(); + var uaMatch = function (ua) { + ua = ua.toLowerCase(); - $(document).on('WebComponentsReady', function () { - if (Dashboard.isRunningInCordova()) { - initCordova(initDeferred); - } else { - init(initDeferred, Dashboard.capabilities()); + var match = /(edge)[ \/]([\w.]+)/.exec(ua) || + /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(safari)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + var platform_match = /(ipad)/.exec(ua) || + /(iphone)/.exec(ua) || + /(android)/.exec(ua) || + []; + + var browser = match[1] || ""; + + if (ua.indexOf("windows phone") != -1 || ua.indexOf("iemobile") != -1) { + + // http://www.neowin.net/news/ie11-fakes-user-agent-to-fool-gmail-in-windows-phone-81-gdr1-update + browser = "msie"; + } + else if (ua.indexOf("like gecko") != -1 && ua.indexOf('webkit') == -1 && ua.indexOf('opera') == -1 && ua.indexOf('chrome') == -1 && ua.indexOf('safari') == -1) { + browser = "msie"; + } + + return { + browser: browser, + version: match[2] || "0", + platform: platform_match[0] || "" + }; + }; + + var userAgent = window.navigator.userAgent; + var matched = uaMatch(userAgent); + var browser = {}; + + if (matched.browser) { + browser[matched.browser] = true; + browser.version = matched.version; } + + if (matched.platform) { + browser[matched.platform] = true; + } + + if (!browser.chrome && !browser.msie && !browser.edge && !browser.opera && userAgent.toLowerCase().indexOf("webkit") != -1) { + browser.safari = true; + } + + if (isMobile.any) { + browser.mobile = true; + } + + browser.animate = document.documentElement.animate != null; + + window.browserInfo = browser; + } + + initRequire(); + + var initialDependencies = []; + + initialDependencies.push('isMobile'); + initialDependencies.push('apiclient/logger'); + initialDependencies.push('apiclient/store'); + initialDependencies.push('apiclient/device'); + initialDependencies.push('scripts/extensions'); + + var supportsNativeWebComponents = 'registerElement' in document && 'content' in document.createElement('template'); + + if (!supportsNativeWebComponents) { + initialDependencies.push('bower_components/webcomponentsjs/webcomponents-lite.min.js'); + } + + if (!window.Promise) { + initialDependencies.push('bower_components/native-promise-only/lib/npo.src'); + } + + require(initialDependencies, function (isMobile) { + + Dashboard.initPromise = new Promise(function (resolve, reject) { + + function onWebComponentsReady() { + + var link = document.createElement('link'); + link.rel = 'import'; + + link.onload = function () { + if (Dashboard.isRunningInCordova()) { + initCordova(resolve); + } else { + init(resolve, Dashboard.capabilities()); + } + }; + link.href = "vulcanize-out.html?v=" + window.dashboardVersion; + document.head.appendChild(link); + } + + setBrowserInfo(isMobile); + setAppInfo(); + setDocumentClasses(); + + if (supportsNativeWebComponents) { + onWebComponentsReady(); + } else { + document.addEventListener('WebComponentsReady', onWebComponentsReady); + } + }); }); })(); function pageClassOn(eventName, className, fn) { - $(document).on(eventName, function (e) { + document.addEventListener(eventName, function (e) { var target = e.target; - if (target.classList.contains(className)) { fn.call(target, e); } @@ -2455,10 +2433,9 @@ function pageClassOn(eventName, className, fn) { function pageIdOn(eventName, id, fn) { - $(document).on(eventName, function (e) { + document.addEventListener(eventName, function (e) { var target = e.target; - if (target.id == id) { fn.call(target, e); } @@ -2467,25 +2444,21 @@ function pageIdOn(eventName, id, fn) { pageClassOn('pagecreate', "page", function () { - var page = $(this); + var page = this; - var current = page.data('theme'); + var current = page.getAttribute('data-theme'); if (!current) { var newTheme; - if (page.hasClass('libraryPage')) { + if (page.classList.contains('libraryPage')) { newTheme = 'b'; } else { newTheme = 'a'; } - current = page.page("option", "theme"); - - if (current && current != newTheme) { - page.page("option", "theme", newTheme); - } + page.setAttribute("data-theme", newTheme); } }); @@ -2509,7 +2482,7 @@ pageClassOn('pageshow', "page", function () { page.classList.remove('ui-body-a'); } - if (currentTheme != 'a' && !$.browser.mobile) { + if (currentTheme != 'a' && !browserInfo.mobile) { document.body.classList.add('darkScrollbars'); } else { document.body.classList.remove('darkScrollbars'); @@ -2527,7 +2500,7 @@ pageClassOn('pageshow', "page", function () { Dashboard.ensureToolsMenu(page); - Dashboard.getCurrentUser().done(function (user) { + Dashboard.getCurrentUser().then(function (user) { if (!user.Policy.IsAdministrator) { Dashboard.logout(); @@ -2564,4 +2537,21 @@ pageClassOn('pageshow', "page", function () { }); -Dashboard.jQueryMobileInit(); \ No newline at end of file +window.addEventListener("beforeunload", function () { + + var apiClient = window.ApiClient; + + // Close the connection gracefully when possible + if (apiClient && apiClient.isWebSocketOpen()) { + + var localActivePlayers = MediaController.getPlayers().filter(function (p) { + + return p.isLocalPlayer && p.isPlaying(); + }); + + if (!localActivePlayers.length) { + Logger.log('Sending close web socket command'); + apiClient.closeWebSocket(); + } + } +}); \ No newline at end of file diff --git a/dashboard-ui/scripts/useredit.js b/dashboard-ui/scripts/useredit.js index 435f49092..76dff622e 100644 --- a/dashboard-ui/scripts/useredit.js +++ b/dashboard-ui/scripts/useredit.js @@ -68,7 +68,7 @@ type: "DELETE", url: linkUrl - }).done(function () { + }).then(function () { Dashboard.alert({ @@ -78,7 +78,7 @@ callback: actionCallback }); - }).fail(function () { + }, function () { Dashboard.alert({ @@ -99,7 +99,7 @@ }, dataType: 'json' - }).done(function (result) { + }).then(function (result) { var msgKey = result.IsPending ? 'MessagePendingEmbyAccountAdded' : 'MessageEmbyAccountAdded'; @@ -110,7 +110,8 @@ callback: actionCallback }); - }).fail(function () { + + }, function () { Dashboard.alert({ @@ -169,9 +170,9 @@ user.Policy.EnableSyncTranscoding = $('#chkEnableSyncTranscoding', page).checked(); user.Policy.EnablePublicSharing = $('#chkEnableSharing', page).checked(); - ApiClient.updateUser(user).done(function () { + ApiClient.updateUser(user).then(function () { - ApiClient.updateUserPolicy(user.Id, user.Policy).done(function () { + ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { onSaveComplete(page, user); }); @@ -183,7 +184,7 @@ Dashboard.showLoadingMsg(); - getUser().done(function (result) { + getUser().then(function (result) { saveUser(result, page); }); @@ -202,7 +203,7 @@ Dashboard.showLoadingMsg(); - getUser().done(function (user) { + getUser().then(function (user) { loadUser(page, user); });