1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

fix sync status display

This commit is contained in:
Luke Pulverenti 2015-10-02 02:14:04 -04:00
parent a07e6b59a3
commit 94a5cf7549
26 changed files with 415 additions and 276 deletions

View file

@ -880,7 +880,7 @@
var tests = [];
if (server.LastConnectionMode != null) {
tests.push(server.LastConnectionMode);
//tests.push(server.LastConnectionMode);
}
if (tests.indexOf(MediaBrowser.ConnectionMode.Manual) == -1) { tests.push(MediaBrowser.ConnectionMode.Manual); }
if (tests.indexOf(MediaBrowser.ConnectionMode.Local) == -1) { tests.push(MediaBrowser.ConnectionMode.Local); }

View file

@ -27,14 +27,14 @@
"web-component-tester": "*",
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
},
"homepage": "https://github.com/polymerelements/iron-behaviors",
"homepage": "https://github.com/PolymerElements/iron-behaviors",
"_release": "1.0.8",
"_resolution": {
"type": "version",
"tag": "v1.0.8",
"commit": "663ad706b43989f4961d945b8116cf4db346532f"
},
"_source": "git://github.com/polymerelements/iron-behaviors.git",
"_source": "git://github.com/PolymerElements/iron-behaviors.git",
"_target": "^1.0.0",
"_originalSource": "polymerelements/iron-behaviors"
"_originalSource": "PolymerElements/iron-behaviors"
}

View file

@ -1,6 +1,6 @@
{
"name": "iron-overlay-behavior",
"version": "1.0.8",
"version": "1.0.9",
"license": "http://polymer.github.io/LICENSE.txt",
"description": "Provides a behavior for making an element an overlay",
"private": true,
@ -35,11 +35,11 @@
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
},
"homepage": "https://github.com/polymerelements/iron-overlay-behavior",
"_release": "1.0.8",
"_release": "1.0.9",
"_resolution": {
"type": "version",
"tag": "v1.0.8",
"commit": "cf25fe1ff2f585fa84190537bf62b94eb1579aad"
"tag": "v1.0.9",
"commit": "87f7763d323fffa07357a08777ad831b7c2c2fb8"
},
"_source": "git://github.com/polymerelements/iron-overlay-behavior.git",
"_target": "^1.0.0",

View file

