mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
module resolution for appRouter and moved controllers to dir
This commit is contained in:
parent
d49fee2a29
commit
9c758a8d85
49 changed files with 464 additions and 530 deletions
140
src/controllers/addpluginpage.js
Normal file
140
src/controllers/addpluginpage.js
Normal file
|
@ -0,0 +1,140 @@
|
|||
define(["jQuery", "loading", "libraryMenu", "globalize", "connectionManager", "emby-linkbutton"], function($, loading, libraryMenu, globalize, connectionManager) {
|
||||
"use strict";
|
||||
|
||||
function populateHistory(packageInfo, page) {
|
||||
for (var html = "", i = 0, length = Math.min(packageInfo.versions.length, 10); i < length; i++) {
|
||||
var version = packageInfo.versions[i];
|
||||
html += '<h2 style="margin:.5em 0;">' + version.versionStr + " (" + version.classification + ")</h2>", html += '<div style="margin-bottom:1.5em;">' + version.description + "</div>"
|
||||
}
|
||||
$("#revisionHistory", page).html(html)
|
||||
}
|
||||
|
||||
function populateVersions(packageInfo, page, installedPlugin) {
|
||||
for (var html = "", i = 0, length = packageInfo.versions.length; i < length; i++) {
|
||||
var version = packageInfo.versions[i];
|
||||
html += '<option value="' + version.versionStr + "|" + version.classification + '">' + version.versionStr + " (" + version.classification + ")</option>"
|
||||
}
|
||||
var selectmenu = $("#selectVersion", page).html(html);
|
||||
installedPlugin || $("#pCurrentVersion", page).hide().html("");
|
||||
var packageVersion = packageInfo.versions.filter(function(current) {
|
||||
return "Release" == current.classification
|
||||
})[0];
|
||||
if (packageVersion || (packageVersion = packageInfo.versions.filter(function(current) {
|
||||
return "Beta" == current.classification
|
||||
})[0]), packageVersion) {
|
||||
var val = packageVersion.versionStr + "|" + packageVersion.classification;
|
||||
selectmenu.val(val)
|
||||
}
|
||||
}
|
||||
|
||||
function renderPackage(pkg, installedPlugins, pluginSecurityInfo, page) {
|
||||
var installedPlugin = installedPlugins.filter(function(ip) {
|
||||
return ip.Name == pkg.name
|
||||
})[0];
|
||||
populateVersions(pkg, page, installedPlugin);
|
||||
populateHistory(pkg, page);
|
||||
$(".pluginName", page).html(pkg.name);
|
||||
if ("Server" == pkg.targetSystem) {
|
||||
$("#btnInstallDiv", page).removeClass("hide");
|
||||
$("#nonServerMsg", page).hide();
|
||||
$("#pSelectVersion", page).removeClass("hide");
|
||||
} else {
|
||||
$("#btnInstallDiv", page).addClass("hide");
|
||||
$("#pSelectVersion", page).addClass("hide");
|
||||
var msg = globalize.translate("MessageInstallPluginFromApp");
|
||||
$("#nonServerMsg", page).html(msg).show();
|
||||
}
|
||||
if (pkg.shortDescription) {
|
||||
$("#tagline", page).show().html(pkg.shortDescription);
|
||||
} else {
|
||||
$("#tagline", page).hide();
|
||||
}
|
||||
$("#overview", page).html(pkg.overview || "");
|
||||
$("#developer", page).html(pkg.owner);
|
||||
if (pkg.richDescUrl) {
|
||||
$("#pViewWebsite", page).show();
|
||||
$("#pViewWebsite a", page).attr("href", pkg.richDescUrl);
|
||||
} else {
|
||||
$("#pViewWebsite", page).hide();
|
||||
}
|
||||
if (pkg.previewImage || pkg.thumbImage) {
|
||||
var img = pkg.previewImage ? pkg.previewImage : pkg.thumbImage;
|
||||
$("#pPreviewImage", page).show().html("<img class='pluginPreviewImg' src='" + img + "' style='max-width: 100%;' />");
|
||||
} else {
|
||||
$("#pPreviewImage", page).hide().html("");
|
||||
}
|
||||
if (installedPlugin) {
|
||||
var currentVersionText = globalize.translate("MessageYouHaveVersionInstalled").replace("{0}", "<strong>" + installedPlugin.Version + "</strong>");
|
||||
$("#pCurrentVersion", page).show().html(currentVersionText);
|
||||
} else {
|
||||
$("#pCurrentVersion", page).hide().html("");
|
||||
}
|
||||
loading.hide();
|
||||
}
|
||||
|
||||
function alertText(options) {
|
||||
require(["alert"], function(alert) {
|
||||
alert(options)
|
||||
})
|
||||
}
|
||||
|
||||
function performInstallation(page, packageName, guid, updateClass, version) {
|
||||
var developer = $("#developer", page).html().toLowerCase(),
|
||||
alertCallback = function(confirmed) {
|
||||
confirmed && (loading.show(), page.querySelector("#btnInstall").disabled = !0, ApiClient.installPlugin(packageName, guid, updateClass, version).then(function() {
|
||||
loading.hide(), alertText(globalize.translate("PluginInstalledMessage"))
|
||||
}))
|
||||
};
|
||||
if ("luke" != developer && "ebr" != developer) {
|
||||
loading.hide();
|
||||
var msg = globalize.translate("MessagePluginInstallDisclaimer");
|
||||
msg += "<br/>", msg += "<br/>", msg += globalize.translate("PleaseConfirmPluginInstallation"), require(["confirm"], function(confirm) {
|
||||
confirm(msg, globalize.translate("HeaderConfirmPluginInstallation")).then(function() {
|
||||
alertCallback(!0)
|
||||
}, function() {
|
||||
alertCallback(!1)
|
||||
})
|
||||
})
|
||||
} else alertCallback(!0)
|
||||
}
|
||||
return function(view, params) {
|
||||
var onSubmit = function() {
|
||||
loading.show();
|
||||
var page = $(this).parents("#addPluginPage")[0],
|
||||
name = params.name,
|
||||
guid = params.guid;
|
||||
return ApiClient.getInstalledPlugins().then(function(plugins) {
|
||||
var installedPlugin = plugins.filter(function(ip) {
|
||||
return ip.Name == name
|
||||
})[0],
|
||||
vals = $("#selectVersion", page).val().split("|"),
|
||||
version = vals[0];
|
||||
installedPlugin && installedPlugin.Version == version ? (loading.hide(), Dashboard.alert({
|
||||
message: globalize.translate("MessageAlreadyInstalled"),
|
||||
title: globalize.translate("HeaderPluginInstallation")
|
||||
})) : performInstallation(page, name, guid, vals[1], version)
|
||||
}), !1
|
||||
};
|
||||
$(".addPluginForm", view).on("submit", onSubmit), view.addEventListener("viewshow", function() {
|
||||
var page = this;
|
||||
loading.show();
|
||||
var name = params.name,
|
||||
guid = params.guid,
|
||||
promise1 = ApiClient.getPackageInfo(name, guid),
|
||||
promise2 = ApiClient.getInstalledPlugins();
|
||||
connectionManager.getRegistrationInfo("themes", ApiClient, {
|
||||
viewOnly: !0
|
||||
}), Promise.all([promise1, promise2]).then(function(responses) {
|
||||
connectionManager.getRegistrationInfo("themes", ApiClient, {
|
||||
viewOnly: !0
|
||||
}).then(function() {
|
||||
renderPackage(responses[0], responses[1], {
|
||||
IsMBSupporter: !0
|
||||
}, page)
|
||||
}, function() {
|
||||
renderPackage(responses[0], responses[1], {}, page)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
65
src/controllers/addserver.js
Normal file
65
src/controllers/addserver.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
define(["appSettings", "loading", "browser", "emby-linkbutton"], function(appSettings, loading, browser) {
|
||||
"use strict";
|
||||
|
||||
function handleConnectionResult(page, result) {
|
||||
loading.hide();
|
||||
switch (result.State) {
|
||||
case "SignedIn":
|
||||
var apiClient = result.ApiClient;
|
||||
Dashboard.onServerChanged(apiClient.getCurrentUserId(), apiClient.accessToken(), apiClient), Dashboard.navigate("home.html");
|
||||
break;
|
||||
case "ServerSignIn":
|
||||
Dashboard.navigate("login.html?serverid=" + result.Servers[0].Id, false, "none");
|
||||
break;
|
||||
case "ServerSelection":
|
||||
Dashboard.navigate("selectserver.html", false, "none");
|
||||
break;
|
||||
case "ServerUpdateNeeded":
|
||||
Dashboard.alert({
|
||||
message: Globalize.translate("ServerUpdateNeeded", '<a href="https://github.com/jellyfin/jellyfin">https://github.com/jellyfin/jellyfin</a>')
|
||||
});
|
||||
break;
|
||||
case "Unavailable":
|
||||
Dashboard.alert({
|
||||
message: Globalize.translate("MessageUnableToConnectToServer"),
|
||||
title: Globalize.translate("HeaderConnectionFailure")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function submitManualServer(page) {
|
||||
var host = page.querySelector("#txtServerHost").value;
|
||||
var port = page.querySelector("#txtServerPort").value;
|
||||
if (port) {
|
||||
host += ":" + port;
|
||||
}
|
||||
|
||||
loading.show();
|
||||
ConnectionManager.connectToAddress(host, {
|
||||
enableAutoLogin: appSettings.enableAutoLogin()
|
||||
}).then(function(result) {
|
||||
handleConnectionResult(page, result);
|
||||
}, function() {
|
||||
handleConnectionResult(page, {
|
||||
State: "Unavailable"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return function(view, params) {
|
||||
view.querySelector(".manualServerForm").addEventListener("submit", onManualServerSubmit);
|
||||
view.querySelector(".btnCancelManualServer").addEventListener("click", goBack);
|
||||
|
||||
function onManualServerSubmit(e) {
|
||||
submitManualServer(view);
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
require(["appRouter"], function(appRouter) {
|
||||
appRouter.back();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
127
src/controllers/dashboardgeneral.js
Normal file
127
src/controllers/dashboardgeneral.js
Normal file
|
@ -0,0 +1,127 @@
|
|||
define(["jQuery", "loading", "fnchecked", "emby-checkbox", "emby-textarea", "emby-input", "emby-select", "emby-linkbutton"], function($, loading) {
|
||||
"use strict";
|
||||
|
||||
function loadPage(page, config, languageOptions, systemInfo) {
|
||||
if (systemInfo.CanLaunchWebBrowser) {
|
||||
page.querySelector("#fldRunWebAppAtStartup").classList.remove("hide");
|
||||
} else {
|
||||
page.querySelector("#fldRunWebAppAtStartup").classList.add("hide");
|
||||
}
|
||||
page.querySelector("#txtCachePath").value = config.CachePath || "";
|
||||
$("#txtMetadataPath", page).val(config.MetadataPath || "");
|
||||
$("#txtMetadataNetworkPath", page).val(config.MetadataNetworkPath || "");
|
||||
$("#selectLocalizationLanguage", page).html(languageOptions.map(function(language) {
|
||||
return '<option value="' + language.Value + '">' + language.Name + "</option>"
|
||||
})).val(config.UICulture);
|
||||
currentLanguage = config.UICulture;
|
||||
if (systemInfo.CanSelfUpdate) {
|
||||
page.querySelector(".fldAutomaticUpdates").classList.remove("hide");
|
||||
} else {
|
||||
page.querySelector(".fldAutomaticUpdates").classList.add("hide");
|
||||
}
|
||||
$("#chkEnableAutomaticServerUpdates", page).checked(config.EnableAutoUpdate);
|
||||
$("#chkEnableAutomaticRestart", page).checked(config.EnableAutomaticRestart);
|
||||
if (systemInfo.CanSelfRestart) {
|
||||
page.querySelector("#fldEnableAutomaticRestart").classList.remove("hide");
|
||||
} else {
|
||||
page.querySelector("#fldEnableAutomaticRestart").classList.add("hide");
|
||||
}
|
||||
if (systemInfo.CanSelfRestart || systemInfo.CanSelfUpdate) {
|
||||
$(".autoUpdatesContainer", page).removeClass("hide");
|
||||
} else {
|
||||
$(".autoUpdatesContainer", page).addClass("hide");
|
||||
}
|
||||
loading.hide();
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
loading.show();
|
||||
var form = this;
|
||||
$(form).parents(".page");
|
||||
return ApiClient.getServerConfiguration().then(function(config) {
|
||||
config.UICulture = $("#selectLocalizationLanguage", form).val();
|
||||
config.CachePath = form.querySelector("#txtCachePath").value;
|
||||
config.MetadataPath = $("#txtMetadataPath", form).val();
|
||||
config.MetadataNetworkPath = $("#txtMetadataNetworkPath", form).val();
|
||||
var requiresReload = (config.UICulture !== currentLanguage);
|
||||
config.EnableAutomaticRestart = $("#chkEnableAutomaticRestart", form).checked();
|
||||
config.EnableAutoUpdate = $("#chkEnableAutomaticServerUpdates", form).checked();
|
||||
ApiClient.updateServerConfiguration(config).then(function() {
|
||||
ApiClient.getNamedConfiguration(brandingConfigKey).then(function(brandingConfig) {
|
||||
brandingConfig.LoginDisclaimer = form.querySelector("#txtLoginDisclaimer").value;
|
||||
brandingConfig.CustomCss = form.querySelector("#txtCustomCss").value;
|
||||
if (currentBrandingOptions && brandingConfig.CustomCss !== currentBrandingOptions.CustomCss) {
|
||||
requiresReload = true;
|
||||
}
|
||||
ApiClient.updateNamedConfiguration(brandingConfigKey, brandingConfig).then(function() {
|
||||
Dashboard.processServerConfigurationUpdateResult();
|
||||
if (requiresReload && !AppInfo.isNativeApp) {
|
||||
window.location.reload(true);
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
}), !1
|
||||
}
|
||||
|
||||
var currentBrandingOptions;
|
||||
var currentLanguage;
|
||||
var brandingConfigKey = "branding";
|
||||
|
||||
return function(view, params) {
|
||||
$("#btnSelectCachePath", view).on("click.selectDirectory", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
callback: function(path) {
|
||||
if (path) {
|
||||
view.querySelector("#txtCachePath").value = path;
|
||||
}
|
||||
picker.close();
|
||||
},
|
||||
validateWriteable: true,
|
||||
header: Globalize.translate("HeaderSelectServerCachePath"),
|
||||
instruction: Globalize.translate("HeaderSelectServerCachePathHelp")
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
$("#btnSelectMetadataPath", view).on("click.selectDirectory", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser();
|
||||
picker.show({
|
||||
path: $("#txtMetadataPath", view).val(),
|
||||
networkSharePath: $("#txtMetadataNetworkPath", view).val(),
|
||||
callback: function(path, networkPath) {
|
||||
if (path) {
|
||||
$("#txtMetadataPath", view).val(path);
|
||||
}
|
||||
if (networkPath) {
|
||||
$("#txtMetadataNetworkPath", view).val(networkPath);
|
||||
}
|
||||
picker.close();
|
||||
},
|
||||
validateWriteable: true,
|
||||
header: Globalize.translate("HeaderSelectMetadataPath"),
|
||||
instruction: Globalize.translate("HeaderSelectMetadataPathHelp"),
|
||||
enableNetworkSharePath: true
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
$(".dashboardGeneralForm", view).off("submit", onSubmit).on("submit", onSubmit);
|
||||
view.addEventListener("viewshow", function() {
|
||||
var promiseConfig = ApiClient.getServerConfiguration();
|
||||
var promiseLanguageOptions = ApiClient.getJSON(ApiClient.getUrl("Localization/Options"));
|
||||
var promiseSystemInfo = ApiClient.getSystemInfo();
|
||||
Promise.all([promiseConfig, promiseLanguageOptions, promiseSystemInfo]).then(function(responses) {
|
||||
loadPage(view, responses[0], responses[1], responses[2]);
|
||||
});
|
||||
ApiClient.getNamedConfiguration(brandingConfigKey).then(function(config) {
|
||||
currentBrandingOptions = config;
|
||||
view.querySelector("#txtLoginDisclaimer").value = config.LoginDisclaimer || "";
|
||||
view.querySelector("#txtCustomCss").value = config.CustomCss || "";
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
105
src/controllers/dashboardhosting.js
Normal file
105
src/controllers/dashboardhosting.js
Normal file
|
@ -0,0 +1,105 @@
|
|||
define(["loading", "libraryMenu", "globalize", "emby-checkbox", "emby-select"], function(loading, libraryMenu, globalize) {
|
||||
"use strict";
|
||||
|
||||
function onSubmit(e) {
|
||||
var form = this,
|
||||
localAddress = form.querySelector("#txtLocalAddress").value,
|
||||
enableUpnp = form.querySelector("#chkEnableUpnp").checked;
|
||||
confirmSelections(localAddress, enableUpnp, function() {
|
||||
var validationResult = getValidationAlert(form);
|
||||
if (validationResult) return void alertText(validationResult);
|
||||
validateHttps(form).then(function() {
|
||||
loading.show(), ApiClient.getServerConfiguration().then(function(config) {
|
||||
config.LocalNetworkSubnets = form.querySelector("#txtLanNetworks").value.split(",").map(function(s) {
|
||||
return s.trim()
|
||||
}).filter(function(s) {
|
||||
return s.length > 0
|
||||
}), config.RemoteIPFilter = form.querySelector("#txtExternalAddressFilter").value.split(",").map(function(s) {
|
||||
return s.trim()
|
||||
}).filter(function(s) {
|
||||
return s.length > 0
|
||||
}), config.IsRemoteIPFilterBlacklist = "blacklist" === form.querySelector("#selectExternalAddressFilterMode").value, config.PublicPort = form.querySelector("#txtPublicPort").value, config.PublicHttpsPort = form.querySelector("#txtPublicHttpsPort").value;
|
||||
var httpsMode = form.querySelector("#selectHttpsMode").value;
|
||||
"proxy" === httpsMode ? (config.EnableHttps = !0, config.RequireHttps = !1, config.IsBehindProxy = !0) : "required" === httpsMode ? (config.EnableHttps = !0, config.RequireHttps = !0, config.IsBehindProxy = !1) : "enabled" === httpsMode ? (config.EnableHttps = !0, config.RequireHttps = !1, config.IsBehindProxy = !1) : (config.EnableHttps = !1, config.RequireHttps = !1, config.IsBehindProxy = !1), config.HttpsPortNumber = form.querySelector("#txtHttpsPort").value, config.HttpServerPortNumber = form.querySelector("#txtPortNumber").value, config.EnableUPnP = enableUpnp, config.WanDdns = form.querySelector("#txtDdns").value, config.EnableRemoteAccess = form.querySelector("#chkRemoteAccess").checked, config.CertificatePath = form.querySelector("#txtCertificatePath").value || null, config.CertificatePassword = form.querySelector("#txtCertPassword").value || null, config.LocalNetworkAddresses = localAddress ? [localAddress] : [], ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult, Dashboard.processErrorResponse)
|
||||
})
|
||||
})
|
||||
}), e.preventDefault()
|
||||
}
|
||||
|
||||
function triggerChange(select) {
|
||||
var evt = document.createEvent("HTMLEvents");
|
||||
evt.initEvent("change", !1, !0), select.dispatchEvent(evt)
|
||||
}
|
||||
|
||||
function getValidationAlert(form) {
|
||||
return form.querySelector("#txtPublicPort").value === form.querySelector("#txtPublicHttpsPort").value ? "The public http and https ports must be different." : form.querySelector("#txtPortNumber").value === form.querySelector("#txtHttpsPort").value ? "The http and https ports must be different." : null
|
||||
}
|
||||
|
||||
function validateHttps(form) {
|
||||
var certPath = form.querySelector("#txtCertificatePath").value || null,
|
||||
httpsMode = form.querySelector("#selectHttpsMode").value;
|
||||
return "enabled" !== httpsMode && "required" !== httpsMode || certPath ? Promise.resolve() : new Promise(function(resolve, reject) {
|
||||
return alertText({
|
||||
title: globalize.translate("TitleHostingSettings"),
|
||||
text: globalize.translate("HttpsRequiresCert")
|
||||
}).then(reject, reject)
|
||||
})
|
||||
}
|
||||
|
||||
function alertText(options) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
require(["alert"], function(alert) {
|
||||
alert(options).then(resolve, reject)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function confirmSelections(localAddress, enableUpnp, callback) {
|
||||
localAddress || !enableUpnp ? alertText({
|
||||
title: globalize.translate("TitleHostingSettings"),
|
||||
text: globalize.translate("SettingsWarning")
|
||||
}).then(callback) : callback()
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "dashboardhosting.html",
|
||||
name: globalize.translate("TabHosting")
|
||||
}, {
|
||||
href: "serversecurity.html",
|
||||
name: globalize.translate("TabSecurity")
|
||||
}]
|
||||
}
|
||||
return function(view, params) {
|
||||
function loadPage(page, config) {
|
||||
page.querySelector("#txtPortNumber").value = config.HttpServerPortNumber, page.querySelector("#txtPublicPort").value = config.PublicPort, page.querySelector("#txtPublicHttpsPort").value = config.PublicHttpsPort, page.querySelector("#txtLocalAddress").value = config.LocalNetworkAddresses[0] || "", page.querySelector("#txtLanNetworks").value = (config.LocalNetworkSubnets || []).join(", "), page.querySelector("#txtExternalAddressFilter").value = (config.RemoteIPFilter || []).join(", "), page.querySelector("#selectExternalAddressFilterMode").value = config.IsRemoteIPFilterBlacklist ? "blacklist" : "whitelist", page.querySelector("#chkRemoteAccess").checked = null == config.EnableRemoteAccess || config.EnableRemoteAccess;
|
||||
var selectHttpsMode = page.querySelector("#selectHttpsMode");
|
||||
config.IsBehindProxy ? selectHttpsMode.value = "proxy" : config.RequireHttps ? selectHttpsMode.value = "required" : config.EnableHttps ? selectHttpsMode.value = "enabled" : selectHttpsMode.value = "disabled", page.querySelector("#txtHttpsPort").value = config.HttpsPortNumber, page.querySelector("#txtDdns").value = config.WanDdns || "";
|
||||
var txtCertificatePath = page.querySelector("#txtCertificatePath");
|
||||
txtCertificatePath.value = config.CertificatePath || "", page.querySelector("#txtCertPassword").value = config.CertificatePassword || "", page.querySelector("#chkEnableUpnp").checked = config.EnableUPnP, onCertPathChange.call(txtCertificatePath), triggerChange(page.querySelector("#chkRemoteAccess")), loading.hide()
|
||||
}
|
||||
|
||||
function onCertPathChange() {
|
||||
this.value ? view.querySelector("#txtDdns").setAttribute("required", "required") : view.querySelector("#txtDdns").removeAttribute("required")
|
||||
}
|
||||
view.querySelector("#chkRemoteAccess").addEventListener("change", function() {
|
||||
this.checked ? (view.querySelector(".fldExternalAddressFilter").classList.remove("hide"), view.querySelector(".fldExternalAddressFilterMode").classList.remove("hide"), view.querySelector(".fldPublicPort").classList.remove("hide"), view.querySelector(".fldPublicHttpsPort").classList.remove("hide"), view.querySelector(".fldDdns").classList.remove("hide"), view.querySelector(".fldCertificatePath").classList.remove("hide"), view.querySelector(".fldCertPassword").classList.remove("hide"), view.querySelector(".fldHttpsMode").classList.remove("hide"), view.querySelector(".fldEnableUpnp").classList.remove("hide")) : (view.querySelector(".fldExternalAddressFilter").classList.add("hide"), view.querySelector(".fldExternalAddressFilterMode").classList.add("hide"), view.querySelector(".fldPublicPort").classList.add("hide"), view.querySelector(".fldPublicHttpsPort").classList.add("hide"), view.querySelector(".fldDdns").classList.add("hide"), view.querySelector(".fldCertificatePath").classList.add("hide"), view.querySelector(".fldCertPassword").classList.add("hide"), view.querySelector(".fldHttpsMode").classList.add("hide"), view.querySelector(".fldEnableUpnp").classList.add("hide"))
|
||||
}), view.querySelector("#btnSelectCertPath").addEventListener("click", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
includeFiles: !0,
|
||||
includeDirectories: !0,
|
||||
callback: function(path) {
|
||||
path && (view.querySelector("#txtCertificatePath").value = path), picker.close()
|
||||
},
|
||||
header: globalize.translate("HeaderSelectCertificatePath")
|
||||
})
|
||||
})
|
||||
}), view.querySelector(".dashboardHostingForm").addEventListener("submit", onSubmit), view.querySelector("#txtCertificatePath").addEventListener("change", onCertPathChange), view.addEventListener("viewshow", function(e) {
|
||||
libraryMenu.setTabs("adminadvanced", 0, getTabs), loading.show(), ApiClient.getServerConfiguration().then(function(config) {
|
||||
loadPage(view, config)
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
918
src/controllers/dashboardpage.js
Normal file
918
src/controllers/dashboardpage.js
Normal file
|
@ -0,0 +1,918 @@
|
|||
define(["datetime", "events", "itemHelper", "serverNotifications", "dom", "globalize", "loading", "connectionManager", "playMethodHelper", "cardBuilder", "imageLoader", "components/activitylog", "humanedate", "listViewStyle", "emby-linkbutton", "flexStyles", "emby-button", "emby-itemscontainer"], function (datetime, events, itemHelper, serverNotifications, dom, globalize, loading, connectionManager, playMethodHelper, cardBuilder, imageLoader, ActivityLog) {
|
||||
"use strict";
|
||||
|
||||
function onConnectionHelpClick(evt) {
|
||||
evt.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
function buttonEnabled(elem, enabled) {
|
||||
if (enabled) {
|
||||
elem.setAttribute("disabled", "");
|
||||
elem.removeAttribute("disabled");
|
||||
} else {
|
||||
elem.setAttribute("disabled", "disabled");
|
||||
}
|
||||
}
|
||||
|
||||
function onEditServerNameClick(evt) {
|
||||
var page = dom.parentWithClass(this, "page");
|
||||
|
||||
require(["prompt"], function (prompt) {
|
||||
prompt({
|
||||
label: globalize.translate("LabelFriendlyServerName"),
|
||||
description: globalize.translate("LabelFriendlyServerNameHelp"),
|
||||
value: page.querySelector(".serverNameHeader").innerHTML,
|
||||
confirmText: globalize.translate("ButtonSave")
|
||||
}).then(function (value) {
|
||||
loading.show();
|
||||
ApiClient.getServerConfiguration().then(function (config) {
|
||||
config.ServerName = value;
|
||||
ApiClient.updateServerConfiguration(config).then(function () {
|
||||
page.querySelector(".serverNameHeader").innerHTML = value;
|
||||
loading.hide();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
evt.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
function showPlaybackInfo(btn, session) {
|
||||
require(["alert"], function (alert) {
|
||||
var showTranscodeReasons;
|
||||
var title;
|
||||
var text = [];
|
||||
var displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session);
|
||||
var isDirectStream = "DirectStream" === displayPlayMethod;
|
||||
var isTranscode = "Transcode" === displayPlayMethod;
|
||||
|
||||
if (isDirectStream) {
|
||||
title = globalize.translate("DirectStreaming");
|
||||
text.push(globalize.translate("DirectStreamHelp1"));
|
||||
text.push("<br/>");
|
||||
text.push(globalize.translate("DirectStreamHelp2"));
|
||||
} else if (isTranscode) {
|
||||
title = globalize.translate("Transcoding");
|
||||
text.push(globalize.translate("MediaIsBeingConverted"));
|
||||
|
||||
if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) {
|
||||
text.push("<br/>");
|
||||
text.push(globalize.translate("LabelReasonForTranscoding"));
|
||||
session.TranscodingInfo.TranscodeReasons.forEach(function (transcodeReason) {
|
||||
text.push(globalize.translate("" + transcodeReason));
|
||||
});
|
||||
}
|
||||
}
|
||||
alert({
|
||||
text: text.join("<br/>"),
|
||||
title: title
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showSendMessageForm(btn, session) {
|
||||
require(["prompt"], function (prompt) {
|
||||
prompt({
|
||||
title: globalize.translate("HeaderSendMessage"),
|
||||
label: globalize.translate("LabelMessageText"),
|
||||
confirmText: globalize.translate("ButtonSend")
|
||||
}).then(function (text) {
|
||||
if (text) {
|
||||
connectionManager.getApiClient(session.ServerId).sendMessageCommand(session.Id, {
|
||||
Text: text,
|
||||
TimeoutMs: 5e3
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showOptionsMenu(btn, session) {
|
||||
require(["actionsheet"], function (actionsheet) {
|
||||
var menuItems = [];
|
||||
|
||||
if (session.ServerId && session.DeviceId !== connectionManager.deviceId()) {
|
||||
menuItems.push({
|
||||
name: globalize.translate("SendMessage"),
|
||||
id: "sendmessage"
|
||||
});
|
||||
}
|
||||
|
||||
if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length) {
|
||||
menuItems.push({
|
||||
name: globalize.translate("ViewPlaybackInfo"),
|
||||
id: "transcodinginfo"
|
||||
});
|
||||
}
|
||||
|
||||
return actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: btn
|
||||
}).then(function (id) {
|
||||
switch (id) {
|
||||
case "sendmessage":
|
||||
showSendMessageForm(btn, session);
|
||||
break;
|
||||
case "transcodinginfo":
|
||||
showPlaybackInfo(btn, session);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onActiveDevicesClick(evt) {
|
||||
var btn = dom.parentWithClass(evt.target, "sessionCardButton");
|
||||
|
||||
if (btn) {
|
||||
var card = dom.parentWithClass(btn, "card");
|
||||
|
||||
if (card) {
|
||||
var sessionId = card.id;
|
||||
var session = (DashboardPage.sessionsList || []).filter(function (dashboardSession) {
|
||||
return "session" + dashboardSession.Id === sessionId;
|
||||
})[0];
|
||||
|
||||
if (session) {
|
||||
if (btn.classList.contains("btnCardOptions")) {
|
||||
showOptionsMenu(btn, session);
|
||||
} else if (btn.classList.contains("btnSessionInfo")) {
|
||||
showPlaybackInfo(btn, session);
|
||||
} else if (btn.classList.contains("btnSessionSendMessage")) {
|
||||
showSendMessageForm(btn, session);
|
||||
} else if (btn.classList.contains("btnSessionStop")) {
|
||||
connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, "Stop");
|
||||
} else if (btn.classList.contains("btnSessionPlayPause") && session.PlayState) {
|
||||
connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, "PlayPause");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function filterSessions(sessions) {
|
||||
var list = [];
|
||||
var minActiveDate = new Date().getTime() - 9e5;
|
||||
|
||||
for (var i = 0, length = sessions.length; i < length; i++) {
|
||||
var session = sessions[i];
|
||||
|
||||
if (!session.NowPlayingItem && !session.UserId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (datetime.parseISO8601Date(session.LastActivityDate, true).getTime() >= minActiveDate) {
|
||||
list.push(session);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
function refreshActiveRecordings(view, apiClient) {
|
||||
apiClient.getLiveTvRecordings({
|
||||
UserId: Dashboard.getCurrentUserId(),
|
||||
IsInProgress: true,
|
||||
Fields: "CanDelete,PrimaryImageAspectRatio",
|
||||
EnableTotalRecordCount: false,
|
||||
EnableImageTypes: "Primary,Thumb,Backdrop"
|
||||
}).then(function (result) {
|
||||
var itemsContainer = view.querySelector(".activeRecordingItems");
|
||||
|
||||
if (!result.Items.length) {
|
||||
view.querySelector(".activeRecordingsSection").classList.add("hide");
|
||||
return void (itemsContainer.innerHTML = "");
|
||||
}
|
||||
|
||||
view.querySelector(".activeRecordingsSection").classList.remove("hide");
|
||||
itemsContainer.innerHTML = cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "auto",
|
||||
defaultShape: "backdrop",
|
||||
showTitle: true,
|
||||
showParentTitle: true,
|
||||
coverImage: true,
|
||||
cardLayout: false,
|
||||
centerText: true,
|
||||
preferThumb: "auto",
|
||||
overlayText: false,
|
||||
overlayMoreButton: true,
|
||||
action: "none",
|
||||
centerPlayButton: true
|
||||
});
|
||||
imageLoader.lazyChildren(itemsContainer);
|
||||
});
|
||||
}
|
||||
|
||||
function reloadSystemInfo(view, apiClient) {
|
||||
apiClient.getSystemInfo().then(function (systemInfo) {
|
||||
view.querySelector(".serverNameHeader").innerHTML = systemInfo.ServerName;
|
||||
var localizedVersion = globalize.translate("LabelVersionNumber", systemInfo.Version);
|
||||
|
||||
if (systemInfo.SystemUpdateLevel && "Release" != systemInfo.SystemUpdateLevel) {
|
||||
localizedVersion += " " + globalize.translate("Option" + systemInfo.SystemUpdateLevel).toLowerCase();
|
||||
}
|
||||
|
||||
if (systemInfo.CanSelfRestart) {
|
||||
view.querySelector("#btnRestartServer").classList.remove("hide");
|
||||
} else {
|
||||
view.querySelector("#btnRestartServer").classList.add("hide");
|
||||
}
|
||||
|
||||
view.querySelector("#appVersionNumber").innerHTML = localizedVersion;
|
||||
|
||||
if (systemInfo.SupportsHttps) {
|
||||
view.querySelector("#ports").innerHTML = globalize.translate("LabelRunningOnPorts", systemInfo.HttpServerPortNumber, systemInfo.HttpsPortNumber);
|
||||
} else {
|
||||
view.querySelector("#ports").innerHTML = globalize.translate("LabelRunningOnPort", systemInfo.HttpServerPortNumber);
|
||||
}
|
||||
|
||||
DashboardPage.renderUrls(view, systemInfo);
|
||||
DashboardPage.renderPaths(view, systemInfo);
|
||||
});
|
||||
}
|
||||
|
||||
function renderInfo(view, sessions, forceUpdate) {
|
||||
sessions = filterSessions(sessions);
|
||||
renderActiveConnections(view, sessions);
|
||||
loading.hide();
|
||||
}
|
||||
|
||||
function pollForInfo(view, apiClient, forceUpdate) {
|
||||
apiClient.getSessions({
|
||||
ActiveWithinSeconds: 960
|
||||
}).then(function (sessions) {
|
||||
renderInfo(view, sessions, forceUpdate);
|
||||
});
|
||||
apiClient.getScheduledTasks().then(function (tasks) {
|
||||
renderRunningTasks(view, tasks);
|
||||
});
|
||||
}
|
||||
|
||||
function renderActiveConnections(view, sessions) {
|
||||
var html = "";
|
||||
DashboardPage.sessionsList = sessions;
|
||||
var parentElement = view.querySelector(".activeDevices");
|
||||
var cardElem = parentElement.querySelector(".card");
|
||||
|
||||
if (cardElem) {
|
||||
cardElem.classList.add("deadSession");
|
||||
}
|
||||
|
||||
for (var i = 0, length = sessions.length; i < length; i++) {
|
||||
var session = sessions[i];
|
||||
var rowId = "session" + session.Id;
|
||||
var elem = view.querySelector("#" + rowId);
|
||||
|
||||
if (elem) {
|
||||
DashboardPage.updateSession(elem, session);
|
||||
} else {
|
||||
var nowPlayingItem = session.NowPlayingItem;
|
||||
var className = "scalableCard card activeSession backdropCard backdropCard-scalable";
|
||||
|
||||
if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) {
|
||||
className += " transcodingSession";
|
||||
}
|
||||
|
||||
html += '<div class="' + className + '" id="' + rowId + '">';
|
||||
html += '<div class="cardBox visualCardBox">';
|
||||
html += '<div class="cardScalable visualCardBox-cardScalable">';
|
||||
html += '<div class="cardPadder cardPadder-backdrop"></div>';
|
||||
html += '<div class="cardContent">';
|
||||
var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem);
|
||||
|
||||
if (imgUrl) {
|
||||
html += '<div class="sessionNowPlayingContent sessionNowPlayingContent-withbackground"';
|
||||
html += ' data-src="' + imgUrl + '" style="display:inline-block;background-image:url(\'' + imgUrl + "');\"";
|
||||
} else {
|
||||
html += '<div class="sessionNowPlayingContent"';
|
||||
}
|
||||
|
||||
html += "></div>";
|
||||
html += '<div class="sessionNowPlayingInnerContent">';
|
||||
html += '<div class="sessionAppInfo">';
|
||||
var clientImage = DashboardPage.getClientImage(session);
|
||||
|
||||
if (clientImage) {
|
||||
html += clientImage;
|
||||
}
|
||||
|
||||
html += '<div class="sessionAppName" style="display:inline-block;">';
|
||||
html += '<div class="sessionDeviceName">' + session.DeviceName + "</div>";
|
||||
html += '<div class="sessionAppSecondaryText">' + DashboardPage.getAppSecondaryText(session) + "</div>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += '<div class="sessionNowPlayingTime">' + DashboardPage.getSessionNowPlayingTime(session) + "</div>";
|
||||
|
||||
if (session.TranscodingInfo && session.TranscodingInfo.Framerate) {
|
||||
html += '<div class="sessionTranscodingFramerate">' + session.TranscodingInfo.Framerate + " fps</div>";
|
||||
} else {
|
||||
html += '<div class="sessionTranscodingFramerate"></div>';
|
||||
}
|
||||
|
||||
var nowPlayingName = DashboardPage.getNowPlayingName(session);
|
||||
html += '<div class="sessionNowPlayingInfo" data-imgsrc="' + nowPlayingName.image + '">';
|
||||
html += nowPlayingName.html;
|
||||
html += "</div>";
|
||||
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
|
||||
html += '<progress class="playbackProgress" min="0" max="100" value="' + 100 * (session.PlayState.PositionTicks || 0) / nowPlayingItem.RunTimeTicks + '"></progress>';
|
||||
} else {
|
||||
html += '<progress class="playbackProgress hide" min="0" max="100"></progress>';
|
||||
}
|
||||
|
||||
if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) {
|
||||
html += '<progress class="transcodingProgress" min="0" max="100" value="' + session.TranscodingInfo.CompletionPercentage.toFixed(1) + '"></progress>';
|
||||
} else {
|
||||
html += '<progress class="transcodingProgress hide" min="0" max="100"></progress>';
|
||||
}
|
||||
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += '<div class="sessionCardFooter cardFooter">';
|
||||
html += '<div class="sessionCardButtons flex align-items-center justify-content-center">';
|
||||
var btnCssClass;
|
||||
btnCssClass = session.ServerId && session.NowPlayingItem && session.SupportsRemoteControl && session.DeviceId !== connectionManager.deviceId() ? "" : " hide";
|
||||
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionPlayPause paper-icon-button-light ' + btnCssClass + '"><i class="md-icon"></i></button>';
|
||||
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionStop paper-icon-button-light ' + btnCssClass + '"><i class="md-icon"></i></button>';
|
||||
btnCssClass = session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length ? "" : " hide";
|
||||
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionInfo paper-icon-button-light ' + btnCssClass + '" title="' + globalize.translate("ViewPlaybackInfo") + '"><i class="md-icon"></i></button>';
|
||||
btnCssClass = session.ServerId && -1 !== session.SupportedCommands.indexOf("DisplayMessage") && session.DeviceId !== connectionManager.deviceId() ? "" : " hide";
|
||||
html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionSendMessage paper-icon-button-light ' + btnCssClass + '" title="' + globalize.translate("SendMessage") + '"><i class="md-icon"></i></button>';
|
||||
html += "</div>";
|
||||
html += '<div class="sessionNowPlayingStreamInfo" style="padding:.5em 0 1em;">';
|
||||
html += DashboardPage.getSessionNowPlayingStreamInfo(session);
|
||||
html += "</div>";
|
||||
html += '<div class="flex align-items-center justify-content-center">';
|
||||
var userImage = DashboardPage.getUserImage(session);
|
||||
html += userImage ? '<img style="height:1.71em;border-radius:50px;margin-right:.5em;" src="' + userImage + '" />' : '<div style="height:1.71em;"></div>';
|
||||
html += '<div class="sessionUserName" style="text-transform:uppercase;">';
|
||||
html += DashboardPage.getUsersHtml(session) || " ";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
}
|
||||
}
|
||||
|
||||
parentElement.insertAdjacentHTML("beforeend", html);
|
||||
var deadSessionElem = parentElement.querySelector(".deadSession");
|
||||
|
||||
if (deadSessionElem) {
|
||||
deadSessionElem.parentNode.removeChild(deadSessionElem);
|
||||
}
|
||||
}
|
||||
|
||||
function renderRunningTasks(view, tasks) {
|
||||
var html = "";
|
||||
tasks = tasks.filter(function (task) {
|
||||
if ("Idle" != task.State) {
|
||||
return !task.IsHidden;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (tasks.length) {
|
||||
view.querySelector(".runningTasksContainer").classList.remove("hide");
|
||||
} else {
|
||||
view.querySelector(".runningTasksContainer").classList.add("hide");
|
||||
}
|
||||
|
||||
for (var i = 0, length = tasks.length; i < length; i++) {
|
||||
var task = tasks[i];
|
||||
|
||||
html += "<p>";
|
||||
html += task.Name + "<br/>";
|
||||
if (task.State === "Running") {
|
||||
var progress = (task.CurrentProgressPercentage || 0).toFixed(1);
|
||||
html += '<progress max="100" value="' + progress + '" title="' + progress + '%">';
|
||||
html += progress + "%";
|
||||
html += "</progress>";
|
||||
html += "<span style='color:#00a4dc;margin-left:5px;margin-right:5px;'>" + progress + "%</span>";
|
||||
html += '<button type="button" is="paper-icon-button-light" title="' + globalize.translate("ButtonStop") + '" onclick="DashboardPage.stopTask(this, \'' + task.Id + '\');" class="autoSize"><i class="md-icon">cancel</i></button>';
|
||||
} else if (task.State === "Cancelling") {
|
||||
html += '<span style="color:#cc0000;">' + globalize.translate("LabelStopping") + "</span>";
|
||||
}
|
||||
|
||||
html += "</p>";
|
||||
}
|
||||
|
||||
view.querySelector("#divRunningTasks").innerHTML = html;
|
||||
}
|
||||
|
||||
window.DashboardPage = {
|
||||
renderPaths: function (page, systemInfo) {
|
||||
page.querySelector("#cachePath").innerHTML = systemInfo.CachePath;
|
||||
page.querySelector("#logPath").innerHTML = systemInfo.LogPath;
|
||||
page.querySelector("#transcodePath").innerHTML = systemInfo.TranscodingTempPath;
|
||||
page.querySelector("#metadataPath").innerHTML = systemInfo.InternalMetadataPath;
|
||||
page.querySelector("#webPath").innerHTML = systemInfo.WebPath;
|
||||
},
|
||||
startInterval: function (apiClient) {
|
||||
apiClient.sendMessage("SessionsStart", "0,1500");
|
||||
apiClient.sendMessage("ScheduledTasksInfoStart", "0,1000");
|
||||
},
|
||||
stopInterval: function (apiClient) {
|
||||
apiClient.sendMessage("SessionsStop");
|
||||
apiClient.sendMessage("ScheduledTasksInfoStop");
|
||||
},
|
||||
getSessionNowPlayingStreamInfo: function (session) {
|
||||
var html = "";
|
||||
var showTranscodingInfo = false;
|
||||
var displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session);
|
||||
if (displayPlayMethod === "DirectStream") {
|
||||
html += globalize.translate("DirectStreaming");
|
||||
} else if (displayPlayMethod === "Transcode") {
|
||||
html += globalize.translate("Transcoding");
|
||||
if (session.TranscodingInfo && session.TranscodingInfo.Framerate) {
|
||||
html += " (" + session.TranscodingInfo.Framerate + " fps)";
|
||||
}
|
||||
showTranscodingInfo = true;
|
||||
} else if (displayPlayMethod === "DirectPlay") {
|
||||
html += globalize.translate("DirectPlaying");
|
||||
}
|
||||
if (showTranscodingInfo) {
|
||||
var line = [];
|
||||
|
||||
if (session.TranscodingInfo) {
|
||||
if (session.TranscodingInfo.Bitrate) {
|
||||
if (session.TranscodingInfo.Bitrate > 1e6) {
|
||||
line.push((session.TranscodingInfo.Bitrate / 1e6).toFixed(1) + " Mbps");
|
||||
} else {
|
||||
line.push(Math.floor(session.TranscodingInfo.Bitrate / 1e3) + " kbps");
|
||||
}
|
||||
}
|
||||
|
||||
if (session.TranscodingInfo.Container) {
|
||||
line.push(session.TranscodingInfo.Container);
|
||||
}
|
||||
|
||||
if (session.TranscodingInfo.VideoCodec) {
|
||||
line.push(session.TranscodingInfo.VideoCodec);
|
||||
}
|
||||
|
||||
if (session.TranscodingInfo.AudioCodec && session.TranscodingInfo.AudioCodec != session.TranscodingInfo.Container) {
|
||||
line.push(session.TranscodingInfo.AudioCodec);
|
||||
}
|
||||
}
|
||||
|
||||
if (line.length) {
|
||||
html += " - " + line.join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
return html || " ";
|
||||
},
|
||||
getSessionNowPlayingTime: function (session) {
|
||||
var nowPlayingItem = session.NowPlayingItem;
|
||||
var html = "";
|
||||
|
||||
if (nowPlayingItem) {
|
||||
if (session.PlayState.PositionTicks) {
|
||||
html += datetime.getDisplayRunningTime(session.PlayState.PositionTicks);
|
||||
} else {
|
||||
html += "--:--:--";
|
||||
}
|
||||
|
||||
html += " / ";
|
||||
|
||||
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
|
||||
html += datetime.getDisplayRunningTime(nowPlayingItem.RunTimeTicks);
|
||||
} else {
|
||||
html += "--:--:--";
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
return html;
|
||||
},
|
||||
getAppSecondaryText: function (session) {
|
||||
return session.Client + " " + session.ApplicationVersion;
|
||||
},
|
||||
getNowPlayingName: function (session) {
|
||||
var imgUrl = "";
|
||||
var nowPlayingItem = session.NowPlayingItem;
|
||||
|
||||
if (!nowPlayingItem) {
|
||||
return {
|
||||
html: "Last seen " + humane_date(session.LastActivityDate),
|
||||
image: imgUrl
|
||||
};
|
||||
}
|
||||
|
||||
var topText = itemHelper.getDisplayName(nowPlayingItem);
|
||||
var bottomText = "";
|
||||
|
||||
if (nowPlayingItem.Artists && nowPlayingItem.Artists.length) {
|
||||
bottomText = topText;
|
||||
topText = nowPlayingItem.Artists[0];
|
||||
} else {
|
||||
if (nowPlayingItem.SeriesName || nowPlayingItem.Album) {
|
||||
bottomText = topText;
|
||||
topText = nowPlayingItem.SeriesName || nowPlayingItem.Album;
|
||||
} else if (nowPlayingItem.ProductionYear) {
|
||||
bottomText = nowPlayingItem.ProductionYear;
|
||||
}
|
||||
}
|
||||
|
||||
if (nowPlayingItem.ImageTags && nowPlayingItem.ImageTags.Logo) {
|
||||
imgUrl = ApiClient.getScaledImageUrl(nowPlayingItem.Id, {
|
||||
tag: nowPlayingItem.ImageTags.Logo,
|
||||
maxHeight: 24,
|
||||
maxWidth: 130,
|
||||
type: "Logo"
|
||||
});
|
||||
} else {
|
||||
if (nowPlayingItem.ParentLogoImageTag) {
|
||||
imgUrl = ApiClient.getScaledImageUrl(nowPlayingItem.ParentLogoItemId, {
|
||||
tag: nowPlayingItem.ParentLogoImageTag,
|
||||
maxHeight: 24,
|
||||
maxWidth: 130,
|
||||
type: "Logo"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (imgUrl) {
|
||||
topText = '<img src="' + imgUrl + '" style="max-height:24px;max-width:130px;" />';
|
||||
}
|
||||
|
||||
return {
|
||||
html: bottomText ? topText + "<br/>" + bottomText : topText,
|
||||
image: imgUrl
|
||||
};
|
||||
},
|
||||
getUsersHtml: function (session) {
|
||||
var html = [];
|
||||
|
||||
if (session.UserId) {
|
||||
html.push(session.UserName);
|
||||
}
|
||||
|
||||
for (var i = 0, length = session.AdditionalUsers.length; i < length; i++) {
|
||||
html.push(session.AdditionalUsers[i].UserName);
|
||||
}
|
||||
|
||||
return html.join(", ");
|
||||
},
|
||||
getUserImage: function (session) {
|
||||
if (session.UserId && session.UserPrimaryImageTag) {
|
||||
return ApiClient.getUserImageUrl(session.UserId, {
|
||||
tag: session.UserPrimaryImageTag,
|
||||
height: 24,
|
||||
type: "Primary"
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
updateSession: function (row, session) {
|
||||
row.classList.remove("deadSession");
|
||||
var nowPlayingItem = session.NowPlayingItem;
|
||||
|
||||
if (nowPlayingItem) {
|
||||
row.classList.add("playingSession");
|
||||
} else {
|
||||
row.classList.remove("playingSession");
|
||||
}
|
||||
|
||||
if (session.ServerId && -1 !== session.SupportedCommands.indexOf("DisplayMessage") && session.DeviceId !== connectionManager.deviceId()) {
|
||||
row.querySelector(".btnSessionSendMessage").classList.remove("hide");
|
||||
} else {
|
||||
row.querySelector(".btnSessionSendMessage").classList.add("hide");
|
||||
}
|
||||
|
||||
if (session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons.length) {
|
||||
row.querySelector(".btnSessionInfo").classList.remove("hide");
|
||||
} else {
|
||||
row.querySelector(".btnSessionInfo").classList.add("hide");
|
||||
}
|
||||
|
||||
var btnSessionPlayPause = row.querySelector(".btnSessionPlayPause");
|
||||
|
||||
if (session.ServerId && nowPlayingItem && session.SupportsRemoteControl && session.DeviceId !== connectionManager.deviceId()) {
|
||||
btnSessionPlayPause.classList.remove("hide");
|
||||
row.querySelector(".btnSessionStop").classList.remove("hide");
|
||||
} else {
|
||||
btnSessionPlayPause.classList.add("hide");
|
||||
row.querySelector(".btnSessionStop").classList.add("hide");
|
||||
}
|
||||
|
||||
if (session.PlayState && session.PlayState.IsPaused) {
|
||||
btnSessionPlayPause.querySelector("i").innerHTML = "";
|
||||
} else {
|
||||
btnSessionPlayPause.querySelector("i").innerHTML = "";
|
||||
}
|
||||
|
||||
row.querySelector(".sessionNowPlayingStreamInfo").innerHTML = DashboardPage.getSessionNowPlayingStreamInfo(session);
|
||||
row.querySelector(".sessionNowPlayingTime").innerHTML = DashboardPage.getSessionNowPlayingTime(session);
|
||||
row.querySelector(".sessionUserName").innerHTML = DashboardPage.getUsersHtml(session) || " ";
|
||||
row.querySelector(".sessionAppSecondaryText").innerHTML = DashboardPage.getAppSecondaryText(session);
|
||||
row.querySelector(".sessionTranscodingFramerate").innerHTML = session.TranscodingInfo && session.TranscodingInfo.Framerate ? session.TranscodingInfo.Framerate + " fps" : "";
|
||||
var nowPlayingName = DashboardPage.getNowPlayingName(session);
|
||||
var nowPlayingInfoElem = row.querySelector(".sessionNowPlayingInfo");
|
||||
|
||||
if (!(nowPlayingName.image && nowPlayingName.image == nowPlayingInfoElem.getAttribute("data-imgsrc"))) {
|
||||
nowPlayingInfoElem.innerHTML = nowPlayingName.html;
|
||||
nowPlayingInfoElem.setAttribute("data-imgsrc", nowPlayingName.image || "");
|
||||
}
|
||||
|
||||
var playbackProgressElem = row.querySelector(".playbackProgress");
|
||||
|
||||
if (playbackProgressElem) {
|
||||
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
|
||||
var position = session.PlayState.PositionTicks || 0;
|
||||
var value = 100 * position / nowPlayingItem.RunTimeTicks;
|
||||
playbackProgressElem.classList.remove("hide");
|
||||
playbackProgressElem.value = value;
|
||||
} else {
|
||||
playbackProgressElem.classList.add("hide");
|
||||
}
|
||||
}
|
||||
|
||||
var transcodingProgress = row.querySelector(".transcodingProgress");
|
||||
|
||||
if (session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage) {
|
||||
row.classList.add("transcodingSession");
|
||||
transcodingProgress.value = session.TranscodingInfo.CompletionPercentage;
|
||||
transcodingProgress.classList.remove("hide");
|
||||
} else {
|
||||
transcodingProgress.classList.add("hide");
|
||||
row.classList.remove("transcodingSession");
|
||||
}
|
||||
|
||||
var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem) || "";
|
||||
var imgElem = row.querySelector(".sessionNowPlayingContent");
|
||||
|
||||
if (imgUrl != imgElem.getAttribute("data-src")) {
|
||||
imgElem.style.backgroundImage = imgUrl ? "url('" + imgUrl + "')" : "";
|
||||
imgElem.setAttribute("data-src", imgUrl);
|
||||
|
||||
if (imgUrl) {
|
||||
imgElem.classList.add("sessionNowPlayingContent-withbackground");
|
||||
} else {
|
||||
imgElem.classList.remove("sessionNowPlayingContent-withbackground");
|
||||
}
|
||||
}
|
||||
},
|
||||
getClientImage: function (connection) {
|
||||
var iconUrl = (connection.Client.toLowerCase(), connection.DeviceName.toLowerCase(), connection.AppIconUrl);
|
||||
|
||||
if (iconUrl) {
|
||||
if (-1 === iconUrl.indexOf("://")) {
|
||||
iconUrl = ApiClient.getUrl(iconUrl);
|
||||
}
|
||||
|
||||
return "<img src='" + iconUrl + "' />";
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
getNowPlayingImageUrl: function (item) {
|
||||
if (item && item.BackdropImageTags && item.BackdropImageTags.length) {
|
||||
return ApiClient.getScaledImageUrl(item.Id, {
|
||||
type: "Backdrop",
|
||||
width: 275,
|
||||
tag: item.BackdropImageTags[0]
|
||||
});
|
||||
}
|
||||
|
||||
if (item && item.ParentBackdropImageTags && item.ParentBackdropImageTags.length) {
|
||||
return ApiClient.getScaledImageUrl(item.ParentBackdropItemId, {
|
||||
type: "Backdrop",
|
||||
width: 275,
|
||||
tag: item.ParentBackdropImageTags[0]
|
||||
});
|
||||
}
|
||||
|
||||
if (item && item.BackdropImageTag) {
|
||||
return ApiClient.getScaledImageUrl(item.BackdropItemId, {
|
||||
type: "Backdrop",
|
||||
width: 275,
|
||||
tag: item.BackdropImageTag
|
||||
});
|
||||
}
|
||||
|
||||
var imageTags = (item || {}).ImageTags || {};
|
||||
|
||||
if (item && imageTags.Thumb) {
|
||||
return ApiClient.getScaledImageUrl(item.Id, {
|
||||
type: "Thumb",
|
||||
width: 275,
|
||||
tag: imageTags.Thumb
|
||||
});
|
||||
}
|
||||
|
||||
if (item && item.ParentThumbImageTag) {
|
||||
return ApiClient.getScaledImageUrl(item.ParentThumbItemId, {
|
||||
type: "Thumb",
|
||||
width: 275,
|
||||
tag: item.ParentThumbImageTag
|
||||
});
|
||||
}
|
||||
|
||||
if (item && item.ThumbImageTag) {
|
||||
return ApiClient.getScaledImageUrl(item.ThumbItemId, {
|
||||
type: "Thumb",
|
||||
width: 275,
|
||||
tag: item.ThumbImageTag
|
||||
});
|
||||
}
|
||||
|
||||
if (item && imageTags.Primary) {
|
||||
return ApiClient.getScaledImageUrl(item.Id, {
|
||||
type: "Primary",
|
||||
width: 275,
|
||||
tag: imageTags.Primary
|
||||
});
|
||||
}
|
||||
|
||||
if (item && item.PrimaryImageTag) {
|
||||
return ApiClient.getScaledImageUrl(item.PrimaryImageItemId, {
|
||||
type: "Primary",
|
||||
width: 275,
|
||||
tag: item.PrimaryImageTag
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
systemUpdateTaskKey: "SystemUpdateTask",
|
||||
renderUrls: function (page, systemInfo) {
|
||||
var helpButton = '<a is="emby-linkbutton" class="raised raised-mini button-submit" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Connectivity" target="_blank" style="margin-left:.7em;font-size:84%;padding:.2em .8em;">' + globalize.translate("ButtonHelp") + "</a>";
|
||||
var localUrlElem = page.querySelector(".localUrl");
|
||||
var externalUrlElem = page.querySelector(".externalUrl");
|
||||
|
||||
if (systemInfo.LocalAddress) {
|
||||
var localAccessHtml = globalize.translate("LabelLocalAccessUrl", '<a is="emby-linkbutton" class="button-link" href="' + systemInfo.LocalAddress + '" target="_blank">' + systemInfo.LocalAddress + "</a>");
|
||||
localUrlElem.innerHTML = localAccessHtml + helpButton;
|
||||
localUrlElem.classList.remove("hide");
|
||||
} else {
|
||||
localUrlElem.classList.add("hide");
|
||||
}
|
||||
|
||||
if (systemInfo.WanAddress) {
|
||||
var externalUrl = systemInfo.WanAddress;
|
||||
var remoteAccessHtml = globalize.translate("LabelRemoteAccessUrl", '<a is="emby-linkbutton" class="button-link" href="' + externalUrl + '" target="_blank">' + externalUrl + "</a>");
|
||||
externalUrlElem.innerHTML = remoteAccessHtml + helpButton;
|
||||
externalUrlElem.classList.remove("hide");
|
||||
} else {
|
||||
externalUrlElem.classList.add("hide");
|
||||
}
|
||||
},
|
||||
stopTask: function (btn, id) {
|
||||
var page = dom.parentWithClass(btn, "page");
|
||||
ApiClient.stopScheduledTask(id).then(function () {
|
||||
pollForInfo(page, ApiClient);
|
||||
});
|
||||
},
|
||||
restart: function (btn) {
|
||||
require(["confirm"], function (confirm) {
|
||||
confirm({
|
||||
title: globalize.translate("HeaderRestart"),
|
||||
text: globalize.translate("MessageConfirmRestart"),
|
||||
confirmText: globalize.translate("ButtonRestart"),
|
||||
primary: "cancel"
|
||||
}).then(function () {
|
||||
var page = dom.parentWithClass(btn, "page");
|
||||
buttonEnabled(page.querySelector("#btnRestartServer"), false);
|
||||
buttonEnabled(page.querySelector("#btnShutdown"), false);
|
||||
Dashboard.restartServer();
|
||||
});
|
||||
});
|
||||
},
|
||||
shutdown: function (btn) {
|
||||
require(["confirm"], function (confirm) {
|
||||
confirm({
|
||||
title: globalize.translate("HeaderShutdown"),
|
||||
text: globalize.translate("MessageConfirmShutdown"),
|
||||
confirmText: globalize.translate("ButtonShutdown"),
|
||||
primary: "cancel"
|
||||
}).then(function () {
|
||||
var page = dom.parentWithClass(btn, "page");
|
||||
buttonEnabled(page.querySelector("#btnRestartServer"), false);
|
||||
buttonEnabled(page.querySelector("#btnShutdown"), false);
|
||||
ApiClient.shutdownServer();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
return function (view, params) {
|
||||
function onRestartRequired(evt, apiClient) {
|
||||
if (apiClient.serverId() === serverId) {
|
||||
renderHasPendingRestart(view, apiClient, true);
|
||||
}
|
||||
}
|
||||
|
||||
function onServerShuttingDown(evt, apiClient) {
|
||||
if (apiClient.serverId() === serverId) {
|
||||
renderHasPendingRestart(view, apiClient, true);
|
||||
}
|
||||
}
|
||||
|
||||
function onServerRestarting(evt, apiClient) {
|
||||
if (apiClient.serverId() === serverId) {
|
||||
renderHasPendingRestart(view, apiClient, true);
|
||||
}
|
||||
}
|
||||
|
||||
function onPackageInstalling(evt, apiClient) {
|
||||
if (apiClient.serverId() === serverId) {
|
||||
pollForInfo(view, apiClient, true);
|
||||
reloadSystemInfo(view, apiClient);
|
||||
}
|
||||
}
|
||||
|
||||
function onPackageInstallationCompleted(evt, apiClient) {
|
||||
if (apiClient.serverId() === serverId) {
|
||||
pollForInfo(view, apiClient, true);
|
||||
reloadSystemInfo(view, apiClient);
|
||||
}
|
||||
}
|
||||
|
||||
function onSessionsUpdate(evt, apiClient, info) {
|
||||
if (apiClient.serverId() === serverId) {
|
||||
renderInfo(view, info);
|
||||
}
|
||||
}
|
||||
|
||||
function onScheduledTasksUpdate(evt, apiClient, info) {
|
||||
if (apiClient.serverId() === serverId) {
|
||||
renderRunningTasks(view, info);
|
||||
}
|
||||
}
|
||||
|
||||
var serverId = ApiClient.serverId();
|
||||
view.querySelector(".btnConnectionHelp").addEventListener("click", onConnectionHelpClick);
|
||||
view.querySelector(".btnEditServerName").addEventListener("click", onEditServerNameClick);
|
||||
view.querySelector(".activeDevices").addEventListener("click", onActiveDevicesClick);
|
||||
view.addEventListener("viewshow", function () {
|
||||
var page = this;
|
||||
var apiClient = ApiClient;
|
||||
|
||||
if (apiClient) {
|
||||
loading.show();
|
||||
pollForInfo(page, apiClient);
|
||||
DashboardPage.startInterval(apiClient);
|
||||
// TODO we currently don't support packages and thus these events are useless
|
||||
events.on(serverNotifications, "RestartRequired", onRestartRequired);
|
||||
events.on(serverNotifications, "ServerShuttingDown", onServerShuttingDown);
|
||||
events.on(serverNotifications, "ServerRestarting", onServerRestarting);
|
||||
events.on(serverNotifications, "PackageInstalling", onPackageInstalling);
|
||||
events.on(serverNotifications, "PackageInstallationCompleted", onPackageInstallationCompleted);
|
||||
events.on(serverNotifications, "Sessions", onSessionsUpdate);
|
||||
events.on(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate);
|
||||
DashboardPage.lastAppUpdateCheck = null;
|
||||
reloadSystemInfo(page, ApiClient);
|
||||
|
||||
if (!page.userActivityLog) {
|
||||
page.userActivityLog = new ActivityLog({
|
||||
serverId: ApiClient.serverId(),
|
||||
element: page.querySelector(".userActivityItems")
|
||||
});
|
||||
}
|
||||
|
||||
if (ApiClient.isMinServerVersion("3.4.1.25")) {
|
||||
if (!page.serverActivityLog) {
|
||||
page.serverActivityLog = new ActivityLog({
|
||||
serverId: ApiClient.serverId(),
|
||||
element: page.querySelector(".serverActivityItems")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
refreshActiveRecordings(view, apiClient);
|
||||
loading.hide();
|
||||
}
|
||||
});
|
||||
view.addEventListener("viewbeforehide", function () {
|
||||
var apiClient = ApiClient;
|
||||
events.off(serverNotifications, "RestartRequired", onRestartRequired);
|
||||
events.off(serverNotifications, "ServerShuttingDown", onServerShuttingDown);
|
||||
events.off(serverNotifications, "ServerRestarting", onServerRestarting);
|
||||
events.off(serverNotifications, "PackageInstalling", onPackageInstalling);
|
||||
events.off(serverNotifications, "PackageInstallationCompleted", onPackageInstallationCompleted);
|
||||
events.off(serverNotifications, "Sessions", onSessionsUpdate);
|
||||
events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate);
|
||||
|
||||
if (apiClient) {
|
||||
DashboardPage.stopInterval(apiClient);
|
||||
}
|
||||
});
|
||||
view.addEventListener("viewdestroy", function () {
|
||||
var page = this;
|
||||
var userActivityLog = page.userActivityLog;
|
||||
if (userActivityLog) {
|
||||
userActivityLog.destroy();
|
||||
}
|
||||
var serverActivityLog = page.serverActivityLog;
|
||||
if (serverActivityLog) {
|
||||
serverActivityLog.destroy();
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
44
src/controllers/device.js
Normal file
44
src/controllers/device.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
define(["loading", "libraryMenu", "dom", "emby-input", "emby-button"], function(loading, libraryMenu, dom) {
|
||||
"use strict";
|
||||
|
||||
function load(page, device, deviceOptions) {
|
||||
page.querySelector("#txtCustomName", page).value = deviceOptions.CustomName || "", page.querySelector(".reportedName", page).innerHTML = device.Name || ""
|
||||
}
|
||||
|
||||
function loadData() {
|
||||
var page = this;
|
||||
loading.show();
|
||||
var id = getParameterByName("id"),
|
||||
promise1 = ApiClient.getJSON(ApiClient.getUrl("Devices/Info", {
|
||||
Id: id
|
||||
})),
|
||||
promise2 = ApiClient.getJSON(ApiClient.getUrl("Devices/Options", {
|
||||
Id: id
|
||||
}));
|
||||
Promise.all([promise1, promise2]).then(function(responses) {
|
||||
load(page, responses[0], responses[1]), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function save(page) {
|
||||
var id = getParameterByName("id");
|
||||
ApiClient.ajax({
|
||||
url: ApiClient.getUrl("Devices/Options", {
|
||||
Id: id
|
||||
}),
|
||||
type: "POST",
|
||||
data: JSON.stringify({
|
||||
CustomName: page.querySelector("#txtCustomName").value
|
||||
}),
|
||||
contentType: "application/json"
|
||||
}).then(Dashboard.processServerConfigurationUpdateResult)
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
var form = this;
|
||||
return save(dom.parentWithClass(form, "page")), e.preventDefault(), !1
|
||||
}
|
||||
return function(view, params) {
|
||||
view.querySelector("form").addEventListener("submit", onSubmit), view.addEventListener("viewshow", loadData)
|
||||
}
|
||||
});
|
80
src/controllers/devices.js
Normal file
80
src/controllers/devices.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
define(["loading", "dom", "libraryMenu", "globalize", "humanedate", "emby-linkbutton", "emby-itemscontainer", "cardStyle"], function(loading, dom, libraryMenu, globalize) {
|
||||
"use strict";
|
||||
|
||||
function canDelete(deviceId) {
|
||||
return deviceId !== ApiClient.deviceId()
|
||||
}
|
||||
|
||||
function deleteDevice(page, id) {
|
||||
var msg = globalize.translate("DeleteDeviceConfirmation");
|
||||
require(["confirm"], function(confirm) {
|
||||
confirm({
|
||||
text: msg,
|
||||
title: globalize.translate("HeaderDeleteDevice"),
|
||||
confirmText: globalize.translate("ButtonDelete"),
|
||||
primary: "cancel"
|
||||
}).then(function() {
|
||||
loading.show(), ApiClient.ajax({
|
||||
type: "DELETE",
|
||||
url: ApiClient.getUrl("Devices", {
|
||||
Id: id
|
||||
})
|
||||
}).then(function() {
|
||||
loadData(page)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function showDeviceMenu(view, btn, deviceId) {
|
||||
var menuItems = [];
|
||||
canEdit && menuItems.push({
|
||||
name: globalize.translate("Edit"),
|
||||
id: "open",
|
||||
ironIcon: "mode-edit"
|
||||
}), canDelete(deviceId) && menuItems.push({
|
||||
name: globalize.translate("Delete"),
|
||||
id: "delete",
|
||||
ironIcon: "delete"
|
||||
}), require(["actionsheet"], function(actionsheet) {
|
||||
actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: btn,
|
||||
callback: function(id) {
|
||||
switch (id) {
|
||||
case "open":
|
||||
Dashboard.navigate("devices/device.html?id=" + deviceId);
|
||||
break;
|
||||
case "delete":
|
||||
deleteDevice(view, deviceId)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function load(page, devices) {
|
||||
var html = "";
|
||||
html += devices.map(function(device) {
|
||||
var deviceHtml = "";
|
||||
deviceHtml += "<div data-id='" + device.Id + "' class='card backdropCard'>", deviceHtml += '<div class="cardBox visualCardBox">', deviceHtml += '<div class="cardScalable">', deviceHtml += '<div class="cardPadder cardPadder-backdrop"></div>', deviceHtml += '<a is="emby-linkbutton" href="' + (canEdit ? "devices/device.html?id=" + device.Id : "#") + '" class="cardContent cardImageContainer">';
|
||||
var iconUrl = device.IconUrl;
|
||||
return iconUrl && -1 === iconUrl.indexOf("://") && (iconUrl = ApiClient.getUrl(iconUrl)), iconUrl ? (deviceHtml += '<div class="cardImage" style="background-image:url(\'' + iconUrl + "');background-size: auto 64%;background-position:center center;\">", deviceHtml += "</div>") : deviceHtml += '<i class="cardImageIcon md-icon">tablet_android</i>', deviceHtml += "</a>", deviceHtml += "</div>", deviceHtml += '<div class="cardFooter">', (canEdit || canDelete(device.Id)) && (deviceHtml += '<div style="text-align:right; float:right;padding-top:5px;">', deviceHtml += '<button type="button" is="paper-icon-button-light" data-id="' + device.Id + '" title="' + globalize.translate("Menu") + '" class="btnDeviceMenu"><i class="md-icon"></i></button>', deviceHtml += "</div>"), deviceHtml += "<div class='cardText'>", deviceHtml += device.Name, deviceHtml += "</div>", deviceHtml += "<div class='cardText cardText-secondary'>", deviceHtml += device.AppName + " " + device.AppVersion, deviceHtml += "</div>", deviceHtml += "<div class='cardText cardText-secondary'>", device.LastUserName && (deviceHtml += device.LastUserName, deviceHtml += ", " + humane_date(device.DateLastActivity)), deviceHtml += " ", deviceHtml += "</div>", deviceHtml += "</div>", deviceHtml += "</div>", deviceHtml += "</div>"
|
||||
}).join(""), page.querySelector(".devicesList").innerHTML = html
|
||||
}
|
||||
|
||||
function loadData(page) {
|
||||
loading.show(), ApiClient.getJSON(ApiClient.getUrl("Devices")).then(function(result) {
|
||||
load(page, result.Items), loading.hide()
|
||||
})
|
||||
}
|
||||
var canEdit = ApiClient.isMinServerVersion("3.4.1.31");
|
||||
return function(view, params) {
|
||||
view.querySelector(".devicesList").addEventListener("click", function(e) {
|
||||
var btnDeviceMenu = dom.parentWithClass(e.target, "btnDeviceMenu");
|
||||
btnDeviceMenu && showDeviceMenu(view, btnDeviceMenu, btnDeviceMenu.getAttribute("data-id"))
|
||||
}), view.addEventListener("viewshow", function() {
|
||||
loadData(this)
|
||||
})
|
||||
}
|
||||
});
|
17
src/controllers/edititemmetadata.js
Normal file
17
src/controllers/edititemmetadata.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
define(["loading"], function(loading) {
|
||||
"use strict";
|
||||
|
||||
function reload(context, itemId) {
|
||||
loading.show(), itemId ? require(["metadataEditor"], function(metadataEditor) {
|
||||
metadataEditor.embed(context.querySelector(".editPageInnerContent"), itemId, ApiClient.serverInfo().Id)
|
||||
}) : (context.querySelector(".editPageInnerContent").innerHTML = "", loading.hide())
|
||||
}
|
||||
return function(view, params) {
|
||||
view.addEventListener("viewshow", function() {
|
||||
reload(this, MetadataEditor.getCurrentItemId())
|
||||
}), MetadataEditor.setCurrentItemId(null), view.querySelector(".libraryTree").addEventListener("itemclicked", function(event) {
|
||||
var data = event.detail;
|
||||
data.id != MetadataEditor.getCurrentItemId() && (MetadataEditor.setCurrentItemId(data.id), reload(view, data.id))
|
||||
})
|
||||
}
|
||||
});
|
208
src/controllers/favorites.js
Normal file
208
src/controllers/favorites.js
Normal file
|
@ -0,0 +1,208 @@
|
|||
define(["appRouter", "cardBuilder", "dom", "globalize", "connectionManager", "apphost", "layoutManager", "focusManager", "emby-itemscontainer", "emby-scroller"], function(appRouter, cardBuilder, dom, globalize, connectionManager, appHost, layoutManager, focusManager) {
|
||||
"use strict";
|
||||
|
||||
function enableScrollX() {
|
||||
return !0
|
||||
}
|
||||
|
||||
function getThumbShape() {
|
||||
return enableScrollX() ? "overflowBackdrop" : "backdrop"
|
||||
}
|
||||
|
||||
function getPosterShape() {
|
||||
return enableScrollX() ? "overflowPortrait" : "portrait"
|
||||
}
|
||||
|
||||
function getSquareShape() {
|
||||
return enableScrollX() ? "overflowSquare" : "square"
|
||||
}
|
||||
|
||||
function getSections() {
|
||||
return [{
|
||||
name: "HeaderFavoriteMovies",
|
||||
types: "Movie",
|
||||
shape: getPosterShape(),
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
overlayPlayButton: !0,
|
||||
overlayText: !1,
|
||||
centerText: !0
|
||||
}, {
|
||||
name: "HeaderFavoriteShows",
|
||||
types: "Series",
|
||||
shape: getPosterShape(),
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
overlayPlayButton: !0,
|
||||
overlayText: !1,
|
||||
centerText: !0
|
||||
}, {
|
||||
name: "HeaderFavoriteEpisodes",
|
||||
types: "Episode",
|
||||
shape: getThumbShape(),
|
||||
preferThumb: !1,
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
overlayPlayButton: !0,
|
||||
overlayText: !1,
|
||||
centerText: !0
|
||||
}, {
|
||||
name: "HeaderFavoriteVideos",
|
||||
types: "Video",
|
||||
shape: getThumbShape(),
|
||||
preferThumb: !0,
|
||||
showTitle: !0,
|
||||
overlayPlayButton: !0,
|
||||
overlayText: !1,
|
||||
centerText: !0
|
||||
}, {
|
||||
name: "HeaderFavoriteCollections",
|
||||
types: "BoxSet",
|
||||
shape: getPosterShape(),
|
||||
showTitle: !0,
|
||||
overlayPlayButton: !0,
|
||||
overlayText: !1,
|
||||
centerText: !0
|
||||
}, {
|
||||
name: "HeaderFavoritePlaylists",
|
||||
types: "Playlist",
|
||||
shape: getSquareShape(),
|
||||
preferThumb: !1,
|
||||
showTitle: !0,
|
||||
overlayText: !1,
|
||||
showParentTitle: !1,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0,
|
||||
coverImage: !0
|
||||
}, {
|
||||
name: "HeaderFavoriteArtists",
|
||||
types: "MusicArtist",
|
||||
shape: getSquareShape(),
|
||||
preferThumb: !1,
|
||||
showTitle: !0,
|
||||
overlayText: !1,
|
||||
showParentTitle: !1,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0,
|
||||
coverImage: !0
|
||||
}, {
|
||||
name: "HeaderFavoriteAlbums",
|
||||
types: "MusicAlbum",
|
||||
shape: getSquareShape(),
|
||||
preferThumb: !1,
|
||||
showTitle: !0,
|
||||
overlayText: !1,
|
||||
showParentTitle: !0,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0,
|
||||
coverImage: !0
|
||||
}, {
|
||||
name: "HeaderFavoriteSongs",
|
||||
types: "Audio",
|
||||
shape: getSquareShape(),
|
||||
preferThumb: !1,
|
||||
showTitle: !0,
|
||||
overlayText: !1,
|
||||
showParentTitle: !0,
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0,
|
||||
action: "instantmix",
|
||||
coverImage: !0
|
||||
}]
|
||||
}
|
||||
|
||||
function getFetchDataFn(section) {
|
||||
return function() {
|
||||
var apiClient = this.apiClient,
|
||||
options = {
|
||||
SortBy: (section.types, "SeriesName,SortName"),
|
||||
SortOrder: "Ascending",
|
||||
Filters: "IsFavorite",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
CollapseBoxSetItems: !1,
|
||||
ExcludeLocationTypes: "Virtual",
|
||||
EnableTotalRecordCount: !1
|
||||
};
|
||||
options.Limit = 20;
|
||||
var userId = apiClient.getCurrentUserId();
|
||||
return "MusicArtist" === section.types ? apiClient.getArtists(userId, options) : (options.IncludeItemTypes = section.types, apiClient.getItems(userId, options))
|
||||
}
|
||||
}
|
||||
|
||||
function getRouteUrl(section, serverId) {
|
||||
return appRouter.getRouteUrl("list", {
|
||||
serverId: serverId,
|
||||
itemTypes: section.types,
|
||||
isFavorite: !0
|
||||
})
|
||||
}
|
||||
|
||||
function getItemsHtmlFn(section) {
|
||||
return function(items) {
|
||||
var supportsImageAnalysis = appHost.supports("imageanalysis"),
|
||||
cardLayout = (appHost.preferVisualCards || supportsImageAnalysis) && section.autoCardLayout && section.showTitle;
|
||||
cardLayout = !1;
|
||||
var serverId = this.apiClient.serverId(),
|
||||
leadingButtons = layoutManager.tv ? [{
|
||||
name: globalize.translate("All"),
|
||||
id: "more",
|
||||
icon: "",
|
||||
routeUrl: getRouteUrl(section, serverId)
|
||||
}] : null,
|
||||
lines = 0;
|
||||
return section.showTitle && lines++, section.showYear && lines++, section.showParentTitle && lines++, cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
preferThumb: section.preferThumb,
|
||||
shape: section.shape,
|
||||
centerText: section.centerText && !cardLayout,
|
||||
overlayText: !1 !== section.overlayText,
|
||||
showTitle: section.showTitle,
|
||||
showYear: section.showYear,
|
||||
showParentTitle: section.showParentTitle,
|
||||
scalable: !0,
|
||||
coverImage: section.coverImage,
|
||||
overlayPlayButton: section.overlayPlayButton,
|
||||
overlayMoreButton: section.overlayMoreButton && !cardLayout,
|
||||
action: section.action,
|
||||
allowBottomPadding: !enableScrollX(),
|
||||
cardLayout: cardLayout,
|
||||
vibrant: supportsImageAnalysis && cardLayout,
|
||||
leadingButtons: leadingButtons,
|
||||
lines: lines
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function FavoritesTab(view, params) {
|
||||
this.view = view, this.params = params, this.apiClient = connectionManager.currentApiClient(), this.sectionsContainer = view.querySelector(".sections"), createSections(this, this.sectionsContainer, this.apiClient)
|
||||
}
|
||||
|
||||
function createSections(instance, elem, apiClient) {
|
||||
var i, length, sections = getSections(),
|
||||
html = "";
|
||||
for (i = 0, length = sections.length; i < length; i++) {
|
||||
var section = sections[i],
|
||||
sectionClass = "verticalSection";
|
||||
section.showTitle || (sectionClass += " verticalSection-extrabottompadding"), html += '<div class="' + sectionClass + ' hide">', html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">', layoutManager.tv ? html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate(section.name) + "</h2>" : (html += '<a is="emby-linkbutton" href="' + getRouteUrl(section, apiClient.serverId()) + '" class="more button-flat button-flat-mini sectionTitleTextButton">', html += '<h2 class="sectionTitle sectionTitle-cards">', html += globalize.translate(section.name), html += "</h2>", html += '<i class="md-icon"></i>', html += "</a>"), html += "</div>", html += '<div is="emby-scroller" class="padded-top-focusscale padded-bottom-focusscale" data-mousewheel="false" data-centerfocus="true"><div is="emby-itemscontainer" class="itemsContainer scrollSlider focuscontainer-x padded-left padded-right" data-monitor="markfavorite"></div></div>', html += "</div>"
|
||||
}
|
||||
elem.innerHTML = html;
|
||||
var elems = elem.querySelectorAll(".itemsContainer");
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
var itemsContainer = elems[i];
|
||||
itemsContainer.fetchData = getFetchDataFn(sections[i]).bind(instance), itemsContainer.getItemsHtml = getItemsHtmlFn(sections[i]).bind(instance), itemsContainer.parentContainer = dom.parentWithClass(itemsContainer, "verticalSection")
|
||||
}
|
||||
}
|
||||
return FavoritesTab.prototype.onResume = function(options) {
|
||||
for (var promises = (this.apiClient, []), view = this.view, elems = this.sectionsContainer.querySelectorAll(".itemsContainer"), i = 0, length = elems.length; i < length; i++) promises.push(elems[i].resume(options));
|
||||
Promise.all(promises).then(function() {
|
||||
options.autoFocus && focusManager.autoFocus(view)
|
||||
})
|
||||
}, FavoritesTab.prototype.onPause = function() {
|
||||
for (var elems = this.sectionsContainer.querySelectorAll(".itemsContainer"), i = 0, length = elems.length; i < length; i++) elems[i].pause()
|
||||
}, FavoritesTab.prototype.destroy = function() {
|
||||
this.view = null, this.params = null, this.apiClient = null;
|
||||
for (var elems = this.sectionsContainer.querySelectorAll(".itemsContainer"), i = 0, length = elems.length; i < length; i++) elems[i].fetchData = null, elems[i].getItemsHtml = null, elems[i].parentContainer = null;
|
||||
this.sectionsContainer = null
|
||||
}, FavoritesTab
|
||||
});
|
34
src/controllers/forgotpassword.js
Normal file
34
src/controllers/forgotpassword.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
define([], function() {
|
||||
"use strict";
|
||||
|
||||
function processForgotPasswordResult(result) {
|
||||
if ("ContactAdmin" == result.Action) return void Dashboard.alert({
|
||||
message: Globalize.translate("MessageContactAdminToResetPassword"),
|
||||
title: Globalize.translate("HeaderForgotPassword")
|
||||
});
|
||||
if ("InNetworkRequired" == result.Action) return void Dashboard.alert({
|
||||
message: Globalize.translate("MessageForgotPasswordInNetworkRequired"),
|
||||
title: Globalize.translate("HeaderForgotPassword")
|
||||
});
|
||||
if ("PinCode" == result.Action) {
|
||||
var msg = Globalize.translate("MessageForgotPasswordFileCreated");
|
||||
return msg += "<br/>", msg += "<br/>", msg += result.PinFile, msg += "<br/>", void Dashboard.alert({
|
||||
message: msg,
|
||||
title: Globalize.translate("HeaderForgotPassword")
|
||||
})
|
||||
}
|
||||
}
|
||||
return function(view, params) {
|
||||
function onSubmit(e) {
|
||||
return ApiClient.ajax({
|
||||
type: "POST",
|
||||
url: ApiClient.getUrl("Users/ForgotPassword"),
|
||||
dataType: "json",
|
||||
data: {
|
||||
EnteredUsername: view.querySelector("#txtName").value
|
||||
}
|
||||
}).then(processForgotPasswordResult), e.preventDefault(), !1
|
||||
}
|
||||
view.querySelector("form").addEventListener("submit", onSubmit)
|
||||
}
|
||||
});
|
33
src/controllers/forgotpasswordpin.js
Normal file
33
src/controllers/forgotpasswordpin.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
define([], function() {
|
||||
"use strict";
|
||||
|
||||
function processForgotPasswordResult(result) {
|
||||
if (result.Success) {
|
||||
var msg = Globalize.translate("MessagePasswordResetForUsers");
|
||||
return msg += "<br/>", msg += "<br/>", msg += result.UsersReset.join("<br/>"), void Dashboard.alert({
|
||||
message: msg,
|
||||
title: Globalize.translate("HeaderPasswordReset"),
|
||||
callback: function() {
|
||||
window.location.href = "index.html"
|
||||
}
|
||||
})
|
||||
}
|
||||
Dashboard.alert({
|
||||
message: Globalize.translate("MessageInvalidForgotPasswordPin"),
|
||||
title: Globalize.translate("HeaderPasswordReset")
|
||||
})
|
||||
}
|
||||
return function(view, params) {
|
||||
function onSubmit(e) {
|
||||
return ApiClient.ajax({
|
||||
type: "POST",
|
||||
url: ApiClient.getUrl("Users/ForgotPassword/Pin"),
|
||||
dataType: "json",
|
||||
data: {
|
||||
Pin: view.querySelector("#txtPin").value
|
||||
}
|
||||
}).then(processForgotPasswordResult), e.preventDefault(), !1
|
||||
}
|
||||
view.querySelector("form").addEventListener("submit", onSubmit)
|
||||
}
|
||||
});
|
52
src/controllers/home.js
Normal file
52
src/controllers/home.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
define(["tabbedView", "globalize", "require", "emby-tabs", "emby-button", "emby-scroller"], function(TabbedView, globalize, require) {
|
||||
"use strict";
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
name: globalize.translate("Home")
|
||||
}, {
|
||||
name: globalize.translate("Favorites")
|
||||
}]
|
||||
}
|
||||
|
||||
function getDefaultTabIndex() {
|
||||
return 0
|
||||
}
|
||||
|
||||
function getRequirePromise(deps) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
require(deps, resolve)
|
||||
})
|
||||
}
|
||||
|
||||
function getTabController(index) {
|
||||
if (null == index) throw new Error("index cannot be null");
|
||||
var depends = [];
|
||||
switch (index) {
|
||||
case 0:
|
||||
depends.push("controllers/hometab");
|
||||
break;
|
||||
case 1:
|
||||
depends.push("controllers/favorites")
|
||||
}
|
||||
var instance = this;
|
||||
return getRequirePromise(depends).then(function(controllerFactory) {
|
||||
var controller = instance.tabControllers[index];
|
||||
if (!controller) {
|
||||
controller = new controllerFactory(instance.view.querySelector(".tabContent[data-index='" + index + "']"), instance.params), instance.tabControllers[index] = controller
|
||||
}
|
||||
return controller
|
||||
})
|
||||
}
|
||||
|
||||
function HomeView(view, params) {
|
||||
TabbedView.call(this, view, params)
|
||||
}
|
||||
return Object.assign(HomeView.prototype, TabbedView.prototype), HomeView.prototype.getTabs = getTabs, HomeView.prototype.getDefaultTabIndex = getDefaultTabIndex, HomeView.prototype.getTabController = getTabController, HomeView.prototype.setTitle = function() {
|
||||
Emby.Page.setTitle(null)
|
||||
}, HomeView.prototype.onPause = function() {
|
||||
TabbedView.prototype.onPause.call(this), document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader")
|
||||
}, HomeView.prototype.onResume = function(options) {
|
||||
TabbedView.prototype.onResume.call(this, options), document.querySelector(".skinHeader").classList.add("noHomeButtonHeader")
|
||||
}, HomeView
|
||||
});
|
35
src/controllers/hometab.js
Normal file
35
src/controllers/hometab.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
define(["userSettings", "loading", "connectionManager", "apphost", "layoutManager", "focusManager", "homeSections", "emby-itemscontainer"], function(userSettings, loading, connectionManager, appHost, layoutManager, focusManager, homeSections) {
|
||||
"use strict";
|
||||
|
||||
function HomeTab(view, params) {
|
||||
this.view = view, this.params = params, this.apiClient = connectionManager.currentApiClient(), this.sectionsContainer = view.querySelector(".sections"), view.querySelector(".sections").addEventListener("settingschange", onHomeScreenSettingsChanged.bind(this))
|
||||
}
|
||||
|
||||
function onHomeScreenSettingsChanged() {
|
||||
this.sectionsRendered = !1, this.paused || this.onResume({
|
||||
refresh: !0
|
||||
})
|
||||
}
|
||||
return HomeTab.prototype.onResume = function(options) {
|
||||
if (this.sectionsRendered) {
|
||||
var sectionsContainer = this.sectionsContainer;
|
||||
return sectionsContainer ? homeSections.resume(sectionsContainer, options) : Promise.resolve()
|
||||
}
|
||||
loading.show();
|
||||
var view = this.view,
|
||||
apiClient = this.apiClient;
|
||||
return this.destroyHomeSections(), this.sectionsRendered = !0, apiClient.getCurrentUser().then(function(user) {
|
||||
return homeSections.loadSections(view.querySelector(".sections"), apiClient, user, userSettings).then(function() {
|
||||
options.autoFocus && focusManager.autoFocus(view), loading.hide()
|
||||
})
|
||||
})
|
||||
}, HomeTab.prototype.onPause = function() {
|
||||
var sectionsContainer = this.sectionsContainer;
|
||||
sectionsContainer && homeSections.pause(sectionsContainer)
|
||||
}, HomeTab.prototype.destroy = function() {
|
||||
this.view = null, this.params = null, this.apiClient = null, this.destroyHomeSections(), this.sectionsContainer = null
|
||||
}, HomeTab.prototype.destroyHomeSections = function() {
|
||||
var sectionsContainer = this.sectionsContainer;
|
||||
sectionsContainer && homeSections.destroySections(sectionsContainer)
|
||||
}, HomeTab
|
||||
});
|
1231
src/controllers/itemdetailpage.js
Normal file
1231
src/controllers/itemdetailpage.js
Normal file
File diff suppressed because it is too large
Load diff
38
src/controllers/librarydisplay.js
Normal file
38
src/controllers/librarydisplay.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
define(["globalize", "loading", "libraryMenu", "emby-checkbox", "emby-button", "emby-linkbutton"], function(globalize, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "library.html",
|
||||
name: Globalize.translate("HeaderLibraries")
|
||||
}, {
|
||||
href: "librarydisplay.html",
|
||||
name: Globalize.translate("TabDisplay")
|
||||
}, {
|
||||
href: "metadataimages.html",
|
||||
name: Globalize.translate("TabMetadata")
|
||||
}, {
|
||||
href: "metadatanfo.html",
|
||||
name: Globalize.translate("TabNfoSettings")
|
||||
}, {
|
||||
href: "librarysettings.html",
|
||||
name: Globalize.translate("TabAdvanced")
|
||||
}]
|
||||
}
|
||||
return function(view, params) {
|
||||
function loadData() {
|
||||
ApiClient.getServerConfiguration().then(function(config) {
|
||||
view.querySelector(".chkFolderView").checked = config.EnableFolderView, view.querySelector(".chkGroupMoviesIntoCollections").checked = config.EnableGroupingIntoCollections, view.querySelector(".chkDisplaySpecialsWithinSeasons").checked = config.DisplaySpecialsWithinSeasons, view.querySelector(".chkExternalContentInSuggestions").checked = config.EnableExternalContentInSuggestions
|
||||
})
|
||||
}
|
||||
view.querySelector("form").addEventListener("submit", function(e) {
|
||||
loading.show();
|
||||
var form = this;
|
||||
return ApiClient.getServerConfiguration().then(function(config) {
|
||||
config.EnableFolderView = form.querySelector(".chkFolderView").checked, config.EnableGroupingIntoCollections = form.querySelector(".chkGroupMoviesIntoCollections").checked, config.DisplaySpecialsWithinSeasons = form.querySelector(".chkDisplaySpecialsWithinSeasons").checked, config.EnableExternalContentInSuggestions = form.querySelector(".chkExternalContentInSuggestions").checked, ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult)
|
||||
}), e.preventDefault(), !1
|
||||
}), view.addEventListener("viewshow", function() {
|
||||
libraryMenu.setTabs("librarysetup", 1, getTabs), loadData()
|
||||
})
|
||||
}
|
||||
});
|
91
src/controllers/librarysettings.js
Normal file
91
src/controllers/librarysettings.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
define(["jQuery", "loading", "libraryMenu", "fnchecked", "emby-checkbox", "emby-linkbutton"], function($, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function loadPage(page, config) {
|
||||
$("#chkSaveMetadataHidden", page).checked(config.SaveMetadataHidden);
|
||||
loading.hide();
|
||||
}
|
||||
|
||||
function loadMetadataConfig(page, config) {
|
||||
$("#selectDateAdded", page).val(config.UseFileCreationTimeForDateAdded ? "1" : "0");
|
||||
}
|
||||
|
||||
function loadFanartConfig(page, config) {
|
||||
$("#txtFanartApiKey", page).val(config.UserApiKey || "");
|
||||
}
|
||||
|
||||
function saveFanart(form) {
|
||||
ApiClient.getNamedConfiguration("fanart").then(function(config) {
|
||||
config.UserApiKey = $("#txtFanartApiKey", form).val(), ApiClient.updateNamedConfiguration("fanart", config);
|
||||
});
|
||||
}
|
||||
|
||||
function saveMetadata(form) {
|
||||
ApiClient.getNamedConfiguration("metadata").then(function(config) {
|
||||
config.UseFileCreationTimeForDateAdded = "1" === $("#selectDateAdded", form).val(), ApiClient.updateNamedConfiguration("metadata", config);
|
||||
})
|
||||
}
|
||||
|
||||
function alertText(options) {
|
||||
require(["alert"], function(alert) {
|
||||
alert(options);
|
||||
});
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
loading.show();
|
||||
var form = this;
|
||||
ApiClient.getServerConfiguration().then(function(config) {
|
||||
config.SaveMetadataHidden = $("#chkSaveMetadataHidden", form).checked();
|
||||
config.FanartApiKey = $("#txtFanartApiKey", form).val();
|
||||
ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult);
|
||||
});
|
||||
saveMetadata(form);
|
||||
saveFanart(form);
|
||||
return false;
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "library.html",
|
||||
name: Globalize.translate("HeaderLibraries")
|
||||
}, {
|
||||
href: "librarydisplay.html",
|
||||
name: Globalize.translate("TabDisplay")
|
||||
}, {
|
||||
href: "metadataimages.html",
|
||||
name: Globalize.translate("TabMetadata")
|
||||
}, {
|
||||
href: "metadatanfo.html",
|
||||
name: Globalize.translate("TabNfoSettings")
|
||||
}, {
|
||||
href: "librarysettings.html",
|
||||
name: Globalize.translate("TabAdvanced")
|
||||
}]
|
||||
}
|
||||
|
||||
return function(view, params) {
|
||||
$(".librarySettingsForm").off("submit", onSubmit).on("submit", onSubmit);
|
||||
view.addEventListener("viewshow", function() {
|
||||
libraryMenu.setTabs("librarysetup", 4, getTabs);
|
||||
loading.show();
|
||||
var page = this;
|
||||
ApiClient.getServerConfiguration().then(function(config) {
|
||||
loadPage(page, config)
|
||||
});
|
||||
ApiClient.getNamedConfiguration("metadata").then(function(metadata) {
|
||||
loadMetadataConfig(page, metadata)
|
||||
});
|
||||
ApiClient.getNamedConfiguration("fanart").then(function(metadata) {
|
||||
loadFanartConfig(page, metadata)
|
||||
});
|
||||
ApiClient.getSystemInfo().then(function(info) {
|
||||
if ("Windows" === info.OperatingSystem) {
|
||||
page.querySelector(".fldSaveMetadataHidden").classList.remove("hide");
|
||||
} else {
|
||||
page.querySelector(".fldSaveMetadataHidden").classList.add("hide");
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
462
src/controllers/list.js
Normal file
462
src/controllers/list.js
Normal file
|
@ -0,0 +1,462 @@
|
|||
define(["globalize", "listView", "layoutManager", "userSettings", "focusManager", "cardBuilder", "loading", "connectionManager", "alphaNumericShortcuts", "scroller", "playbackManager", "alphaPicker", "emby-itemscontainer", "emby-scroller"], function(globalize, listView, layoutManager, userSettings, focusManager, cardBuilder, loading, connectionManager, AlphaNumericShortcuts, scroller, playbackManager, alphaPicker) {
|
||||
"use strict";
|
||||
|
||||
function getInitialLiveTvQuery(instance, params) {
|
||||
var query = {
|
||||
UserId: connectionManager.getApiClient(params.serverId).getCurrentUserId(),
|
||||
StartIndex: 0,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio",
|
||||
Limit: 300
|
||||
};
|
||||
return "Recordings" === params.type ? query.IsInProgress = !1 : query.HasAired = !1, params.genreId && (query.GenreIds = params.genreId), "true" === params.IsMovie ? query.IsMovie = !0 : "false" === params.IsMovie && (query.IsMovie = !1), "true" === params.IsSeries ? query.IsSeries = !0 : "false" === params.IsSeries && (query.IsSeries = !1), "true" === params.IsNews ? query.IsNews = !0 : "false" === params.IsNews && (query.IsNews = !1), "true" === params.IsSports ? query.IsSports = !0 : "false" === params.IsSports && (query.IsSports = !1), "true" === params.IsKids ? query.IsKids = !0 : "false" === params.IsKids && (query.IsKids = !1), "true" === params.IsAiring ? query.IsAiring = !0 : "false" === params.IsAiring && (query.IsAiring = !1), modifyQueryWithFilters(instance, query)
|
||||
}
|
||||
|
||||
function modifyQueryWithFilters(instance, query) {
|
||||
var sortValues = instance.getSortValues();
|
||||
query.SortBy || (query.SortBy = sortValues.sortBy, query.SortOrder = sortValues.sortOrder), query.Fields = query.Fields ? query.Fields + ",PrimaryImageAspectRatio" : "PrimaryImageAspectRatio", query.ImageTypeLimit = 1;
|
||||
var hasFilters, queryFilters = [],
|
||||
filters = instance.getFilters();
|
||||
return filters.IsPlayed && (queryFilters.push("IsPlayed"), hasFilters = !0), filters.IsUnplayed && (queryFilters.push("IsUnplayed"), hasFilters = !0), filters.IsFavorite && (queryFilters.push("IsFavorite"), hasFilters = !0), filters.IsResumable && (queryFilters.push("IsResumable"), hasFilters = !0), filters.VideoTypes && (hasFilters = !0, query.VideoTypes = filters.VideoTypes), filters.GenreIds && (hasFilters = !0, query.GenreIds = filters.GenreIds), filters.Is4K && (query.Is4K = !0, hasFilters = !0), filters.IsHD && (query.IsHD = !0, hasFilters = !0), filters.IsSD && (query.IsHD = !1, hasFilters = !0), filters.Is3D && (query.Is3D = !0, hasFilters = !0), filters.HasSubtitles && (query.HasSubtitles = !0, hasFilters = !0), filters.HasTrailer && (query.HasTrailer = !0, hasFilters = !0), filters.HasSpecialFeature && (query.HasSpecialFeature = !0, hasFilters = !0), filters.HasThemeSong && (query.HasThemeSong = !0, hasFilters = !0), filters.HasThemeVideo && (query.HasThemeVideo = !0, hasFilters = !0), query.Filters = queryFilters.length ? queryFilters.join(",") : null, instance.setFilterStatus(hasFilters), instance.alphaPicker && (query.NameStartsWithOrGreater = instance.alphaPicker.value()), query
|
||||
}
|
||||
|
||||
function updateSortText(instance) {
|
||||
var btnSortText = instance.btnSortText;
|
||||
if (btnSortText) {
|
||||
for (var options = instance.getSortMenuOptions(), values = instance.getSortValues(), sortBy = values.sortBy, i = 0, length = options.length; i < length; i++)
|
||||
if (sortBy === options[i].value) {
|
||||
btnSortText.innerHTML = globalize.translate("SortByValue", options[i].name);
|
||||
break
|
||||
} var btnSortIcon = instance.btnSortIcon;
|
||||
btnSortIcon && (btnSortIcon.innerHTML = "Descending" === values.sortOrder ? "" : "")
|
||||
}
|
||||
}
|
||||
|
||||
function updateItemsContainerForViewType(instance) {
|
||||
"list" === instance.getViewSettings().imageType ? (instance.itemsContainer.classList.remove("vertical-wrap"), instance.itemsContainer.classList.add("vertical-list")) : (instance.itemsContainer.classList.add("vertical-wrap"), instance.itemsContainer.classList.remove("vertical-list"))
|
||||
}
|
||||
|
||||
function updateAlphaPickerState(instance, numItems) {
|
||||
if (instance.alphaPicker) {
|
||||
var alphaPicker = instance.alphaPickerElement;
|
||||
if (alphaPicker) {
|
||||
var values = instance.getSortValues();
|
||||
null == numItems && (numItems = 100), "SortName" === values.sortBy && "Ascending" === values.sortOrder && numItems > 40 ? (alphaPicker.classList.remove("hide"), layoutManager.tv ? instance.itemsContainer.parentNode.classList.add("padded-left-withalphapicker") : instance.itemsContainer.parentNode.classList.add("padded-right-withalphapicker")) : (alphaPicker.classList.add("hide"), instance.itemsContainer.parentNode.classList.remove("padded-left-withalphapicker"), instance.itemsContainer.parentNode.classList.remove("padded-right-withalphapicker"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getItems(instance, params, item, sortBy, startIndex, limit) {
|
||||
var apiClient = connectionManager.getApiClient(params.serverId);
|
||||
if (instance.queryRecursive = !1, "Recordings" === params.type) return apiClient.getLiveTvRecordings(getInitialLiveTvQuery(instance, params));
|
||||
if ("Programs" === params.type) return "true" === params.IsAiring ? apiClient.getLiveTvRecommendedPrograms(getInitialLiveTvQuery(instance, params)) : apiClient.getLiveTvPrograms(getInitialLiveTvQuery(instance, params));
|
||||
if ("nextup" === params.type) return apiClient.getNextUpEpisodes(modifyQueryWithFilters(instance, {
|
||||
Limit: limit,
|
||||
Fields: "PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo",
|
||||
UserId: apiClient.getCurrentUserId(),
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Thumb",
|
||||
EnableTotalRecordCount: !1,
|
||||
SortBy: sortBy
|
||||
}));
|
||||
if (!item) {
|
||||
instance.queryRecursive = !0;
|
||||
var method = "getItems";
|
||||
return "MusicArtist" === params.type ? method = "getArtists" : "Person" === params.type && (method = "getPeople"), apiClient[method](apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, {
|
||||
StartIndex: startIndex,
|
||||
Limit: limit,
|
||||
Fields: "PrimaryImageAspectRatio,SortName",
|
||||
ImageTypeLimit: 1,
|
||||
IncludeItemTypes: "MusicArtist" === params.type || "Person" === params.type ? null : params.type,
|
||||
Recursive: !0,
|
||||
IsFavorite: "true" === params.IsFavorite || null,
|
||||
ArtistIds: params.artistId || null,
|
||||
SortBy: sortBy
|
||||
}))
|
||||
}
|
||||
if ("Genre" === item.Type || "MusicGenre" === item.Type || "Studio" === item.Type || "Person" === item.Type) {
|
||||
instance.queryRecursive = !0;
|
||||
var query = {
|
||||
StartIndex: startIndex,
|
||||
Limit: limit,
|
||||
Fields: "PrimaryImageAspectRatio,SortName",
|
||||
Recursive: !0,
|
||||
parentId: params.parentId,
|
||||
SortBy: sortBy
|
||||
};
|
||||
return "Studio" === item.Type ? query.StudioIds = item.Id : "Genre" === item.Type || "MusicGenre" === item.Type ? query.GenreIds = item.Id : "Person" === item.Type && (query.PersonIds = item.Id), "MusicGenre" === item.Type ? query.IncludeItemTypes = "MusicAlbum" : "GameGenre" === item.Type ? query.IncludeItemTypes = "Game" : "movies" === item.CollectionType ? query.IncludeItemTypes = "Movie" : "tvshows" === item.CollectionType ? query.IncludeItemTypes = "Series" : "Genre" === item.Type ? query.IncludeItemTypes = "Movie,Series,Video" : "Person" === item.Type && (query.IncludeItemTypes = params.type), apiClient.getItems(apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, query))
|
||||
}
|
||||
return apiClient.getItems(apiClient.getCurrentUserId(), modifyQueryWithFilters(instance, {
|
||||
StartIndex: startIndex,
|
||||
Limit: limit,
|
||||
Fields: "PrimaryImageAspectRatio,SortName",
|
||||
ImageTypeLimit: 1,
|
||||
ParentId: item.Id,
|
||||
SortBy: sortBy
|
||||
}))
|
||||
}
|
||||
|
||||
function getItem(params) {
|
||||
if ("Recordings" === params.type) return Promise.resolve(null);
|
||||
if ("Programs" === params.type) return Promise.resolve(null);
|
||||
if ("nextup" === params.type) return Promise.resolve(null);
|
||||
var apiClient = connectionManager.getApiClient(params.serverId),
|
||||
itemId = params.genreId || params.musicGenreId || params.studioId || params.personId || params.parentId;
|
||||
return itemId ? apiClient.getItem(apiClient.getCurrentUserId(), itemId) : Promise.resolve(null)
|
||||
}
|
||||
|
||||
function showViewSettingsMenu() {
|
||||
var instance = this;
|
||||
require(["viewSettings"], function(ViewSettings) {
|
||||
(new ViewSettings).show({
|
||||
settingsKey: instance.getSettingsKey(),
|
||||
settings: instance.getViewSettings(),
|
||||
visibleSettings: instance.getVisibleViewSettings()
|
||||
}).then(function() {
|
||||
updateItemsContainerForViewType(instance), instance.itemsContainer.refreshItems()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function showFilterMenu() {
|
||||
var instance = this;
|
||||
require(["filterMenu"], function(FilterMenu) {
|
||||
(new FilterMenu).show({
|
||||
settingsKey: instance.getSettingsKey(),
|
||||
settings: instance.getFilters(),
|
||||
visibleSettings: instance.getVisibleFilters(),
|
||||
onChange: instance.itemsContainer.refreshItems.bind(instance.itemsContainer),
|
||||
parentId: instance.params.parentId,
|
||||
itemTypes: instance.getItemTypes(),
|
||||
serverId: instance.params.serverId,
|
||||
filterMenuOptions: instance.getFilterMenuOptions()
|
||||
}).then(function() {
|
||||
instance.itemsContainer.refreshItems()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function showSortMenu() {
|
||||
var instance = this;
|
||||
require(["sortMenu"], function(SortMenu) {
|
||||
(new SortMenu).show({
|
||||
settingsKey: instance.getSettingsKey(),
|
||||
settings: instance.getSortValues(),
|
||||
onChange: instance.itemsContainer.refreshItems.bind(instance.itemsContainer),
|
||||
serverId: instance.params.serverId,
|
||||
sortOptions: instance.getSortMenuOptions()
|
||||
}).then(function() {
|
||||
updateSortText(instance), updateAlphaPickerState(instance), instance.itemsContainer.refreshItems()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onNewItemClick() {
|
||||
var instance = this;
|
||||
require(["playlistEditor"], function(playlistEditor) {
|
||||
(new playlistEditor).show({
|
||||
items: [],
|
||||
serverId: instance.params.serverId
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function hideOrShowAll(elems, hide) {
|
||||
for (var i = 0, length = elems.length; i < length; i++) hide ? elems[i].classList.add("hide") : elems[i].classList.remove("hide")
|
||||
}
|
||||
|
||||
function bindAll(elems, eventName, fn) {
|
||||
for (var i = 0, length = elems.length; i < length; i++) elems[i].addEventListener(eventName, fn)
|
||||
}
|
||||
|
||||
function ItemsView(view, params) {
|
||||
function fetchData() {
|
||||
return getItems(self, params, self.currentItem).then(function(result) {
|
||||
return null == self.totalItemCount && (self.totalItemCount = result.Items ? result.Items.length : result.length), updateAlphaPickerState(self, self.totalItemCount), result
|
||||
})
|
||||
}
|
||||
|
||||
function getItemsHtml(items) {
|
||||
var settings = self.getViewSettings();
|
||||
if ("list" === settings.imageType) return listView.getListViewHtml({
|
||||
items: items
|
||||
});
|
||||
var shape, preferThumb, preferDisc, preferLogo, defaultShape, item = self.currentItem,
|
||||
lines = settings.showTitle ? 2 : 0;
|
||||
"banner" === settings.imageType ? shape = "banner" : "disc" === settings.imageType ? (shape = "square", preferDisc = !0) : "logo" === settings.imageType ? (shape = "backdrop", preferLogo = !0) : "thumb" === settings.imageType ? (shape = "backdrop", preferThumb = !0) : "nextup" === params.type ? (shape = "backdrop", preferThumb = "thumb" === settings.imageType) : "Programs" === params.type || "Recordings" === params.type ? (shape = "true" === params.IsMovie ? "portrait" : "autoVertical", preferThumb = "true" !== params.IsMovie && "auto", defaultShape = "true" === params.IsMovie ? "portrait" : "backdrop") : shape = "autoVertical";
|
||||
var posterOptions = {
|
||||
shape: shape,
|
||||
showTitle: settings.showTitle,
|
||||
showYear: settings.showTitle,
|
||||
centerText: !0,
|
||||
coverImage: !0,
|
||||
preferThumb: preferThumb,
|
||||
preferDisc: preferDisc,
|
||||
preferLogo: preferLogo,
|
||||
overlayPlayButton: !1,
|
||||
overlayMoreButton: !0,
|
||||
overlayText: !settings.showTitle,
|
||||
defaultShape: defaultShape,
|
||||
action: "Audio" === params.type ? "playallfromhere" : null
|
||||
};
|
||||
if ("nextup" === params.type) posterOptions.showParentTitle = settings.showTitle;
|
||||
else if ("Person" === params.type) posterOptions.showYear = !1, posterOptions.showParentTitle = !1, lines = 1;
|
||||
else if ("Audio" === params.type) posterOptions.showParentTitle = settings.showTitle;
|
||||
else if ("MusicAlbum" === params.type) posterOptions.showParentTitle = settings.showTitle;
|
||||
else if ("Episode" === params.type) posterOptions.showParentTitle = settings.showTitle;
|
||||
else if ("MusicArtist" === params.type) posterOptions.showYear = !1, lines = 1;
|
||||
else if ("Programs" === params.type) {
|
||||
lines = settings.showTitle ? 1 : 0;
|
||||
var showParentTitle = settings.showTitle && "true" !== params.IsMovie;
|
||||
showParentTitle && lines++;
|
||||
var showAirTime = settings.showTitle && "Recordings" !== params.type;
|
||||
showAirTime && lines++;
|
||||
var showYear = settings.showTitle && "true" === params.IsMovie && "Recordings" === params.type;
|
||||
showYear && lines++, posterOptions = Object.assign(posterOptions, {
|
||||
inheritThumb: "Recordings" === params.type,
|
||||
context: "livetv",
|
||||
showParentTitle: showParentTitle,
|
||||
showAirTime: showAirTime,
|
||||
showAirDateTime: showAirTime,
|
||||
overlayPlayButton: !1,
|
||||
overlayMoreButton: !0,
|
||||
showYear: showYear,
|
||||
coverImage: !0
|
||||
})
|
||||
} else posterOptions.showParentTitle = settings.showTitle;
|
||||
return posterOptions.lines = lines, posterOptions.items = items, item && "folders" === item.CollectionType && (posterOptions.context = "folders"), cardBuilder.getCardsHtml(posterOptions)
|
||||
}
|
||||
|
||||
function initAlphaPicker() {
|
||||
self.scroller = view.querySelector(".scrollFrameY");
|
||||
var alphaPickerElement = self.alphaPickerElement;
|
||||
layoutManager.tv ? (alphaPickerElement.classList.add("alphaPicker-fixed-left"), alphaPickerElement.classList.add("focuscontainer-left"), self.itemsContainer.parentNode.classList.add("padded-left-withalphapicker")) : (alphaPickerElement.classList.add("alphaPicker-fixed-right"), alphaPickerElement.classList.add("focuscontainer-right"), self.itemsContainer.parentNode.classList.add("padded-right-withalphapicker")), self.alphaPicker = new alphaPicker({
|
||||
element: alphaPickerElement,
|
||||
itemsContainer: layoutManager.tv ? self.itemsContainer : null,
|
||||
itemClass: "card",
|
||||
valueChangeEvent: layoutManager.tv ? null : "click"
|
||||
}), self.alphaPicker.on("alphavaluechanged", onAlphaPickerValueChanged)
|
||||
}
|
||||
|
||||
function onAlphaPickerValueChanged() {
|
||||
self.alphaPicker.value();
|
||||
self.itemsContainer.refreshItems()
|
||||
}
|
||||
|
||||
function setTitle(item) {
|
||||
Emby.Page.setTitle(getTitle(item) || ""), item && "playlists" === item.CollectionType ? hideOrShowAll(view.querySelectorAll(".btnNewItem"), !1) : hideOrShowAll(view.querySelectorAll(".btnNewItem"), !0)
|
||||
}
|
||||
|
||||
function getTitle(item) {
|
||||
return "Recordings" === params.type ? globalize.translate("Recordings") : "Programs" === params.type ? "true" === params.IsMovie ? globalize.translate("Movies") : "true" === params.IsSports ? globalize.translate("Sports") : "true" === params.IsKids ? globalize.translate("HeaderForKids") : "true" === params.IsAiring ? globalize.translate("HeaderOnNow") : "true" === params.IsSeries ? globalize.translate("Shows") : "true" === params.IsNews ? globalize.translate("News") : globalize.translate("Programs") : "nextup" === params.type ? globalize.translate("NextUp") : "favoritemovies" === params.type ? globalize.translate("FavoriteMovies") : item ? item.Name : "Movie" === params.type ? globalize.translate("Movies") : "Series" === params.type ? globalize.translate("Shows") : "Season" === params.type ? globalize.translate("Seasons") : "Episode" === params.type ? globalize.translate("Episodes") : "MusicArtist" === params.type ? globalize.translate("Artists") : "MusicAlbum" === params.type ? globalize.translate("Albums") : "Audio" === params.type ? globalize.translate("Songs") : "Video" === params.type ? globalize.translate("Videos") : void 0
|
||||
}
|
||||
|
||||
function play() {
|
||||
var currentItem = self.currentItem;
|
||||
if (currentItem && !self.hasFilters) return void playbackManager.play({
|
||||
items: [currentItem]
|
||||
});
|
||||
getItems(self, self.params, currentItem, null, null, 300).then(function(result) {
|
||||
playbackManager.play({
|
||||
items: result.Items
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function queue() {
|
||||
var currentItem = self.currentItem;
|
||||
if (currentItem && !self.hasFilters) return void playbackManager.queue({
|
||||
items: [currentItem]
|
||||
});
|
||||
getItems(self, self.params, currentItem, null, null, 300).then(function(result) {
|
||||
playbackManager.queue({
|
||||
items: result.Items
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function shuffle() {
|
||||
var currentItem = self.currentItem;
|
||||
if (currentItem && !self.hasFilters) return void playbackManager.shuffle(currentItem);
|
||||
getItems(self, self.params, currentItem, "Random", null, 300).then(function(result) {
|
||||
playbackManager.play({
|
||||
items: result.Items
|
||||
})
|
||||
})
|
||||
}
|
||||
var self = this;
|
||||
self.params = params, this.itemsContainer = view.querySelector(".itemsContainer"), params.parentId ? this.itemsContainer.setAttribute("data-parentid", params.parentId) : "nextup" === params.type ? this.itemsContainer.setAttribute("data-monitor", "videoplayback") : "favoritemovies" === params.type ? this.itemsContainer.setAttribute("data-monitor", "markfavorite") : "Programs" === params.type && this.itemsContainer.setAttribute("data-refreshinterval", "300000");
|
||||
var i, length, btnViewSettings = view.querySelectorAll(".btnViewSettings");
|
||||
for (i = 0, length = btnViewSettings.length; i < length; i++) btnViewSettings[i].addEventListener("click", showViewSettingsMenu.bind(this));
|
||||
var filterButtons = view.querySelectorAll(".btnFilter");
|
||||
this.filterButtons = filterButtons;
|
||||
var hasVisibleFilters = this.getVisibleFilters().length;
|
||||
for (i = 0, length = filterButtons.length; i < length; i++) {
|
||||
var btnFilter = filterButtons[i];
|
||||
btnFilter.addEventListener("click", showFilterMenu.bind(this)), hasVisibleFilters ? btnFilter.classList.remove("hide") : btnFilter.classList.add("hide")
|
||||
}
|
||||
var sortButtons = view.querySelectorAll(".btnSort");
|
||||
for (this.sortButtons = sortButtons, i = 0, length = sortButtons.length; i < length; i++) {
|
||||
var sortButton = sortButtons[i];
|
||||
sortButton.addEventListener("click", showSortMenu.bind(this)), "nextup" !== params.type && sortButton.classList.remove("hide")
|
||||
}
|
||||
this.btnSortText = view.querySelector(".btnSortText"), this.btnSortIcon = view.querySelector(".btnSortIcon"), bindAll(view.querySelectorAll(".btnNewItem"), "click", onNewItemClick.bind(this)), this.alphaPickerElement = view.querySelector(".alphaPicker"), self.itemsContainer.fetchData = fetchData, self.itemsContainer.getItemsHtml = getItemsHtml, view.addEventListener("viewshow", function(e) {
|
||||
var isRestored = e.detail.isRestored;
|
||||
isRestored || (loading.show(), updateSortText(self), updateItemsContainerForViewType(self)), setTitle(null), getItem(params).then(function(item) {
|
||||
setTitle(item), self.currentItem = item;
|
||||
var refresh = !isRestored;
|
||||
self.itemsContainer.resume({
|
||||
refresh: refresh
|
||||
}).then(function() {
|
||||
loading.hide(), refresh && focusManager.autoFocus(self.itemsContainer)
|
||||
}), isRestored || item && "PhotoAlbum" !== item.Type && initAlphaPicker();
|
||||
var itemType = item ? item.Type : null;
|
||||
"MusicGenre" === itemType || "Programs" !== params.type && "Channel" !== itemType ? hideOrShowAll(view.querySelectorAll(".btnPlay"), !1) : hideOrShowAll(view.querySelectorAll(".btnPlay"), !0), "MusicGenre" === itemType || "Programs" !== params.type && "nextup" !== params.type && "Channel" !== itemType ? hideOrShowAll(view.querySelectorAll(".btnShuffle"), !1) : hideOrShowAll(view.querySelectorAll(".btnShuffle"), !0), item && playbackManager.canQueue(item) ? hideOrShowAll(view.querySelectorAll(".btnQueue"), !1) : hideOrShowAll(view.querySelectorAll(".btnQueue"), !0)
|
||||
}), isRestored || (bindAll(view.querySelectorAll(".btnPlay"), "click", play), bindAll(view.querySelectorAll(".btnQueue"), "click", queue), bindAll(view.querySelectorAll(".btnShuffle"), "click", shuffle)), this.alphaNumericShortcuts = new AlphaNumericShortcuts({
|
||||
itemsContainer: self.itemsContainer
|
||||
})
|
||||
}), view.addEventListener("viewhide", function(e) {
|
||||
var itemsContainer = self.itemsContainer;
|
||||
itemsContainer && itemsContainer.pause();
|
||||
var alphaNumericShortcuts = self.alphaNumericShortcuts;
|
||||
alphaNumericShortcuts && (alphaNumericShortcuts.destroy(), self.alphaNumericShortcuts = null)
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
self.listController && self.listController.destroy(), self.alphaPicker && (self.alphaPicker.off("alphavaluechanged", onAlphaPickerValueChanged), self.alphaPicker.destroy()), self.currentItem = null, self.scroller = null, self.itemsContainer = null, self.filterButtons = null, self.sortButtons = null, self.btnSortText = null, self.btnSortIcon = null, self.alphaPickerElement = null
|
||||
})
|
||||
}
|
||||
return ItemsView.prototype.getFilters = function() {
|
||||
var basekey = this.getSettingsKey();
|
||||
return {
|
||||
IsPlayed: "true" === userSettings.getFilter(basekey + "-filter-IsPlayed"),
|
||||
IsUnplayed: "true" === userSettings.getFilter(basekey + "-filter-IsUnplayed"),
|
||||
IsFavorite: "true" === userSettings.getFilter(basekey + "-filter-IsFavorite"),
|
||||
IsResumable: "true" === userSettings.getFilter(basekey + "-filter-IsResumable"),
|
||||
Is4K: "true" === userSettings.getFilter(basekey + "-filter-Is4K"),
|
||||
IsHD: "true" === userSettings.getFilter(basekey + "-filter-IsHD"),
|
||||
IsSD: "true" === userSettings.getFilter(basekey + "-filter-IsSD"),
|
||||
Is3D: "true" === userSettings.getFilter(basekey + "-filter-Is3D"),
|
||||
VideoTypes: userSettings.getFilter(basekey + "-filter-VideoTypes"),
|
||||
SeriesStatus: userSettings.getFilter(basekey + "-filter-SeriesStatus"),
|
||||
HasSubtitles: userSettings.getFilter(basekey + "-filter-HasSubtitles"),
|
||||
HasTrailer: userSettings.getFilter(basekey + "-filter-HasTrailer"),
|
||||
HasSpecialFeature: userSettings.getFilter(basekey + "-filter-HasSpecialFeature"),
|
||||
HasThemeSong: userSettings.getFilter(basekey + "-filter-HasThemeSong"),
|
||||
HasThemeVideo: userSettings.getFilter(basekey + "-filter-HasThemeVideo"),
|
||||
GenreIds: userSettings.getFilter(basekey + "-filter-GenreIds")
|
||||
}
|
||||
}, ItemsView.prototype.getSortValues = function() {
|
||||
var basekey = this.getSettingsKey();
|
||||
return {
|
||||
sortBy: userSettings.getFilter(basekey + "-sortby") || this.getDefaultSortBy(),
|
||||
sortOrder: "Descending" === userSettings.getFilter(basekey + "-sortorder") ? "Descending" : "Ascending"
|
||||
}
|
||||
}, ItemsView.prototype.getDefaultSortBy = function() {
|
||||
var params = this.params,
|
||||
sortNameOption = this.getNameSortOption(params);
|
||||
return params.type ? sortNameOption.value : "IsFolder," + sortNameOption.value
|
||||
}, ItemsView.prototype.getSortMenuOptions = function() {
|
||||
var sortBy = [],
|
||||
params = this.params;
|
||||
"Programs" === params.type && sortBy.push({
|
||||
name: globalize.translate("AirDate"),
|
||||
value: "StartDate,SortName"
|
||||
});
|
||||
var option = this.getNameSortOption(params);
|
||||
return option && sortBy.push(option), option = this.getCommunityRatingSortOption(), option && sortBy.push(option), option = this.getCriticRatingSortOption(), option && sortBy.push(option), "Programs" !== params.type && sortBy.push({
|
||||
name: globalize.translate("DateAdded"),
|
||||
value: "DateCreated,SortName"
|
||||
}), option = this.getDatePlayedSortOption(), option && sortBy.push(option), params.type || (option = this.getNameSortOption(params), sortBy.push({
|
||||
name: globalize.translate("Folders"),
|
||||
value: "IsFolder," + option.value
|
||||
})), sortBy.push({
|
||||
name: globalize.translate("ParentalRating"),
|
||||
value: "OfficialRating,SortName"
|
||||
}), option = this.getPlayCountSortOption(), option && sortBy.push(option), sortBy.push({
|
||||
name: globalize.translate("ReleaseDate"),
|
||||
value: "ProductionYear,PremiereDate,SortName"
|
||||
}), sortBy.push({
|
||||
name: globalize.translate("Runtime"),
|
||||
value: "Runtime,SortName"
|
||||
}), sortBy
|
||||
}, ItemsView.prototype.getNameSortOption = function(params) {
|
||||
return "Episode" === params.type ? {
|
||||
name: globalize.translate("Name"),
|
||||
value: "SeriesName,SortName"
|
||||
} : {
|
||||
name: globalize.translate("Name"),
|
||||
value: "SortName"
|
||||
}
|
||||
}, ItemsView.prototype.getPlayCountSortOption = function() {
|
||||
return "Programs" === this.params.type ? null : {
|
||||
name: globalize.translate("PlayCount"),
|
||||
value: "PlayCount,SortName"
|
||||
}
|
||||
}, ItemsView.prototype.getDatePlayedSortOption = function() {
|
||||
return "Programs" === this.params.type ? null : {
|
||||
name: globalize.translate("DatePlayed"),
|
||||
value: "DatePlayed,SortName"
|
||||
}
|
||||
}, ItemsView.prototype.getCriticRatingSortOption = function() {
|
||||
return "Programs" === this.params.type ? null : {
|
||||
name: globalize.translate("CriticRating"),
|
||||
value: "CriticRating,SortName"
|
||||
}
|
||||
}, ItemsView.prototype.getCommunityRatingSortOption = function() {
|
||||
return {
|
||||
name: globalize.translate("CommunityRating"),
|
||||
value: "CommunityRating,SortName"
|
||||
}
|
||||
}, ItemsView.prototype.getVisibleFilters = function() {
|
||||
var filters = [],
|
||||
params = this.params;
|
||||
return "nextup" === params.type || ("Programs" === params.type ? filters.push("Genres") : (params.type, filters.push("IsUnplayed"), filters.push("IsPlayed"), params.IsFavorite || filters.push("IsFavorite"), filters.push("IsResumable"), filters.push("VideoType"), filters.push("HasSubtitles"), filters.push("HasTrailer"), filters.push("HasSpecialFeature"), filters.push("HasThemeSong"), filters.push("HasThemeVideo"))), filters
|
||||
}, ItemsView.prototype.setFilterStatus = function(hasFilters) {
|
||||
this.hasFilters = hasFilters;
|
||||
var filterButtons = this.filterButtons;
|
||||
if (filterButtons.length)
|
||||
for (var i = 0, length = filterButtons.length; i < length; i++) {
|
||||
var btnFilter = filterButtons[i],
|
||||
bubble = btnFilter.querySelector(".filterButtonBubble");
|
||||
if (!bubble) {
|
||||
if (!hasFilters) continue;
|
||||
btnFilter.insertAdjacentHTML("afterbegin", '<div class="filterButtonBubble">!</div>'), btnFilter.classList.add("btnFilterWithBubble"), bubble = btnFilter.querySelector(".filterButtonBubble")
|
||||
}
|
||||
hasFilters ? bubble.classList.remove("hide") : bubble.classList.add("hide")
|
||||
}
|
||||
}, ItemsView.prototype.getFilterMenuOptions = function() {
|
||||
var params = this.params;
|
||||
return {
|
||||
IsAiring: params.IsAiring,
|
||||
IsMovie: params.IsMovie,
|
||||
IsSports: params.IsSports,
|
||||
IsKids: params.IsKids,
|
||||
IsNews: params.IsNews,
|
||||
IsSeries: params.IsSeries,
|
||||
Recursive: this.queryRecursive
|
||||
}
|
||||
}, ItemsView.prototype.getVisibleViewSettings = function() {
|
||||
var item = (this.params, this.currentItem),
|
||||
fields = ["showTitle"];
|
||||
return (!item || "PhotoAlbum" !== item.Type && "ChannelFolderItem" !== item.Type) && fields.push("imageType"), fields.push("viewType"), fields
|
||||
}, ItemsView.prototype.getViewSettings = function() {
|
||||
var basekey = this.getSettingsKey(),
|
||||
params = this.params,
|
||||
item = this.currentItem,
|
||||
showTitle = userSettings.get(basekey + "-showTitle");
|
||||
"true" === showTitle ? showTitle = !0 : "false" === showTitle ? showTitle = !1 : "Programs" === params.type || "Recordings" === params.type || "Person" === params.type || "nextup" === params.type || "Audio" === params.type || "MusicAlbum" === params.type || "MusicArtist" === params.type ? showTitle = !0 : item && "PhotoAlbum" !== item.Type && (showTitle = !0);
|
||||
var imageType = userSettings.get(basekey + "-imageType");
|
||||
return imageType || "nextup" === params.type && (imageType = "thumb"), {
|
||||
showTitle: showTitle,
|
||||
showYear: "false" !== userSettings.get(basekey + "-showYear"),
|
||||
imageType: imageType || "primary",
|
||||
viewType: userSettings.get(basekey + "-viewType") || "images"
|
||||
}
|
||||
}, ItemsView.prototype.getItemTypes = function() {
|
||||
var params = this.params;
|
||||
return "nextup" === params.type ? ["Episode"] : "Programs" === params.type ? ["Program"] : []
|
||||
}, ItemsView.prototype.getSettingsKey = function() {
|
||||
var values = [];
|
||||
values.push("items");
|
||||
var params = this.params;
|
||||
return params.type ? values.push(params.type) : params.parentId && values.push(params.parentId), params.IsAiring && values.push("IsAiring"), params.IsMovie && values.push("IsMovie"), params.IsKids && values.push("IsKids"), params.IsSports && values.push("IsSports"), params.IsNews && values.push("IsNews"), params.IsSeries && values.push("IsSeries"), params.IsFavorite && values.push("IsFavorite"), params.genreId && values.push("Genre"), params.musicGenreId && values.push("MusicGenre"), params.studioId && values.push("Studio"), params.personId && values.push("Person"), params.parentId && values.push("Folder"), values.join("-")
|
||||
}, ItemsView
|
||||
});
|
43
src/controllers/livetvseriestimers.js
Normal file
43
src/controllers/livetvseriestimers.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
define(["datetime", "cardBuilder", "imageLoader", "apphost", "loading", "paper-icon-button-light", "emby-button"], function(datetime, cardBuilder, imageLoader, appHost, loading) {
|
||||
"use strict";
|
||||
|
||||
function renderTimers(context, timers) {
|
||||
var html = "";
|
||||
appHost.supports("imageanalysis");
|
||||
html += cardBuilder.getCardsHtml({
|
||||
items: timers,
|
||||
shape: "auto",
|
||||
defaultShape: "portrait",
|
||||
showTitle: !0,
|
||||
cardLayout: !1,
|
||||
preferThumb: "auto",
|
||||
coverImage: !0,
|
||||
overlayText: !1,
|
||||
showSeriesTimerTime: !0,
|
||||
showSeriesTimerChannel: !0,
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0,
|
||||
lines: 3
|
||||
});
|
||||
var elem = context.querySelector("#items");
|
||||
elem.innerHTML = html, imageLoader.lazyChildren(elem), loading.hide()
|
||||
}
|
||||
|
||||
function reload(context, promise) {
|
||||
loading.show(), promise.then(function(result) {
|
||||
renderTimers(context, result.Items)
|
||||
})
|
||||
}
|
||||
var query = {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending"
|
||||
};
|
||||
return function(view, params, tabContent) {
|
||||
var timersPromise, self = this;
|
||||
self.preRender = function() {
|
||||
timersPromise = ApiClient.getLiveTvSeriesTimers(query)
|
||||
}, self.renderTab = function() {
|
||||
reload(tabContent, timersPromise)
|
||||
}
|
||||
}
|
||||
});
|
376
src/controllers/livetvsuggested.js
Normal file
376
src/controllers/livetvsuggested.js
Normal file
|
@ -0,0 +1,376 @@
|
|||
define(["layoutManager", "userSettings", "inputManager", "loading", "globalize", "libraryBrowser", "mainTabsManager", "cardBuilder", "apphost", "imageLoader", "scrollStyles", "emby-itemscontainer", "emby-tabs", "emby-button"], function (layoutManager, userSettings, inputManager, loading, globalize, libraryBrowser, mainTabsManager, cardBuilder, appHost, imageLoader) {
|
||||
"use strict";
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop;
|
||||
}
|
||||
|
||||
function getBackdropShape() {
|
||||
if (enableScrollX()) {
|
||||
return "overflowBackdrop";
|
||||
}
|
||||
return "backdrop";
|
||||
}
|
||||
|
||||
function getPortraitShape() {
|
||||
if (enableScrollX()) {
|
||||
return "overflowPortrait";
|
||||
}
|
||||
return "portrait";
|
||||
}
|
||||
|
||||
function getLimit() {
|
||||
if (enableScrollX()) {
|
||||
return 12;
|
||||
}
|
||||
return 9;
|
||||
}
|
||||
|
||||
function loadRecommendedPrograms(page) {
|
||||
loading.show();
|
||||
var limit = getLimit();
|
||||
|
||||
if (enableScrollX()) {
|
||||
limit *= 2;
|
||||
}
|
||||
|
||||
ApiClient.getLiveTvRecommendedPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
IsAiring: true,
|
||||
limit: limit,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Thumb,Backdrop",
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio"
|
||||
}).then(function (result) {
|
||||
renderItems(page, result.Items, "activeProgramItems", "play", {
|
||||
showAirDateTime: false,
|
||||
showAirEndTime: true
|
||||
});
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
function reload(page, enableFullRender) {
|
||||
if (enableFullRender) {
|
||||
loadRecommendedPrograms(page);
|
||||
ApiClient.getLiveTvPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
HasAired: false,
|
||||
limit: getLimit(),
|
||||
IsMovie: false,
|
||||
IsSports: false,
|
||||
IsKids: false,
|
||||
IsNews: false,
|
||||
IsSeries: true,
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio",
|
||||
EnableImageTypes: "Primary,Thumb"
|
||||
}).then(function (result) {
|
||||
renderItems(page, result.Items, "upcomingEpisodeItems");
|
||||
});
|
||||
ApiClient.getLiveTvPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
HasAired: false,
|
||||
limit: getLimit(),
|
||||
IsMovie: true,
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: "ChannelInfo",
|
||||
EnableImageTypes: "Primary,Thumb"
|
||||
}).then(function (result) {
|
||||
renderItems(page, result.Items, "upcomingTvMovieItems", null, {
|
||||
shape: getPortraitShape(),
|
||||
preferThumb: null,
|
||||
showParentTitle: false
|
||||
});
|
||||
});
|
||||
ApiClient.getLiveTvPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
HasAired: false,
|
||||
limit: getLimit(),
|
||||
IsSports: true,
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio",
|
||||
EnableImageTypes: "Primary,Thumb"
|
||||
}).then(function (result) {
|
||||
renderItems(page, result.Items, "upcomingSportsItems");
|
||||
});
|
||||
ApiClient.getLiveTvPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
HasAired: false,
|
||||
limit: getLimit(),
|
||||
IsKids: true,
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio",
|
||||
EnableImageTypes: "Primary,Thumb"
|
||||
}).then(function (result) {
|
||||
renderItems(page, result.Items, "upcomingKidsItems");
|
||||
});
|
||||
ApiClient.getLiveTvPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
HasAired: false,
|
||||
limit: getLimit(),
|
||||
IsNews: true,
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio",
|
||||
EnableImageTypes: "Primary,Thumb"
|
||||
}).then(function (result) {
|
||||
renderItems(page, result.Items, "upcomingNewsItems", null, {
|
||||
showParentTitleOrTitle: true,
|
||||
showTitle: false,
|
||||
showParentTitle: false
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function renderItems(page, items, sectionClass, overlayButton, cardOptions) {
|
||||
var html = cardBuilder.getCardsHtml(Object.assign({
|
||||
items: items,
|
||||
preferThumb: "auto",
|
||||
inheritThumb: false,
|
||||
shape: enableScrollX() ? "autooverflow" : "auto",
|
||||
defaultShape: getBackdropShape(),
|
||||
showParentTitle: true,
|
||||
showTitle: true,
|
||||
centerText: true,
|
||||
coverImage: true,
|
||||
overlayText: false,
|
||||
lazy: true,
|
||||
overlayPlayButton: "play" === overlayButton,
|
||||
overlayMoreButton: "more" === overlayButton,
|
||||
overlayInfoButton: "info" === overlayButton,
|
||||
allowBottomPadding: !enableScrollX(),
|
||||
showAirTime: true,
|
||||
showAirDateTime: true
|
||||
}, cardOptions || {}));
|
||||
var elem = page.querySelector("." + sectionClass);
|
||||
elem.innerHTML = html;
|
||||
imageLoader.lazyChildren(elem);
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [
|
||||
{ name: globalize.translate("Programs") },
|
||||
{ name: globalize.translate("TabGuide") },
|
||||
{ name: globalize.translate("TabChannels") },
|
||||
{ name: globalize.translate("TabRecordings") },
|
||||
{ name: globalize.translate("HeaderSchedule") },
|
||||
{ name: globalize.translate("TabSeries") },
|
||||
{ name: globalize.translate("ButtonSearch"), cssClass: "searchTabButton" }
|
||||
];
|
||||
}
|
||||
|
||||
function setScrollClasses(elem, scrollX) {
|
||||
if (scrollX) {
|
||||
elem.classList.add("hiddenScrollX");
|
||||
|
||||
if (layoutManager.tv) {
|
||||
elem.classList.add("smoothScrollX");
|
||||
}
|
||||
|
||||
elem.classList.add("scrollX");
|
||||
elem.classList.remove("vertical-wrap");
|
||||
} else {
|
||||
elem.classList.remove("hiddenScrollX");
|
||||
elem.classList.remove("smoothScrollX");
|
||||
elem.classList.remove("scrollX");
|
||||
elem.classList.add("vertical-wrap");
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultTabIndex(folderId) {
|
||||
if (userSettings.get("landing-" + folderId) === "guide") {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return function (view, params) {
|
||||
function enableFullRender() {
|
||||
return new Date().getTime() - lastFullRender > 3e5;
|
||||
}
|
||||
|
||||
function onBeforeTabChange(evt) {
|
||||
preLoadTab(view, parseInt(evt.detail.selectedTabIndex));
|
||||
}
|
||||
|
||||
function onTabChange(evt) {
|
||||
var previousTabController = tabControllers[parseInt(evt.detail.previousIndex)];
|
||||
|
||||
if (previousTabController && previousTabController.onHide) {
|
||||
previousTabController.onHide();
|
||||
}
|
||||
|
||||
loadTab(view, parseInt(evt.detail.selectedTabIndex));
|
||||
}
|
||||
|
||||
function getTabContainers() {
|
||||
return view.querySelectorAll(".pageTabContent");
|
||||
}
|
||||
|
||||
function initTabs() {
|
||||
mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange);
|
||||
}
|
||||
|
||||
function getTabController(page, index, callback) {
|
||||
var depends = [];
|
||||
|
||||
// TODO int is a little hard to read
|
||||
switch (index) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
depends.push("scripts/livetvguide");
|
||||
break;
|
||||
case 2:
|
||||
depends.push("scripts/livetvchannels");
|
||||
break;
|
||||
case 3:
|
||||
depends.push("scripts/livetvrecordings");
|
||||
break;
|
||||
case 4:
|
||||
depends.push("scripts/livetvschedule");
|
||||
break;
|
||||
case 5:
|
||||
depends.push("scripts/livetvseriestimers");
|
||||
break;
|
||||
case 6:
|
||||
depends.push("scripts/searchtab");
|
||||
}
|
||||
|
||||
require(depends, function (controllerFactory) {
|
||||
var tabContent;
|
||||
|
||||
if (0 == index) {
|
||||
tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']");
|
||||
self.tabContent = tabContent;
|
||||
}
|
||||
|
||||
var controller = tabControllers[index];
|
||||
|
||||
if (!controller) {
|
||||
tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']");
|
||||
if (0 === index) {
|
||||
controller = self;
|
||||
} else if (6 === index) {
|
||||
controller = new controllerFactory(view, tabContent, {
|
||||
collectionType: "livetv"
|
||||
});
|
||||
} else {
|
||||
controller = new controllerFactory(view, params, tabContent);
|
||||
}
|
||||
tabControllers[index] = controller;
|
||||
|
||||
if (controller.initTab) {
|
||||
controller.initTab();
|
||||
}
|
||||
}
|
||||
|
||||
callback(controller);
|
||||
});
|
||||
}
|
||||
|
||||
function preLoadTab(page, index) {
|
||||
getTabController(page, index, function (controller) {
|
||||
if (renderedTabs.indexOf(index) === -1 && controller.preRender) {
|
||||
controller.preRender();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadTab(page, index) {
|
||||
currentTabIndex = index;
|
||||
getTabController(page, index, function (controller) {
|
||||
initialTabIndex = null;
|
||||
|
||||
if (1 === index) {
|
||||
document.body.classList.add("autoScrollY");
|
||||
} else {
|
||||
document.body.classList.remove("autoScrollY");
|
||||
}
|
||||
|
||||
if (-1 == renderedTabs.indexOf(index)) {
|
||||
if (1 === index) {
|
||||
renderedTabs.push(index);
|
||||
}
|
||||
|
||||
controller.renderTab();
|
||||
} else if (controller.onShow) {
|
||||
controller.onShow();
|
||||
}
|
||||
|
||||
currentTabController = controller;
|
||||
});
|
||||
}
|
||||
|
||||
function onInputCommand(evt) {
|
||||
if (evt.detail.command === "search") {
|
||||
evt.preventDefault();
|
||||
Dashboard.navigate("search.html?collectionType=livetv");
|
||||
}
|
||||
}
|
||||
|
||||
var isViewRestored;
|
||||
var self = this;
|
||||
var currentTabIndex = parseInt(params.tab || getDefaultTabIndex("livetv"));
|
||||
var initialTabIndex = currentTabIndex;
|
||||
var lastFullRender = 0;
|
||||
[].forEach.call(view.querySelectorAll(".sectionTitleTextButton-programs"), function (link) {
|
||||
var href = link.href;
|
||||
|
||||
if (href) {
|
||||
link.href = href + "&serverId=" + ApiClient.serverId();
|
||||
}
|
||||
});
|
||||
|
||||
self.initTab = function () {
|
||||
var tabContent = view.querySelector(".pageTabContent[data-index='0']");
|
||||
var containers = tabContent.querySelectorAll(".itemsContainer");
|
||||
|
||||
for (var i = 0, length = containers.length; i < length; i++) {
|
||||
setScrollClasses(containers[i], enableScrollX());
|
||||
}
|
||||
};
|
||||
|
||||
self.renderTab = function () {
|
||||
var tabContent = view.querySelector(".pageTabContent[data-index='0']");
|
||||
|
||||
if (enableFullRender()) {
|
||||
reload(tabContent, true);
|
||||
lastFullRender = new Date().getTime();
|
||||
} else {
|
||||
reload(tabContent);
|
||||
}
|
||||
};
|
||||
|
||||
var currentTabController;
|
||||
var tabControllers = [];
|
||||
var renderedTabs = [];
|
||||
view.addEventListener("viewbeforeshow", function (evt) {
|
||||
isViewRestored = evt.detail.isRestored;
|
||||
initTabs();
|
||||
});
|
||||
view.addEventListener("viewshow", function (evt) {
|
||||
isViewRestored = evt.detail.isRestored;
|
||||
if (!isViewRestored) {
|
||||
mainTabsManager.selectedTabIndex(initialTabIndex);
|
||||
}
|
||||
inputManager.on(window, onInputCommand);
|
||||
});
|
||||
view.addEventListener("viewbeforehide", function (e__u) {
|
||||
if (currentTabController && currentTabController.onHide) {
|
||||
currentTabController.onHide();
|
||||
}
|
||||
document.body.classList.remove("autoScrollY");
|
||||
inputManager.off(window, onInputCommand);
|
||||
});
|
||||
view.addEventListener("viewdestroy", function (evt) {
|
||||
tabControllers.forEach(function (tabController) {
|
||||
if (tabController.destroy) {
|
||||
tabController.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
143
src/controllers/livetvtuner.js
Normal file
143
src/controllers/livetvtuner.js
Normal file
|
@ -0,0 +1,143 @@
|
|||
define(["globalize", "loading", "libraryMenu", "dom", "emby-input", "emby-button", "emby-checkbox", "emby-select"], function(globalize, loading, libraryMenu, dom) {
|
||||
"use strict";
|
||||
|
||||
function isM3uVariant(type) {
|
||||
return ["nextpvr"].indexOf(type || "") !== -1;
|
||||
}
|
||||
|
||||
function fillTypes(view, currentId) {
|
||||
ApiClient.getJSON(ApiClient.getUrl("LiveTv/TunerHosts/Types")).then(function(types) {
|
||||
var selectType = view.querySelector(".selectType");
|
||||
var html = "";
|
||||
html += types.map(function(tuner) {
|
||||
return '<option value="' + tuner.Id + '">' + tuner.Name + "</option>";
|
||||
}).join("");
|
||||
html += '<option value="other">';
|
||||
html += globalize.translate("TabOther");
|
||||
html += "</option>";
|
||||
selectType.innerHTML = html;
|
||||
|
||||
selectType.disabled = null != currentId;
|
||||
selectType.value = "";
|
||||
onTypeChange.call(selectType);
|
||||
});
|
||||
}
|
||||
|
||||
function reload(view, providerId) {
|
||||
view.querySelector(".txtDevicePath").value = "";
|
||||
view.querySelector(".chkFavorite").checked = false;
|
||||
view.querySelector(".txtDevicePath").value = "";
|
||||
if (providerId) {
|
||||
ApiClient.getNamedConfiguration("livetv").then(function(config) {
|
||||
var info = config.TunerHosts.filter(function(i) {
|
||||
return i.Id === providerId;
|
||||
})[0];
|
||||
fillTunerHostInfo(view, info);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function fillTunerHostInfo(view, info) {
|
||||
var selectType = view.querySelector(".selectType");
|
||||
var type = info.Type || "";
|
||||
if (info.Source && isM3uVariant(info.Source)) {
|
||||
type = info.Source;
|
||||
}
|
||||
selectType.value = type;
|
||||
onTypeChange.call(selectType);
|
||||
view.querySelector(".txtDevicePath").value = info.Url || "";
|
||||
view.querySelector(".txtFriendlyName").value = info.FriendlyName || "";
|
||||
view.querySelector(".txtUserAgent").value = info.UserAgent || "";
|
||||
view.querySelector(".fldDeviceId").value = info.DeviceId || "";
|
||||
view.querySelector(".chkFavorite").checked = info.ImportFavoritesOnly;
|
||||
view.querySelector(".chkTranscode").checked = info.AllowHWTranscoding;
|
||||
view.querySelector(".chkStreamLoop").checked = info.EnableStreamLooping;
|
||||
view.querySelector(".txtTunerCount").value = info.TunerCount || "0";
|
||||
}
|
||||
|
||||
function submitForm(page) {
|
||||
loading.show();
|
||||
var info = {
|
||||
Type: page.querySelector(".selectType").value,
|
||||
Url: page.querySelector(".txtDevicePath").value || null,
|
||||
UserAgent: page.querySelector(".txtUserAgent").value || null,
|
||||
FriendlyName: page.querySelector(".txtFriendlyName").value || null,
|
||||
DeviceId: page.querySelector(".fldDeviceId").value || null,
|
||||
TunerCount: page.querySelector(".txtTunerCount").value || 0,
|
||||
ImportFavoritesOnly: page.querySelector(".chkFavorite").checked,
|
||||
AllowHWTranscoding: page.querySelector(".chkTranscode").checked,
|
||||
EnableStreamLooping: page.querySelector(".chkStreamLoop").checked
|
||||
};
|
||||
isM3uVariant(info.Type) && (info.Source = info.Type, info.Type = "m3u");
|
||||
var id = getParameterByName("id");
|
||||
id && (info.Id = id);
|
||||
info.Id;
|
||||
ApiClient.ajax({
|
||||
type: "POST",
|
||||
url: ApiClient.getUrl("LiveTv/TunerHosts"),
|
||||
data: JSON.stringify(info),
|
||||
contentType: "application/json"
|
||||
}).then(function(result) {
|
||||
Dashboard.processServerConfigurationUpdateResult(), Dashboard.navigate("livetvstatus.html")
|
||||
}, function() {
|
||||
loading.hide(), Dashboard.alert({
|
||||
message: globalize.translate("ErrorSavingTvProvider")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getRequirePromise(deps) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
require(deps, resolve)
|
||||
})
|
||||
}
|
||||
|
||||
function getDetectedDevice() {
|
||||
return getRequirePromise(["tunerPicker"]).then(function(tunerPicker) {
|
||||
return (new tunerPicker).show({
|
||||
serverId: ApiClient.serverId()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onTypeChange() {
|
||||
var value = this.value,
|
||||
view = dom.parentWithClass(this, "page"),
|
||||
mayIncludeUnsupportedDrmChannels = "hdhomerun" === value,
|
||||
supportsTranscoding = "hdhomerun" === value,
|
||||
supportsFavorites = "hdhomerun" === value,
|
||||
supportsTunerIpAddress = "hdhomerun" === value,
|
||||
supportsTunerFileOrUrl = "m3u" === value,
|
||||
supportsStreamLooping = "m3u" === value,
|
||||
supportsTunerCount = "m3u" === value,
|
||||
supportsUserAgent = "m3u" === value,
|
||||
suppportsSubmit = "other" !== value,
|
||||
supportsSelectablePath = supportsTunerFileOrUrl,
|
||||
txtDevicePath = view.querySelector(".txtDevicePath");
|
||||
supportsTunerIpAddress ? (txtDevicePath.label(globalize.translate("LabelTunerIpAddress")), view.querySelector(".fldPath").classList.remove("hide")) : supportsTunerFileOrUrl ? (txtDevicePath.label(globalize.translate("LabelFileOrUrl")), view.querySelector(".fldPath").classList.remove("hide")) : view.querySelector(".fldPath").classList.add("hide"), supportsSelectablePath ? (view.querySelector(".btnSelectPath").classList.remove("hide"), view.querySelector(".txtDevicePath").setAttribute("required", "required")) : (view.querySelector(".btnSelectPath").classList.add("hide"), view.querySelector(".txtDevicePath").removeAttribute("required")), supportsUserAgent ? view.querySelector(".fldUserAgent").classList.remove("hide") : view.querySelector(".fldUserAgent").classList.add("hide"), supportsFavorites ? view.querySelector(".fldFavorites").classList.remove("hide") : view.querySelector(".fldFavorites").classList.add("hide"), supportsTranscoding ? view.querySelector(".fldTranscode").classList.remove("hide") : view.querySelector(".fldTranscode").classList.add("hide"), supportsStreamLooping ? view.querySelector(".fldStreamLoop").classList.remove("hide") : view.querySelector(".fldStreamLoop").classList.add("hide"), supportsTunerCount ? (view.querySelector(".fldTunerCount").classList.remove("hide"), view.querySelector(".txtTunerCount").setAttribute("required", "required")) : (view.querySelector(".fldTunerCount").classList.add("hide"), view.querySelector(".txtTunerCount").removeAttribute("required")), mayIncludeUnsupportedDrmChannels ? view.querySelector(".drmMessage").classList.remove("hide") : view.querySelector(".drmMessage").classList.add("hide"), suppportsSubmit ? (view.querySelector(".button-submit").classList.remove("hide"), view.querySelector(".otherOptionsMessage").classList.add("hide")) : (view.querySelector(".button-submit").classList.add("hide"), view.querySelector(".otherOptionsMessage").classList.remove("hide"))
|
||||
}
|
||||
return function(view, params) {
|
||||
params.id || view.querySelector(".btnDetect").classList.remove("hide"), view.addEventListener("viewshow", function() {
|
||||
var currentId = params.id;
|
||||
fillTypes(view, currentId).then(function() {
|
||||
reload(view, currentId)
|
||||
})
|
||||
}), view.querySelector("form").addEventListener("submit", function(e) {
|
||||
return submitForm(view), e.preventDefault(), e.stopPropagation(), !1
|
||||
}), view.querySelector(".selectType").addEventListener("change", onTypeChange), view.querySelector(".btnDetect").addEventListener("click", function() {
|
||||
getDetectedDevice().then(function(info) {
|
||||
fillTunerHostInfo(view, info)
|
||||
})
|
||||
}), view.querySelector(".btnSelectPath").addEventListener("click", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
includeFiles: !0,
|
||||
callback: function(path) {
|
||||
path && (view.querySelector(".txtDevicePath").value = path), picker.close()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
98
src/controllers/loginpage.js
Normal file
98
src/controllers/loginpage.js
Normal file
|
@ -0,0 +1,98 @@
|
|||
define(["appSettings", "dom", "connectionManager", "loading", "cardStyle", "emby-checkbox"], function(appSettings, dom, connectionManager, loading) {
|
||||
"use strict";
|
||||
|
||||
function authenticateUserByName(page, apiClient, username, password) {
|
||||
loading.show(), apiClient.authenticateUserByName(username, password).then(function(result) {
|
||||
var newUrl, user = result.User,
|
||||
serverId = getParameterByName("serverid");
|
||||
newUrl = user.Policy.IsAdministrator && !serverId ? "dashboard.html" : "home.html", loading.hide(), Dashboard.onServerChanged(user.Id, result.AccessToken, apiClient), Dashboard.navigate(newUrl)
|
||||
}, function(response) {
|
||||
page.querySelector("#txtManualName").value = "", page.querySelector("#txtManualPassword").value = "", loading.hide(), 401 == response.status ? require(["toast"], function(toast) {
|
||||
toast(Globalize.translate("MessageInvalidUser"))
|
||||
}) : showServerConnectionFailure()
|
||||
})
|
||||
}
|
||||
|
||||
function showServerConnectionFailure() {
|
||||
Dashboard.alert({
|
||||
message: Globalize.translate("MessageUnableToConnectToServer"),
|
||||
title: Globalize.translate("HeaderConnectionFailure")
|
||||
})
|
||||
}
|
||||
|
||||
function showManualForm(context, showCancel, focusPassword) {
|
||||
context.querySelector(".chkRememberLogin").checked = appSettings.enableAutoLogin(), context.querySelector(".manualLoginForm").classList.remove("hide"), context.querySelector(".visualLoginForm").classList.add("hide"), focusPassword ? context.querySelector("#txtManualPassword").focus() : context.querySelector("#txtManualName").focus(), showCancel ? context.querySelector(".btnCancel").classList.remove("hide") : context.querySelector(".btnCancel").classList.add("hide")
|
||||
}
|
||||
|
||||
function getRandomMetroColor() {
|
||||
var index = Math.floor(Math.random() * (metroColors.length - 1));
|
||||
return metroColors[index]
|
||||
}
|
||||
|
||||
function getMetroColor(str) {
|
||||
if (str) {
|
||||
for (var character = String(str.substr(0, 1).charCodeAt()), sum = 0, i = 0; i < character.length; i++) sum += parseInt(character.charAt(i));
|
||||
var index = String(sum).substr(-1);
|
||||
return metroColors[index]
|
||||
}
|
||||
return getRandomMetroColor()
|
||||
}
|
||||
|
||||
function loadUserList(context, apiClient, users) {
|
||||
for (var html = "", i = 0, length = users.length; i < length; i++) {
|
||||
var user = users[i];
|
||||
html += '<button type="button" class="card squareCard scalableCard squareCard-scalable"><div class="cardBox cardBox-bottompadded">', html += '<div class="cardScalable">', html += '<div class="cardPadder cardPadder-square"></div>', html += '<div class="cardContent" data-haspw="' + user.HasPassword + '" data-username="' + user.Name + '" data-userid="' + user.Id + '">';
|
||||
var imgUrl;
|
||||
if (user.PrimaryImageTag) imgUrl = apiClient.getUserImageUrl(user.Id, {
|
||||
width: 300,
|
||||
tag: user.PrimaryImageTag,
|
||||
type: "Primary"
|
||||
}), html += '<div class="cardImageContainer coveredImage coveredImage-noScale" style="background-image:url(\'' + imgUrl + "');\"></div>";
|
||||
else {
|
||||
var background = getMetroColor(user.Id);
|
||||
imgUrl = "css/images/logindefault.png", html += '<div class="cardImageContainer coveredImage coveredImage-noScale" style="background-image:url(\'' + imgUrl + "');background-color:" + background + ';"></div>'
|
||||
}
|
||||
html += "</div>", html += "</div>", html += '<div class="cardFooter visualCardBox-cardFooter">', html += '<div class="cardText singleCardText cardTextCentered">' + user.Name + "</div>", html += "</div>", html += "</div>", html += "</button>"
|
||||
}
|
||||
context.querySelector("#divUsers").innerHTML = html
|
||||
}
|
||||
var metroColors = ["#6FBD45", "#4BB3DD", "#4164A5", "#E12026", "#800080", "#E1B222", "#008040", "#0094FF", "#FF00C7", "#FF870F", "#7F0037"];
|
||||
return function(view, params) {
|
||||
function getApiClient() {
|
||||
var serverId = params.serverid;
|
||||
return serverId ? connectionManager.getOrCreateApiClient(serverId) : ApiClient
|
||||
}
|
||||
|
||||
function showVisualForm() {
|
||||
view.querySelector(".visualLoginForm").classList.remove("hide"), view.querySelector(".manualLoginForm").classList.add("hide")
|
||||
}
|
||||
view.querySelector("#divUsers").addEventListener("click", function(e) {
|
||||
var card = dom.parentWithClass(e.target, "card"),
|
||||
cardContent = card ? card.querySelector(".cardContent") : null;
|
||||
if (cardContent) {
|
||||
var context = view,
|
||||
id = cardContent.getAttribute("data-userid"),
|
||||
name = cardContent.getAttribute("data-username"),
|
||||
haspw = cardContent.getAttribute("data-haspw");
|
||||
"manual" == id ? (context.querySelector("#txtManualName").value = "", showManualForm(context, !0)) : "false" == haspw ? authenticateUserByName(context, getApiClient(), name, "") : (context.querySelector("#txtManualName").value = name, context.querySelector("#txtManualPassword").value = "", showManualForm(context, !0, !0))
|
||||
}
|
||||
}), view.querySelector(".manualLoginForm").addEventListener("submit", function(e) {
|
||||
appSettings.enableAutoLogin(view.querySelector(".chkRememberLogin").checked);
|
||||
var apiClient = getApiClient();
|
||||
return authenticateUserByName(view, apiClient, view.querySelector("#txtManualName").value, view.querySelector("#txtManualPassword").value), e.preventDefault(), !1
|
||||
}), view.querySelector(".btnForgotPassword").addEventListener("click", function() {
|
||||
Dashboard.navigate("forgotpassword.html")
|
||||
}), view.querySelector(".btnCancel").addEventListener("click", showVisualForm), view.querySelector(".btnManual").addEventListener("click", function() {
|
||||
view.querySelector("#txtManualName").value = "", showManualForm(view, !0)
|
||||
}), view.addEventListener("viewshow", function(e) {
|
||||
loading.show();
|
||||
var apiClient = getApiClient();
|
||||
apiClient.getPublicUsers().then(function(users) {
|
||||
users.length ? users.length && users[0].EnableAutoLogin ? authenticateUserByName(view, apiClient, users[0].Name, "") : (showVisualForm(), loadUserList(view, apiClient, users)) : (view.querySelector("#txtManualName").value = "", showManualForm(view, !1, !1)), loading.hide()
|
||||
});
|
||||
apiClient.getJSON(apiClient.getUrl("Branding/Configuration")).then(function(options) {
|
||||
view.querySelector(".disclaimer").textContent = options.LoginDisclaimer || ""
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
29
src/controllers/logpage.js
Normal file
29
src/controllers/logpage.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
define(["datetime", "loading", "apphost", "listViewStyle", "emby-linkbutton", "flexStyles"], function(datetime, loading, appHost) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
view.querySelector("#chkDebugLog").addEventListener("change", function() {
|
||||
ApiClient.getServerConfiguration().then(function(config) {
|
||||
config.EnableDebugLevelLogging = view.querySelector("#chkDebugLog").checked, ApiClient.updateServerConfiguration(config)
|
||||
})
|
||||
}), view.addEventListener("viewbeforeshow", function() {
|
||||
loading.show();
|
||||
var apiClient = ApiClient;
|
||||
apiClient.getJSON(apiClient.getUrl("System/Logs")).then(function(logs) {
|
||||
var html = "";
|
||||
html += '<div class="paperList">', html += logs.map(function(log) {
|
||||
var logUrl = apiClient.getUrl("System/Logs/Log", {
|
||||
name: log.Name
|
||||
});
|
||||
logUrl += "&api_key=" + apiClient.accessToken();
|
||||
var logHtml = "";
|
||||
logHtml += '<a is="emby-linkbutton" href="' + logUrl + '" target="_blank" class="listItem listItem-border" style="color:inherit;">', logHtml += '<div class="listItemBody two-line">', logHtml += "<h3 class='listItemBodyText'>" + log.Name + "</h3>";
|
||||
var date = datetime.parseISO8601Date(log.DateModified, !0),
|
||||
text = datetime.toLocaleDateString(date);
|
||||
return text += " " + datetime.getDisplayTime(date), logHtml += '<div class="listItemBodyText secondary">' + text + "</div>", logHtml += "</div>", logHtml += "</a>"
|
||||
}).join(""), html += "</div>", view.querySelector(".serverLogs").innerHTML = html, loading.hide()
|
||||
}), apiClient.getServerConfiguration().then(function(config) {
|
||||
view.querySelector("#chkDebugLog").checked = config.EnableDebugLevelLogging
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
276
src/controllers/moviesrecommended.js
Normal file
276
src/controllers/moviesrecommended.js
Normal file
|
@ -0,0 +1,276 @@
|
|||
define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu", "mainTabsManager", "cardBuilder", "dom", "imageLoader", "playbackManager", "emby-itemscontainer", "emby-tabs", "emby-button"], function(events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, cardBuilder, dom, imageLoader, playbackManager) {
|
||||
"use strict";
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop
|
||||
}
|
||||
|
||||
function getPortraitShape() {
|
||||
return enableScrollX() ? "overflowPortrait" : "portrait"
|
||||
}
|
||||
|
||||
function getThumbShape() {
|
||||
return enableScrollX() ? "overflowBackdrop" : "backdrop"
|
||||
}
|
||||
|
||||
function loadLatest(page, userId, parentId) {
|
||||
var options = {
|
||||
IncludeItemTypes: "Movie",
|
||||
Limit: 18,
|
||||
Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo",
|
||||
ParentId: parentId,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
EnableTotalRecordCount: !1
|
||||
};
|
||||
ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function(items) {
|
||||
var allowBottomPadding = !enableScrollX(),
|
||||
container = page.querySelector("#recentlyAddedItems");
|
||||
cardBuilder.buildCards(items, {
|
||||
itemsContainer: container,
|
||||
shape: getPortraitShape(),
|
||||
scalable: !0,
|
||||
overlayPlayButton: !0,
|
||||
allowBottomPadding: allowBottomPadding,
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
centerText: !0
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function loadResume(page, userId, parentId) {
|
||||
var screenWidth = dom.getWindowSize().innerWidth,
|
||||
options = {
|
||||
SortBy: "DatePlayed",
|
||||
SortOrder: "Descending",
|
||||
IncludeItemTypes: "Movie",
|
||||
Filters: "IsResumable",
|
||||
Limit: screenWidth >= 1920 ? 5 : screenWidth >= 1600 ? 5 : 3,
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo",
|
||||
CollapseBoxSetItems: !1,
|
||||
ParentId: parentId,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
EnableTotalRecordCount: !1
|
||||
};
|
||||
ApiClient.getItems(userId, options).then(function(result) {
|
||||
result.Items.length ? page.querySelector("#resumableSection").classList.remove("hide") : page.querySelector("#resumableSection").classList.add("hide");
|
||||
var allowBottomPadding = !enableScrollX(),
|
||||
container = page.querySelector("#resumableItems");
|
||||
cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: container,
|
||||
preferThumb: !0,
|
||||
shape: getThumbShape(),
|
||||
scalable: !0,
|
||||
overlayPlayButton: !0,
|
||||
allowBottomPadding: allowBottomPadding,
|
||||
cardLayout: !1,
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
centerText: !0
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getRecommendationHtml(recommendation) {
|
||||
var html = "",
|
||||
title = "";
|
||||
switch (recommendation.RecommendationType) {
|
||||
case "SimilarToRecentlyPlayed":
|
||||
title = Globalize.translate("RecommendationBecauseYouWatched").replace("{0}", recommendation.BaselineItemName);
|
||||
break;
|
||||
case "SimilarToLikedItem":
|
||||
title = Globalize.translate("RecommendationBecauseYouLike").replace("{0}", recommendation.BaselineItemName);
|
||||
break;
|
||||
case "HasDirectorFromRecentlyPlayed":
|
||||
case "HasLikedDirector":
|
||||
title = Globalize.translate("RecommendationDirectedBy").replace("{0}", recommendation.BaselineItemName);
|
||||
break;
|
||||
case "HasActorFromRecentlyPlayed":
|
||||
case "HasLikedActor":
|
||||
title = Globalize.translate("RecommendationStarring").replace("{0}", recommendation.BaselineItemName)
|
||||
}
|
||||
html += '<div class="verticalSection">', html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + title + "</h2>";
|
||||
var allowBottomPadding = !0;
|
||||
return enableScrollX() ? (allowBottomPadding = !1, html += '<div is="emby-itemscontainer" class="itemsContainer scrollX hiddenScrollX padded-left padded-right">') : html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right">', html += cardBuilder.getCardsHtml(recommendation.Items, {
|
||||
shape: getPortraitShape(),
|
||||
scalable: !0,
|
||||
overlayPlayButton: !0,
|
||||
allowBottomPadding: allowBottomPadding
|
||||
}), html += "</div>", html += "</div>"
|
||||
}
|
||||
|
||||
function loadSuggestions(page, userId, parentId) {
|
||||
var screenWidth = dom.getWindowSize().innerWidth,
|
||||
url = ApiClient.getUrl("Movies/Recommendations", {
|
||||
userId: userId,
|
||||
categoryLimit: 6,
|
||||
ItemLimit: screenWidth >= 1920 ? 8 : screenWidth >= 1600 ? 8 : screenWidth >= 1200 ? 6 : 5,
|
||||
Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo",
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb"
|
||||
});
|
||||
ApiClient.getJSON(url).then(function(recommendations) {
|
||||
if (!recommendations.length) return page.querySelector(".noItemsMessage").classList.remove("hide"), void(page.querySelector(".recommendations").innerHTML = "");
|
||||
var html = recommendations.map(getRecommendationHtml).join("");
|
||||
page.querySelector(".noItemsMessage").classList.add("hide");
|
||||
var recs = page.querySelector(".recommendations");
|
||||
recs.innerHTML = html, imageLoader.lazyChildren(recs)
|
||||
})
|
||||
}
|
||||
|
||||
function setScrollClasses(elem, scrollX) {
|
||||
scrollX ? (elem.classList.add("hiddenScrollX"), layoutManager.tv && elem.classList.add("smoothScrollX"), elem.classList.add("scrollX"), elem.classList.remove("vertical-wrap")) : (elem.classList.remove("hiddenScrollX"), elem.classList.remove("smoothScrollX"), elem.classList.remove("scrollX"), elem.classList.add("vertical-wrap"))
|
||||
}
|
||||
|
||||
function initSuggestedTab(page, tabContent) {
|
||||
for (var containers = tabContent.querySelectorAll(".itemsContainer"), i = 0, length = containers.length; i < length; i++) setScrollClasses(containers[i], enableScrollX())
|
||||
}
|
||||
|
||||
function loadSuggestionsTab(view, params, tabContent) {
|
||||
var parentId = params.topParentId,
|
||||
userId = ApiClient.getCurrentUserId();
|
||||
console.log("loadSuggestionsTab"), loadResume(tabContent, userId, parentId), loadLatest(tabContent, userId, parentId), loadSuggestions(tabContent, userId, parentId)
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
name: Globalize.translate("Movies")
|
||||
}, {
|
||||
name: Globalize.translate("TabSuggestions")
|
||||
}, {
|
||||
name: Globalize.translate("TabTrailers")
|
||||
}, {
|
||||
name: Globalize.translate("TabFavorites")
|
||||
}, {
|
||||
name: Globalize.translate("TabCollections")
|
||||
}, {
|
||||
name: Globalize.translate("TabGenres")
|
||||
}, {
|
||||
name: Globalize.translate("ButtonSearch"),
|
||||
cssClass: "searchTabButton"
|
||||
}]
|
||||
}
|
||||
|
||||
function getDefaultTabIndex(folderId) {
|
||||
switch (userSettings.get("landing-" + folderId)) {
|
||||
case "suggestions":
|
||||
return 1;
|
||||
case "favorites":
|
||||
return 3;
|
||||
case "collections":
|
||||
return 4;
|
||||
case "genres":
|
||||
return 5;
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return function(view, params) {
|
||||
function onBeforeTabChange(e) {
|
||||
preLoadTab(view, parseInt(e.detail.selectedTabIndex))
|
||||
}
|
||||
|
||||
function onTabChange(e) {
|
||||
var newIndex = parseInt(e.detail.selectedTabIndex);
|
||||
loadTab(view, newIndex)
|
||||
}
|
||||
|
||||
function getTabContainers() {
|
||||
return view.querySelectorAll(".pageTabContent")
|
||||
}
|
||||
|
||||
function initTabs() {
|
||||
mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange)
|
||||
}
|
||||
|
||||
function getTabController(page, index, callback) {
|
||||
var depends = [];
|
||||
switch (index) {
|
||||
case 0:
|
||||
depends.push("scripts/movies");
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
depends.push("scripts/movietrailers");
|
||||
break;
|
||||
case 3:
|
||||
depends.push("scripts/movies");
|
||||
break;
|
||||
case 4:
|
||||
depends.push("scripts/moviecollections");
|
||||
break;
|
||||
case 5:
|
||||
depends.push("scripts/moviegenres");
|
||||
break;
|
||||
case 6:
|
||||
depends.push("scripts/searchtab")
|
||||
}
|
||||
require(depends, function(controllerFactory) {
|
||||
var tabContent;
|
||||
index === suggestionsTabIndex && (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), self.tabContent = tabContent);
|
||||
var controller = tabControllers[index];
|
||||
controller || (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), controller = index === suggestionsTabIndex ? self : 6 === index ? new controllerFactory(view, tabContent, {
|
||||
collectionType: "movies",
|
||||
parentId: params.topParentId
|
||||
}) : 0 === index || 3 === index ? new controllerFactory(view, params, tabContent, {
|
||||
mode: index ? "favorites" : "movies"
|
||||
}) : new controllerFactory(view, params, tabContent), tabControllers[index] = controller, controller.initTab && controller.initTab()), callback(controller)
|
||||
})
|
||||
}
|
||||
|
||||
function preLoadTab(page, index) {
|
||||
getTabController(page, index, function(controller) {
|
||||
-1 == renderedTabs.indexOf(index) && controller.preRender && controller.preRender()
|
||||
})
|
||||
}
|
||||
|
||||
function loadTab(page, index) {
|
||||
currentTabIndex = index, getTabController(page, index, function(controller) {
|
||||
initialTabIndex = null, -1 == renderedTabs.indexOf(index) && (renderedTabs.push(index), controller.renderTab())
|
||||
})
|
||||
}
|
||||
|
||||
function onPlaybackStop(e, state) {
|
||||
state.NowPlayingItem && "Video" == state.NowPlayingItem.MediaType && (renderedTabs = [], mainTabsManager.getTabsElement().triggerTabChange())
|
||||
}
|
||||
|
||||
function onInputCommand(e) {
|
||||
switch (e.detail.command) {
|
||||
case "search":
|
||||
e.preventDefault(), Dashboard.navigate("search.html?collectionType=movies&parentId=" + params.topParentId)
|
||||
}
|
||||
}
|
||||
var isViewRestored, self = this,
|
||||
currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)),
|
||||
initialTabIndex = currentTabIndex,
|
||||
suggestionsTabIndex = 1;
|
||||
self.initTab = function() {
|
||||
var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
|
||||
initSuggestedTab(view, tabContent);
|
||||
}, self.renderTab = function() {
|
||||
var tabContent = view.querySelector(".pageTabContent[data-index='" + suggestionsTabIndex + "']");
|
||||
loadSuggestionsTab(view, params, tabContent)
|
||||
};
|
||||
var tabControllers = [],
|
||||
renderedTabs = [];
|
||||
view.addEventListener("viewshow", function(e) {
|
||||
if (isViewRestored = e.detail.isRestored, initTabs(), !view.getAttribute("data-title")) {
|
||||
var parentId = params.topParentId;
|
||||
parentId ? ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function(item) {
|
||||
view.setAttribute("data-title", item.Name), libraryMenu.setTitle(item.Name)
|
||||
}) : (view.setAttribute("data-title", Globalize.translate("TabMovies")), libraryMenu.setTitle(Globalize.translate("TabMovies")))
|
||||
}
|
||||
events.on(playbackManager, "playbackstop", onPlaybackStop), inputManager.on(window, onInputCommand)
|
||||
}), view.addEventListener("viewbeforehide", function(e) {
|
||||
inputManager.off(window, onInputCommand)
|
||||
}), view.addEventListener("viewdestroy", function(e) {
|
||||
tabControllers.forEach(function(t) {
|
||||
t.destroy && t.destroy()
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
279
src/controllers/musicrecommended.js
Normal file
279
src/controllers/musicrecommended.js
Normal file
|
@ -0,0 +1,279 @@
|
|||
define(["browser", "layoutManager", "userSettings", "inputManager", "loading", "cardBuilder", "dom", "apphost", "imageLoader", "libraryMenu", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-tabs", "emby-button", "flexStyles"], function(browser, layoutManager, userSettings, inputManager, loading, cardBuilder, dom, appHost, imageLoader, libraryMenu, playbackManager, mainTabsManager) {
|
||||
"use strict";
|
||||
|
||||
function itemsPerRow() {
|
||||
var screenWidth = dom.getWindowSize().innerWidth;
|
||||
return screenWidth >= 1920 ? 9 : screenWidth >= 1200 ? 12 : screenWidth >= 1e3 ? 10 : 8
|
||||
}
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop
|
||||
}
|
||||
|
||||
function getSquareShape() {
|
||||
return enableScrollX() ? "overflowSquare" : "square"
|
||||
}
|
||||
|
||||
function loadLatest(page, parentId) {
|
||||
loading.show();
|
||||
var userId = ApiClient.getCurrentUserId(),
|
||||
options = {
|
||||
IncludeItemTypes: "Audio",
|
||||
Limit: enableScrollX() ? 3 * itemsPerRow() : 2 * itemsPerRow(),
|
||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
ParentId: parentId,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
EnableTotalRecordCount: !1
|
||||
};
|
||||
ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function(items) {
|
||||
var elem = page.querySelector("#recentlyAddedSongs"),
|
||||
supportsImageAnalysis = appHost.supports("imageanalysis");
|
||||
supportsImageAnalysis = !1, elem.innerHTML = cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
showUnplayedIndicator: !1,
|
||||
showLatestItemsPopup: !1,
|
||||
shape: getSquareShape(),
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
lazy: !0,
|
||||
centerText: !supportsImageAnalysis,
|
||||
overlayPlayButton: !supportsImageAnalysis,
|
||||
allowBottomPadding: !enableScrollX(),
|
||||
cardLayout: supportsImageAnalysis,
|
||||
vibrant: supportsImageAnalysis,
|
||||
coverImage: !0
|
||||
}), imageLoader.lazyChildren(elem), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function loadRecentlyPlayed(page, parentId) {
|
||||
var options = {
|
||||
SortBy: "DatePlayed",
|
||||
SortOrder: "Descending",
|
||||
IncludeItemTypes: "Audio",
|
||||
Limit: itemsPerRow(),
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,AudioInfo",
|
||||
Filters: "IsPlayed",
|
||||
ParentId: parentId,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
EnableTotalRecordCount: !1
|
||||
};
|
||||
ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) {
|
||||
var elem = page.querySelector("#recentlyPlayed");
|
||||
result.Items.length ? elem.classList.remove("hide") : elem.classList.add("hide");
|
||||
var itemsContainer = elem.querySelector(".itemsContainer"),
|
||||
supportsImageAnalysis = appHost.supports("imageanalysis");
|
||||
supportsImageAnalysis = !1, itemsContainer.innerHTML = cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
showUnplayedIndicator: !1,
|
||||
shape: getSquareShape(),
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
action: "instantmix",
|
||||
lazy: !0,
|
||||
centerText: !supportsImageAnalysis,
|
||||
overlayMoreButton: !supportsImageAnalysis,
|
||||
allowBottomPadding: !enableScrollX(),
|
||||
cardLayout: supportsImageAnalysis,
|
||||
vibrant: supportsImageAnalysis,
|
||||
coverImage: !0
|
||||
}), imageLoader.lazyChildren(itemsContainer)
|
||||
})
|
||||
}
|
||||
|
||||
function loadFrequentlyPlayed(page, parentId) {
|
||||
var options = {
|
||||
SortBy: "PlayCount",
|
||||
SortOrder: "Descending",
|
||||
IncludeItemTypes: "Audio",
|
||||
Limit: itemsPerRow(),
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,AudioInfo",
|
||||
Filters: "IsPlayed",
|
||||
ParentId: parentId,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
EnableTotalRecordCount: !1
|
||||
};
|
||||
ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) {
|
||||
var elem = page.querySelector("#topPlayed");
|
||||
result.Items.length ? elem.classList.remove("hide") : elem.classList.add("hide");
|
||||
var itemsContainer = elem.querySelector(".itemsContainer"),
|
||||
supportsImageAnalysis = appHost.supports("imageanalysis");
|
||||
supportsImageAnalysis = !1, itemsContainer.innerHTML = cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
showUnplayedIndicator: !1,
|
||||
shape: getSquareShape(),
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
action: "instantmix",
|
||||
lazy: !0,
|
||||
centerText: !supportsImageAnalysis,
|
||||
overlayMoreButton: !supportsImageAnalysis,
|
||||
allowBottomPadding: !enableScrollX(),
|
||||
cardLayout: supportsImageAnalysis,
|
||||
vibrant: supportsImageAnalysis,
|
||||
coverImage: !0
|
||||
}), imageLoader.lazyChildren(itemsContainer)
|
||||
})
|
||||
}
|
||||
|
||||
function loadSuggestionsTab(page, tabContent, parentId) {
|
||||
console.log("loadSuggestionsTab"), loadLatest(tabContent, parentId), loadRecentlyPlayed(tabContent, parentId), loadFrequentlyPlayed(tabContent, parentId), require(["components/favoriteitems"], function(favoriteItems) {
|
||||
favoriteItems.render(tabContent, ApiClient.getCurrentUserId(), parentId, ["favoriteArtists", "favoriteAlbums", "favoriteSongs"])
|
||||
})
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
name: Globalize.translate("TabSuggestions")
|
||||
}, {
|
||||
name: Globalize.translate("TabAlbums")
|
||||
}, {
|
||||
name: Globalize.translate("TabAlbumArtists")
|
||||
}, {
|
||||
name: Globalize.translate("TabArtists")
|
||||
}, {
|
||||
name: Globalize.translate("TabPlaylists")
|
||||
}, {
|
||||
name: Globalize.translate("TabSongs")
|
||||
}, {
|
||||
name: Globalize.translate("TabGenres")
|
||||
}, {
|
||||
name: Globalize.translate("ButtonSearch"),
|
||||
cssClass: "searchTabButton"
|
||||
}]
|
||||
}
|
||||
|
||||
function getDefaultTabIndex(folderId) {
|
||||
switch (userSettings.get("landing-" + folderId)) {
|
||||
case "albums":
|
||||
return 1;
|
||||
case "albumartists":
|
||||
return 2;
|
||||
case "artists":
|
||||
return 3;
|
||||
case "playlists":
|
||||
return 4;
|
||||
case "songs":
|
||||
return 5;
|
||||
case "genres":
|
||||
return 6;
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return function(view, params) {
|
||||
function reload() {
|
||||
loading.show();
|
||||
var tabContent = view.querySelector(".pageTabContent[data-index='0']");
|
||||
loadSuggestionsTab(view, tabContent, params.topParentId)
|
||||
}
|
||||
|
||||
function enableScrollX() {
|
||||
return browser.mobile
|
||||
}
|
||||
|
||||
function setScrollClasses(elem, scrollX) {
|
||||
scrollX ? (elem.classList.add("hiddenScrollX"), layoutManager.tv && elem.classList.add("smoothScrollX"), elem.classList.add("scrollX"), elem.classList.remove("vertical-wrap")) : (elem.classList.remove("hiddenScrollX"), elem.classList.remove("smoothScrollX"), elem.classList.remove("scrollX"), elem.classList.add("vertical-wrap"))
|
||||
}
|
||||
|
||||
function onBeforeTabChange(e) {
|
||||
preLoadTab(view, parseInt(e.detail.selectedTabIndex))
|
||||
}
|
||||
|
||||
function onTabChange(e) {
|
||||
loadTab(view, parseInt(e.detail.selectedTabIndex))
|
||||
}
|
||||
|
||||
function getTabContainers() {
|
||||
return view.querySelectorAll(".pageTabContent")
|
||||
}
|
||||
|
||||
function initTabs() {
|
||||
mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange)
|
||||
}
|
||||
|
||||
function getTabController(page, index, callback) {
|
||||
var depends = [];
|
||||
switch (index) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
depends.push("scripts/musicalbums");
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
depends.push("scripts/musicartists");
|
||||
break;
|
||||
case 4:
|
||||
depends.push("scripts/musicplaylists");
|
||||
break;
|
||||
case 5:
|
||||
depends.push("scripts/songs");
|
||||
break;
|
||||
case 6:
|
||||
depends.push("scripts/musicgenres");
|
||||
break;
|
||||
case 7:
|
||||
depends.push("scripts/searchtab")
|
||||
}
|
||||
require(depends, function(controllerFactory) {
|
||||
var tabContent;
|
||||
0 == index && (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), self.tabContent = tabContent);
|
||||
var controller = tabControllers[index];
|
||||
controller || (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), controller = 0 === index ? self : 7 === index ? new controllerFactory(view, tabContent, {
|
||||
collectionType: "music",
|
||||
parentId: params.topParentId
|
||||
}) : new controllerFactory(view, params, tabContent), 2 == index ? controller.mode = "albumartists" : 3 == index && (controller.mode = "artists"), tabControllers[index] = controller, controller.initTab && controller.initTab()), callback(controller)
|
||||
})
|
||||
}
|
||||
|
||||
function preLoadTab(page, index) {
|
||||
getTabController(page, index, function(controller) {
|
||||
-1 == renderedTabs.indexOf(index) && controller.preRender && controller.preRender()
|
||||
})
|
||||
}
|
||||
|
||||
function loadTab(page, index) {
|
||||
currentTabIndex = index, getTabController(page, index, function(controller) {
|
||||
initialTabIndex = null, -1 == renderedTabs.indexOf(index) && (renderedTabs.push(index), controller.renderTab())
|
||||
})
|
||||
}
|
||||
|
||||
function onInputCommand(e) {
|
||||
switch (e.detail.command) {
|
||||
case "search":
|
||||
e.preventDefault(), Dashboard.navigate("search.html?collectionType=music&parentId=" + params.topParentId)
|
||||
}
|
||||
}
|
||||
var isViewRestored, self = this,
|
||||
currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)),
|
||||
initialTabIndex = currentTabIndex;
|
||||
self.initTab = function() {
|
||||
for (var tabContent = view.querySelector(".pageTabContent[data-index='0']"), containers = tabContent.querySelectorAll(".itemsContainer"), i = 0, length = containers.length; i < length; i++) setScrollClasses(containers[i], enableScrollX())
|
||||
}, self.renderTab = function() {
|
||||
reload()
|
||||
};
|
||||
var tabControllers = [],
|
||||
renderedTabs = [];
|
||||
view.addEventListener("viewshow", function(e) {
|
||||
if (isViewRestored = e.detail.isRestored, initTabs(), !view.getAttribute("data-title")) {
|
||||
var parentId = params.topParentId;
|
||||
parentId ? ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function(item) {
|
||||
view.setAttribute("data-title", item.Name), libraryMenu.setTitle(item.Name)
|
||||
}) : (view.setAttribute("data-title", Globalize.translate("TabMusic")), libraryMenu.setTitle(Globalize.translate("TabMusic")))
|
||||
}
|
||||
inputManager.on(window, onInputCommand)
|
||||
}), view.addEventListener("viewbeforehide", function(e) {
|
||||
inputManager.off(window, onInputCommand)
|
||||
}), view.addEventListener("viewdestroy", function(e) {
|
||||
tabControllers.forEach(function(t) {
|
||||
t.destroy && t.destroy()
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
43
src/controllers/mypreferencescommon.js
Normal file
43
src/controllers/mypreferencescommon.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
define(["apphost", "connectionManager", "listViewStyle", "emby-linkbutton"], function(appHost, connectionManager) {
|
||||
"use strict";
|
||||
|
||||
return function(view, params) {
|
||||
view.querySelector(".btnLogout").addEventListener("click", function() {
|
||||
Dashboard.logout();
|
||||
});
|
||||
|
||||
view.addEventListener("viewshow", function() {
|
||||
var page = this;
|
||||
var userId = params.userId || Dashboard.getCurrentUserId();
|
||||
|
||||
page.querySelector(".lnkDisplayPreferences").setAttribute("href", "mypreferencesdisplay.html?userId=" + userId);
|
||||
page.querySelector(".lnkLanguagePreferences").setAttribute("href", "mypreferenceslanguages.html?userId=" + userId);
|
||||
page.querySelector(".lnkSubtitleSettings").setAttribute("href", "mypreferencessubtitles.html?userId=" + userId);
|
||||
page.querySelector(".lnkHomeScreenPreferences").setAttribute("href", "mypreferenceshome.html?userId=" + userId);
|
||||
page.querySelector(".lnkMyProfile").setAttribute("href", "myprofile.html?userId=" + userId);
|
||||
|
||||
if (appHost.supports("multiserver")) {
|
||||
page.querySelector(".selectServer").classList.remove("hide")
|
||||
} else {
|
||||
page.querySelector(".selectServer").classList.add("hide");
|
||||
}
|
||||
|
||||
connectionManager.user(ApiClient).then(function(user) {
|
||||
if (user.localUser && !user.localUser.EnableAutoLogin) {
|
||||
view.querySelector(".btnLogout").classList.remove("hide");
|
||||
} else {
|
||||
view.querySelector(".btnLogout").classList.add("hide");
|
||||
}
|
||||
});
|
||||
|
||||
Dashboard.getCurrentUser().then(function(user) {
|
||||
page.querySelector(".headerUser").innerHTML = user.Name;
|
||||
if (user.Policy.IsAdministrator) {
|
||||
page.querySelector(".adminSection").classList.remove("hide");
|
||||
} else {
|
||||
page.querySelector(".adminSection").classList.add("hide");
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
});
|
28
src/controllers/mypreferencesdisplay.js
Normal file
28
src/controllers/mypreferencesdisplay.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
define(["displaySettings", "userSettingsBuilder", "userSettings"], function(DisplaySettings, userSettingsBuilder, currentUserSettings) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
function onBeforeUnload(e) {
|
||||
hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?")
|
||||
}
|
||||
var settingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(),
|
||||
userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder;
|
||||
view.addEventListener("viewshow", function() {
|
||||
window.addEventListener("beforeunload", onBeforeUnload), settingsInstance ? settingsInstance.loadData() : settingsInstance = new DisplaySettings({
|
||||
serverId: ApiClient.serverId(),
|
||||
userId: userId,
|
||||
element: view.querySelector(".settingsContainer"),
|
||||
userSettings: userSettings,
|
||||
enableSaveButton: !1,
|
||||
enableSaveConfirmation: !1
|
||||
})
|
||||
}), view.addEventListener("change", function() {
|
||||
hasChanges = !0
|
||||
}), view.addEventListener("viewbeforehide", function() {
|
||||
window.removeEventListener("beforeunload", onBeforeUnload), hasChanges = !1, settingsInstance && settingsInstance.submit()
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
settingsInstance && (settingsInstance.destroy(), settingsInstance = null)
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
settingsInstance && (settingsInstance.destroy(), settingsInstance = null)
|
||||
})
|
||||
}
|
||||
});
|
26
src/controllers/mypreferenceshome.js
Normal file
26
src/controllers/mypreferenceshome.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
define(["homescreenSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function(HomescreenSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
function onBeforeUnload(e) {
|
||||
hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?")
|
||||
}
|
||||
var homescreenSettingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(),
|
||||
userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder;
|
||||
view.addEventListener("viewshow", function() {
|
||||
window.addEventListener("beforeunload", onBeforeUnload), homescreenSettingsInstance ? homescreenSettingsInstance.loadData() : homescreenSettingsInstance = new HomescreenSettings({
|
||||
serverId: ApiClient.serverId(),
|
||||
userId: userId,
|
||||
element: view.querySelector(".homeScreenSettingsContainer"),
|
||||
userSettings: userSettings,
|
||||
enableSaveButton: !1,
|
||||
enableSaveConfirmation: !1
|
||||
})
|
||||
}), view.addEventListener("change", function() {
|
||||
hasChanges = !0
|
||||
}), view.addEventListener("viewbeforehide", function() {
|
||||
hasChanges = !1, homescreenSettingsInstance && homescreenSettingsInstance.submit()
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
homescreenSettingsInstance && (homescreenSettingsInstance.destroy(), homescreenSettingsInstance = null)
|
||||
})
|
||||
}
|
||||
});
|
26
src/controllers/mypreferenceslanguages.js
Normal file
26
src/controllers/mypreferenceslanguages.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
define(["playbackSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function(PlaybackSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
function onBeforeUnload(e) {
|
||||
hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?")
|
||||
}
|
||||
var settingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(),
|
||||
userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder;
|
||||
view.addEventListener("viewshow", function() {
|
||||
window.addEventListener("beforeunload", onBeforeUnload), settingsInstance ? settingsInstance.loadData() : settingsInstance = new PlaybackSettings({
|
||||
serverId: ApiClient.serverId(),
|
||||
userId: userId,
|
||||
element: view.querySelector(".settingsContainer"),
|
||||
userSettings: userSettings,
|
||||
enableSaveButton: !1,
|
||||
enableSaveConfirmation: !1
|
||||
})
|
||||
}), view.addEventListener("change", function() {
|
||||
hasChanges = !0
|
||||
}), view.addEventListener("viewbeforehide", function() {
|
||||
hasChanges = !1, settingsInstance && settingsInstance.submit()
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
settingsInstance && (settingsInstance.destroy(), settingsInstance = null)
|
||||
})
|
||||
}
|
||||
});
|
26
src/controllers/mypreferencessubtitles.js
Normal file
26
src/controllers/mypreferencessubtitles.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
define(["subtitleSettings", "userSettingsBuilder", "userSettings"], function(SubtitleSettings, userSettingsBuilder, currentUserSettings) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
function onBeforeUnload(e) {
|
||||
hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?")
|
||||
}
|
||||
var subtitleSettingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(),
|
||||
userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder;
|
||||
view.addEventListener("viewshow", function() {
|
||||
window.addEventListener("beforeunload", onBeforeUnload), subtitleSettingsInstance ? subtitleSettingsInstance.loadData() : subtitleSettingsInstance = new SubtitleSettings({
|
||||
serverId: ApiClient.serverId(),
|
||||
userId: userId,
|
||||
element: view.querySelector(".settingsContainer"),
|
||||
userSettings: userSettings,
|
||||
enableSaveButton: !1,
|
||||
enableSaveConfirmation: !1
|
||||
})
|
||||
}), view.addEventListener("change", function() {
|
||||
hasChanges = !0
|
||||
}), view.addEventListener("viewbeforehide", function() {
|
||||
hasChanges = !1, subtitleSettingsInstance && subtitleSettingsInstance.submit()
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
subtitleSettingsInstance && (subtitleSettingsInstance.destroy(), subtitleSettingsInstance = null)
|
||||
})
|
||||
}
|
||||
});
|
145
src/controllers/myprofile.js
Normal file
145
src/controllers/myprofile.js
Normal file
|
@ -0,0 +1,145 @@
|
|||
define(["controllers/userpasswordpage", "loading", "libraryMenu", "apphost", "emby-linkbutton"], function (Userpasswordpage, loading, libraryMenu, appHost) {
|
||||
"use strict";
|
||||
|
||||
function reloadUser(page) {
|
||||
var userId = getParameterByName("userId");
|
||||
loading.show();
|
||||
ApiClient.getUser(userId).then(function (user) {
|
||||
page.querySelector(".username").innerHTML = user.Name;
|
||||
var uploadUserImage = page.querySelector("#uploadUserImage");
|
||||
uploadUserImage.value = "";
|
||||
uploadUserImage.dispatchEvent(new CustomEvent("change", {}));
|
||||
libraryMenu.setTitle(user.Name);
|
||||
var imageUrl = "css/images/logindefault.png";
|
||||
if (user.PrimaryImageTag) {
|
||||
imageUrl = ApiClient.getUserImageUrl(user.Id, {
|
||||
height: 200,
|
||||
tag: user.PrimaryImageTag,
|
||||
type: "Primary"
|
||||
});
|
||||
}
|
||||
var fldImage = page.querySelector("#fldImage");
|
||||
fldImage.classList.remove("hide");
|
||||
fldImage.innerHTML = "<img width='140px' src='" + imageUrl + "' />";
|
||||
Dashboard.getCurrentUser().then(function (loggedInUser) {
|
||||
if (appHost.supports("fileinput") && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess)) {
|
||||
page.querySelector(".newImageForm").classList.remove("hide");
|
||||
|
||||
if (user.PrimaryImageTag) {
|
||||
page.querySelector("#btnDeleteImage").classList.remove("hide");
|
||||
} else {
|
||||
page.querySelector("#btnDeleteImage").classList.add("hide");
|
||||
}
|
||||
} else {
|
||||
page.querySelector(".newImageForm").classList.add("hide");
|
||||
page.querySelector("#btnDeleteImage").classList.add("hide");
|
||||
}
|
||||
});
|
||||
loading.hide();
|
||||
});
|
||||
}
|
||||
|
||||
function onFileReaderError(evt) {
|
||||
loading.hide();
|
||||
switch (evt.target.error.code) {
|
||||
case evt.target.error.NOT_FOUND_ERR:
|
||||
require(["toast"], function (toast) {
|
||||
toast(Globalize.translate("FileNotFound"));
|
||||
});
|
||||
break;
|
||||
case evt.target.error.NOT_READABLE_ERR:
|
||||
require(["toast"], function (toast) {
|
||||
toast(Globalize.translate("FileReadError"));
|
||||
});
|
||||
break;
|
||||
case evt.target.error.ABORT_ERR:
|
||||
break;
|
||||
default:
|
||||
require(["toast"], function (toast) {
|
||||
toast(Globalize.translate("FileReadError"));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function onFileReaderAbort(evt) {
|
||||
loading.hide();
|
||||
|
||||
require(["toast"], function (toast) {
|
||||
toast(Globalize.translate("FileReadCancelled"));
|
||||
});
|
||||
}
|
||||
|
||||
function setFiles(page, files) {
|
||||
var file = files[0];
|
||||
|
||||
if (!file || !file.type.match("image.*")) {
|
||||
page.querySelector("#userImageOutput").innerHTML = "";
|
||||
page.querySelector("#fldUpload").classList.add("hide");
|
||||
return void (currentFile = null);
|
||||
}
|
||||
|
||||
currentFile = file;
|
||||
var reader = new FileReader();
|
||||
reader.onerror = onFileReaderError;
|
||||
|
||||
reader.onloadstart = function () {
|
||||
page.querySelector("#fldUpload").classList.add("hide");
|
||||
};
|
||||
|
||||
reader.onabort = onFileReaderAbort;
|
||||
|
||||
reader.onload = function (evt) {
|
||||
var html = ['<img style="max-width:100%;max-height:100%;" src="', evt.target.result, '" title="', escape(file.name), '"/>'].join("");
|
||||
page.querySelector("#userImageOutput").innerHTML = html;
|
||||
page.querySelector("#fldUpload").classList.remove("hide");
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
function onImageDragOver(evt) {
|
||||
evt.preventDefault();
|
||||
evt.originalEvent.dataTransfer.dropEffect = "Copy";
|
||||
return false;
|
||||
}
|
||||
|
||||
var currentFile;
|
||||
return function (view, params) {
|
||||
reloadUser(view);
|
||||
new Userpasswordpage(view, params);
|
||||
view.querySelector("#userImageDropZone").addEventListener("dragOver", onImageDragOver);
|
||||
view.querySelector("#btnDeleteImage").addEventListener("click", function () {
|
||||
require(["confirm"], function (confirm) {
|
||||
confirm(Globalize.translate("DeleteImageConfirmation"), Globalize.translate("DeleteImage")).then(function () {
|
||||
loading.show();
|
||||
var userId = getParameterByName("userId");
|
||||
ApiClient.deleteUserImage(userId, "primary").then(function () {
|
||||
loading.hide();
|
||||
reloadUser(view);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
view.querySelector(".btnBrowse").addEventListener("click", function () {
|
||||
view.querySelector("#uploadUserImage").click();
|
||||
});
|
||||
view.querySelector(".newImageForm").addEventListener("submit", function (evt) {
|
||||
var file = currentFile;
|
||||
if (!file || "image/png" != file.type && "image/jpeg" != file.type && "image/jpeg" != file.type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
loading.show();
|
||||
var userId = getParameterByName("userId");
|
||||
ApiClient.uploadUserImage(userId, "Primary", file).then(function () {
|
||||
loading.hide();
|
||||
reloadUser(view);
|
||||
});
|
||||
evt.preventDefault();
|
||||
return false;
|
||||
});
|
||||
view.querySelector("#uploadUserImage").addEventListener("change", function (evt) {
|
||||
setFiles(view, evt.target.files);
|
||||
});
|
||||
};
|
||||
});
|
60
src/controllers/notificationsettings.js
Normal file
60
src/controllers/notificationsettings.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
define(["loading", "libraryMenu", "globalize", "listViewStyle", "emby-linkbutton"], function(loading, libraryMenu, globalize) {
|
||||
"use strict";
|
||||
|
||||
function reload(page) {
|
||||
loading.show();
|
||||
ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")).then(function(list) {
|
||||
var html = "";
|
||||
var lastCategory = "";
|
||||
var showHelp = true;
|
||||
html += list.map(function(notification) {
|
||||
var itemHtml = "";
|
||||
if (notification.Category !== lastCategory) {
|
||||
lastCategory = notification.Category;
|
||||
if (lastCategory) {
|
||||
itemHtml += "</div>";
|
||||
itemHtml += "</div>";
|
||||
}
|
||||
itemHtml += '<div class="verticalSection verticalSection-extrabottompadding">';
|
||||
itemHtml += '<div class="sectionTitleContainer" style="margin-bottom:1em;">';
|
||||
itemHtml += '<h2 class="sectionTitle">';
|
||||
itemHtml += notification.Category;
|
||||
itemHtml += "</h2>";
|
||||
if (showHelp) {
|
||||
showHelp = false;
|
||||
itemHtml += '<a is="emby-linkbutton" class="raised button-alt headerHelpButton" target="_blank" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Notifications">';
|
||||
itemHtml += globalize.translate("Help");
|
||||
itemHtml += "</a>";
|
||||
}
|
||||
itemHtml += "</div>";
|
||||
itemHtml += '<div class="paperList">';
|
||||
}
|
||||
itemHtml += '<a class="listItem listItem-border" is="emby-linkbutton" data-ripple="false" href="notificationsetting.html?type=' + notification.Type + '">';
|
||||
if (notification.Enabled) {
|
||||
itemHtml += '<i class="listItemIcon md-icon">notifications_active</i>';
|
||||
} else {
|
||||
itemHtml += '<i class="listItemIcon md-icon" style="background-color:#999;">notifications_off</i>';
|
||||
}
|
||||
itemHtml += '<div class="listItemBody">';
|
||||
itemHtml += '<div class="listItemBodyText">' + notification.Name + "</div>";
|
||||
itemHtml += "</div>";
|
||||
itemHtml += '<button type="button" is="paper-icon-button-light"><i class="md-icon">mode_edit</i></button>';
|
||||
itemHtml += "</a>";
|
||||
return itemHtml;
|
||||
}).join("");
|
||||
|
||||
if (list.length) {
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
}
|
||||
page.querySelector(".notificationList").innerHTML = html;
|
||||
loading.hide();
|
||||
})
|
||||
}
|
||||
|
||||
return function(view, params) {
|
||||
view.addEventListener("viewshow", function() {
|
||||
reload(view);
|
||||
});
|
||||
}
|
||||
});
|
11
src/controllers/nowplayingpage.js
Normal file
11
src/controllers/nowplayingpage.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
define(["components/remotecontrol", "libraryMenu", "emby-button"], function(remotecontrolFactory, libraryMenu) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
var remoteControl = new remotecontrolFactory;
|
||||
remoteControl.init(view, view.querySelector(".remoteControlContent")), view.addEventListener("viewshow", function(e) {
|
||||
libraryMenu.setTransparentMenu(!0), remoteControl && remoteControl.onShow()
|
||||
}), view.addEventListener("viewbeforehide", function(e) {
|
||||
libraryMenu.setTransparentMenu(!1), remoteControl && remoteControl.destroy()
|
||||
})
|
||||
}
|
||||
});
|
176
src/controllers/plugincatalogpage.js
Normal file
176
src/controllers/plugincatalogpage.js
Normal file
|
@ -0,0 +1,176 @@
|
|||
define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", "emby-checkbox", "emby-select"], function (loading, libraryMenu, globalize) {
|
||||
"use strict";
|
||||
|
||||
function reloadList(page) {
|
||||
loading.show();
|
||||
var promise1 = ApiClient.getAvailablePlugins(query);
|
||||
var promise2 = ApiClient.getInstalledPlugins();
|
||||
Promise.all([promise1, promise2]).then(function (responses) {
|
||||
populateList({
|
||||
catalogElement: page.querySelector("#pluginTiles"),
|
||||
noItemsElement: page.querySelector("#noPlugins"),
|
||||
availablePlugins: responses[0],
|
||||
installedPlugins: responses[1]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getHeaderText(category) {
|
||||
category = category.replace(" ", "");
|
||||
if ("Channel" === category) {
|
||||
category = "Channels";
|
||||
} else if ("Theme" === category) {
|
||||
category = "Themes";
|
||||
} else if ("LiveTV" === category) {
|
||||
category = "HeaderLiveTV";
|
||||
} else if ("ScreenSaver" === category) {
|
||||
category = "HeaderScreenSavers";
|
||||
}
|
||||
|
||||
return globalize.translate(category);
|
||||
}
|
||||
|
||||
function populateList(options) {
|
||||
var availablePlugins = options.availablePlugins;
|
||||
var installedPlugins = options.installedPlugins;
|
||||
var allPlugins = availablePlugins.filter(function (plugin) {
|
||||
plugin.category = plugin.category || "General";
|
||||
plugin.categoryDisplayName = getHeaderText(plugin.category);
|
||||
|
||||
if (!options.categories || -1 != options.categories.indexOf(plugin.category)) {
|
||||
if (!options.targetSystem || plugin.targetSystem == options.targetSystem) {
|
||||
return "UserInstalled" == plugin.type;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
availablePlugins = allPlugins.sort(function (a, b) {
|
||||
if (a.category > b.category) {
|
||||
return 1;
|
||||
} else if (b.category > a.category) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name > b.name) {
|
||||
return 1;
|
||||
} else if (b.name > a.name) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
var length;
|
||||
var plugin;
|
||||
var currentCategory;
|
||||
var html = "";
|
||||
|
||||
var hasOpenTag = false;
|
||||
currentCategory = null;
|
||||
if (options.showCategory === false) {
|
||||
html += '<div class="itemsContainer vertical-wrap">';
|
||||
hasOpenTag = true;
|
||||
}
|
||||
for (var i = 0; i < availablePlugins.length; i++) {
|
||||
plugin = availablePlugins[i];
|
||||
var category = plugin.categoryDisplayName;
|
||||
|
||||
if (category != currentCategory) {
|
||||
if (false !== options.showCategory) {
|
||||
if (currentCategory) {
|
||||
hasOpenTag = false;
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
}
|
||||
html += '<div class="verticalSection">';
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + category + "</h2>";
|
||||
html += '<div class="itemsContainer vertical-wrap">';
|
||||
hasOpenTag = true;
|
||||
}
|
||||
currentCategory = category;
|
||||
}
|
||||
html += getPluginHtml(plugin, options, installedPlugins);
|
||||
}
|
||||
|
||||
if (hasOpenTag) {
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
}
|
||||
|
||||
if (!availablePlugins.length && options.noItemsElement) {
|
||||
options.noItemsElement.classList.add("hide");
|
||||
}
|
||||
|
||||
options.catalogElement.innerHTML = html;
|
||||
loading.hide();
|
||||
}
|
||||
|
||||
function getPluginHtml(plugin, options, installedPlugins) {
|
||||
var html = "";
|
||||
var href = plugin.externalUrl ? plugin.externalUrl : "addplugin.html?name=" + encodeURIComponent(plugin.name) + "&guid=" + plugin.guid;
|
||||
|
||||
if (options.context) {
|
||||
href += "&context=" + options.context;
|
||||
}
|
||||
|
||||
var target = plugin.externalUrl ? ' target="_blank"' : "";
|
||||
html += "<div class='card backdropCard'>";
|
||||
html += '<div class="cardBox visualCardBox">';
|
||||
html += '<div class="cardScalable visualCardBox-cardScalable">';
|
||||
html += '<div class="cardPadder cardPadder-backdrop"></div>';
|
||||
html += '<a class="cardContent cardImageContainer" is="emby-linkbutton" href="' + href + '"' + target + ">";
|
||||
|
||||
if (plugin.thumbImage) {
|
||||
html += '<div class="cardImage coveredImage" style="background-image:url(\'' + plugin.thumbImage + "');\">";
|
||||
html += "</div>";
|
||||
} else {
|
||||
html += '<i class="cardImageIcon md-icon"></i>';
|
||||
}
|
||||
|
||||
html += "</a>";
|
||||
html += "</div>";
|
||||
html += '<div class="cardFooter">';
|
||||
html += "<div class='cardText'>";
|
||||
html += plugin.name;
|
||||
html += "</div>";
|
||||
var installedPlugin = plugin.isApp ? null : installedPlugins.filter(function (ip) {
|
||||
return ip.Id == plugin.guid;
|
||||
})[0];
|
||||
html += "<div class='cardText cardText-secondary'>";
|
||||
html += installedPlugin ? globalize.translate("LabelVersionInstalled").replace("{0}", installedPlugin.Version) : " ";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
return html += "</div>";
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "plugins.html",
|
||||
name: globalize.translate("TabMyPlugins")
|
||||
}, {
|
||||
href: "plugincatalog.html",
|
||||
name: globalize.translate("TabCatalog")
|
||||
}];
|
||||
}
|
||||
|
||||
var query = {
|
||||
TargetSystems: "Server",
|
||||
IsAppStoreSafe: true,
|
||||
IsAdult: false
|
||||
};
|
||||
|
||||
window.PluginCatalog = {
|
||||
renderCatalog: populateList
|
||||
};
|
||||
|
||||
return function (view, params) {
|
||||
view.querySelector("#selectSystem").addEventListener("change", function () {
|
||||
query.TargetSystems = this.value;
|
||||
reloadList(view);
|
||||
});
|
||||
view.addEventListener("viewshow", function () {
|
||||
libraryMenu.setTabs("plugins", 1, getTabs);
|
||||
reloadList(this);
|
||||
});
|
||||
};
|
||||
});
|
111
src/controllers/scheduledtaskpage.js
Normal file
111
src/controllers/scheduledtaskpage.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby-button", "emby-select"], function($, loading, datetime, dom, globalize) {
|
||||
"use strict";
|
||||
|
||||
function fillTimeOfDay(select) {
|
||||
for (var options = [], i = 0; i < 864e5; i += 9e5) options.push({
|
||||
name: ScheduledTaskPage.getDisplayTime(1e4 * i),
|
||||
value: 1e4 * i
|
||||
});
|
||||
select.innerHTML = options.map(function(o) {
|
||||
return '<option value="' + o.value + '">' + o.name + "</option>"
|
||||
}).join("")
|
||||
}
|
||||
Array.prototype.remove = function(from, to) {
|
||||
var rest = this.slice((to || from) + 1 || this.length);
|
||||
return this.length = from < 0 ? this.length + from : from, this.push.apply(this, rest)
|
||||
};
|
||||
var ScheduledTaskPage = {
|
||||
refreshScheduledTask: function(view) {
|
||||
loading.show();
|
||||
var id = getParameterByName("id");
|
||||
ApiClient.getScheduledTask(id).then(function(task) {
|
||||
ScheduledTaskPage.loadScheduledTask(view, task)
|
||||
})
|
||||
},
|
||||
loadScheduledTask: function(view, task) {
|
||||
$(".taskName", view).html(task.Name), $("#pTaskDescription", view).html(task.Description), require(["listViewStyle"], function() {
|
||||
ScheduledTaskPage.loadTaskTriggers(view, task)
|
||||
}), loading.hide()
|
||||
},
|
||||
loadTaskTriggers: function(context, task) {
|
||||
var html = "";
|
||||
html += '<div class="paperList">';
|
||||
for (var i = 0, length = task.Triggers.length; i < length; i++) {
|
||||
var trigger = task.Triggers[i];
|
||||
if (html += '<div class="listItem listItem-border">', html += '<i class="md-icon listItemIcon">schedule</i>', trigger.MaxRuntimeTicks ? html += '<div class="listItemBody two-line">' : html += '<div class="listItemBody">', html += "<div class='listItemBodyText'>" + ScheduledTaskPage.getTriggerFriendlyName(trigger) + "</div>", trigger.MaxRuntimeTicks) {
|
||||
html += '<div class="listItemBodyText secondary">';
|
||||
var hours = trigger.MaxRuntimeTicks / 36e9;
|
||||
html += 1 == hours ? globalize.translate("ValueTimeLimitSingleHour") : globalize.translate("ValueTimeLimitMultiHour", hours), html += "</div>"
|
||||
}
|
||||
html += "</div>", html += '<button class="btnDeleteTrigger" data-index="' + i + '" type="button" is="paper-icon-button-light" title="' + globalize.translate("ButtonDelete") + '"><i class="md-icon">delete</i></button>', html += "</div>"
|
||||
}
|
||||
html += "</div>", context.querySelector(".taskTriggers").innerHTML = html
|
||||
},
|
||||
getTriggerFriendlyName: function(trigger) {
|
||||
if ("DailyTrigger" == trigger.Type) return "Daily at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks);
|
||||
if ("WeeklyTrigger" == trigger.Type) return trigger.DayOfWeek + "s at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks);
|
||||
if ("SystemEventTrigger" == trigger.Type && "WakeFromSleep" == trigger.SystemEvent) return "On wake from sleep";
|
||||
if ("IntervalTrigger" == trigger.Type) {
|
||||
var hours = trigger.IntervalTicks / 36e9;
|
||||
return .25 == hours ? "Every 15 minutes" : .5 == hours ? "Every 30 minutes" : .75 == hours ? "Every 45 minutes" : 1 == hours ? "Every hour" : "Every " + hours + " hours"
|
||||
}
|
||||
return "StartupTrigger" == trigger.Type ? "On application startup" : trigger.Type
|
||||
},
|
||||
getDisplayTime: function(ticks) {
|
||||
var ms = ticks / 1e4,
|
||||
now = new Date;
|
||||
return now.setHours(0, 0, 0, 0), now.setTime(now.getTime() + ms), datetime.getDisplayTime(now)
|
||||
},
|
||||
showAddTriggerPopup: function(view) {
|
||||
$("#selectTriggerType", view).val("DailyTrigger"), view.querySelector("#selectTriggerType").dispatchEvent(new CustomEvent("change", {})), $("#popupAddTrigger", view).removeClass("hide")
|
||||
},
|
||||
confirmDeleteTrigger: function(view, index) {
|
||||
require(["confirm"], function(confirm) {
|
||||
confirm(globalize.translate("MessageDeleteTaskTrigger"), globalize.translate("HeaderDeleteTaskTrigger")).then(function() {
|
||||
ScheduledTaskPage.deleteTrigger(view, index)
|
||||
})
|
||||
})
|
||||
},
|
||||
deleteTrigger: function(view, index) {
|
||||
loading.show();
|
||||
var id = getParameterByName("id");
|
||||
ApiClient.getScheduledTask(id).then(function(task) {
|
||||
task.Triggers.remove(index), ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function() {
|
||||
ScheduledTaskPage.refreshScheduledTask(view)
|
||||
})
|
||||
})
|
||||
},
|
||||
refreshTriggerFields: function(page, triggerType) {
|
||||
"DailyTrigger" == triggerType ? ($("#fldTimeOfDay", page).show(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).attr("required", "required")) : "WeeklyTrigger" == triggerType ? ($("#fldTimeOfDay", page).show(), $("#fldDayOfWeek", page).show(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).attr("required", "required")) : "SystemEventTrigger" == triggerType ? ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).show(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).removeAttr("required")) : "IntervalTrigger" == triggerType ? ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).show(), $("#selectTimeOfDay", page).removeAttr("required")) : "StartupTrigger" == triggerType && ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).removeAttr("required"))
|
||||
},
|
||||
getTriggerToAdd: function(page) {
|
||||
var trigger = {
|
||||
Type: $("#selectTriggerType", page).val()
|
||||
};
|
||||
"DailyTrigger" == trigger.Type ? trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val() : "WeeklyTrigger" == trigger.Type ? (trigger.DayOfWeek = $("#selectDayOfWeek", page).val(), trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val()) : "SystemEventTrigger" == trigger.Type ? trigger.SystemEvent = $("#selectSystemEvent", page).val() : "IntervalTrigger" == trigger.Type && (trigger.IntervalTicks = $("#selectInterval", page).val());
|
||||
var timeLimit = $("#txtTimeLimit", page).val() || "0";
|
||||
return timeLimit = 36e5 * parseFloat(timeLimit), trigger.MaxRuntimeMs = timeLimit || null, trigger
|
||||
}
|
||||
};
|
||||
return function(view, params) {
|
||||
function onSubmit(e) {
|
||||
loading.show();
|
||||
var id = getParameterByName("id");
|
||||
ApiClient.getScheduledTask(id).then(function(task) {
|
||||
task.Triggers.push(ScheduledTaskPage.getTriggerToAdd(view)), ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function() {
|
||||
$("#popupAddTrigger").addClass("hide"), ScheduledTaskPage.refreshScheduledTask(view)
|
||||
})
|
||||
}), e.preventDefault()
|
||||
}
|
||||
view.querySelector(".addTriggerForm").addEventListener("submit", onSubmit), fillTimeOfDay(view.querySelector("#selectTimeOfDay")), $(view.querySelector("#popupAddTrigger").parentNode).trigger("create"), view.querySelector(".selectTriggerType").addEventListener("change", function() {
|
||||
ScheduledTaskPage.refreshTriggerFields(view, this.value)
|
||||
}), view.querySelector(".btnAddTrigger").addEventListener("click", function() {
|
||||
ScheduledTaskPage.showAddTriggerPopup(view)
|
||||
}), view.addEventListener("click", function(e) {
|
||||
var btnDeleteTrigger = dom.parentWithClass(e.target, "btnDeleteTrigger");
|
||||
btnDeleteTrigger && ScheduledTaskPage.confirmDeleteTrigger(view, parseInt(btnDeleteTrigger.getAttribute("data-index")))
|
||||
}), view.addEventListener("viewshow", function() {
|
||||
ScheduledTaskPage.refreshScheduledTask(view)
|
||||
})
|
||||
}
|
||||
});
|
99
src/controllers/scheduledtaskspage.js
Normal file
99
src/controllers/scheduledtaskspage.js
Normal file
|
@ -0,0 +1,99 @@
|
|||
define(["jQuery", "loading", "events", "globalize", "serverNotifications", "humanedate", "listViewStyle", "emby-linkbutton"], function($, loading, events, globalize, serverNotifications) {
|
||||
"use strict";
|
||||
|
||||
function reloadList(page) {
|
||||
ApiClient.getScheduledTasks({
|
||||
isHidden: !1
|
||||
}).then(function(tasks) {
|
||||
populateList(page, tasks), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function populateList(page, tasks) {
|
||||
tasks = tasks.sort(function(a, b) {
|
||||
return a = a.Category + " " + a.Name, b = b.Category + " " + b.Name, a == b ? 0 : a < b ? -1 : 1
|
||||
});
|
||||
for (var currentCategory, html = "", i = 0, length = tasks.length; i < length; i++) {
|
||||
var task = tasks[i];
|
||||
task.Category != currentCategory && (currentCategory = task.Category, currentCategory && (html += "</div>", html += "</div>"), html += '<div class="verticalSection verticalSection-extrabottompadding">', html += '<div class="sectionTitleContainer" style="margin-bottom:1em;">', html += '<h2 class="sectionTitle">', html += currentCategory, html += "</h2>", 0 === i && (html += '<a is="emby-linkbutton" class="raised button-alt headerHelpButton" target="_blank" href="https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Scheduled-tasks">' + globalize.translate("Help") + "</a>"), html += "</div>", html += '<div class="paperList">'), html += '<div class="listItem listItem-border scheduledTaskPaperIconItem" data-status="' + task.State + '">', html += "<a is='emby-linkbutton' style='margin:0;padding:0;' class='clearLink listItemIconContainer' href='scheduledtask.html?id=" + task.Id + "'>", html += '<i class="md-icon listItemIcon">schedule</i>', html += "</a>", html += '<div class="listItemBody two-line">', html += "<a class='clearLink' style='margin:0;padding:0;display:block;text-align:left;' is='emby-linkbutton' href='scheduledtask.html?id=" + task.Id + "'>", html += "<h3 class='listItemBodyText'>" + task.Name + "</h3>", html += "<div class='secondary listItemBodyText' id='taskProgress" + task.Id + "'>" + getTaskProgressHtml(task) + "</div>", html += "</a>", html += "</div>", "Idle" == task.State ? html += '<button type="button" is="paper-icon-button-light" id="btnTask' + task.Id + '" class="btnStartTask" data-taskid="' + task.Id + '" title="' + globalize.translate("ButtonStart") + '"><i class="md-icon">play_arrow</i></button>' : "Running" == task.State ? html += '<button type="button" is="paper-icon-button-light" id="btnTask' + task.Id + '" class="btnStopTask" data-taskid="' + task.Id + '" title="' + globalize.translate("ButtonStop") + '"><i class="md-icon">stop</i></button>' : html += '<button type="button" is="paper-icon-button-light" id="btnTask' + task.Id + '" class="btnStartTask hide" data-taskid="' + task.Id + '" title="' + globalize.translate("ButtonStart") + '"><i class="md-icon">play_arrow</i></button>', html += "</div>"
|
||||
}
|
||||
tasks.length && (html += "</div>", html += "</div>"), page.querySelector(".divScheduledTasks").innerHTML = html
|
||||
}
|
||||
|
||||
function humane_elapsed(firstDateStr, secondDateStr) {
|
||||
var dt1 = new Date(firstDateStr),
|
||||
dt2 = new Date(secondDateStr),
|
||||
seconds = (dt2.getTime() - dt1.getTime()) / 1e3,
|
||||
numdays = Math.floor(seconds % 31536e3 / 86400),
|
||||
numhours = Math.floor(seconds % 31536e3 % 86400 / 3600),
|
||||
numminutes = Math.floor(seconds % 31536e3 % 86400 % 3600 / 60),
|
||||
numseconds = Math.round(seconds % 31536e3 % 86400 % 3600 % 60),
|
||||
elapsedStr = "";
|
||||
return elapsedStr += 1 == numdays ? numdays + " day " : "", elapsedStr += numdays > 1 ? numdays + " days " : "", elapsedStr += 1 == numhours ? numhours + " hour " : "", elapsedStr += numhours > 1 ? numhours + " hours " : "", elapsedStr += 1 == numminutes ? numminutes + " minute " : "", elapsedStr += numminutes > 1 ? numminutes + " minutes " : "", elapsedStr += elapsedStr.length > 0 ? "and " : "", elapsedStr += 1 == numseconds ? numseconds + " second" : "", elapsedStr += 0 == numseconds || numseconds > 1 ? numseconds + " seconds" : ""
|
||||
}
|
||||
|
||||
function getTaskProgressHtml(task) {
|
||||
var html = "";
|
||||
if ("Idle" == task.State) task.LastExecutionResult && (html += globalize.translate("LabelScheduledTaskLastRan").replace("{0}", humane_date(task.LastExecutionResult.EndTimeUtc)).replace("{1}", humane_elapsed(task.LastExecutionResult.StartTimeUtc, task.LastExecutionResult.EndTimeUtc)), "Failed" == task.LastExecutionResult.Status ? html += " <span style='color:#FF0000;'>(" + globalize.translate("LabelFailed") + ")</span>" : "Cancelled" == task.LastExecutionResult.Status ? html += " <span style='color:#0026FF;'>(" + globalize.translate("LabelCancelled") + ")</span>" : "Aborted" == task.LastExecutionResult.Status && (html += " <span style='color:#FF0000;'>" + globalize.translate("LabelAbortedByServerShutdown") + "</span>"));
|
||||
else if ("Running" == task.State) {
|
||||
var progress = (task.CurrentProgressPercentage || 0).toFixed(1);
|
||||
html += '<div style="display:flex;align-items:center;">';
|
||||
html += '<div class="taskProgressOuter" title="' + progress + '%" style="flex-grow:1;">';
|
||||
html += '<div class="taskProgressInner" style="width:' + progress + '%;">';
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += "<span style='color:#00a4dc;margin-left:5px;'>" + progress + "%</span>";
|
||||
html += "</div>";
|
||||
} else {
|
||||
html += "<span style='color:#FF0000;'>" + globalize.translate("LabelStopping") + "</span>";
|
||||
}
|
||||
return html
|
||||
}
|
||||
|
||||
function updateTaskButton(elem, state) {
|
||||
"Idle" == state ? (elem.classList.add("btnStartTask"), elem.classList.remove("btnStopTask"), elem.classList.remove("hide"), elem.querySelector("i").innerHTML = "play_arrow", elem.title = globalize.translate("ButtonStart")) : "Running" == state ? (elem.classList.remove("btnStartTask"), elem.classList.add("btnStopTask"), elem.classList.remove("hide"), elem.querySelector("i").innerHTML = "stop", elem.title = globalize.translate("ButtonStop")) : (elem.classList.add("btnStartTask"), elem.classList.remove("btnStopTask"), elem.classList.add("hide"), elem.querySelector("i").innerHTML = "play_arrow", elem.title = globalize.translate("ButtonStart")), $(elem).parents(".listItem")[0].setAttribute("data-status", state)
|
||||
}
|
||||
return function(view, params) {
|
||||
function updateTasks(tasks) {
|
||||
for (var i = 0, length = tasks.length; i < length; i++) {
|
||||
var task = tasks[i];
|
||||
view.querySelector("#taskProgress" + task.Id).innerHTML = getTaskProgressHtml(task);
|
||||
updateTaskButton(view.querySelector("#btnTask" + task.Id), task.State)
|
||||
}
|
||||
}
|
||||
|
||||
function onPollIntervalFired() {
|
||||
ApiClient.isMessageChannelOpen() || reloadList(view)
|
||||
}
|
||||
|
||||
function onScheduledTasksUpdate(e, apiClient, info) {
|
||||
apiClient.serverId() === serverId && updateTasks(info)
|
||||
}
|
||||
|
||||
function startInterval() {
|
||||
ApiClient.sendMessage("ScheduledTasksInfoStart", "1000,1000"), pollInterval && clearInterval(pollInterval), pollInterval = setInterval(onPollIntervalFired, 1e4)
|
||||
}
|
||||
|
||||
function stopInterval() {
|
||||
ApiClient.sendMessage("ScheduledTasksInfoStop"), pollInterval && clearInterval(pollInterval)
|
||||
}
|
||||
var pollInterval, serverId = ApiClient.serverId();
|
||||
$(".divScheduledTasks", view).on("click", ".btnStartTask", function() {
|
||||
var button = this,
|
||||
id = button.getAttribute("data-taskid");
|
||||
ApiClient.startScheduledTask(id).then(function() {
|
||||
updateTaskButton(button, "Running"), reloadList(view)
|
||||
})
|
||||
}).on("click", ".btnStopTask", function() {
|
||||
var button = this,
|
||||
id = button.getAttribute("data-taskid");
|
||||
ApiClient.stopScheduledTask(id).then(function() {
|
||||
updateTaskButton(button, ""), reloadList(view)
|
||||
})
|
||||
}), view.addEventListener("viewbeforehide", function() {
|
||||
events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate), stopInterval()
|
||||
}), view.addEventListener("viewshow", function() {
|
||||
loading.show(), startInterval(), reloadList(view), events.on(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate)
|
||||
})
|
||||
}
|
||||
});
|
21
src/controllers/searchpage.js
Normal file
21
src/controllers/searchpage.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
define(["focusManager", "searchFields", "searchResults", "events"], function(focusManager, SearchFields, SearchResults, events) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
function onSearch(e, value) {
|
||||
self.searchResults.search(value)
|
||||
}
|
||||
var self = this;
|
||||
view.addEventListener("viewshow", function() {
|
||||
self.searchFields || (self.searchFields = new SearchFields({
|
||||
element: view.querySelector(".searchFields")
|
||||
}), self.searchResults = new SearchResults({
|
||||
element: view.querySelector(".searchResults"),
|
||||
serverId: params.serverId || ApiClient.serverId(),
|
||||
parentId: params.parentId,
|
||||
collectionType: params.collectionType
|
||||
}), events.on(self.searchFields, "search", onSearch))
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
self.searchFields && (self.searchFields.destroy(), self.searchFields = null), self.searchResults && (self.searchResults.destroy(), self.searchResults = null)
|
||||
})
|
||||
}
|
||||
});
|
140
src/controllers/selectserver.js
Normal file
140
src/controllers/selectserver.js
Normal file
|
@ -0,0 +1,140 @@
|
|||
define(["loading", "appRouter", "layoutManager", "appSettings", "apphost", "focusManager", "connectionManager", "backdrop", "globalize", "staticBackdrops", "actionsheet", "dom", "material-icons", "flexStyles", "emby-scroller", "emby-itemscontainer", "cardStyle", "emby-button"], function(loading, appRouter, layoutManager, appSettings, appHost, focusManager, connectionManager, backdrop, globalize, staticBackdrops, actionSheet, dom) {
|
||||
"use strict";
|
||||
|
||||
function renderSelectServerItems(view, servers) {
|
||||
var items = servers.map(function(server) {
|
||||
return {
|
||||
name: server.Name,
|
||||
showIcon: !0,
|
||||
icon: "",
|
||||
cardType: "",
|
||||
id: server.Id,
|
||||
server: server
|
||||
}
|
||||
}),
|
||||
html = items.map(function(item) {
|
||||
var cardImageContainer;
|
||||
cardImageContainer = item.showIcon ? '<i class="cardImageIcon md-icon">' + item.icon + "</i>" : '<div class="cardImage" style="' + item.cardImageStyle + '"></div>';
|
||||
var cardBoxCssClass = "cardBox";
|
||||
layoutManager.tv && (cardBoxCssClass += " cardBox-focustransform");
|
||||
var innerOpening = '<div class="' + cardBoxCssClass + '">';
|
||||
return '<button raised class="card overflowSquareCard loginSquareCard scalableCard overflowSquareCard-scalable" style="display:inline-block;" data-id="' + item.id + '" data-url="' + (item.url || "") + '" data-cardtype="' + item.cardType + '">' + innerOpening + '<div class="cardScalable card-focuscontent"><div class="cardPadder cardPadder-square"></div><div class="cardContent"><div class="cardImageContainer coveredImage" style="background:#0288D1;border-radius:.15em;">' + cardImageContainer + '</div></div></div><div class="cardFooter"><div class="cardText cardTextCentered">' + item.name + "</div></div></div></button>"
|
||||
}).join(""),
|
||||
itemsContainer = view.querySelector(".servers");
|
||||
items.length || (html = "<p>" + globalize.translate("MessageNoServersAvailableToConnect") + "</p>"), itemsContainer.innerHTML = html, loading.hide()
|
||||
}
|
||||
|
||||
function updatePageStyle(view, params) {
|
||||
"1" == params.showuser ? (view.classList.add("libraryPage"), view.classList.remove("standalonePage"), view.classList.add("noSecondaryNavPage")) : (view.classList.add("standalonePage"), view.classList.remove("libraryPage"), view.classList.remove("noSecondaryNavPage"))
|
||||
}
|
||||
|
||||
function showGeneralError() {
|
||||
loading.hide(), alertText(globalize.translate("DefaultErrorMessage"))
|
||||
}
|
||||
|
||||
function alertText(text) {
|
||||
alertTextWithOptions({
|
||||
text: text
|
||||
})
|
||||
}
|
||||
|
||||
function alertTextWithOptions(options) {
|
||||
require(["alert"], function(alert) {
|
||||
alert(options)
|
||||
})
|
||||
}
|
||||
|
||||
function showServerConnectionFailure() {
|
||||
alertText(globalize.translate("MessageUnableToConnectToServer"), globalize.translate("HeaderConnectionFailure"))
|
||||
}
|
||||
|
||||
return function(view, params) {
|
||||
function connectToServer(server) {
|
||||
loading.show(), connectionManager.connectToServer(server, {
|
||||
enableAutoLogin: appSettings.enableAutoLogin()
|
||||
}).then(function(result) {
|
||||
loading.hide();
|
||||
var apiClient = result.ApiClient;
|
||||
switch (result.State) {
|
||||
case "SignedIn":
|
||||
Dashboard.onServerChanged(apiClient.getCurrentUserId(), apiClient.accessToken(), apiClient), Dashboard.navigate("home.html");
|
||||
break;
|
||||
case "ServerSignIn":
|
||||
Dashboard.onServerChanged(null, null, apiClient), Dashboard.navigate("login.html?serverid=" + result.Servers[0].Id);
|
||||
break;
|
||||
case "ServerUpdateNeeded":
|
||||
alertTextWithOptions({
|
||||
text: globalize.translate("core#ServerUpdateNeeded", "https://github.com/jellyfin/jellyfin"),
|
||||
html: globalize.translate("core#ServerUpdateNeeded", '<a href="https://github.com/jellyfin/jellyfin">https://github.com/jellyfin/jellyfin</a>')
|
||||
});
|
||||
break;
|
||||
default:
|
||||
showServerConnectionFailure()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function deleteServer(server) {
|
||||
loading.show(), connectionManager.deleteServer(server.Id).then(function() {
|
||||
loading.hide(), loadServers()
|
||||
}, function() {
|
||||
loading.hide(), loadServers()
|
||||
})
|
||||
}
|
||||
|
||||
function onServerClick(server) {
|
||||
var menuItems = [];
|
||||
menuItems.push({
|
||||
name: globalize.translate("Connect"),
|
||||
id: "connect"
|
||||
}), menuItems.push({
|
||||
name: globalize.translate("Delete"),
|
||||
id: "delete"
|
||||
});
|
||||
actionSheet.show({
|
||||
items: menuItems,
|
||||
title: server.Name
|
||||
}).then(function(id) {
|
||||
switch (id) {
|
||||
case "connect":
|
||||
connectToServer(server);
|
||||
break;
|
||||
case "delete":
|
||||
deleteServer(server);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function onServersRetrieved(result) {
|
||||
servers = result, renderSelectServerItems(view, result), layoutManager.tv && focusManager.autoFocus(view)
|
||||
}
|
||||
|
||||
function loadServers() {
|
||||
loading.show(), connectionManager.getAvailableServers().then(onServersRetrieved, function(result) {
|
||||
onServersRetrieved([])
|
||||
})
|
||||
}
|
||||
var servers;
|
||||
layoutManager.desktop;
|
||||
updatePageStyle(view, params);
|
||||
var backdropUrl = staticBackdrops.getRandomImageUrl();
|
||||
view.addEventListener("viewshow", function(e) {
|
||||
var isRestored = e.detail.isRestored;
|
||||
appRouter.setTitle(null);
|
||||
backdrop.setBackdrop(backdropUrl);
|
||||
if (!isRestored) loadServers();
|
||||
}), view.querySelector(".servers").addEventListener("click", function(e) {
|
||||
var card = dom.parentWithClass(e.target, "card");
|
||||
if (card) {
|
||||
var url = card.getAttribute("data-url");
|
||||
if (url) appRouter.show(url);
|
||||
else {
|
||||
var id = card.getAttribute("data-id");
|
||||
onServerClick(servers.filter(function(s) {
|
||||
return s.Id === id
|
||||
})[0])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
14
src/controllers/serveractivity.js
Normal file
14
src/controllers/serveractivity.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
define(["components/activitylog", "globalize"], function(ActivityLog, globalize) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
var activityLog;
|
||||
"false" !== params.useractivity ? (view.querySelector(".activityItems").setAttribute("data-useractivity", "true"), view.querySelector(".sectionTitle").innerHTML = globalize.translate("HeaderActivity")) : (view.querySelector(".activityItems").setAttribute("data-useractivity", "false"), view.querySelector(".sectionTitle").innerHTML = globalize.translate("Alerts")), view.addEventListener("viewshow", function() {
|
||||
activityLog || (activityLog = new ActivityLog({
|
||||
serverId: ApiClient.serverId(),
|
||||
element: view.querySelector(".activityItems")
|
||||
}))
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
activityLog && activityLog.destroy(), activityLog = null
|
||||
})
|
||||
}
|
||||
});
|
229
src/controllers/tvrecommended.js
Normal file
229
src/controllers/tvrecommended.js
Normal file
|
@ -0,0 +1,229 @@
|
|||
define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "dom", "userSettings", "cardBuilder", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-button"], function(events, inputManager, libraryMenu, layoutManager, loading, dom, userSettings, cardBuilder, playbackManager, mainTabsManager) {
|
||||
"use strict";
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
name: Globalize.translate("TabShows")
|
||||
}, {
|
||||
name: Globalize.translate("TabSuggestions")
|
||||
}, {
|
||||
name: Globalize.translate("TabLatest")
|
||||
}, {
|
||||
name: Globalize.translate("TabUpcoming")
|
||||
}, {
|
||||
name: Globalize.translate("TabGenres")
|
||||
}, {
|
||||
name: Globalize.translate("TabNetworks")
|
||||
}, {
|
||||
name: Globalize.translate("TabEpisodes")
|
||||
}, {
|
||||
name: Globalize.translate("ButtonSearch"),
|
||||
cssClass: "searchTabButton"
|
||||
}]
|
||||
}
|
||||
|
||||
function getDefaultTabIndex(folderId) {
|
||||
switch (userSettings.get("landing-" + folderId)) {
|
||||
case "suggestions":
|
||||
return 1;
|
||||
case "latest":
|
||||
return 2;
|
||||
case "favorites":
|
||||
return 1;
|
||||
case "genres":
|
||||
return 4;
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
function setScrollClasses(elem, scrollX) {
|
||||
scrollX ? (elem.classList.add("hiddenScrollX"), layoutManager.tv && elem.classList.add("smoothScrollX"), elem.classList.add("scrollX"), elem.classList.remove("vertical-wrap")) : (elem.classList.remove("hiddenScrollX"), elem.classList.remove("smoothScrollX"), elem.classList.remove("scrollX"), elem.classList.add("vertical-wrap"))
|
||||
}
|
||||
return function(view, params) {
|
||||
function reload() {
|
||||
loading.show(), loadResume(), loadNextUp()
|
||||
}
|
||||
|
||||
function loadNextUp() {
|
||||
var query = {
|
||||
Limit: 24,
|
||||
Fields: "PrimaryImageAspectRatio,SeriesInfo,DateCreated,BasicSyncInfo",
|
||||
UserId: ApiClient.getCurrentUserId(),
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Thumb",
|
||||
EnableTotalRecordCount: !1
|
||||
};
|
||||
query.ParentId = libraryMenu.getTopParentId(), ApiClient.getNextUpEpisodes(query).then(function(result) {
|
||||
result.Items.length ? view.querySelector(".noNextUpItems").classList.add("hide") : view.querySelector(".noNextUpItems").classList.remove("hide");
|
||||
var container = view.querySelector("#nextUpItems");
|
||||
cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: container,
|
||||
preferThumb: !0,
|
||||
shape: "backdrop",
|
||||
scalable: !0,
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
overlayText: !1,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0,
|
||||
cardLayout: !1
|
||||
}), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop
|
||||
}
|
||||
|
||||
function getThumbShape() {
|
||||
return enableScrollX() ? "overflowBackdrop" : "backdrop"
|
||||
}
|
||||
|
||||
function loadResume() {
|
||||
var parentId = libraryMenu.getTopParentId(),
|
||||
screenWidth = dom.getWindowSize().innerWidth,
|
||||
limit = screenWidth >= 1600 ? 5 : 6,
|
||||
options = {
|
||||
SortBy: "DatePlayed",
|
||||
SortOrder: "Descending",
|
||||
IncludeItemTypes: "Episode",
|
||||
Filters: "IsResumable",
|
||||
Limit: limit,
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,SeriesInfo,UserData,BasicSyncInfo",
|
||||
ExcludeLocationTypes: "Virtual",
|
||||
ParentId: parentId,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Thumb",
|
||||
EnableTotalRecordCount: !1
|
||||
};
|
||||
ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) {
|
||||
result.Items.length ? view.querySelector("#resumableSection").classList.remove("hide") : view.querySelector("#resumableSection").classList.add("hide");
|
||||
var allowBottomPadding = !enableScrollX(),
|
||||
container = view.querySelector("#resumableItems");
|
||||
cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: container,
|
||||
preferThumb: !0,
|
||||
shape: getThumbShape(),
|
||||
scalable: !0,
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
overlayText: !1,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0,
|
||||
allowBottomPadding: allowBottomPadding,
|
||||
cardLayout: !1
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onBeforeTabChange(e) {
|
||||
preLoadTab(view, parseInt(e.detail.selectedTabIndex))
|
||||
}
|
||||
|
||||
function onTabChange(e) {
|
||||
var newIndex = parseInt(e.detail.selectedTabIndex);
|
||||
loadTab(view, newIndex)
|
||||
}
|
||||
|
||||
function getTabContainers() {
|
||||
return view.querySelectorAll(".pageTabContent")
|
||||
}
|
||||
|
||||
function initTabs() {
|
||||
mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange)
|
||||
}
|
||||
|
||||
function getTabController(page, index, callback) {
|
||||
var depends = [];
|
||||
switch (index) {
|
||||
case 0:
|
||||
depends.push("scripts/tvshows");
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
depends.push("scripts/tvlatest");
|
||||
break;
|
||||
case 3:
|
||||
depends.push("scripts/tvupcoming");
|
||||
break;
|
||||
case 4:
|
||||
depends.push("scripts/tvgenres");
|
||||
break;
|
||||
case 5:
|
||||
depends.push("scripts/tvstudios");
|
||||
break;
|
||||
case 6:
|
||||
depends.push("scripts/episodes");
|
||||
break;
|
||||
case 7:
|
||||
depends.push("scripts/searchtab")
|
||||
}
|
||||
require(depends, function(controllerFactory) {
|
||||
var tabContent;
|
||||
1 === index && (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), self.tabContent = tabContent);
|
||||
var controller = tabControllers[index];
|
||||
controller || (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), controller = 1 === index ? self : 7 === index ? new controllerFactory(view, tabContent, {
|
||||
collectionType: "tvshows",
|
||||
parentId: params.topParentId
|
||||
}) : new controllerFactory(view, params, tabContent), tabControllers[index] = controller, controller.initTab && controller.initTab()), callback(controller)
|
||||
})
|
||||
}
|
||||
|
||||
function preLoadTab(page, index) {
|
||||
getTabController(page, index, function(controller) {
|
||||
-1 == renderedTabs.indexOf(index) && controller.preRender && controller.preRender()
|
||||
})
|
||||
}
|
||||
|
||||
function loadTab(page, index) {
|
||||
currentTabIndex = index, getTabController(page, index, function(controller) {
|
||||
initialTabIndex = null, -1 == renderedTabs.indexOf(index) && (renderedTabs.push(index), controller.renderTab())
|
||||
})
|
||||
}
|
||||
|
||||
function onPlaybackStop(e, state) {
|
||||
state.NowPlayingItem && "Video" == state.NowPlayingItem.MediaType && (renderedTabs = [], mainTabsManager.getTabsElement().triggerTabChange())
|
||||
}
|
||||
|
||||
function onWebSocketMessage(e, data) {
|
||||
var msg = data;
|
||||
"UserDataChanged" === msg.MessageType && msg.Data.UserId == ApiClient.getCurrentUserId() && (renderedTabs = [])
|
||||
}
|
||||
|
||||
function onInputCommand(e) {
|
||||
switch (e.detail.command) {
|
||||
case "search":
|
||||
e.preventDefault(), Dashboard.navigate("search.html?collectionType=tv&parentId=" + params.topParentId)
|
||||
}
|
||||
}
|
||||
var isViewRestored, self = this,
|
||||
currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)),
|
||||
initialTabIndex = currentTabIndex;
|
||||
self.initTab = function() {
|
||||
var tabContent = self.tabContent;
|
||||
setScrollClasses(tabContent.querySelector("#resumableItems"), enableScrollX());
|
||||
}, self.renderTab = function() {
|
||||
reload()
|
||||
};
|
||||
var tabControllers = [],
|
||||
renderedTabs = [];
|
||||
setScrollClasses(view.querySelector("#resumableItems"), enableScrollX()), view.addEventListener("viewshow", function(e) {
|
||||
if (isViewRestored = e.detail.isRestored, initTabs(), !view.getAttribute("data-title")) {
|
||||
var parentId = params.topParentId;
|
||||
parentId ? ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function(item) {
|
||||
view.setAttribute("data-title", item.Name), libraryMenu.setTitle(item.Name)
|
||||
}) : (view.setAttribute("data-title", Globalize.translate("TabShows")), libraryMenu.setTitle(Globalize.translate("TabShows")))
|
||||
}
|
||||
events.on(playbackManager, "playbackstop", onPlaybackStop), events.on(ApiClient, "message", onWebSocketMessage), inputManager.on(window, onInputCommand)
|
||||
}), view.addEventListener("viewbeforehide", function(e) {
|
||||
inputManager.off(window, onInputCommand), events.off(playbackManager, "playbackstop", onPlaybackStop), events.off(ApiClient, "message", onWebSocketMessage)
|
||||
}), view.addEventListener("viewdestroy", function(e) {
|
||||
tabControllers.forEach(function(t) {
|
||||
t.destroy && t.destroy()
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
101
src/controllers/userpasswordpage.js
Normal file
101
src/controllers/userpasswordpage.js
Normal file
|
@ -0,0 +1,101 @@
|
|||
define(["loading", "libraryMenu", "emby-linkbutton"], function(loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function loadUser(page, params) {
|
||||
var userid = params.userId;
|
||||
ApiClient.getUser(userid).then(function(user) {
|
||||
Dashboard.getCurrentUser().then(function(loggedInUser) {
|
||||
libraryMenu.setTitle(user.Name), page.querySelector(".username").innerHTML = user.Name;
|
||||
var showPasswordSection = !0,
|
||||
showLocalAccessSection = !1;
|
||||
"Guest" == user.ConnectLinkType ? (page.querySelector(".localAccessSection").classList.add("hide"), showPasswordSection = !1) : user.HasConfiguredPassword ? (page.querySelector("#btnResetPassword").classList.remove("hide"), page.querySelector("#fldCurrentPassword").classList.remove("hide"), showLocalAccessSection = !0) : (page.querySelector("#btnResetPassword").classList.add("hide"), page.querySelector("#fldCurrentPassword").classList.add("hide")), showPasswordSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess) ? page.querySelector(".passwordSection").classList.remove("hide") : page.querySelector(".passwordSection").classList.add("hide"), showLocalAccessSection && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess) ? page.querySelector(".localAccessSection").classList.remove("hide") : page.querySelector(".localAccessSection").classList.add("hide");
|
||||
var txtEasyPassword = page.querySelector("#txtEasyPassword");
|
||||
txtEasyPassword.value = "", user.HasConfiguredEasyPassword ? (txtEasyPassword.placeholder = "******", page.querySelector("#btnResetEasyPassword").classList.remove("hide")) : (txtEasyPassword.removeAttribute("placeholder"), txtEasyPassword.placeholder = "", page.querySelector("#btnResetEasyPassword").classList.add("hide")), page.querySelector(".chkEnableLocalEasyPassword").checked = user.Configuration.EnableLocalPassword
|
||||
})
|
||||
}), page.querySelector("#txtCurrentPassword").value = "", page.querySelector("#txtNewPassword").value = "", page.querySelector("#txtNewPasswordConfirm").value = ""
|
||||
}
|
||||
return function(view, params) {
|
||||
function saveEasyPassword() {
|
||||
var userId = params.userId,
|
||||
easyPassword = view.querySelector("#txtEasyPassword").value;
|
||||
easyPassword ? ApiClient.updateEasyPassword(userId, easyPassword).then(function() {
|
||||
onEasyPasswordSaved(userId)
|
||||
}) : onEasyPasswordSaved(userId)
|
||||
}
|
||||
|
||||
function onEasyPasswordSaved(userId) {
|
||||
ApiClient.getUser(userId).then(function(user) {
|
||||
user.Configuration.EnableLocalPassword = view.querySelector(".chkEnableLocalEasyPassword").checked, ApiClient.updateUserConfiguration(user.Id, user.Configuration).then(function() {
|
||||
loading.hide(), require(["toast"], function(toast) {
|
||||
toast(Globalize.translate("MessageSettingsSaved"))
|
||||
}), loadUser(view, params)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function savePassword() {
|
||||
var userId = params.userId,
|
||||
currentPassword = view.querySelector("#txtCurrentPassword").value,
|
||||
newPassword = view.querySelector("#txtNewPassword").value;
|
||||
if (view.querySelector("#fldCurrentPassword").classList.contains("hide")) {
|
||||
// Firefox does not respect autocomplete=off, so clear it if the field is supposed to be hidden (and blank)
|
||||
// This should only happen when user.HasConfiguredPassword is false, but this information is not passed on
|
||||
currentPassword = "";
|
||||
}
|
||||
ApiClient.updateUserPassword(userId, currentPassword, newPassword).then(function() {
|
||||
loading.hide(), require(["toast"], function(toast) {
|
||||
toast(Globalize.translate("PasswordSaved"))
|
||||
}), loadUser(view, params)
|
||||
}, function() {
|
||||
loading.hide(), Dashboard.alert({
|
||||
title: Globalize.translate("HeaderLoginFailure"),
|
||||
message: Globalize.translate("MessageInvalidUser")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
var form = this;
|
||||
return form.querySelector("#txtNewPassword").value != form.querySelector("#txtNewPasswordConfirm").value ? require(["toast"], function(toast) {
|
||||
toast(Globalize.translate("PasswordMatchError"))
|
||||
}) : (loading.show(), savePassword()), e.preventDefault(), !1
|
||||
}
|
||||
|
||||
function onLocalAccessSubmit(e) {
|
||||
return loading.show(), saveEasyPassword(), e.preventDefault(), !1
|
||||
}
|
||||
|
||||
function resetPassword() {
|
||||
var msg = Globalize.translate("PasswordResetConfirmation");
|
||||
require(["confirm"], function(confirm) {
|
||||
confirm(msg, Globalize.translate("PasswordResetHeader")).then(function() {
|
||||
var userId = params.userId;
|
||||
loading.show(), ApiClient.resetUserPassword(userId).then(function() {
|
||||
loading.hide(), Dashboard.alert({
|
||||
message: Globalize.translate("PasswordResetComplete"),
|
||||
title: Globalize.translate("PasswordResetHeader")
|
||||
}), loadUser(view, params)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function resetEasyPassword() {
|
||||
var msg = Globalize.translate("PinCodeResetConfirmation");
|
||||
require(["confirm"], function(confirm) {
|
||||
confirm(msg, Globalize.translate("HeaderPinCodeReset")).then(function() {
|
||||
var userId = params.userId;
|
||||
loading.show(), ApiClient.resetEasyPassword(userId).then(function() {
|
||||
loading.hide(), Dashboard.alert({
|
||||
message: Globalize.translate("PinCodeResetComplete"),
|
||||
title: Globalize.translate("HeaderPinCodeReset")
|
||||
}), loadUser(view, params)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
view.querySelector(".updatePasswordForm").addEventListener("submit", onSubmit), view.querySelector(".localAccessForm").addEventListener("submit", onLocalAccessSubmit), view.querySelector("#btnResetEasyPassword").addEventListener("click", resetEasyPassword), view.querySelector("#btnResetPassword").addEventListener("click", resetPassword), view.addEventListener("viewshow", function() {
|
||||
loadUser(view, params)
|
||||
})
|
||||
}
|
||||
});
|
1355
src/controllers/videoosd.js
Normal file
1355
src/controllers/videoosd.js
Normal file
File diff suppressed because it is too large
Load diff
19
src/controllers/wizardfinishpage.js
Normal file
19
src/controllers/wizardfinishpage.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
define(["loading"], function(loading) {
|
||||
"use strict";
|
||||
|
||||
function onFinish() {
|
||||
loading.show(), ApiClient.ajax({
|
||||
url: ApiClient.getUrl("Startup/Complete"),
|
||||
type: "POST"
|
||||
}).then(function() {
|
||||
Dashboard.navigate_direct("/dashboard.html"), loading.hide()
|
||||
})
|
||||
}
|
||||
return function(view, params) {
|
||||
view.querySelector(".btnWizardNext").addEventListener("click", onFinish), view.addEventListener("viewshow", function() {
|
||||
document.querySelector(".skinHeader").classList.add("noHomeButtonHeader")
|
||||
}), view.addEventListener("viewhide", function() {
|
||||
document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader")
|
||||
})
|
||||
}
|
||||
});
|
31
src/controllers/wizardremoteaccess.js
Normal file
31
src/controllers/wizardremoteaccess.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
define(["loading", "emby-checkbox", "emby-button", "emby-select"], function(loading) {
|
||||
"use strict";
|
||||
|
||||
function save(page) {
|
||||
loading.show();
|
||||
var apiClient = ApiClient,
|
||||
config = {};
|
||||
config.EnableRemoteAccess = page.querySelector("#chkRemoteAccess").checked, config.EnableAutomaticPortMapping = page.querySelector("#chkEnableUpnp").checked, apiClient.ajax({
|
||||
type: "POST",
|
||||
data: config,
|
||||
url: apiClient.getUrl("Startup/RemoteAccess")
|
||||
}).then(function() {
|
||||
loading.hide(), navigateToNextPage()
|
||||
})
|
||||
}
|
||||
|
||||
function navigateToNextPage() {
|
||||
Dashboard.navigate("wizardfinish.html")
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
return save(this), e.preventDefault(), !1
|
||||
}
|
||||
return function(view, params) {
|
||||
view.querySelector(".wizardSettingsForm").addEventListener("submit", onSubmit), view.addEventListener("viewshow", function() {
|
||||
document.querySelector(".skinHeader").classList.add("noHomeButtonHeader")
|
||||
}), view.addEventListener("viewhide", function() {
|
||||
document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader")
|
||||
})
|
||||
}
|
||||
});
|
67
src/controllers/wizardsettings.js
Normal file
67
src/controllers/wizardsettings.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
define(["loading", "emby-checkbox", "emby-button", "emby-select"], function(loading) {
|
||||
"use strict";
|
||||
|
||||
function save(page) {
|
||||
loading.show();
|
||||
var apiClient = ApiClient;
|
||||
apiClient.getJSON(apiClient.getUrl("Startup/Configuration")).then(function(config) {
|
||||
config.PreferredMetadataLanguage = page.querySelector("#selectLanguage").value, config.MetadataCountryCode = page.querySelector("#selectCountry").value, apiClient.ajax({
|
||||
type: "POST",
|
||||
data: config,
|
||||
url: apiClient.getUrl("Startup/Configuration")
|
||||
}).then(function() {
|
||||
loading.hide(), navigateToNextPage()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function populateLanguages(select, languages) {
|
||||
var html = "";
|
||||
html += "<option value=''></option>";
|
||||
for (var i = 0, length = languages.length; i < length; i++) {
|
||||
var culture = languages[i];
|
||||
html += "<option value='" + culture.TwoLetterISOLanguageName + "'>" + culture.DisplayName + "</option>"
|
||||
}
|
||||
select.innerHTML = html
|
||||
}
|
||||
|
||||
function populateCountries(select, allCountries) {
|
||||
var html = "";
|
||||
html += "<option value=''></option>";
|
||||
for (var i = 0, length = allCountries.length; i < length; i++) {
|
||||
var culture = allCountries[i];
|
||||
html += "<option value='" + culture.TwoLetterISORegionName + "'>" + culture.DisplayName + "</option>"
|
||||
}
|
||||
select.innerHTML = html
|
||||
}
|
||||
|
||||
function reloadData(page, config, cultures, countries) {
|
||||
populateLanguages(page.querySelector("#selectLanguage"), cultures), populateCountries(page.querySelector("#selectCountry"), countries), page.querySelector("#selectLanguage").value = config.PreferredMetadataLanguage, page.querySelector("#selectCountry").value = config.MetadataCountryCode, loading.hide()
|
||||
}
|
||||
|
||||
function reload(page) {
|
||||
loading.show();
|
||||
var apiClient = ApiClient,
|
||||
promise1 = apiClient.getJSON(apiClient.getUrl("Startup/Configuration")),
|
||||
promise2 = apiClient.getCultures(),
|
||||
promise3 = apiClient.getCountries();
|
||||
Promise.all([promise1, promise2, promise3]).then(function(responses) {
|
||||
reloadData(page, responses[0], responses[1], responses[2])
|
||||
})
|
||||
}
|
||||
|
||||
function navigateToNextPage() {
|
||||
Dashboard.navigate("wizardremoteaccess.html")
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
return save(this), e.preventDefault(), !1
|
||||
}
|
||||
return function(view, params) {
|
||||
view.querySelector(".wizardSettingsForm").addEventListener("submit", onSubmit), view.addEventListener("viewshow", function() {
|
||||
document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"), reload(this)
|
||||
}), view.addEventListener("viewhide", function() {
|
||||
document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader")
|
||||
})
|
||||
}
|
||||
});
|
41
src/controllers/wizardstart.js
Normal file
41
src/controllers/wizardstart.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
define(["jQuery", "loading", "emby-button", "emby-select"], function($, loading) {
|
||||
"use strict";
|
||||
|
||||
function loadPage(page, config, languageOptions) {
|
||||
$("#selectLocalizationLanguage", page).html(languageOptions.map(function(l) {
|
||||
return '<option value="' + l.Value + '">' + l.Name + "</option>"
|
||||
})).val(config.UICulture), loading.hide()
|
||||
}
|
||||
|
||||
function save(page) {
|
||||
loading.show();
|
||||
var apiClient = ApiClient;
|
||||
apiClient.getJSON(apiClient.getUrl("Startup/Configuration")).then(function(config) {
|
||||
config.UICulture = $("#selectLocalizationLanguage", page).val(), apiClient.ajax({
|
||||
type: "POST",
|
||||
data: config,
|
||||
url: apiClient.getUrl("Startup/Configuration")
|
||||
}).then(function() {
|
||||
Dashboard.navigate("wizarduser.html")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
return save($(this).parents(".page")), !1
|
||||
}
|
||||
return function(view, params) {
|
||||
$(".wizardStartForm", view).on("submit", onSubmit), view.addEventListener("viewshow", function() {
|
||||
document.querySelector(".skinHeader").classList.add("noHomeButtonHeader"), loading.show();
|
||||
var page = this,
|
||||
apiClient = ApiClient,
|
||||
promise1 = apiClient.getJSON(apiClient.getUrl("Startup/Configuration")),
|
||||
promise2 = apiClient.getJSON(apiClient.getUrl("Localization/Options"));
|
||||
Promise.all([promise1, promise2]).then(function(responses) {
|
||||
loadPage(page, responses[0], responses[1])
|
||||
})
|
||||
}), view.addEventListener("viewhide", function() {
|
||||
document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader")
|
||||
})
|
||||
}
|
||||
});
|
68
src/controllers/wizarduserpage.js
Normal file
68
src/controllers/wizarduserpage.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
define(["loading", "globalize", "dashboardcss", "emby-input", "emby-button", "emby-linkbutton"], function(loading, globalize) {
|
||||
"use strict";
|
||||
|
||||
function getApiClient() {
|
||||
return ApiClient
|
||||
}
|
||||
|
||||
function nextWizardPage() {
|
||||
Dashboard.navigate("wizardlibrary.html")
|
||||
}
|
||||
|
||||
function onUpdateUserComplete(result) {
|
||||
if (loading.hide(), result.UserLinkResult) {
|
||||
var msgKey = result.UserLinkResult.IsPending ? "MessagePendingEmbyAccountAdded" : "MessageEmbyAccountAdded";
|
||||
Dashboard.alert({
|
||||
message: globalize.translate(msgKey),
|
||||
title: globalize.translate("HeaderEmbyAccountAdded"),
|
||||
callback: nextWizardPage
|
||||
})
|
||||
} else nextWizardPage()
|
||||
}
|
||||
|
||||
function submit(form) {
|
||||
loading.show();
|
||||
var apiClient = getApiClient();
|
||||
apiClient.ajax({
|
||||
type: "POST",
|
||||
data: {
|
||||
Name: form.querySelector("#txtUsername").value,
|
||||
Password: form.querySelector("#txtManualPassword").value
|
||||
},
|
||||
url: apiClient.getUrl("Startup/User")
|
||||
}).then(onUpdateUserComplete, function(response) {
|
||||
console.log(response);
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
var form = this;
|
||||
if (form.querySelector("#txtManualPassword").value != form.querySelector("#txtPasswordConfirm").value) {
|
||||
require(["toast"], function(toast) {
|
||||
toast(Globalize.translate("PasswordMatchError"));
|
||||
});
|
||||
} else {
|
||||
submit(form);
|
||||
}
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
function onViewShow() {
|
||||
loading.show();
|
||||
var page = this,
|
||||
apiClient = getApiClient();
|
||||
apiClient.getJSON(apiClient.getUrl("Startup/User")).then(function(user) {
|
||||
page.querySelector("#txtUsername").value = user.Name || "";
|
||||
page.querySelector("#txtManualPassword").value = user.Password || "";
|
||||
loading.hide();
|
||||
})
|
||||
}
|
||||
return function(view, params) {
|
||||
view.querySelector(".wizardUserForm").addEventListener("submit", onSubmit), view.addEventListener("viewshow", function() {
|
||||
document.querySelector(".skinHeader").classList.add("noHomeButtonHeader")
|
||||
}), view.addEventListener("viewhide", function() {
|
||||
document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader")
|
||||
}), view.addEventListener("viewshow", onViewShow)
|
||||
}
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue