diff --git a/dashboard-ui/bower_components/get-style-property/.bower.json b/dashboard-ui/bower_components/get-style-property/.bower.json index 973f1966c0..d943fa3b04 100644 --- a/dashboard-ui/bower_components/get-style-property/.bower.json +++ b/dashboard-ui/bower_components/get-style-property/.bower.json @@ -31,6 +31,6 @@ "commit": "34fc5e4a0f252964ed2790138b8d7d30d04b55c1" }, "_source": "git://github.com/desandro/get-style-property.git", - "_target": "1.x", + "_target": "~1.0.4", "_originalSource": "get-style-property" } \ No newline at end of file diff --git a/dashboard-ui/cordova/android/iap.js b/dashboard-ui/cordova/android/iap.js index c2be5bf73b..13e85dc617 100644 --- a/dashboard-ui/cordova/android/iap.js +++ b/dashboard-ui/cordova/android/iap.js @@ -89,6 +89,7 @@ }).map(function (o) { o.buttonText = Globalize.translate(o.buttonText, getProduct(o.feature).price); + o.owned = getProduct(o.feature).owned; return o; }); diff --git a/dashboard-ui/cordova/iap.js b/dashboard-ui/cordova/iap.js index dfa58646f0..8099a47048 100644 --- a/dashboard-ui/cordova/iap.js +++ b/dashboard-ui/cordova/iap.js @@ -14,9 +14,9 @@ function updateProductInfo(product) { - if (product.id == 'appunlock') { - product.owned = false; - } + //if (product.id == 'appunlock') { + // product.owned = false; + //} updatedProducts = updatedProducts.filter(function (r) { return r.id != product.id; @@ -51,20 +51,42 @@ enteredEmail = email; } + validationCache = {}; + var id = getStoreFeatureId(feature); store.order(id); } function restorePurchase(id) { + validationCache = {}; store.refresh(); } + var validationCache = {}; + function validateProduct(product, callback) { + var productId = product.id; + var cacheKey = productId + (product.transaction.id || ''); + + var cachedResult = validationCache[cacheKey]; + if (cachedResult && (new Date().getTime() - cachedResult.date) < 60000) { + if (cachedResult.result) { + callback(true, product); + } else { + callback(false, { + code: cachedResult.errorCode, + error: { + message: cachedResult.errorMessage + } + }); + } + return; + } + // product attributes: // https://github.com/j3k0/cordova-plugin-purchase/blob/master/doc/api.md#validation-error-codes - var productId = product.id; var receipt = product.transaction.appStoreReceipt; var price = product.price; @@ -94,7 +116,7 @@ } else { - promise = ApiClient.ajax({ + promise = HttpClient.send({ type: "POST", url: "http://mb3admin.com/admin/service/appstore/register", data: JSON.stringify(postData), @@ -107,12 +129,16 @@ promise.done(function () { + setCachedResult(cacheKey, true); + callback(true, product); }).fail(function (e) { if (e.status == 402) { + setCachedResult(cacheKey, false, store.PURCHASE_EXPIRED, 'Subscription Expired'); + callback(false, { code: store.PURCHASE_EXPIRED, error: { @@ -121,7 +147,9 @@ }); } else { - alert('validate fail - other'); + //alert('validate fail - other ' + e.status); + + validationCache = {}; callback(false, { code: store.CONNECTION_FAILED, @@ -133,6 +161,16 @@ }); } + function setCachedResult(key, result, code, message) { + + validationCache[key] = { + date: new Date().getTime(), + result: result, + errorCode: code, + errorMessage: message + }; + } + function initProduct(id, requiresVerification, type) { store.register({ @@ -221,6 +259,7 @@ o.id = getStoreFeatureId(o.feature); o.buttonText = Globalize.translate(o.buttonText, getProduct(o.feature).price); + o.owned = getProduct(o.feature).owned; return o; }); diff --git a/dashboard-ui/cordova/ios/vlcplayer.js b/dashboard-ui/cordova/ios/vlcplayer.js index 32a33927f3..fd99fca680 100644 --- a/dashboard-ui/cordova/ios/vlcplayer.js +++ b/dashboard-ui/cordova/ios/vlcplayer.js @@ -225,7 +225,14 @@ return; } - if (result.state == 4 || result.state == 6) { + if (result.type === 'next') { + console.log('skip to next audio track'); // typically fired by remote control/lock screen controls + MediaPlayer.nextTrack(); + } else if (result.type === 'previous') { + console.log('skip to previous track'); // typically fired by remote/control/lock screen controls + MediaPlayer.previousTrack(); + } + else if (result.state == 4 || result.state == 6) { reportEvent('playbackstop', result); } else { diff --git a/dashboard-ui/cordova/registrationservices.js b/dashboard-ui/cordova/registrationservices.js index 13ed4c8db5..47c4ebe380 100644 --- a/dashboard-ui/cordova/registrationservices.js +++ b/dashboard-ui/cordova/registrationservices.js @@ -1,36 +1,23 @@ (function () { - function validateServerManagement(deferred) { - deferred.resolve(); - } - function getRegistrationInfo(feature) { return ConnectionManager.getRegistrationInfo(feature, ApiClient); } - var validatedFeatures = []; - function validateFeature(feature, deferred) { - if (validatedFeatures.indexOf(feature) != -1) { - deferred.resolve(); - return; - } + var unlockableProduct = IapManager.getProductInfo(feature) || {}; - var info = IapManager.getProductInfo(feature) || {}; - - if (info.owned) { - notifyServer(info.id); - validatedFeatures.push(feature); + if (unlockableProduct.owned) { deferred.resolve(); return; } var unlockableProductInfo = IapManager.isPurchaseAvailable(feature) ? { - enableAppUnlock: IapManager.isPurchaseAvailable(feature), - id: info.id, - price: info.price, + enableAppUnlock: true, + id: unlockableProduct.id, + price: unlockableProduct.price, feature: feature } : null; @@ -41,13 +28,19 @@ getRegistrationInfo(prefix + 'appunlock').done(function (registrationInfo) { if (registrationInfo.IsRegistered) { - validatedFeatures.push(feature); deferred.resolve(); return; } IapManager.getSubscriptionOptions().done(function (subscriptionOptions) { + if (subscriptionOptions.filter(function (p) { + return p.owned; + }).length > 0) { + deferred.resolve(); + return; + } + var dialogOptions = { title: Globalize.translate('HeaderUnlockApp') }; @@ -60,33 +53,6 @@ }); } - function notifyServer(id) { - - if (!$.browser.android) { - return; - } - - HttpClient.send({ - type: "POST", - url: "https://mb3admin.com/admin/service/appstore/addDeviceFeature", - data: { - deviceId: ConnectionManager.deviceId(), - feature: 'com.mb.android.unlock' - }, - contentType: 'application/x-www-form-urlencoded; charset=UTF-8', - headers: { - "X-EMBY-TOKEN": "EMBY_DEVICE" - } - - }).done(function (result) { - - Logger.log('addDeviceFeature succeeded'); - - }).fail(function () { - Logger.log('addDeviceFeature failed'); - }); - } - function cancelInAppPurchase() { var elem = document.querySelector('.inAppPurchaseOverlay'); @@ -288,7 +254,6 @@ getRegistrationInfo('Sync').done(function (registrationInfo) { if (registrationInfo.IsRegistered) { - validatedFeatures.push(feature); deferred.resolve(); return; } diff --git a/dashboard-ui/css/search.css b/dashboard-ui/css/search.css index 6468bd3ce7..9d8e85d203 100644 --- a/dashboard-ui/css/search.css +++ b/dashboard-ui/css/search.css @@ -126,7 +126,7 @@ .searchInputIcon { position: absolute; left: 20px; - top: 12px; + top: 18px; color: #ddd !important; } diff --git a/dashboard-ui/scripts/itemdetailpage.js b/dashboard-ui/scripts/itemdetailpage.js index 3902bcd330..9fd339bbc2 100644 --- a/dashboard-ui/scripts/itemdetailpage.js +++ b/dashboard-ui/scripts/itemdetailpage.js @@ -859,6 +859,8 @@ var html = ''; + var scrollX = false; + if (item.Type == "MusicAlbum") { html = LibraryBrowser.getListViewHtml({ @@ -874,9 +876,12 @@ } else if (item.Type == "Series") { + + scrollX = enableScrollX(); + html = LibraryBrowser.getPosterViewHtml({ items: result.Items, - shape: "detailPagePortrait", + shape: getPortraitShape(), showTitle: false, centerText: true, context: context, @@ -911,6 +916,12 @@ elem.innerHTML = html; ImageLoader.lazyChildren(elem); + if (scrollX) { + elem.classList.add('hiddenScrollX'); + } else { + elem.classList.remove('hiddenScrollX'); + } + if (item.Type == "BoxSet") { var collectionItemTypes = [ diff --git a/dashboard-ui/scripts/itemlistpage.js b/dashboard-ui/scripts/itemlistpage.js index cb71da0cca..27f192c703 100644 --- a/dashboard-ui/scripts/itemlistpage.js +++ b/dashboard-ui/scripts/itemlistpage.js @@ -88,7 +88,8 @@ items: result.Items, shape: "auto", centerText: true, - lazy: true + lazy: true, + coverImage: item.Type == 'PhotoAlbum' }; if (view == "Backdrop") { diff --git a/dashboard-ui/scripts/nowplayingpage.js b/dashboard-ui/scripts/nowplayingpage.js index 1d3e415821..a7f1c8d07a 100644 --- a/dashboard-ui/scripts/nowplayingpage.js +++ b/dashboard-ui/scripts/nowplayingpage.js @@ -599,7 +599,10 @@ // This should be outside of the IF // But for now, if you change songs but keep the same artist, the backdrop will flicker because in-between songs it clears out the image - Backdrops.setBackdropUrl(page, backdropUrl); + if (!$.browser.safari) { + // Exclude from safari because it just doesn't perform well + Backdrops.setBackdropUrl(page, backdropUrl); + } ApiClient.getItem(Dashboard.getCurrentUserId(), item.Id).done(function (fullItem) { page.querySelector('.nowPlayingPageUserDataButtons').innerHTML = LibraryBrowser.getUserDataIconsHtml(fullItem, false); diff --git a/dashboard-ui/scripts/sync.js b/dashboard-ui/scripts/sync.js index 6699828d43..adcf156619 100644 --- a/dashboard-ui/scripts/sync.js +++ b/dashboard-ui/scripts/sync.js @@ -387,7 +387,11 @@ Dashboard.getCurrentUser().done(function (user) { - $('.categorySyncButton', page).visible(user.Policy.EnableSync); + var item = { + SupportsSync: true + }; + + $('.categorySyncButton', page).visible(isAvailable(item)); }); }