@ -1,6 +1,6 @@
{
"name": "iron-overlay-behavior",
"version": "1.0.8",
"version": "1.0.9",
"license": "http://polymer.github.io/LICENSE.txt",
"description": "Provides a behavior for making an element an overlay",
"private": true,

View file

@ -28,7 +28,8 @@ intent. Closing generally implies that the user acknowledged the content on the
it will cancel whenever the user taps outside it or presses the escape key. This behavior is
configurable with the `no-cancel-on-esc-key` and the `no-cancel-on-outside-click` properties.
`close()` should be called explicitly by the implementer when the user interacts with a control
in the overlay element.
in the overlay element. When the dialog is canceled, the overlay fires an 'iron-overlay-canceled'
event. Call `preventDefault` on this event to prevent the overlay from closing.
### Positioning
@ -199,6 +200,11 @@ context. You should place this element as a child of `<body>` whenever possible.
* Cancels the overlay.
*/
cancel: function() {
var cancelEvent = this.fire('iron-overlay-canceled', undefined, {cancelable: true});
if (cancelEvent.defaultPrevented) {
return;
}
this.opened = false;
this._setCanceled(true);
},

View file

@ -180,6 +180,15 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
});
test('cancel an overlay by clicking outside', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-canceled', function(event) {
done();
});
Polymer.Base.fire.call(document, 'click');
});
});
test('close an overlay by clicking outside', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-closed', function(event) {
assert.isTrue(event.detail.canceled, 'overlay is canceled');
@ -189,7 +198,35 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
});
});
test('cancel event can be prevented', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-canceled', function(event) {
event.preventDefault();
});
var closedListener = function(event) {
throw new Error('iron-overlay-closed should not fire');
};
overlay.addEventListener('iron-overlay-closed', closedListener);
Polymer.Base.fire.call(document, 'click');
setTimeout(function() {
overlay.removeEventListener('iron-overlay-closed', closedListener);
done();
}, 10);
});
});
test('cancel an overlay with esc key', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-canceled', function(event) {
done();
});
fireEvent('keydown', {
keyCode: 27
}, document);
});
});
test('close an overlay with esc key', function(done) {
runAfterOpen(overlay, function() {
overlay.addEventListener('iron-overlay-closed', function(event) {
assert.isTrue(event.detail.canceled, 'overlay is canceled');

View file

@ -269,22 +269,7 @@
currentItemId = itemId;
currentItemType = itemType;
var dlg = document.createElement('paper-dialog');
dlg.setAttribute('with-backdrop', 'with-backdrop');
dlg.setAttribute('role', 'alertdialog');
// without this safari will scroll the background instead of the dialog contents
// but not needed here since this is already on top of an existing dialog
// dlg.setAttribute('modal', 'modal');
// seeing max call stack size exceeded in the debugger with this
dlg.setAttribute('noAutoFocus', 'noAutoFocus');
dlg.entryAnimation = 'scale-up-animation';
dlg.exitAnimation = 'fade-out-animation';
dlg.classList.add('fullscreen-editor-paper-dialog');
dlg.classList.add('ui-body-b');
dlg.classList.add('smoothScrollY');
var dlg = PaperDialogHelper.createDialog();
var html = '';
html += '<h2 class="dialogHeader">';

View file

@ -230,19 +230,7 @@
ApiClient.getItem(Dashboard.getCurrentUserId(), itemId).done(function (item) {
var dlg = document.createElement('paper-dialog');
dlg.setAttribute('with-backdrop', 'with-backdrop');
dlg.setAttribute('role', 'alertdialog');
// without this safari will scroll the background instead of the dialog contents
dlg.setAttribute('modal', 'modal');
// seeing max call stack size exceeded in the debugger with this
dlg.setAttribute('noAutoFocus', 'noAutoFocus');
dlg.entryAnimation = 'scale-up-animation';
dlg.exitAnimation = 'fade-out-animation';
dlg.classList.add('fullscreen-editor-paper-dialog');
dlg.classList.add('ui-body-b');
dlg.classList.add('smoothScrollY');
var dlg = PaperDialogHelper.createDialog();
var html = '';
html += '<h2 class="dialogHeader">';

View file

@ -132,22 +132,7 @@
currentItemId = itemId;
var dlg = document.createElement('paper-dialog');
dlg.setAttribute('with-backdrop', 'with-backdrop');
dlg.setAttribute('role', 'alertdialog');
// without this safari will scroll the background instead of the dialog contents
// but not needed here since this is already on top of an existing dialog
// dlg.setAttribute('modal', 'modal');
// seeing max call stack size exceeded in the debugger with this
dlg.setAttribute('noAutoFocus', 'noAutoFocus');
dlg.entryAnimation = 'scale-up-animation';
dlg.exitAnimation = 'fade-out-animation';
dlg.classList.add('fullscreen-editor-paper-dialog');
dlg.classList.add('ui-body-b');
dlg.classList.add('smoothScrollY');
var dlg = PaperDialogHelper.createDialog();
var html = '';
html += '<h2 class="dialogHeader">';

View file

@ -66,15 +66,41 @@
function close(dlg) {
if (enableHashChange()) {
if (dlg.opened) {
history.back();
}
} else {
dlg.close();
}
}
function createDialog() {
var dlg = document.createElement('paper-dialog');
dlg.setAttribute('with-backdrop', 'with-backdrop');
dlg.setAttribute('role', 'alertdialog');
// without this safari will scroll the background instead of the dialog contents
// but not needed here since this is already on top of an existing dialog
dlg.setAttribute('modal', 'modal');
// seeing max call stack size exceeded in the debugger with this
dlg.setAttribute('noAutoFocus', 'noAutoFocus');
dlg.entryAnimation = 'scale-up-animation';
dlg.exitAnimation = 'fade-out-animation';
dlg.classList.add('fullscreen-editor-paper-dialog');
dlg.classList.add('ui-body-b');
dlg.classList.add('smoothScrollY');
return dlg;
}
globalScope.PaperDialogHelper = {
openWithHash: openWithHash,
close: close
close: close,
createDialog: createDialog
};
})(this);

View file

@ -0,0 +1,10 @@
define([], function () {
return function (options) {
var result = prompt(options.text, options.defaultText || '');
if (options.callback) {
options.callback(result);
}
};
});

View file

@ -335,19 +335,7 @@
ApiClient.getItem(Dashboard.getCurrentUserId(), itemId).done(function (item) {
var dlg = document.createElement('paper-dialog');
dlg.setAttribute('with-backdrop', 'with-backdrop');
dlg.setAttribute('role', 'alertdialog');
// without this safari will scroll the background instead of the dialog contents
dlg.setAttribute('modal', 'modal');
// seeing max call stack size exceeded in the debugger with this
dlg.setAttribute('noAutoFocus', 'noAutoFocus');
dlg.entryAnimation = 'scale-up-animation';
dlg.exitAnimation = 'fade-out-animation';
dlg.classList.add('fullscreen-editor-paper-dialog');
dlg.classList.add('ui-body-b');
dlg.classList.add('smoothScrollY');
var dlg = PaperDialogHelper.createDialog();
var html = '';
html += '<h2 class="dialogHeader">';

View file

@ -1,8 +1,16 @@
(function () {
var unlockId = "com.mb.android.unlock";
var updatedProducts = [];
function getStoreFeatureId(feature) {
if (feature == 'embypremieremonthly') {
return "emby.supporter.monthly";
}
return "com.mb.android.unlock";
}
function updateProductInfo(id, owned, price) {
updatedProducts = updatedProducts.filter(function (r) {
@ -20,7 +28,10 @@
Events.trigger(IapManager, 'productupdated', [product]);
}
function getProduct(id) {
function getProduct(feature) {
var id = getStoreFeatureId(feature);
var products = updatedProducts.filter(function (r) {
return r.id == id;
});
@ -28,13 +39,14 @@
return products.length ? products[0] : null;
}
function isPurchaseAvailable(id) {
function isPurchaseAvailable(feature) {
return NativeIapManager.isStoreAvailable();
}
function beginPurchase(id) {
return MainActivity.beginPurchase(id);
function beginPurchase(feature, email) {
var id = getStoreFeatureId(feature);
return MainActivity.beginPurchase(id, email);
}
function onPurchaseComplete(result) {
@ -45,7 +57,31 @@
}
function refreshPurchases() {
NativeIapManager.isPurchased(unlockId, "window.IapManager.updateProduct");
NativeIapManager.isPurchased(getStoreFeatureId("") + "|" + getStoreFeatureId("embypremieremonthly"), "window.IapManager.updateProduct");
//NativeIapManager.isPurchased(getStoreFeatureId("embypremieremonthly"), "window.IapManager.updateProduct");
}
function getSubscriptionOptions() {
var deferred = DeferredBuilder.Deferred();
var options = [];
options.push({
feature: 'embypremieremonthly',
buttonText: 'EmbyPremiereMonthlyWithPrice'
});
options = options.filter(function (o) {
return getProduct(o.feature) != null;
}).map(function (o) {
o.buttonText = Globalize.translate(o.buttonText, o.price);
return o;
});
deferred.resolveWith(null, [options]);
return deferred.promise();
}
window.IapManager = {
@ -53,7 +89,9 @@
getProductInfo: getProduct,
updateProduct: updateProductInfo,
beginPurchase: beginPurchase,
onPurchaseComplete: onPurchaseComplete
onPurchaseComplete: onPurchaseComplete,
getStoreFeatureId: getStoreFeatureId,
getSubscriptionOptions: getSubscriptionOptions
};
refreshPurchases();

View file

@ -1,10 +1,16 @@
(function () {
var unlockAlias = "premium features";
var unlockAppProductId = 'appunlock';
var updatedProducts = [];
function getStoreFeatureId(feature) {
if (feature == 'embypremieremonthly') {
return 'emby.subscription.monthly';
}
return 'appunlock';
}
function updateProductInfo(product) {
updatedProducts = updatedProducts.filter(function (r) {
@ -16,17 +22,9 @@
Events.trigger(IapManager, 'productupdated', [product]);
}
function normalizeId(id) {
function getProduct(feature) {
// This is what i named it in itunes
id = id.replace('premiumunlock', 'appunlock');
return id;
}
function getProduct(id) {
id = normalizeId(id);
var id = getStoreFeatureId(feature);
var products = updatedProducts.filter(function (r) {
return r.id == id;
@ -35,19 +33,19 @@
return products.length ? products[0] : null;
}
function isPurchaseAvailable(id) {
var product = getProduct(id);
function isPurchaseAvailable(feature) {
var product = getProduct(feature);
return product != null && product.valid /*&& product.canPurchase*/;
}
function beginPurchase(id) {
id = normalizeId(id);
function beginPurchase(feature, email) {
var id = getStoreFeatureId(feature);
store.order(id);
}
function restorePurchase(id) {
id = normalizeId(id);
store.refresh();
}
@ -74,6 +72,36 @@
//callback(false, "Impossible to proceed with validation");
}
function initProduct(id, alias, type) {
store.register({
id: id,
alias: alias,
type: type
});
// When purchase of the full version is approved,
// show some logs and finish the transaction.
store.when(id).approved(function (order) {
order.finish();
});
store.when(id).verified(function (p) {
p.finish();
});
// The play button can only be accessed when the user
// owns the full version.
store.when(id).updated(function (product) {
if (product.loaded && product.valid && product.state == store.APPROVED) {
Logger.log('finishing previously created transaction');
product.finish();
}
updateProductInfo(product);
});
}
function initializeStore() {
// Let's set a pretty high verbosity level, so that we see a lot of stuff
@ -82,35 +110,8 @@
store.validator = validateProduct;
// iOS
store.register({
id: unlockAppProductId,
alias: unlockAlias,
type: store.NON_CONSUMABLE
});
// When purchase of the full version is approved,
// show some logs and finish the transaction.
store.when(unlockAppProductId).approved(function (order) {
log('You just unlocked the FULL VERSION!');
order.finish();
});
store.when(unlockAppProductId).verified(function (p) {
log("verified");
p.finish();
});
// The play button can only be accessed when the user
// owns the full version.
store.when(unlockAppProductId).updated(function (product) {
if (product.loaded && product.valid && product.state == store.APPROVED) {
Logger.log('finishing previously created transaction');
product.finish();
}
updateProductInfo(product);
});
initProduct(getStoreFeatureId(""), "premium features", store.NON_CONSUMABLE);
initProduct(getStoreFeatureId("embypremieremonthly"), "emby premiere monthly", store.PAID_SUBSCRIPTION);
// When every goes as expected, it's time to celebrate!
// The "ready" event should be welcomed with music and fireworks,
@ -125,11 +126,36 @@
store.refresh();
}
function getSubscriptionOptions() {
var deferred = DeferredBuilder.Deferred();
var options = [];
options.push({
feature: 'embypremieremonthly',
buttonText: 'EmbyPremiereMonthlyWithPrice'
});
options = options.filter(function (o) {
return getProduct(o.feature) != null;
}).map(function (o) {
o.buttonText = Globalize.translate(o.buttonText, o.price);
return o;
});
deferred.resolveWith(null, [options]);
return deferred.promise();
}
window.IapManager = {
isPurchaseAvailable: isPurchaseAvailable,
getProductInfo: getProduct,
beginPurchase: beginPurchase,
restorePurchase: restorePurchase
restorePurchase: restorePurchase,
getStoreFeatureId: getStoreFeatureId,
getSubscriptionOptions: getSubscriptionOptions
};
initializeStore();

View file

@ -4,11 +4,11 @@
function onDeviceReady() {
var fetcher = window.BackgroundFetch;
//var fetcher = window.BackgroundFetch;
fetcher.configure(onBackgroundFetch, onBackgroundFetchFailed, {
stopOnTerminate: false // <-- false is default
});
//fetcher.configure(onBackgroundFetch, onBackgroundFetchFailed, {
// stopOnTerminate: false // <-- false is default
//});
}
function onSyncFinish() {
@ -86,7 +86,7 @@
});
});
pageClassOn('pageshow', "page", function () {
pageClassOn('pageshow', "libraryPage", function () {
if (!Dashboard.getCurrentUserId()) {
return;

View file

@ -523,7 +523,7 @@
function downloadFile(url, localPath, enableBackground, enableNewDownloads) {
if (!enableBackground) {
return downloadWithFileTransfer(url, localPath);
return downloadWithFileTransfer(url, localPath, enableBackground);
}
var deferred = DeferredBuilder.Deferred();

17
dashboard-ui/cordova/prompt.js vendored Normal file
View file

@ -0,0 +1,17 @@
define([], function () {
return function (options) {
var callback = function (result) {
if (result.buttonIndex == 1) {
options.callback(result.input1);
} else {
options.callback(null);
}
};
var buttonLabels = [Globalize.translate('ButtonOk'), Globalize.translate('ButtonCancel')];
navigator.notification.prompt(options.text, callback, options.title, buttonLabels, options.defaultText || '');
};
});

View file

@ -1,86 +1,56 @@
(function () {
function isAndroid() {
return $.browser.android;
}
function getPremiumUnlockFeatureId() {
if (isAndroid()) {
return "com.mb.android.unlock";
}
return 'appunlock';
}
function validatePlayback(deferred) {
// Don't require validation on android
if (isAndroid()) {
deferred.resolve();
return;
}
validateFeature(getPremiumUnlockFeatureId(), deferred);
}
function validateLiveTV(deferred) {
validateFeature(getPremiumUnlockFeatureId(), deferred);
}
function validateServerManagement(deferred) {
deferred.resolve();
}
function getRegistrationInfo(feature, enableSupporterUnlock) {
function getRegistrationInfo(feature) {
if (!enableSupporterUnlock) {
var deferred = $.Deferred();
deferred.resolveWith(null, [{}]);
return deferred.promise();
}
return ConnectionManager.getRegistrationInfo(feature, ApiClient);
}
var validatedFeatures = [];
function validateFeature(id, deferred) {
function validateFeature(feature, deferred) {
if (validatedFeatures.indexOf(id) != -1) {
var id = IapManager.getStoreFeatureId(feature);
if (validatedFeatures.indexOf(feature) != -1) {
deferred.resolve();
return;
}
var info = IapManager.getProductInfo(id) || {};
var info = IapManager.getProductInfo(feature) || {};
if (info.owned) {
notifyServer(id);
validatedFeatures.push(id);
validatedFeatures.push(feature);
deferred.resolve();
return;
}
var productInfo = {
enableSupporterUnlock: true,
enableAppUnlock: IapManager.isPurchaseAvailable(id),
enableAppUnlock: IapManager.isPurchaseAvailable(feature),
id: id,
price: info.price
price: info.price,
feature: feature
};
var prefix = isAndroid() ? 'android' : 'ios';
var prefix = $.browser.android ? 'android' : 'ios';
// Get supporter status
getRegistrationInfo(prefix + 'appunlock', productInfo.enableSupporterUnlock).done(function (registrationInfo) {
getRegistrationInfo(prefix + 'appunlock').done(function (registrationInfo) {
if (registrationInfo.IsRegistered) {
validatedFeatures.push(id);
validatedFeatures.push(feature);
deferred.resolve();
return;
}
showInAppPurchaseInfo(productInfo, registrationInfo, deferred);
IapManager.getSubscriptionOptions().done(function (subscriptionOptions) {
showInAppPurchaseInfo(productInfo, subscriptionOptions, registrationInfo, deferred);
});
}).fail(function () {
deferred.reject();
@ -114,42 +84,32 @@
});
}
function getInAppPurchaseElement(info) {
function getInAppPurchaseElement(info, subscriptionOptions) {
cancelInAppPurchase();
var dlg = PaperDialogHelper.createDialog();
var html = '';
html += '<div class="inAppPurchaseOverlay" style="background-image:url(css/images/splash.jpg);top:0;left:0;right:0;bottom:0;position:fixed;background-position:center center;background-size:100% 100%;background-repeat:no-repeat;z-index:999999;">';
html += '<div class="inAppPurchaseOverlayInner" style="background:rgba(10,10,10,.8);width:100%;height:100%;color:#eee;">';
html += '<h2 class="dialogHeader">';
html += '<paper-fab icon="arrow-back" class="mini btnCloseDialog"></paper-fab>';
html += '<div style="display:inline-block;margin-left:.6em;vertical-align:middle;">' + Globalize.translate('HeaderUnlockApp') + '</div>';
html += '</h2>';
html += '<div class="editorContent">';
html += '<div class="inAppPurchaseForm" style="margin: 0 auto;padding: 30px 1em 0;">';
html += '<h1 style="color:#fff;">' + Globalize.translate('HeaderUnlockApp') + '</h1>';
html += '<form style="max-width: 800px;margin:auto;">';
html += '<p style="margin:2em 0;">';
var showSupporterInfo = info.enableSupporterUnlock && !$.browser.safari;
if (showSupporterInfo && info.enableAppUnlock) {
if (info.enableAppUnlock) {
html += Globalize.translate('MessageUnlockAppWithPurchaseOrSupporter');
}
else if (showSupporterInfo) {
else {
html += Globalize.translate('MessageUnlockAppWithSupporter');
} else if (info.enableAppUnlock) {
html += Globalize.translate('MessageUnlockAppWithPurchase');
} else {
html += '<span style="color:red;">';
html += Globalize.translate('MessagePaymentServicesUnavailable');
html += '</span>';
}
html += '</p>';
if (showSupporterInfo) {
html += '<p style="margin:2em 0;">';
html += Globalize.translate('MessageToValidateSupporter');
html += '</p>';
}
if (info.enableAppUnlock) {
@ -158,76 +118,118 @@
unlockText = Globalize.translate('ButtonUnlockPrice', info.price);
}
html += '<p>';
html += '<paper-button raised class="secondary block btnAppUnlock"><iron-icon icon="check"></iron-icon><span>' + unlockText + '</span></paper-button>';
html += '<paper-button raised class="secondary block btnPurchase" data-feature="' + info.feature + '"><iron-icon icon="check"></iron-icon><span>' + unlockText + '</span></paper-button>';
html += '</p>';
}
for (var i = 0, length = subscriptionOptions.length; i < length; i++) {
html += '<p>';
html += '<paper-button raised class="submit block btnPurchase" data-email="true" data-feature="' + subscriptionOptions[i].feature + '"><iron-icon icon="check"></iron-icon><span>';
html += subscriptionOptions[i].buttonText;
html += '</span></paper-button>';
html += '</p>';
}
if (IapManager.restorePurchase) {
html += '<p>';
html += '<paper-button raised class="secondary block btnRestorePurchase" style="background-color: #673AB7;"><iron-icon icon="check"></iron-icon><span>' + Globalize.translate('ButtonRestorePreviousPurchase') + '</span></paper-button>';
html += '</p>';
}
}
html += '<p>';
html += '<paper-button raised class="cancelDark block btnCancel"><iron-icon icon="close"></iron-icon><span>' + Globalize.translate('ButtonCancel') + '</span></paper-button>';
html += '</p>';
html += '</form>';
html += '</div>';
html += '</div>';
html += '</div>';
dlg.innerHTML = html;
document.body.appendChild(dlg);
$(document.body).append(html);
// init dlg content here
return $('.inAppPurchaseOverlay');
PaperDialogHelper.openWithHash(dlg, 'iap');
$('.btnCloseDialog', dlg).on('click', function () {
PaperDialogHelper.close(dlg);
});
dlg.classList.add('inAppPurchaseOverlay');
return dlg;
}
function cancelInAppPurchase() {
$('.inAppPurchaseOverlay').remove();
var elem = document.querySelector('.inAppPurchaseOverlay');
if (elem) {
PaperDialogHelper.close(elem);
}
}
var currentDisplayingProductInfo = null;
var currentDisplayingProductInfos = [];
var currentDisplayingDeferred = null;
var isCancelled = true;
function clearCurrentDisplayingInfo() {
currentDisplayingProductInfo = null;
currentDisplayingProductInfos = [];
currentDisplayingDeferred = null;
}
function showInAppPurchaseInfo(info, serverRegistrationInfo, deferred) {
function showInAppPurchaseInfo(info, subscriptionOptions, serverRegistrationInfo, deferred) {
var elem = getInAppPurchaseElement(info);
require(['components/paperdialoghelper'], function () {
cancelInAppPurchase();
isCancelled = true;
var elem = getInAppPurchaseElement(info, subscriptionOptions);
// clone
currentDisplayingProductInfos = subscriptionOptions.slice(0);
currentDisplayingProductInfos.push(info);
currentDisplayingProductInfo = info;
currentDisplayingDeferred = deferred;
$('.btnAppUnlock', elem).on('click', function () {
$('.btnPurchase', elem).on('click', function () {
IapManager.beginPurchase(info.id);
isCancelled = false;
if (this.getAttribute('data-email') == 'true') {
promptForEmail(this.getAttribute('data-feature'));
} else {
IapManager.beginPurchase(this.getAttribute('data-feature'));
}
});
$('.btnRestorePurchase', elem).on('click', function () {
IapManager.restorePurchase(info.id);
isCancelled = false;
IapManager.restorePurchase(info.feature);
});
$('.btnCancel', elem).on('click', function () {
$(elem).on('iron-overlay-closed', function () {
if (isCancelled) {
clearCurrentDisplayingInfo();
cancelInAppPurchase();
deferred.reject();
}
});
$('.btnSignInSupporter', elem).on('click', function () {
});
}
clearCurrentDisplayingInfo();
function promptForEmail(feature) {
Dashboard.alert({
message: Globalize.translate('MessagePleaseSignInLocalNetwork'),
callback: function () {
cancelInAppPurchase();
Dashboard.logout();
require(['prompt'], function (prompt) {
prompt({
text: Globalize.translate('TextPleaseEnterYourEmailAddressForSubscription'),
title: Globalize.translate('HeaderEmailAddress'),
callback: function(email) {
if (email) {
IapManager.beginPurchase(this.getAttribute('data-feature'), email);
}
}
});
});
@ -235,12 +237,15 @@
function onProductUpdated(e, product) {
var currentInfo = currentDisplayingProductInfo;
var deferred = currentDisplayingDeferred;
if (currentInfo && deferred) {
if (product.owned && product.id == currentInfo.id) {
if (deferred && product.owned) {
if (currentDisplayingProductInfos.filter(function (p) {
return product.id == p.id;
}).length) {
clearCurrentDisplayingInfo();
cancelInAppPurchase();
deferred.resolve();
@ -305,11 +310,9 @@
var deferred = DeferredBuilder.Deferred();
if (name == 'playback') {
validatePlayback(deferred);
validateFeature(name, deferred);
} else if (name == 'livetv') {
validateLiveTV(deferred);
} else if (name == 'manageserver') {
validateServerManagement(deferred);
validateFeature(name, deferred);
} else if (name == 'sync') {
validateSync(deferred);
} else {
@ -324,7 +327,7 @@
Events.on(IapManager, 'productupdated', onProductUpdated);
}
if (isAndroid()) {
if ($.browser.android) {
requirejs(['cordova/android/iap'], onIapManagerLoaded);
} else {
requirejs(['cordova/iap'], onIapManagerLoaded);

View file

@ -26,8 +26,9 @@
} else {
var url = getUrl(name, culture);
var requestUrl = url + "?v=" + window.dashboardVersion;
$.getJSON(url).done(function (dictionary) {
$.getJSON(requestUrl).done(function (dictionary) {
dictionaries[url] = dictionary;
deferred.resolve();

View file

@ -45,6 +45,7 @@
getPromise().done(function (item) {
reloadFromItem(page, item);
window.scrollTo(0, 0);
});
}

View file

@ -548,13 +548,7 @@
closeMainDrawer();
requirejs(["scripts/registrationservices"], function () {
RegistrationServices.validateFeature('manageserver').done(function () {
Dashboard.navigate('dashboard.html');
});
});
}
function getTopParentId() {

View file

@ -6,8 +6,6 @@
if (LocalSync.isSupported()) {
page.querySelector('.localSyncStatus').classList.remove('hide');
var status = LocalSync.getSyncStatus();
page.querySelector('.labelSyncStatus').innerHTML = Globalize.translate('LabelLocalSyncStatusValue', status);
@ -20,9 +18,6 @@
page.querySelector('.btnSyncNow').classList.remove('hide');
}
} else {
page.querySelector('.localSyncStatus').classList.add('hide');
page.querySelector('.syncSpinner').active = false;
}
});
}
@ -47,7 +42,19 @@
syncNow(page);
});
}).on('pageshow', "#mySyncActivityPage", function () {
require(['localsync'], function () {
if (LocalSync.isSupported()) {
page.querySelector('.localSyncStatus').classList.remove('hide');
} else {
page.querySelector('.localSyncStatus').classList.add('hide');
page.querySelector('.syncSpinner').active = false;
}
});
}).on('pagebeforeshow', "#mySyncActivityPage", function () {
var page = this;

View file

@ -100,6 +100,12 @@ var Dashboard = {
return;
}
// Don't bounce if the failure is in a sync service
if (url.indexOf('/sync') != -1) {
Dashboard.hideLoadingMsg();
return;
}
// Bounce to the login screen, but not if a password entry fails, obviously
if (url.indexOf('/password') == -1 &&
url.indexOf('/authenticate') == -1 &&
@ -238,6 +244,8 @@ var Dashboard = {
importCss: function (url) {
url += "?v=" + window.dashboardVersion;
if (!Dashboard.importedCss) {
Dashboard.importedCss = [];
}
@ -2019,12 +2027,20 @@ var AppInfo = {};
urlArgs += new Date().getTime();
}
var paths = {
velocity: "bower_components/velocity/velocity.min"
};
if (Dashboard.isRunningInCordova()) {
paths.prompt = "cordova/prompt";
} else {
paths.prompt = "components/prompt";
}
requirejs.config({
urlArgs: urlArgs,
paths: {
"velocity": "bower_components/velocity/velocity.min"
}
paths: paths
});
// Required since jQuery is loaded before requireJs

View file

@ -788,11 +788,10 @@
"TabScenes": "Scenes",
"HeaderUnlockApp": "Unlock App",
"MessageUnlockAppWithPurchase": "Unlock the full features of the app with a small one-time purchase.",
"MessageUnlockAppWithPurchaseOrSupporter": "Unlock the full features of the app with a small one-time purchase, or by signing in with an active Emby Supporter Membership.",
"MessageUnlockAppWithSupporter": "Unlock the full features of the app by signing in with an active Emby Supporter Membership.",
"MessageToValidateSupporter": "If you have an active Emby Supporter Membership, simply sign into the app using your Wifi connection within your home network.",
"MessageUnlockAppWithPurchaseOrSupporter": "Unlock the full features of the app with a small one-time purchase, or with an active Emby Premiere subscription.",
"MessageUnlockAppWithSupporter": "Unlock the full features of the app by signing in with an active Emby Premiere subscription.",
"MessageToValidateSupporter": "If you have an active Emby Premiere subscription, simply sign into the app using your Wifi connection within your home network.",
"MessagePaymentServicesUnavailable": "Payment services are currently unavailable. Please try again later.",
"ButtonUnlockWithSupporter": "Sign in with Emby Supporter Membership",
"MessagePleaseSignInLocalNetwork": "Before proceeding, please ensure that you're connected to your local network using a Wifi or LAN connection.",
"ButtonUnlockWithPurchase": "Unlock with Purchase",
"ButtonUnlockPrice": "Unlock {0}",
@ -903,5 +902,8 @@
"MessageEmbyForAndroidHasMoved": "Emby for Android has moved to a new home in the app store. Please consider checking out the new app. You may continue to use this app for as long as you wish.",
"HeaderNextUp": "Next Up",
"HeaderLatestMovies": "Latest Movies",
"HeaderLatestEpisodes": "Latest Episodes"
"HeaderLatestEpisodes": "Latest Episodes",
"EmbyPremiereMonthlyWithPrice": "Emby Premiere Monthly {0}",
"HeaderEmailAddress": "E-Mail Address",
"TextPleaseEnterYourEmailAddressForSubscription": "Please enter your e-mail address."
}

View file

@ -233,3 +233,6 @@ paper-tab {
.nowPlayingPage {
padding-top: 50px !important;
}
.localSyncStatus .labelSyncStatus {
display: none !important;
}

View file

@ -9835,7 +9835,8 @@ intent. Closing generally implies that the user acknowledged the content on the
it will cancel whenever the user taps outside it or presses the escape key. This behavior is
configurable with the `no-cancel-on-esc-key` and the `no-cancel-on-outside-click` properties.
`close()` should be called explicitly by the implementer when the user interacts with a control
in the overlay element.
in the overlay element. When the dialog is canceled, the overlay fires an 'iron-overlay-canceled'
event. Call `preventDefault` on this event to prevent the overlay from closing.
### Positioning
@ -10006,6 +10007,11 @@ context. You should place this element as a child of `<body>` whenever possible.
* Cancels the overlay.
*/
cancel: function() {
var cancelEvent = this.fire('iron-overlay-canceled', undefined, {cancelable: true});
if (cancelEvent.defaultPrevented) {
return;
}
this.opened = false;
this._setCanceled(true);
},