mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge pull request #30 from dkanada/iap
Remove iap and simplify registrationservices
This commit is contained in:
commit
52cd371b51
3 changed files with 5 additions and 779 deletions
|
@ -1,732 +1,15 @@
|
||||||
define(['appSettings', 'loading', 'apphost', 'iapManager', 'events', 'shell', 'globalize', 'dialogHelper', 'connectionManager', 'layoutManager', 'emby-button', 'emby-linkbutton'], function (appSettings, loading, appHost, iapManager, events, shell, globalize, dialogHelper, connectionManager, layoutManager) {
|
define(['appSettings', 'loading', 'apphost', 'events', 'shell', 'globalize', 'dialogHelper', 'connectionManager', 'layoutManager', 'emby-button', 'emby-linkbutton'], function (appSettings, loading, appHost, events, shell, globalize, dialogHelper, connectionManager, layoutManager) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var currentDisplayingProductInfos = [];
|
function validateFeature(feature, options) {
|
||||||
var currentDisplayingResolve = null;
|
|
||||||
var currentValidatingFeature = null;
|
|
||||||
var isCurrentDialogRejected = null;
|
|
||||||
|
|
||||||
function alertText(options) {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
|
|
||||||
require(['alert'], function (alert) {
|
|
||||||
alert(options).then(resolve, reject);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showInAppPurchaseInfo(subscriptionOptions, unlockableProductInfo, dialogOptions) {
|
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
|
|
||||||
require(['listViewStyle', 'formDialogStyle'], function () {
|
|
||||||
showInAppPurchaseElement(subscriptionOptions, unlockableProductInfo, dialogOptions, resolve, reject);
|
|
||||||
|
|
||||||
currentDisplayingResolve = resolve;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showPeriodicMessage(feature, settingsKey) {
|
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
|
|
||||||
require(['listViewStyle', 'emby-button', 'formDialogStyle'], function () {
|
|
||||||
|
|
||||||
var dlg = dialogHelper.createDialog({
|
|
||||||
size: layoutManager.tv ? 'fullscreen' : 'fullscreen-border',
|
|
||||||
removeOnClose: true,
|
|
||||||
scrollY: false
|
|
||||||
});
|
|
||||||
|
|
||||||
dlg.classList.add('formDialog');
|
|
||||||
|
|
||||||
var html = '';
|
|
||||||
var seconds = 11;
|
|
||||||
|
|
||||||
html += '<div class="continueTimeText formDialogFooterItem" style="margin: 1.5em 0 .5em;">' + globalize.translate('sharedcomponents#ContinueInSecondsValue', seconds) + '</div>';
|
|
||||||
|
|
||||||
html += '<button is="emby-button" type="button" class="raised button-cancel block btnContinue block formDialogFooterItem hide"><span>' + globalize.translate('sharedcomponents#Continue') + '</span></button>';
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
dlg.innerHTML = html;
|
|
||||||
|
|
||||||
var isRejected = true;
|
|
||||||
|
|
||||||
var timeTextInterval = setInterval(function () {
|
|
||||||
|
|
||||||
seconds -= 1;
|
|
||||||
if (seconds <= 0) {
|
|
||||||
dlg.querySelector('.continueTimeText').classList.add('hide');
|
|
||||||
dlg.querySelector('.btnContinue').classList.remove('hide');
|
|
||||||
} else {
|
|
||||||
dlg.querySelector('.continueTimeText').innerHTML = globalize.translate('sharedcomponents#ContinueInSecondsValue', seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
var i, length;
|
|
||||||
var btnPurchases = dlg.querySelectorAll('.buttonPremiereInfo');
|
|
||||||
for (i = 0, length = btnPurchases.length; i < length; i++) {
|
|
||||||
btnPurchases[i].addEventListener('click', showExternalPremiereInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
centerFocus(dlg.querySelector('.formDialogContent'), false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has to be assigned a z-index after the call to .open()
|
|
||||||
dlg.addEventListener('close', function (e) {
|
|
||||||
|
|
||||||
clearInterval(timeTextInterval);
|
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isRejected) {
|
|
||||||
reject();
|
|
||||||
} else {
|
|
||||||
appSettings.set(settingsKey, new Date().getTime());
|
|
||||||
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dlg.querySelector('.btnContinue').addEventListener('click', function () {
|
|
||||||
isRejected = false;
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
});
|
|
||||||
|
|
||||||
dlg.querySelector('.btnGetPremiere').addEventListener('click', showPremiereInfo);
|
|
||||||
|
|
||||||
dialogHelper.open(dlg);
|
|
||||||
|
|
||||||
var onCancelClick = function () {
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
};
|
|
||||||
var elems = dlg.querySelectorAll('.btnCancelSupporterInfo');
|
|
||||||
for (i = 0, length = elems.length; i < length; i++) {
|
|
||||||
elems[i].addEventListener('click', onCancelClick);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showPeriodicMessageIfNeeded(feature) {
|
|
||||||
|
|
||||||
if (feature !== 'playback') {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
var intervalMs = iapManager.getPeriodicMessageIntervalMs(feature);
|
|
||||||
if (intervalMs <= 0) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
var settingsKey = 'periodicmessage11-' + feature;
|
|
||||||
|
|
||||||
var lastMessage = parseInt(appSettings.get(settingsKey) || '0');
|
|
||||||
|
|
||||||
if (!lastMessage) {
|
|
||||||
|
|
||||||
// Don't show on the very first playback attempt
|
|
||||||
appSettings.set(settingsKey, new Date().getTime());
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((new Date().getTime() - lastMessage) > intervalMs) {
|
|
||||||
|
|
||||||
var apiClient = connectionManager.currentApiClient();
|
|
||||||
if (apiClient.serverId() === '6da60dd6edfc4508bca2c434d4400816') {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
var registrationOptions = {
|
|
||||||
viewOnly: true
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get supporter status
|
|
||||||
return connectionManager.getRegistrationInfo(iapManager.getAdminFeatureName(feature), apiClient, registrationOptions).catch(function (errorResult) {
|
|
||||||
|
|
||||||
if (errorResult === 'overlimit') {
|
|
||||||
appSettings.set(settingsKey, new Date().getTime());
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
return showPeriodicMessage(feature, settingsKey);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateFeature(feature, options) {
|
|
||||||
|
|
||||||
options = options || {};
|
|
||||||
|
|
||||||
console.log('validateFeature: ' + feature);
|
|
||||||
|
|
||||||
return iapManager.isUnlockedByDefault(feature, options).then(function () {
|
|
||||||
|
|
||||||
return showPeriodicMessageIfNeeded(feature);
|
|
||||||
|
|
||||||
}, function () {
|
|
||||||
|
|
||||||
var unlockableFeatureCacheKey = 'featurepurchased-' + feature;
|
|
||||||
if (appSettings.get(unlockableFeatureCacheKey) === '1') {
|
|
||||||
return showPeriodicMessageIfNeeded(feature);
|
|
||||||
}
|
|
||||||
|
|
||||||
var unlockableProduct = iapManager.getProductInfo(feature);
|
|
||||||
if (unlockableProduct) {
|
|
||||||
|
|
||||||
var unlockableCacheKey = 'productpurchased-' + unlockableProduct.id;
|
|
||||||
if (unlockableProduct.owned) {
|
|
||||||
|
|
||||||
// Cache this to eliminate the store as a possible point of failure in the future
|
|
||||||
appSettings.set(unlockableFeatureCacheKey, '1');
|
|
||||||
appSettings.set(unlockableCacheKey, '1');
|
|
||||||
return showPeriodicMessageIfNeeded(feature);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appSettings.get(unlockableCacheKey) === '1') {
|
|
||||||
return showPeriodicMessageIfNeeded(feature);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var unlockableProductInfo = unlockableProduct ? {
|
|
||||||
enableAppUnlock: true,
|
|
||||||
id: unlockableProduct.id,
|
|
||||||
price: unlockableProduct.price,
|
|
||||||
feature: feature
|
|
||||||
|
|
||||||
} : null;
|
|
||||||
|
|
||||||
return iapManager.getSubscriptionOptions().then(function (subscriptionOptions) {
|
|
||||||
|
|
||||||
if (subscriptionOptions.filter(function (p) {
|
|
||||||
return p.owned;
|
|
||||||
}).length > 0) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
var registrationOptions = {
|
|
||||||
viewOnly: options.viewOnly
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get supporter status
|
|
||||||
return connectionManager.getRegistrationInfo(iapManager.getAdminFeatureName(feature), connectionManager.currentApiClient(), registrationOptions).catch(function (errorResult) {
|
|
||||||
|
|
||||||
if (options.showDialog === false) {
|
|
||||||
return Promise.reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
var alertPromise;
|
|
||||||
|
|
||||||
if (errorResult === 'overlimit') {
|
|
||||||
alertPromise = showOverLimitAlert();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!alertPromise) {
|
|
||||||
alertPromise = Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
return alertPromise.then(function () {
|
|
||||||
|
|
||||||
var dialogOptions = {
|
|
||||||
title: globalize.translate('sharedcomponents#HeaderUnlockFeature'),
|
|
||||||
feature: feature
|
|
||||||
};
|
|
||||||
|
|
||||||
currentValidatingFeature = feature;
|
|
||||||
|
|
||||||
return showInAppPurchaseInfo(subscriptionOptions, unlockableProductInfo, dialogOptions);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showOverLimitAlert() {
|
|
||||||
|
|
||||||
return alertText('Your Jellyfin Premiere device limit has been exceeded. Please check with the owner of your Jellyfin Server and have them contact Emby support at apps@emby.media if necessary.').catch(function () {
|
|
||||||
return Promise.resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancelInAppPurchase() {
|
|
||||||
|
|
||||||
var elem = document.querySelector('.inAppPurchaseOverlay');
|
|
||||||
if (elem) {
|
|
||||||
dialogHelper.close(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearCurrentDisplayingInfo() {
|
|
||||||
currentDisplayingProductInfos = [];
|
|
||||||
currentDisplayingResolve = null;
|
|
||||||
currentValidatingFeature = null;
|
|
||||||
isCurrentDialogRejected = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showExternalPremiereInfo() {
|
|
||||||
shell.openUrl(iapManager.getPremiumInfoUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
function centerFocus(elem, horiz, on) {
|
|
||||||
require(['scrollHelper'], function (scrollHelper) {
|
|
||||||
var fn = on ? 'on' : 'off';
|
|
||||||
scrollHelper.centerFocus[fn](elem, horiz);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPurchaseTermHtml(term) {
|
|
||||||
|
|
||||||
return '<li>' + term + '</li>';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTermsOfPurchaseHtml() {
|
|
||||||
|
|
||||||
var html = '';
|
|
||||||
|
|
||||||
var termsOfPurchase = iapManager.getTermsOfPurchase ? iapManager.getTermsOfPurchase() : [];
|
|
||||||
|
|
||||||
if (!termsOfPurchase.length) {
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '<h1>' + globalize.translate('sharedcomponents#HeaderTermsOfPurchase') + '</h1>';
|
|
||||||
|
|
||||||
termsOfPurchase.push('<a is="emby-linkbutton" class="button-link" href="https://github.com/jellyfin/jellyfin" target="_blank">' + globalize.translate('sharedcomponents#PrivacyPolicy') + '</a>');
|
|
||||||
termsOfPurchase.push('<a is="emby-linkbutton" class="button-link" href="https://github.com/jellyfin/jellyfin" target="_blank">' + globalize.translate('sharedcomponents#TermsOfUse') + '</a>');
|
|
||||||
|
|
||||||
html += '<ul>';
|
|
||||||
html += termsOfPurchase.map(getPurchaseTermHtml).join('');
|
|
||||||
html += '</ul>';
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showInAppPurchaseElement(subscriptionOptions, unlockableProductInfo, dialogOptions, resolve, reject) {
|
|
||||||
|
|
||||||
cancelInAppPurchase();
|
|
||||||
|
|
||||||
// clone
|
|
||||||
currentDisplayingProductInfos = subscriptionOptions.slice(0);
|
|
||||||
|
|
||||||
if (unlockableProductInfo) {
|
|
||||||
currentDisplayingProductInfos.push(unlockableProductInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
var dlg = dialogHelper.createDialog({
|
|
||||||
size: layoutManager.tv ? 'fullscreen' : 'fullscreen-border',
|
|
||||||
removeOnClose: true,
|
|
||||||
scrollY: false
|
|
||||||
});
|
|
||||||
|
|
||||||
dlg.classList.add('formDialog');
|
|
||||||
|
|
||||||
var html = '';
|
|
||||||
html += '<div class="formDialogHeader">';
|
|
||||||
html += '<button is="paper-icon-button-light" class="btnCloseDialog autoSize" tabindex="-1"><i class="md-icon"></i></button>';
|
|
||||||
html += '<h3 class="formDialogHeaderTitle">';
|
|
||||||
html += dialogOptions.title || '';
|
|
||||||
html += '</h3>';
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
html += '<div class="formDialogContent smoothScrollY">';
|
|
||||||
html += '<div class="dialogContentInner dialog-content-centered">';
|
|
||||||
html += '<form style="margin:auto;">';
|
|
||||||
|
|
||||||
html += '<p style="margin-top:1.5em;">';
|
|
||||||
|
|
||||||
if (unlockableProductInfo) {
|
|
||||||
html += globalize.translate('sharedcomponents#MessageUnlockAppWithPurchaseOrSupporter');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
html += globalize.translate('sharedcomponents#MessageUnlockAppWithSupporter');
|
|
||||||
}
|
|
||||||
html += '</p>';
|
|
||||||
|
|
||||||
html += '<p style="margin:1.5em 0 2em;">';
|
|
||||||
html += globalize.translate('sharedcomponents#MessageToValidateSupporter');
|
|
||||||
html += '</p>';
|
|
||||||
|
|
||||||
var hasProduct = false;
|
|
||||||
var i, length;
|
|
||||||
|
|
||||||
for (i = 0, length = subscriptionOptions.length; i < length; i++) {
|
|
||||||
|
|
||||||
hasProduct = true;
|
|
||||||
html += '<p>';
|
|
||||||
html += '<button is="emby-button" type="button" class="raised button-submit block btnPurchase" data-email="' + (subscriptionOptions[i].requiresEmail !== false) + '" data-featureid="' + subscriptionOptions[i].id + '"><span>';
|
|
||||||
html += subscriptionOptions[i].title;
|
|
||||||
html += '</span></button>';
|
|
||||||
html += '</p>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlockableProductInfo) {
|
|
||||||
|
|
||||||
hasProduct = true;
|
|
||||||
var unlockText = globalize.translate('sharedcomponents#ButtonUnlockWithPurchase');
|
|
||||||
if (unlockableProductInfo.price) {
|
|
||||||
unlockText = globalize.translate('sharedcomponents#ButtonUnlockPrice', unlockableProductInfo.price);
|
|
||||||
}
|
|
||||||
html += '<p>';
|
|
||||||
html += '<button is="emby-button" type="button" class="raised secondary block btnPurchase" data-featureid="' + unlockableProductInfo.id + '"><span>' + unlockText + '</span></button>';
|
|
||||||
html += '</p>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '<p>';
|
|
||||||
html += '<button is="emby-button" type="button" class="raised button-cancel block btnRestorePurchase"><span>' + iapManager.getRestoreButtonText() + '</span></button>';
|
|
||||||
html += '</p>';
|
|
||||||
|
|
||||||
if (subscriptionOptions.length) {
|
|
||||||
html += '<h1 style="margin-top:1.5em;">' + globalize.translate('sharedcomponents#HeaderBenefitsJellyfinPremiere') + '</h1>';
|
|
||||||
|
|
||||||
html += '<div class="paperList" style="margin-bottom:1em;">';
|
|
||||||
html += getSubscriptionBenefits().map(getSubscriptionBenefitHtml).join('');
|
|
||||||
html += '</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dialogOptions.feature === 'playback') {
|
|
||||||
html += '<p>';
|
|
||||||
html += '<button is="emby-button" type="button" class="raised button-cancel block btnPlayMinute"><span>' + globalize.translate('sharedcomponents#ButtonPlayOneMinute') + '</span></button>';
|
|
||||||
html += '</p>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += getTermsOfPurchaseHtml();
|
|
||||||
|
|
||||||
html += '</form>';
|
|
||||||
html += '</div>';
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
dlg.innerHTML = html;
|
|
||||||
document.body.appendChild(dlg);
|
|
||||||
|
|
||||||
var btnPurchases = dlg.querySelectorAll('.btnPurchase');
|
|
||||||
for (i = 0, length = btnPurchases.length; i < length; i++) {
|
|
||||||
btnPurchases[i].addEventListener('click', onPurchaseButtonClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
btnPurchases = dlg.querySelectorAll('.buttonPremiereInfo');
|
|
||||||
for (i = 0, length = btnPurchases.length; i < length; i++) {
|
|
||||||
btnPurchases[i].addEventListener('click', showExternalPremiereInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
isCurrentDialogRejected = true;
|
|
||||||
var resolveWithTimeLimit = false;
|
|
||||||
|
|
||||||
var btnPlayMinute = dlg.querySelector('.btnPlayMinute');
|
|
||||||
if (btnPlayMinute) {
|
|
||||||
btnPlayMinute.addEventListener('click', function () {
|
|
||||||
|
|
||||||
resolveWithTimeLimit = true;
|
|
||||||
isCurrentDialogRejected = false;
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
dlg.querySelector('.btnRestorePurchase').addEventListener('click', function () {
|
|
||||||
restorePurchase(unlockableProductInfo);
|
|
||||||
});
|
|
||||||
|
|
||||||
loading.hide();
|
|
||||||
|
|
||||||
function onCloseButtonClick() {
|
|
||||||
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
}
|
|
||||||
|
|
||||||
var btnCloseDialogs = dlg.querySelectorAll('.btnCloseDialog');
|
|
||||||
for (i = 0, length = btnCloseDialogs.length; i < length; i++) {
|
|
||||||
btnCloseDialogs[i].addEventListener('click', onCloseButtonClick);
|
|
||||||
}
|
|
||||||
|
|
||||||
dlg.classList.add('inAppPurchaseOverlay');
|
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
centerFocus(dlg.querySelector('.formDialogContent'), false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
dialogHelper.open(dlg).then(function () {
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
var rejected = isCurrentDialogRejected;
|
|
||||||
clearCurrentDisplayingInfo();
|
|
||||||
if (rejected) {
|
|
||||||
reject();
|
|
||||||
} else if (resolveWithTimeLimit) {
|
|
||||||
resolve({
|
|
||||||
enableTimeLimit: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSubscriptionBenefits() {
|
|
||||||
|
|
||||||
var list = [];
|
|
||||||
|
|
||||||
list.push({
|
|
||||||
name: globalize.translate('sharedcomponents#HeaderFreeApps'),
|
|
||||||
icon: '',
|
|
||||||
text: globalize.translate('sharedcomponents#FreeAppsFeatureDescription')
|
|
||||||
});
|
|
||||||
|
|
||||||
if (appHost.supports('sync')) {
|
|
||||||
list.push({
|
|
||||||
name: globalize.translate('sharedcomponents#HeaderOfflineDownloads'),
|
|
||||||
icon: '',
|
|
||||||
text: globalize.translate('sharedcomponents#HeaderOfflineDownloadsDescription')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
list.push({
|
|
||||||
name: globalize.translate('sharedcomponents#LiveTV'),
|
|
||||||
icon: '',
|
|
||||||
text: globalize.translate('sharedcomponents#LiveTvFeatureDescription')
|
|
||||||
});
|
|
||||||
|
|
||||||
list.push({
|
|
||||||
name: 'Jellyfin DVR',
|
|
||||||
icon: '',
|
|
||||||
text: globalize.translate('sharedcomponents#DvrFeatureDescription')
|
|
||||||
});
|
|
||||||
|
|
||||||
list.push({
|
|
||||||
name: globalize.translate('sharedcomponents#HeaderCinemaMode'),
|
|
||||||
icon: '',
|
|
||||||
text: globalize.translate('sharedcomponents#CinemaModeFeatureDescription')
|
|
||||||
});
|
|
||||||
|
|
||||||
list.push({
|
|
||||||
name: globalize.translate('sharedcomponents#HeaderCloudSync'),
|
|
||||||
icon: '',
|
|
||||||
text: globalize.translate('sharedcomponents#CloudSyncFeatureDescription')
|
|
||||||
});
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSubscriptionBenefitHtml(item) {
|
|
||||||
|
|
||||||
var enableLink = appHost.supports('externalpremium');
|
|
||||||
|
|
||||||
var html = '';
|
|
||||||
|
|
||||||
var cssClass = "listItem";
|
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
cssClass += ' listItem-focusscale';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enableLink) {
|
|
||||||
cssClass += ' listItem-button';
|
|
||||||
|
|
||||||
html += '<button type="button" class="' + cssClass + ' buttonPremiereInfo">';
|
|
||||||
} else {
|
|
||||||
html += '<div class="' + cssClass + '">';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '<i class="listItemIcon md-icon">' + item.icon + '</i>';
|
|
||||||
|
|
||||||
html += '<div class="listItemBody">';
|
|
||||||
|
|
||||||
html += '<h3 class="listItemBodyText">';
|
|
||||||
html += item.name;
|
|
||||||
html += '</h3>';
|
|
||||||
|
|
||||||
html += '<div class="listItemBodyText secondary">';
|
|
||||||
html += item.text;
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
if (enableLink) {
|
|
||||||
html += '</button>';
|
|
||||||
} else {
|
|
||||||
html += '</div>';
|
|
||||||
}
|
|
||||||
|
|
||||||
return html;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onPurchaseButtonClick() {
|
|
||||||
|
|
||||||
var featureId = this.getAttribute('data-featureid');
|
|
||||||
|
|
||||||
if (this.getAttribute('data-email') === 'true') {
|
|
||||||
getUserEmail().then(function (email) {
|
|
||||||
iapManager.beginPurchase(featureId, email);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
iapManager.beginPurchase(featureId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function restorePurchase(unlockableProductInfo) {
|
|
||||||
|
|
||||||
var dlg = dialogHelper.createDialog({
|
|
||||||
size: layoutManager.tv ? 'fullscreen' : 'fullscreen-border',
|
|
||||||
removeOnClose: true,
|
|
||||||
scrollY: false
|
|
||||||
});
|
|
||||||
|
|
||||||
dlg.classList.add('formDialog');
|
|
||||||
|
|
||||||
var html = '';
|
|
||||||
html += '<div class="formDialogHeader">';
|
|
||||||
html += '<button is="paper-icon-button-light" class="btnCloseDialog autoSize" tabindex="-1"><i class="md-icon"></i></button>';
|
|
||||||
html += '<h3 class="formDialogHeaderTitle">';
|
|
||||||
html += iapManager.getRestoreButtonText();
|
|
||||||
html += '</h3>';
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
html += '<div class="formDialogContent smoothScrollY">';
|
|
||||||
html += '<div class="dialogContentInner dialog-content-centered">';
|
|
||||||
|
|
||||||
html += '<p style="margin:2em 0;">';
|
|
||||||
html += globalize.translate('sharedcomponents#HowDidYouPay');
|
|
||||||
html += '</p>';
|
|
||||||
|
|
||||||
html += '<p>';
|
|
||||||
html += '<button is="emby-button" type="button" class="raised button-cancel block btnRestoreSub"><span>' + globalize.translate('sharedcomponents#IHaveJellyfinPremiere') + '</span></button>';
|
|
||||||
html += '</p>';
|
|
||||||
|
|
||||||
if (unlockableProductInfo) {
|
|
||||||
html += '<p>';
|
|
||||||
html += '<button is="emby-button" type="button" class="raised button-cancel block btnRestoreUnlock"><span>' + globalize.translate('sharedcomponents#IPurchasedThisApp') + '</span></button>';
|
|
||||||
html += '</p>';
|
|
||||||
}
|
|
||||||
|
|
||||||
html += '</div>';
|
|
||||||
html += '</div>';
|
|
||||||
|
|
||||||
dlg.innerHTML = html;
|
|
||||||
document.body.appendChild(dlg);
|
|
||||||
|
|
||||||
loading.hide();
|
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
centerFocus(dlg.querySelector('.formDialogContent'), false, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
dlg.querySelector('.btnCloseDialog').addEventListener('click', function () {
|
|
||||||
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
});
|
|
||||||
|
|
||||||
dlg.querySelector('.btnRestoreSub').addEventListener('click', function () {
|
|
||||||
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
alertText({
|
|
||||||
text: globalize.translate('sharedcomponents#MessageToValidateSupporter'),
|
|
||||||
title: 'Jellyfin Premiere'
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
var btnRestoreUnlock = dlg.querySelector('.btnRestoreUnlock');
|
|
||||||
if (btnRestoreUnlock) {
|
|
||||||
btnRestoreUnlock.addEventListener('click', function () {
|
|
||||||
|
|
||||||
dialogHelper.close(dlg);
|
|
||||||
iapManager.restorePurchase();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
dialogHelper.open(dlg).then(function () {
|
|
||||||
|
|
||||||
if (layoutManager.tv) {
|
|
||||||
centerFocus(dlg.querySelector('.formDialogContent'), false, false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUserEmail() {
|
|
||||||
|
|
||||||
if (connectionManager.isLoggedIntoConnect()) {
|
|
||||||
|
|
||||||
var connectUser = connectionManager.connectUser();
|
|
||||||
|
|
||||||
if (connectUser && connectUser.Email) {
|
|
||||||
return Promise.resolve(connectUser.Email);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
|
|
||||||
require(['prompt'], function (prompt) {
|
|
||||||
|
|
||||||
prompt({
|
|
||||||
|
|
||||||
label: globalize.translate('sharedcomponents#LabelEmailAddress')
|
|
||||||
|
|
||||||
}).then(resolve, reject);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onProductUpdated(e, product) {
|
|
||||||
|
|
||||||
if (product.owned) {
|
|
||||||
|
|
||||||
var resolve = currentDisplayingResolve;
|
|
||||||
|
|
||||||
if (resolve && currentDisplayingProductInfos.filter(function (p) {
|
|
||||||
|
|
||||||
return product.id === p.id;
|
|
||||||
|
|
||||||
}).length) {
|
|
||||||
|
|
||||||
isCurrentDialogRejected = false;
|
|
||||||
cancelInAppPurchase();
|
|
||||||
resolve();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var feature = currentValidatingFeature;
|
|
||||||
if (feature) {
|
|
||||||
iapManager.isUnlockedByDefault(feature).then(function () {
|
|
||||||
isCurrentDialogRejected = false;
|
|
||||||
cancelInAppPurchase();
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showPremiereInfo() {
|
function showPremiereInfo() {
|
||||||
|
return Promise.resolve();
|
||||||
if (appHost.supports('externalpremium')) {
|
|
||||||
showExternalPremiereInfo();
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
return iapManager.getSubscriptionOptions().then(function (subscriptionOptions) {
|
|
||||||
|
|
||||||
var dialogOptions = {
|
|
||||||
title: 'Jellyfin Premiere',
|
|
||||||
feature: 'sync'
|
|
||||||
};
|
|
||||||
|
|
||||||
return showInAppPurchaseInfo(subscriptionOptions, null, dialogOptions);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
events.on(iapManager, 'productupdated', onProductUpdated);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
||||||
validateFeature: validateFeature,
|
validateFeature: validateFeature,
|
||||||
showPremiereInfo: showPremiereInfo
|
showPremiereInfo: showPremiereInfo
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
define(["globalize", "shell", "browser", "apphost"], function(globalize, shell, browser, appHost) {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function getProductInfo(feature) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPremiumInfoUrl() {
|
|
||||||
return "https://github.com/jellyfin/jellyfin"
|
|
||||||
}
|
|
||||||
|
|
||||||
function beginPurchase(feature, email) {
|
|
||||||
appHost.supports("externalpremium") ? shell.openUrl(getPremiumInfoUrl()) : require(["alert"], function(alert) {
|
|
||||||
alert("Please visit " + getPremiumInfoUrl())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function restorePurchase(id) {
|
|
||||||
return Promise.reject()
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSubscriptionOptions() {
|
|
||||||
var options = [];
|
|
||||||
return options.push({
|
|
||||||
id: "embypremiere",
|
|
||||||
title: globalize.translate("sharedcomponents#HeaderBecomeProjectSupporter"),
|
|
||||||
requiresEmail: !1
|
|
||||||
}), Promise.resolve(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
function isUnlockedByDefault(feature, options) {
|
|
||||||
return "playback" === feature || "livetv" === feature ? Promise.resolve() : Promise.reject()
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAdminFeatureName(feature) {
|
|
||||||
return feature
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRestoreButtonText() {
|
|
||||||
return globalize.translate("sharedcomponents#HeaderAlreadyPaid")
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPeriodicMessageIntervalMs(feature) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
getProductInfo: getProductInfo,
|
|
||||||
beginPurchase: beginPurchase,
|
|
||||||
restorePurchase: restorePurchase,
|
|
||||||
getSubscriptionOptions: getSubscriptionOptions,
|
|
||||||
isUnlockedByDefault: isUnlockedByDefault,
|
|
||||||
getAdminFeatureName: getAdminFeatureName,
|
|
||||||
getRestoreButtonText: getRestoreButtonText,
|
|
||||||
getPeriodicMessageIntervalMs: getPeriodicMessageIntervalMs,
|
|
||||||
getPremiumInfoUrl: getPremiumInfoUrl
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -288,7 +288,7 @@ var Dashboard = {
|
||||||
var bowerPath = getBowerPath(),
|
var bowerPath = getBowerPath(),
|
||||||
apiClientBowerPath = bowerPath + "/emby-apiclient",
|
apiClientBowerPath = bowerPath + "/emby-apiclient",
|
||||||
embyWebComponentsBowerPath = bowerPath + "/emby-webcomponents";
|
embyWebComponentsBowerPath = bowerPath + "/emby-webcomponents";
|
||||||
"android" === self.appMode ? define("iapManager", ["cordova/iap"], returnFirstDependency) : "cordova" === self.appMode ? define("iapManager", ["cordova/iap"], returnFirstDependency) : define("iapManager", ["components/iap"], returnFirstDependency), "android" === self.appMode ? (define("filesystem", ["cordova/filesystem"], returnFirstDependency), define("cameraRoll", ["cordova/cameraroll"], returnFirstDependency)) : (define("filesystem", [embyWebComponentsBowerPath + "/filesystem"], returnFirstDependency), define("cameraRoll", [apiClientBowerPath + "/cameraroll"], returnFirstDependency)), window.IntersectionObserver && !browser.edge ? define("lazyLoader", [embyWebComponentsBowerPath + "/lazyloader/lazyloader-intersectionobserver"], returnFirstDependency) : define("lazyLoader", [embyWebComponentsBowerPath + "/lazyloader/lazyloader-scroll"], returnFirstDependency), "android" === self.appMode ? define("shell", ["cordova/shell"], returnFirstDependency) : define("shell", [embyWebComponentsBowerPath + "/shell"], returnFirstDependency), "cordova" === self.appMode || "android" === self.appMode ? (define("apiclientcore", ["bower_components/emby-apiclient/apiclient"], returnFirstDependency), define("apiclient", ["bower_components/emby-apiclient/apiclientex"], returnFirstDependency)) : define("apiclient", ["bower_components/emby-apiclient/apiclient"], returnFirstDependency), "cordova" === self.appMode || "android" === self.appMode ? define("wakeOnLan", ["cordova/wakeonlan"], returnFirstDependency) : define("wakeOnLan", ["bower_components/emby-apiclient/wakeonlan"], returnFirstDependency), define("actionsheet", ["webActionSheet"], returnFirstDependency), "registerElement" in document ? define("registerElement", []) : browser.msie ? define("registerElement", [bowerPath + "/webcomponentsjs/webcomponents-lite.min.js"], returnFirstDependency) : define("registerElement", [bowerPath + "/document-register-element/build/document-register-element"], returnFirstDependency), "android" === self.appMode ? define("serverdiscovery", ["cordova/serverdiscovery"], returnFirstDependency) : "cordova" === self.appMode ? define("serverdiscovery", ["cordova/serverdiscovery"], returnFirstDependency) : define("serverdiscovery", [apiClientBowerPath + "/serverdiscovery"], returnFirstDependency), "cordova" === self.appMode && browser.iOSVersion && browser.iOSVersion < 11 ? define("imageFetcher", ["cordova/imagestore"], returnFirstDependency) : define("imageFetcher", [embyWebComponentsBowerPath + "/images/basicimagefetcher"], returnFirstDependency);
|
"android" === self.appMode ? (define("filesystem", ["cordova/filesystem"], returnFirstDependency), define("cameraRoll", ["cordova/cameraroll"], returnFirstDependency)) : (define("filesystem", [embyWebComponentsBowerPath + "/filesystem"], returnFirstDependency), define("cameraRoll", [apiClientBowerPath + "/cameraroll"], returnFirstDependency)), window.IntersectionObserver && !browser.edge ? define("lazyLoader", [embyWebComponentsBowerPath + "/lazyloader/lazyloader-intersectionobserver"], returnFirstDependency) : define("lazyLoader", [embyWebComponentsBowerPath + "/lazyloader/lazyloader-scroll"], returnFirstDependency), "android" === self.appMode ? define("shell", ["cordova/shell"], returnFirstDependency) : define("shell", [embyWebComponentsBowerPath + "/shell"], returnFirstDependency), "cordova" === self.appMode || "android" === self.appMode ? (define("apiclientcore", ["bower_components/emby-apiclient/apiclient"], returnFirstDependency), define("apiclient", ["bower_components/emby-apiclient/apiclientex"], returnFirstDependency)) : define("apiclient", ["bower_components/emby-apiclient/apiclient"], returnFirstDependency), "cordova" === self.appMode || "android" === self.appMode ? define("wakeOnLan", ["cordova/wakeonlan"], returnFirstDependency) : define("wakeOnLan", ["bower_components/emby-apiclient/wakeonlan"], returnFirstDependency), define("actionsheet", ["webActionSheet"], returnFirstDependency), "registerElement" in document ? define("registerElement", []) : browser.msie ? define("registerElement", [bowerPath + "/webcomponentsjs/webcomponents-lite.min.js"], returnFirstDependency) : define("registerElement", [bowerPath + "/document-register-element/build/document-register-element"], returnFirstDependency), "android" === self.appMode ? define("serverdiscovery", ["cordova/serverdiscovery"], returnFirstDependency) : "cordova" === self.appMode ? define("serverdiscovery", ["cordova/serverdiscovery"], returnFirstDependency) : define("serverdiscovery", [apiClientBowerPath + "/serverdiscovery"], returnFirstDependency), "cordova" === self.appMode && browser.iOSVersion && browser.iOSVersion < 11 ? define("imageFetcher", ["cordova/imagestore"], returnFirstDependency) : define("imageFetcher", [embyWebComponentsBowerPath + "/images/basicimagefetcher"], returnFirstDependency);
|
||||||
var preferNativeAlerts = browser.tv;
|
var preferNativeAlerts = browser.tv;
|
||||||
preferNativeAlerts && window.alert ? define("alert", [embyWebComponentsBowerPath + "/alert/nativealert"], returnFirstDependency) : define("alert", [embyWebComponentsBowerPath + "/alert/alert"], returnFirstDependency), defineResizeObserver(), define("dialog", [embyWebComponentsBowerPath + "/dialog/dialog"], returnFirstDependency), preferNativeAlerts && window.confirm ? define("confirm", [embyWebComponentsBowerPath + "/confirm/nativeconfirm"], returnFirstDependency) : define("confirm", [embyWebComponentsBowerPath + "/confirm/confirm"], returnFirstDependency), (preferNativeAlerts || browser.xboxOne) && window.confirm ? define("prompt", [embyWebComponentsBowerPath + "/prompt/nativeprompt"], returnFirstDependency) : define("prompt", [embyWebComponentsBowerPath + "/prompt/prompt"], returnFirstDependency), browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4 ? define("loading", [embyWebComponentsBowerPath + "/loading/loading-legacy"], returnFirstDependency) : define("loading", [embyWebComponentsBowerPath + "/loading/loading-lite"], returnFirstDependency), define("multi-download", [embyWebComponentsBowerPath + "/multidownload"], returnFirstDependency), "android" === self.appMode ? define("fileDownloader", ["cordova/filedownloader"], returnFirstDependency) : define("fileDownloader", [embyWebComponentsBowerPath + "/filedownloader"], returnFirstDependency), define("localassetmanager", [apiClientBowerPath + "/localassetmanager"], returnFirstDependency), "cordova" === self.appMode || "android" === self.appMode ? define("castSenderApiLoader", [], getDummyCastSenderApiLoader) : define("castSenderApiLoader", [], getCastSenderApiLoader), self.Windows ? (define("bgtaskregister", ["environments/windows-uwp/bgtaskregister"], returnFirstDependency), define("transfermanager", ["environments/windows-uwp/transfermanager"], returnFirstDependency), define("filerepository", ["environments/windows-uwp/filerepository"], returnFirstDependency)) : "cordova" === self.appMode ? (define("filerepository", ["cordova/filerepository"], returnFirstDependency), define("transfermanager", ["filerepository"], returnFirstDependency)) : "android" === self.appMode ? (define("transfermanager", ["cordova/transfermanager"], returnFirstDependency), define("filerepository", ["cordova/filerepository"], returnFirstDependency)) : (define("transfermanager", [apiClientBowerPath + "/sync/transfermanager"], returnFirstDependency), define("filerepository", [apiClientBowerPath + "/sync/filerepository"], returnFirstDependency)), "android" === self.appMode ? define("localsync", ["cordova/localsync"], returnFirstDependency) : define("localsync", [apiClientBowerPath + "/sync/localsync"], returnFirstDependency)
|
preferNativeAlerts && window.alert ? define("alert", [embyWebComponentsBowerPath + "/alert/nativealert"], returnFirstDependency) : define("alert", [embyWebComponentsBowerPath + "/alert/alert"], returnFirstDependency), defineResizeObserver(), define("dialog", [embyWebComponentsBowerPath + "/dialog/dialog"], returnFirstDependency), preferNativeAlerts && window.confirm ? define("confirm", [embyWebComponentsBowerPath + "/confirm/nativeconfirm"], returnFirstDependency) : define("confirm", [embyWebComponentsBowerPath + "/confirm/confirm"], returnFirstDependency), (preferNativeAlerts || browser.xboxOne) && window.confirm ? define("prompt", [embyWebComponentsBowerPath + "/prompt/nativeprompt"], returnFirstDependency) : define("prompt", [embyWebComponentsBowerPath + "/prompt/prompt"], returnFirstDependency), browser.tizen || browser.operaTv || browser.chromecast || browser.orsay || browser.web0s || browser.ps4 ? define("loading", [embyWebComponentsBowerPath + "/loading/loading-legacy"], returnFirstDependency) : define("loading", [embyWebComponentsBowerPath + "/loading/loading-lite"], returnFirstDependency), define("multi-download", [embyWebComponentsBowerPath + "/multidownload"], returnFirstDependency), "android" === self.appMode ? define("fileDownloader", ["cordova/filedownloader"], returnFirstDependency) : define("fileDownloader", [embyWebComponentsBowerPath + "/filedownloader"], returnFirstDependency), define("localassetmanager", [apiClientBowerPath + "/localassetmanager"], returnFirstDependency), "cordova" === self.appMode || "android" === self.appMode ? define("castSenderApiLoader", [], getDummyCastSenderApiLoader) : define("castSenderApiLoader", [], getCastSenderApiLoader), self.Windows ? (define("bgtaskregister", ["environments/windows-uwp/bgtaskregister"], returnFirstDependency), define("transfermanager", ["environments/windows-uwp/transfermanager"], returnFirstDependency), define("filerepository", ["environments/windows-uwp/filerepository"], returnFirstDependency)) : "cordova" === self.appMode ? (define("filerepository", ["cordova/filerepository"], returnFirstDependency), define("transfermanager", ["filerepository"], returnFirstDependency)) : "android" === self.appMode ? (define("transfermanager", ["cordova/transfermanager"], returnFirstDependency), define("filerepository", ["cordova/filerepository"], returnFirstDependency)) : (define("transfermanager", [apiClientBowerPath + "/sync/transfermanager"], returnFirstDependency), define("filerepository", [apiClientBowerPath + "/sync/filerepository"], returnFirstDependency)), "android" === self.appMode ? define("localsync", ["cordova/localsync"], returnFirstDependency) : define("localsync", [apiClientBowerPath + "/sync/localsync"], returnFirstDependency)
|
||||||
}
|
}
|
||||||
|
@ -872,7 +872,7 @@ var Dashboard = {
|
||||||
var deps = [],
|
var deps = [],
|
||||||
isBackgroundSync = -1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync"),
|
isBackgroundSync = -1 !== self.location.href.toString().toLowerCase().indexOf("start=backgroundsync"),
|
||||||
isInBackground = isBackgroundSync;
|
isInBackground = isBackgroundSync;
|
||||||
deps.push("apphost"), isInBackground || (deps.push("appRouter"), deps.push("scripts/themeloader"), browser.iOS && deps.push("css!devices/ios/ios.css"), "cordova" !== self.appMode && "android" !== self.appMode || deps.push("registrationServices"), deps.push("libraryMenu")), console.log("onAppReady - loading dependencies"), require(deps, function(appHost, pageObjects) {
|
deps.push("apphost"), isInBackground || (deps.push("appRouter"), deps.push("scripts/themeloader"), browser.iOS && deps.push("css!devices/ios/ios.css"), deps.push("libraryMenu")), console.log("onAppReady - loading dependencies"), require(deps, function(appHost, pageObjects) {
|
||||||
if (console.log("Loaded dependencies in onAppReady"), window.Emby = {}, isBackgroundSync) return void syncNow();
|
if (console.log("Loaded dependencies in onAppReady"), window.Emby = {}, isBackgroundSync) return void syncNow();
|
||||||
window.Emby.Page = pageObjects, defineCoreRoutes(appHost), Emby.Page.start({
|
window.Emby.Page = pageObjects, defineCoreRoutes(appHost), Emby.Page.start({
|
||||||
click: !1,
|
click: !1,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue