diff --git a/dashboard-ui/css/materialize.css b/dashboard-ui/css/materialize.css index c74532bfb8..17bd28a40c 100644 --- a/dashboard-ui/css/materialize.css +++ b/dashboard-ui/css/materialize.css @@ -57,9 +57,9 @@ position: relative; } -.btn:not(.btnStatic), .btn-large:not(.btnStatic) { - cursor: pointer; -} + .btn:not(.btnStatic), .btn-large:not(.btnStatic) { + cursor: pointer; + } .btn-floating { -webkit-border-radius: 2px; @@ -119,7 +119,7 @@ } .btn { - padding: .6em 2em; + padding: .6em 1.6em .6em 2em; } .btn-large { @@ -191,7 +191,7 @@ display: inline-block; width: auto; margin-bottom: 0; - padding: .6em .5em .6em .5em!important; + padding: .6em .5em .6em .5em !important; } button.btn:not(.btn-inline), button.btn-large:not(.btn-inline) { @@ -219,9 +219,9 @@ button.btn:not(.btn-inline), button.btn-large:not(.btn-inline) { } .btnNoText { - padding: .6em .5em!important; + padding: .6em .5em !important; } .btnNoText { border-radius: 5px; -} \ No newline at end of file +} diff --git a/dashboard-ui/css/mediaplayer-video.css b/dashboard-ui/css/mediaplayer-video.css index 57bef94a58..6606cd7045 100644 --- a/dashboard-ui/css/mediaplayer-video.css +++ b/dashboard-ui/css/mediaplayer-video.css @@ -252,7 +252,7 @@ #videoPlayer .nowPlayingImage img { height: auto !important; max-width: 400px; - max-height: 300px; + max-height: 280px; } } diff --git a/dashboard-ui/mypreferencesdisplay.html b/dashboard-ui/mypreferencesdisplay.html index b8db74f553..738b300bd4 100644 --- a/dashboard-ui/mypreferencesdisplay.html +++ b/dashboard-ui/mypreferencesdisplay.html @@ -5,7 +5,7 @@ Emby -
+
${TabDisplay} ${TabPlayback} @@ -147,9 +147,6 @@ -
diff --git a/dashboard-ui/mypreferenceslanguages.html b/dashboard-ui/mypreferenceslanguages.html index 730edaa9d8..3f6c176a16 100644 --- a/dashboard-ui/mypreferenceslanguages.html +++ b/dashboard-ui/mypreferenceslanguages.html @@ -5,7 +5,7 @@ Emby -
+
${TabDisplay} ${TabPlayback} @@ -82,9 +82,6 @@ -
diff --git a/dashboard-ui/mypreferenceswebclient.html b/dashboard-ui/mypreferenceswebclient.html index c7f8007512..fc9aaac31f 100644 --- a/dashboard-ui/mypreferenceswebclient.html +++ b/dashboard-ui/mypreferenceswebclient.html @@ -5,7 +5,7 @@ Emby -
+
${TabDisplay} ${TabPlayback} @@ -150,6 +150,18 @@
+ +
+
+
+ ${LabelExternalPlayers} + + +
+ + +
+

@@ -180,17 +192,6 @@
${LabelEnableItemPreviewsHelp}
- -
-
-
- ${LabelExternalPlayers} - - -
- - -
@@ -206,9 +207,6 @@
-
\ No newline at end of file diff --git a/dashboard-ui/myprofile.html b/dashboard-ui/myprofile.html index 14a0166dbc..59f1804f40 100644 --- a/dashboard-ui/myprofile.html +++ b/dashboard-ui/myprofile.html @@ -4,7 +4,7 @@ Emby -
+
${TabDisplay} @@ -124,11 +124,6 @@
-
diff --git a/dashboard-ui/scripts/appsettings.js b/dashboard-ui/scripts/appsettings.js new file mode 100644 index 0000000000..945bbc16d1 --- /dev/null +++ b/dashboard-ui/scripts/appsettings.js @@ -0,0 +1,55 @@ +(function (window, store) { + + function update(key, val) { + store.setItem(key, val); + + Events.trigger(AppSettings, 'settingupdated', [key]); + } + + window.AppSettings = { + + maxStreamingBitrate: function (val) { + + if (val != null) { + update('preferredVideoBitrate', val); + } + + return parseInt(store.getItem('preferredVideoBitrate') || '') || 1500000; + }, + maxChromecastBitrate: function (val) { + + if (val != null) { + update('chromecastBitrate', val); + } + + return parseInt(store.getItem('chromecastBitrate') || '') || 3000000; + }, + enableExternalPlayers: function (val) { + + if (val != null) { + update('externalplayers', val.toString()); + } + + return store.getItem('externalplayers') == 'true'; + }, + enableItemPreviews: function (val) { + + if (val != null) { + update('enableItemPreviews', val.toString()); + } + + return store.getItem('enableItemPreviews') != 'false'; + }, + enableFullScreen: function (val) { + + if (val != null) { + update('enableFullScreen', val.toString()); + } + + return store.getItem('enableFullScreen') == 'true'; + } + + }; + + +})(window, window.appStorage); \ No newline at end of file diff --git a/dashboard-ui/scripts/backdrops.js b/dashboard-ui/scripts/backdrops.js index f4f96c9eb9..aa1702445e 100644 --- a/dashboard-ui/scripts/backdrops.js +++ b/dashboard-ui/scripts/backdrops.js @@ -98,7 +98,7 @@ } function setDefault(page) { - + var backdropContainer = $('.backdropContainer'); if (backdropContainer.length) { @@ -128,6 +128,10 @@ return false; } + if ($.browser.android && Dashboard.isRunningInCordova()) { + return true; + } + if ($.browser.mobile) { return false; } @@ -179,7 +183,7 @@ $(page).removeClass('backdropPage'); } } - + function setBackdropUrl(page, url) { if (url) { diff --git a/dashboard-ui/scripts/chromecast.js b/dashboard-ui/scripts/chromecast.js index c1891de592..586cf89f95 100644 --- a/dashboard-ui/scripts/chromecast.js +++ b/dashboard-ui/scripts/chromecast.js @@ -28,11 +28,11 @@ var PlayerName = 'Chromecast'; - //var applicationID = "2D4B1DA3"; - //var messageNamespace = 'urn:x-cast:com.connectsdk'; + var applicationID = "2D4B1DA3"; + var messageNamespace = 'urn:x-cast:com.connectsdk'; - var applicationID = "F4EB2E8E"; - var messageNamespace = 'urn:x-cast:com.google.cast.mediabrowser.v3'; + //var applicationID = "F4EB2E8E"; + //var messageNamespace = 'urn:x-cast:com.google.cast.mediabrowser.v3'; var CastPlayer = function () { diff --git a/dashboard-ui/scripts/indexpage.js b/dashboard-ui/scripts/indexpage.js index d6cdad118a..57d0e1b7de 100644 --- a/dashboard-ui/scripts/indexpage.js +++ b/dashboard-ui/scripts/indexpage.js @@ -631,7 +631,7 @@ takeTour(page, Dashboard.getCurrentUserId()); }); - }).on('pagebeforeshowready', "#indexPage", function () { + }).on('pageshowready', "#indexPage", function () { var page = this; diff --git a/dashboard-ui/scripts/mediacontroller.js b/dashboard-ui/scripts/mediacontroller.js index 169ce63731..0ece48d46d 100644 --- a/dashboard-ui/scripts/mediacontroller.js +++ b/dashboard-ui/scripts/mediacontroller.js @@ -130,6 +130,7 @@ triggerPlayerChange(player, targetInfo); }; + var currentPairingId = null; self.trySetActivePlayer = function (player, targetInfo) { if (typeof (player) === 'string') { @@ -142,6 +143,12 @@ throw new Error('null player'); } + if (currentPairingId == targetInfo.id) { + return; + } + + currentPairingId = targetInfo.id; + player.tryPair(targetInfo).done(function () { currentPlayer = player; diff --git a/dashboard-ui/scripts/mediaplayer-video.js b/dashboard-ui/scripts/mediaplayer-video.js index e1e904eb8d..a9554b6c4f 100644 --- a/dashboard-ui/scripts/mediaplayer-video.js +++ b/dashboard-ui/scripts/mediaplayer-video.js @@ -45,8 +45,8 @@ if (document.exitFullscreen) { document.exitFullscreen(); - } else if (document.mozExitFullScreen) { - document.mozExitFullScreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { @@ -396,7 +396,7 @@ var chapterIndex = 0; html += item.Chapters.map(function (c) { - var width = 360; + var width = 320; var chapterHtml = ''; chapterHtml += '
'; chapterHtml += '
'; @@ -445,11 +445,12 @@ var personHtml = '
'; var imgUrl; + var height = 160; if (cast.PrimaryImageTag) { imgUrl = ApiClient.getScaledImageUrl(cast.Id, { - height: 160, + height: height, tag: cast.PrimaryImageTag, type: "primary", minScale: 2 @@ -460,7 +461,7 @@ imgUrl = "css/images/items/list/person.png"; } - personHtml += '
'; + personHtml += '
'; @@ -623,7 +624,7 @@ idleState = true; $('.hiddenOnIdle').addClass("inactive"); $('#videoPlayer').addClass('idlePlayer'); - }, 5000); + }, 4000); } function updateVolumeButtons(vol) { @@ -1317,10 +1318,10 @@ }; self.updatePlaylistUi = function () { - var index = self.currentPlaylistIndex(null), - length = self.playlist.length, - requiresNativeControls = !self.enableCustomVideoControls(), - controls = $(requiresNativeControls ? '.videoAdvancedControls' : '.videoControls'); + var index = self.currentPlaylistIndex(null); + var length = self.playlist.length; + var requiresNativeControls = !self.enableCustomVideoControls(); + var controls = $(requiresNativeControls ? '.videoAdvancedControls' : '.videoControls'); if (length < 2) { $('.videoTrackControl').hide(); diff --git a/dashboard-ui/scripts/mypreferencescommon.js b/dashboard-ui/scripts/mypreferencescommon.js new file mode 100644 index 0000000000..15d49f334d --- /dev/null +++ b/dashboard-ui/scripts/mypreferencescommon.js @@ -0,0 +1,11 @@ +$(document).on('pageshowready', ".userPreferencesPage", function () { + + var page = this; + + var userId = getParameterByName('userId') || Dashboard.getCurrentUserId(); + + $('.lnkDisplayPreferences', page).attr('href', 'mypreferencesdisplay.html?userId=' + userId); + $('.lnkLanguagePreferences', page).attr('href', 'mypreferenceslanguages.html?userId=' + userId); + $('.lnkWebClientPreferences', page).attr('href', 'mypreferenceswebclient.html?userId=' + userId); + $('.lnkMyProfile', page).attr('href', 'myprofile.html?userId=' + userId); +}); \ No newline at end of file diff --git a/dashboard-ui/scripts/mypreferencesdisplay.js b/dashboard-ui/scripts/mypreferencesdisplay.js index bb213c2dc8..f0a6c5ecec 100644 --- a/dashboard-ui/scripts/mypreferencesdisplay.js +++ b/dashboard-ui/scripts/mypreferencesdisplay.js @@ -257,10 +257,9 @@ // Disable default form submission return false; - } - $(document).on('pageinit', "#displayPreferencesPage", function () { + $(document).on('pageinitdepends', "#displayPreferencesPage", function () { var page = this; @@ -295,7 +294,9 @@ ul.listview('destroy').listview({}); }); - }).on('pageshow', "#displayPreferencesPage", function () { + $('.displayPreferencesForm').off('submit', onSubmit).on('submit', onSubmit); + + }).on('pageshowready', "#displayPreferencesPage", function () { var page = this; @@ -308,21 +309,6 @@ loadForm(page, user); }); - - }).on('pageshow', ".userPreferencesPage", function () { - - var page = this; - - var userId = getParameterByName('userId') || Dashboard.getCurrentUserId(); - - $('.lnkDisplayPreferences', page).attr('href', 'mypreferencesdisplay.html?userId=' + userId); - $('.lnkLanguagePreferences', page).attr('href', 'mypreferenceslanguages.html?userId=' + userId); - $('.lnkWebClientPreferences', page).attr('href', 'mypreferenceswebclient.html?userId=' + userId); - $('.lnkMyProfile', page).attr('href', 'myprofile.html?userId=' + userId); }); - window.DisplayPreferencesPage = { - onSubmit: onSubmit - }; - })(jQuery, window, document); \ No newline at end of file diff --git a/dashboard-ui/scripts/mypreferenceslanguages.js b/dashboard-ui/scripts/mypreferenceslanguages.js index b257965ccc..2e0f6d7e86 100644 --- a/dashboard-ui/scripts/mypreferenceslanguages.js +++ b/dashboard-ui/scripts/mypreferenceslanguages.js @@ -92,10 +92,9 @@ // Disable default form submission return false; - } - $(document).on('pageinit', "#languagePreferencesPage", function () { + $(document).on('pageinitdepends', "#languagePreferencesPage", function () { var page = this; @@ -105,15 +104,14 @@ $('.subtitles' + this.value + 'Help', page).show(); }); - }).on('pageshow', "#languagePreferencesPage", function () { + $('.languagePreferencesForm').off('submit', onSubmit).on('submit', onSubmit); + + + }).on('pageshowready', "#languagePreferencesPage", function () { var page = this; loadPage(page); }); - window.LanguagePreferencesPage = { - onSubmit: onSubmit - }; - })(jQuery, window, document); \ No newline at end of file diff --git a/dashboard-ui/scripts/mypreferenceswebclient.js b/dashboard-ui/scripts/mypreferenceswebclient.js index fd7c354ba5..a08028657e 100644 --- a/dashboard-ui/scripts/mypreferenceswebclient.js +++ b/dashboard-ui/scripts/mypreferenceswebclient.js @@ -65,7 +65,13 @@ return false; } - $(document).on('pageshowready', "#webClientPreferencesPage", function () { + $(document).on('pageinitdepends', "#webClientPreferencesPage", function () { + + var page = this; + + $('.webClientPreferencesForm', page).off('submit', onSubmit).on('submit', onSubmit); + + }).on('pageshowready', "#webClientPreferencesPage", function () { var page = this; @@ -96,50 +102,4 @@ } }); - window.WebClientPreferencesPage = { - onSubmit: onSubmit - }; - -})(jQuery, window, document); - -(function (window, store) { - - window.AppSettings = { - - maxStreamingBitrate: function (val) { - - if (val != null) { - store.setItem('preferredVideoBitrate', val); - } - - return parseInt(store.getItem('preferredVideoBitrate') || '') || 1500000; - }, - maxChromecastBitrate: function (val) { - - if (val != null) { - store.setItem('chromecastBitrate', val); - } - - return parseInt(store.getItem('chromecastBitrate') || '') || 3000000; - }, - enableExternalPlayers: function (val) { - - if (val != null) { - store.setItem('externalplayers', val.toString()); - } - - return store.getItem('externalplayers') == 'true'; - }, - enableItemPreviews: function (val) { - - if (val != null) { - store.setItem('enableItemPreviews', val.toString()); - } - - return store.getItem('enableItemPreviews') != 'false'; - } - - }; - - -})(window, window.appStorage); \ No newline at end of file +})(jQuery, window, document); \ No newline at end of file diff --git a/dashboard-ui/scripts/myprofile.js b/dashboard-ui/scripts/myprofile.js index 06570fc753..1f66052383 100644 --- a/dashboard-ui/scripts/myprofile.js +++ b/dashboard-ui/scripts/myprofile.js @@ -181,7 +181,7 @@ window.MyProfilePage = new myProfilePage(); - $(document).on('pageinit', "#userImagePage", function () { + $(document).on('pageinitdepends', "#userImagePage", function () { var page = this; @@ -204,6 +204,9 @@ }); }); + + $('.newImageForm').off('submit', MyProfilePage.onImageSubmit).on('submit', MyProfilePage.onImageSubmit); + }); @@ -316,7 +319,7 @@ Dashboard.showError(Globalize.translate('PasswordMatchError')); } else { - + Dashboard.showLoadingMsg(); savePassword(page); } @@ -403,7 +406,14 @@ window.UpdatePasswordPage = new updatePasswordPage(); - $(document).on('pageshow', ".userPasswordPage", function () { + $(document).on('pageinitdepends', ".userPasswordPage", function () { + + var page = this; + + $('.updatePasswordForm').off('submit', UpdatePasswordPage.onSubmit).on('submit', UpdatePasswordPage.onSubmit); + $('.localAccessForm').off('submit', UpdatePasswordPage.onLocalAccessSubmit).on('submit', UpdatePasswordPage.onLocalAccessSubmit); + + }).on('pageshowready', ".userPasswordPage", function () { var page = this; diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index 8e4d276494..354e39bb9b 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -640,6 +640,11 @@ var Dashboard = { html += '
'; + if (AppInfo.supportsFullScreen) { + var checkedHtml = AppSettings.enableFullScreen() ? ' checked="checked"' : ''; + html += '

'; + } + html += '

'; if (Dashboard.isConnectMode()) { @@ -1540,9 +1545,13 @@ var AppInfo = {}; AppInfo.enableAppStorePolicy = isCordova; - if ($.browser.safari) { + var isSafari = $.browser.safari; + var isAndroid = $.browser.android; + var isMobile = $.browser.mobile; - if ($.browser.mobile) { + if (isSafari) { + + if (isMobile) { AppInfo.hasLowImageBandwidth = true; AppInfo.forcedImageFormat = 'jpg'; } @@ -1584,15 +1593,16 @@ var AppInfo = {}; AppInfo.enableFooterNotifications = true; AppInfo.enableSupporterMembership = true; - if (!$.browser.android && !$.browser.ipad && !$.browser.iphone) { + if (!isAndroid && !isSafari) { AppInfo.enableAppLayouts = true; } } AppInfo.enableUserImage = true; - AppInfo.hasPhysicalVolumeButtons = isCordova || $.browser.mobile; + AppInfo.hasPhysicalVolumeButtons = isCordova || isMobile; - AppInfo.enableBackButton = ($.browser.safari && window.navigator.standalone) || (isCordova && $.browser.safari); + AppInfo.enableBackButton = (isSafari && window.navigator.standalone) || (isCordova && isSafari); + AppInfo.supportsFullScreen = isCordova && isAndroid; } function initializeApiClient(apiClient) { @@ -1829,11 +1839,16 @@ var AppInfo = {}; }); if (Dashboard.isRunningInCordova()) { - requirejs(['thirdparty/cordova/connectsdk', 'thirdparty/cordova/remotecontrols', 'scripts/registrationservices']); + requirejs(['thirdparty/cordova/connectsdk', 'scripts/registrationservices']); if ($.browser.android) { requirejs(['thirdparty/cordova/android/immersive']); } + + if ($.browser.safari) { + requirejs(['thirdparty/cordova/remotecontrols']); + } + } else { if ($.browser.chrome) { requirejs(['scripts/chromecast']); diff --git a/dashboard-ui/scripts/sync.js b/dashboard-ui/scripts/sync.js index 1a988b6a13..3018d62af4 100644 --- a/dashboard-ui/scripts/sync.js +++ b/dashboard-ui/scripts/sync.js @@ -346,10 +346,6 @@ function isAvailable(item, user) { - if (Dashboard.isRunningInCordova()) { - return false; - } - return item.SupportsSync; } diff --git a/dashboard-ui/thirdparty/apiclient/apiclient.js b/dashboard-ui/thirdparty/apiclient/apiclient.js index e32bd37c73..ef0474b89f 100644 --- a/dashboard-ui/thirdparty/apiclient/apiclient.js +++ b/dashboard-ui/thirdparty/apiclient/apiclient.js @@ -148,11 +148,14 @@ } if (includeAuthorization !== false) { + + var currentServerInfo = self.serverInfo(); + if (clientName) { var auth = 'MediaBrowser Client="' + clientName + '", Device="' + deviceName + '", DeviceId="' + deviceId + '", Version="' + applicationVersion + '"'; - var userId = serverInfo.UserId; + var userId = currentServerInfo.UserId; if (userId) { auth += ', UserId="' + userId + '"'; @@ -163,7 +166,7 @@ }; } - var accessToken = serverInfo.AccessToken; + var accessToken = currentServerInfo.AccessToken; if (accessToken) { request.headers['X-MediaBrowser-Token'] = accessToken; @@ -184,10 +187,12 @@ var newConnectionMode; - if (connectionMode == MediaBrowser.ConnectionMode.Local && serverInfo.RemoteAddress) { + var currentServerInfo = self.serverInfo(); + + if (connectionMode == MediaBrowser.ConnectionMode.Local && currentServerInfo.RemoteAddress) { newConnectionMode = MediaBrowser.ConnectionMode.Remote; } - else if (connectionMode == MediaBrowser.ConnectionMode.Remote && serverInfo.LocalAddress) { + else if (connectionMode == MediaBrowser.ConnectionMode.Remote && currentServerInfo.LocalAddress) { newConnectionMode = MediaBrowser.ConnectionMode.Local; } else { @@ -199,9 +204,7 @@ function tryReconnectInternal(deferred, connectionMode, currentRetryCount) { - var url = connectionMode == MediaBrowser.ConnectionMode.Local ? - self.serverInfo().LocalAddress : - self.serverInfo().RemoteAddress; + var url = MediaBrowser.ServerInfo.getServerAddress(self.serverInfo(), connectionMode); logger.log("Attempting reconnection to " + url); @@ -258,9 +261,7 @@ if (replaceUrl) { - var baseUrl = self.connectionMode == MediaBrowser.ConnectionMode.Local ? - self.serverInfo().LocalAddress : - self.serverInfo().RemoteAddress; + var baseUrl = MediaBrowser.ServerInfo.getServerAddress(self.serverInfo(), self.connectionMode); request.url = replaceServerAddress(request.url, baseUrl); } @@ -379,7 +380,7 @@ self.openWebSocket = function () { - var accessToken = serverInfo.AccessToken; + var accessToken = self.serverInfo().AccessToken; if (!accessToken) { throw new Error("Cannot open web socket without access token."); @@ -578,7 +579,7 @@ self.setAuthenticationInfo(null, null); }; - if (serverInfo.AccessToken) { + if (self.serverInfo().AccessToken) { var url = self.getUrl("Sessions/Logout"); return self.ajax({ diff --git a/dashboard-ui/thirdparty/apiclient/connectionmanager.js b/dashboard-ui/thirdparty/apiclient/connectionmanager.js index e27d464838..edf8cf4f75 100644 --- a/dashboard-ui/thirdparty/apiclient/connectionmanager.js +++ b/dashboard-ui/thirdparty/apiclient/connectionmanager.js @@ -176,7 +176,7 @@ if (!apiClient) { - var url = self.getServerAddress(server, connectionMode); + var url = MediaBrowser.ServerInfo.getServerAddress(server, connectionMode); apiClient = new MediaBrowser.ApiClient(logger, url, appName, appVersion, deviceName, deviceId); @@ -339,7 +339,7 @@ throw new Error("credentials.ConnectUserId cannot be null"); } - var url = self.getServerAddress(server, connectionMode); + var url = MediaBrowser.ServerInfo.getServerAddress(server, connectionMode); url += "/Connect/Exchange?format=json&ConnectUserId=" + credentials.ConnectUserId; @@ -367,7 +367,7 @@ var deferred = DeferredBuilder.Deferred(); - var url = self.getServerAddress(server, connectionMode); + var url = MediaBrowser.ServerInfo.getServerAddress(server, connectionMode); AjaxApi.ajax({ @@ -663,7 +663,7 @@ function findServers() { var deferred = DeferredBuilder.Deferred(); - ServerDiscovery.findServers(2000).done(function (foundServers) { + ServerDiscovery.findServers(2500).done(function (foundServers) { var servers = foundServers.map(function (foundServer) { @@ -710,26 +710,15 @@ logger.log('Begin connect'); var deferred = DeferredBuilder.Deferred(); - var isResolved = false; - if (capabilities.SupportsOfflineAccess) { - if (!NetworkStatus.isNetworkAvailable()) { + self.getAvailableServers().done(function (servers) { - deferred.resolveWith(null, [self.getOffineResult()]); - isResolved = true; - } - } + self.connectToServers(servers).done(function (result) { - if (!isResolved) { - self.getAvailableServers().done(function (servers) { + deferred.resolveWith(null, [result]); - self.connectToServers(servers).done(function (result) { - - deferred.resolveWith(null, [result]); - - }); }); - } + }); return deferred.promise(); }; @@ -813,8 +802,7 @@ if (tests.indexOf(MediaBrowser.ConnectionMode.Local) == -1) { tests.push(MediaBrowser.ConnectionMode.Local); } if (tests.indexOf(MediaBrowser.ConnectionMode.Remote) == -1) { tests.push(MediaBrowser.ConnectionMode.Remote); } - var isLocalNetworkAvailable = NetworkStatus.isAnyLocalNetworkAvailable(); - var sendWakeOnLan = server.WakeOnLanInfos && server.WakeOnLanInfos.length && isLocalNetworkAvailable; + var sendWakeOnLan = server.WakeOnLanInfos && server.WakeOnLanInfos.length; if (sendWakeOnLan) { beginWakeServer(server); @@ -822,7 +810,7 @@ var wakeOnLanSendTime = new Date().getTime(); - testNextConnectionMode(tests, 0, isLocalNetworkAvailable, server, wakeOnLanSendTime, options, deferred); + testNextConnectionMode(tests, 0, server, wakeOnLanSendTime, options, deferred); return deferred.promise(); }; @@ -832,7 +820,7 @@ return (str1 || '').toLowerCase() == (str2 || '').toLowerCase(); } - function testNextConnectionMode(tests, index, isLocalNetworkAvailable, server, wakeOnLanSendTime, options, deferred) { + function testNextConnectionMode(tests, index, server, wakeOnLanSendTime, options, deferred) { if (index >= tests.length) { @@ -842,16 +830,13 @@ } var mode = tests[index]; - var address = self.getServerAddress(server, mode); + var address = MediaBrowser.ServerInfo.getServerAddress(server, mode); var enableRetry = false; var skipTest = false; var timeout = defaultTimeout; if (mode == MediaBrowser.ConnectionMode.Local) { - if (!isLocalNetworkAvailable) { - skipTest = true; - } enableRetry = true; timeout = 5000; } @@ -865,7 +850,7 @@ } if (skipTest || !address) { - testNextConnectionMode(tests, index + 1, isLocalNetworkAvailable, server, wakeOnLanSendTime, options, deferred); + testNextConnectionMode(tests, index + 1, server, wakeOnLanSendTime, options, deferred); return; } @@ -886,10 +871,10 @@ // TODO: Implement delay and retry - testNextConnectionMode(tests, index + 1, isLocalNetworkAvailable, server, wakeOnLanSendTime, options, deferred); + testNextConnectionMode(tests, index + 1, server, wakeOnLanSendTime, options, deferred); } else { - testNextConnectionMode(tests, index + 1, isLocalNetworkAvailable, server, wakeOnLanSendTime, options, deferred); + testNextConnectionMode(tests, index + 1, server, wakeOnLanSendTime, options, deferred); } }); @@ -949,7 +934,7 @@ MediaBrowser.ConnectionState.ServerSignIn; result.Servers.push(server); - result.ApiClient.enableAutomaticNetworking(server, connectionMode, self.getServerAddress(server, connectionMode)); + result.ApiClient.enableAutomaticNetworking(server, connectionMode, MediaBrowser.ServerInfo.getServerAddress(server, connectionMode)); if (result.State == MediaBrowser.ConnectionState.SignedIn) { afterConnected(result.ApiClient, options); @@ -960,20 +945,6 @@ Events.trigger(self, 'connected', [result]); } - self.getServerAddress = function (server, mode) { - - switch (mode) { - case MediaBrowser.ConnectionMode.Local: - return server.LocalAddress; - case MediaBrowser.ConnectionMode.Manual: - return server.ManualAddress; - case MediaBrowser.ConnectionMode.Remote: - return server.RemoteAddress; - default: - return server.ManualAddress || server.LocalAddress || server.RemoteAddress; - } - }; - function normalizeAddress(address) { if (address.toLowerCase().indexOf('http') != 0) { diff --git a/dashboard-ui/thirdparty/apiclient/credentials.js b/dashboard-ui/thirdparty/apiclient/credentials.js index e459831fe0..55a9653a29 100644 --- a/dashboard-ui/thirdparty/apiclient/credentials.js +++ b/dashboard-ui/thirdparty/apiclient/credentials.js @@ -94,4 +94,21 @@ }; }; + globalScope.MediaBrowser.ServerInfo = { + + getServerAddress: function (server, mode) { + + switch (mode) { + case MediaBrowser.ConnectionMode.Local: + return server.LocalAddress; + case MediaBrowser.ConnectionMode.Manual: + return server.ManualAddress; + case MediaBrowser.ConnectionMode.Remote: + return server.RemoteAddress; + default: + return server.ManualAddress || server.LocalAddress || server.RemoteAddress; + } + } + }; + })(window, window.JSON); \ No newline at end of file diff --git a/dashboard-ui/thirdparty/cordova/android/immersive.js b/dashboard-ui/thirdparty/cordova/android/immersive.js index 4b072cc70a..b0c62a3a4c 100644 --- a/dashboard-ui/thirdparty/cordova/android/immersive.js +++ b/dashboard-ui/thirdparty/cordova/android/immersive.js @@ -12,23 +12,97 @@ //AndroidFullScreen.isSupported(); //// Is immersive mode supported? - //AndroidFullScreen.isImmersiveModeSupported(successFunction, errorFunction); + //AndroidFullScreen.isImmersiveModeSupported(onSuccess, onError); //// The width of the screen in immersive mode - //AndroidFullScreen.immersiveWidth(trace, errorFunction); + //AndroidFullScreen.immersiveWidth(trace, onError); //// The height of the screen in immersive mode - //AndroidFullScreen.immersiveHeight(trace, errorFunction); + //AndroidFullScreen.immersiveHeight(trace, onError); //// Hide system UI until user interacts - //AndroidFullScreen.leanMode(successFunction, errorFunction); + //AndroidFullScreen.leanMode(onSuccess, onError); //// Show system UI - //AndroidFullScreen.showSystemUI(successFunction, errorFunction); + //AndroidFullScreen.showSystemUI(onSuccess, onError); //// Extend your app underneath the system UI (Android 4.4+ only) - //AndroidFullScreen.showUnderSystemUI(successFunction, errorFunction); + //AndroidFullScreen.showUnderSystemUI(onSuccess, onError); //// Hide system UI and keep it hidden (Android 4.4+ only) - //AndroidFullScreen.immersiveMode(successFunction, errorFunction); + //AndroidFullScreen.immersiveMode(onSuccess, onError); + + var currentPlayer; + + function onPlaybackStart(e, state) { + + var player = this; + + if (player.isLocalPlayer && state.NowPlayingItem && state.NowPlayingItem.MediaType == 'Video') { + AndroidFullScreen.immersiveMode(onSuccess, onError); + } + } + + function onPlaybackStopped(e, state) { + + var player = this; + + if (player.isLocalPlayer && state.NowPlayingItem && state.NowPlayingItem.MediaType == 'Video') { + AndroidFullScreen.showSystemUI(onSuccess, onError); + } + } + + function bindToPlayer(player) { + + releaseCurrentPlayer(); + + currentPlayer = player; + + if (!player.isLocalPlayer) { + return; + } + + $(player).on('playbackstart.fullscreen', onPlaybackStart) + .on('playbackstop.fullscreen', onPlaybackStopped); + } + + function releaseCurrentPlayer() { + + if (currentPlayer) { + + $(currentPlayer).off('.fullscreen'); + } + } + + function updateFromSetting(leaveFullScreen) { + + if (AppSettings.enableFullScreen()) { + AndroidFullScreen.immersiveMode(onSuccess, onError); + } + else if (leaveFullScreen) { + AndroidFullScreen.showSystemUI(onSuccess, onError); + } + } + + Dashboard.ready(function () { + + console.log('binding fullscreen to MediaController'); + + $(MediaController).on('playerchange', function () { + + bindToPlayer(MediaController.getCurrentPlayer()); + }); + + bindToPlayer(MediaController.getCurrentPlayer()); + + updateFromSetting(false); + + $(AppSettings).on('settingupdated', function (e, key) { + + if (key == 'enableFullScreen') { + updateFromSetting(true); + } + }); + }); + })(); \ No newline at end of file diff --git a/dashboard-ui/thirdparty/cordova/chromecast.js b/dashboard-ui/thirdparty/cordova/chromecast.js index 253d830bb1..e5962880f3 100644 --- a/dashboard-ui/thirdparty/cordova/chromecast.js +++ b/dashboard-ui/thirdparty/cordova/chromecast.js @@ -6,6 +6,7 @@ var currentPairedDeviceId; var currentDeviceFriendlyName; var currentWebAppSession; + var currentDevice; function chromecastPlayer() { @@ -312,6 +313,10 @@ }; self.seek = function (position) { + + position = parseInt(position); + position = position / 10000000; + sendMessageToDevice({ options: { position: position @@ -441,18 +446,38 @@ } } - function onSessionConnected(device, session) { + function handleMessage(message) { + // message could be either a string or an object + if (typeof message === 'string') { + onMessage(JSON.parse(message)); + } else { + onMessage(message); + } + } + + function handleSessionDisconnect() { + console.log("session disconnected"); + + cleanupSession(); + MediaController.removeActivePlayer(PlayerName); + } + + function setupWebAppSession(device, session) { // hold on to a reference currentWebAppSession = session.acquire(); - session.connect().success(function () { + currentWebAppSession.on('message', handleMessage); + currentWebAppSession.on('disconnect', handleSessionDisconnect); + + currentWebAppSession.connect().success(function () { console.log('session.connect succeeded'); MediaController.setActivePlayer(PlayerName, convertDeviceToTarget(device)); currentDeviceFriendlyName = device.getFriendlyName(); currentPairedDeviceId = device.getId(); + currentDevice = device; $(castPlayer).trigger('connect'); @@ -460,34 +485,32 @@ options: {}, command: 'Identify' }); - }); - - session.on('message', function (message) { - // message could be either a string or an object - if (typeof message === 'string') { - onMessage(JSON.parse(message)); - } else { - onMessage(message); - } - }); - - session.on('disconnect', function () { - - console.log("session disconnected"); - - if (currentPairedDeviceId == device.getId()) { - onDisconnected(); - MediaController.removeActivePlayer(PlayerName); - } - - }); + }).error(handleSessionError); } - function onDisconnected() { + function handleSessionError() { + cleanupSession(); + } + + function cleanupSession() { + + var session = currentWebAppSession; + + if (session) { + // Clean up listeners + session.off("message"); + session.off("disconnect"); + + // Release session to free up memory + session.disconnect(); + session.release(); + } + currentWebAppSession = null; currentPairedDeviceId = null; currentDeviceFriendlyName = null; + currentDevice = null; } function launchWebApp(device) { @@ -497,7 +520,7 @@ device.getWebAppLauncher().joinWebApp(ApplicationID).success(function (session) { console.log('joinWebApp success. calling onSessionConnected'); - onSessionConnected(device, session); + setupWebAppSession(device, session); }).error(function (err) { @@ -506,7 +529,7 @@ device.getWebAppLauncher().launchWebApp(ApplicationID).success(function (session) { console.log('launchWebApp success. calling onSessionConnected'); - onSessionConnected(device, session); + setupWebAppSession(device, session); }).error(function (err1) { @@ -533,46 +556,18 @@ }, 0); } - var boundHandlers = []; - self.tryPair = function (target) { var deferred = $.Deferred(); - var manager = ConnectSDK.discoveryManager; - - var device = manager.getDeviceList().filter(function (d) { + var device = ConnectSDK.discoveryManager.getDeviceList().filter(function (d) { return d.getId() == target.id; })[0]; if (device) { - var deviceId = device.getId(); - currentPairingDeviceId = deviceId; - - console.log('Will attempt to connect to Chromecast'); - - if (device.isReady()) { - console.log('Device is already ready, calling onDeviceReady'); - onDeviceReady(device); - } else { - - console.log('Binding device ready handler'); - - if (boundHandlers.indexOf(deviceId) == -1) { - - boundHandlers.push(deviceId); - device.on("ready", function () { - console.log('device.ready fired'); - onDeviceReady(device); - }); - } - - console.log('Calling device.connect'); - device.connect(); - } - //deferred.resolve(); + self.tryPairWithDevice(device, deferred); } else { deferred.reject(); @@ -581,6 +576,34 @@ return deferred.promise(); }; + self.tryPairWithDevice = function (device, deferred) { + + var deviceId = device.getId(); + currentPairingDeviceId = deviceId; + + console.log('Will attempt to connect to Chromecast'); + + if (device.isReady()) { + console.log('Device is already ready, calling onDeviceReady'); + onDeviceReady(device); + } else { + + console.log('Binding device ready handler'); + + device.on("ready", function () { + console.log('device.ready fired'); + onDeviceReady(device); + }); + + device.on("disconnect", function () { + device.off("ready"); + }); + + console.log('Calling device.connect'); + device.connect(); + } + }; + $(MediaController).on('playerchange', function (e, newPlayer, newTarget) { if (currentPairedDeviceId) { @@ -588,7 +611,6 @@ if (currentWebAppSession) { console.log('Disconnecting from chromecast'); currentWebAppSession.disconnect(); - onDisconnected(); } } } diff --git a/dashboard-ui/thirdparty/cordova/registrationservices.js b/dashboard-ui/thirdparty/cordova/registrationservices.js index ff52699762..20d3001fa4 100644 --- a/dashboard-ui/thirdparty/cordova/registrationservices.js +++ b/dashboard-ui/thirdparty/cordova/registrationservices.js @@ -2,6 +2,8 @@ var updatedProducts = []; + var unlockAlias = "premium features"; + function updateProductInfo(p) { updatedProducts = updatedProducts.filter(function (r) { @@ -11,6 +13,26 @@ updatedProducts.push(p); } + function getProduct(alias) { + var products = updatedProducts.filter(function (r) { + return r.alias == alias; + }); + + return products.length ? products[0] : null; + } + + function hasPurchased(alias) { + var product = getProduct(alias); + + return product != null && product.owned; + } + + function isPurchaseAvailable(alias) { + var product = getProduct(alias); + + return product != null && product.canPurchase; + } + function isAndroid() { var platform = (device.platform || '').toLowerCase(); @@ -29,7 +51,7 @@ validateFeature({ id: 'appunlock', - alias: "premium features" + alias: unlockAlias }, deferred); } @@ -45,7 +67,7 @@ validateFeature({ id: 'premiumunlock', - alias: "premium features" + alias: unlockAlias }, deferred); } @@ -61,7 +83,7 @@ validateFeature({ id: 'premiumunlock', - alias: "premium features" + alias: unlockAlias }, deferred); } @@ -78,24 +100,20 @@ function validateFeature(info, deferred) { - var products = updatedProducts.filter(function (r) { - return r.alias == info.alias; - }); - - var product = products.length ? products[0] : null; - - if (product && product.owned) { + if (hasPurchased(info.alias)) { deferred.resolve(); return; } var productInfo = { enableSupporterUnlock: isAndroid(), - enableAppUnlock: product != null && product.canPurchase + enableAppUnlock: isPurchaseAvailable(info.alias) }; + var prefix = isAndroid() ? 'android' : 'ios'; + // Get supporter status - getRegistrationInfo('appunlock', productInfo.enableSupporterUnlock).done(function (registrationInfo) { + getRegistrationInfo(prefix + 'appunlock', productInfo.enableSupporterUnlock).done(function (registrationInfo) { if (registrationInfo.IsRegistered) { deferred.resolve(); @@ -267,38 +285,32 @@ function initializeStore() { + if (isAndroid()) { + return; + } // Let's set a pretty high verbosity level, so that we see a lot of stuff // in the console (reassuring us that something is happening). store.verbosity = store.INFO; store.validator = validateProduct; - if (isAndroid) { - store.register({ - id: "premiumunlock", - alias: "premium features", - type: store.NON_CONSUMABLE - }); - } else { - - // iOS - store.register({ - id: "appunlock", - alias: "premium features", - type: store.NON_CONSUMABLE - }); - } + // iOS + store.register({ + id: "appunlock", + alias: unlockAlias, + type: store.NON_CONSUMABLE + }); // When purchase of the full version is approved, // show some logs and finish the transaction. - store.when("premium feautres").approved(function (order) { + store.when(unlockAlias).approved(function (order) { log('You just unlocked the FULL VERSION!'); order.finish(); }); // The play button can only be accessed when the user // owns the full version. - store.when("premium feautres").updated(function (product) { + store.when(unlockAlias).updated(function (product) { updateProductInfo(product); }); @@ -309,11 +321,11 @@ store.ready(function () { console.log("Store ready"); - - // After we've done our setup, we tell the store to do - // it's first refresh. Nothing will happen if we do not call store.refresh() - store.refresh(); }); + + // After we've done our setup, we tell the store to do + // it's first refresh. Nothing will happen if we do not call store.refresh() + store.refresh(); } // We must wait for the "deviceready" event to fire diff --git a/dashboard-ui/thirdparty/cordova/serverdiscovery.js b/dashboard-ui/thirdparty/cordova/serverdiscovery.js index 4f7581a71f..2b57f7b4fa 100644 --- a/dashboard-ui/thirdparty/cordova/serverdiscovery.js +++ b/dashboard-ui/thirdparty/cordova/serverdiscovery.js @@ -48,25 +48,23 @@ return deferred.promise(); } - var isTimedOut = false; var timeout; var socketId; + function onTimerExpired() { + deferred.resolveWith(null, [servers]); + + if (socketId) { + chrome.sockets.udp.onReceive.removeListener(onReceive); + closeSocket(socketId); + } + } + function startTimer() { console.log('starting udp receive timer with timeout ms: ' + timeoutMs); - timeout = setTimeout(function () { - - isTimedOut = true; - deferred.resolveWith(null, [servers]); - - if (socketId) { - chrome.sockets.udp.onReceive.removeListener(onReceive); - closeSocket(socketId); - } - - }, timeoutMs); + timeout = setTimeout(onTimerExpired, timeoutMs); } function onReceive(info) { @@ -98,48 +96,42 @@ var port = 7359; console.log('chrome.sockets.udp.create'); + + startTimer(); + chrome.sockets.udp.create(function (createInfo) { if (!createInfo) { console.log('create fail'); - deferred.resolveWith(null, [servers]); return; } if (!createInfo.socketId) { console.log('create fail'); - deferred.resolveWith(null, [servers]); return; } socketId = createInfo.socketId; console.log('chrome.sockets.udp.bind'); - chrome.sockets.udp.bind(createInfo.socketId, '0.0.0.0', 0, function (bindResult) { if (getResultCode(bindResult) != 0) { console.log('bind fail: ' + bindResult); - deferred.resolveWith(null, [servers]); - closeSocket(createInfo.socketId); return; } var data = stringToArrayBuffer('who is EmbyServer?'); console.log('chrome.sockets.udp.send'); + chrome.sockets.udp.send(createInfo.socketId, data, '255.255.255.255', port, function (sendResult) { if (getResultCode(sendResult) != 0) { console.log('send fail: ' + sendResult); - deferred.resolveWith(null, [servers]); - closeSocket(createInfo.socketId); } else { - - console.log('sendTo: success ' + port); - - startTimer(); chrome.sockets.udp.onReceive.addListener(onReceive); + console.log('sendTo: success ' + port); } }); }); @@ -163,10 +155,10 @@ }).fail(function () { - deferred.reject(); + deferred.resolveWith(null, [[]]); }); } catch (err) { - deferred.reject(); + deferred.resolveWith(null, [[]]); } }); diff --git a/dashboard-ui/thirdparty/jquery.unveil-custom.js b/dashboard-ui/thirdparty/jquery.unveil-custom.js index 7059dc3806..2f474dc7ae 100644 --- a/dashboard-ui/thirdparty/jquery.unveil-custom.js +++ b/dashboard-ui/thirdparty/jquery.unveil-custom.js @@ -15,12 +15,10 @@ function getThreshold() { - if (window.AppInfo && AppInfo.hasLowImageBandwidth) { - return 0; - } - - // Test search before setting to 0 - return 100; + // If less than 100, the search window ends up not getting images + // If less than 200, this happens on the home page + // Need to fix those before this can be set to 0 + return 200; } $.fn.unveil = function () { diff --git a/dashboard-ui/userpassword.html b/dashboard-ui/userpassword.html index 1d3b5605fb..923914dd9f 100644 --- a/dashboard-ui/userpassword.html +++ b/dashboard-ui/userpassword.html @@ -4,7 +4,7 @@ -
+