First separation commit.
Added LICENSE, README.md, CONTRIBUTORS.md
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
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 renderPluginInfo(page, pkg, pluginSecurityInfo) {
|
||||
if (!AppInfo.isNativeApp)
|
||||
if (pkg.isPremium) {
|
||||
$(".premiumPackage", page).show();
|
||||
var regStatus = "";
|
||||
if (pkg.isRegistered) regStatus += "<p style='color:green;'>", regStatus += globalize.translate("MessageFeatureIncludedWithSupporter");
|
||||
else {
|
||||
var expDateTime = new Date(pkg.expDate).getTime(),
|
||||
nowTime = (new Date).getTime();
|
||||
expDateTime <= nowTime ? (regStatus += "<p style='color:red;'>", regStatus += globalize.translate("MessageTrialExpired")) : expDateTime > new Date(1970, 1, 1).getTime() && (regStatus += "<p style='color:blue;'>", regStatus += globalize.translate("MessageTrialWillExpireIn").replace("{0}", Math.round(expDateTime - nowTime) / 864e5))
|
||||
}
|
||||
if (regStatus += "</p>", $("#regStatus", page).html(regStatus), pluginSecurityInfo.IsMBSupporter)
|
||||
if ($(".premiumDescription", page).hide(), $(".supporterDescription", page).hide(), pkg.price > 0) {
|
||||
$(".premiumHasPrice", page).show(), $("#featureId", page).val(pkg.featureId), $("#featureName", page).val(pkg.name), $("#amount", page).val(pkg.price), $("#regPrice", page).html("<h3>" + globalize.translate("ValuePriceUSD").replace("{0}", "$" + pkg.price.toFixed(2)) + "</h3>"), $("#ppButton", page).hide();
|
||||
var url = "https://mb3admin.local/admin/service/user/getPayPalEmail?id=" + pkg.owner;
|
||||
fetch(url).then(function(response) {
|
||||
return response.json()
|
||||
}).then(function(dev) {
|
||||
dev.payPalEmail && ($("#payPalEmail", page).val(dev.payPalEmail), $("#ppButton", page).show())
|
||||
})
|
||||
} else $(".premiumHasPrice", page).hide();
|
||||
else pkg.price ? ($(".premiumDescription", page).show(), $(".supporterDescription", page).hide()) : ($(".premiumDescription", page).hide(), $(".supporterDescription", page).show()), $("#ppButton", page).hide()
|
||||
} else $(".premiumPackage", page).hide()
|
||||
}
|
||||
|
||||
function renderPackage(pkg, installedPlugins, pluginSecurityInfo, page) {
|
||||
var installedPlugin = installedPlugins.filter(function(ip) {
|
||||
return ip.Name == pkg.name
|
||||
})[0];
|
||||
if (populateVersions(pkg, page, installedPlugin), populateHistory(pkg, page), $(".pluginName", page).html(pkg.name), "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) : $("#tagline", page).hide(), $("#overview", page).html(pkg.overview || ""), $("#developer", page).html(pkg.owner), renderPluginInfo(page, pkg, pluginSecurityInfo), pkg.richDescUrl ? ($("#pViewWebsite", page).show(), $("#pViewWebsite a", page).attr("href", pkg.richDescUrl)) : $("#pViewWebsite", page).hide(), 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)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
! function() {
|
||||
"use strict";
|
||||
|
||||
function loadApp() {
|
||||
var script = document.createElement("script"),
|
||||
src = "./scripts/site.js";
|
||||
self.dashboardVersion && (src += "?v=" + self.dashboardVersion), script.src = src, document.head.appendChild(script)
|
||||
}! function() {
|
||||
var src, script = document.createElement("script");
|
||||
src = self.Promise ? "./bower_components/alameda/alameda.js" : "./bower_components/requirejs/require.js", self.dashboardVersion && (src += "?v=" + self.dashboardVersion), script.src = src, script.onload = loadApp, document.head.appendChild(script)
|
||||
}()
|
||||
}();
|
||||
@@ -0,0 +1,56 @@
|
||||
define(["loading", "libraryMenu"], function(loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function reloadList(page) {
|
||||
loading.show();
|
||||
var promise1 = ApiClient.getAvailablePlugins({
|
||||
TargetSystems: "Server"
|
||||
}),
|
||||
promise2 = ApiClient.getInstalledPlugins();
|
||||
Promise.all([promise1, promise2]).then(function(responses) {
|
||||
renderInstalled(page, responses[0], responses[1]), renderCatalog(page, responses[0], responses[1])
|
||||
})
|
||||
}
|
||||
|
||||
function getCategories() {
|
||||
var context = getParameterByName("context"),
|
||||
categories = [];
|
||||
return "sync" == context ? categories.push("Sync") : "livetv" == context ? categories.push("Live TV") : "notifications" == context && categories.push("Notifications"), categories
|
||||
}
|
||||
|
||||
function renderInstalled(page, availablePlugins, installedPlugins) {
|
||||
requirejs(["scripts/pluginspage"], function() {
|
||||
var category = getCategories()[0];
|
||||
installedPlugins = installedPlugins.filter(function(i) {
|
||||
var catalogEntry = availablePlugins.filter(function(a) {
|
||||
return (a.guid || "").toLowerCase() == (i.Id || "").toLowerCase()
|
||||
})[0];
|
||||
return !!catalogEntry && catalogEntry.category == category
|
||||
}), PluginsPage.renderPlugins(page, installedPlugins)
|
||||
})
|
||||
}
|
||||
|
||||
function renderCatalog(page, availablePlugins, installedPlugins) {
|
||||
requirejs(["scripts/plugincatalogpage"], function() {
|
||||
var categories = getCategories();
|
||||
PluginCatalog.renderCatalog({
|
||||
catalogElement: page.querySelector(".catalog"),
|
||||
availablePlugins: availablePlugins,
|
||||
installedPlugins: installedPlugins,
|
||||
categories: categories,
|
||||
showCategory: !1,
|
||||
context: getParameterByName("context"),
|
||||
targetSystem: "Server"
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onPageShow() {
|
||||
var page = this,
|
||||
context = getParameterByName("context");
|
||||
"sync" == context ? (libraryMenu.setTitle(Globalize.translate("TitleSync")), page.querySelector(".headerHelpButton").setAttribute("href", "https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Sync")) : "livetv" == context ? (libraryMenu.setTitle(Globalize.translate("TitleLiveTV")), page.querySelector(".headerHelpButton").setAttribute("href", "https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Live-TV")) : "notifications" == context && (libraryMenu.setTitle(Globalize.translate("TitleNotifications")), page.querySelector(".headerHelpButton").setAttribute("href", "https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Notifications"))
|
||||
}
|
||||
pageIdOn("pagebeforeshow", "appServicesPage", onPageShow), pageIdOn("pageshow", "appServicesPage", onPageShow), pageIdOn("pageshow", "appServicesPage", function() {
|
||||
reloadList(this)
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
define(["backdrop", "userSettings", "libraryMenu"], function(backdrop, userSettings, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function enabled() {
|
||||
return userSettings.enableBackdrops()
|
||||
}
|
||||
|
||||
function getBackdropItemIds(apiClient, userId, types, parentId) {
|
||||
var key = "backdrops2_" + userId + (types || "") + (parentId || ""),
|
||||
data = cache[key];
|
||||
if (data) return console.log("Found backdrop id list in cache. Key: " + key), data = JSON.parse(data), Promise.resolve(data);
|
||||
var options = {
|
||||
SortBy: "IsFavoriteOrLiked,Random",
|
||||
Limit: 20,
|
||||
Recursive: !0,
|
||||
IncludeItemTypes: types,
|
||||
ImageTypes: "Backdrop",
|
||||
ParentId: parentId,
|
||||
EnableTotalRecordCount: !1
|
||||
};
|
||||
return apiClient.getItems(apiClient.getCurrentUserId(), options).then(function(result) {
|
||||
var images = result.Items.map(function(i) {
|
||||
return {
|
||||
Id: i.Id,
|
||||
tag: i.BackdropImageTags[0],
|
||||
ServerId: i.ServerId
|
||||
}
|
||||
});
|
||||
return cache[key] = JSON.stringify(images), images
|
||||
})
|
||||
}
|
||||
|
||||
function showBackdrop(type, parentId) {
|
||||
var apiClient = window.ApiClient;
|
||||
apiClient && getBackdropItemIds(apiClient, apiClient.getCurrentUserId(), type, parentId).then(function(images) {
|
||||
images.length ? backdrop.setBackdrops(images.map(function(i) {
|
||||
return i.BackdropImageTags = [i.tag], i
|
||||
})) : backdrop.clear()
|
||||
})
|
||||
}
|
||||
var cache = {};
|
||||
pageClassOn("pagebeforeshow", "page", function() {
|
||||
var page = this;
|
||||
if (!page.classList.contains("selfBackdropPage"))
|
||||
if (page.classList.contains("backdropPage"))
|
||||
if (enabled()) {
|
||||
var type = page.getAttribute("data-backdroptype"),
|
||||
parentId = page.classList.contains("globalBackdropPage") ? "" : libraryMenu.getTopParentId();
|
||||
showBackdrop(type, parentId)
|
||||
} else page.classList.remove("backdropPage"), backdrop.clear();
|
||||
else backdrop.clear()
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
define(["appSettings", "loading", "emby-checkbox"], function(appSettings, loading) {
|
||||
"use strict";
|
||||
|
||||
function loadForm(page, user) {
|
||||
var uploadServers = appSettings.cameraUploadServers();
|
||||
page.querySelector(".uploadServerList").innerHTML = ConnectionManager.getSavedServers().map(function(s) {
|
||||
return '<label><input type="checkbox" is="emby-checkbox"' + (-1 == uploadServers.indexOf(s.Id) ? "" : " checked") + ' class="chkUploadServer" data-id="' + s.Id + '"/><span>' + s.Name + "</span></label>"
|
||||
}).join(""), loading.hide()
|
||||
}
|
||||
|
||||
function saveUser(page) {
|
||||
for (var chkUploadServer = page.querySelectorAll(".chkUploadServer"), cameraUploadServers = [], i = 0, length = chkUploadServer.length; i < length; i++) chkUploadServer[i].checked && cameraUploadServers.push(chkUploadServer[i].getAttribute("data-id"));
|
||||
appSettings.cameraUploadServers(cameraUploadServers), window.MainActivity && MainActivity.authorizeStorage(), loading.hide()
|
||||
}
|
||||
return function(view, params) {
|
||||
view.querySelector("form").addEventListener("submit", function(e) {
|
||||
return loading.show(), saveUser(view), e.preventDefault(), !1
|
||||
}), view.addEventListener("viewshow", function() {
|
||||
var page = this;
|
||||
loading.show();
|
||||
var userId = params.userId || Dashboard.getCurrentUserId();
|
||||
ApiClient.getUser(userId).then(function(user) {
|
||||
loadForm(page, user)
|
||||
})
|
||||
}), view.addEventListener("viewbeforehide", function() {
|
||||
saveUser(this)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,168 @@
|
||||
define(["appSettings", "loading", "browser", "emby-linkbutton"], function(appSettings, loading, browser) {
|
||||
"use strict";
|
||||
|
||||
function login(page, username, password) {
|
||||
loading.show(), appSettings.enableAutoLogin(!0), ConnectionManager.loginToConnect(username, password).then(function() {
|
||||
loading.hide(), Dashboard.navigate("selectserver.html")
|
||||
}, function() {
|
||||
loading.hide(), Dashboard.alert({
|
||||
message: Globalize.translate("MessageInvalidUser"),
|
||||
title: Globalize.translate("HeaderLoginFailure")
|
||||
}), page.querySelector("#txtManualPassword").value = ""
|
||||
})
|
||||
}
|
||||
|
||||
function handleConnectionResult(page, result) {
|
||||
switch (loading.hide(), 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, !1, "none");
|
||||
break;
|
||||
case "ServerSelection":
|
||||
Dashboard.navigate("selectserver.html", !1, "none");
|
||||
break;
|
||||
case "ConnectSignIn":
|
||||
loadMode(page, "welcome");
|
||||
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 loadAppConnection(page) {
|
||||
loading.show(), ConnectionManager.connect({
|
||||
enableAutoLogin: appSettings.enableAutoLogin()
|
||||
}).then(function(result) {
|
||||
handleConnectionResult(page, result)
|
||||
})
|
||||
}
|
||||
|
||||
function loadPage(page, params) {
|
||||
var mode = params.mode || "auto";
|
||||
if ("auto" == mode) {
|
||||
if (AppInfo.isNativeApp) return void loadAppConnection(page);
|
||||
mode = "connect"
|
||||
}
|
||||
loadMode(page, mode)
|
||||
}
|
||||
|
||||
function loadMode(page, mode) {
|
||||
"welcome" == mode ? (page.querySelector(".connectLoginForm").classList.add("hide"), page.querySelector(".welcomeContainer").classList.remove("hide"), page.querySelector(".manualServerForm").classList.add("hide"), page.querySelector(".signupForm").classList.add("hide")) : "connect" == mode ? (page.querySelector(".connectLoginForm").classList.remove("hide"), page.querySelector(".welcomeContainer").classList.add("hide"), page.querySelector(".manualServerForm").classList.add("hide"), page.querySelector(".signupForm").classList.add("hide")) : "manualserver" == mode ? (page.querySelector(".manualServerForm").classList.remove("hide"), page.querySelector(".connectLoginForm").classList.add("hide"), page.querySelector(".welcomeContainer").classList.add("hide"), page.querySelector(".signupForm").classList.add("hide")) : "signup" == mode && (page.querySelector(".manualServerForm").classList.add("hide"), page.querySelector(".connectLoginForm").classList.add("hide"), page.querySelector(".welcomeContainer").classList.add("hide"), page.querySelector(".signupForm").classList.remove("hide"), initSignup(page))
|
||||
}
|
||||
|
||||
function skip() {
|
||||
Dashboard.navigate("selectserver.html")
|
||||
}
|
||||
|
||||
function requireCaptcha() {
|
||||
return !AppInfo.isNativeApp && 0 == window.location.href.toLowerCase().indexOf("https")
|
||||
}
|
||||
|
||||
function supportInAppSignup() {
|
||||
return AppInfo.isNativeApp || 0 == window.location.href.toLowerCase().indexOf("https")
|
||||
}
|
||||
|
||||
function initSignup(page) {
|
||||
supportInAppSignup() && requireCaptcha() && require(["https://www.google.com/recaptcha/api.js?render=explicit"], function() {
|
||||
setTimeout(function() {
|
||||
var recaptchaContainer = page.querySelector(".recaptchaContainer");
|
||||
greWidgetId = grecaptcha.render(recaptchaContainer, {
|
||||
sitekey: "6Le2LAgTAAAAAK06Wvttt_yUnbISTy6q3Azqp9po",
|
||||
theme: "dark"
|
||||
})
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
|
||||
function submitManualServer(page) {
|
||||
var host = page.querySelector("#txtServerHost").value,
|
||||
port = page.querySelector("#txtServerPort").value;
|
||||
port && (host += ":" + port), loading.show(), ConnectionManager.connectToAddress(host, {
|
||||
enableAutoLogin: appSettings.enableAutoLogin()
|
||||
}).then(function(result) {
|
||||
handleConnectionResult(page, result)
|
||||
}, function() {
|
||||
handleConnectionResult(page, {
|
||||
State: "Unavailable"
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function submit(page) {
|
||||
login(page, page.querySelector("#txtManualName").value, page.querySelector("#txtManualPassword").value)
|
||||
}
|
||||
var greWidgetId;
|
||||
return function(view, params) {
|
||||
function onSubmit(e) {
|
||||
return submit(view), e.preventDefault(), !1
|
||||
}
|
||||
|
||||
function onManualServerSubmit(e) {
|
||||
return submitManualServer(view), e.preventDefault(), !1
|
||||
}
|
||||
|
||||
function onSignupFormSubmit(e) {
|
||||
if (!supportInAppSignup()) return e.preventDefault(), !1;
|
||||
var page = view,
|
||||
greResponse = greWidgetId ? grecaptcha.getResponse(greWidgetId) : null;
|
||||
return ConnectionManager.signupForConnect({
|
||||
email: page.querySelector("#txtSignupEmail", page).value,
|
||||
username: page.querySelector("#txtSignupUsername", page).value,
|
||||
password: page.querySelector("#txtSignupPassword", page).value,
|
||||
passwordConfirm: page.querySelector("#txtSignupPasswordConfirm", page).value,
|
||||
grecaptcha: greResponse
|
||||
}).then(function(result) {
|
||||
var msg = result.Validated ? Globalize.translate("MessageThankYouForConnectSignUpNoValidation") : Globalize.translate("MessageThankYouForConnectSignUp");
|
||||
Dashboard.alert({
|
||||
message: msg,
|
||||
callback: function() {
|
||||
Dashboard.navigate("connectlogin.html?mode=welcome")
|
||||
}
|
||||
})
|
||||
}, function(result) {
|
||||
"passwordmatch" == result.errorCode ? Dashboard.alert({
|
||||
message: Globalize.translate("ErrorMessagePasswordNotMatchConfirm")
|
||||
}) : "USERNAME_IN_USE" == result.errorCode ? Dashboard.alert({
|
||||
message: Globalize.translate("ErrorMessageUsernameInUse")
|
||||
}) : "EMAIL_IN_USE" == result.errorCode ? Dashboard.alert({
|
||||
message: Globalize.translate("ErrorMessageEmailInUse")
|
||||
}) : Dashboard.alert({
|
||||
message: Globalize.translate("DefaultErrorMessage")
|
||||
})
|
||||
}), e.preventDefault(), !1
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
require(["appRouter"], function(appRouter) {
|
||||
appRouter.back()
|
||||
})
|
||||
}
|
||||
view.querySelector(".btnSkipConnect").addEventListener("click", skip), view.querySelector(".connectLoginForm").addEventListener("submit", onSubmit), view.querySelector(".manualServerForm").addEventListener("submit", onManualServerSubmit), view.querySelector(".signupForm").addEventListener("submit", onSignupFormSubmit), view.querySelector(".btnSignupForConnect").addEventListener("click", function(e) {
|
||||
if (supportInAppSignup()) return e.preventDefault(), e.stopPropagation(), Dashboard.navigate("connectlogin.html?mode=signup"), !1
|
||||
}), view.querySelector(".btnCancelSignup").addEventListener("click", goBack), view.querySelector(".btnCancelManualServer").addEventListener("click", goBack), view.querySelector(".btnWelcomeNext").addEventListener("click", function() {
|
||||
Dashboard.navigate("connectlogin.html?mode=connect")
|
||||
});
|
||||
var terms = view.querySelector(".terms");
|
||||
//FIXME: Link below directs to "jellyfin.media/terms" which is a non existant URL
|
||||
terms.innerHTML = Globalize.translate("LoginDisclaimer") + "<div style='margin-top:5px;'><a is='emby-linkbutton' class='button-link' href='http://jellyfin.media/terms' target='_blank'>" + Globalize.translate("TermsOfUse") + "</a></div>", AppInfo.isNativeApp ? (terms.classList.add("hide"), view.querySelector(".tvAppInfo").classList.add("hide")) : (terms.classList.remove("hide"), view.querySelector(".tvAppInfo").classList.remove("hide")), view.addEventListener("viewbeforeshow", function() {
|
||||
var page = this;
|
||||
if (page.querySelector("#txtSignupEmail").value = "", page.querySelector("#txtSignupUsername").value = "", page.querySelector("#txtSignupPassword").value = "", page.querySelector("#txtSignupPasswordConfirm").value = "", browser.safari && AppInfo.isNativeApp) page.querySelector(".embyIntroDownloadMessage").innerHTML = Globalize.translate("EmbyIntroDownloadMessageWithoutLink");
|
||||
else {
|
||||
page.querySelector(".embyIntroDownloadMessage").innerHTML = Globalize.translate("EmbyIntroDownloadMessage", '<a is="emby-linkbutton" class="button-link" href="https://github.com/jellyfin/jellyfin" target="_blank">http://jellyfin.media</a>')
|
||||
}
|
||||
}), view.addEventListener("viewshow", function() {
|
||||
loadPage(view, params)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,527 @@
|
||||
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(e) {
|
||||
return e.preventDefault(), !1
|
||||
}
|
||||
|
||||
function buttonEnabled(elem, enabled) {
|
||||
enabled ? (elem.setAttribute("disabled", ""), elem.removeAttribute("disabled")) : elem.setAttribute("disabled", "disabled")
|
||||
}
|
||||
|
||||
function onEditServerNameClick(e) {
|
||||
var page = dom.parentWithClass(this, "page");
|
||||
return 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()
|
||||
})
|
||||
})
|
||||
})
|
||||
}), e.preventDefault(), !1
|
||||
}
|
||||
|
||||
function showPlaybackInfo(btn, session) {
|
||||
require(["alert"], function(alert) {
|
||||
var showTranscodeReasons, title, text = [],
|
||||
displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session),
|
||||
isDirectStream = "DirectStream" === displayPlayMethod,
|
||||
isTranscode = "Transcode" === displayPlayMethod;
|
||||
isDirectStream ? (title = globalize.translate("sharedcomponents#DirectStreaming"), text.push(globalize.translate("sharedcomponents#DirectStreamHelp1")), text.push("<br/>"), text.push(globalize.translate("sharedcomponents#DirectStreamHelp2"))) : isTranscode && (title = globalize.translate("sharedcomponents#Transcoding"), text.push(globalize.translate("sharedcomponents#MediaIsBeingConverted")), session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length && (text.push("<br/>"), text.push(globalize.translate("sharedcomponents#LabelReasonForTranscoding")), showTranscodeReasons = !0)), showTranscodeReasons && session.TranscodingInfo.TranscodeReasons.forEach(function(t) {
|
||||
text.push(globalize.translate("sharedcomponents#" + t))
|
||||
}), 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 = [];
|
||||
return session.ServerId && session.DeviceId !== connectionManager.deviceId() && menuItems.push({
|
||||
name: globalize.translate("SendMessage"),
|
||||
id: "sendmessage"
|
||||
}), session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo.TranscodeReasons.length && menuItems.push({
|
||||
name: globalize.translate("ViewPlaybackInfo"),
|
||||
id: "transcodinginfo"
|
||||
}), actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: btn
|
||||
}).then(function(id) {
|
||||
switch (id) {
|
||||
case "sendmessage":
|
||||
showSendMessageForm(btn, session);
|
||||
break;
|
||||
case "transcodinginfo":
|
||||
showPlaybackInfo(btn, session)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onActiveDevicesClick(e) {
|
||||
var btn = dom.parentWithClass(e.target, "sessionCardButton");
|
||||
if (btn) {
|
||||
var card = dom.parentWithClass(btn, "card");
|
||||
if (card) {
|
||||
var sessionId = card.id,
|
||||
session = (DashboardPage.sessionsList || []).filter(function(s) {
|
||||
return "session" + s.Id === sessionId
|
||||
})[0];
|
||||
session && (btn.classList.contains("btnCardOptions") ? showOptionsMenu(btn, session) : btn.classList.contains("btnSessionInfo") ? showPlaybackInfo(btn, session) : btn.classList.contains("btnSessionSendMessage") ? showSendMessageForm(btn, session) : btn.classList.contains("btnSessionStop") ? connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, "Stop") : btn.classList.contains("btnSessionPlayPause") && session.PlayState && connectionManager.getApiClient(session.ServerId).sendPlayStateCommand(session.Id, "PlayPause"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function filterSessions(sessions) {
|
||||
for (var list = [], minActiveDate = (new Date).getTime() - 9e5, i = 0, length = sessions.length; i < length; i++) {
|
||||
var session = sessions[i];
|
||||
if (session.NowPlayingItem || session.UserId) {
|
||||
datetime.parseISO8601Date(session.LastActivityDate, !0).getTime() >= minActiveDate && list.push(session)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
function getPluginSecurityInfo() {
|
||||
var apiClient = window.ApiClient;
|
||||
return apiClient ? connectionManager.getRegistrationInfo("themes", apiClient, {
|
||||
viewOnly: !0
|
||||
}).then(function(result) {
|
||||
return {
|
||||
IsMBSupporter: !0
|
||||
}
|
||||
}, function() {
|
||||
return {
|
||||
IsMBSupporter: !1
|
||||
}
|
||||
}) : Promise.reject()
|
||||
}
|
||||
|
||||
function refreshActiveRecordings(view, apiClient) {
|
||||
apiClient.getLiveTvRecordings({
|
||||
UserId: Dashboard.getCurrentUserId(),
|
||||
IsInProgress: !0,
|
||||
Fields: "CanDelete,PrimaryImageAspectRatio",
|
||||
EnableTotalRecordCount: !1,
|
||||
EnableImageTypes: "Primary,Thumb,Backdrop"
|
||||
}).then(function(result) {
|
||||
var itemsContainer = view.querySelector(".activeRecordingItems");
|
||||
if (!result.Items.length) return view.querySelector(".activeRecordingsSection").classList.add("hide"), void(itemsContainer.innerHTML = "");
|
||||
view.querySelector(".activeRecordingsSection").classList.remove("hide");
|
||||
itemsContainer.innerHTML = cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "auto",
|
||||
defaultShape: "backdrop",
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
coverImage: !0,
|
||||
cardLayout: !1,
|
||||
centerText: !0,
|
||||
preferThumb: "auto",
|
||||
overlayText: !1,
|
||||
overlayMoreButton: !0,
|
||||
action: "none",
|
||||
centerPlayButton: !0
|
||||
}), imageLoader.lazyChildren(itemsContainer)
|
||||
})
|
||||
}
|
||||
|
||||
function renderHasPendingRestart(view, apiClient, hasPendingRestart) {
|
||||
}
|
||||
|
||||
function reloadSystemInfo(view, apiClient) {
|
||||
apiClient.getSystemInfo().then(function(systemInfo) {
|
||||
view.querySelector(".serverNameHeader").innerHTML = systemInfo.ServerName;
|
||||
var localizedVersion = globalize.translate("LabelVersionNumber", systemInfo.Version);
|
||||
systemInfo.SystemUpdateLevel && "Release" != systemInfo.SystemUpdateLevel && (localizedVersion += " " + globalize.translate("Option" + systemInfo.SystemUpdateLevel).toLowerCase()), systemInfo.CanSelfRestart ? view.querySelector("#btnRestartServer").classList.remove("hide") : view.querySelector("#btnRestartServer").classList.add("hide"), view.querySelector("#appVersionNumber").innerHTML = localizedVersion, systemInfo.SupportsHttps ? view.querySelector("#ports").innerHTML = globalize.translate("LabelRunningOnPorts", systemInfo.HttpServerPortNumber, systemInfo.HttpsPortNumber) : view.querySelector("#ports").innerHTML = globalize.translate("LabelRunningOnPort", systemInfo.HttpServerPortNumber), DashboardPage.renderUrls(view, systemInfo), DashboardPage.renderPendingInstallations(view, systemInfo), systemInfo.CanSelfUpdate ? (view.querySelector("#btnUpdateApplicationContainer").classList.remove("hide"), view.querySelector("#btnManualUpdateContainer").classList.add("hide")) : (view.querySelector("#btnUpdateApplicationContainer").classList.add("hide"), view.querySelector("#btnManualUpdateContainer").classList.remove("hide")), "synology" == systemInfo.PackageName ? view.querySelector("#btnManualUpdateContainer").innerHTML = globalize.translate("SynologyUpdateInstructions") : view.querySelector("#btnManualUpdateContainer").innerHTML = '<a href="https://github.com/jellyfin/jellyfin/download" target="_blank">' + globalize.translate("PleaseUpdateManually") + "</a>", DashboardPage.renderPaths(view, systemInfo), renderHasPendingRestart(view, apiClient, systemInfo.HasPendingRestart)
|
||||
})
|
||||
}
|
||||
|
||||
function renderInfo(view, sessions, forceUpdate) {
|
||||
sessions = filterSessions(sessions), renderActiveConnections(view, sessions), DashboardPage.renderPluginUpdateInfo(view, forceUpdate), 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"),
|
||||
cardElem = parentElement.querySelector(".card");
|
||||
cardElem && cardElem.classList.add("deadSession");
|
||||
for (var i = 0, length = sessions.length; i < length; i++) {
|
||||
var session = sessions[i],
|
||||
rowId = "session" + session.Id,
|
||||
elem = view.querySelector("#" + rowId);
|
||||
if (elem) DashboardPage.updateSession(elem, session);
|
||||
else {
|
||||
var nowPlayingItem = session.NowPlayingItem,
|
||||
className = "scalableCard card activeSession backdropCard backdropCard-scalable";
|
||||
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);
|
||||
imgUrl ? (html += '<div class="sessionNowPlayingContent sessionNowPlayingContent-withbackground"', html += ' data-src="' + imgUrl + '" style="display:inline-block;background-image:url(\'' + imgUrl + "');\"") : html += '<div class="sessionNowPlayingContent"', html += "></div>", html += '<div class="sessionNowPlayingInnerContent">', html += '<div class="sessionAppInfo">';
|
||||
var clientImage = DashboardPage.getClientImage(session);
|
||||
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>", session.TranscodingInfo && session.TranscodingInfo.Framerate ? html += '<div class="sessionTranscodingFramerate">' + session.TranscodingInfo.Framerate + " fps</div>" : html += '<div class="sessionTranscodingFramerate"></div>';
|
||||
var nowPlayingName = DashboardPage.getNowPlayingName(session);
|
||||
if (html += '<div class="sessionNowPlayingInfo" data-imgsrc="' + nowPlayingName.image + '">', html += nowPlayingName.html, html += "</div>", 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>';
|
||||
session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage ? html += '<progress class="transcodingProgress" min="0" max="100" value="' + session.TranscodingInfo.CompletionPercentage.toFixed(1) + '"></progress>' : 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 && 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");
|
||||
deadSessionElem && deadSessionElem.parentNode.removeChild(deadSessionElem)
|
||||
}
|
||||
|
||||
function renderRunningTasks(view, tasks) {
|
||||
var html = "";
|
||||
tasks = tasks.filter(function(t) {
|
||||
return "Idle" != t.State && !t.IsHidden
|
||||
}), tasks.length ? view.querySelector(".runningTasksContainer").classList.remove("hide") : view.querySelector(".runningTasksContainer").classList.add("hide"), tasks.filter(function(t) {
|
||||
return t.Key == DashboardPage.systemUpdateTaskKey
|
||||
}).length ? buttonEnabled(view.querySelector("#btnUpdateApplication"), !1) : buttonEnabled(view.querySelector("#btnUpdateApplication"), !0);
|
||||
for (var i = 0, length = tasks.length; i < length; i++) {
|
||||
var task = tasks[i];
|
||||
if (html += "<p>", html += task.Name + "<br/>", "Running" == task.State) {
|
||||
var progress = (task.CurrentProgressPercentage || 0).toFixed(1);
|
||||
html += '<progress max="100" value="' + progress + '" title="' + progress + '%">', html += progress + "%", html += "</progress>", html += "<span style='color:#009F00;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 "Cancelling" == task.State && (html += '<span style="color:#cc0000;">' + globalize.translate("LabelStopping") + "</span>");
|
||||
html += "</p>"
|
||||
}
|
||||
view.querySelector("#divRunningTasks").innerHTML = html
|
||||
}
|
||||
return window.DashboardPage = {
|
||||
newsStartIndex: 0,
|
||||
renderPaths: function(page, systemInfo) {
|
||||
page.querySelector("#cachePath").innerHTML = systemInfo.CachePath, page.querySelector("#logPath").innerHTML = systemInfo.LogPath, page.querySelector("#transcodingTemporaryPath").innerHTML = systemInfo.TranscodingTempPath, page.querySelector("#metadataPath").innerHTML = systemInfo.InternalMetadataPath
|
||||
},
|
||||
reloadNews: function(page) {
|
||||
var query = {
|
||||
StartIndex: DashboardPage.newsStartIndex,
|
||||
Limit: 4
|
||||
};
|
||||
},
|
||||
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 = "",
|
||||
showTranscodingInfo = !1,
|
||||
displayPlayMethod = playMethodHelper.getDisplayPlayMethod(session);
|
||||
if ("DirectStream" === displayPlayMethod ? (html += globalize.translate("sharedcomponents#DirectStreaming"), !0) : "Transcode" == displayPlayMethod ? (html += globalize.translate("sharedcomponents#Transcoding"), session.TranscodingInfo && session.TranscodingInfo.Framerate && (html += " (" + session.TranscodingInfo.Framerate + " fps)"), showTranscodingInfo = !0, !0) : "DirectPlay" == displayPlayMethod && (html += globalize.translate("sharedcomponents#DirectPlaying")), showTranscodingInfo) {
|
||||
var line = [];
|
||||
session.TranscodingInfo && (session.TranscodingInfo.Bitrate && (session.TranscodingInfo.Bitrate > 1e6 ? line.push((session.TranscodingInfo.Bitrate / 1e6).toFixed(1) + " Mbps") : line.push(Math.floor(session.TranscodingInfo.Bitrate / 1e3) + " kbps")), session.TranscodingInfo.Container && line.push(session.TranscodingInfo.Container), session.TranscodingInfo.VideoCodec && line.push(session.TranscodingInfo.VideoCodec), session.TranscodingInfo.AudioCodec && session.TranscodingInfo.AudioCodec != session.TranscodingInfo.Container && line.push(session.TranscodingInfo.AudioCodec)), line.length && (html += " - " + line.join(" "))
|
||||
}
|
||||
return html || " "
|
||||
},
|
||||
getSessionNowPlayingTime: function(session) {
|
||||
var nowPlayingItem = session.NowPlayingItem,
|
||||
html = "";
|
||||
return nowPlayingItem ? (session.PlayState.PositionTicks ? html += datetime.getDisplayRunningTime(session.PlayState.PositionTicks) : html += "--:--:--", html += " / ", nowPlayingItem && nowPlayingItem.RunTimeTicks ? html += datetime.getDisplayRunningTime(nowPlayingItem.RunTimeTicks) : html += "--:--:--", html) : html
|
||||
},
|
||||
getAppSecondaryText: function(session) {
|
||||
return session.Client + " " + session.ApplicationVersion
|
||||
},
|
||||
getNowPlayingName: function(session) {
|
||||
var imgUrl = "",
|
||||
nowPlayingItem = session.NowPlayingItem;
|
||||
if (!nowPlayingItem) return {
|
||||
html: "Last seen " + humane_date(session.LastActivityDate),
|
||||
image: imgUrl
|
||||
};
|
||||
var topText = itemHelper.getDisplayName(nowPlayingItem),
|
||||
bottomText = "";
|
||||
return nowPlayingItem.Artists && nowPlayingItem.Artists.length ? (bottomText = topText, topText = nowPlayingItem.Artists[0]) : nowPlayingItem.SeriesName || nowPlayingItem.Album ? (bottomText = topText, topText = nowPlayingItem.SeriesName || nowPlayingItem.Album) : nowPlayingItem.ProductionYear && (bottomText = nowPlayingItem.ProductionYear), nowPlayingItem.ImageTags && nowPlayingItem.ImageTags.Logo ? imgUrl = ApiClient.getScaledImageUrl(nowPlayingItem.Id, {
|
||||
tag: nowPlayingItem.ImageTags.Logo,
|
||||
maxHeight: 24,
|
||||
maxWidth: 130,
|
||||
type: "Logo"
|
||||
}) : nowPlayingItem.ParentLogoImageTag && (imgUrl = ApiClient.getScaledImageUrl(nowPlayingItem.ParentLogoItemId, {
|
||||
tag: nowPlayingItem.ParentLogoImageTag,
|
||||
maxHeight: 24,
|
||||
maxWidth: 130,
|
||||
type: "Logo"
|
||||
})), imgUrl && (topText = '<img src="' + imgUrl + '" style="max-height:24px;max-width:130px;" />'), {
|
||||
html: bottomText ? topText + "<br/>" + bottomText : topText,
|
||||
image: imgUrl
|
||||
}
|
||||
},
|
||||
getUsersHtml: function(session) {
|
||||
var html = [];
|
||||
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) {
|
||||
return session.UserId && session.UserPrimaryImageTag ? ApiClient.getUserImageUrl(session.UserId, {
|
||||
tag: session.UserPrimaryImageTag,
|
||||
height: 24,
|
||||
type: "Primary"
|
||||
}) : null
|
||||
},
|
||||
updateSession: function(row, session) {
|
||||
row.classList.remove("deadSession");
|
||||
var nowPlayingItem = session.NowPlayingItem;
|
||||
nowPlayingItem ? row.classList.add("playingSession") : row.classList.remove("playingSession"), session.ServerId && -1 !== session.SupportedCommands.indexOf("DisplayMessage") && session.DeviceId !== connectionManager.deviceId() ? row.querySelector(".btnSessionSendMessage").classList.remove("hide") : row.querySelector(".btnSessionSendMessage").classList.add("hide"), session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons && session.TranscodingInfo && session.TranscodingInfo.TranscodeReasons.length ? row.querySelector(".btnSessionInfo").classList.remove("hide") : row.querySelector(".btnSessionInfo").classList.add("hide");
|
||||
var btnSessionPlayPause = row.querySelector(".btnSessionPlayPause");
|
||||
session.ServerId && nowPlayingItem && session.SupportsRemoteControl && session.DeviceId !== connectionManager.deviceId() ? (btnSessionPlayPause.classList.remove("hide"), row.querySelector(".btnSessionStop").classList.remove("hide")) : (btnSessionPlayPause.classList.add("hide"), row.querySelector(".btnSessionStop").classList.add("hide")), session.PlayState && session.PlayState.IsPaused ? btnSessionPlayPause.querySelector("i").innerHTML = "" : 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),
|
||||
nowPlayingInfoElem = row.querySelector(".sessionNowPlayingInfo");
|
||||
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,
|
||||
value = 100 * position / nowPlayingItem.RunTimeTicks;
|
||||
playbackProgressElem.classList.remove("hide"), playbackProgressElem.value = value
|
||||
} else playbackProgressElem.classList.add("hide");
|
||||
var transcodingProgress = row.querySelector(".transcodingProgress");
|
||||
session.TranscodingInfo && session.TranscodingInfo.CompletionPercentage ? (row.classList.add("transcodingSession"), transcodingProgress.value = session.TranscodingInfo.CompletionPercentage, transcodingProgress.classList.remove("hide")) : (transcodingProgress.classList.add("hide"), row.classList.remove("transcodingSession"));
|
||||
var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem) || "",
|
||||
imgElem = row.querySelector(".sessionNowPlayingContent");
|
||||
imgUrl != imgElem.getAttribute("data-src") && (imgElem.style.backgroundImage = imgUrl ? "url('" + imgUrl + "')" : "", imgElem.setAttribute("data-src", imgUrl), imgUrl ? imgElem.classList.add("sessionNowPlayingContent-withbackground") : imgElem.classList.remove("sessionNowPlayingContent-withbackground"))
|
||||
},
|
||||
getClientImage: function(connection) {
|
||||
var iconUrl = (connection.Client.toLowerCase(), connection.DeviceName.toLowerCase(), connection.AppIconUrl);
|
||||
return iconUrl ? (-1 === iconUrl.indexOf("://") && (iconUrl = ApiClient.getUrl(iconUrl)), "<img src='" + iconUrl + "' />") : 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 || {};
|
||||
return item && imageTags.Thumb ? ApiClient.getScaledImageUrl(item.Id, {
|
||||
type: "Thumb",
|
||||
width: 275,
|
||||
tag: imageTags.Thumb
|
||||
}) : item && item.ParentThumbImageTag ? ApiClient.getScaledImageUrl(item.ParentThumbItemId, {
|
||||
type: "Thumb",
|
||||
width: 275,
|
||||
tag: item.ParentThumbImageTag
|
||||
}) : item && item.ThumbImageTag ? ApiClient.getScaledImageUrl(item.ThumbItemId, {
|
||||
type: "Thumb",
|
||||
width: 275,
|
||||
tag: item.ThumbImageTag
|
||||
}) : item && imageTags.Primary ? ApiClient.getScaledImageUrl(item.Id, {
|
||||
type: "Primary",
|
||||
width: 275,
|
||||
tag: imageTags.Primary
|
||||
}) : item && item.PrimaryImageTag ? ApiClient.getScaledImageUrl(item.PrimaryImageItemId, {
|
||||
type: "Primary",
|
||||
width: 275,
|
||||
tag: item.PrimaryImageTag
|
||||
}) : 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>",
|
||||
localUrlElem = page.querySelector(".localUrl"),
|
||||
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,
|
||||
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")
|
||||
},
|
||||
renderSupporterIcon: function(page, pluginSecurityInfo) {
|
||||
var imgUrl, text, supporterIconContainer = page.querySelector(".supporterIconContainer");
|
||||
pluginSecurityInfo.IsMBSupporter ? (supporterIconContainer.classList.remove("hide"), imgUrl = "css/images/supporter/supporterbadge.png", text = globalize.translate("MessageThankYouForSupporting"), supporterIconContainer.innerHTML = '<a is="emby-linkbutton" class="button-link imageLink supporterIcon" href="https://github.com/jellyfin/jellyfin/premiere" target="_blank" title="' + text + '"><img src="' + imgUrl + '" style="height:2em;" /></a>') : supporterIconContainer.classList.add("hide")
|
||||
},
|
||||
renderPendingInstallations: function(page, systemInfo) {
|
||||
if (!systemInfo.CompletedInstallations.length) return void page.querySelector("#collapsiblePendingInstallations").classList.add("hide");
|
||||
page.querySelector("#collapsiblePendingInstallations").classList.remove("hide");
|
||||
for (var html = "", i = 0, length = systemInfo.CompletedInstallations.length; i < length; i++) {
|
||||
var update = systemInfo.CompletedInstallations[i];
|
||||
html += "<div><strong>" + update.Name + "</strong> (" + update.Version + ")</div>"
|
||||
}
|
||||
page.querySelector("#pendingInstallations").innerHTML = html
|
||||
},
|
||||
renderPluginUpdateInfo: function(page, forceUpdate) {
|
||||
!forceUpdate && DashboardPage.lastPluginUpdateCheck && (new Date).getTime() - DashboardPage.lastPluginUpdateCheck < 18e5 || (DashboardPage.lastPluginUpdateCheck = (new Date).getTime(), ApiClient.getAvailablePluginUpdates().then(function(updates) {
|
||||
var elem = page.querySelector("#pPluginUpdates");
|
||||
if (!updates.length) return void elem.classList.add("hide");
|
||||
elem.classList.remove("hide");
|
||||
for (var html = "", i = 0, length = updates.length; i < length; i++) {
|
||||
var update = updates[i];
|
||||
html += "<p><strong>" + globalize.translate("NewVersionOfSomethingAvailable").replace("{0}", update.name) + "</strong></p>", html += '<button type="button" is="emby-button" class="raised block" onclick="DashboardPage.installPluginUpdate(this);" data-name="' + update.name + '" data-guid="' + update.guid + '" data-version="' + update.versionStr + '" data-classification="' + update.classification + '">' + globalize.translate("ButtonUpdateNow") + "</button>"
|
||||
}
|
||||
elem.innerHTML = html
|
||||
}))
|
||||
},
|
||||
installPluginUpdate: function(button) {
|
||||
buttonEnabled(button, !1);
|
||||
var name = button.getAttribute("data-name"),
|
||||
guid = button.getAttribute("data-guid"),
|
||||
version = button.getAttribute("data-version"),
|
||||
classification = button.getAttribute("data-classification");
|
||||
loading.show(), ApiClient.installPlugin(name, guid, classification, version).then(function() {
|
||||
loading.hide()
|
||||
})
|
||||
},
|
||||
updateApplication: function(btn) {
|
||||
var page = dom.parentWithClass(btn, "page");
|
||||
buttonEnabled(page.querySelector("#btnUpdateApplication"), !1), loading.show(), ApiClient.getScheduledTasks().then(function(tasks) {
|
||||
var task = tasks.filter(function(t) {
|
||||
return t.Key == DashboardPage.systemUpdateTaskKey
|
||||
})[0];
|
||||
ApiClient.startScheduledTask(task.Id).then(function() {
|
||||
pollForInfo(page, ApiClient), loading.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"), !1), buttonEnabled(page.querySelector("#btnShutdown"), !1), 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"), !1), buttonEnabled(page.querySelector("#btnShutdown"), !1), ApiClient.shutdownServer()
|
||||
})
|
||||
})
|
||||
}
|
||||
}, pageClassOn("pageshow", "type-interior", function() {
|
||||
var page = this;
|
||||
page.querySelector(".customSupporterPromotion") || getPluginSecurityInfo().then(function(pluginSecurityInfo) {
|
||||
var supporterPromotionElem = page.querySelector(".supporterPromotion");
|
||||
if (supporterPromotionElem && supporterPromotionElem.parentNode.removeChild(supporterPromotionElem), !pluginSecurityInfo.IsMBSupporter) {
|
||||
var html = '<div class="supporterPromotionContainer"><div class="supporterPromotion">';
|
||||
html += '<a is="emby-linkbutton" href="https://github.com/jellyfin/jellyfin" target="_blank" class="raised block" style="background-color:#00a4dc;color:#fff;"><div>' + globalize.translate("HeaderSupportTheTeam") + '</div><div style="font-weight:normal;margin-top:5px;">' + globalize.translate("TextEnjoyBonusFeatures") + "</div></a></div></div>", page.querySelector(".content-primary").insertAdjacentHTML("afterbegin", html)
|
||||
}
|
||||
})
|
||||
}),
|
||||
function(view, params) {
|
||||
function onRestartRequired(e, apiClient) {
|
||||
apiClient.serverId() === serverId && renderHasPendingRestart(view, apiClient, !0)
|
||||
}
|
||||
|
||||
function onServerShuttingDown(e, apiClient) {
|
||||
apiClient.serverId() === serverId && renderHasPendingRestart(view, apiClient, !0)
|
||||
}
|
||||
|
||||
function onServerRestarting(e, apiClient) {
|
||||
apiClient.serverId() === serverId && renderHasPendingRestart(view, apiClient, !0)
|
||||
}
|
||||
|
||||
function onPackageInstalling(e, apiClient) {
|
||||
apiClient.serverId() === serverId && (pollForInfo(view, apiClient, !0), reloadSystemInfo(view, apiClient))
|
||||
}
|
||||
|
||||
function onPackageInstallationCompleted(e, apiClient) {
|
||||
apiClient.serverId() === serverId && (pollForInfo(view, apiClient, !0), reloadSystemInfo(view, apiClient))
|
||||
}
|
||||
|
||||
function onSessionsUpdate(e, apiClient, info) {
|
||||
apiClient.serverId() === serverId && renderInfo(view, info)
|
||||
}
|
||||
|
||||
function onScheduledTasksUpdate(e, apiClient, info) {
|
||||
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,
|
||||
apiClient = ApiClient;
|
||||
if (apiClient) {
|
||||
loading.show(), pollForInfo(page, apiClient), DashboardPage.startInterval(apiClient), 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, DashboardPage.lastPluginUpdateCheck = null, getPluginSecurityInfo().then(function(pluginSecurityInfo) {
|
||||
DashboardPage.renderSupporterIcon(page, pluginSecurityInfo)
|
||||
}), reloadSystemInfo(page, ApiClient), page.userActivityLog || (page.userActivityLog = new ActivityLog({
|
||||
serverId: ApiClient.serverId(),
|
||||
element: page.querySelector(".userActivityItems")
|
||||
})), ApiClient.isMinServerVersion("3.4.1.25") && (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), apiClient && DashboardPage.stopInterval(apiClient)
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
var page = this,
|
||||
userActivityLog = page.userActivityLog;
|
||||
userActivityLog && userActivityLog.destroy();
|
||||
var serverActivityLog = page.serverActivityLog;
|
||||
serverActivityLog && serverActivityLog.destroy()
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,371 @@
|
||||
define(["jQuery", "loading", "fnchecked", "emby-select", "emby-button", "emby-input", "emby-checkbox", "listViewStyle", "emby-linkbutton"], function($, loading) {
|
||||
"use strict";
|
||||
|
||||
function loadProfile(page) {
|
||||
loading.show();
|
||||
var promise1 = getProfile(),
|
||||
promise2 = ApiClient.getUsers();
|
||||
Promise.all([promise1, promise2]).then(function(responses) {
|
||||
currentProfile = responses[0], renderProfile(page, currentProfile, responses[1]), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function getProfile() {
|
||||
var id = getParameterByName("id"),
|
||||
url = id ? "Dlna/Profiles/" + id : "Dlna/Profiles/Default";
|
||||
return ApiClient.getJSON(ApiClient.getUrl(url))
|
||||
}
|
||||
|
||||
function renderProfile(page, profile, users) {
|
||||
$("#txtName", page).val(profile.Name), $(".chkMediaType", page).each(function() {
|
||||
this.checked = -1 != (profile.SupportedMediaTypes || "").split(",").indexOf(this.getAttribute("data-value"))
|
||||
}), $("#chkEnableAlbumArtInDidl", page).checked(profile.EnableAlbumArtInDidl), $("#chkEnableSingleImageLimit", page).checked(profile.EnableSingleAlbumArtLimit), renderXmlDocumentAttributes(page, profile.XmlRootAttributes || []);
|
||||
var idInfo = profile.Identification || {};
|
||||
renderIdentificationHeaders(page, idInfo.Headers || []), renderSubtitleProfiles(page, profile.SubtitleProfiles || []), $("#txtInfoFriendlyName", page).val(profile.FriendlyName || ""), $("#txtInfoModelName", page).val(profile.ModelName || ""), $("#txtInfoModelNumber", page).val(profile.ModelNumber || ""), $("#txtInfoModelDescription", page).val(profile.ModelDescription || ""), $("#txtInfoModelUrl", page).val(profile.ModelUrl || ""), $("#txtInfoManufacturer", page).val(profile.Manufacturer || ""), $("#txtInfoManufacturerUrl", page).val(profile.ManufacturerUrl || ""), $("#txtInfoSerialNumber", page).val(profile.SerialNumber || ""), $("#txtIdFriendlyName", page).val(idInfo.FriendlyName || ""), $("#txtIdModelName", page).val(idInfo.ModelName || ""), $("#txtIdModelNumber", page).val(idInfo.ModelNumber || ""), $("#txtIdModelDescription", page).val(idInfo.ModelDescription || ""), $("#txtIdModelUrl", page).val(idInfo.ModelUrl || ""), $("#txtIdManufacturer", page).val(idInfo.Manufacturer || ""), $("#txtIdManufacturerUrl", page).val(idInfo.ManufacturerUrl || ""), $("#txtIdSerialNumber", page).val(idInfo.SerialNumber || ""), $("#txtIdDeviceDescription", page).val(idInfo.DeviceDescription || ""), $("#txtAlbumArtPn", page).val(profile.AlbumArtPn || ""), $("#txtAlbumArtMaxWidth", page).val(profile.MaxAlbumArtWidth || ""), $("#txtAlbumArtMaxHeight", page).val(profile.MaxAlbumArtHeight || ""), $("#txtIconMaxWidth", page).val(profile.MaxIconWidth || ""), $("#txtIconMaxHeight", page).val(profile.MaxIconHeight || ""), $("#chkIgnoreTranscodeByteRangeRequests", page).checked(profile.IgnoreTranscodeByteRangeRequests), $("#txtMaxAllowedBitrate", page).val(profile.MaxStreamingBitrate || ""), $("#txtMusicStreamingTranscodingBitrate", page).val(profile.MusicStreamingTranscodingBitrate || ""), $("#chkRequiresPlainFolders", page).checked(profile.RequiresPlainFolders), $("#chkRequiresPlainVideoItems", page).checked(profile.RequiresPlainVideoItems), $("#txtProtocolInfo", page).val(profile.ProtocolInfo || ""), $("#txtXDlnaCap", page).val(profile.XDlnaCap || ""), $("#txtXDlnaDoc", page).val(profile.XDlnaDoc || ""), $("#txtSonyAggregationFlags", page).val(profile.SonyAggregationFlags || ""), profile.DirectPlayProfiles = profile.DirectPlayProfiles || [], profile.TranscodingProfiles = profile.TranscodingProfiles || [], profile.ContainerProfiles = profile.ContainerProfiles || [], profile.CodecProfiles = profile.CodecProfiles || [], profile.ResponseProfiles = profile.ResponseProfiles || [];
|
||||
var usersHtml = "<option></option>" + users.map(function(u) {
|
||||
return '<option value="' + u.Id + '">' + u.Name + "</option>"
|
||||
}).join("");
|
||||
$("#selectUser", page).html(usersHtml).val(profile.UserId || ""), renderSubProfiles(page, profile)
|
||||
}
|
||||
|
||||
function renderIdentificationHeaders(page, headers) {
|
||||
var index = 0,
|
||||
html = '<div class="paperList">' + headers.map(function(h) {
|
||||
var li = '<div class="listItem">';
|
||||
return li += '<i class="md-icon listItemIcon">info</i>', li += '<div class="listItemBody">', li += '<h3 class="listItemBodyText">' + h.Name + ": " + (h.Value || "") + "</h3>", li += '<div class="listItemBodyText secondary">' + (h.Match || "") + "</div>", li += "</div>", li += '<button type="button" is="paper-icon-button-light" class="btnDeleteIdentificationHeader listItemButton" data-index="' + index + '"><i class="md-icon">delete</i></button>', li += "</div>", index++, li
|
||||
}).join("") + "</div>",
|
||||
elem = $(".httpHeaderIdentificationList", page).html(html).trigger("create");
|
||||
$(".btnDeleteIdentificationHeader", elem).on("click", function() {
|
||||
var itemIndex = parseInt(this.getAttribute("data-index"));
|
||||
currentProfile.Identification.Headers.splice(itemIndex, 1), renderIdentificationHeaders(page, currentProfile.Identification.Headers)
|
||||
})
|
||||
}
|
||||
|
||||
function openPopup(elem) {
|
||||
elem.classList.remove("hide")
|
||||
}
|
||||
|
||||
function closePopup(elem) {
|
||||
elem.classList.add("hide")
|
||||
}
|
||||
|
||||
function editIdentificationHeader(page, header) {
|
||||
isSubProfileNew = null == header, header = header || {}, currentSubProfile = header;
|
||||
var popup = $("#identificationHeaderPopup", page);
|
||||
$("#txtIdentificationHeaderName", popup).val(header.Name || ""), $("#txtIdentificationHeaderValue", popup).val(header.Value || ""), $("#selectMatchType", popup).val(header.Match || "Equals"), openPopup(popup[0])
|
||||
}
|
||||
|
||||
function saveIdentificationHeader(page) {
|
||||
currentSubProfile.Name = $("#txtIdentificationHeaderName", page).val(), currentSubProfile.Value = $("#txtIdentificationHeaderValue", page).val(), currentSubProfile.Match = $("#selectMatchType", page).val(), isSubProfileNew && (currentProfile.Identification = currentProfile.Identification || {}, currentProfile.Identification.Headers = currentProfile.Identification.Headers || [], currentProfile.Identification.Headers.push(currentSubProfile)), renderIdentificationHeaders(page, currentProfile.Identification.Headers), currentSubProfile = null, closePopup($("#identificationHeaderPopup", page)[0])
|
||||
}
|
||||
|
||||
function renderXmlDocumentAttributes(page, attribute) {
|
||||
var html = '<div class="paperList">' + attribute.map(function(h) {
|
||||
var li = '<div class="listItem">';
|
||||
return li += '<i class="md-icon listItemIcon">info</i>', li += '<div class="listItemBody">', li += '<h3 class="listItemBodyText">' + h.Name + " = " + (h.Value || "") + "</h3>", li += "</div>", li += '<button type="button" is="paper-icon-button-light" class="btnDeleteXmlAttribute listItemButton" data-index="0"><i class="md-icon">delete</i></button>', li += "</div>"
|
||||
}).join("") + "</div>",
|
||||
elem = $(".xmlDocumentAttributeList", page).html(html).trigger("create");
|
||||
$(".btnDeleteXmlAttribute", elem).on("click", function() {
|
||||
var itemIndex = parseInt(this.getAttribute("data-index"));
|
||||
currentProfile.XmlRootAttributes.splice(itemIndex, 1), renderXmlDocumentAttributes(page, currentProfile.XmlRootAttributes)
|
||||
})
|
||||
}
|
||||
|
||||
function editXmlDocumentAttribute(page, attribute) {
|
||||
isSubProfileNew = null == attribute, attribute = attribute || {}, currentSubProfile = attribute;
|
||||
var popup = $("#xmlAttributePopup", page);
|
||||
$("#txtXmlAttributeName", popup).val(attribute.Name || ""), $("#txtXmlAttributeValue", popup).val(attribute.Value || ""), openPopup(popup[0])
|
||||
}
|
||||
|
||||
function saveXmlDocumentAttribute(page) {
|
||||
currentSubProfile.Name = $("#txtXmlAttributeName", page).val(), currentSubProfile.Value = $("#txtXmlAttributeValue", page).val(), isSubProfileNew && currentProfile.XmlRootAttributes.push(currentSubProfile), renderXmlDocumentAttributes(page, currentProfile.XmlRootAttributes), currentSubProfile = null, closePopup($("#xmlAttributePopup", page)[0])
|
||||
}
|
||||
|
||||
function renderSubtitleProfiles(page, profiles) {
|
||||
var index = 0,
|
||||
html = '<div class="paperList">' + profiles.map(function(h) {
|
||||
var li = '<div class="listItem lnkEditSubProfile" data-index="' + index + '">';
|
||||
return li += '<i class="md-icon listItemIcon">info</i>', li += '<div class="listItemBody">', li += '<h3 class="listItemBodyText">' + (h.Format || "") + "</h3>", li += "</div>", li += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile listItemButton" data-index="' + index + '"><i class="md-icon">delete</i></button>', li += "</div>", index++, li
|
||||
}).join("") + "</div>",
|
||||
elem = $(".subtitleProfileList", page).html(html).trigger("create");
|
||||
$(".btnDeleteProfile", elem).on("click", function() {
|
||||
var itemIndex = parseInt(this.getAttribute("data-index"));
|
||||
currentProfile.SubtitleProfiles.splice(itemIndex, 1), renderSubtitleProfiles(page, currentProfile.SubtitleProfiles)
|
||||
}), $(".lnkEditSubProfile", elem).on("click", function() {
|
||||
var itemIndex = parseInt(this.getAttribute("data-index"));
|
||||
editSubtitleProfile(page, currentProfile.SubtitleProfiles[itemIndex])
|
||||
})
|
||||
}
|
||||
|
||||
function editSubtitleProfile(page, profile) {
|
||||
isSubProfileNew = null == profile, profile = profile || {}, currentSubProfile = profile;
|
||||
var popup = $("#subtitleProfilePopup", page);
|
||||
$("#txtSubtitleProfileFormat", popup).val(profile.Format || ""), $("#selectSubtitleProfileMethod", popup).val(profile.Method || ""), $("#selectSubtitleProfileDidlMode", popup).val(profile.DidlMode || ""), openPopup(popup[0])
|
||||
}
|
||||
|
||||
function saveSubtitleProfile(page) {
|
||||
currentSubProfile.Format = $("#txtSubtitleProfileFormat", page).val(), currentSubProfile.Method = $("#selectSubtitleProfileMethod", page).val(), currentSubProfile.DidlMode = $("#selectSubtitleProfileDidlMode", page).val(), isSubProfileNew && currentProfile.SubtitleProfiles.push(currentSubProfile), renderSubtitleProfiles(page, currentProfile.SubtitleProfiles), currentSubProfile = null, closePopup($("#subtitleProfilePopup", page)[0])
|
||||
}
|
||||
|
||||
function renderSubProfiles(page, profile) {
|
||||
renderDirectPlayProfiles(page, profile.DirectPlayProfiles), renderTranscodingProfiles(page, profile.TranscodingProfiles), renderContainerProfiles(page, profile.ContainerProfiles), renderCodecProfiles(page, profile.CodecProfiles), renderResponseProfiles(page, profile.ResponseProfiles)
|
||||
}
|
||||
|
||||
function saveDirectPlayProfile(page) {
|
||||
currentSubProfile.Type = $("#selectDirectPlayProfileType", page).val(), currentSubProfile.Container = $("#txtDirectPlayContainer", page).val(), currentSubProfile.AudioCodec = $("#txtDirectPlayAudioCodec", page).val(), currentSubProfile.VideoCodec = $("#txtDirectPlayVideoCodec", page).val(), isSubProfileNew && currentProfile.DirectPlayProfiles.push(currentSubProfile), renderSubProfiles(page, currentProfile), currentSubProfile = null, closePopup($("#popupEditDirectPlayProfile", page)[0])
|
||||
}
|
||||
|
||||
function renderDirectPlayProfiles(page, profiles) {
|
||||
var html = "";
|
||||
html += '<ul data-role="listview" data-inset="true" data-split-icon="delete">';
|
||||
for (var currentType, i = 0, length = profiles.length; i < length; i++) {
|
||||
var profile = profiles[i];
|
||||
profile.Type !== currentType && (html += '<li data-role="list-divider">' + profile.Type + "</li>", currentType = profile.Type), html += "<li>", html += '<a data-profileindex="' + i + '" class="lnkEditSubProfile" is="emby-linkbutton" href="#">', html += "<p>" + Globalize.translate("ValueContainer").replace("{0}", profile.Container || allText) + "</p>", "Video" == profile.Type ? (html += "<p>" + Globalize.translate("ValueVideoCodec").replace("{0}", profile.VideoCodec || allText) + "</p>", html += "<p>" + Globalize.translate("ValueAudioCodec").replace("{0}", profile.AudioCodec || allText) + "</p>") : "Audio" == profile.Type && (html += "<p>" + Globalize.translate("ValueCodec").replace("{0}", profile.AudioCodec || allText) + "</p>"), html += "</a>", html += '<a is="emby-linkbutton" href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i + '">Delete</a>', html += "</li>"
|
||||
}
|
||||
html += "</ul>";
|
||||
var elem = $(".directPlayProfiles", page).html(html).trigger("create");
|
||||
$(".btnDeleteProfile", elem).on("click", function() {
|
||||
var index = this.getAttribute("data-profileindex");
|
||||
deleteDirectPlayProfile(page, index)
|
||||
}), $(".lnkEditSubProfile", elem).on("click", function() {
|
||||
var index = parseInt(this.getAttribute("data-profileindex"));
|
||||
editDirectPlayProfile(page, currentProfile.DirectPlayProfiles[index])
|
||||
})
|
||||
}
|
||||
|
||||
function deleteDirectPlayProfile(page, index) {
|
||||
currentProfile.DirectPlayProfiles.splice(index, 1), renderDirectPlayProfiles(page, currentProfile.DirectPlayProfiles)
|
||||
}
|
||||
|
||||
function editDirectPlayProfile(page, directPlayProfile) {
|
||||
isSubProfileNew = null == directPlayProfile, directPlayProfile = directPlayProfile || {}, currentSubProfile = directPlayProfile;
|
||||
var popup = $("#popupEditDirectPlayProfile", page);
|
||||
$("#selectDirectPlayProfileType", popup).val(directPlayProfile.Type || "Video").trigger("change"), $("#txtDirectPlayContainer", popup).val(directPlayProfile.Container || ""), $("#txtDirectPlayAudioCodec", popup).val(directPlayProfile.AudioCodec || ""), $("#txtDirectPlayVideoCodec", popup).val(directPlayProfile.VideoCodec || ""), openPopup(popup[0])
|
||||
}
|
||||
|
||||
function renderTranscodingProfiles(page, profiles) {
|
||||
var html = "";
|
||||
html += '<ul data-role="listview" data-inset="true" data-split-icon="delete">';
|
||||
for (var currentType, i = 0, length = profiles.length; i < length; i++) {
|
||||
var profile = profiles[i];
|
||||
profile.Type !== currentType && (html += '<li data-role="list-divider">' + profile.Type + "</li>", currentType = profile.Type), html += "<li>", html += '<a data-profileindex="' + i + '" class="lnkEditSubProfile" is="emby-linkbutton" href="#">', html += "<p>Protocol: " + (profile.Protocol || "Http") + "</p>", html += "<p>" + Globalize.translate("ValueContainer").replace("{0}", profile.Container || allText) + "</p>", "Video" == profile.Type ? (html += "<p>" + Globalize.translate("ValueVideoCodec").replace("{0}", profile.VideoCodec || allText) + "</p>", html += "<p>" + Globalize.translate("ValueAudioCodec").replace("{0}", profile.AudioCodec || allText) + "</p>") : "Audio" == profile.Type && (html += "<p>" + Globalize.translate("ValueCodec").replace("{0}", profile.AudioCodec || allText) + "</p>"), html += "</a>", html += '<a is="emby-linkbutton" href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i + '">Delete</a>', html += "</li>"
|
||||
}
|
||||
html += "</ul>";
|
||||
var elem = $(".transcodingProfiles", page).html(html).trigger("create");
|
||||
$(".btnDeleteProfile", elem).on("click", function() {
|
||||
var index = this.getAttribute("data-profileindex");
|
||||
deleteTranscodingProfile(page, index)
|
||||
}), $(".lnkEditSubProfile", elem).on("click", function() {
|
||||
var index = parseInt(this.getAttribute("data-profileindex"));
|
||||
editTranscodingProfile(page, currentProfile.TranscodingProfiles[index])
|
||||
})
|
||||
}
|
||||
|
||||
function editTranscodingProfile(page, transcodingProfile) {
|
||||
isSubProfileNew = null == transcodingProfile, transcodingProfile = transcodingProfile || {}, currentSubProfile = transcodingProfile;
|
||||
var popup = $("#transcodingProfilePopup", page);
|
||||
$("#selectTranscodingProfileType", popup).val(transcodingProfile.Type || "Video").trigger("change"), $("#txtTranscodingContainer", popup).val(transcodingProfile.Container || ""), $("#txtTranscodingAudioCodec", popup).val(transcodingProfile.AudioCodec || ""), $("#txtTranscodingVideoCodec", popup).val(transcodingProfile.VideoCodec || ""), $("#selectTranscodingProtocol", popup).val(transcodingProfile.Protocol || "Http"), $("#chkEnableMpegtsM2TsMode", popup).checked(transcodingProfile.EnableMpegtsM2TsMode || !1), $("#chkEstimateContentLength", popup).checked(transcodingProfile.EstimateContentLength || !1), $("#chkReportByteRangeRequests", popup).checked("Bytes" == transcodingProfile.TranscodeSeekInfo), $(".radioTabButton:first", popup).trigger("click"), openPopup(popup[0])
|
||||
}
|
||||
|
||||
function deleteTranscodingProfile(page, index) {
|
||||
currentProfile.TranscodingProfiles.splice(index, 1), renderTranscodingProfiles(page, currentProfile.TranscodingProfiles)
|
||||
}
|
||||
|
||||
function saveTranscodingProfile(page) {
|
||||
currentSubProfile.Type = $("#selectTranscodingProfileType", page).val(), currentSubProfile.Container = $("#txtTranscodingContainer", page).val(), currentSubProfile.AudioCodec = $("#txtTranscodingAudioCodec", page).val(), currentSubProfile.VideoCodec = $("#txtTranscodingVideoCodec", page).val(), currentSubProfile.Protocol = $("#selectTranscodingProtocol", page).val(), currentSubProfile.Context = "Streaming", currentSubProfile.EnableMpegtsM2TsMode = $("#chkEnableMpegtsM2TsMode", page).checked(), currentSubProfile.EstimateContentLength = $("#chkEstimateContentLength", page).checked(), currentSubProfile.TranscodeSeekInfo = $("#chkReportByteRangeRequests", page).checked() ? "Bytes" : "Auto", isSubProfileNew && currentProfile.TranscodingProfiles.push(currentSubProfile), renderSubProfiles(page, currentProfile), currentSubProfile = null, closePopup($("#transcodingProfilePopup", page)[0])
|
||||
}
|
||||
|
||||
function renderContainerProfiles(page, profiles) {
|
||||
var html = "";
|
||||
html += '<ul data-role="listview" data-inset="true" data-split-icon="delete">';
|
||||
for (var currentType, i = 0, length = profiles.length; i < length; i++) {
|
||||
var profile = profiles[i];
|
||||
profile.Type !== currentType && (html += '<li data-role="list-divider">' + profile.Type + "</li>", currentType = profile.Type), html += "<li>", html += '<a data-profileindex="' + i + '" class="lnkEditSubProfile" is="emby-linkbutton" href="#">', html += "<p>" + Globalize.translate("ValueContainer").replace("{0}", profile.Container || allText) + "</p>", profile.Conditions && profile.Conditions.length && (html += "<p>", html += Globalize.translate("ValueConditions").replace("{0}", profile.Conditions.map(function(c) {
|
||||
return c.Property
|
||||
}).join(", ")), html += "</p>"), html += "</a>", html += '<a is="emby-linkbutton" href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i + '">Delete</a>', html += "</li>"
|
||||
}
|
||||
html += "</ul>";
|
||||
var elem = $(".containerProfiles", page).html(html).trigger("create");
|
||||
$(".btnDeleteProfile", elem).on("click", function() {
|
||||
var index = this.getAttribute("data-profileindex");
|
||||
deleteContainerProfile(page, index)
|
||||
}), $(".lnkEditSubProfile", elem).on("click", function() {
|
||||
var index = parseInt(this.getAttribute("data-profileindex"));
|
||||
editContainerProfile(page, currentProfile.ContainerProfiles[index])
|
||||
})
|
||||
}
|
||||
|
||||
function deleteContainerProfile(page, index) {
|
||||
currentProfile.ContainerProfiles.splice(index, 1), renderContainerProfiles(page, currentProfile.ContainerProfiles)
|
||||
}
|
||||
|
||||
function editContainerProfile(page, containerProfile) {
|
||||
isSubProfileNew = null == containerProfile, containerProfile = containerProfile || {}, currentSubProfile = containerProfile;
|
||||
var popup = $("#containerProfilePopup", page);
|
||||
$("#selectContainerProfileType", popup).val(containerProfile.Type || "Video").trigger("change"), $("#txtContainerProfileContainer", popup).val(containerProfile.Container || ""), $(".radioTabButton:first", popup).trigger("click"), openPopup(popup[0])
|
||||
}
|
||||
|
||||
function saveContainerProfile(page) {
|
||||
currentSubProfile.Type = $("#selectContainerProfileType", page).val(), currentSubProfile.Container = $("#txtContainerProfileContainer", page).val(), isSubProfileNew && currentProfile.ContainerProfiles.push(currentSubProfile), renderSubProfiles(page, currentProfile), currentSubProfile = null, closePopup($("#containerProfilePopup", page)[0])
|
||||
}
|
||||
|
||||
function renderCodecProfiles(page, profiles) {
|
||||
var html = "";
|
||||
html += '<ul data-role="listview" data-inset="true" data-split-icon="delete">';
|
||||
for (var currentType, i = 0, length = profiles.length; i < length; i++) {
|
||||
var profile = profiles[i],
|
||||
type = profile.Type.replace("VideoAudio", "Video Audio");
|
||||
type !== currentType && (html += '<li data-role="list-divider">' + type + "</li>", currentType = type), html += "<li>", html += '<a data-profileindex="' + i + '" class="lnkEditSubProfile" is="emby-linkbutton" href="#">', html += "<p>" + Globalize.translate("ValueCodec").replace("{0}", profile.Codec || allText) + "</p>", profile.Conditions && profile.Conditions.length && (html += "<p>", html += Globalize.translate("ValueConditions").replace("{0}", profile.Conditions.map(function(c) {
|
||||
return c.Property
|
||||
}).join(", ")), html += "</p>"), html += "</a>", html += '<a is="emby-linkbutton" href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i + '">Delete</a>', html += "</li>"
|
||||
}
|
||||
html += "</ul>";
|
||||
var elem = $(".codecProfiles", page).html(html).trigger("create");
|
||||
$(".btnDeleteProfile", elem).on("click", function() {
|
||||
var index = this.getAttribute("data-profileindex");
|
||||
deleteCodecProfile(page, index)
|
||||
}), $(".lnkEditSubProfile", elem).on("click", function() {
|
||||
var index = parseInt(this.getAttribute("data-profileindex"));
|
||||
editCodecProfile(page, currentProfile.CodecProfiles[index])
|
||||
})
|
||||
}
|
||||
|
||||
function deleteCodecProfile(page, index) {
|
||||
currentProfile.CodecProfiles.splice(index, 1), renderCodecProfiles(page, currentProfile.CodecProfiles)
|
||||
}
|
||||
|
||||
function editCodecProfile(page, codecProfile) {
|
||||
isSubProfileNew = null == codecProfile, codecProfile = codecProfile || {}, currentSubProfile = codecProfile;
|
||||
var popup = $("#codecProfilePopup", page);
|
||||
$("#selectCodecProfileType", popup).val(codecProfile.Type || "Video").trigger("change"), $("#txtCodecProfileCodec", popup).val(codecProfile.Codec || ""), $(".radioTabButton:first", popup).trigger("click"), openPopup(popup[0])
|
||||
}
|
||||
|
||||
function saveCodecProfile(page) {
|
||||
currentSubProfile.Type = $("#selectCodecProfileType", page).val(), currentSubProfile.Codec = $("#txtCodecProfileCodec", page).val(), isSubProfileNew && currentProfile.CodecProfiles.push(currentSubProfile), renderSubProfiles(page, currentProfile), currentSubProfile = null, closePopup($("#codecProfilePopup", page)[0])
|
||||
}
|
||||
|
||||
function renderResponseProfiles(page, profiles) {
|
||||
var html = "";
|
||||
html += '<ul data-role="listview" data-inset="true" data-split-icon="delete">';
|
||||
for (var currentType, i = 0, length = profiles.length; i < length; i++) {
|
||||
var profile = profiles[i];
|
||||
profile.Type !== currentType && (html += '<li data-role="list-divider">' + profile.Type + "</li>", currentType = profile.Type), html += "<li>", html += '<a data-profileindex="' + i + '" class="lnkEditSubProfile" is="emby-linkbutton" href="#">', html += "<p>" + Globalize.translate("ValueContainer").replace("{0}", profile.Container || allText) + "</p>", "Video" == profile.Type ? (html += "<p>" + Globalize.translate("ValueVideoCodec").replace("{0}", profile.VideoCodec || allText) + "</p>", html += "<p>" + Globalize.translate("ValueAudioCodec").replace("{0}", profile.AudioCodec || allText) + "</p>") : "Audio" == profile.Type && (html += "<p>" + Globalize.translate("ValueCodec").replace("{0}", profile.AudioCodec || allText) + "</p>"), profile.Conditions && profile.Conditions.length && (html += "<p>", html += Globalize.translate("ValueConditions").replace("{0}", profile.Conditions.map(function(c) {
|
||||
return c.Property
|
||||
}).join(", ")), html += "</p>"), html += "</a>", html += '<a is="emby-linkbutton" href="#" data-icon="delete" class="btnDeleteProfile" data-profileindex="' + i + '">Delete</a>', html += "</li>"
|
||||
}
|
||||
html += "</ul>";
|
||||
var elem = $(".mediaProfiles", page).html(html).trigger("create");
|
||||
$(".btnDeleteProfile", elem).on("click", function() {
|
||||
var index = this.getAttribute("data-profileindex");
|
||||
deleteResponseProfile(page, index)
|
||||
}), $(".lnkEditSubProfile", elem).on("click", function() {
|
||||
var index = parseInt(this.getAttribute("data-profileindex"));
|
||||
editResponseProfile(page, currentProfile.ResponseProfiles[index])
|
||||
})
|
||||
}
|
||||
|
||||
function deleteResponseProfile(page, index) {
|
||||
currentProfile.ResponseProfiles.splice(index, 1), renderResponseProfiles(page, currentProfile.ResponseProfiles)
|
||||
}
|
||||
|
||||
function editResponseProfile(page, responseProfile) {
|
||||
isSubProfileNew = null == responseProfile, responseProfile = responseProfile || {}, currentSubProfile = responseProfile;
|
||||
var popup = $("#responseProfilePopup", page);
|
||||
$("#selectResponseProfileType", popup).val(responseProfile.Type || "Video").trigger("change"), $("#txtResponseProfileContainer", popup).val(responseProfile.Container || ""), $("#txtResponseProfileAudioCodec", popup).val(responseProfile.AudioCodec || ""), $("#txtResponseProfileVideoCodec", popup).val(responseProfile.VideoCodec || ""), $(".radioTabButton:first", popup).trigger("click"), openPopup(popup[0])
|
||||
}
|
||||
|
||||
function saveResponseProfile(page) {
|
||||
currentSubProfile.Type = $("#selectResponseProfileType", page).val(), currentSubProfile.Container = $("#txtResponseProfileContainer", page).val(), currentSubProfile.AudioCodec = $("#txtResponseProfileAudioCodec", page).val(), currentSubProfile.VideoCodec = $("#txtResponseProfileVideoCodec", page).val(), isSubProfileNew && currentProfile.ResponseProfiles.push(currentSubProfile), renderSubProfiles(page, currentProfile), currentSubProfile = null, closePopup($("#responseProfilePopup", page)[0])
|
||||
}
|
||||
|
||||
function saveProfile(page, profile) {
|
||||
updateProfile(page, profile);
|
||||
var id = getParameterByName("id");
|
||||
id ? ApiClient.ajax({
|
||||
type: "POST",
|
||||
url: ApiClient.getUrl("Dlna/Profiles/" + id),
|
||||
data: JSON.stringify(profile),
|
||||
contentType: "application/json"
|
||||
}).then(function() {
|
||||
require(["toast"], function(toast) {
|
||||
toast("Settings saved.")
|
||||
})
|
||||
}, Dashboard.processErrorResponse) : ApiClient.ajax({
|
||||
type: "POST",
|
||||
url: ApiClient.getUrl("Dlna/Profiles"),
|
||||
data: JSON.stringify(profile),
|
||||
contentType: "application/json"
|
||||
}).then(function() {
|
||||
Dashboard.navigate("dlnaprofiles.html")
|
||||
}, Dashboard.processErrorResponse), loading.hide()
|
||||
}
|
||||
|
||||
function updateProfile(page, profile) {
|
||||
profile.Name = $("#txtName", page).val(), profile.EnableAlbumArtInDidl = $("#chkEnableAlbumArtInDidl", page).checked(), profile.EnableSingleAlbumArtLimit = $("#chkEnableSingleImageLimit", page).checked(), profile.SupportedMediaTypes = $(".chkMediaType:checked", page).get().map(function(c) {
|
||||
return c.getAttribute("data-value")
|
||||
}).join(","), profile.Identification = profile.Identification || {}, profile.FriendlyName = $("#txtInfoFriendlyName", page).val(), profile.ModelName = $("#txtInfoModelName", page).val(), profile.ModelNumber = $("#txtInfoModelNumber", page).val(), profile.ModelDescription = $("#txtInfoModelDescription", page).val(), profile.ModelUrl = $("#txtInfoModelUrl", page).val(), profile.Manufacturer = $("#txtInfoManufacturer", page).val(), profile.ManufacturerUrl = $("#txtInfoManufacturerUrl", page).val(), profile.SerialNumber = $("#txtInfoSerialNumber", page).val(), profile.Identification.FriendlyName = $("#txtIdFriendlyName", page).val(), profile.Identification.ModelName = $("#txtIdModelName", page).val(), profile.Identification.ModelNumber = $("#txtIdModelNumber", page).val(), profile.Identification.ModelDescription = $("#txtIdModelDescription", page).val(), profile.Identification.ModelUrl = $("#txtIdModelUrl", page).val(), profile.Identification.Manufacturer = $("#txtIdManufacturer", page).val(), profile.Identification.ManufacturerUrl = $("#txtIdManufacturerUrl", page).val(), profile.Identification.SerialNumber = $("#txtIdSerialNumber", page).val(), profile.Identification.DeviceDescription = $("#txtIdDeviceDescription", page).val(), profile.AlbumArtPn = $("#txtAlbumArtPn", page).val(), profile.MaxAlbumArtWidth = $("#txtAlbumArtMaxWidth", page).val(), profile.MaxAlbumArtHeight = $("#txtAlbumArtMaxHeight", page).val(), profile.MaxIconWidth = $("#txtIconMaxWidth", page).val(), profile.MaxIconHeight = $("#txtIconMaxHeight", page).val(), profile.RequiresPlainFolders = $("#chkRequiresPlainFolders", page).checked(), profile.RequiresPlainVideoItems = $("#chkRequiresPlainVideoItems", page).checked(), profile.IgnoreTranscodeByteRangeRequests = $("#chkIgnoreTranscodeByteRangeRequests", page).checked(), profile.MaxStreamingBitrate = $("#txtMaxAllowedBitrate", page).val(), profile.MusicStreamingTranscodingBitrate = $("#txtMusicStreamingTranscodingBitrate", page).val(), profile.ProtocolInfo = $("#txtProtocolInfo", page).val(), profile.XDlnaCap = $("#txtXDlnaCap", page).val(), profile.XDlnaDoc = $("#txtXDlnaDoc", page).val(), profile.SonyAggregationFlags = $("#txtSonyAggregationFlags", page).val(), profile.UserId = $("#selectUser", page).val()
|
||||
}
|
||||
var currentProfile, currentSubProfile, isSubProfileNew, allText = Globalize.translate("LabelAll");
|
||||
$(document).on("pageinit", "#dlnaProfilePage", function() {
|
||||
var page = this;
|
||||
$(".radioTabButton", page).on("click", function() {
|
||||
$(this).siblings().removeClass("ui-btn-active"), $(this).addClass("ui-btn-active");
|
||||
var value = "A" == this.tagName ? this.getAttribute("data-value") : this.value,
|
||||
elem = $("." + value, page);
|
||||
elem.siblings(".tabContent").hide(), elem.show()
|
||||
}), $("#selectDirectPlayProfileType", page).on("change", function() {
|
||||
"Video" == this.value ? $("#fldDirectPlayVideoCodec", page).show() : $("#fldDirectPlayVideoCodec", page).hide(), "Photo" == this.value ? $("#fldDirectPlayAudioCodec", page).hide() : $("#fldDirectPlayAudioCodec", page).show()
|
||||
}), $("#selectTranscodingProfileType", page).on("change", function() {
|
||||
"Video" == this.value ? ($("#fldTranscodingVideoCodec", page).show(), $("#fldTranscodingProtocol", page).show(), $("#fldEnableMpegtsM2TsMode", page).show()) : ($("#fldTranscodingVideoCodec", page).hide(), $("#fldTranscodingProtocol", page).hide(), $("#fldEnableMpegtsM2TsMode", page).hide()), "Photo" == this.value ? ($("#fldTranscodingAudioCodec", page).hide(), $("#fldEstimateContentLength", page).hide(), $("#fldReportByteRangeRequests", page).hide()) : ($("#fldTranscodingAudioCodec", page).show(), $("#fldEstimateContentLength", page).show(), $("#fldReportByteRangeRequests", page).show())
|
||||
}), $("#selectResponseProfileType", page).on("change", function() {
|
||||
"Video" == this.value ? $("#fldResponseProfileVideoCodec", page).show() : $("#fldResponseProfileVideoCodec", page).hide(), "Photo" == this.value ? $("#fldResponseProfileAudioCodec", page).hide() : $("#fldResponseProfileAudioCodec", page).show()
|
||||
}), $(".btnAddDirectPlayProfile", page).on("click", function() {
|
||||
editDirectPlayProfile(page)
|
||||
}), $(".btnAddTranscodingProfile", page).on("click", function() {
|
||||
editTranscodingProfile(page)
|
||||
}), $(".btnAddContainerProfile", page).on("click", function() {
|
||||
editContainerProfile(page)
|
||||
}), $(".btnAddCodecProfile", page).on("click", function() {
|
||||
editCodecProfile(page)
|
||||
}), $(".btnAddResponseProfile", page).on("click", function() {
|
||||
editResponseProfile(page)
|
||||
}), $(".btnAddIdentificationHttpHeader", page).on("click", function() {
|
||||
editIdentificationHeader(page)
|
||||
}), $(".btnAddXmlDocumentAttribute", page).on("click", function() {
|
||||
editXmlDocumentAttribute(page)
|
||||
}), $(".btnAddSubtitleProfile", page).on("click", function() {
|
||||
editSubtitleProfile(page)
|
||||
}), $(".dlnaProfileForm").off("submit", DlnaProfilePage.onSubmit).on("submit", DlnaProfilePage.onSubmit), $(".editDirectPlayProfileForm").off("submit", DlnaProfilePage.onDirectPlayFormSubmit).on("submit", DlnaProfilePage.onDirectPlayFormSubmit), $(".transcodingProfileForm").off("submit", DlnaProfilePage.onTranscodingProfileFormSubmit).on("submit", DlnaProfilePage.onTranscodingProfileFormSubmit), $(".containerProfileForm").off("submit", DlnaProfilePage.onContainerProfileFormSubmit).on("submit", DlnaProfilePage.onContainerProfileFormSubmit), $(".codecProfileForm").off("submit", DlnaProfilePage.onCodecProfileFormSubmit).on("submit", DlnaProfilePage.onCodecProfileFormSubmit), $(".editResponseProfileForm").off("submit", DlnaProfilePage.onResponseProfileFormSubmit).on("submit", DlnaProfilePage.onResponseProfileFormSubmit), $(".identificationHeaderForm").off("submit", DlnaProfilePage.onIdentificationHeaderFormSubmit).on("submit", DlnaProfilePage.onIdentificationHeaderFormSubmit), $(".xmlAttributeForm").off("submit", DlnaProfilePage.onXmlAttributeFormSubmit).on("submit", DlnaProfilePage.onXmlAttributeFormSubmit), $(".subtitleProfileForm").off("submit", DlnaProfilePage.onSubtitleProfileFormSubmit).on("submit", DlnaProfilePage.onSubtitleProfileFormSubmit)
|
||||
}).on("pageshow", "#dlnaProfilePage", function() {
|
||||
var page = this;
|
||||
$("#radioInfo", page).trigger("click"), loadProfile(page)
|
||||
}), window.DlnaProfilePage = {
|
||||
onSubmit: function() {
|
||||
return loading.show(), saveProfile($(this).parents(".page"), currentProfile), !1
|
||||
},
|
||||
onDirectPlayFormSubmit: function() {
|
||||
return saveDirectPlayProfile($(this).parents(".page")), !1
|
||||
},
|
||||
onTranscodingProfileFormSubmit: function() {
|
||||
return saveTranscodingProfile($(this).parents(".page")), !1
|
||||
},
|
||||
onContainerProfileFormSubmit: function() {
|
||||
return saveContainerProfile($(this).parents(".page")), !1
|
||||
},
|
||||
onCodecProfileFormSubmit: function() {
|
||||
return saveCodecProfile($(this).parents(".page")), !1
|
||||
},
|
||||
onResponseProfileFormSubmit: function() {
|
||||
return saveResponseProfile($(this).parents(".page")), !1
|
||||
},
|
||||
onIdentificationHeaderFormSubmit: function() {
|
||||
return saveIdentificationHeader($(this).parents(".page")), !1
|
||||
},
|
||||
onXmlAttributeFormSubmit: function() {
|
||||
return saveXmlDocumentAttribute($(this).parents(".page")), !1
|
||||
},
|
||||
onSubtitleProfileFormSubmit: function() {
|
||||
return saveSubtitleProfile($(this).parents(".page")), !1
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
define(["jQuery", "globalize", "loading", "libraryMenu", "listViewStyle", "emby-linkbutton"], function($, globalize, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function loadProfiles(page) {
|
||||
loading.show(), ApiClient.getJSON(ApiClient.getUrl("Dlna/ProfileInfos")).then(function(result) {
|
||||
renderUserProfiles(page, result), renderSystemProfiles(page, result), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function renderUserProfiles(page, profiles) {
|
||||
renderProfiles(page, page.querySelector(".customProfiles"), profiles.filter(function(p) {
|
||||
return "User" == p.Type
|
||||
}))
|
||||
}
|
||||
|
||||
function renderSystemProfiles(page, profiles) {
|
||||
renderProfiles(page, page.querySelector(".systemProfiles"), profiles.filter(function(p) {
|
||||
return "System" == p.Type
|
||||
}))
|
||||
}
|
||||
|
||||
function renderProfiles(page, element, profiles) {
|
||||
var html = "";
|
||||
profiles.length && (html += '<div class="paperList">');
|
||||
for (var i = 0, length = profiles.length; i < length; i++) {
|
||||
var profile = profiles[i];
|
||||
html += '<div class="listItem listItem-border">', html += '<i class="listItemIcon md-icon">live_tv</i>', html += '<div class="listItemBody two-line">', html += "<a is='emby-linkbutton' style='padding:0;margin:0;' data-ripple='false' class='clearLink' href='dlnaprofile.html?id=" + profile.Id + "'>", html += "<div>" + profile.Name + "</div>", html += "</a>", html += "</div>", "User" == profile.Type && (html += '<button type="button" is="paper-icon-button-light" class="btnDeleteProfile" data-profileid="' + profile.Id + '" title="' + globalize.translate("ButtonDelete") + '"><i class="md-icon">delete</i></button>'), html += "</div>"
|
||||
}
|
||||
profiles.length && (html += "</div>"), element.innerHTML = html, $(".btnDeleteProfile", element).on("click", function() {
|
||||
var id = this.getAttribute("data-profileid");
|
||||
deleteProfile(page, id)
|
||||
})
|
||||
}
|
||||
|
||||
function deleteProfile(page, id) {
|
||||
require(["confirm"], function(confirm) {
|
||||
confirm(globalize.translate("MessageConfirmProfileDeletion"), globalize.translate("HeaderConfirmProfileDeletion")).then(function() {
|
||||
loading.show(), ApiClient.ajax({
|
||||
type: "DELETE",
|
||||
url: ApiClient.getUrl("Dlna/Profiles/" + id)
|
||||
}).then(function() {
|
||||
loading.hide(), loadProfiles(page)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "dlnasettings.html",
|
||||
name: globalize.translate("TabSettings")
|
||||
}, {
|
||||
href: "dlnaprofiles.html",
|
||||
name: globalize.translate("TabProfiles")
|
||||
}]
|
||||
}
|
||||
$(document).on("pageshow", "#dlnaProfilesPage", function() {
|
||||
libraryMenu.setTabs("dlna", 1, getTabs), loadProfiles(this)
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function loadPage(page, config, users) {
|
||||
page.querySelector("#chkEnablePlayTo").checked = config.EnablePlayTo, page.querySelector("#chkEnableDlnaDebugLogging").checked = config.EnableDebugLog, $("#txtClientDiscoveryInterval", page).val(config.ClientDiscoveryIntervalSeconds), $("#chkEnableServer", page).checked(config.EnableServer), $("#chkBlastAliveMessages", page).checked(config.BlastAliveMessages), $("#txtBlastInterval", page).val(config.BlastAliveMessageIntervalSeconds);
|
||||
var usersHtml = users.map(function(u) {
|
||||
return '<option value="' + u.Id + '">' + u.Name + "</option>"
|
||||
}).join("");
|
||||
$("#selectUser", page).html(usersHtml).val(config.DefaultUserId || ""), loading.hide()
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
loading.show();
|
||||
var form = this;
|
||||
return ApiClient.getNamedConfiguration("dlna").then(function(config) {
|
||||
config.EnablePlayTo = form.querySelector("#chkEnablePlayTo").checked, config.EnableDebugLog = form.querySelector("#chkEnableDlnaDebugLogging").checked, config.ClientDiscoveryIntervalSeconds = $("#txtClientDiscoveryInterval", form).val(), config.EnableServer = $("#chkEnableServer", form).checked(), config.BlastAliveMessages = $("#chkBlastAliveMessages", form).checked(), config.BlastAliveMessageIntervalSeconds = $("#txtBlastInterval", form).val(), config.DefaultUserId = $("#selectUser", form).val(), ApiClient.updateNamedConfiguration("dlna", config).then(Dashboard.processServerConfigurationUpdateResult)
|
||||
}), !1
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "dlnasettings.html",
|
||||
name: Globalize.translate("TabSettings")
|
||||
}, {
|
||||
href: "dlnaprofiles.html",
|
||||
name: Globalize.translate("TabProfiles")
|
||||
}]
|
||||
}
|
||||
$(document).on("pageinit", "#dlnaSettingsPage", function() {
|
||||
$(".dlnaSettingsForm").off("submit", onSubmit).on("submit", onSubmit)
|
||||
}).on("pageshow", "#dlnaSettingsPage", function() {
|
||||
libraryMenu.setTabs("dlna", 0, getTabs), loading.show();
|
||||
var page = this,
|
||||
promise1 = ApiClient.getNamedConfiguration("dlna"),
|
||||
promise2 = ApiClient.getUsers();
|
||||
Promise.all([promise1, promise2]).then(function(responses) {
|
||||
loadPage(page, responses[0], responses[1])
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -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))
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,223 @@
|
||||
define(["datetime", "jQuery", "material-icons"], function(datetime, $) {
|
||||
"use strict";
|
||||
|
||||
function getNode(item, folderState, selected) {
|
||||
var htmlName = getNodeInnerHtml(item),
|
||||
node = {
|
||||
id: item.Id,
|
||||
text: htmlName,
|
||||
state: {
|
||||
opened: item.IsFolder && "open" == folderState,
|
||||
selected: selected
|
||||
},
|
||||
li_attr: {
|
||||
serveritemtype: item.Type,
|
||||
collectiontype: item.CollectionType
|
||||
}
|
||||
};
|
||||
return item.IsFolder ? (node.children = [{
|
||||
text: "Loading...",
|
||||
icon: !1
|
||||
}], node.icon = !1) : node.icon = !1, node.state.opened && (node.li_attr.loadedFromServer = !0), selected && (selectedNodeId = item.Id), node
|
||||
}
|
||||
|
||||
function getNodeInnerHtml(item) {
|
||||
var name = item.Name;
|
||||
item.Number && (name = item.Number + " - " + name), null != item.IndexNumber && "Season" != item.Type && (name = item.IndexNumber + " - " + name);
|
||||
var htmlName = "<div class='editorNode'>";
|
||||
return item.LockData && (htmlName += '<i class="md-icon">lock</i>'), htmlName += name, htmlName += "</div>"
|
||||
}
|
||||
|
||||
function loadChildrenOfRootNode(page, scope, callback) {
|
||||
ApiClient.getLiveTvChannels({
|
||||
limit: 0
|
||||
}).then(function(result) {
|
||||
var nodes = [];
|
||||
nodes.push({
|
||||
id: "MediaFolders",
|
||||
text: Globalize.translate("HeaderMediaFolders"),
|
||||
state: {
|
||||
opened: !0
|
||||
},
|
||||
li_attr: {
|
||||
itemtype: "mediafolders",
|
||||
loadedFromServer: !0
|
||||
},
|
||||
icon: !1
|
||||
}), result.TotalRecordCount && nodes.push({
|
||||
id: "livetv",
|
||||
text: Globalize.translate("HeaderLiveTV"),
|
||||
state: {
|
||||
opened: !1
|
||||
},
|
||||
li_attr: {
|
||||
itemtype: "livetv"
|
||||
},
|
||||
children: [{
|
||||
text: "Loading...",
|
||||
icon: !1
|
||||
}],
|
||||
icon: !1
|
||||
}), callback.call(scope, nodes), nodesToLoad.push("MediaFolders")
|
||||
})
|
||||
}
|
||||
|
||||
function loadLiveTvChannels(openItems, callback) {
|
||||
ApiClient.getLiveTvChannels({
|
||||
AddCurrentProgram: !1
|
||||
}).then(function(result) {
|
||||
var nodes = result.Items.map(function(i) {
|
||||
return getNode(i, -1 == openItems.indexOf(i.Id) ? "closed" : "open", !1)
|
||||
});
|
||||
callback(nodes)
|
||||
})
|
||||
}
|
||||
|
||||
function loadMediaFolders(page, scope, openItems, callback) {
|
||||
ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders")).then(function(result) {
|
||||
var nodes = result.Items.map(function(n) {
|
||||
return getNode(n, -1 == openItems.indexOf(n.Id) ? "closed" : "open", !1)
|
||||
});
|
||||
callback.call(scope, nodes);
|
||||
for (var i = 0, length = nodes.length; i < length; i++) nodes[i].state.opened && nodesToLoad.push(nodes[i].id)
|
||||
})
|
||||
}
|
||||
|
||||
function loadNode(page, scope, node, openItems, selectedId, currentUser, callback) {
|
||||
var id = node.id;
|
||||
if ("#" == id) return void loadChildrenOfRootNode(page, scope, callback);
|
||||
if ("livetv" == id) return void loadLiveTvChannels(openItems, callback);
|
||||
if ("MediaFolders" == id) return void loadMediaFolders(page, scope, openItems, callback);
|
||||
var query = {
|
||||
ParentId: id,
|
||||
Fields: "Settings",
|
||||
IsVirtualUnaired: !1,
|
||||
IsMissing: !1,
|
||||
EnableTotalRecordCount: !1,
|
||||
EnableImages: !1,
|
||||
EnableUserData: !1
|
||||
},
|
||||
itemtype = node.li_attr.itemtype;
|
||||
"Season" != itemtype && "Series" != itemtype && (query.SortBy = "SortName"), ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function(result) {
|
||||
var nodes = result.Items.map(function(n) {
|
||||
return getNode(n, -1 == openItems.indexOf(n.Id) ? "closed" : "open", n.Id == selectedId)
|
||||
});
|
||||
callback.call(scope, nodes);
|
||||
for (var i = 0, length = nodes.length; i < length; i++) nodes[i].state.opened && nodesToLoad.push(nodes[i].id)
|
||||
})
|
||||
}
|
||||
|
||||
function scrollToNode(id) {
|
||||
var elem = $("#" + id)[0];
|
||||
elem && elem.scrollIntoView()
|
||||
}
|
||||
|
||||
function initializeTree(page, currentUser, openItems, selectedId) {
|
||||
require(["jstree"], function() {
|
||||
initializeTreeInternal(page, currentUser, openItems, selectedId)
|
||||
})
|
||||
}
|
||||
|
||||
function onNodeSelect(event, data) {
|
||||
var node = data.node,
|
||||
eventData = {
|
||||
id: node.id,
|
||||
itemType: node.li_attr.itemtype,
|
||||
serverItemType: node.li_attr.serveritemtype,
|
||||
collectionType: node.li_attr.collectiontype
|
||||
};
|
||||
"livetv" != eventData.itemType && "mediafolders" != eventData.itemType ? (this.dispatchEvent(new CustomEvent("itemclicked", {
|
||||
detail: eventData,
|
||||
bubbles: !0,
|
||||
cancelable: !1
|
||||
})), document.querySelector(".editPageSidebar").classList.add("editPageSidebar-withcontent")) : document.querySelector(".editPageSidebar").classList.remove("editPageSidebar-withcontent")
|
||||
}
|
||||
|
||||
function onNodeOpen(event, data) {
|
||||
var page = $(this).parents(".page")[0],
|
||||
node = data.node;
|
||||
node.children && node.children && loadNodesToLoad(page, node), node.li_attr && "#" != node.id && !node.li_attr.loadedFromServer && (node.li_attr.loadedFromServer = !0, $.jstree.reference(".libraryTree", page).load_node(node.id, loadNodeCallback))
|
||||
}
|
||||
|
||||
function onNodeLoad(event, data) {
|
||||
var page = $(this).parents(".page")[0],
|
||||
node = data.node;
|
||||
node.children && node.children && loadNodesToLoad(page, node), node.li_attr && "#" != node.id && !node.li_attr.loadedFromServer && (node.li_attr.loadedFromServer = !0, $.jstree.reference(".libraryTree", page).load_node(node.id, loadNodeCallback))
|
||||
}
|
||||
|
||||
function initializeTreeInternal(page, currentUser, openItems, selectedId) {
|
||||
nodesToLoad = [], selectedNodeId = null, $.jstree.destroy(), $(".libraryTree", page).jstree({
|
||||
plugins: ["wholerow"],
|
||||
core: {
|
||||
check_callback: !0,
|
||||
data: function(node, callback) {
|
||||
loadNode(page, this, node, openItems, selectedId, currentUser, callback)
|
||||
},
|
||||
themes: {
|
||||
variant: "large"
|
||||
}
|
||||
}
|
||||
}).off("select_node.jstree", onNodeSelect).on("select_node.jstree", onNodeSelect).off("open_node.jstree", onNodeOpen).on("open_node.jstree", onNodeOpen).off("load_node.jstree", onNodeLoad).on("load_node.jstree", onNodeLoad)
|
||||
}
|
||||
|
||||
function loadNodesToLoad(page, node) {
|
||||
for (var children = node.children, i = 0, length = children.length; i < length; i++) {
|
||||
var child = children[i]; - 1 != nodesToLoad.indexOf(child) && (nodesToLoad = nodesToLoad.filter(function(n) {
|
||||
return n != child
|
||||
}), $.jstree.reference(".libraryTree", page).load_node(child, loadNodeCallback))
|
||||
}
|
||||
}
|
||||
|
||||
function loadNodeCallback(node) {
|
||||
selectedNodeId && node.children && -1 != node.children.indexOf(selectedNodeId) && setTimeout(function() {
|
||||
scrollToNode(selectedNodeId)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
function updateEditorNode(page, item) {
|
||||
var elem = $("#" + item.Id + ">a", page)[0];
|
||||
if (null != elem && ($(".editorNode", elem).remove(), $(elem).append(getNodeInnerHtml(item)), item.IsFolder)) {
|
||||
var tree = jQuery.jstree._reference(".libraryTree"),
|
||||
currentNode = tree._get_node(null, !1);
|
||||
tree.refresh(currentNode)
|
||||
}
|
||||
}
|
||||
|
||||
function setCurrentItemId(id) {
|
||||
itemId = id
|
||||
}
|
||||
|
||||
function getCurrentItemId() {
|
||||
if (itemId) return itemId;
|
||||
var url = window.location.hash || window.location.href;
|
||||
return getParameterByName("id", url)
|
||||
}
|
||||
var selectedNodeId, nodesToLoad = [];
|
||||
$(document).on("itemsaved", ".metadataEditorPage", function(e, item) {
|
||||
updateEditorNode(this, item)
|
||||
}).on("pagebeforeshow", ".metadataEditorPage", function() {
|
||||
require(["css!css/metadataeditor.css"])
|
||||
}).on("pagebeforeshow", ".metadataEditorPage", function() {
|
||||
var page = this;
|
||||
Dashboard.getCurrentUser().then(function(user) {
|
||||
var id = getCurrentItemId();
|
||||
id ? ApiClient.getAncestorItems(id, user.Id).then(function(ancestors) {
|
||||
var ids = ancestors.map(function(i) {
|
||||
return i.Id
|
||||
});
|
||||
initializeTree(page, user, ids, id)
|
||||
}) : initializeTree(page, user, [])
|
||||
})
|
||||
}).on("pagebeforehide", ".metadataEditorPage", function() {
|
||||
$(".libraryTree", this).off("select_node.jstree", onNodeSelect).off("open_node.jstree", onNodeOpen).off("load_node.jstree", onNodeLoad)
|
||||
});
|
||||
var itemId;
|
||||
window.MetadataEditor = {
|
||||
getItemPromise: function() {
|
||||
var currentItemId = getCurrentItemId();
|
||||
return currentItemId ? ApiClient.getItem(Dashboard.getCurrentUserId(), currentItemId) : ApiClient.getRootFolder(Dashboard.getCurrentUserId())
|
||||
},
|
||||
getCurrentItemId: getCurrentItemId,
|
||||
setCurrentItemId: setCurrentItemId
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
define(["jQuery", "loading", "globalize", "dom"], function($, loading, globalize, dom) {
|
||||
"use strict";
|
||||
|
||||
function loadPage(page, config, systemInfo) {
|
||||
Array.prototype.forEach.call(page.querySelectorAll(".chkDecodeCodec"), function(c) {
|
||||
c.checked = -1 !== (config.HardwareDecodingCodecs || []).indexOf(c.getAttribute("data-codec"))
|
||||
}), page.querySelector("#chkHardwareEncoding").checked = config.EnableHardwareEncoding, $("#selectVideoDecoder", page).val(config.HardwareAccelerationType), $("#selectThreadCount", page).val(config.EncodingThreadCount), $("#txtDownMixAudioBoost", page).val(config.DownMixAudioBoost), page.querySelector(".txtEncoderPath").value = config.EncoderAppPath || "", $("#txtTranscodingTempPath", page).val(config.TranscodingTempPath || ""), $("#txtVaapiDevice", page).val(config.VaapiDevice || ""), page.querySelector("#selectH264Preset").value = config.H264Preset || "", page.querySelector("#txtH264Crf").value = config.H264Crf || "", page.querySelector("#chkEnableSubtitleExtraction").checked = config.EnableSubtitleExtraction || !1, page.querySelector("#selectVideoDecoder").dispatchEvent(new CustomEvent("change", {
|
||||
bubbles: !0
|
||||
})), loading.hide()
|
||||
}
|
||||
|
||||
function onSaveEncodingPathFailure(response) {
|
||||
loading.hide();
|
||||
var msg = "";
|
||||
msg = globalize.translate("FFmpegSavePathNotFound"), require(["alert"], function(alert) {
|
||||
alert(msg)
|
||||
})
|
||||
}
|
||||
|
||||
function updateEncoder(form) {
|
||||
return ApiClient.getSystemInfo().then(function(systemInfo) {
|
||||
return ApiClient.ajax({
|
||||
url: ApiClient.getUrl("System/MediaEncoder/Path"),
|
||||
type: "POST",
|
||||
data: {
|
||||
Path: form.querySelector(".txtEncoderPath").value,
|
||||
PathType: "Custom"
|
||||
}
|
||||
}).then(Dashboard.processServerConfigurationUpdateResult, onSaveEncodingPathFailure)
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
var form = this,
|
||||
onDecoderConfirmed = function() {
|
||||
loading.show(), ApiClient.getNamedConfiguration("encoding").then(function(config) {
|
||||
config.DownMixAudioBoost = $("#txtDownMixAudioBoost", form).val(), config.TranscodingTempPath = $("#txtTranscodingTempPath", form).val(), config.EncodingThreadCount = $("#selectThreadCount", form).val(), config.HardwareAccelerationType = $("#selectVideoDecoder", form).val(), config.VaapiDevice = $("#txtVaapiDevice", form).val(), config.H264Preset = form.querySelector("#selectH264Preset").value, config.H264Crf = parseInt(form.querySelector("#txtH264Crf").value || "0"), config.EnableSubtitleExtraction = form.querySelector("#chkEnableSubtitleExtraction").checked, config.HardwareDecodingCodecs = Array.prototype.map.call(Array.prototype.filter.call(form.querySelectorAll(".chkDecodeCodec"), function(c) {
|
||||
return c.checked
|
||||
}), function(c) {
|
||||
return c.getAttribute("data-codec")
|
||||
}), config.EnableHardwareEncoding = form.querySelector("#chkHardwareEncoding").checked, ApiClient.updateNamedConfiguration("encoding", config).then(function() {
|
||||
updateEncoder(form)
|
||||
})
|
||||
})
|
||||
};
|
||||
return $("#selectVideoDecoder", form).val() ? require(["alert"], function(alert) {
|
||||
alert({
|
||||
title: globalize.translate("TitleHardwareAcceleration"),
|
||||
text: globalize.translate("HardwareAccelerationWarning")
|
||||
}).then(onDecoderConfirmed)
|
||||
}) : onDecoderConfirmed(), !1
|
||||
}
|
||||
|
||||
function setDecodingCodecsVisible(context, value) {
|
||||
value = value || "";
|
||||
var any;
|
||||
Array.prototype.forEach.call(context.querySelectorAll(".chkDecodeCodec"), function(c) {
|
||||
-1 === c.getAttribute("data-types").split(",").indexOf(value) ? dom.parentWithTag(c, "LABEL").classList.add("hide") : (dom.parentWithTag(c, "LABEL").classList.remove("hide"), any = !0)
|
||||
}), any ? context.querySelector(".decodingCodecsList").classList.remove("hide") : context.querySelector(".decodingCodecsList").classList.add("hide")
|
||||
}
|
||||
$(document).on("pageinit", "#encodingSettingsPage", function() {
|
||||
var page = this;
|
||||
page.querySelector("#selectVideoDecoder").addEventListener("change", function() {
|
||||
"vaapi" == this.value ? (page.querySelector(".fldVaapiDevice").classList.remove("hide"), page.querySelector("#txtVaapiDevice").setAttribute("required", "required")) : (page.querySelector(".fldVaapiDevice").classList.add("hide"), page.querySelector("#txtVaapiDevice").removeAttribute("required")), this.value ? page.querySelector(".hardwareAccelerationOptions").classList.remove("hide") : page.querySelector(".hardwareAccelerationOptions").classList.add("hide"), setDecodingCodecsVisible(page, this.value)
|
||||
}), $("#btnSelectEncoderPath", page).on("click.selectDirectory", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
includeFiles: !0,
|
||||
callback: function(path) {
|
||||
path && $(".txtEncoderPath", page).val(path), picker.close()
|
||||
}
|
||||
})
|
||||
})
|
||||
}), $("#btnSelectTranscodingTempPath", page).on("click.selectDirectory", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
callback: function(path) {
|
||||
path && $("#txtTranscodingTempPath", page).val(path), picker.close()
|
||||
},
|
||||
validateWriteable: !0,
|
||||
header: globalize.translate("HeaderSelectTranscodingPath"),
|
||||
instruction: globalize.translate("HeaderSelectTranscodingPathHelp")
|
||||
})
|
||||
})
|
||||
}), $(".encodingSettingsForm").off("submit", onSubmit).on("submit", onSubmit)
|
||||
}).on("pageshow", "#encodingSettingsPage", function() {
|
||||
loading.show();
|
||||
var page = this;
|
||||
ApiClient.getNamedConfiguration("encoding").then(function(config) {
|
||||
ApiClient.getSystemInfo().then(function(systemInfo) {
|
||||
"External" == systemInfo.EncoderLocationType ? (page.querySelector(".fldEncoderPath").classList.add("hide"), page.querySelector(".txtEncoderPath").removeAttribute("required")) : (page.querySelector(".fldEncoderPath").classList.remove("hide"), page.querySelector(".txtEncoderPath").setAttribute("required", "required")), loadPage(page, config, systemInfo)
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,155 @@
|
||||
define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "emby-itemscontainer"], function(loading, events, libraryBrowser, imageLoader, listView, cardBuilder) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData(context) {
|
||||
var key = getSavedQueryKey(context),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SeriesSortName,SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Episode",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,MediaSourceCount,UserData",
|
||||
IsMissing: !1,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Thumb",
|
||||
StartIndex: 0,
|
||||
Limit: pageSize
|
||||
},
|
||||
view: libraryBrowser.getSavedView(key) || "Poster"
|
||||
}, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery(context) {
|
||||
return getPageData(context).query
|
||||
}
|
||||
|
||||
function getSavedQueryKey(context) {
|
||||
return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("episodes")), context.savedQueryKey
|
||||
}
|
||||
|
||||
function onViewStyleChange() {
|
||||
var viewStyle = self.getCurrentViewStyle(),
|
||||
itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
"List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = ""
|
||||
}
|
||||
|
||||
function reloadItems(page) {
|
||||
loading.show();
|
||||
var query = getQuery(page);
|
||||
ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function(result) {
|
||||
function onNextPageClick() {
|
||||
query.StartIndex += query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
|
||||
function onPreviousPageClick() {
|
||||
query.StartIndex -= query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
window.scrollTo(0, 0);
|
||||
var html, pagingHtml = libraryBrowser.getQueryPagingHtml({
|
||||
startIndex: query.StartIndex,
|
||||
limit: query.Limit,
|
||||
totalRecordCount: result.TotalRecordCount,
|
||||
showLimit: !1,
|
||||
updatePageSizeSetting: !1,
|
||||
addLayoutButton: !1,
|
||||
sortButton: !1,
|
||||
filterButton: !1
|
||||
}),
|
||||
viewStyle = self.getCurrentViewStyle(),
|
||||
itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
html = "List" == viewStyle ? listView.getListViewHtml({
|
||||
items: result.Items,
|
||||
sortBy: query.SortBy,
|
||||
showParentTitle: !0
|
||||
}) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
scalable: !0,
|
||||
cardLayout: !0
|
||||
}) : cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
overlayText: !1,
|
||||
centerText: !0,
|
||||
scalable: !0,
|
||||
overlayPlayButton: !0
|
||||
});
|
||||
var i, length, elems = tabContent.querySelectorAll(".paging");
|
||||
for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml;
|
||||
for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick);
|
||||
for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick);
|
||||
itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(page), query), loading.hide()
|
||||
})
|
||||
}
|
||||
var self = this,
|
||||
pageSize = 100,
|
||||
data = {};
|
||||
self.showFilterMenu = function() {
|
||||
require(["components/filterdialog/filterdialog"], function(filterDialogFactory) {
|
||||
var filterDialog = new filterDialogFactory({
|
||||
query: getQuery(tabContent),
|
||||
mode: "episodes",
|
||||
serverId: ApiClient.serverId()
|
||||
});
|
||||
events.on(filterDialog, "filterchange", function() {
|
||||
reloadItems(tabContent)
|
||||
}), filterDialog.show()
|
||||
})
|
||||
}, self.getCurrentViewStyle = function() {
|
||||
return getPageData(tabContent).view
|
||||
},
|
||||
function(tabContent) {
|
||||
tabContent.querySelector(".btnFilter").addEventListener("click", function() {
|
||||
self.showFilterMenu()
|
||||
}), tabContent.querySelector(".btnSort").addEventListener("click", function(e) {
|
||||
libraryBrowser.showSortMenu({
|
||||
items: [{
|
||||
name: Globalize.translate("OptionNameSort"),
|
||||
id: "SeriesSortName,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionTvdbRating"),
|
||||
id: "CommunityRating,SeriesSortName,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDateAdded"),
|
||||
id: "DateCreated,SeriesSortName,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionPremiereDate"),
|
||||
id: "PremiereDate,SeriesSortName,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDatePlayed"),
|
||||
id: "DatePlayed,SeriesSortName,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionParentalRating"),
|
||||
id: "OfficialRating,SeriesSortName,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionPlayCount"),
|
||||
id: "PlayCount,SeriesSortName,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionRuntime"),
|
||||
id: "Runtime,SeriesSortName,SortName"
|
||||
}],
|
||||
callback: function() {
|
||||
reloadItems(tabContent)
|
||||
},
|
||||
query: getQuery(tabContent),
|
||||
button: e.target
|
||||
})
|
||||
});
|
||||
var btnSelectView = tabContent.querySelector(".btnSelectView");
|
||||
btnSelectView.addEventListener("click", function(e) {
|
||||
libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(","))
|
||||
}), btnSelectView.addEventListener("layoutchange", function(e) {
|
||||
var viewStyle = e.detail.viewStyle;
|
||||
getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), onViewStyleChange(), reloadItems(tabContent)
|
||||
})
|
||||
}(tabContent), onViewStyleChange(), self.renderTab = function() {
|
||||
reloadItems(tabContent)
|
||||
}, self.destroy = function() {}
|
||||
}
|
||||
});
|
||||
@@ -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)
|
||||
}
|
||||
});
|
||||
@@ -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 = "login.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)
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,263 @@
|
||||
define(["connectionManager", "listView", "cardBuilder", "imageLoader", "libraryBrowser", "emby-itemscontainer", "emby-linkbutton"], function(connectionManager, listView, cardBuilder, imageLoader, libraryBrowser) {
|
||||
"use strict";
|
||||
|
||||
function renderItems(page, item) {
|
||||
var sections = [];
|
||||
item.ArtistCount && sections.push({
|
||||
name: Globalize.translate("TabArtists"),
|
||||
type: "MusicArtist"
|
||||
}), item.ProgramCount && "Person" == item.Type && sections.push({
|
||||
name: Globalize.translate("HeaderUpcomingOnTV"),
|
||||
type: "Program"
|
||||
}), item.MovieCount && sections.push({
|
||||
name: Globalize.translate("TabMovies"),
|
||||
type: "Movie"
|
||||
}), item.SeriesCount && sections.push({
|
||||
name: Globalize.translate("TabShows"),
|
||||
type: "Series"
|
||||
}), item.EpisodeCount && sections.push({
|
||||
name: Globalize.translate("TabEpisodes"),
|
||||
type: "Episode"
|
||||
}), item.TrailerCount && sections.push({
|
||||
name: Globalize.translate("TabTrailers"),
|
||||
type: "Trailer"
|
||||
}), item.GameCount && sections.push({
|
||||
name: Globalize.translate("TabGames"),
|
||||
type: "Game"
|
||||
}), item.AlbumCount && sections.push({
|
||||
name: Globalize.translate("TabAlbums"),
|
||||
type: "MusicAlbum"
|
||||
}), item.MusicVideoCount && sections.push({
|
||||
name: Globalize.translate("TabMusicVideos"),
|
||||
type: "MusicVideo"
|
||||
});
|
||||
var elem = page.querySelector("#childrenContent");
|
||||
elem.innerHTML = sections.map(function(section) {
|
||||
var html = "",
|
||||
sectionClass = "verticalSection";
|
||||
return "Audio" === section.type && (sectionClass += " verticalSection-extrabottompadding"), html += '<div class="' + sectionClass + '" data-type="' + section.type + '">', html += '<div class="sectionTitleContainer sectionTitleContainer-cards">', html += '<h2 class="sectionTitle sectionTitle-cards padded-left">', html += section.name, html += "</h2>", html += '<a is="emby-linkbutton" href="#" class="clearLink hide" style="margin-left:1em;vertical-align:middle;"><button is="emby-button" type="button" class="raised more raised-mini noIcon">' + Globalize.translate("ButtonMore") + "</button></a>", html += "</div>", html += '<div is="emby-itemscontainer" class="itemsContainer padded-left padded-right">', html += "</div>", html += "</div>"
|
||||
}).join("");
|
||||
for (var sectionElems = elem.querySelectorAll(".verticalSection"), i = 0, length = sectionElems.length; i < length; i++) renderSection(page, item, sectionElems[i], sectionElems[i].getAttribute("data-type"))
|
||||
}
|
||||
|
||||
function renderSection(page, item, element, type) {
|
||||
switch (type) {
|
||||
case "Program":
|
||||
loadItems(element, item, type, {
|
||||
MediaTypes: "",
|
||||
IncludeItemTypes: "Program",
|
||||
PersonTypes: "",
|
||||
ArtistIds: "",
|
||||
AlbumArtistIds: "",
|
||||
Limit: 10,
|
||||
SortBy: "StartDate"
|
||||
}, {
|
||||
shape: "backdrop",
|
||||
showTitle: !0,
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0,
|
||||
preferThumb: !0,
|
||||
overlayText: !1,
|
||||
showAirTime: !0,
|
||||
showAirDateTime: !0,
|
||||
showChannelName: !0
|
||||
});
|
||||
break;
|
||||
case "Movie":
|
||||
loadItems(element, item, type, {
|
||||
MediaTypes: "",
|
||||
IncludeItemTypes: "Movie",
|
||||
PersonTypes: "",
|
||||
ArtistIds: "",
|
||||
AlbumArtistIds: "",
|
||||
Limit: 10,
|
||||
SortBy: "SortName"
|
||||
}, {
|
||||
shape: "portrait",
|
||||
showTitle: !0,
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0,
|
||||
overlayText: !1,
|
||||
showYear: !0
|
||||
});
|
||||
break;
|
||||
case "MusicVideo":
|
||||
loadItems(element, item, type, {
|
||||
MediaTypes: "",
|
||||
IncludeItemTypes: "MusicVideo",
|
||||
PersonTypes: "",
|
||||
ArtistIds: "",
|
||||
AlbumArtistIds: "",
|
||||
Limit: 10,
|
||||
SortBy: "SortName"
|
||||
}, {
|
||||
shape: "portrait",
|
||||
showTitle: !0,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0
|
||||
});
|
||||
break;
|
||||
case "Game":
|
||||
loadItems(element, item, type, {
|
||||
MediaTypes: "",
|
||||
IncludeItemTypes: "Game",
|
||||
PersonTypes: "",
|
||||
ArtistIds: "",
|
||||
AlbumArtistIds: "",
|
||||
Limit: 10,
|
||||
SortBy: "SortName"
|
||||
}, {
|
||||
shape: "portrait",
|
||||
showTitle: !0,
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0
|
||||
});
|
||||
break;
|
||||
case "Trailer":
|
||||
loadItems(element, item, type, {
|
||||
MediaTypes: "",
|
||||
IncludeItemTypes: "Trailer",
|
||||
PersonTypes: "",
|
||||
ArtistIds: "",
|
||||
AlbumArtistIds: "",
|
||||
Limit: 10,
|
||||
SortBy: "SortName"
|
||||
}, {
|
||||
shape: "portrait",
|
||||
showTitle: !0,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0
|
||||
});
|
||||
break;
|
||||
case "Series":
|
||||
loadItems(element, item, type, {
|
||||
MediaTypes: "",
|
||||
IncludeItemTypes: "Series",
|
||||
PersonTypes: "",
|
||||
ArtistIds: "",
|
||||
AlbumArtistIds: "",
|
||||
Limit: 10,
|
||||
SortBy: "SortName"
|
||||
}, {
|
||||
shape: "portrait",
|
||||
showTitle: !0,
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0
|
||||
});
|
||||
break;
|
||||
case "MusicAlbum":
|
||||
loadItems(element, item, type, {
|
||||
MediaTypes: "",
|
||||
IncludeItemTypes: "MusicAlbum",
|
||||
PersonTypes: "",
|
||||
ArtistIds: "",
|
||||
AlbumArtistIds: ""
|
||||
}, {
|
||||
shape: "square",
|
||||
playFromHere: !0,
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
coverImage: !0,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0
|
||||
});
|
||||
break;
|
||||
case "MusicArtist":
|
||||
loadItems(element, item, type, {
|
||||
MediaTypes: "",
|
||||
IncludeItemTypes: "MusicArtist",
|
||||
PersonTypes: "",
|
||||
ArtistIds: "",
|
||||
AlbumArtistIds: "",
|
||||
Limit: 8,
|
||||
SortBy: "SortName"
|
||||
}, {
|
||||
shape: "square",
|
||||
playFromHere: !0,
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
coverImage: !0,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0
|
||||
});
|
||||
break;
|
||||
case "Episode":
|
||||
loadItems(element, item, type, {
|
||||
MediaTypes: "",
|
||||
IncludeItemTypes: "Episode",
|
||||
PersonTypes: "",
|
||||
ArtistIds: "",
|
||||
AlbumArtistIds: "",
|
||||
Limit: 6,
|
||||
SortBy: "SortName"
|
||||
}, {
|
||||
shape: "backdrop",
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0
|
||||
});
|
||||
break;
|
||||
case "Audio":
|
||||
loadItems(element, item, type, {
|
||||
MediaTypes: "",
|
||||
IncludeItemTypes: "Audio",
|
||||
PersonTypes: "",
|
||||
ArtistIds: "",
|
||||
AlbumArtistIds: "",
|
||||
SortBy: "AlbumArtist,Album,SortName"
|
||||
}, {
|
||||
playFromHere: !0,
|
||||
action: "playallfromhere",
|
||||
smallIcon: !0,
|
||||
artist: !0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function loadItems(element, item, type, query, listOptions) {
|
||||
query = getQuery(query, item), getItemsFunction(query, item)(query.StartIndex, query.Limit, query.Fields).then(function(result) {
|
||||
var html = "";
|
||||
if (query.Limit && result.TotalRecordCount > query.Limit) {
|
||||
var link = element.querySelector("a");
|
||||
link.classList.remove("hide"), link.setAttribute("href", getMoreItemsHref(item, type))
|
||||
} else element.querySelector("a").classList.add("hide");
|
||||
listOptions.items = result.Items;
|
||||
var itemsContainer = element.querySelector(".itemsContainer");
|
||||
"Audio" == type ? (html = listView.getListViewHtml(listOptions), itemsContainer.classList.remove("vertical-wrap"), itemsContainer.classList.add("vertical-list")) : (html = cardBuilder.getCardsHtml(listOptions), itemsContainer.classList.add("vertical-wrap"), itemsContainer.classList.remove("vertical-list")), itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer)
|
||||
})
|
||||
}
|
||||
|
||||
function getMoreItemsHref(item, type) {
|
||||
return "Genre" == item.Type ? "list/list.html?type=" + type + "&genreId=" + item.Id + "&serverId=" + item.ServerId : "MusicGenre" == item.Type ? "list/list.html?type=" + type + "&musicGenreId=" + item.Id + "&serverId=" + item.ServerId : "GameGenre" == item.Type ? "list/list.html?type=" + type + "&gameGenreId=" + item.Id + "&serverId=" + item.ServerId : "Studio" == item.Type ? "list/list.html?type=" + type + "&studioId=" + item.Id + "&serverId=" + item.ServerId : "MusicArtist" == item.Type ? "list/list.html?type=" + type + "&artistId=" + item.Id + "&serverId=" + item.ServerId : "Person" == item.Type ? "list/list.html?type=" + type + "&personId=" + item.Id + "&serverId=" + item.ServerId : "list/list.html?type=" + type + "&parentId=" + item.Id + "&serverId=" + item.ServerId
|
||||
}
|
||||
|
||||
function addCurrentItemToQuery(query, item) {
|
||||
"Person" == item.Type ? query.PersonIds = item.Id : "Genre" == item.Type ? query.GenreIds = item.Id : "MusicGenre" == item.Type ? query.GenreIds = item.Id : "GameGenre" == item.Type ? query.GenreIds = item.Id : "Studio" == item.Type ? query.StudioIds = item.Id : "MusicArtist" == item.Type && (connectionManager.getApiClient(item.ServerId).isMinServerVersion("3.4.1.18") ? query.AlbumArtistIds = item.Id : query.ArtistIds = item.Id)
|
||||
}
|
||||
|
||||
function getQuery(options, item) {
|
||||
var query = {
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "",
|
||||
Recursive: !0,
|
||||
Fields: "AudioInfo,SeriesInfo,ParentId,PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
Limit: 100,
|
||||
StartIndex: 0,
|
||||
CollapseBoxSetItems: !1
|
||||
};
|
||||
return query = Object.assign(query, options || {}), addCurrentItemToQuery(query, item), query
|
||||
}
|
||||
|
||||
function getItemsFunction(options, item) {
|
||||
var query = getQuery(options, item);
|
||||
return function(index, limit, fields) {
|
||||
query.StartIndex = index, query.Limit = limit, fields && (query.Fields += "," + fields);
|
||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
return "MusicArtist" === query.IncludeItemTypes ? (query.IncludeItemTypes = null, apiClient.getAlbumArtists(apiClient.getCurrentUserId(), query)) : apiClient.getItems(apiClient.getCurrentUserId(), query)
|
||||
}
|
||||
}
|
||||
window.ItemsByName = {
|
||||
renderItems: renderItems
|
||||
}
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,101 @@
|
||||
define(["userSettings"], function(userSettings) {
|
||||
"use strict";
|
||||
var libraryBrowser = {
|
||||
getSavedQueryKey: function(modifier) {
|
||||
return window.location.href.split("#")[0] + (modifier || "")
|
||||
},
|
||||
loadSavedQueryValues: function(key, query) {
|
||||
var values = userSettings.get(key);
|
||||
return values ? (values = JSON.parse(values), Object.assign(query, values)) : query
|
||||
},
|
||||
saveQueryValues: function(key, query) {
|
||||
var values = {};
|
||||
query.SortBy && (values.SortBy = query.SortBy), query.SortOrder && (values.SortOrder = query.SortOrder), userSettings.set(key, JSON.stringify(values))
|
||||
},
|
||||
saveViewSetting: function(key, value) {
|
||||
userSettings.set(key + "-_view", value)
|
||||
},
|
||||
getSavedView: function(key) {
|
||||
return userSettings.get(key + "-_view")
|
||||
},
|
||||
showLayoutMenu: function(button, currentLayout, views) {
|
||||
var dispatchEvent = !0;
|
||||
views || (dispatchEvent = !1, views = button.getAttribute("data-layouts"), views = views ? views.split(",") : ["List", "Poster", "PosterCard", "Thumb", "ThumbCard"]);
|
||||
var menuItems = views.map(function(v) {
|
||||
return {
|
||||
name: Globalize.translate("Option" + v),
|
||||
id: v,
|
||||
selected: currentLayout == v
|
||||
}
|
||||
});
|
||||
require(["actionsheet"], function(actionsheet) {
|
||||
actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: button,
|
||||
callback: function(id) {
|
||||
button.dispatchEvent(new CustomEvent("layoutchange", {
|
||||
detail: {
|
||||
viewStyle: id
|
||||
},
|
||||
bubbles: !0,
|
||||
cancelable: !1
|
||||
})), dispatchEvent || window.$ && $(button).trigger("layoutchange", [id])
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
getQueryPagingHtml: function(options) {
|
||||
var startIndex = options.startIndex,
|
||||
limit = options.limit,
|
||||
totalRecordCount = options.totalRecordCount,
|
||||
html = "",
|
||||
recordsEnd = Math.min(startIndex + limit, totalRecordCount),
|
||||
showControls = limit < totalRecordCount;
|
||||
if (html += '<div class="listPaging">', showControls) {
|
||||
html += '<span style="vertical-align:middle;">';
|
||||
html += (totalRecordCount ? startIndex + 1 : 0) + "-" + recordsEnd + " of " + totalRecordCount, html += "</span>"
|
||||
}
|
||||
return (showControls || options.viewButton || options.filterButton || options.sortButton || options.addLayoutButton) && (html += '<div style="display:inline-block;">', showControls && (html += '<button is="paper-icon-button-light" class="btnPreviousPage autoSize" ' + (startIndex ? "" : "disabled") + '><i class="md-icon"></i></button>', html += '<button is="paper-icon-button-light" class="btnNextPage autoSize" ' + (startIndex + limit >= totalRecordCount ? "disabled" : "") + '><i class="md-icon"></i></button>'), options.addLayoutButton && (html += '<button is="paper-icon-button-light" title="' + Globalize.translate("ButtonSelectView") + '" class="btnChangeLayout autoSize" data-layouts="' + (options.layouts || "") + '" onclick="LibraryBrowser.showLayoutMenu(this, \'' + (options.currentLayout || "") + '\');"><i class="md-icon"></i></button>'), options.sortButton && (html += '<button is="paper-icon-button-light" class="btnSort autoSize" title="' + Globalize.translate("ButtonSort") + '"><i class="md-icon"></i></button>'), options.filterButton && (html += '<button is="paper-icon-button-light" class="btnFilter autoSize" title="' + Globalize.translate("ButtonFilter") + '"><i class="md-icon"></i></button>'), html += "</div>"), html += "</div>"
|
||||
},
|
||||
showSortMenu: function(options) {
|
||||
require(["dialogHelper", "emby-radio"], function(dialogHelper) {
|
||||
function onSortByChange() {
|
||||
var newValue = this.value;
|
||||
if (this.checked) {
|
||||
var changed = options.query.SortBy != newValue;
|
||||
options.query.SortBy = newValue.replace("_", ","), options.query.StartIndex = 0, options.callback && changed && options.callback()
|
||||
}
|
||||
}
|
||||
|
||||
function onSortOrderChange() {
|
||||
var newValue = this.value;
|
||||
if (this.checked) {
|
||||
var changed = options.query.SortOrder != newValue;
|
||||
options.query.SortOrder = newValue, options.query.StartIndex = 0, options.callback && changed && options.callback()
|
||||
}
|
||||
}
|
||||
var dlg = dialogHelper.createDialog({
|
||||
removeOnClose: !0,
|
||||
modal: !1,
|
||||
entryAnimationDuration: 160,
|
||||
exitAnimationDuration: 200
|
||||
});
|
||||
dlg.classList.add("ui-body-a"), dlg.classList.add("background-theme-a"), dlg.classList.add("formDialog");
|
||||
var html = "";
|
||||
html += '<div style="margin:0;padding:1.25em 1.5em 1.5em;">', html += '<h2 style="margin:0 0 .5em;">', html += Globalize.translate("HeaderSortBy"), html += "</h2>";
|
||||
var i, length, isChecked;
|
||||
for (html += "<div>", i = 0, length = options.items.length; i < length; i++) {
|
||||
var option = options.items[i],
|
||||
radioValue = option.id.replace(",", "_");
|
||||
isChecked = (options.query.SortBy || "").replace(",", "_") == radioValue ? " checked" : "", html += '<label class="radio-label-block"><input type="radio" is="emby-radio" name="SortBy" data-id="' + option.id + '" value="' + radioValue + '" class="menuSortBy" ' + isChecked + " /><span>" + option.name + "</span></label>"
|
||||
}
|
||||
html += "</div>", html += '<h2 style="margin: 1em 0 .5em;">', html += Globalize.translate("HeaderSortOrder"), html += "</h2>", html += "<div>", isChecked = "Ascending" == options.query.SortOrder ? " checked" : "", html += '<label class="radio-label-block"><input type="radio" is="emby-radio" name="SortOrder" value="Ascending" class="menuSortOrder" ' + isChecked + " /><span>" + Globalize.translate("OptionAscending") + "</span></label>", isChecked = "Descending" == options.query.SortOrder ? " checked" : "", html += '<label class="radio-label-block"><input type="radio" is="emby-radio" name="SortOrder" value="Descending" class="menuSortOrder" ' + isChecked + " /><span>" + Globalize.translate("OptionDescending") + "</span></label>", html += "</div>", html += "</div>", dlg.innerHTML = html, dialogHelper.open(dlg);
|
||||
var sortBys = dlg.querySelectorAll(".menuSortBy");
|
||||
for (i = 0, length = sortBys.length; i < length; i++) sortBys[i].addEventListener("change", onSortByChange);
|
||||
var sortOrders = dlg.querySelectorAll(".menuSortOrder");
|
||||
for (i = 0, length = sortOrders.length; i < length; i++) sortOrders[i].addEventListener("change", onSortOrderChange)
|
||||
})
|
||||
}
|
||||
};
|
||||
return window.LibraryBrowser = libraryBrowser, libraryBrowser
|
||||
});
|
||||
@@ -0,0 +1,451 @@
|
||||
define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "viewManager", "libraryBrowser", "appRouter", "apphost", "playbackManager", "browser", "globalize", "paper-icon-button-light", "material-icons", "scrollStyles", "flexStyles"], function(dom, layoutManager, inputManager, connectionManager, events, viewManager, libraryBrowser, appRouter, appHost, playbackManager, browser, globalize) {
|
||||
"use strict";
|
||||
|
||||
function getCurrentApiClient() {
|
||||
return currentUser && currentUser.localUser ? connectionManager.getApiClient(currentUser.localUser.ServerId) : connectionManager.currentApiClient()
|
||||
}
|
||||
|
||||
function lazyLoadViewMenuBarImages() {
|
||||
require(["imageLoader"], function(imageLoader) {
|
||||
imageLoader.lazyChildren(skinHeader)
|
||||
})
|
||||
}
|
||||
|
||||
function onBackClick() {
|
||||
appRouter.back()
|
||||
}
|
||||
|
||||
function updateUserInHeader(user) {
|
||||
var hasImage;
|
||||
if (user && user.name) {
|
||||
if (user.imageUrl) {
|
||||
var url = user.imageUrl;
|
||||
user.supportsImageParams && (url += "&height=" + Math.round(26 * Math.max(window.devicePixelRatio || 1, 2))), updateHeaderUserButton(url), hasImage = !0
|
||||
}
|
||||
headerUserButton.classList.remove("hide")
|
||||
} else headerUserButton.classList.add("hide");
|
||||
hasImage || updateHeaderUserButton(null), user && user.localUser ? (headerHomeButton && headerHomeButton.classList.remove("hide"), headerSearchButton && headerSearchButton.classList.remove("hide"), headerSettingsButton && (user.localUser.Policy.IsAdministrator ? headerSettingsButton.classList.remove("hide") : headerSettingsButton.classList.add("hide")), headerCastButton.classList.remove("hide")) : (headerHomeButton.classList.add("hide"), headerCastButton.classList.add("hide"), headerSearchButton && headerSearchButton.classList.add("hide"), headerSettingsButton && headerSettingsButton.classList.add("hide")), requiresUserRefresh = !1
|
||||
}
|
||||
|
||||
function updateHeaderUserButton(src) {
|
||||
src ? (headerUserButton.classList.add("headerUserButtonRound"), headerUserButton.innerHTML = '<img src="' + src + '" />') : (headerUserButton.classList.remove("headerUserButtonRound"), headerUserButton.innerHTML = '<i class="md-icon"></i>')
|
||||
}
|
||||
|
||||
function showSearch() {
|
||||
inputManager.trigger("search")
|
||||
}
|
||||
|
||||
function onHeaderUserButtonClick(e) {
|
||||
Dashboard.navigate("mypreferencesmenu.html")
|
||||
}
|
||||
|
||||
function onSettingsClick(e) {
|
||||
Dashboard.navigate("dashboard.html")
|
||||
}
|
||||
|
||||
function onHeaderHomeButtonClick() {
|
||||
Dashboard.navigate("home.html")
|
||||
}
|
||||
|
||||
function bindMenuEvents() {
|
||||
(mainDrawerButton = document.querySelector(".mainDrawerButton")) && mainDrawerButton.addEventListener("click", toggleMainDrawer);
|
||||
var headerBackButton = skinHeader.querySelector(".headerBackButton");
|
||||
headerBackButton && headerBackButton.addEventListener("click", onBackClick), headerSearchButton && headerSearchButton.addEventListener("click", showSearch), headerUserButton.addEventListener("click", onHeaderUserButtonClick), headerHomeButton.addEventListener("click", onHeaderHomeButtonClick), initHeadRoom(skinHeader), headerCastButton.addEventListener("click", onCastButtonClicked), headerSettingsButton && headerSettingsButton.addEventListener("click", onSettingsClick)
|
||||
}
|
||||
|
||||
function onCastButtonClicked() {
|
||||
var btn = this;
|
||||
require(["playerSelectionMenu"], function(playerSelectionMenu) {
|
||||
playerSelectionMenu.show(btn)
|
||||
})
|
||||
}
|
||||
|
||||
function getItemHref(item, context) {
|
||||
return appRouter.getRouteUrl(item, {
|
||||
context: context
|
||||
})
|
||||
}
|
||||
|
||||
function toggleMainDrawer() {
|
||||
navDrawerInstance.isVisible ? closeMainDrawer() : openMainDrawer()
|
||||
}
|
||||
|
||||
function openMainDrawer() {
|
||||
navDrawerInstance.open(), lastOpenTime = (new Date).getTime()
|
||||
}
|
||||
|
||||
function onMainDrawerOpened() {
|
||||
layoutManager.mobile && document.body.classList.add("bodyWithPopupOpen")
|
||||
}
|
||||
|
||||
function closeMainDrawer() {
|
||||
navDrawerInstance.close()
|
||||
}
|
||||
|
||||
function onMainDrawerSelect(e) {
|
||||
navDrawerInstance.isVisible ? onMainDrawerOpened() : document.body.classList.remove("bodyWithPopupOpen")
|
||||
}
|
||||
|
||||
function refreshLibraryInfoInDrawer(user, drawer) {
|
||||
var html = "";
|
||||
html += '<div style="height:.5em;"></div>', html += '<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder" href="home.html"><i class="md-icon navMenuOptionIcon"></i><span class="navMenuOptionText">' + globalize.translate("ButtonHome") + "</span></a>", html += '<div class="libraryMenuDownloads">', html += '<h3 class="sidebarHeader">', html += globalize.translate("sharedcomponents#HeaderMyDownloads"), html += "</h3>", html += '<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder" data-itemid="manageoffline" href="offline/offline.html"><i class="md-icon navMenuOptionIcon"></i><span class="navMenuOptionText">' + globalize.translate("sharedcomponents#Browse") + "</span></a>", html += '<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder" data-itemid="manageoffline" href="managedownloads.html"><i class="md-icon navMenuOptionIcon"></i><span class="navMenuOptionText">' + globalize.translate("sharedcomponents#Manage") + "</span></a>", html += "</div>", html += '<div class="libraryMenuOptions">', html += "</div>";
|
||||
var localUser = user.localUser;
|
||||
localUser && localUser.Policy.IsAdministrator && (html += '<div class="adminMenuOptions">', html += '<h3 class="sidebarHeader">', html += globalize.translate("HeaderAdmin"), html += "</h3>", html += '<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder lnkManageServer" data-itemid="dashboard" href="dashboard.html"><i class="md-icon navMenuOptionIcon"></i><span class="navMenuOptionText">' + globalize.translate("ButtonManageServer") + "</span></a>", html += '<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder editorViewMenu" data-itemid="editor" href="edititemmetadata.html"><i class="md-icon navMenuOptionIcon"></i><span class="navMenuOptionText">' + globalize.translate("MetadataManager") + "</span></a>", html += "</div>"), html += '<div class="userMenuOptions">', user.localUser && (html += '<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder lnkMySettings" href="mypreferencesmenu.html"><i class="md-icon navMenuOptionIcon"></i><span class="navMenuOptionText">' + globalize.translate("ButtonSettings") + "</span></a>"), html += '<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder lnkSyncToOtherDevices" data-itemid="syncotherdevices" href="mysync.html"><i class="md-icon navMenuOptionIcon"></i><span class="navMenuOptionText">' + globalize.translate("sharedcomponents#Sync") + "</span></a>", AppInfo.isNativeApp && (html += '<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder" data-itemid="selectserver" href="selectserver.html?showuser=1"><i class="md-icon navMenuOptionIcon"></i><span class="navMenuOptionText">' + globalize.translate("ButtonSelectServer") + "</span></a>"), /* TODO cvium user is always localUser I think */!user.localUser || user.localUser.EnableAutoLogin || (html += '<a is="emby-linkbutton" class="navMenuOption lnkMediaFolder btnLogout" data-itemid="logout" href="#"><i class="md-icon navMenuOptionIcon"></i><span class="navMenuOptionText">' + globalize.translate("ButtonSignOut") + "</span></a>"), html += "</div>", navDrawerScrollContainer.innerHTML = html;
|
||||
var btnLogout = navDrawerScrollContainer.querySelector(".btnLogout");
|
||||
btnLogout && btnLogout.addEventListener("click", onLogoutClick)
|
||||
}
|
||||
|
||||
function refreshDashboardInfoInDrawer(apiClient) {
|
||||
currentDrawerType = "admin", loadNavDrawer(), navDrawerScrollContainer.querySelector(".adminDrawerLogo") ? updateDashboardMenuSelectedItem() : createDashboardMenu(apiClient)
|
||||
}
|
||||
|
||||
function isUrlInCurrentView(url) {
|
||||
return -1 !== window.location.href.toString().toLowerCase().indexOf(url.toLowerCase())
|
||||
}
|
||||
|
||||
function updateDashboardMenuSelectedItem() {
|
||||
for (var links = navDrawerScrollContainer.querySelectorAll(".navMenuOption"), currentViewId = viewManager.currentView().id, i = 0, length = links.length; i < length; i++) {
|
||||
var link = links[i],
|
||||
selected = !1,
|
||||
pageIds = link.getAttribute("data-pageids");
|
||||
pageIds && (pageIds = pageIds.split("|"), selected = -1 != pageIds.indexOf(currentViewId));
|
||||
var pageUrls = link.getAttribute("data-pageurls");
|
||||
if (pageUrls && (pageUrls = pageUrls.split("|"), selected = pageUrls.filter(isUrlInCurrentView).length > 0), selected) {
|
||||
link.classList.add("navMenuOption-selected");
|
||||
var title = "";
|
||||
link = link.querySelector("span") || link;
|
||||
title += (link.innerText || link.textContent).trim(), LibraryMenu.setTitle(title)
|
||||
} else link.classList.remove("navMenuOption-selected")
|
||||
}
|
||||
}
|
||||
|
||||
function createToolsMenuList(pluginItems) {
|
||||
var links = [{
|
||||
name: globalize.translate("TabServer")
|
||||
}, {
|
||||
name: globalize.translate("TabDashboard"),
|
||||
href: "dashboard.html",
|
||||
pageIds: ["dashboardPage", "serverActivityPage"],
|
||||
icon: "dashboard"
|
||||
}, {
|
||||
name: globalize.translate("TabSettings"),
|
||||
href: "dashboardgeneral.html",
|
||||
pageIds: ["dashboardGeneralPage"],
|
||||
icon: "settings"
|
||||
}, {
|
||||
name: globalize.translate("TabUsers"),
|
||||
href: "userprofiles.html",
|
||||
pageIds: ["userProfilesPage", "newUserPage", "editUserPage", "userLibraryAccessPage", "userParentalControlPage", "userPasswordPage"],
|
||||
icon: "people"
|
||||
}, {
|
||||
name: globalize.translate("TabLibrary"),
|
||||
href: "library.html",
|
||||
pageIds: ["mediaLibraryPage", "librarySettingsPage", "libraryDisplayPage", "metadataImagesConfigurationPage", "metadataNfoPage"],
|
||||
icon: "folder",
|
||||
color: "#38c"
|
||||
}, {
|
||||
name: globalize.translate("TabPlayback"),
|
||||
icon: "play_circle_filled",
|
||||
color: "#E5342E",
|
||||
href: "playbackconfiguration.html",
|
||||
pageIds: ["playbackConfigurationPage", "streamingSettingsPage"]
|
||||
}, {
|
||||
name: globalize.translate("TabTranscoding"),
|
||||
icon: "transform",
|
||||
href: "encodingsettings.html",
|
||||
pageIds: ["encodingSettingsPage"]
|
||||
}];
|
||||
return addPluginPagesToMainMenu(links, pluginItems, "server"), links.push({
|
||||
divider: !0,
|
||||
name: globalize.translate("TabDevices")
|
||||
}), links.push({
|
||||
name: globalize.translate("TabDevices"),
|
||||
href: "devices/devices.html",
|
||||
pageIds: ["devicesPage", "devicePage"],
|
||||
icon: "tablet"
|
||||
}), links.push({
|
||||
name: globalize.translate("HeaderDownloadSync"),
|
||||
icon: "file_download",
|
||||
href: "syncactivity.html",
|
||||
pageIds: ["syncActivityPage", "syncJobPage", "syncSettingsPage"],
|
||||
color: "#009688"
|
||||
}), links.push({
|
||||
name: globalize.translate("TabCameraUpload"),
|
||||
href: "devicesupload.html",
|
||||
pageIds: ["devicesUploadPage"],
|
||||
icon: "photo_camera"
|
||||
}), links.push({
|
||||
name: globalize.translate("DLNA"),
|
||||
href: "dlnasettings.html",
|
||||
pageIds: ["dlnaSettingsPage", "dlnaProfilesPage", "dlnaProfilePage"],
|
||||
icon: ""
|
||||
}), links.push({
|
||||
divider: !0,
|
||||
name: globalize.translate("TabLiveTV")
|
||||
}), links.push({
|
||||
name: globalize.translate("TabLiveTV"),
|
||||
href: "livetvstatus.html",
|
||||
pageIds: ["liveTvStatusPage", "liveTvTunerPage"],
|
||||
icon: ""
|
||||
}), links.push({
|
||||
name: globalize.translate("DVR"),
|
||||
href: "livetvsettings.html",
|
||||
pageIds: ["liveTvSettingsPage"],
|
||||
icon: "dvr"
|
||||
}), links.push({
|
||||
divider: !0,
|
||||
name: globalize.translate("TabExpert")
|
||||
}), links.push({
|
||||
name: globalize.translate("TabAdvanced"),
|
||||
icon: "settings",
|
||||
href: "dashboardhosting.html",
|
||||
color: "#F16834",
|
||||
pageIds: ["dashboardHostingPage", "serverSecurityPage"]
|
||||
}), links.push({
|
||||
name: globalize.translate("TabLogs"),
|
||||
href: "log.html",
|
||||
pageIds: ["logPage"],
|
||||
icon: "folder_open"
|
||||
}), links.push({
|
||||
name: globalize.translate("TabNotifications"),
|
||||
icon: "notifications",
|
||||
color: "brown",
|
||||
href: "notificationsettings.html",
|
||||
pageIds: ["notificationSettingsPage", "notificationSettingPage"]
|
||||
}), links.push({
|
||||
name: globalize.translate("TabPlugins"),
|
||||
icon: "add_shopping_cart",
|
||||
color: "#9D22B1",
|
||||
href: "plugins.html",
|
||||
pageIds: ["pluginsPage", "pluginCatalogPage"]
|
||||
}), links.push({
|
||||
name: globalize.translate("TabScheduledTasks"),
|
||||
href: "scheduledtasks.html",
|
||||
pageIds: ["scheduledTasksPage", "scheduledTaskPage"],
|
||||
icon: "schedule"
|
||||
}), links.push({
|
||||
name: globalize.translate("MetadataManager"),
|
||||
href: "edititemmetadata.html",
|
||||
pageIds: [],
|
||||
icon: "mode_edit"
|
||||
}), addPluginPagesToMainMenu(links, pluginItems), links
|
||||
}
|
||||
|
||||
function addPluginPagesToMainMenu(links, pluginItems, section) {
|
||||
for (var i = 0, length = pluginItems.length; i < length; i++) {
|
||||
var pluginItem = pluginItems[i];
|
||||
Dashboard.allowPluginPages(pluginItem.PluginId) && (pluginItem.EnableInMainMenu && pluginItem.MenuSection === section && links.push({
|
||||
name: pluginItem.DisplayName,
|
||||
icon: pluginItem.MenuIcon || "folder",
|
||||
href: Dashboard.getConfigurationPageUrl(pluginItem.Name),
|
||||
pageUrls: [Dashboard.getConfigurationPageUrl(pluginItem.Name)]
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
function getToolsMenuLinks(apiClient) {
|
||||
return apiClient.getJSON(apiClient.getUrl("web/configurationpages") + "?pageType=PluginConfiguration&EnableInMainMenu=true").then(createToolsMenuList, function(err) {
|
||||
return createToolsMenuList([])
|
||||
})
|
||||
}
|
||||
|
||||
function getToolsLinkHtml(item) {
|
||||
var menuHtml = "",
|
||||
pageIds = item.pageIds ? item.pageIds.join("|") : "";
|
||||
pageIds = pageIds ? ' data-pageids="' + pageIds + '"' : "";
|
||||
var pageUrls = item.pageUrls ? item.pageUrls.join("|") : "";
|
||||
return pageUrls = pageUrls ? ' data-pageurls="' + pageUrls + '"' : "", menuHtml += '<a is="emby-linkbutton" class="navMenuOption" href="' + item.href + '"' + pageIds + pageUrls + ">", item.icon && (menuHtml += '<i class="md-icon navMenuOptionIcon">' + item.icon + "</i>"), menuHtml += '<span class="navMenuOptionText">', menuHtml += item.name, menuHtml += "</span>", menuHtml += "</a>"
|
||||
}
|
||||
|
||||
function getToolsMenuHtml(apiClient) {
|
||||
return getToolsMenuLinks(apiClient).then(function(items) {
|
||||
var i, length, item, menuHtml = "";
|
||||
for (menuHtml += '<div class="drawerContent">', i = 0, length = items.length; i < length; i++) item = items[i], item.href ? menuHtml += getToolsLinkHtml(item) : item.name && (menuHtml += '<h3 class="sidebarHeader">', menuHtml += item.name, menuHtml += "</h3>");
|
||||
return menuHtml += "</div>"
|
||||
})
|
||||
}
|
||||
|
||||
function createDashboardMenu(apiClient) {
|
||||
return getToolsMenuHtml(apiClient).then(function(toolsMenuHtml) {
|
||||
var html = "";
|
||||
html += '<a class="adminDrawerLogo clearLink" is="emby-linkbutton" href="home.html" style="text-align:left;">', html += '<img src="css/images/logoblack.png" />', html += "</a>", html += toolsMenuHtml, navDrawerScrollContainer.innerHTML = html, updateDashboardMenuSelectedItem()
|
||||
})
|
||||
}
|
||||
|
||||
function onSidebarLinkClick() {
|
||||
var section = this.getElementsByClassName("sectionName")[0],
|
||||
text = section ? section.innerHTML : this.innerHTML;
|
||||
LibraryMenu.setTitle(text)
|
||||
}
|
||||
|
||||
function getUserViews(apiClient, userId) {
|
||||
return apiClient.getUserViews({}, userId).then(function(result) {
|
||||
for (var items = result.Items, list = [], i = 0, length = items.length; i < length; i++) {
|
||||
var view = items[i];
|
||||
if (list.push(view), "livetv" == view.CollectionType) {
|
||||
view.ImageTags = {}, view.icon = "live_tv";
|
||||
var guideView = Object.assign({}, view);
|
||||
guideView.Name = globalize.translate("ButtonGuide"), guideView.ImageTags = {}, guideView.icon = "dvr", guideView.url = "livetv.html?tab=1", list.push(guideView)
|
||||
}
|
||||
}
|
||||
return list
|
||||
})
|
||||
}
|
||||
|
||||
function showBySelector(selector, show) {
|
||||
var elem = document.querySelector(selector);
|
||||
elem && (show ? elem.classList.remove("hide") : elem.classList.add("hide"))
|
||||
}
|
||||
|
||||
function updateLibraryMenu(user) {
|
||||
if (!user) return showBySelector(".libraryMenuDownloads", !1), showBySelector(".lnkSyncToOtherDevices", !1), void showBySelector(".userMenuOptions", !1);
|
||||
user.Policy.EnableContentDownloading ? showBySelector(".lnkSyncToOtherDevices", !0) : showBySelector(".lnkSyncToOtherDevices", !1), user.Policy.EnableContentDownloading && appHost.supports("sync") ? showBySelector(".libraryMenuDownloads", !0) : showBySelector(".libraryMenuDownloads", !1);
|
||||
var userId = Dashboard.getCurrentUserId(),
|
||||
apiClient = getCurrentApiClient(),
|
||||
libraryMenuOptions = document.querySelector(".libraryMenuOptions");
|
||||
libraryMenuOptions && getUserViews(apiClient, userId).then(function(result) {
|
||||
var items = result,
|
||||
html = "";
|
||||
html += '<h3 class="sidebarHeader">', html += globalize.translate("HeaderMedia"), html += "</h3>", html += items.map(function(i) {
|
||||
var icon = "folder",
|
||||
itemId = i.Id;
|
||||
"channels" == i.CollectionType ? itemId = "channels" : "livetv" == i.CollectionType && (itemId = "livetv"), "photos" == i.CollectionType ? icon = "photo_library" : "music" == i.CollectionType || "musicvideos" == i.CollectionType ? icon = "library_music" : "books" == i.CollectionType ? icon = "library_books" : "playlists" == i.CollectionType ? icon = "view_list" : "games" == i.CollectionType ? icon = "games" : "movies" == i.CollectionType ? icon = "video_library" : "channels" == i.CollectionType || "Channel" == i.Type ? icon = "videocam" : "tvshows" == i.CollectionType ? icon = "tv" : "livetv" == i.CollectionType && (icon = "live_tv"), icon = i.icon || icon;
|
||||
i.onclick && i.onclick;
|
||||
return '<a is="emby-linkbutton" data-itemid="' + itemId + '" class="lnkMediaFolder navMenuOption" href="' + getItemHref(i, i.CollectionType) + '"><i class="md-icon navMenuOptionIcon">' + icon + '</i><span class="sectionName navMenuOptionText">' + i.Name + "</span></a>"
|
||||
}).join(""), libraryMenuOptions.innerHTML = html;
|
||||
for (var elem = libraryMenuOptions, sidebarLinks = elem.querySelectorAll(".navMenuOption"), i = 0, length = sidebarLinks.length; i < length; i++) sidebarLinks[i].removeEventListener("click", onSidebarLinkClick), sidebarLinks[i].addEventListener("click", onSidebarLinkClick)
|
||||
})
|
||||
}
|
||||
|
||||
function getTopParentId() {
|
||||
return getParameterByName("topParentId") || null
|
||||
}
|
||||
|
||||
function onMainDrawerClick(e) {
|
||||
dom.parentWithTag(e.target, "A") && setTimeout(closeMainDrawer, 30)
|
||||
}
|
||||
|
||||
function onLogoutClick() {
|
||||
Dashboard.logout()
|
||||
}
|
||||
|
||||
function updateCastIcon() {
|
||||
var context = document,
|
||||
info = playbackManager.getPlayerInfo(),
|
||||
icon = headerCastButton.querySelector("i");
|
||||
info && !info.isLocalPlayer ? (icon.innerHTML = "", headerCastButton.classList.add("castButton-active"), context.querySelector(".headerSelectedPlayer").innerHTML = info.deviceName || info.name) : (icon.innerHTML = "", headerCastButton.classList.remove("castButton-active"), context.querySelector(".headerSelectedPlayer").innerHTML = "")
|
||||
}
|
||||
|
||||
function updateLibraryNavLinks(page) {
|
||||
var i, length, isLiveTvPage = page.classList.contains("liveTvPage"),
|
||||
isChannelsPage = page.classList.contains("channelsPage"),
|
||||
isEditorPage = page.classList.contains("metadataEditorPage"),
|
||||
isMySyncPage = page.classList.contains("mySyncPage"),
|
||||
id = isLiveTvPage || isChannelsPage || isEditorPage || isMySyncPage || page.classList.contains("allLibraryPage") ? "" : getTopParentId() || "",
|
||||
elems = document.getElementsByClassName("lnkMediaFolder");
|
||||
for (i = 0, length = elems.length; i < length; i++) {
|
||||
var lnkMediaFolder = elems[i],
|
||||
itemId = lnkMediaFolder.getAttribute("data-itemid");
|
||||
isChannelsPage && "channels" == itemId ? lnkMediaFolder.classList.add("navMenuOption-selected") : isLiveTvPage && "livetv" == itemId ? lnkMediaFolder.classList.add("navMenuOption-selected") : isEditorPage && "editor" == itemId ? lnkMediaFolder.classList.add("navMenuOption-selected") : isMySyncPage && "manageoffline" == itemId && -1 != window.location.href.toString().indexOf("mode=download") ? lnkMediaFolder.classList.add("navMenuOption-selected") : isMySyncPage && "syncotherdevices" == itemId && -1 == window.location.href.toString().indexOf("mode=download") ? lnkMediaFolder.classList.add("navMenuOption-selected") : id && itemId == id ? lnkMediaFolder.classList.add("navMenuOption-selected") : lnkMediaFolder.classList.remove("navMenuOption-selected")
|
||||
}
|
||||
}
|
||||
|
||||
function updateMenuForPageType(isDashboardPage, isLibraryPage) {
|
||||
var newPageType = isDashboardPage ? 2 : isLibraryPage ? 1 : 3;
|
||||
if (currentPageType !== newPageType) {
|
||||
currentPageType = newPageType, isDashboardPage && !layoutManager.mobile ? skinHeader.classList.add("headroomDisabled") : skinHeader.classList.remove("headroomDisabled");
|
||||
var bodyClassList = document.body.classList;
|
||||
isLibraryPage ? (bodyClassList.add("libraryDocument"), bodyClassList.remove("dashboardDocument"), bodyClassList.remove("hideMainDrawer"), navDrawerInstance && navDrawerInstance.setEdgeSwipeEnabled(!0)) : isDashboardPage ? (bodyClassList.remove("libraryDocument"), bodyClassList.add("dashboardDocument"), bodyClassList.remove("hideMainDrawer"), navDrawerInstance && navDrawerInstance.setEdgeSwipeEnabled(!0)) : (bodyClassList.remove("libraryDocument"), bodyClassList.remove("dashboardDocument"), bodyClassList.add("hideMainDrawer"), navDrawerInstance && navDrawerInstance.setEdgeSwipeEnabled(!1))
|
||||
}
|
||||
requiresUserRefresh && connectionManager.user(getCurrentApiClient()).then(updateUserInHeader)
|
||||
}
|
||||
|
||||
function updateTitle(page) {
|
||||
var title = page.getAttribute("data-title");
|
||||
title ? LibraryMenu.setTitle(title) : page.classList.contains("standalonePage") && LibraryMenu.setDefaultTitle()
|
||||
}
|
||||
|
||||
function updateBackButton(page) {
|
||||
headerBackButton || (headerBackButton = document.querySelector(".headerBackButton")), headerBackButton && ("false" !== page.getAttribute("data-backbutton") && appRouter.canGoBack() ? headerBackButton.classList.remove("hide") : headerBackButton.classList.add("hide"))
|
||||
}
|
||||
|
||||
function initHeadRoom(elem) {
|
||||
require(["headroom-window"], function(headroom) {
|
||||
headroom.add(elem)
|
||||
})
|
||||
}
|
||||
|
||||
function refreshLibraryDrawer(user) {
|
||||
loadNavDrawer(), currentDrawerType = "library", (user ? Promise.resolve(user) : connectionManager.user(getCurrentApiClient())).then(function(user) {
|
||||
refreshLibraryInfoInDrawer(user), updateLibraryMenu(user.localUser)
|
||||
})
|
||||
}
|
||||
|
||||
function getNavDrawerOptions() {
|
||||
var drawerWidth = screen.availWidth - 50;
|
||||
return drawerWidth = Math.max(drawerWidth, 240), drawerWidth = Math.min(drawerWidth, 320), {
|
||||
target: navDrawerElement,
|
||||
onChange: onMainDrawerSelect,
|
||||
width: drawerWidth
|
||||
}
|
||||
}
|
||||
|
||||
function loadNavDrawer() {
|
||||
return navDrawerInstance ? Promise.resolve(navDrawerInstance) : (navDrawerElement = document.querySelector(".mainDrawer"), navDrawerScrollContainer = navDrawerElement.querySelector(".scrollContainer"), navDrawerScrollContainer.addEventListener("click", onMainDrawerClick), new Promise(function(resolve, reject) {
|
||||
require(["navdrawer"], function(navdrawer) {
|
||||
navDrawerInstance = new navdrawer(getNavDrawerOptions()), navDrawerElement.classList.remove("hide"), resolve(navDrawerInstance)
|
||||
})
|
||||
}))
|
||||
}
|
||||
var navDrawerElement, navDrawerScrollContainer, navDrawerInstance, mainDrawerButton, headerHomeButton, currentDrawerType, pageTitleElement, headerBackButton, headerUserButton, currentUser, headerSettingsButton, headerCastButton, headerSearchButton, enableLibraryNavDrawer = !layoutManager.tv,
|
||||
skinHeader = document.querySelector(".skinHeader"),
|
||||
requiresUserRefresh = !0,
|
||||
lastOpenTime = (new Date).getTime();
|
||||
window.LibraryMenu = {
|
||||
getTopParentId: getTopParentId,
|
||||
onHardwareMenuButtonClick: function() {
|
||||
toggleMainDrawer()
|
||||
},
|
||||
setTabs: function(type, selectedIndex, builder) {
|
||||
require(["mainTabsManager"], function(mainTabsManager) {
|
||||
type ? mainTabsManager.setTabs(viewManager.currentView(), selectedIndex, builder, function() {
|
||||
return []
|
||||
}) : mainTabsManager.setTabs(null)
|
||||
})
|
||||
},
|
||||
setDefaultTitle: function() {
|
||||
pageTitleElement || (pageTitleElement = document.querySelector(".pageTitle")), pageTitleElement && (pageTitleElement.classList.add("pageTitleWithLogo"), pageTitleElement.classList.add("pageTitleWithDefaultLogo"), pageTitleElement.style.backgroundImage = null, pageTitleElement.innerHTML = ""), document.title = "Jellyfin"
|
||||
},
|
||||
setTitle: function(title) {
|
||||
if (null == title) return void LibraryMenu.setDefaultTitle();
|
||||
"-" === title && (title = "");
|
||||
var html = title;
|
||||
pageTitleElement || (pageTitleElement = document.querySelector(".pageTitle")), pageTitleElement && (pageTitleElement.classList.remove("pageTitleWithLogo"), pageTitleElement.classList.remove("pageTitleWithDefaultLogo"), pageTitleElement.style.backgroundImage = null, pageTitleElement.innerHTML = html || ""), document.title = title || "Jellyfin"
|
||||
},
|
||||
setTransparentMenu: function(transparent) {
|
||||
transparent ? skinHeader.classList.add("semiTransparent") : skinHeader.classList.remove("semiTransparent")
|
||||
}
|
||||
};
|
||||
var currentPageType;
|
||||
return pageClassOn("pagebeforeshow", "page", function(e) {
|
||||
this.classList.contains("withTabs") || LibraryMenu.setTabs(null)
|
||||
}), pageClassOn("pageshow", "page", function(e) {
|
||||
var page = this,
|
||||
isDashboardPage = page.classList.contains("type-interior"),
|
||||
isLibraryPage = !isDashboardPage && page.classList.contains("libraryPage"),
|
||||
apiClient = getCurrentApiClient();
|
||||
isDashboardPage ? (mainDrawerButton && mainDrawerButton.classList.remove("hide"), refreshDashboardInfoInDrawer(apiClient)) : (mainDrawerButton && (enableLibraryNavDrawer ? mainDrawerButton.classList.remove("hide") : mainDrawerButton.classList.add("hide")), "library" !== currentDrawerType && refreshLibraryDrawer()), updateMenuForPageType(isDashboardPage, isLibraryPage), e.detail.isRestored || window.scrollTo(0, 0), updateTitle(page), updateBackButton(page), updateLibraryNavLinks(page)
|
||||
}),
|
||||
function() {
|
||||
var html = "";
|
||||
html += '<div class="flex align-items-center flex-grow headerTop">', html += '<div class="headerLeft">', html += '<button type="button" is="paper-icon-button-light" class="headerButton headerButtonLeft headerBackButton hide"><i class="md-icon">' + (browser.safari ? "chevron_left" : "") + "</i></button>", html += '<button type="button" is="paper-icon-button-light" class="headerButton headerHomeButton hide barsMenuButton headerButtonLeft"><i class="md-icon"></i></button>', html += '<button type="button" is="paper-icon-button-light" class="headerButton mainDrawerButton barsMenuButton headerButtonLeft hide"><i class="md-icon"></i></button>', html += '<h3 class="pageTitle"></h3>', html += "</div>", html += '<div class="headerRight">', html += '<span class="headerSelectedPlayer"></span>', html += '<button is="paper-icon-button-light" class="headerCastButton castButton headerButton headerButtonRight hide"><i class="md-icon"></i></button>', html += '<button type="button" is="paper-icon-button-light" class="headerButton headerButtonRight headerSearchButton hide"><i class="md-icon"></i></button>', html += '<button is="paper-icon-button-light" class="headerButton headerButtonRight headerUserButton hide"><i class="md-icon"></i></button>', layoutManager.mobile || (html += '<button is="paper-icon-button-light" class="headerButton headerButtonRight headerSettingsButton hide"><i class="md-icon"></i></button>'), html += "</div>", html += "</div>", html += '<div class="headerTabs sectionTabs hide">', html += "</div>", skinHeader.classList.add("skinHeader-withBackground"), skinHeader.innerHTML = html, headerHomeButton = skinHeader.querySelector(".headerHomeButton"), headerUserButton = skinHeader.querySelector(".headerUserButton"), headerSettingsButton = skinHeader.querySelector(".headerSettingsButton"), headerCastButton = skinHeader.querySelector(".headerCastButton"), headerSearchButton = skinHeader.querySelector(".headerSearchButton"), browser.chrome || skinHeader.classList.add("skinHeader-blurred"), lazyLoadViewMenuBarImages(), bindMenuEvents()
|
||||
}(), events.on(connectionManager, "localusersignedin", function(e, user) {
|
||||
currentDrawerType = null, currentUser = {
|
||||
localUser: user
|
||||
}, loadNavDrawer(), connectionManager.user(connectionManager.getApiClient(user.ServerId)).then(function(user) {
|
||||
currentUser = user, updateUserInHeader(user)
|
||||
})
|
||||
}), events.on(connectionManager, "localusersignedout", function() {
|
||||
currentUser = {}, updateUserInHeader()
|
||||
}), events.on(playbackManager, "playerchange", updateCastIcon), loadNavDrawer(), LibraryMenu
|
||||
});
|
||||
@@ -0,0 +1,84 @@
|
||||
define(["cardBuilder", "imageLoader", "libraryBrowser", "loading", "events", "emby-itemscontainer"], function(cardBuilder, imageLoader, libraryBrowser, loading, events) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData() {
|
||||
return pageData || (pageData = {
|
||||
query: {
|
||||
StartIndex: 0,
|
||||
Limit: 100,
|
||||
Fields: "PrimaryImageAspectRatio"
|
||||
}
|
||||
}), pageData
|
||||
}
|
||||
|
||||
function getQuery() {
|
||||
return getPageData().query
|
||||
}
|
||||
|
||||
function getChannelsHtml(channels) {
|
||||
return cardBuilder.getCardsHtml({
|
||||
items: channels,
|
||||
shape: "square",
|
||||
showTitle: !0,
|
||||
lazy: !0,
|
||||
cardLayout: !0,
|
||||
showDetailsMenu: !0,
|
||||
showCurrentProgram: !0,
|
||||
showCurrentProgramTime: !0
|
||||
})
|
||||
}
|
||||
|
||||
function renderChannels(context, result) {
|
||||
function onNextPageClick() {
|
||||
query.StartIndex += query.Limit, reloadItems(context)
|
||||
}
|
||||
|
||||
function onPreviousPageClick() {
|
||||
query.StartIndex -= query.Limit, reloadItems(context)
|
||||
}
|
||||
var query = getQuery();
|
||||
context.querySelector(".paging").innerHTML = libraryBrowser.getQueryPagingHtml({
|
||||
startIndex: query.StartIndex,
|
||||
limit: query.Limit,
|
||||
totalRecordCount: result.TotalRecordCount,
|
||||
showLimit: !1,
|
||||
updatePageSizeSetting: !1,
|
||||
filterButton: !1
|
||||
});
|
||||
var html = getChannelsHtml(result.Items),
|
||||
elem = context.querySelector("#items");
|
||||
elem.innerHTML = html, imageLoader.lazyChildren(elem);
|
||||
var i, length, elems;
|
||||
for (elems = context.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick);
|
||||
for (elems = context.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick)
|
||||
}
|
||||
|
||||
function showFilterMenu(context) {
|
||||
require(["components/filterdialog/filterdialog"], function(filterDialogFactory) {
|
||||
var filterDialog = new filterDialogFactory({
|
||||
query: getQuery(),
|
||||
mode: "livetvchannels",
|
||||
serverId: ApiClient.serverId()
|
||||
});
|
||||
events.on(filterDialog, "filterchange", function() {
|
||||
reloadItems(context)
|
||||
}), filterDialog.show()
|
||||
})
|
||||
}
|
||||
|
||||
function reloadItems(context, save) {
|
||||
loading.show();
|
||||
var query = getQuery(),
|
||||
apiClient = ApiClient;
|
||||
query.UserId = apiClient.getCurrentUserId(), apiClient.getLiveTvChannels(query).then(function(result) {
|
||||
renderChannels(context, result), loading.hide()
|
||||
})
|
||||
}
|
||||
var pageData, self = this;
|
||||
tabContent.querySelector(".btnFilter").addEventListener("click", function() {
|
||||
showFilterMenu(tabContent)
|
||||
}), self.renderTab = function() {
|
||||
reloadItems(tabContent)
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
define(["layoutManager", "datetime", "cardBuilder", "apphost"], function(layoutManager, datetime, cardBuilder, appHost) {
|
||||
"use strict";
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop
|
||||
}
|
||||
|
||||
function getBackdropShape() {
|
||||
return enableScrollX() ? "overflowBackdrop" : "backdrop"
|
||||
}
|
||||
|
||||
function getTimersHtml(timers, options) {
|
||||
options = options || {};
|
||||
var i, length, items = timers.map(function(t) {
|
||||
return t.Type = "Timer", t
|
||||
}),
|
||||
groups = [],
|
||||
currentGroupName = "",
|
||||
currentGroup = [];
|
||||
for (i = 0, length = items.length; i < length; i++) {
|
||||
var item = items[i],
|
||||
dateText = "";
|
||||
if (!1 !== options.indexByDate && item.StartDate) try {
|
||||
var premiereDate = datetime.parseISO8601Date(item.StartDate, !0);
|
||||
dateText = datetime.toLocaleDateString(premiereDate, {
|
||||
weekday: "long",
|
||||
month: "short",
|
||||
day: "numeric"
|
||||
})
|
||||
} catch (err) {}
|
||||
dateText != currentGroupName ? (currentGroup.length && groups.push({
|
||||
name: currentGroupName,
|
||||
items: currentGroup
|
||||
}), currentGroupName = dateText, currentGroup = [item]) : currentGroup.push(item)
|
||||
}
|
||||
currentGroup.length && groups.push({
|
||||
name: currentGroupName,
|
||||
items: currentGroup
|
||||
});
|
||||
var html = "";
|
||||
for (i = 0, length = groups.length; i < length; i++) {
|
||||
var group = groups[i],
|
||||
supportsImageAnalysis = appHost.supports("imageanalysis"),
|
||||
cardLayout = appHost.preferVisualCards || supportsImageAnalysis;
|
||||
if (cardLayout = !0, group.name && (html += '<div class="verticalSection">', html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + group.name + "</h2>"), enableScrollX()) {
|
||||
var scrollXClass = "scrollX hiddenScrollX";
|
||||
layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '<div is="emby-itemscontainer" class="itemsContainer ' + scrollXClass + ' padded-left padded-right">'
|
||||
} else html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right">';
|
||||
html += cardBuilder.getCardsHtml({
|
||||
items: group.items,
|
||||
shape: cardLayout ? getBackdropShape() : enableScrollX() ? "autoOverflow" : "autoVertical",
|
||||
showParentTitleOrTitle: !0,
|
||||
showAirTime: !0,
|
||||
showAirEndTime: !0,
|
||||
showChannelName: !cardLayout,
|
||||
cardLayout: cardLayout,
|
||||
centerText: !cardLayout,
|
||||
action: "edit",
|
||||
cardFooterAside: "none",
|
||||
preferThumb: !!cardLayout || "auto",
|
||||
defaultShape: cardLayout ? null : "portrait",
|
||||
coverImage: !0,
|
||||
allowBottomPadding: !1,
|
||||
overlayText: !1,
|
||||
showChannelLogo: cardLayout
|
||||
}), html += "</div>", group.name && (html += "</div>")
|
||||
}
|
||||
return Promise.resolve(html)
|
||||
}
|
||||
window.LiveTvHelpers = {
|
||||
getTimersHtml: getTimersHtml
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
define(["tvguide"], function(tvguide) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
var guideInstance, self = this;
|
||||
self.renderTab = function() {
|
||||
guideInstance || (guideInstance = new tvguide({
|
||||
element: tabContent,
|
||||
serverId: ApiClient.serverId()
|
||||
}))
|
||||
}, self.onShow = function() {
|
||||
guideInstance && guideInstance.resume()
|
||||
}, self.onHide = function() {
|
||||
guideInstance && guideInstance.pause()
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
define(["events", "loading"], function(events, loading) {
|
||||
"use strict";
|
||||
|
||||
function onListingsSubmitted() {
|
||||
Dashboard.navigate("livetvstatus.html")
|
||||
}
|
||||
|
||||
function init(page, type, providerId) {
|
||||
var url = "components/tvproviders/" + type + ".js";
|
||||
require([url], function(factory) {
|
||||
var instance = new factory(page, providerId, {});
|
||||
events.on(instance, "submitted", onListingsSubmitted), instance.init()
|
||||
})
|
||||
}
|
||||
|
||||
function loadTemplate(page, type, providerId) {
|
||||
require(["text!./components/tvproviders/" + type + ".template.html"], function(html) {
|
||||
page.querySelector(".providerTemplate").innerHTML = Globalize.translateDocument(html), init(page, type, providerId)
|
||||
})
|
||||
}
|
||||
pageIdOn("pageshow", "liveTvGuideProviderPage", function() {
|
||||
loading.show();
|
||||
var providerId = getParameterByName("id");
|
||||
loadTemplate(this, getParameterByName("type"), providerId)
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
define(["layoutManager", "loading", "components/categorysyncbuttons", "cardBuilder", "apphost", "imageLoader", "scripts/livetvcomponents", "listViewStyle", "emby-itemscontainer"], function(layoutManager, loading, categorysyncbuttons, cardBuilder, appHost, imageLoader) {
|
||||
"use strict";
|
||||
|
||||
function renderRecordings(elem, recordings, cardOptions, scrollX) {
|
||||
recordings.length ? elem.classList.remove("hide") : elem.classList.add("hide");
|
||||
var recordingItems = elem.querySelector(".recordingItems");
|
||||
scrollX ? (recordingItems.classList.add("scrollX"), recordingItems.classList.add("hiddenScrollX"), recordingItems.classList.remove("vertical-wrap")) : (recordingItems.classList.remove("scrollX"), recordingItems.classList.remove("hiddenScrollX"), recordingItems.classList.add("vertical-wrap"));
|
||||
appHost.supports("imageanalysis");
|
||||
recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({
|
||||
items: recordings,
|
||||
shape: scrollX ? "autooverflow" : "auto",
|
||||
defaultShape: scrollX ? "overflowBackdrop" : "backdrop",
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
coverImage: !0,
|
||||
cardLayout: !1,
|
||||
centerText: !0,
|
||||
vibrant: !1,
|
||||
allowBottomPadding: !scrollX,
|
||||
preferThumb: "auto",
|
||||
overlayText: !1
|
||||
}, cardOptions || {})), imageLoader.lazyChildren(recordingItems)
|
||||
}
|
||||
|
||||
function renderLatestRecordings(context, promise) {
|
||||
promise.then(function(result) {
|
||||
renderRecordings(context.querySelector("#latestRecordings"), result.Items, {
|
||||
showYear: !0,
|
||||
lines: 2
|
||||
}, !1), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function renderRecordingFolders(context, promise) {
|
||||
promise.then(function(result) {
|
||||
renderRecordings(context.querySelector("#recordingFolders"), result.Items, {
|
||||
showYear: !1,
|
||||
showParentTitle: !1
|
||||
}, !1)
|
||||
})
|
||||
}
|
||||
|
||||
function onMoreClick(e) {
|
||||
var type = this.getAttribute("data-type"),
|
||||
serverId = ApiClient.serverId();
|
||||
switch (type) {
|
||||
case "latest":
|
||||
Dashboard.navigate("list/list.html?type=Recordings&serverId=" + serverId)
|
||||
}
|
||||
}
|
||||
return function(view, params, tabContent) {
|
||||
function enableFullRender() {
|
||||
return (new Date).getTime() - lastFullRender > 3e5
|
||||
}
|
||||
var foldersPromise, latestPromise, self = this,
|
||||
lastFullRender = 0;
|
||||
categorysyncbuttons.init(tabContent);
|
||||
for (var moreButtons = tabContent.querySelectorAll(".more"), i = 0, length = moreButtons.length; i < length; i++) moreButtons[i].addEventListener("click", onMoreClick);
|
||||
self.preRender = function() {
|
||||
enableFullRender() && (latestPromise = ApiClient.getLiveTvRecordings({
|
||||
UserId: Dashboard.getCurrentUserId(),
|
||||
Limit: 12,
|
||||
Fields: "CanDelete,PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
EnableTotalRecordCount: !1,
|
||||
EnableImageTypes: "Primary,Thumb,Backdrop"
|
||||
}), foldersPromise = ApiClient.getRecordingFolders(Dashboard.getCurrentUserId()))
|
||||
}, self.renderTab = function() {
|
||||
enableFullRender() && (loading.show(), renderLatestRecordings(tabContent, latestPromise), renderRecordingFolders(tabContent, foldersPromise), lastFullRender = (new Date).getTime())
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
define(["layoutManager", "cardBuilder", "apphost", "imageLoader", "loading", "scripts/livetvcomponents", "emby-button", "emby-itemscontainer"], function(layoutManager, cardBuilder, appHost, imageLoader, loading) {
|
||||
"use strict";
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop
|
||||
}
|
||||
|
||||
function renderRecordings(elem, recordings, cardOptions) {
|
||||
recordings.length ? elem.classList.remove("hide") : elem.classList.add("hide");
|
||||
var recordingItems = elem.querySelector(".recordingItems");
|
||||
enableScrollX() ? (recordingItems.classList.add("scrollX"), layoutManager.tv && recordingItems.classList.add("smoothScrollX"), recordingItems.classList.add("hiddenScrollX"), recordingItems.classList.remove("vertical-wrap")) : (recordingItems.classList.remove("scrollX"), recordingItems.classList.remove("smoothScrollX"), recordingItems.classList.remove("hiddenScrollX"), recordingItems.classList.add("vertical-wrap"));
|
||||
var supportsImageAnalysis = appHost.supports("imageanalysis"),
|
||||
cardLayout = appHost.preferVisualCards || supportsImageAnalysis;
|
||||
cardLayout = !1, recordingItems.innerHTML = cardBuilder.getCardsHtml(Object.assign({
|
||||
items: recordings,
|
||||
shape: enableScrollX() ? "autooverflow" : "auto",
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
coverImage: !0,
|
||||
cardLayout: cardLayout,
|
||||
centerText: !cardLayout,
|
||||
vibrant: cardLayout && supportsImageAnalysis,
|
||||
allowBottomPadding: !enableScrollX(),
|
||||
preferThumb: "auto"
|
||||
}, cardOptions || {})), imageLoader.lazyChildren(recordingItems)
|
||||
}
|
||||
|
||||
function getBackdropShape() {
|
||||
return enableScrollX() ? "overflowBackdrop" : "backdrop"
|
||||
}
|
||||
|
||||
function renderActiveRecordings(context, promise) {
|
||||
promise.then(function(result) {
|
||||
renderRecordings(context.querySelector("#activeRecordings"), result.Items, {
|
||||
shape: enableScrollX() ? "autooverflow" : "auto",
|
||||
defaultShape: getBackdropShape(),
|
||||
showParentTitle: !1,
|
||||
showParentTitleOrTitle: !0,
|
||||
showTitle: !1,
|
||||
showAirTime: !0,
|
||||
showAirEndTime: !0,
|
||||
showChannelName: !0,
|
||||
coverImage: !0,
|
||||
overlayText: !1,
|
||||
overlayMoreButton: !0
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function renderTimers(context, timers, options) {
|
||||
LiveTvHelpers.getTimersHtml(timers, options).then(function(html) {
|
||||
var elem = context;
|
||||
html ? elem.classList.remove("hide") : elem.classList.add("hide"), elem.querySelector(".recordingItems").innerHTML = html, imageLoader.lazyChildren(elem)
|
||||
})
|
||||
}
|
||||
|
||||
function renderUpcomingRecordings(context, promise) {
|
||||
promise.then(function(result) {
|
||||
renderTimers(context.querySelector("#upcomingRecordings"), result.Items), loading.hide()
|
||||
})
|
||||
}
|
||||
return function(view, params, tabContent) {
|
||||
var activeRecordingsPromise, upcomingRecordingsPromise, self = this;
|
||||
tabContent.querySelector("#upcomingRecordings .recordingItems").addEventListener("timercancelled", function() {
|
||||
self.preRender(), self.renderTab()
|
||||
}), self.preRender = function() {
|
||||
activeRecordingsPromise = ApiClient.getLiveTvRecordings({
|
||||
UserId: Dashboard.getCurrentUserId(),
|
||||
IsInProgress: !0,
|
||||
Fields: "CanDelete,PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
EnableTotalRecordCount: !1,
|
||||
EnableImageTypes: "Primary,Thumb,Backdrop"
|
||||
}), upcomingRecordingsPromise = ApiClient.getLiveTvTimers({
|
||||
IsActive: !1,
|
||||
IsScheduled: !0
|
||||
})
|
||||
}, self.renderTab = function() {
|
||||
loading.show(), renderActiveRecordings(tabContent, activeRecordingsPromise), renderUpcomingRecordings(tabContent, upcomingRecordingsPromise)
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,79 @@
|
||||
define(["jQuery", "loading", "fnchecked", "emby-linkbutton"], function($, loading) {
|
||||
"use strict";
|
||||
|
||||
function loadPage(page, config) {
|
||||
$(".liveTvSettingsForm", page).show(), $(".noLiveTvServices", page).hide(), $("#selectGuideDays", page).val(config.GuideDays || ""), $("#txtPrePaddingMinutes", page).val(config.PrePaddingSeconds / 60), $("#txtPostPaddingMinutes", page).val(config.PostPaddingSeconds / 60), page.querySelector("#txtRecordingPath").value = config.RecordingPath || "", page.querySelector("#txtMovieRecordingPath").value = config.MovieRecordingPath || "", page.querySelector("#txtSeriesRecordingPath").value = config.SeriesRecordingPath || "", page.querySelector("#txtPostProcessor").value = config.RecordingPostProcessor || "", page.querySelector("#txtPostProcessorArguments").value = config.RecordingPostProcessorArguments || "", loading.hide()
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
loading.show();
|
||||
var form = this;
|
||||
return ApiClient.getNamedConfiguration("livetv").then(function(config) {
|
||||
config.GuideDays = $("#selectGuideDays", form).val() || null;
|
||||
var recordingPath = form.querySelector("#txtRecordingPath").value || null,
|
||||
movieRecordingPath = form.querySelector("#txtMovieRecordingPath").value || null,
|
||||
seriesRecordingPath = form.querySelector("#txtSeriesRecordingPath").value || null,
|
||||
recordingPathChanged = recordingPath != config.RecordingPath || movieRecordingPath != config.MovieRecordingPath || seriesRecordingPath != config.SeriesRecordingPath;
|
||||
config.RecordingPath = recordingPath, config.MovieRecordingPath = movieRecordingPath, config.SeriesRecordingPath = seriesRecordingPath, config.RecordingEncodingFormat = "mkv", config.PrePaddingSeconds = 60 * $("#txtPrePaddingMinutes", form).val(), config.PostPaddingSeconds = 60 * $("#txtPostPaddingMinutes", form).val(), config.RecordingPostProcessor = $("#txtPostProcessor", form).val(), config.RecordingPostProcessorArguments = $("#txtPostProcessorArguments", form).val(), ApiClient.updateNamedConfiguration("livetv", config).then(function() {
|
||||
Dashboard.processServerConfigurationUpdateResult(), showSaveMessage(recordingPathChanged)
|
||||
})
|
||||
}), !1
|
||||
}
|
||||
|
||||
function showSaveMessage(recordingPathChanged) {
|
||||
var msg = "";
|
||||
recordingPathChanged && (msg += Globalize.translate("RecordingPathChangeMessage")), msg && require(["alert"], function(alert) {
|
||||
alert(msg)
|
||||
})
|
||||
}
|
||||
$(document).on("pageinit", "#liveTvSettingsPage", function() {
|
||||
var page = this;
|
||||
$(".liveTvSettingsForm").off("submit", onSubmit).on("submit", onSubmit), $("#btnSelectRecordingPath", page).on("click.selectDirectory", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
callback: function(path) {
|
||||
path && $("#txtRecordingPath", page).val(path), picker.close()
|
||||
},
|
||||
validateWriteable: !0
|
||||
})
|
||||
})
|
||||
}), $("#btnSelectMovieRecordingPath", page).on("click.selectDirectory", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
callback: function(path) {
|
||||
path && $("#txtMovieRecordingPath", page).val(path), picker.close()
|
||||
},
|
||||
validateWriteable: !0
|
||||
})
|
||||
})
|
||||
}), $("#btnSelectSeriesRecordingPath", page).on("click.selectDirectory", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
callback: function(path) {
|
||||
path && $("#txtSeriesRecordingPath", page).val(path), picker.close()
|
||||
},
|
||||
validateWriteable: !0
|
||||
})
|
||||
})
|
||||
}), $("#btnSelectPostProcessorPath", page).on("click.selectDirectory", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
includeFiles: !0,
|
||||
callback: function(path) {
|
||||
path && $("#txtPostProcessor", page).val(path), picker.close()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}).on("pageshow", "#liveTvSettingsPage", function() {
|
||||
loading.show();
|
||||
var page = this;
|
||||
ApiClient.getNamedConfiguration("livetv").then(function(config) {
|
||||
loadPage(page, config)
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,260 @@
|
||||
define(["jQuery", "globalize", "scripts/taskbutton", "dom", "libraryMenu", "layoutManager", "loading", "listViewStyle", "flexStyles", "emby-itemscontainer", "cardStyle", "material-icons", "emby-linkbutton"], function($, globalize, taskButton, dom, libraryMenu, layoutManager, loading) {
|
||||
"use strict";
|
||||
|
||||
function getDeviceHtml(device) {
|
||||
var padderClass, html = "",
|
||||
cssClass = "card scalableCard",
|
||||
cardBoxCssClass = "cardBox visualCardBox";
|
||||
return cssClass += " backdropCard backdropCard-scalable", padderClass = "cardPadder-backdrop", layoutManager.tv && (cssClass += " card-focusscale", cardBoxCssClass += " cardBox-focustransform"), cardBoxCssClass += " card-focuscontent", html += '<div type="button" class="' + cssClass + '" data-id="' + device.Id + '">', html += '<div class="' + cardBoxCssClass + '">', html += '<div class="cardScalable visualCardBox-cardScalable">', html += '<div class="' + padderClass + '"></div>', html += '<div class="cardContent searchImage">', html += '<div class="cardImageContainer coveredImage"><i class="cardImageIcon md-icon">dvr</i></div>', html += "</div>", html += "</div>", html += '<div class="cardFooter visualCardBox-cardFooter">', html += '<button is="paper-icon-button-light" class="itemAction btnCardOptions autoSize" data-action="menu"><i class="md-icon">more_horiz</i></button>', html += '<div class="cardText">' + (device.FriendlyName || getTunerName(device.Type)) + "</div>", html += '<div class="cardText cardText-secondary">', html += device.Url || " ", html += "</div>", html += "</div>", html += "</div>", html += "</div>"
|
||||
}
|
||||
|
||||
function renderDevices(page, devices) {
|
||||
var html = devices.map(getDeviceHtml).join("");
|
||||
page.querySelector(".devicesList").innerHTML = html
|
||||
}
|
||||
|
||||
function deleteDevice(page, id) {
|
||||
var message = globalize.translate("MessageConfirmDeleteTunerDevice");
|
||||
require(["confirm"], function(confirm) {
|
||||
confirm(message, globalize.translate("HeaderDeleteDevice")).then(function() {
|
||||
loading.show(), ApiClient.ajax({
|
||||
type: "DELETE",
|
||||
url: ApiClient.getUrl("LiveTv/TunerHosts", {
|
||||
Id: id
|
||||
})
|
||||
}).then(function() {
|
||||
reload(page)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function reload(page) {
|
||||
loading.show(), ApiClient.getNamedConfiguration("livetv").then(function(config) {
|
||||
renderDevices(page, config.TunerHosts), renderProviders(page, config.ListingProviders)
|
||||
}), loading.hide()
|
||||
}
|
||||
|
||||
function submitAddDeviceForm(page) {
|
||||
page.querySelector(".dlgAddDevice").close(), loading.show(), ApiClient.ajax({
|
||||
type: "POST",
|
||||
url: ApiClient.getUrl("LiveTv/TunerHosts"),
|
||||
data: JSON.stringify({
|
||||
Type: $("#selectTunerDeviceType", page).val(),
|
||||
Url: $("#txtDevicePath", page).val()
|
||||
}),
|
||||
contentType: "application/json"
|
||||
}).then(function() {
|
||||
reload(page)
|
||||
}, function() {
|
||||
Dashboard.alert({
|
||||
message: globalize.translate("ErrorAddingTunerDevice")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function renderProviders(page, providers) {
|
||||
var html = "";
|
||||
if (providers.length) {
|
||||
html += '<div class="paperList">';
|
||||
for (var i = 0, length = providers.length; i < length; i++) {
|
||||
var provider = providers[i];
|
||||
html += '<div class="listItem">', html += '<i class="listItemIcon md-icon">dvr</i>', html += '<div class="listItemBody two-line">', html += '<a is="emby-linkbutton" style="display:block;padding:0;margin:0;text-align:left;" class="clearLink" href="' + getProviderConfigurationUrl(provider.Type) + "&id=" + provider.Id + '">', html += '<h3 class="listItemBodyText">', html += getProviderName(provider.Type), html += "</h3>", html += '<div class="listItemBodyText secondary">', html += provider.Path || provider.ListingsId || "", html += "</div>", html += "</a>", html += "</div>", html += '<button type="button" is="paper-icon-button-light" class="btnOptions" data-id="' + provider.Id + '"><i class="md-icon listItemAside">more_horiz</i></button>', html += "</div>"
|
||||
}
|
||||
html += "</div>"
|
||||
}
|
||||
var elem = $(".providerList", page).html(html);
|
||||
$(".btnOptions", elem).on("click", function() {
|
||||
var id = this.getAttribute("data-id");
|
||||
showProviderOptions(page, id, this)
|
||||
})
|
||||
}
|
||||
|
||||
function showProviderOptions(page, providerId, button) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: globalize.translate("ButtonDelete"),
|
||||
id: "delete"
|
||||
}), items.push({
|
||||
name: globalize.translate("MapChannels"),
|
||||
id: "map"
|
||||
}), require(["actionsheet"], function(actionsheet) {
|
||||
actionsheet.show({
|
||||
items: items,
|
||||
positionTo: button
|
||||
}).then(function(id) {
|
||||
switch (id) {
|
||||
case "delete":
|
||||
deleteProvider(page, providerId);
|
||||
break;
|
||||
case "map":
|
||||
mapChannels(page, providerId)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function mapChannels(page, providerId) {
|
||||
require(["components/channelmapper/channelmapper"], function(channelmapper) {
|
||||
new channelmapper({
|
||||
serverId: ApiClient.serverInfo().Id,
|
||||
providerId: providerId
|
||||
}).show()
|
||||
})
|
||||
}
|
||||
|
||||
function deleteProvider(page, id) {
|
||||
var message = globalize.translate("MessageConfirmDeleteGuideProvider");
|
||||
require(["confirm"], function(confirm) {
|
||||
confirm(message, globalize.translate("HeaderDeleteProvider")).then(function() {
|
||||
loading.show(), ApiClient.ajax({
|
||||
type: "DELETE",
|
||||
url: ApiClient.getUrl("LiveTv/ListingProviders", {
|
||||
Id: id
|
||||
})
|
||||
}).then(function() {
|
||||
reload(page)
|
||||
}, function() {
|
||||
reload(page)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getTunerName(providerId) {
|
||||
switch (providerId = providerId.toLowerCase()) {
|
||||
case "m3u":
|
||||
return "M3U";
|
||||
case "hdhomerun":
|
||||
return "HDHomerun";
|
||||
case "hauppauge":
|
||||
return "Hauppauge";
|
||||
case "satip":
|
||||
return "DVB";
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
function getProviderName(providerId) {
|
||||
switch (providerId = providerId.toLowerCase()) {
|
||||
case "schedulesdirect":
|
||||
return "Schedules Direct";
|
||||
case "xmltv":
|
||||
return "Xml TV";
|
||||
case "emby":
|
||||
return "Emby Guide";
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
function getProviderConfigurationUrl(providerId) {
|
||||
switch (providerId = providerId.toLowerCase()) {
|
||||
case "xmltv":
|
||||
return "livetvguideprovider.html?type=xmltv";
|
||||
case "schedulesdirect":
|
||||
return "livetvguideprovider.html?type=schedulesdirect";
|
||||
case "emby":
|
||||
return "livetvguideprovider.html?type=emby"
|
||||
}
|
||||
}
|
||||
|
||||
function addProvider(button) {
|
||||
var menuItems = [];
|
||||
menuItems.push({
|
||||
name: "Schedules Direct",
|
||||
id: "SchedulesDirect"
|
||||
}), menuItems.push({
|
||||
name: "Xml TV",
|
||||
id: "xmltv"
|
||||
}), menuItems.push({
|
||||
name: globalize.translate("ButtonOther"),
|
||||
id: "other"
|
||||
}), require(["actionsheet"], function(actionsheet) {
|
||||
actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: button,
|
||||
callback: function(id) {
|
||||
"other" == id ? Dashboard.alert({
|
||||
message: globalize.translate("ForAdditionalLiveTvOptions")
|
||||
}) : Dashboard.navigate(getProviderConfigurationUrl(id))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function addDevice(button) {
|
||||
Dashboard.navigate("livetvtuner.html")
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "livetvstatus.html",
|
||||
name: globalize.translate("TabDevices")
|
||||
}, {
|
||||
href: "appservices.html?context=livetv",
|
||||
name: globalize.translate("TabServices")
|
||||
}]
|
||||
}
|
||||
|
||||
function showDeviceMenu(button, tunerDeviceId) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: globalize.translate("ButtonDelete"),
|
||||
id: "delete"
|
||||
}), items.push({
|
||||
name: globalize.translate("ButtonEdit"),
|
||||
id: "edit"
|
||||
}), require(["actionsheet"], function(actionsheet) {
|
||||
actionsheet.show({
|
||||
items: items,
|
||||
positionTo: button
|
||||
}).then(function(id) {
|
||||
switch (id) {
|
||||
case "delete":
|
||||
deleteDevice(dom.parentWithClass(button, "page"), tunerDeviceId);
|
||||
break;
|
||||
case "edit":
|
||||
Dashboard.navigate("livetvtuner.html?id=" + tunerDeviceId)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onDevicesListClick(e) {
|
||||
var card = dom.parentWithClass(e.target, "card");
|
||||
if (card) {
|
||||
var id = card.getAttribute("data-id"),
|
||||
btnCardOptions = dom.parentWithClass(e.target, "btnCardOptions");
|
||||
btnCardOptions ? showDeviceMenu(btnCardOptions, id) : Dashboard.navigate("livetvtuner.html?id=" + id)
|
||||
}
|
||||
}
|
||||
$(document).on("pageinit", "#liveTvStatusPage", function() {
|
||||
var page = this;
|
||||
$(".btnAddDevice", page).on("click", function() {
|
||||
addDevice(this)
|
||||
}), $(".formAddDevice", page).on("submit", function() {
|
||||
return submitAddDeviceForm(page), !1
|
||||
}), $(".btnAddProvider", page).on("click", function() {
|
||||
addProvider(this)
|
||||
}), page.querySelector(".devicesList").addEventListener("click", onDevicesListClick)
|
||||
}).on("pageshow", "#liveTvStatusPage", function() {
|
||||
libraryMenu.setTabs("livetvadmin", 0, getTabs);
|
||||
var page = this;
|
||||
reload(page), taskButton({
|
||||
mode: "on",
|
||||
progressElem: page.querySelector(".refreshGuideProgress"),
|
||||
taskKey: "RefreshGuide",
|
||||
button: page.querySelector(".btnRefresh")
|
||||
})
|
||||
}).on("pagehide", "#liveTvStatusPage", function() {
|
||||
var page = this;
|
||||
taskButton({
|
||||
mode: "off",
|
||||
progressElem: page.querySelector(".refreshGuideProgress"),
|
||||
taskKey: "RefreshGuide",
|
||||
button: page.querySelector(".btnRefresh")
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,273 @@
|
||||
define(["layoutManager", "userSettings", "inputManager", "loading", "registrationServices", "globalize", "libraryBrowser", "mainTabsManager", "cardBuilder", "apphost", "imageLoader", "scrollStyles", "emby-itemscontainer", "emby-tabs", "emby-button"], function(layoutManager, userSettings, inputManager, loading, registrationServices, globalize, libraryBrowser, mainTabsManager, cardBuilder, appHost, imageLoader) {
|
||||
"use strict";
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop
|
||||
}
|
||||
|
||||
function getBackdropShape() {
|
||||
return enableScrollX() ? "overflowBackdrop" : "backdrop"
|
||||
}
|
||||
|
||||
function getPortraitShape() {
|
||||
return enableScrollX() ? "overflowPortrait" : "portrait"
|
||||
}
|
||||
|
||||
function getLimit() {
|
||||
return enableScrollX() ? 12 : 9
|
||||
}
|
||||
|
||||
function loadRecommendedPrograms(page) {
|
||||
loading.show();
|
||||
var limit = getLimit();
|
||||
enableScrollX() && (limit *= 2), ApiClient.getLiveTvRecommendedPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
IsAiring: !0,
|
||||
limit: limit,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Thumb,Backdrop",
|
||||
EnableTotalRecordCount: !1,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio"
|
||||
}).then(function(result) {
|
||||
renderItems(page, result.Items, "activeProgramItems", "play", {
|
||||
showAirDateTime: !1,
|
||||
showAirEndTime: !0
|
||||
}), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function reload(page, enableFullRender) {
|
||||
enableFullRender && (loadRecommendedPrograms(page), ApiClient.getLiveTvPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
HasAired: !1,
|
||||
limit: getLimit(),
|
||||
IsMovie: !1,
|
||||
IsSports: !1,
|
||||
IsKids: !1,
|
||||
IsNews: !1,
|
||||
IsSeries: !0,
|
||||
EnableTotalRecordCount: !1,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio",
|
||||
EnableImageTypes: "Primary,Thumb"
|
||||
}).then(function(result) {
|
||||
renderItems(page, result.Items, "upcomingEpisodeItems")
|
||||
}), ApiClient.getLiveTvPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
HasAired: !1,
|
||||
limit: getLimit(),
|
||||
IsMovie: !0,
|
||||
EnableTotalRecordCount: !1,
|
||||
Fields: "ChannelInfo",
|
||||
EnableImageTypes: "Primary,Thumb"
|
||||
}).then(function(result) {
|
||||
renderItems(page, result.Items, "upcomingTvMovieItems", null, {
|
||||
shape: getPortraitShape(),
|
||||
preferThumb: null,
|
||||
showParentTitle: !1
|
||||
})
|
||||
}), ApiClient.getLiveTvPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
HasAired: !1,
|
||||
limit: getLimit(),
|
||||
IsSports: !0,
|
||||
EnableTotalRecordCount: !1,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio",
|
||||
EnableImageTypes: "Primary,Thumb"
|
||||
}).then(function(result) {
|
||||
renderItems(page, result.Items, "upcomingSportsItems")
|
||||
}), ApiClient.getLiveTvPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
HasAired: !1,
|
||||
limit: getLimit(),
|
||||
IsKids: !0,
|
||||
EnableTotalRecordCount: !1,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio",
|
||||
EnableImageTypes: "Primary,Thumb"
|
||||
}).then(function(result) {
|
||||
renderItems(page, result.Items, "upcomingKidsItems")
|
||||
}), ApiClient.getLiveTvPrograms({
|
||||
userId: Dashboard.getCurrentUserId(),
|
||||
HasAired: !1,
|
||||
limit: getLimit(),
|
||||
IsNews: !0,
|
||||
EnableTotalRecordCount: !1,
|
||||
Fields: "ChannelInfo,PrimaryImageAspectRatio",
|
||||
EnableImageTypes: "Primary,Thumb"
|
||||
}).then(function(result) {
|
||||
renderItems(page, result.Items, "upcomingNewsItems", null, {
|
||||
showParentTitleOrTitle: !0,
|
||||
showTitle: !1,
|
||||
showParentTitle: !1
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
function renderItems(page, items, sectionClass, overlayButton, cardOptions) {
|
||||
var html = cardBuilder.getCardsHtml(Object.assign({
|
||||
items: items,
|
||||
preferThumb: "auto",
|
||||
inheritThumb: !1,
|
||||
shape: enableScrollX() ? "autooverflow" : "auto",
|
||||
defaultShape: getBackdropShape(),
|
||||
showParentTitle: !0,
|
||||
showTitle: !0,
|
||||
centerText: !0,
|
||||
coverImage: !0,
|
||||
overlayText: !1,
|
||||
lazy: !0,
|
||||
overlayPlayButton: "play" === overlayButton,
|
||||
overlayMoreButton: "more" === overlayButton,
|
||||
overlayInfoButton: "info" === overlayButton,
|
||||
allowBottomPadding: !enableScrollX(),
|
||||
showAirTime: !0,
|
||||
showAirDateTime: !0
|
||||
}, cardOptions || {})),
|
||||
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 validateUnlock(view, showDialog) {
|
||||
registrationServices.validateFeature("livetv", {
|
||||
showDialog: showDialog,
|
||||
viewOnly: !0
|
||||
}).then(function() {
|
||||
view.querySelector(".liveTvContainer").classList.remove("hide"), view.querySelector(".unlockContainer").classList.add("hide")
|
||||
}, function() {
|
||||
view.querySelector(".liveTvContainer").classList.add("hide"), view.querySelector(".unlockContainer").classList.remove("hide")
|
||||
})
|
||||
}
|
||||
|
||||
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 getDefaultTabIndex(folderId) {
|
||||
switch (userSettings.get("landing-" + folderId)) {
|
||||
case "guide":
|
||||
return 1;
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return function(view, params) {
|
||||
function enableFullRender() {
|
||||
return (new Date).getTime() - lastFullRender > 3e5
|
||||
}
|
||||
|
||||
function onBeforeTabChange(e) {
|
||||
preLoadTab(view, parseInt(e.detail.selectedTabIndex))
|
||||
}
|
||||
|
||||
function onTabChange(e) {
|
||||
var previousTabController = tabControllers[parseInt(e.detail.previousIndex)];
|
||||
previousTabController && previousTabController.onHide && previousTabController.onHide(), 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/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;
|
||||
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 : 6 === index ? new controllerFactory(view, tabContent, {
|
||||
collectionType: "livetv"
|
||||
}) : 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 === index ? document.body.classList.add("autoScrollY") : document.body.classList.remove("autoScrollY"), -1 == renderedTabs.indexOf(index) ? (1 === index && renderedTabs.push(index), controller.renderTab()) : controller.onShow && controller.onShow(), currentTabController = controller
|
||||
})
|
||||
}
|
||||
|
||||
function onInputCommand(e) {
|
||||
switch (e.detail.command) {
|
||||
case "search":
|
||||
e.preventDefault(), Dashboard.navigate("search.html?collectionType=livetv")
|
||||
}
|
||||
}
|
||||
var isViewRestored, self = this,
|
||||
currentTabIndex = parseInt(params.tab || getDefaultTabIndex("livetv")),
|
||||
initialTabIndex = currentTabIndex,
|
||||
lastFullRender = 0;
|
||||
[].forEach.call(view.querySelectorAll(".sectionTitleTextButton-programs"), function(link) {
|
||||
var href = link.href;
|
||||
href && (link.href = href + "&serverId=" + ApiClient.serverId())
|
||||
}), view.querySelector(".unlockText").innerHTML = globalize.translate("sharedcomponents#LiveTvRequiresUnlock"), validateUnlock(view, !1), 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() {
|
||||
var tabContent = view.querySelector(".pageTabContent[data-index='0']");
|
||||
enableFullRender() ? (reload(tabContent, !0), lastFullRender = (new Date).getTime()) : reload(tabContent)
|
||||
};
|
||||
var currentTabController, tabControllers = [],
|
||||
renderedTabs = [];
|
||||
view.querySelector(".btnUnlock").addEventListener("click", function() {
|
||||
validateUnlock(view, !0)
|
||||
}), view.addEventListener("viewbeforeshow", function(e) {
|
||||
isViewRestored = e.detail.isRestored, initTabs()
|
||||
}), view.addEventListener("viewshow", function(e) {
|
||||
isViewRestored = e.detail.isRestored, isViewRestored || mainTabsManager.selectedTabIndex(initialTabIndex), inputManager.on(window, onInputCommand)
|
||||
}), view.addEventListener("viewbeforehide", function(e) {
|
||||
currentTabController && currentTabController.onHide && currentTabController.onHide(), document.body.classList.remove("autoScrollY"), inputManager.off(window, onInputCommand)
|
||||
}), view.addEventListener("viewdestroy", function(e) {
|
||||
tabControllers.forEach(function(t) {
|
||||
t.destroy && t.destroy()
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
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 || ""
|
||||
}), AppInfo.isNativeApp ? view.querySelector(".connectButtons").classList.remove("hide") : view.querySelector(".connectButtons").classList.add("hide")
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
define(["syncJobList"], function(syncJobList) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
var apiClient = ApiClient,
|
||||
mySyncJobList = new syncJobList({
|
||||
serverId: apiClient.serverId(),
|
||||
userId: null,
|
||||
element: view.querySelector(".syncActivity"),
|
||||
mode: "download"
|
||||
});
|
||||
view.addEventListener("viewdestroy", function() {
|
||||
mySyncJobList && (mySyncJobList.destroy(), mySyncJobList = null)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,313 @@
|
||||
define(["jQuery", "apphost", "scripts/taskbutton", "loading", "libraryMenu", "globalize", "dom", "indicators", "cardStyle", "emby-itemrefreshindicator"], function($, appHost, taskButton, loading, libraryMenu, globalize, dom, indicators) {
|
||||
"use strict";
|
||||
|
||||
function changeCollectionType(page, virtualFolder) {
|
||||
require(["alert"], function(alert) {
|
||||
alert({
|
||||
title: globalize.translate("HeaderChangeFolderType"),
|
||||
text: globalize.translate("HeaderChangeFolderTypeHelp")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function addVirtualFolder(page) {
|
||||
require(["medialibrarycreator"], function(medialibrarycreator) {
|
||||
(new medialibrarycreator).show({
|
||||
collectionTypeOptions: getCollectionTypeOptions().filter(function(f) {
|
||||
return !f.hidden
|
||||
}),
|
||||
refresh: shouldRefreshLibraryAfterChanges(page)
|
||||
}).then(function(hasChanges) {
|
||||
hasChanges && reloadLibrary(page)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function editVirtualFolder(page, virtualFolder) {
|
||||
require(["medialibraryeditor"], function(medialibraryeditor) {
|
||||
(new medialibraryeditor).show({
|
||||
refresh: shouldRefreshLibraryAfterChanges(page),
|
||||
library: virtualFolder
|
||||
}).then(function(hasChanges) {
|
||||
hasChanges && reloadLibrary(page)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function deleteVirtualFolder(page, virtualFolder) {
|
||||
var msg = globalize.translate("MessageAreYouSureYouWishToRemoveMediaFolder");
|
||||
virtualFolder.Locations.length && (msg += "<br/><br/>" + globalize.translate("MessageTheFollowingLocationWillBeRemovedFromLibrary") + "<br/><br/>", msg += virtualFolder.Locations.join("<br/>")), require(["confirm"], function(confirm) {
|
||||
confirm(msg, globalize.translate("HeaderRemoveMediaFolder")).then(function() {
|
||||
var refreshAfterChange = shouldRefreshLibraryAfterChanges(page);
|
||||
ApiClient.removeVirtualFolder(virtualFolder.Name, refreshAfterChange).then(function() {
|
||||
reloadLibrary(page)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function refreshVirtualFolder(page, virtualFolder) {
|
||||
require(["refreshDialog"], function(refreshDialog) {
|
||||
new refreshDialog({
|
||||
itemIds: [virtualFolder.ItemId],
|
||||
serverId: ApiClient.serverId(),
|
||||
mode: "scan"
|
||||
}).show()
|
||||
})
|
||||
}
|
||||
|
||||
function renameVirtualFolder(page, virtualFolder) {
|
||||
require(["prompt"], function(prompt) {
|
||||
prompt({
|
||||
label: globalize.translate("LabelNewName"),
|
||||
confirmText: globalize.translate("ButtonRename")
|
||||
}).then(function(newName) {
|
||||
if (newName && newName != virtualFolder.Name) {
|
||||
var refreshAfterChange = shouldRefreshLibraryAfterChanges(page);
|
||||
ApiClient.renameVirtualFolder(virtualFolder.Name, newName, refreshAfterChange).then(function() {
|
||||
reloadLibrary(page)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function showCardMenu(page, elem, virtualFolders) {
|
||||
var card = dom.parentWithClass(elem, "card"),
|
||||
index = parseInt(card.getAttribute("data-index")),
|
||||
virtualFolder = virtualFolders[index],
|
||||
menuItems = [];
|
||||
menuItems.push({
|
||||
name: globalize.translate("ButtonChangeContentType"),
|
||||
id: "changetype",
|
||||
ironIcon: "videocam"
|
||||
}), menuItems.push({
|
||||
name: globalize.translate("ButtonEditImages"),
|
||||
id: "editimages",
|
||||
ironIcon: "photo"
|
||||
}), menuItems.push({
|
||||
name: globalize.translate("ManageLibrary"),
|
||||
id: "edit",
|
||||
ironIcon: "folder_open"
|
||||
}), menuItems.push({
|
||||
name: globalize.translate("ButtonRemove"),
|
||||
id: "delete",
|
||||
ironIcon: "remove"
|
||||
}), menuItems.push({
|
||||
name: globalize.translate("ButtonRename"),
|
||||
id: "rename",
|
||||
ironIcon: "mode_edit"
|
||||
}), menuItems.push({
|
||||
name: globalize.translate("ScanLibrary"),
|
||||
id: "refresh",
|
||||
ironIcon: "refresh"
|
||||
}), require(["actionsheet"], function(actionsheet) {
|
||||
actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: elem,
|
||||
callback: function(resultId) {
|
||||
switch (resultId) {
|
||||
case "changetype":
|
||||
changeCollectionType(page, virtualFolder);
|
||||
break;
|
||||
case "edit":
|
||||
editVirtualFolder(page, virtualFolder);
|
||||
break;
|
||||
case "editimages":
|
||||
editImages(page, virtualFolder);
|
||||
break;
|
||||
case "rename":
|
||||
renameVirtualFolder(page, virtualFolder);
|
||||
break;
|
||||
case "delete":
|
||||
deleteVirtualFolder(page, virtualFolder);
|
||||
break;
|
||||
case "refresh":
|
||||
refreshVirtualFolder(page, virtualFolder)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function reloadLibrary(page) {
|
||||
loading.show(), ApiClient.getVirtualFolders().then(function(result) {
|
||||
reloadVirtualFolders(page, result)
|
||||
})
|
||||
}
|
||||
|
||||
function shouldRefreshLibraryAfterChanges(page) {
|
||||
return "mediaLibraryPage" === page.id
|
||||
}
|
||||
|
||||
function reloadVirtualFolders(page, virtualFolders) {
|
||||
var html = "";
|
||||
virtualFolders.push({
|
||||
Name: globalize.translate("ButtonAddMediaLibrary"),
|
||||
icon: "add_circle",
|
||||
Locations: [],
|
||||
showType: !1,
|
||||
showLocations: !1,
|
||||
showMenu: !1,
|
||||
showNameWithIcon: !0
|
||||
});
|
||||
for (var i = 0, length = virtualFolders.length; i < length; i++) {
|
||||
var virtualFolder = virtualFolders[i];
|
||||
html += getVirtualFolderHtml(page, virtualFolder, i)
|
||||
}
|
||||
var divVirtualFolders = page.querySelector("#divVirtualFolders");
|
||||
divVirtualFolders.innerHTML = html, divVirtualFolders.classList.add("itemsContainer"), divVirtualFolders.classList.add("vertical-wrap"), $(".btnCardMenu", divVirtualFolders).on("click", function() {
|
||||
showCardMenu(page, this, virtualFolders)
|
||||
}), divVirtualFolders.querySelector(".addLibrary").addEventListener("click", function() {
|
||||
addVirtualFolder(page)
|
||||
}), $(".editLibrary", divVirtualFolders).on("click", function() {
|
||||
var card = $(this).parents(".card")[0],
|
||||
index = parseInt(card.getAttribute("data-index")),
|
||||
virtualFolder = virtualFolders[index];
|
||||
virtualFolder.ItemId && editVirtualFolder(page, virtualFolder)
|
||||
}), loading.hide()
|
||||
}
|
||||
|
||||
function editImages(page, virtualFolder) {
|
||||
require(["imageEditor"], function(imageEditor) {
|
||||
imageEditor.show({
|
||||
itemId: virtualFolder.ItemId,
|
||||
serverId: ApiClient.serverId()
|
||||
}).then(function() {
|
||||
reloadLibrary(page)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getLink(text, url) {
|
||||
return globalize.translate(text, '<a is="emby-linkbutton" class="button-link" href="' + url + '" target="_blank" data-autohide="true">', "</a>")
|
||||
}
|
||||
|
||||
function getCollectionTypeOptions() {
|
||||
return [{
|
||||
name: "",
|
||||
value: ""
|
||||
}, {
|
||||
name: globalize.translate("FolderTypeMovies"),
|
||||
value: "movies",
|
||||
message: getLink("MovieLibraryHelp", "https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Movie-naming")
|
||||
}, {
|
||||
name: globalize.translate("FolderTypeMusic"),
|
||||
value: "music"
|
||||
}, {
|
||||
name: globalize.translate("FolderTypeTvShows"),
|
||||
value: "tvshows",
|
||||
message: getLink("TvLibraryHelp", "https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/TV-naming")
|
||||
}, {
|
||||
name: globalize.translate("FolderTypeBooks"),
|
||||
value: "books",
|
||||
message: getLink("BookLibraryHelp", "https://web.archive.org/web/20181216120305/https://github.com/MediaBrowser/Wiki/wiki/Book-naming")
|
||||
}, {
|
||||
name: globalize.translate("FolderTypeGames"),
|
||||
value: "games",
|
||||
message: globalize.translate("MessageGamePluginRequired")
|
||||
}, {
|
||||
name: globalize.translate("OptionHomeVideos"),
|
||||
value: "homevideos"
|
||||
}, {
|
||||
name: globalize.translate("FolderTypeMusicVideos"),
|
||||
value: "musicvideos"
|
||||
}, {
|
||||
name: globalize.translate("FolderTypeUnset"),
|
||||
value: "mixed",
|
||||
message: globalize.translate("MessageUnsetContentHelp")
|
||||
}]
|
||||
}
|
||||
|
||||
function getIcon(type) {
|
||||
switch (type) {
|
||||
case "movies":
|
||||
return "local_movies";
|
||||
case "music":
|
||||
return "library_music";
|
||||
case "photos":
|
||||
return "photo";
|
||||
case "livetv":
|
||||
case "tvshows":
|
||||
return "live_tv";
|
||||
case "games":
|
||||
return "folder";
|
||||
case "trailers":
|
||||
return "local_movies";
|
||||
case "homevideos":
|
||||
case "musicvideos":
|
||||
return "video_library";
|
||||
case "books":
|
||||
case "channels":
|
||||
case "playlists":
|
||||
default:
|
||||
return "folder"
|
||||
}
|
||||
}
|
||||
|
||||
function getVirtualFolderHtml(page, virtualFolder, index) {
|
||||
var html = "",
|
||||
style = "";
|
||||
page.classList.contains("wizardPage") && (style += "min-width:33.3%;"), html += '<div class="card backdropCard scalableCard backdropCard-scalable" style="' + style + '" data-index="' + index + '" data-id="' + virtualFolder.ItemId + '">', html += '<div class="cardBox visualCardBox">', html += '<div class="cardScalable visualCardBox-cardScalable">', html += '<div class="cardPadder cardPadder-backdrop"></div>', html += '<div class="cardContent">';
|
||||
var imgUrl = "";
|
||||
virtualFolder.PrimaryImageItemId && (imgUrl = ApiClient.getScaledImageUrl(virtualFolder.PrimaryImageItemId, {
|
||||
type: "Primary"
|
||||
}));
|
||||
var hasCardImageContainer;
|
||||
if (imgUrl ? (html += '<div class="cardImageContainer editLibrary" style="cursor:pointer;background-image:url(\'' + imgUrl + "');\">", hasCardImageContainer = !0) : virtualFolder.showNameWithIcon || (html += '<div class="cardImageContainer editLibrary" style="cursor:pointer;">', html += '<i class="cardImageIcon-small md-icon">' + (virtualFolder.icon || getIcon(virtualFolder.CollectionType)) + "</i>", hasCardImageContainer = !0), hasCardImageContainer) {
|
||||
html += '<div class="cardIndicators backdropCardIndicators">';
|
||||
html += '<div is="emby-itemrefreshindicator"' + (virtualFolder.RefreshProgress || virtualFolder.RefreshStatus && "Idle" !== virtualFolder.RefreshStatus ? "" : ' class="hide"') + ' data-progress="' + (virtualFolder.RefreshProgress || 0) + '" data-status="' + virtualFolder.RefreshStatus + '"></div>', html += "</div>", html += "</div>"
|
||||
}
|
||||
if (!imgUrl && virtualFolder.showNameWithIcon && (html += '<h3 class="cardImageContainer addLibrary" style="position:absolute;top:0;left:0;right:0;bottom:0;cursor:pointer;flex-direction:column;">', html += '<i class="cardImageIcon-small md-icon">' + (virtualFolder.icon || getIcon(virtualFolder.CollectionType)) + "</i>", virtualFolder.showNameWithIcon && (html += '<div style="margin:1em 0;position:width:100%;">', html += virtualFolder.Name, html += "</div>"), html += "</h3>"), html += "</div>", html += "</div>", html += '<div class="cardFooter visualCardBox-cardFooter">', !1 !== virtualFolder.showMenu) {
|
||||
html += '<div style="text-align:right; float:right;padding-top:5px;">', html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><i class="md-icon"></i></button>', html += "</div>"
|
||||
}
|
||||
html += "<div class='cardText'>", virtualFolder.showNameWithIcon ? html += " " : html += virtualFolder.Name, html += "</div>";
|
||||
var typeName = getCollectionTypeOptions().filter(function(t) {
|
||||
return t.value == virtualFolder.CollectionType
|
||||
})[0];
|
||||
return typeName = typeName ? typeName.name : globalize.translate("FolderTypeUnset"), html += "<div class='cardText cardText-secondary'>", !1 === virtualFolder.showType ? html += " " : html += typeName, html += "</div>", !1 === virtualFolder.showLocations ? (html += "<div class='cardText cardText-secondary'>", html += " ", html += "</div>") : virtualFolder.Locations.length && 1 == virtualFolder.Locations.length ? (html += "<div class='cardText cardText-secondary'>", html += virtualFolder.Locations[0], html += "</div>") : (html += "<div class='cardText cardText-secondary'>", html += globalize.translate("NumLocationsValue", virtualFolder.Locations.length), html += "</div>"), html += "</div>", html += "</div>", html += "</div>"
|
||||
}
|
||||
|
||||
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")
|
||||
}]
|
||||
}
|
||||
window.WizardLibraryPage = {
|
||||
next: function() {
|
||||
Dashboard.navigate("wizardsettings.html")
|
||||
}
|
||||
}, pageClassOn("pageshow", "mediaLibraryPage", function() {
|
||||
reloadLibrary(this)
|
||||
}), pageIdOn("pageshow", "mediaLibraryPage", function() {
|
||||
libraryMenu.setTabs("librarysetup", 0, getTabs);
|
||||
var page = this;
|
||||
taskButton({
|
||||
mode: "on",
|
||||
progressElem: page.querySelector(".refreshProgress"),
|
||||
taskKey: "RefreshLibrary",
|
||||
button: page.querySelector(".btnRefresh")
|
||||
})
|
||||
}), pageIdOn("pagebeforehide", "mediaLibraryPage", function() {
|
||||
var page = this;
|
||||
taskButton({
|
||||
mode: "off",
|
||||
progressElem: page.querySelector(".refreshProgress"),
|
||||
taskKey: "RefreshLibrary",
|
||||
button: page.querySelector(".btnRefresh")
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
define(["jQuery", "dom", "loading", "libraryMenu", "listViewStyle"], function($, dom, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function populateLanguages(select) {
|
||||
return ApiClient.getCultures().then(function(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) {
|
||||
return ApiClient.getCountries().then(function(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 loadPage(page) {
|
||||
var promises = [ApiClient.getServerConfiguration(), populateLanguages(page.querySelector("#selectLanguage")), populateCountries(page.querySelector("#selectCountry"))];
|
||||
Promise.all(promises).then(function(responses) {
|
||||
var config = responses[0];
|
||||
page.querySelector("#selectLanguage").value = config.PreferredMetadataLanguage || "", page.querySelector("#selectCountry").value = config.MetadataCountryCode || "", loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
var form = this;
|
||||
return loading.show(), ApiClient.getServerConfiguration().then(function(config) {
|
||||
config.PreferredMetadataLanguage = form.querySelector("#selectLanguage").value, config.MetadataCountryCode = form.querySelector("#selectCountry").value, ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult)
|
||||
}), !1
|
||||
}
|
||||
|
||||
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")
|
||||
}]
|
||||
}
|
||||
$(document).on("pageinit", "#metadataImagesConfigurationPage", function() {
|
||||
$(".metadataImagesConfigurationForm").off("submit", onSubmit).on("submit", onSubmit)
|
||||
}).on("pageshow", "#metadataImagesConfigurationPage", function() {
|
||||
libraryMenu.setTabs("metadata", 2, getTabs), loading.show(), loadPage(this)
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function loadPage(page, config, users) {
|
||||
var html = '<option value="" selected="selected">' + Globalize.translate("OptionNone") + "</option>";
|
||||
html += users.map(function(user) {
|
||||
return '<option value="' + user.Id + '">' + user.Name + "</option>"
|
||||
}).join(""), $("#selectUser", page).html(html).val(config.UserId || ""), $("#selectReleaseDateFormat", page).val(config.ReleaseDateFormat), page.querySelector("#chkSaveImagePaths").checked = config.SaveImagePathsInNfo, page.querySelector("#chkEnablePathSubstitution").checked = config.EnablePathSubstitution, page.querySelector("#chkEnableExtraThumbs").checked = config.EnableExtraThumbsDuplication, loading.hide()
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
loading.show();
|
||||
var form = this;
|
||||
return ApiClient.getNamedConfiguration(metadataKey).then(function(config) {
|
||||
config.UserId = $("#selectUser", form).val() || null, config.ReleaseDateFormat = $("#selectReleaseDateFormat", form).val(), config.SaveImagePathsInNfo = form.querySelector("#chkSaveImagePaths").checked, config.EnablePathSubstitution = form.querySelector("#chkEnablePathSubstitution").checked, config.EnableExtraThumbsDuplication = form.querySelector("#chkEnableExtraThumbs").checked, ApiClient.updateNamedConfiguration(metadataKey, config).then(function() {
|
||||
Dashboard.processServerConfigurationUpdateResult(), showConfirmMessage(config)
|
||||
})
|
||||
}), !1
|
||||
}
|
||||
|
||||
function showConfirmMessage(config) {
|
||||
var msg = [];
|
||||
msg.push(Globalize.translate("MetadataSettingChangeHelp")), require(["alert"], function(alert) {
|
||||
alert({
|
||||
text: msg.join("<br/><br/>")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
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")
|
||||
}]
|
||||
}
|
||||
var metadataKey = "xbmcmetadata";
|
||||
$(document).on("pageinit", "#metadataNfoPage", function() {
|
||||
$(".metadataNfoForm").off("submit", onSubmit).on("submit", onSubmit)
|
||||
}).on("pageshow", "#metadataNfoPage", function() {
|
||||
libraryMenu.setTabs("metadata", 3, getTabs), loading.show();
|
||||
var page = this,
|
||||
promise1 = ApiClient.getUsers(),
|
||||
promise2 = ApiClient.getNamedConfiguration(metadataKey);
|
||||
Promise.all([promise1, promise2]).then(function(responses) {
|
||||
loadPage(page, responses[1], responses[0])
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,163 @@
|
||||
define(["loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(loading, events, libraryBrowser, imageLoader, listView, cardBuilder, appHost) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData(context) {
|
||||
var key = getSavedQueryKey(context),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "BoxSet",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,SortName",
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
StartIndex: 0,
|
||||
Limit: pageSize
|
||||
},
|
||||
view: libraryBrowser.getSavedView(key) || "Poster"
|
||||
}, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery(context) {
|
||||
return getPageData(context).query
|
||||
}
|
||||
|
||||
function getSavedQueryKey(context) {
|
||||
return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("moviecollections")), context.savedQueryKey
|
||||
}
|
||||
|
||||
function onViewStyleChange() {
|
||||
var viewStyle = self.getCurrentViewStyle(),
|
||||
itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
"List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = ""
|
||||
}
|
||||
|
||||
function reloadItems(page) {
|
||||
loading.show();
|
||||
var query = getQuery(page);
|
||||
ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) {
|
||||
function onNextPageClick() {
|
||||
query.StartIndex += query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
|
||||
function onPreviousPageClick() {
|
||||
query.StartIndex -= query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
window.scrollTo(0, 0);
|
||||
var html, pagingHtml = libraryBrowser.getQueryPagingHtml({
|
||||
startIndex: query.StartIndex,
|
||||
limit: query.Limit,
|
||||
totalRecordCount: result.TotalRecordCount,
|
||||
showLimit: !1,
|
||||
updatePageSizeSetting: !1,
|
||||
addLayoutButton: !1,
|
||||
sortButton: !1,
|
||||
filterButton: !1
|
||||
}),
|
||||
viewStyle = self.getCurrentViewStyle();
|
||||
html = "Thumb" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
context: "movies",
|
||||
overlayPlayButton: !0,
|
||||
centerText: !0,
|
||||
showTitle: !0
|
||||
}) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
context: "movies",
|
||||
lazy: !0,
|
||||
cardLayout: !0,
|
||||
showTitle: !0,
|
||||
vibrant: !0
|
||||
}) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "banner",
|
||||
preferBanner: !0,
|
||||
context: "movies",
|
||||
lazy: !0
|
||||
}) : "List" == viewStyle ? listView.getListViewHtml({
|
||||
items: result.Items,
|
||||
context: "movies",
|
||||
sortBy: query.SortBy
|
||||
}) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "auto",
|
||||
context: "movies",
|
||||
showTitle: !0,
|
||||
centerText: !1,
|
||||
cardLayout: !0,
|
||||
vibrant: !0
|
||||
}) : cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "auto",
|
||||
context: "movies",
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0,
|
||||
showTitle: !0
|
||||
});
|
||||
var i, length, elems = tabContent.querySelectorAll(".paging");
|
||||
for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml;
|
||||
for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick);
|
||||
for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick);
|
||||
result.Items.length || (html = '<p style="text-align:center;">' + Globalize.translate("MessageNoCollectionsAvailable") + "</p>");
|
||||
var itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(page), query), loading.hide()
|
||||
})
|
||||
}
|
||||
var self = this,
|
||||
pageSize = 100,
|
||||
data = {};
|
||||
self.getCurrentViewStyle = function() {
|
||||
return getPageData(tabContent).view
|
||||
},
|
||||
function(tabContent) {
|
||||
tabContent.querySelector(".btnSort").addEventListener("click", function(e) {
|
||||
libraryBrowser.showSortMenu({
|
||||
items: [{
|
||||
name: Globalize.translate("OptionNameSort"),
|
||||
id: "SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionImdbRating"),
|
||||
id: "CommunityRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDateAdded"),
|
||||
id: "DateCreated,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionParentalRating"),
|
||||
id: "OfficialRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionReleaseDate"),
|
||||
id: "PremiereDate,SortName"
|
||||
}],
|
||||
callback: function() {
|
||||
getQuery(tabContent).StartIndex = 0, reloadItems(tabContent)
|
||||
},
|
||||
query: getQuery(tabContent),
|
||||
button: e.target
|
||||
})
|
||||
});
|
||||
var btnSelectView = tabContent.querySelector(".btnSelectView");
|
||||
btnSelectView.addEventListener("click", function(e) {
|
||||
libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard,Thumb,ThumbCard".split(","))
|
||||
}), btnSelectView.addEventListener("layoutchange", function(e) {
|
||||
var viewStyle = e.detail.viewStyle;
|
||||
getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), getQuery(tabContent).StartIndex = 0, onViewStyleChange(), reloadItems(tabContent)
|
||||
}), tabContent.querySelector(".btnNewCollection").addEventListener("click", function() {
|
||||
require(["collectionEditor"], function(collectionEditor) {
|
||||
var serverId = ApiClient.serverInfo().Id;
|
||||
(new collectionEditor).show({
|
||||
items: [],
|
||||
serverId: serverId
|
||||
})
|
||||
})
|
||||
})
|
||||
}(tabContent), onViewStyleChange(), self.renderTab = function() {
|
||||
reloadItems(tabContent)
|
||||
}, self.destroy = function() {}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,141 @@
|
||||
define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-linkbutton"], function(layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData() {
|
||||
var key = getSavedQueryKey(),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Movie",
|
||||
Recursive: !0,
|
||||
EnableTotalRecordCount: !1
|
||||
},
|
||||
view: "Poster"
|
||||
}, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery() {
|
||||
return getPageData().query
|
||||
}
|
||||
|
||||
function getSavedQueryKey() {
|
||||
return libraryBrowser.getSavedQueryKey("moviegenres")
|
||||
}
|
||||
|
||||
function getPromise() {
|
||||
loading.show();
|
||||
var query = getQuery();
|
||||
return ApiClient.getGenres(ApiClient.getCurrentUserId(), query)
|
||||
}
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop
|
||||
}
|
||||
|
||||
function getThumbShape() {
|
||||
return enableScrollX() ? "overflowBackdrop" : "backdrop"
|
||||
}
|
||||
|
||||
function getPortraitShape() {
|
||||
return enableScrollX() ? "overflowPortrait" : "portrait"
|
||||
}
|
||||
|
||||
function fillItemsContainer(elem) {
|
||||
var id = elem.getAttribute("data-id"),
|
||||
viewStyle = self.getCurrentViewStyle(),
|
||||
limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9;
|
||||
enableScrollX() && (limit = 10);
|
||||
var enableImageTypes = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? "Primary,Backdrop,Thumb" : "Primary",
|
||||
query = {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Movie",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo",
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: enableImageTypes,
|
||||
Limit: limit,
|
||||
GenreIds: id,
|
||||
EnableTotalRecordCount: !1,
|
||||
ParentId: params.topParentId
|
||||
};
|
||||
ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) {
|
||||
var supportsImageAnalysis = appHost.supports("imageanalysis");
|
||||
"Thumb" == viewStyle ? cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: elem,
|
||||
shape: getThumbShape(),
|
||||
preferThumb: !0,
|
||||
showTitle: !0,
|
||||
scalable: !0,
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0,
|
||||
allowBottomPadding: !1
|
||||
}) : "ThumbCard" == viewStyle ? cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: elem,
|
||||
shape: getThumbShape(),
|
||||
preferThumb: !0,
|
||||
showTitle: !0,
|
||||
scalable: !0,
|
||||
centerText: !1,
|
||||
cardLayout: !0,
|
||||
vibrant: supportsImageAnalysis,
|
||||
showYear: !0
|
||||
}) : "PosterCard" == viewStyle ? cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: elem,
|
||||
shape: getPortraitShape(),
|
||||
showTitle: !0,
|
||||
scalable: !0,
|
||||
centerText: !1,
|
||||
cardLayout: !0,
|
||||
vibrant: supportsImageAnalysis,
|
||||
showYear: !0
|
||||
}) : "Poster" == viewStyle && cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: elem,
|
||||
shape: getPortraitShape(),
|
||||
scalable: !0,
|
||||
overlayMoreButton: !0,
|
||||
allowBottomPadding: !1
|
||||
}), result.Items.length >= query.Limit && tabContent.querySelector(".btnMoreFromGenre" + id + " i").classList.remove("hide")
|
||||
})
|
||||
}
|
||||
|
||||
function reloadItems(context, promise) {
|
||||
var query = getQuery();
|
||||
promise.then(function(result) {
|
||||
for (var elem = context.querySelector("#items"), html = "", items = result.Items, i = 0, length = items.length; i < length; i++) {
|
||||
var item = items[i];
|
||||
if (html += '<div class="verticalSection">', html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">', html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item, {
|
||||
context: "movies",
|
||||
parentId: params.topParentId
|
||||
}) + '" class="more button-flat button-flat-mini sectionTitleTextButton btnMoreFromGenre' + item.Id + '">', html += '<h2 class="sectionTitle sectionTitle-cards">', html += item.Name, html += "</h2>", html += '<i class="md-icon hide"></i>', html += "</a>", html += "</div>", enableScrollX()) {
|
||||
var scrollXClass = "scrollX hiddenScrollX";
|
||||
layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '<div is="emby-itemscontainer" class="itemsContainer ' + scrollXClass + ' lazy padded-left padded-right" data-id="' + item.Id + '">'
|
||||
} else html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap lazy padded-left padded-right" data-id="' + item.Id + '">';
|
||||
html += "</div>", html += "</div>"
|
||||
}
|
||||
elem.innerHTML = html, lazyLoader.lazyChildren(elem, fillItemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function fullyReload() {
|
||||
self.preRender(), self.renderTab()
|
||||
}
|
||||
var self = this,
|
||||
data = {};
|
||||
self.getViewStyles = function() {
|
||||
return "Poster,PosterCard,Thumb,ThumbCard".split(",")
|
||||
}, self.getCurrentViewStyle = function() {
|
||||
return getPageData(tabContent).view
|
||||
}, self.setCurrentViewStyle = function(viewStyle) {
|
||||
getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), fullyReload()
|
||||
}, self.enableViewSelection = !0;
|
||||
var promise;
|
||||
self.preRender = function() {
|
||||
promise = getPromise()
|
||||
}, self.renderTab = function() {
|
||||
reloadItems(tabContent, promise)
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,188 @@
|
||||
define(["layoutManager", "userSettings", "events", "libraryBrowser", "alphaPicker", "listView", "cardBuilder", "emby-itemscontainer"], function(layoutManager, userSettings, events, libraryBrowser, alphaPicker, listView, cardBuilder) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent, options) {
|
||||
function onViewStyleChange() {
|
||||
"List" == self.getCurrentViewStyle() ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = ""
|
||||
}
|
||||
|
||||
function updateFilterControls() {
|
||||
self.alphaPicker && self.alphaPicker.value(query.NameStartsWithOrGreater)
|
||||
}
|
||||
|
||||
function fetchData() {
|
||||
return ApiClient.getItems(ApiClient.getCurrentUserId(), query)
|
||||
}
|
||||
|
||||
function afterRefresh(result) {
|
||||
function onNextPageClick() {
|
||||
query.StartIndex += query.Limit, itemsContainer.refreshItems()
|
||||
}
|
||||
|
||||
function onPreviousPageClick() {
|
||||
query.StartIndex -= query.Limit, itemsContainer.refreshItems()
|
||||
}
|
||||
window.scrollTo(0, 0), updateFilterControls();
|
||||
var i, length, pagingHtml = libraryBrowser.getQueryPagingHtml({
|
||||
startIndex: query.StartIndex,
|
||||
limit: query.Limit,
|
||||
totalRecordCount: result.TotalRecordCount,
|
||||
showLimit: !1,
|
||||
updatePageSizeSetting: !1,
|
||||
addLayoutButton: !1,
|
||||
sortButton: !1,
|
||||
filterButton: !1
|
||||
}),
|
||||
elems = tabContent.querySelectorAll(".paging");
|
||||
for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml;
|
||||
for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick);
|
||||
for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick)
|
||||
}
|
||||
|
||||
function getItemsHtml(items) {
|
||||
var viewStyle = self.getCurrentViewStyle();
|
||||
return "Thumb" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
context: "movies",
|
||||
lazy: !0,
|
||||
overlayPlayButton: !0,
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
centerText: !0
|
||||
}) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
context: "movies",
|
||||
lazy: !0,
|
||||
cardLayout: !0,
|
||||
showTitle: !0,
|
||||
showYear: !0
|
||||
}) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
shape: "banner",
|
||||
preferBanner: !0,
|
||||
context: "movies",
|
||||
lazy: !0
|
||||
}) : "List" == viewStyle ? listView.getListViewHtml({
|
||||
items: items,
|
||||
context: "movies",
|
||||
sortBy: query.SortBy
|
||||
}) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
shape: "portrait",
|
||||
context: "movies",
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
lazy: !0,
|
||||
cardLayout: !0
|
||||
}) : cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
shape: "portrait",
|
||||
context: "movies",
|
||||
overlayPlayButton: !0,
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
centerText: !0
|
||||
})
|
||||
}
|
||||
|
||||
function initPage(tabContent) {
|
||||
itemsContainer.fetchData = fetchData, itemsContainer.getItemsHtml = getItemsHtml, itemsContainer.afterRefresh = afterRefresh;
|
||||
var alphaPickerElement = tabContent.querySelector(".alphaPicker");
|
||||
alphaPickerElement && (alphaPickerElement.addEventListener("alphavaluechanged", function(e) {
|
||||
var newValue = e.detail.value;
|
||||
query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, itemsContainer.refreshItems()
|
||||
}), self.alphaPicker = new alphaPicker({
|
||||
element: alphaPickerElement,
|
||||
valueChangeEvent: "click"
|
||||
}), (layoutManager.desktop || layoutManager.mobile) && (alphaPickerElement.classList.add("alphabetPicker-right"), itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker")));
|
||||
var btnFilter = tabContent.querySelector(".btnFilter");
|
||||
btnFilter && btnFilter.addEventListener("click", function() {
|
||||
self.showFilterMenu()
|
||||
});
|
||||
var btnSort = tabContent.querySelector(".btnSort");
|
||||
btnSort && btnSort.addEventListener("click", function(e) {
|
||||
libraryBrowser.showSortMenu({
|
||||
items: [{
|
||||
name: Globalize.translate("OptionNameSort"),
|
||||
id: "SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionImdbRating"),
|
||||
id: "CommunityRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionCriticRating"),
|
||||
id: "CriticRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDateAdded"),
|
||||
id: "DateCreated,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDatePlayed"),
|
||||
id: "DatePlayed,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionParentalRating"),
|
||||
id: "OfficialRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionPlayCount"),
|
||||
id: "PlayCount,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionReleaseDate"),
|
||||
id: "PremiereDate,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionRuntime"),
|
||||
id: "Runtime,SortName"
|
||||
}],
|
||||
callback: function() {
|
||||
query.StartIndex = 0, userSettings.saveQuerySettings(savedQueryKey, query), itemsContainer.refreshItems()
|
||||
},
|
||||
query: query,
|
||||
button: e.target
|
||||
})
|
||||
});
|
||||
var btnSelectView = tabContent.querySelector(".btnSelectView");
|
||||
btnSelectView.addEventListener("click", function(e) {
|
||||
libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "Banner,List,Poster,PosterCard,Thumb,ThumbCard".split(","))
|
||||
}), btnSelectView.addEventListener("layoutchange", function(e) {
|
||||
var viewStyle = e.detail.viewStyle;
|
||||
userSettings.set(savedViewKey, viewStyle), query.StartIndex = 0, onViewStyleChange(), itemsContainer.refreshItems()
|
||||
})
|
||||
}
|
||||
var self = this,
|
||||
itemsContainer = tabContent.querySelector(".itemsContainer"),
|
||||
savedQueryKey = params.topParentId + "-" + options.mode,
|
||||
savedViewKey = savedQueryKey + "-view",
|
||||
query = {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Movie",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo",
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
StartIndex: 0,
|
||||
Limit: 100,
|
||||
ParentId: params.topParentId
|
||||
};
|
||||
"favorites" === options.mode && (query.IsFavorite = !0), query = userSettings.loadQuerySettings(savedQueryKey, query), self.showFilterMenu = function() {
|
||||
require(["components/filterdialog/filterdialog"], function(filterDialogFactory) {
|
||||
var filterDialog = new filterDialogFactory({
|
||||
query: query,
|
||||
mode: "movies",
|
||||
serverId: ApiClient.serverId()
|
||||
});
|
||||
events.on(filterDialog, "filterchange", function() {
|
||||
query.StartIndex = 0, itemsContainer.refreshItems()
|
||||
}), filterDialog.show()
|
||||
})
|
||||
}, self.getCurrentViewStyle = function() {
|
||||
return userSettings.get(savedViewKey) || "Poster"
|
||||
}, self.initTab = function() {
|
||||
initPage(tabContent), onViewStyleChange()
|
||||
}, self.renderTab = function() {
|
||||
itemsContainer.refreshItems(), updateFilterControls()
|
||||
}, self.destroy = function() {
|
||||
itemsContainer = null
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,276 @@
|
||||
define(["events", "layoutManager", "inputManager", "userSettings", "libraryMenu", "mainTabsManager", "components/categorysyncbuttons", "cardBuilder", "dom", "imageLoader", "playbackManager", "emby-itemscontainer", "emby-tabs", "emby-button"], function(events, layoutManager, inputManager, userSettings, libraryMenu, mainTabsManager, categorysyncbuttons, 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("sharedcomponents#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 + "']");
|
||||
categorysyncbuttons.init(tabContent), 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()
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,177 @@
|
||||
define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData(context) {
|
||||
var key = getSavedQueryKey(context),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Trailer",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo",
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
StartIndex: 0,
|
||||
Limit: pageSize
|
||||
},
|
||||
view: libraryBrowser.getSavedView(key) || "Poster"
|
||||
}, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery(context) {
|
||||
return getPageData(context).query
|
||||
}
|
||||
|
||||
function getSavedQueryKey(context) {
|
||||
return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("trailers")), context.savedQueryKey
|
||||
}
|
||||
|
||||
function reloadItems() {
|
||||
loading.show();
|
||||
var query = getQuery(tabContent);
|
||||
ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) {
|
||||
function onNextPageClick() {
|
||||
query.StartIndex += query.Limit, reloadItems()
|
||||
}
|
||||
|
||||
function onPreviousPageClick() {
|
||||
query.StartIndex -= query.Limit, reloadItems()
|
||||
}
|
||||
window.scrollTo(0, 0), updateFilterControls(tabContent);
|
||||
var html, pagingHtml = libraryBrowser.getQueryPagingHtml({
|
||||
startIndex: query.StartIndex,
|
||||
limit: query.Limit,
|
||||
totalRecordCount: result.TotalRecordCount,
|
||||
showLimit: !1,
|
||||
updatePageSizeSetting: !1,
|
||||
addLayoutButton: !1,
|
||||
sortButton: !1,
|
||||
filterButton: !1
|
||||
}),
|
||||
viewStyle = self.getCurrentViewStyle();
|
||||
html = "Thumb" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
context: "movies",
|
||||
overlayPlayButton: !0
|
||||
}) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
context: "movies",
|
||||
cardLayout: !0,
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
vibrant: !0
|
||||
}) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "banner",
|
||||
preferBanner: !0,
|
||||
context: "movies"
|
||||
}) : "List" == viewStyle ? listView.getListViewHtml({
|
||||
items: result.Items,
|
||||
context: "movies",
|
||||
sortBy: query.SortBy
|
||||
}) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "portrait",
|
||||
context: "movies",
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
cardLayout: !0,
|
||||
vibrant: !0
|
||||
}) : cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "portrait",
|
||||
context: "movies",
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0,
|
||||
showTitle: !0,
|
||||
showYear: !0
|
||||
});
|
||||
var i, length, elems = tabContent.querySelectorAll(".paging");
|
||||
for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml;
|
||||
for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick);
|
||||
for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick);
|
||||
result.Items.length || (html = '<p style="text-align:center;">' + Globalize.translate("MessageNoTrailersFound") + "</p>");
|
||||
var itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(tabContent), query), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function updateFilterControls(tabContent) {
|
||||
var query = getQuery(tabContent);
|
||||
self.alphaPicker.value(query.NameStartsWithOrGreater)
|
||||
}
|
||||
var self = this,
|
||||
pageSize = 100,
|
||||
data = {};
|
||||
self.showFilterMenu = function() {
|
||||
require(["components/filterdialog/filterdialog"], function(filterDialogFactory) {
|
||||
var filterDialog = new filterDialogFactory({
|
||||
query: getQuery(tabContent),
|
||||
mode: "movies",
|
||||
serverId: ApiClient.serverId()
|
||||
});
|
||||
events.on(filterDialog, "filterchange", function() {
|
||||
getQuery(tabContent).StartIndex = 0, reloadItems()
|
||||
}), filterDialog.show()
|
||||
})
|
||||
}, self.getCurrentViewStyle = function() {
|
||||
return getPageData(tabContent).view
|
||||
},
|
||||
function(tabContent) {
|
||||
var alphaPickerElement = tabContent.querySelector(".alphaPicker");
|
||||
if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) {
|
||||
var newValue = e.detail.value,
|
||||
query = getQuery(tabContent);
|
||||
query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems()
|
||||
}), self.alphaPicker = new alphaPicker({
|
||||
element: alphaPickerElement,
|
||||
valueChangeEvent: "click"
|
||||
}), layoutManager.desktop || layoutManager.mobile) {
|
||||
tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right");
|
||||
var itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker")
|
||||
}
|
||||
tabContent.querySelector(".btnFilter").addEventListener("click", function() {
|
||||
self.showFilterMenu()
|
||||
}), tabContent.querySelector(".btnSort").addEventListener("click", function(e) {
|
||||
libraryBrowser.showSortMenu({
|
||||
items: [{
|
||||
name: Globalize.translate("OptionNameSort"),
|
||||
id: "SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionImdbRating"),
|
||||
id: "CommunityRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDateAdded"),
|
||||
id: "DateCreated,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDatePlayed"),
|
||||
id: "DatePlayed,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionParentalRating"),
|
||||
id: "OfficialRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionPlayCount"),
|
||||
id: "PlayCount,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionReleaseDate"),
|
||||
id: "PremiereDate,SortName"
|
||||
}],
|
||||
callback: function() {
|
||||
getQuery(tabContent).StartIndex = 0, reloadItems()
|
||||
},
|
||||
query: getQuery(tabContent),
|
||||
button: e.target
|
||||
})
|
||||
})
|
||||
}(tabContent), self.renderTab = function() {
|
||||
reloadItems(), updateFilterControls(tabContent)
|
||||
}, self.destroy = function() {}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,182 @@
|
||||
define(["layoutManager", "playbackManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(layoutManager, playbackManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function playAll() {
|
||||
ApiClient.getItem(ApiClient.getCurrentUserId(), params.topParentId).then(function(item) {
|
||||
playbackManager.play({
|
||||
items: [item]
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function shuffle() {
|
||||
ApiClient.getItem(ApiClient.getCurrentUserId(), params.topParentId).then(function(item) {
|
||||
getQuery();
|
||||
playbackManager.shuffle(item, null)
|
||||
})
|
||||
}
|
||||
|
||||
function getPageData() {
|
||||
var key = getSavedQueryKey();
|
||||
return pageData || (pageData = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "MusicAlbum",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo",
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
StartIndex: 0,
|
||||
Limit: pageSize
|
||||
},
|
||||
view: libraryBrowser.getSavedView(key) || "Poster"
|
||||
}, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery() {
|
||||
return getPageData().query
|
||||
}
|
||||
|
||||
function getSavedQueryKey() {
|
||||
return savedQueryKey || (savedQueryKey = libraryBrowser.getSavedQueryKey("musicalbums")), savedQueryKey
|
||||
}
|
||||
|
||||
function onViewStyleChange() {
|
||||
var viewStyle = self.getCurrentViewStyle(),
|
||||
itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
"List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = ""
|
||||
}
|
||||
|
||||
function reloadItems(page) {
|
||||
loading.show();
|
||||
var query = getQuery();
|
||||
ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) {
|
||||
function onNextPageClick() {
|
||||
query.StartIndex += query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
|
||||
function onPreviousPageClick() {
|
||||
query.StartIndex -= query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
window.scrollTo(0, 0), updateFilterControls(page);
|
||||
var html, pagingHtml = libraryBrowser.getQueryPagingHtml({
|
||||
startIndex: query.StartIndex,
|
||||
limit: query.Limit,
|
||||
totalRecordCount: result.TotalRecordCount,
|
||||
showLimit: !1,
|
||||
updatePageSizeSetting: !1,
|
||||
addLayoutButton: !1,
|
||||
sortButton: !1,
|
||||
filterButton: !1
|
||||
}),
|
||||
viewStyle = self.getCurrentViewStyle();
|
||||
html = "List" == viewStyle ? listView.getListViewHtml({
|
||||
items: result.Items,
|
||||
context: "music",
|
||||
sortBy: query.SortBy,
|
||||
addToListButton: !0
|
||||
}) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "square",
|
||||
context: "music",
|
||||
showTitle: !0,
|
||||
coverImage: !0,
|
||||
showParentTitle: !0,
|
||||
lazy: !0,
|
||||
cardLayout: !0
|
||||
}) : cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "square",
|
||||
context: "music",
|
||||
showTitle: !0,
|
||||
showParentTitle: !0,
|
||||
lazy: !0,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0
|
||||
});
|
||||
var i, length, elems = tabContent.querySelectorAll(".paging");
|
||||
for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml;
|
||||
for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick);
|
||||
for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick);
|
||||
var itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function updateFilterControls(tabContent) {
|
||||
var query = getQuery();
|
||||
self.alphaPicker.value(query.NameStartsWithOrGreater)
|
||||
}
|
||||
var savedQueryKey, pageData, self = this,
|
||||
pageSize = 100;
|
||||
self.showFilterMenu = function() {
|
||||
require(["components/filterdialog/filterdialog"], function(filterDialogFactory) {
|
||||
var filterDialog = new filterDialogFactory({
|
||||
query: getQuery(),
|
||||
mode: "albums",
|
||||
serverId: ApiClient.serverId()
|
||||
});
|
||||
events.on(filterDialog, "filterchange", function() {
|
||||
getQuery().StartIndex = 0, reloadItems(tabContent)
|
||||
}), filterDialog.show()
|
||||
})
|
||||
}, self.getCurrentViewStyle = function() {
|
||||
return getPageData().view
|
||||
},
|
||||
function(tabContent) {
|
||||
var alphaPickerElement = tabContent.querySelector(".alphaPicker");
|
||||
if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) {
|
||||
var newValue = e.detail.value,
|
||||
query = getQuery();
|
||||
query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems(tabContent)
|
||||
}), self.alphaPicker = new alphaPicker({
|
||||
element: alphaPickerElement,
|
||||
valueChangeEvent: "click"
|
||||
}), layoutManager.desktop || layoutManager.mobile) {
|
||||
tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right");
|
||||
var itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker")
|
||||
}
|
||||
tabContent.querySelector(".btnFilter").addEventListener("click", function() {
|
||||
self.showFilterMenu()
|
||||
}), tabContent.querySelector(".btnSort").addEventListener("click", function(e) {
|
||||
libraryBrowser.showSortMenu({
|
||||
items: [{
|
||||
name: Globalize.translate("OptionNameSort"),
|
||||
id: "SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionAlbumArtist"),
|
||||
id: "AlbumArtist,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionCommunityRating"),
|
||||
id: "CommunityRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionCriticRating"),
|
||||
id: "CriticRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDateAdded"),
|
||||
id: "DateCreated,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionReleaseDate"),
|
||||
id: "ProductionYear,PremiereDate,SortName"
|
||||
}],
|
||||
callback: function() {
|
||||
getQuery().StartIndex = 0, reloadItems(tabContent)
|
||||
},
|
||||
query: getQuery(),
|
||||
button: e.target
|
||||
})
|
||||
});
|
||||
var btnSelectView = tabContent.querySelector(".btnSelectView");
|
||||
btnSelectView.addEventListener("click", function(e) {
|
||||
libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(","))
|
||||
}), btnSelectView.addEventListener("layoutchange", function(e) {
|
||||
var viewStyle = e.detail.viewStyle;
|
||||
getPageData().view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(), viewStyle), getQuery().StartIndex = 0, onViewStyleChange(), reloadItems(tabContent)
|
||||
}), tabContent.querySelector(".btnPlayAll").addEventListener("click", playAll), tabContent.querySelector(".btnShuffle").addEventListener("click", shuffle)
|
||||
}(tabContent), onViewStyleChange(), self.renderTab = function() {
|
||||
reloadItems(tabContent), updateFilterControls(tabContent)
|
||||
}, self.destroy = function() {}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,136 @@
|
||||
define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "alphaPicker", "listView", "cardBuilder", "apphost", "emby-itemscontainer"], function(layoutManager, loading, events, libraryBrowser, imageLoader, alphaPicker, listView, cardBuilder, appHost) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData(context) {
|
||||
var key = getSavedQueryKey(context),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,SortName,BasicSyncInfo",
|
||||
StartIndex: 0,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
Limit: 100
|
||||
},
|
||||
view: libraryBrowser.getSavedView(key) || "Poster"
|
||||
}, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery(context) {
|
||||
return getPageData(context).query
|
||||
}
|
||||
|
||||
function getSavedQueryKey(context) {
|
||||
return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey(self.mode)), context.savedQueryKey
|
||||
}
|
||||
|
||||
function onViewStyleChange() {
|
||||
var viewStyle = self.getCurrentViewStyle(),
|
||||
itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
"List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = ""
|
||||
}
|
||||
|
||||
function reloadItems(page) {
|
||||
loading.show();
|
||||
var query = getQuery(page);
|
||||
("albumartists" == self.mode ? ApiClient.getAlbumArtists(ApiClient.getCurrentUserId(), query) : ApiClient.getArtists(ApiClient.getCurrentUserId(), query)).then(function(result) {
|
||||
function onNextPageClick() {
|
||||
query.StartIndex += query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
|
||||
function onPreviousPageClick() {
|
||||
query.StartIndex -= query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
window.scrollTo(0, 0), updateFilterControls(page);
|
||||
var html, pagingHtml = libraryBrowser.getQueryPagingHtml({
|
||||
startIndex: query.StartIndex,
|
||||
limit: query.Limit,
|
||||
totalRecordCount: result.TotalRecordCount,
|
||||
showLimit: !1,
|
||||
updatePageSizeSetting: !1,
|
||||
addLayoutButton: !1,
|
||||
sortButton: !1,
|
||||
filterButton: !1
|
||||
}),
|
||||
viewStyle = self.getCurrentViewStyle();
|
||||
html = "List" == viewStyle ? listView.getListViewHtml({
|
||||
items: result.Items,
|
||||
sortBy: query.SortBy
|
||||
}) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "square",
|
||||
context: "music",
|
||||
showTitle: !0,
|
||||
coverImage: !0,
|
||||
cardLayout: !0
|
||||
}) : cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "square",
|
||||
context: "music",
|
||||
showTitle: !0,
|
||||
coverImage: !0,
|
||||
lazy: !0,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0
|
||||
});
|
||||
var i, length, elems = tabContent.querySelectorAll(".paging");
|
||||
for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml;
|
||||
for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick);
|
||||
for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick);
|
||||
var itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(page), query), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function updateFilterControls(tabContent) {
|
||||
var query = getQuery(tabContent);
|
||||
self.alphaPicker.value(query.NameStartsWithOrGreater)
|
||||
}
|
||||
var self = this,
|
||||
data = {};
|
||||
self.showFilterMenu = function() {
|
||||
require(["components/filterdialog/filterdialog"], function(filterDialogFactory) {
|
||||
var filterDialog = new filterDialogFactory({
|
||||
query: getQuery(tabContent),
|
||||
mode: self.mode,
|
||||
serverId: ApiClient.serverId()
|
||||
});
|
||||
events.on(filterDialog, "filterchange", function() {
|
||||
getQuery(tabContent).StartIndex = 0, reloadItems(tabContent)
|
||||
}), filterDialog.show()
|
||||
})
|
||||
}, self.getCurrentViewStyle = function() {
|
||||
return getPageData(tabContent).view
|
||||
},
|
||||
function(tabContent) {
|
||||
var alphaPickerElement = tabContent.querySelector(".alphaPicker");
|
||||
if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) {
|
||||
var newValue = e.detail.value,
|
||||
query = getQuery(tabContent);
|
||||
query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems(tabContent)
|
||||
}), self.alphaPicker = new alphaPicker({
|
||||
element: alphaPickerElement,
|
||||
valueChangeEvent: "click"
|
||||
}), layoutManager.desktop || layoutManager.mobile) {
|
||||
tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right");
|
||||
var itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker")
|
||||
}
|
||||
tabContent.querySelector(".btnFilter").addEventListener("click", function() {
|
||||
self.showFilterMenu()
|
||||
});
|
||||
var btnSelectView = tabContent.querySelector(".btnSelectView");
|
||||
btnSelectView.addEventListener("click", function(e) {
|
||||
libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "List,Poster,PosterCard".split(","))
|
||||
}), btnSelectView.addEventListener("layoutchange", function(e) {
|
||||
var viewStyle = e.detail.viewStyle;
|
||||
getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), getQuery(tabContent).StartIndex = 0, onViewStyleChange(), reloadItems(tabContent)
|
||||
})
|
||||
}(tabContent), onViewStyleChange(), self.renderTab = function() {
|
||||
reloadItems(tabContent), updateFilterControls(tabContent)
|
||||
}, self.destroy = function() {}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], function(libraryBrowser, cardBuilder, appHost, imageLoader, loading) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData() {
|
||||
var key = getSavedQueryKey(),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,ItemCounts",
|
||||
StartIndex: 0
|
||||
},
|
||||
view: libraryBrowser.getSavedView(key) || "Poster"
|
||||
}, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery() {
|
||||
return getPageData().query
|
||||
}
|
||||
|
||||
function getSavedQueryKey() {
|
||||
return libraryBrowser.getSavedQueryKey("genres")
|
||||
}
|
||||
|
||||
function getPromise() {
|
||||
loading.show();
|
||||
var query = getQuery();
|
||||
return ApiClient.getGenres(ApiClient.getCurrentUserId(), query)
|
||||
}
|
||||
|
||||
function reloadItems(context, promise) {
|
||||
var query = getQuery();
|
||||
promise.then(function(result) {
|
||||
var html = "",
|
||||
viewStyle = self.getCurrentViewStyle();
|
||||
"Thumb" == viewStyle ? html = cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
context: "music",
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0,
|
||||
showTitle: !0
|
||||
}) : "ThumbCard" == viewStyle ? html = cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
context: "music",
|
||||
cardLayout: !0,
|
||||
showTitle: !0,
|
||||
vibrant: !0
|
||||
}) : "PosterCard" == viewStyle ? html = cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "auto",
|
||||
context: "music",
|
||||
cardLayout: !0,
|
||||
showTitle: !0,
|
||||
vibrant: !0
|
||||
}) : "Poster" == viewStyle && (html = cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "auto",
|
||||
context: "music",
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0,
|
||||
showTitle: !0
|
||||
}));
|
||||
var elem = context.querySelector("#items");
|
||||
elem.innerHTML = html, imageLoader.lazyChildren(elem), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function fullyReload() {
|
||||
self.preRender(), self.renderTab()
|
||||
}
|
||||
var self = this,
|
||||
data = {};
|
||||
self.getViewStyles = function() {
|
||||
return "Poster,PosterCard,Thumb,ThumbCard".split(",")
|
||||
}, self.getCurrentViewStyle = function() {
|
||||
return getPageData(tabContent).view
|
||||
}, self.setCurrentViewStyle = function(viewStyle) {
|
||||
getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), fullyReload()
|
||||
}, self.enableViewSelection = !0;
|
||||
var promise;
|
||||
self.preRender = function() {
|
||||
promise = getPromise()
|
||||
}, self.renderTab = function() {
|
||||
reloadItems(tabContent, promise)
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
define(["libraryBrowser", "cardBuilder", "apphost", "imageLoader", "loading"], function(libraryBrowser, cardBuilder, appHost, imageLoader, loading) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData() {
|
||||
var key = getSavedQueryKey(),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Playlist",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,SortName,CanDelete",
|
||||
StartIndex: 0
|
||||
},
|
||||
view: libraryBrowser.getSavedView(key) || "Poster"
|
||||
}, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery() {
|
||||
return getPageData().query
|
||||
}
|
||||
|
||||
function getSavedQueryKey() {
|
||||
return libraryBrowser.getSavedQueryKey("genres")
|
||||
}
|
||||
|
||||
function getPromise() {
|
||||
loading.show();
|
||||
var query = getQuery();
|
||||
return ApiClient.getItems(ApiClient.getCurrentUserId(), query)
|
||||
}
|
||||
|
||||
function reloadItems(context, promise) {
|
||||
var query = getQuery();
|
||||
promise.then(function(result) {
|
||||
var html = "";
|
||||
html = cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "square",
|
||||
showTitle: !0,
|
||||
coverImage: !0,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0,
|
||||
allowBottomPadding: !0,
|
||||
cardLayout: !1,
|
||||
vibrant: !1
|
||||
});
|
||||
var elem = context.querySelector("#items");
|
||||
elem.innerHTML = html, imageLoader.lazyChildren(elem), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide()
|
||||
})
|
||||
}
|
||||
var self = this,
|
||||
data = {};
|
||||
self.getCurrentViewStyle = function() {
|
||||
return getPageData(tabContent).view
|
||||
};
|
||||
var promise;
|
||||
self.preRender = function() {
|
||||
promise = getPromise()
|
||||
}, self.renderTab = function() {
|
||||
reloadItems(tabContent, promise)
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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()
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
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,
|
||||
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), page.querySelector(".lnkSync").setAttribute("href", "mysyncsettings.html?userId=" + userId), page.querySelector(".lnkCameraUpload").setAttribute("href", "camerauploadsettings.html?userId=" + userId), appHost.supports("cameraupload") ? page.querySelector(".lnkCameraUpload").classList.remove("hide") : page.querySelector(".lnkCameraUpload").classList.add("hide"), appHost.supports("sync") ? page.querySelector(".lnkSync").classList.remove("hide") : page.querySelector(".lnkSync").classList.add("hide"), connectionManager.user(ApiClient).then(function(user) {
|
||||
!user.localUser || user.localUser.EnableAutoLogin && !user.connectUser ? view.querySelector(".btnLogout").classList.add("hide") : view.querySelector(".btnLogout").classList.remove("hide")
|
||||
}), Dashboard.getCurrentUser().then(function(user) {
|
||||
page.querySelector(".headerUser").innerHTML = user.Name, user.Policy.IsAdministrator ? page.querySelector(".adminSection").classList.remove("hide") : page.querySelector(".adminSection").classList.add("hide")
|
||||
}), appHost.supports("multiserver") ? page.querySelector(".selectServer").classList.remove("hide") : page.querySelector(".selectServer").classList.add("hide")
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
define(["scripts/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, fldImage = page.querySelector("#fldImage");
|
||||
imageUrl = user.PrimaryImageTag ? ApiClient.getUserImageUrl(user.Id, {
|
||||
height: 200,
|
||||
tag: user.PrimaryImageTag,
|
||||
type: "Primary"
|
||||
}) : "css/images/logindefault.png", fldImage.classList.remove("hide"), fldImage.innerHTML = "<img width='140px' src='" + imageUrl + "' />";
|
||||
var showImageEditing = !1;
|
||||
Dashboard.getCurrentUser().then(function(loggedInUser) {
|
||||
showImageEditing && appHost.supports("fileinput") && (loggedInUser.Policy.IsAdministrator || user.Policy.EnableUserPreferenceAccess) ? (page.querySelector(".newImageForm").classList.remove("hide"), user.PrimaryImageTag ? page.querySelector("#btnDeleteImage").classList.remove("hide") : page.querySelector("#btnDeleteImage").classList.add("hide")) : (page.querySelector(".newImageForm").classList.add("hide"), page.querySelector("#btnDeleteImage").classList.add("hide"))
|
||||
}), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function onFileReaderError(evt) {
|
||||
switch (loading.hide(), 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.*")) return page.querySelector("#userImageOutput").innerHTML = "", page.querySelector("#fldUpload").classList.add("hide"), 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(e) {
|
||||
var html = ['<img style="max-width:100%;max-height:100%;" src="', e.target.result, '" title="', escape(file.name), '"/>'].join("");
|
||||
page.querySelector("#userImageOutput").innerHTML = html, page.querySelector("#fldUpload").classList.remove("hide")
|
||||
}, reader.readAsDataURL(file)
|
||||
}
|
||||
|
||||
function onImageDragOver(e) {
|
||||
return e.preventDefault(), e.originalEvent.dataTransfer.dropEffect = "Copy", !1
|
||||
}
|
||||
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(e) {
|
||||
var file = currentFile;
|
||||
if (!file) return !1;
|
||||
if ("image/png" != file.type && "image/jpeg" != file.type && "image/jpeg" != file.type) return !1;
|
||||
loading.show();
|
||||
var userId = getParameterByName("userId");
|
||||
return ApiClient.uploadUserImage(userId, "Primary", file).then(function() {
|
||||
loading.hide(), reloadUser(view)
|
||||
}), e.preventDefault(), !1
|
||||
}), view.querySelector("#uploadUserImage").addEventListener("change", function(e) {
|
||||
setFiles(view, e.target.files)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
define(["apphost", "globalize", "syncJobList", "events", "localsync", "emby-button", "paper-icon-button-light"], function(appHost, globalize, syncJobList, events, localSync) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
var interval, mySyncJobList = new syncJobList({
|
||||
mode: params.mode,
|
||||
enableRemoteSyncManagement: !1,
|
||||
serverId: ApiClient.serverId(),
|
||||
userId: "offline" === params.mode ? null : ApiClient.getCurrentUserId(),
|
||||
element: view.querySelector(".syncActivity"),
|
||||
mode: params.mode
|
||||
});
|
||||
view.addEventListener("viewbeforehide", function() {
|
||||
interval && (clearInterval(interval), interval = null)
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
mySyncJobList.destroy()
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
define(["appSettings", "apphost", "emby-checkbox", "emby-select", "emby-input"], function(appSettings, appHost) {
|
||||
"use strict";
|
||||
|
||||
function loadForm(page, user) {
|
||||
page.querySelector("#txtSyncPath").value = appSettings.syncPath() || "", page.querySelector("#chkWifi").checked = appSettings.syncOnlyOnWifi(), page.querySelector(".selectAudioBitrate").value = appSettings.maxStaticMusicBitrate() || ""
|
||||
}
|
||||
|
||||
function saveUser(page) {
|
||||
var syncPath = page.querySelector("#txtSyncPath").value;
|
||||
appSettings.syncPath(syncPath), appSettings.syncOnlyOnWifi(page.querySelector("#chkWifi").checked), appSettings.maxStaticMusicBitrate(page.querySelector(".selectAudioBitrate").value || null), require(["localsync"], function(localSync) {
|
||||
localSync.sync()
|
||||
})
|
||||
}
|
||||
return function(view, params) {
|
||||
view.querySelector("form").addEventListener("submit", function(e) {
|
||||
return saveUser(view), e.preventDefault(), !1
|
||||
}), view.querySelector("#btnSelectSyncPath").addEventListener("click", function() {
|
||||
require(["nativedirectorychooser"], function() {
|
||||
NativeDirectoryChooser.chooseDirectory().then(function(path) {
|
||||
path && (view.querySelector("#txtSyncPath").value = path)
|
||||
})
|
||||
})
|
||||
}), view.addEventListener("viewshow", function() {
|
||||
var page = this,
|
||||
userId = getParameterByName("userId") || Dashboard.getCurrentUserId();
|
||||
ApiClient.getUser(userId).then(function(user) {
|
||||
loadForm(page, user)
|
||||
}), appHost.supports("customsyncpath") ? page.querySelector(".fldSyncPath").classList.remove("hide") : page.querySelector(".fldSyncPath").classList.add("hide")
|
||||
}), view.addEventListener("viewbeforehide", function() {
|
||||
saveUser(this)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
define(["jQuery", "emby-checkbox", "fnchecked"], function($) {
|
||||
"use strict";
|
||||
|
||||
function fillItems(elem, items, cssClass, idPrefix, currentList, isEnabledList) {
|
||||
var html = '<div class="checkboxList paperList" style="padding: .5em 1em;">';
|
||||
html += items.map(function(u) {
|
||||
var isChecked = isEnabledList ? -1 != currentList.indexOf(u.Id) : -1 == currentList.indexOf(u.Id),
|
||||
checkedHtml = isChecked ? ' checked="checked"' : "";
|
||||
return '<label><input is="emby-checkbox" class="' + cssClass + '" type="checkbox" data-itemid="' + u.Id + '"' + checkedHtml + "/><span>" + u.Name + "</span></label>"
|
||||
}).join(""), html += "</div>", elem.html(html).trigger("create")
|
||||
}
|
||||
|
||||
function reload(page) {
|
||||
var type = getParameterByName("type"),
|
||||
promise1 = ApiClient.getUsers(),
|
||||
promise2 = ApiClient.getNamedConfiguration(notificationsConfigurationKey),
|
||||
promise3 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types")),
|
||||
promise4 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Services"));
|
||||
Promise.all([promise1, promise2, promise3, promise4]).then(function(responses) {
|
||||
var users = responses[0],
|
||||
notificationOptions = responses[1],
|
||||
types = responses[2],
|
||||
services = responses[3],
|
||||
notificationConfig = notificationOptions.Options.filter(function(n) {
|
||||
return n.Type == type
|
||||
})[0],
|
||||
typeInfo = types.filter(function(n) {
|
||||
return n.Type == type
|
||||
})[0] || {};
|
||||
typeInfo.IsBasedOnUserEvent ? $(".monitorUsers", page).show() : $(".monitorUsers", page).hide(), $(".notificationType", page).html(typeInfo.Name || "Unknown Notification"), notificationConfig || (notificationConfig = {
|
||||
DisabledMonitorUsers: [],
|
||||
SendToUsers: [],
|
||||
DisabledServices: [],
|
||||
SendToUserMode: "Admins"
|
||||
}), fillItems($(".monitorUsersList", page), users, "chkMonitor", "chkMonitor", notificationConfig.DisabledMonitorUsers), fillItems($(".sendToUsersList", page), users, "chkSendTo", "chkSendTo", notificationConfig.SendToUsers, !0), fillItems($(".servicesList", page), services, "chkService", "chkService", notificationConfig.DisabledServices), $("#chkEnabled", page).checked(notificationConfig.Enabled || !1), $("#selectUsers", page).val(notificationConfig.SendToUserMode).trigger("change")
|
||||
})
|
||||
}
|
||||
|
||||
function save(page) {
|
||||
var type = getParameterByName("type"),
|
||||
promise1 = ApiClient.getNamedConfiguration(notificationsConfigurationKey),
|
||||
promise2 = ApiClient.getJSON(ApiClient.getUrl("Notifications/Types"));
|
||||
Promise.all([promise1, promise2]).then(function(responses) {
|
||||
var notificationOptions = responses[0],
|
||||
types = responses[1],
|
||||
notificationConfig = notificationOptions.Options.filter(function(n) {
|
||||
return n.Type == type
|
||||
})[0];
|
||||
notificationConfig || (notificationConfig = {
|
||||
Type: type
|
||||
}, notificationOptions.Options.push(notificationConfig));
|
||||
types.filter(function(n) {
|
||||
return n.Type == type
|
||||
})[0];
|
||||
notificationConfig.Enabled = $("#chkEnabled", page).checked(), notificationConfig.SendToUserMode = $("#selectUsers", page).val(), notificationConfig.DisabledMonitorUsers = $(".chkMonitor", page).get().filter(function(c) {
|
||||
return !c.checked
|
||||
}).map(function(c) {
|
||||
return c.getAttribute("data-itemid")
|
||||
}), notificationConfig.SendToUsers = $(".chkSendTo", page).get().filter(function(c) {
|
||||
return c.checked
|
||||
}).map(function(c) {
|
||||
return c.getAttribute("data-itemid")
|
||||
}), notificationConfig.DisabledServices = $(".chkService", page).get().filter(function(c) {
|
||||
return !c.checked
|
||||
}).map(function(c) {
|
||||
return c.getAttribute("data-itemid")
|
||||
}), ApiClient.updateNamedConfiguration(notificationsConfigurationKey, notificationOptions).then(function(r) {
|
||||
Dashboard.processServerConfigurationUpdateResult(), Dashboard.navigate("notificationsettings.html")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
return save($(this).parents(".page")), !1
|
||||
}
|
||||
var notificationsConfigurationKey = "notifications";
|
||||
$(document).on("pageinit", "#notificationSettingPage", function() {
|
||||
var page = this;
|
||||
$("#selectUsers", page).on("change", function() {
|
||||
"Custom" == this.value ? $(".selectCustomUsers", page).show() : $(".selectCustomUsers", page).hide()
|
||||
}), $(".notificationSettingForm").off("submit", onSubmit).on("submit", onSubmit)
|
||||
}).on("pageshow", "#notificationSettingPage", function() {
|
||||
reload(this)
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
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 = "",
|
||||
lastCategory = "",
|
||||
showHelp = !0;
|
||||
html += list.map(function(i) {
|
||||
var itemHtml = "";
|
||||
return i.Category != lastCategory && (lastCategory = i.Category, lastCategory && (itemHtml += "</div>", itemHtml += "</div>"), itemHtml += '<div class="verticalSection verticalSection-extrabottompadding">', itemHtml += '<div class="sectionTitleContainer" style="margin-bottom:1em;">', itemHtml += '<h2 class="sectionTitle">', itemHtml += i.Category, itemHtml += "</h2>", showHelp && (showHelp = !1, 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">' + globalize.translate("Help") + "</a>"), itemHtml += "</div>", itemHtml += '<div class="paperList">'), itemHtml += '<a class="listItem listItem-border" is="emby-linkbutton" data-ripple="false" href="notificationsetting.html?type=' + i.Type + '">', i.Enabled ? itemHtml += '<i class="listItemIcon md-icon">notifications_active</i>' : itemHtml += '<i class="listItemIcon md-icon" style="background-color:#999;">notifications_off</i>', itemHtml += '<div class="listItemBody">', itemHtml += '<div class="listItemBodyText">' + i.Name + "</div>", itemHtml += "</div>", itemHtml += '<button type="button" is="paper-icon-button-light"><i class="md-icon">mode_edit</i></button>', itemHtml += "</a>"
|
||||
}).join(""), list.length && (html += "</div>", html += "</div>"), page.querySelector(".notificationList").innerHTML = html, loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "notificationsettings.html",
|
||||
name: globalize.translate("TabNotifications")
|
||||
}, {
|
||||
href: "appservices.html?context=notifications",
|
||||
name: globalize.translate("TabServices")
|
||||
}]
|
||||
}
|
||||
return function(view, params) {
|
||||
view.addEventListener("viewshow", function() {
|
||||
libraryMenu.setTabs("notifications", 0, getTabs), reload(view)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -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()
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,34 @@
|
||||
define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function loadPage(page, config) {
|
||||
$("#txtMinResumePct", page).val(config.MinResumePct), $("#txtMaxResumePct", page).val(config.MaxResumePct), $("#txtMinResumeDuration", page).val(config.MinResumeDurationSeconds), loading.hide()
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
loading.show();
|
||||
var form = this;
|
||||
return ApiClient.getServerConfiguration().then(function(config) {
|
||||
config.MinResumePct = $("#txtMinResumePct", form).val(), config.MaxResumePct = $("#txtMaxResumePct", form).val(), config.MinResumeDurationSeconds = $("#txtMinResumeDuration", form).val(), ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult)
|
||||
}), !1
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "playbackconfiguration.html",
|
||||
name: Globalize.translate("TabResumeSettings")
|
||||
}, {
|
||||
href: "streamingsettings.html",
|
||||
name: Globalize.translate("TabStreaming")
|
||||
}]
|
||||
}
|
||||
$(document).on("pageinit", "#playbackConfigurationPage", function() {
|
||||
$(".playbackConfigurationForm").off("submit", onSubmit).on("submit", onSubmit)
|
||||
}).on("pageshow", "#playbackConfigurationPage", function() {
|
||||
libraryMenu.setTabs("playback", 0, getTabs), loading.show();
|
||||
var page = this;
|
||||
ApiClient.getServerConfiguration().then(function(config) {
|
||||
loadPage(page, config)
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
define(["listView"], function(listView) {
|
||||
"use strict";
|
||||
|
||||
function getFetchPlaylistItemsFn(itemId) {
|
||||
return function() {
|
||||
var query = {
|
||||
Fields: "PrimaryImageAspectRatio,UserData",
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
UserId: ApiClient.getCurrentUserId()
|
||||
};
|
||||
return ApiClient.getJSON(ApiClient.getUrl("Playlists/" + itemId + "/Items", query))
|
||||
}
|
||||
}
|
||||
|
||||
function getItemsHtmlFn(itemId) {
|
||||
return function(items) {
|
||||
return listView.getListViewHtml({
|
||||
items: items,
|
||||
showIndex: !1,
|
||||
showRemoveFromPlaylist: !0,
|
||||
playFromHere: !0,
|
||||
action: "playallfromhere",
|
||||
smallIcon: !0,
|
||||
dragHandle: !0,
|
||||
playlistId: itemId
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function init(page, item) {
|
||||
var elem = page.querySelector("#childrenContent .itemsContainer");
|
||||
elem.classList.add("vertical-list"), elem.classList.remove("vertical-wrap"), elem.enableDragReordering(!0), elem.fetchData = getFetchPlaylistItemsFn(item.Id), elem.getItemsHtml = getItemsHtmlFn(item.Id)
|
||||
}
|
||||
window.PlaylistViewer = {
|
||||
render: function(page, item) {
|
||||
page.playlistInit || (page.playlistInit = !0, init(page, item)), page.querySelector("#childrenContent").classList.add("verticalSection-extrabottompadding"), page.querySelector("#childrenContent .itemsContainer").refreshItems()
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,126 @@
|
||||
define(["loading", "listView", "cardBuilder", "libraryMenu", "libraryBrowser", "apphost", "imageLoader", "emby-itemscontainer"], function(loading, listView, cardBuilder, libraryMenu, libraryBrowser, appHost, imageLoader) {
|
||||
"use strict";
|
||||
return function(view, params) {
|
||||
function getPageData(context) {
|
||||
var key = getSavedQueryKey(context),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Playlist",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,SortName,CumulativeRunTimeTicks,CanDelete",
|
||||
StartIndex: 0,
|
||||
Limit: 100
|
||||
},
|
||||
view: libraryBrowser.getSavedView(key) || "Poster"
|
||||
}, pageData.query.ParentId = libraryMenu.getTopParentId(), libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery(context) {
|
||||
return getPageData(context).query
|
||||
}
|
||||
|
||||
function getSavedQueryKey(context) {
|
||||
return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey()), context.savedQueryKey
|
||||
}
|
||||
|
||||
function showLoadingMessage() {
|
||||
loading.show()
|
||||
}
|
||||
|
||||
function hideLoadingMessage() {
|
||||
loading.hide()
|
||||
}
|
||||
|
||||
function onViewStyleChange() {
|
||||
var viewStyle = getPageData(view).view,
|
||||
itemsContainer = view.querySelector(".itemsContainer");
|
||||
"List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = ""
|
||||
}
|
||||
|
||||
function reloadItems() {
|
||||
showLoadingMessage();
|
||||
var query = getQuery(view),
|
||||
promise1 = ApiClient.getItems(Dashboard.getCurrentUserId(), query),
|
||||
promise2 = Dashboard.getCurrentUser();
|
||||
Promise.all([promise1, promise2]).then(function(responses) {
|
||||
var result = responses[0];
|
||||
responses[1];
|
||||
window.scrollTo(0, 0);
|
||||
var html = "",
|
||||
viewStyle = getPageData(view).view;
|
||||
view.querySelector(".listTopPaging").innerHTML = libraryBrowser.getQueryPagingHtml({
|
||||
startIndex: query.StartIndex,
|
||||
limit: query.Limit,
|
||||
totalRecordCount: result.TotalRecordCount,
|
||||
viewButton: !1,
|
||||
showLimit: !1,
|
||||
updatePageSizeSetting: !1,
|
||||
addLayoutButton: !0,
|
||||
layouts: "List,Poster,PosterCard,Thumb,ThumbCard",
|
||||
currentLayout: viewStyle
|
||||
}), result.TotalRecordCount ? (html = "List" == viewStyle ? listView.getListViewHtml({
|
||||
items: result.Items,
|
||||
sortBy: query.SortBy
|
||||
}) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "square",
|
||||
coverImage: !0,
|
||||
showTitle: !0,
|
||||
cardLayout: !0,
|
||||
vibrant: !0
|
||||
}) : "Thumb" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
showTitle: !0,
|
||||
centerText: !0,
|
||||
preferThumb: !0,
|
||||
overlayPlayButton: !0
|
||||
}) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
showTitle: !0,
|
||||
preferThumb: !0,
|
||||
cardLayout: !0,
|
||||
vibrant: !0
|
||||
}) : cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "square",
|
||||
showTitle: !0,
|
||||
coverImage: !0,
|
||||
centerText: !0,
|
||||
overlayPlayButton: !0
|
||||
}), view.querySelector(".noItemsMessage").classList.add("hide")) : view.querySelector(".noItemsMessage").classList.remove("hide");
|
||||
var elem = view.querySelector(".itemsContainer");
|
||||
elem.innerHTML = html, imageLoader.lazyChildren(elem);
|
||||
var btnNextPage = view.querySelector(".btnNextPage");
|
||||
btnNextPage && btnNextPage.addEventListener("click", function() {
|
||||
query.StartIndex += query.Limit, reloadItems()
|
||||
});
|
||||
var btnPreviousPage = view.querySelector(".btnPreviousPage");
|
||||
btnPreviousPage && btnPreviousPage.addEventListener("click", function() {
|
||||
query.StartIndex -= query.Limit, reloadItems()
|
||||
});
|
||||
var btnChangeLayout = view.querySelector(".btnChangeLayout");
|
||||
btnChangeLayout && btnChangeLayout.addEventListener("layoutchange", function(e) {
|
||||
var layout = e.detail.viewStyle;
|
||||
getPageData(view).view = layout, libraryBrowser.saveViewSetting(getSavedQueryKey(view), layout), onViewStyleChange(), reloadItems()
|
||||
}), libraryBrowser.saveQueryValues(getSavedQueryKey(view), query), hideLoadingMessage()
|
||||
})
|
||||
}
|
||||
var data = {};
|
||||
view.addEventListener("viewbeforeshow", function() {
|
||||
reloadItems()
|
||||
}), view.querySelector(".btnNewPlaylist").addEventListener("click", function() {
|
||||
require(["playlistEditor"], function(playlistEditor) {
|
||||
var serverId = ApiClient.serverInfo().Id;
|
||||
(new playlistEditor).show({
|
||||
items: [],
|
||||
serverId: serverId
|
||||
})
|
||||
})
|
||||
}), onViewStyleChange()
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,101 @@
|
||||
define(["loading", "libraryMenu", "globalize", "cardStyle", "emby-linkbutton", "emby-checkbox", "emby-select"], function(loading, libraryMenu, globalize) {
|
||||
"use strict";
|
||||
|
||||
function reloadList(page) {
|
||||
loading.show(), query.IsAppStoreSafe = !0;
|
||||
var promise1 = ApiClient.getAvailablePlugins(query),
|
||||
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 populateList(options) {
|
||||
populateListInternal(options)
|
||||
}
|
||||
|
||||
function getHeaderText(category) {
|
||||
category.replace(" ", "").replace(" ", "");
|
||||
return "Channel" === category ? category = "Channels" : "Theme" === category ? category = "Themes" : "LiveTV" === category ? category = "HeaderLiveTV" : "ScreenSaver" === category && (category = "HeaderScreenSavers"), globalize.translate(category)
|
||||
}
|
||||
|
||||
function isUserInstalledPlugin(plugin) {
|
||||
return -1 === ["02528C96-F727-44D7-BE87-9EEF040758C3", "0277E613-3EC0-4360-A3DE-F8AF0AABB5E9", "4DCB591C-0FA2-4C5D-A7E5-DABE37164C8B"].indexOf(plugin.guid)
|
||||
}
|
||||
|
||||
function populateListInternal(options) {
|
||||
var availablePlugins = options.availablePlugins,
|
||||
installedPlugins = options.installedPlugins,
|
||||
allPlugins = availablePlugins.filter(function(p) {
|
||||
return p.category = p.category || "General", p.categoryDisplayName = getHeaderText(p.category), (!options.categories || -1 != options.categories.indexOf(p.category)) && ((!options.targetSystem || p.targetSystem == options.targetSystem) && "UserInstalled" == p.type)
|
||||
});
|
||||
availablePlugins = allPlugins.sort(function(a, b) {
|
||||
var aName = a.category,
|
||||
bName = b.category;
|
||||
return aName > bName ? 1 : bName > aName ? -1 : (aName = a.name, bName = b.name, aName > bName ? 1 : bName > aName ? -1 : 0)
|
||||
});
|
||||
var i, length, plugin, currentCategory, html = "";
|
||||
if (!options.categories) {
|
||||
currentCategory = globalize.translate("HeaderTopPlugins"), html += '<div class="verticalSection">', html += '<h2 class="sectionTitle sectionTitle-cards">' + currentCategory + "</h2>";
|
||||
var topPlugins = allPlugins.slice(0).sort(function(a, b) {
|
||||
if (a.installs > b.installs) return -1;
|
||||
if (b.installs > a.installs) return 1;
|
||||
var aName = a.name,
|
||||
bName = b.name;
|
||||
return aName > bName ? 1 : bName > aName ? -1 : 0
|
||||
}).filter(isUserInstalledPlugin);
|
||||
html += '<div class="itemsContainer vertical-wrap">';
|
||||
var limit = screen.availWidth >= 1920 ? 15 : 12;
|
||||
for (i = 0, length = Math.min(topPlugins.length, limit); i < length; i++) html += getPluginHtml(topPlugins[i], options, installedPlugins);
|
||||
html += "</div>", html += "</div>"
|
||||
}
|
||||
var hasOpenTag = !1;
|
||||
for (currentCategory = null, !1 === options.showCategory && (html += '<div class="itemsContainer vertical-wrap">', hasOpenTag = !0), i = 0, length = availablePlugins.length; i < length; i++) {
|
||||
plugin = availablePlugins[i];
|
||||
var category = plugin.categoryDisplayName;
|
||||
category != currentCategory && (!1 !== options.showCategory && (currentCategory && (hasOpenTag = !1, html += "</div>", html += "</div>"), html += '<div class="verticalSection">', html += '<h2 class="sectionTitle sectionTitle-cards">' + category + "</h2>", html += '<div class="itemsContainer vertical-wrap">', hasOpenTag = !0), currentCategory = category), html += getPluginHtml(plugin, options, installedPlugins)
|
||||
}
|
||||
hasOpenTag && (html += "</div>", html += "</div>"), !availablePlugins.length && options.noItemsElement && options.noItemsElement.classList.add("hide"), options.catalogElement.innerHTML = html, loading.hide()
|
||||
}
|
||||
|
||||
function getPluginHtml(plugin, options, installedPlugins) {
|
||||
var html = "",
|
||||
href = plugin.externalUrl ? plugin.externalUrl : "addplugin.html?name=" + encodeURIComponent(plugin.name) + "&guid=" + plugin.guid;
|
||||
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 + ">", plugin.thumbImage ? (html += '<div class="cardImage coveredImage" style="background-image:url(\'' + plugin.thumbImage + "');\">", html += "</div>") : html += '<i class="cardImageIcon md-icon"></i>', plugin.isPremium && (plugin.price > 0 ? html += "<div class='premiumBanner'><img src='css/images/supporter/premiumflag.png' /></div>" : html += "<div class='premiumBanner'><img src='css/images/supporter/supporterflag.png' /></div>"), 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];
|
||||
return html += "<div class='cardText cardText-secondary'>", html += installedPlugin ? globalize.translate("LabelVersionInstalled").replace("{0}", installedPlugin.Version) : " ", html += "</div>", html += "</div>", html += "</div>", html += "</div>"
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "plugins.html",
|
||||
name: globalize.translate("TabMyPlugins")
|
||||
}, {
|
||||
href: "plugincatalog.html",
|
||||
name: globalize.translate("TabCatalog")
|
||||
}]
|
||||
}
|
||||
var query = {
|
||||
TargetSystems: "Server",
|
||||
IsAdult: !1
|
||||
};
|
||||
return window.PluginCatalog = {
|
||||
renderCatalog: populateList
|
||||
},
|
||||
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)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,120 @@
|
||||
define(["loading", "libraryMenu", "dom", "globalize", "cardStyle", "emby-linkbutton"], function(loading, libraryMenu, dom, globalize) {
|
||||
"use strict";
|
||||
|
||||
function deletePlugin(page, uniqueid, name) {
|
||||
var msg = globalize.translate("UninstallPluginConfirmation").replace("{0}", name);
|
||||
require(["confirm"], function(confirm) {
|
||||
confirm({
|
||||
title: globalize.translate("UninstallPluginHeader"),
|
||||
text: msg,
|
||||
primary: "cancel",
|
||||
confirmText: globalize.translate("UninstallPluginHeader")
|
||||
}).then(function() {
|
||||
loading.show(), ApiClient.uninstallPlugin(uniqueid).then(function() {
|
||||
reloadList(page)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function showNoConfigurationMessage() {
|
||||
Dashboard.alert({
|
||||
message: globalize.translate("NoPluginConfigurationMessage")
|
||||
})
|
||||
}
|
||||
|
||||
function showConnectMessage() {
|
||||
Dashboard.alert({
|
||||
message: globalize.translate("MessagePluginConfigurationRequiresLocalAccess")
|
||||
})
|
||||
}
|
||||
|
||||
function getPluginCardHtml(plugin, pluginConfigurationPages) {
|
||||
var configPage = pluginConfigurationPages.filter(function(pluginConfigurationPage) {
|
||||
return pluginConfigurationPage.PluginId == plugin.Id
|
||||
})[0],
|
||||
html = "",
|
||||
disallowPlugins = !Dashboard.allowPluginPages(plugin.Id),
|
||||
configPageUrl = configPage ? Dashboard.getConfigurationPageUrl(configPage.Name) : null,
|
||||
href = configPage && !disallowPlugins ? configPageUrl : null;
|
||||
return html += "<div data-id='" + plugin.Id + "' data-name='" + plugin.Name + "' class='card backdropCard'>", html += '<div class="cardBox visualCardBox">', html += '<div class="cardScalable">', html += '<div class="cardPadder cardPadder-backdrop"></div>', html += href ? '<a class="cardContent cardImageContainer" is="emby-linkbutton" href="' + href + '">' : configPageUrl ? disallowPlugins ? '<div class="cardContent connectModePluginCard cardImageContainer">' : '<div class="cardContent cardImageContainer">' : '<div class="cardContent noConfigPluginCard noHoverEffect cardImageContainer">', plugin.ImageUrl ? (html += '<div class="cardImage coveredImage" style="background-image:url(\'' + plugin.ImageUrl + "');\">", html += "</div>") : html += '<i class="cardImageIcon md-icon"></i>', html += href ? "</a>" : "</div>", html += "</div>", html += '<div class="cardFooter">', html += '<div style="text-align:right; float:right;padding-top:5px;">', html += '<button type="button" is="paper-icon-button-light" class="btnCardMenu autoSize"><i class="md-icon">more_horiz</i></button>', html += "</div>", html += "<div class='cardText'>", html += configPage ? configPage.DisplayName || plugin.Name : plugin.Name, html += "</div>", html += "<div class='cardText cardText-secondary'>", html += plugin.Version, html += "</div>", html += "</div>", html += "</div>", html += "</div>"
|
||||
}
|
||||
|
||||
function renderPlugins(page, plugins, showNoPluginsMessage) {
|
||||
ApiClient.getJSON(ApiClient.getUrl("web/configurationpages") + "?pageType=PluginConfiguration").then(function(configPages) {
|
||||
populateList(page, plugins, configPages, showNoPluginsMessage)
|
||||
})
|
||||
}
|
||||
|
||||
function populateList(page, plugins, pluginConfigurationPages, showNoPluginsMessage) {
|
||||
plugins = plugins.sort(function(plugin1, plugin2) {
|
||||
return plugin1.Name > plugin2.Name ? 1 : -1
|
||||
});
|
||||
var html = plugins.map(function(p) {
|
||||
return getPluginCardHtml(p, pluginConfigurationPages)
|
||||
}).join(""),
|
||||
installedPluginsElement = page.querySelector(".installedPlugins");
|
||||
installedPluginsElement.removeEventListener("click", onInstalledPluginsClick), installedPluginsElement.addEventListener("click", onInstalledPluginsClick), plugins.length ? (installedPluginsElement.classList.add("itemsContainer"), installedPluginsElement.classList.add("vertical-wrap"), installedPluginsElement.innerHTML = html) : (showNoPluginsMessage && (html += '<div style="padding:5px;">', html += "<p>" + globalize.translate("MessageNoPluginsInstalled") + "</p>", html += '<p><a is="emby-linkbutton" class="button-link" href="plugincatalog.html">', html += globalize.translate("BrowsePluginCatalogMessage"), html += "</a></p>", html += "</div>"), installedPluginsElement.innerHTML = html), loading.hide()
|
||||
}
|
||||
|
||||
function showPluginMenu(page, elem) {
|
||||
var card = dom.parentWithClass(elem, "card"),
|
||||
id = card.getAttribute("data-id"),
|
||||
name = card.getAttribute("data-name"),
|
||||
configHref = card.querySelector(".cardContent").getAttribute("href"),
|
||||
menuItems = [];
|
||||
configHref && menuItems.push({
|
||||
name: globalize.translate("ButtonSettings"),
|
||||
id: "open",
|
||||
ironIcon: "mode-edit"
|
||||
}), menuItems.push({
|
||||
name: globalize.translate("ButtonUninstall"),
|
||||
id: "delete",
|
||||
ironIcon: "delete"
|
||||
}), require(["actionsheet"], function(actionsheet) {
|
||||
actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: elem,
|
||||
callback: function(resultId) {
|
||||
switch (resultId) {
|
||||
case "open":
|
||||
Dashboard.navigate(configHref);
|
||||
break;
|
||||
case "delete":
|
||||
deletePlugin(page, id, name)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function reloadList(page) {
|
||||
loading.show(), ApiClient.getInstalledPlugins().then(function(plugins) {
|
||||
renderPlugins(page, plugins, !0)
|
||||
})
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "plugins.html",
|
||||
name: globalize.translate("TabMyPlugins")
|
||||
}, {
|
||||
href: "plugincatalog.html",
|
||||
name: globalize.translate("TabCatalog")
|
||||
}]
|
||||
}
|
||||
|
||||
function onInstalledPluginsClick(e) {
|
||||
if (dom.parentWithClass(e.target, "noConfigPluginCard")) showNoConfigurationMessage();
|
||||
else if (dom.parentWithClass(e.target, "connectModePluginCard")) showConnectMessage();
|
||||
else {
|
||||
var btnCardMenu = dom.parentWithClass(e.target, "btnCardMenu");
|
||||
btnCardMenu && showPluginMenu(dom.parentWithClass(btnCardMenu, "page"), btnCardMenu)
|
||||
}
|
||||
}
|
||||
pageIdOn("pageshow", "pluginsPage", function() {
|
||||
libraryMenu.setTabs("plugins", 0, getTabs), reloadList(this)
|
||||
}), window.PluginsPage = {
|
||||
renderPlugins: renderPlugins
|
||||
}
|
||||
});
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
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:#009F00;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)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
define(["searchFields", "searchResults", "events"], function(SearchFields, SearchResults, events) {
|
||||
"use strict";
|
||||
|
||||
function init(instance, tabContent, options) {
|
||||
tabContent.innerHTML = '<div class="padded-left padded-right searchFields"></div><div class="searchResults padded-top" style="padding-top:1.5em;"></div>', instance.searchFields = new SearchFields({
|
||||
element: tabContent.querySelector(".searchFields")
|
||||
}), instance.searchResults = new SearchResults({
|
||||
element: tabContent.querySelector(".searchResults"),
|
||||
serverId: ApiClient.serverId(),
|
||||
parentId: options.parentId,
|
||||
collectionType: options.collectionType
|
||||
}), events.on(instance.searchFields, "search", function(e, value) {
|
||||
instance.searchResults.search(value)
|
||||
})
|
||||
}
|
||||
|
||||
function SearchTab(view, tabContent, options) {
|
||||
var self = this;
|
||||
options = options || {}, init(this, tabContent, options), self.preRender = function() {}, self.renderTab = function() {
|
||||
var searchFields = this.searchFields;
|
||||
searchFields && searchFields.focus()
|
||||
}
|
||||
}
|
||||
return SearchTab.prototype.destroy = function() {
|
||||
var searchFields = this.searchFields;
|
||||
searchFields && searchFields.destroy(), this.searchFields = null;
|
||||
var searchResults = this.searchResults;
|
||||
searchResults && searchResults.destroy(), this.searchResults = null
|
||||
}, SearchTab
|
||||
});
|
||||
@@ -0,0 +1,244 @@
|
||||
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("sharedcomponents#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("sharedcomponents#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 acceptInvitation(id) {
|
||||
loading.show(), connectionManager.acceptServer(id).then(function() {
|
||||
loading.hide(), loadServers(), loadInvitations()
|
||||
}, showGeneralError)
|
||||
}
|
||||
|
||||
function rejectInvitation(id) {
|
||||
loading.show(), connectionManager.rejectServer(id).then(function() {
|
||||
loading.hide(), loadServers(), loadInvitations()
|
||||
}, showGeneralError)
|
||||
}
|
||||
|
||||
function showPendingInviteMenu(elem) {
|
||||
var card = dom.parentWithClass(elem, "inviteItem"),
|
||||
invitationId = card.getAttribute("data-id"),
|
||||
menuItems = [];
|
||||
menuItems.push({
|
||||
name: globalize.translate("sharedcomponents#Accept"),
|
||||
id: "accept"
|
||||
}), menuItems.push({
|
||||
name: globalize.translate("sharedcomponents#Reject"),
|
||||
id: "reject"
|
||||
}), require(["actionsheet"], function(actionsheet) {
|
||||
actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: elem,
|
||||
callback: function(id) {
|
||||
switch (id) {
|
||||
case "accept":
|
||||
acceptInvitation(invitationId);
|
||||
break;
|
||||
case "reject":
|
||||
rejectInvitation(invitationId)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getPendingInviteHtml(item) {
|
||||
var cardBoxCssClass = "cardBox";
|
||||
layoutManager.tv && (cardBoxCssClass += " cardBox-focustransform");
|
||||
var innerOpening = '<div class="' + cardBoxCssClass + '">';
|
||||
return '<button raised class="card overflowSquareCard loginSquareCard scalableCard overflowSquareCard-scalable btnInviteMenu inviteItem" style="display:inline-block;" data-id="' + item.Id + '">' + 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;"><i class="cardImageIcon md-icon"></i></div></div></div><div class="cardFooter"><div class="cardText cardTextCentered">' + item.Name + "</div></div></div></button>"
|
||||
}
|
||||
|
||||
function renderInvitations(list) {
|
||||
list.length ? view.querySelector(".invitationSection").classList.remove("hide") : view.querySelector(".invitationSection").classList.add("hide");
|
||||
var html = list.map(getPendingInviteHtml).join("");
|
||||
view.querySelector(".invitations").innerHTML = html
|
||||
}
|
||||
|
||||
function loadInvitations() {
|
||||
connectionManager.isLoggedIntoConnect() ? connectionManager.getUserInvitations().then(renderInvitations) : renderInvitations([])
|
||||
}
|
||||
|
||||
function onServerClick(server) {
|
||||
var menuItems = [];
|
||||
menuItems.push({
|
||||
name: globalize.translate("sharedcomponents#Connect"),
|
||||
id: "connect"
|
||||
}), menuItems.push({
|
||||
name: globalize.translate("sharedcomponents#Delete"),
|
||||
id: "delete"
|
||||
});
|
||||
var apiClient = connectionManager.getApiClient(server.Id);
|
||||
apiClient && apiClient.supportsWakeOnLan() && menuItems.push({
|
||||
name: globalize.translate("sharedcomponents#WakeServer"),
|
||||
id: "wol"
|
||||
}), actionSheet.show({
|
||||
items: menuItems,
|
||||
title: server.Name
|
||||
}).then(function(id) {
|
||||
switch (id) {
|
||||
case "connect":
|
||||
connectToServer(server);
|
||||
break;
|
||||
case "delete":
|
||||
deleteServer(server);
|
||||
break;
|
||||
case "wol":
|
||||
sendWolPacket(server)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function sendWolPacket(server) {
|
||||
var apiClient = connectionManager.getApiClient(server.Id);
|
||||
require(["loadingDialog"], function(LoadingDialog) {
|
||||
var dlg = new LoadingDialog({
|
||||
title: globalize.translate("sharedcomponents#HeaderWakeServer"),
|
||||
text: globalize.translate("sharedcomponents#AttemptingWakeServer")
|
||||
});
|
||||
dlg.show();
|
||||
var afterWol = function() {
|
||||
setTimeout(function() {
|
||||
apiClient.getPublicSystemInfo().then(onWolSuccess.bind(dlg), onWolFail.bind(dlg))
|
||||
}, 12e3)
|
||||
};
|
||||
apiClient.wakeOnLan().then(afterWol, afterWol)
|
||||
})
|
||||
}
|
||||
|
||||
function onWolSuccess() {
|
||||
var dlg = this;
|
||||
dlg.hide(), dlg.destroy(), require(["alert"], function(alert) {
|
||||
alert({
|
||||
text: globalize.translate("sharedcomponents#WakeServerSuccess"),
|
||||
title: globalize.translate("sharedcomponents#HeaderWakeServer")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onWolFail() {
|
||||
var dlg = this;
|
||||
dlg.hide(), dlg.destroy(), require(["alert"], function(alert) {
|
||||
alert({
|
||||
text: globalize.translate("sharedcomponents#WakeServerError"),
|
||||
title: globalize.translate("sharedcomponents#HeaderWakeServer")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
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;
|
||||
(function() {
|
||||
updatePageStyle(view, params), view.querySelector(".btnOfflineText").innerHTML = globalize.translate("sharedcomponents#HeaderMyDownloads"), appHost.supports("sync") && view.querySelector(".btnOffline").classList.remove("hide")
|
||||
})();
|
||||
var backdropUrl = staticBackdrops.getRandomImageUrl();
|
||||
view.addEventListener("viewshow", function(e) {
|
||||
var isRestored = e.detail.isRestored;
|
||||
appRouter.setTitle(null), backdrop.setBackdrop(backdropUrl), isRestored || (loadServers(), loadInvitations())
|
||||
}), view.querySelector(".btnOffline").addEventListener("click", function(e) {
|
||||
appRouter.show("/offline/offline.html")
|
||||
}), 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])
|
||||
}
|
||||
}
|
||||
}), view.querySelector(".invitations").addEventListener("click", function(e) {
|
||||
var btnInviteMenu = dom.parentWithClass(e.target, "btnInviteMenu");
|
||||
btnInviteMenu && showPendingInviteMenu(btnInviteMenu)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
define(["datetime", "loading", "libraryMenu", "dom", "globalize", "emby-button"], function(datetime, loading, libraryMenu, dom, globalize) {
|
||||
"use strict";
|
||||
|
||||
function revoke(page, key) {
|
||||
require(["confirm"], function(confirm) {
|
||||
confirm(globalize.translate("MessageConfirmRevokeApiKey"), globalize.translate("HeaderConfirmRevokeApiKey")).then(function() {
|
||||
loading.show(), ApiClient.ajax({
|
||||
type: "DELETE",
|
||||
url: ApiClient.getUrl("Auth/Keys/" + key)
|
||||
}).then(function() {
|
||||
loadData(page)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function renderKeys(page, keys) {
|
||||
var rows = keys.map(function(item) {
|
||||
var html = "";
|
||||
html += '<tr class="detailTableBodyRow detailTableBodyRow-shaded">', html += '<td class="detailTableBodyCell">', html += '<button type="button" is="emby-button" data-token="' + item.AccessToken + '" class="raised raised-mini btnRevoke" data-mini="true" title="' + globalize.translate("ButtonRevoke") + '" style="margin:0;">' + globalize.translate("ButtonRevoke") + "</button>", html += "</td>", html += '<td class="detailTableBodyCell" style="vertical-align:middle;">', html += item.AccessToken, html += "</td>", html += '<td class="detailTableBodyCell" style="vertical-align:middle;">', html += item.AppName || "", html += "</td>", html += '<td class="detailTableBodyCell" style="vertical-align:middle;">';
|
||||
var date = datetime.parseISO8601Date(item.DateCreated, !0);
|
||||
return html += datetime.toLocaleDateString(date) + " " + datetime.getDisplayTime(date), html += "</td>", html += "</tr>"
|
||||
}).join("");
|
||||
page.querySelector(".resultBody").innerHTML = rows, loading.hide()
|
||||
}
|
||||
|
||||
function loadData(page) {
|
||||
loading.show(), ApiClient.getJSON(ApiClient.getUrl("Auth/Keys")).then(function(result) {
|
||||
renderKeys(page, result.Items)
|
||||
})
|
||||
}
|
||||
|
||||
function showNewKeyPrompt(page) {
|
||||
require(["prompt"], function(prompt) {
|
||||
prompt({
|
||||
title: globalize.translate("HeaderNewApiKey"),
|
||||
label: globalize.translate("LabelAppName"),
|
||||
description: globalize.translate("LabelAppNameExample")
|
||||
}).then(function(value) {
|
||||
ApiClient.ajax({
|
||||
type: "POST",
|
||||
url: ApiClient.getUrl("Auth/Keys", {
|
||||
App: value
|
||||
})
|
||||
}).then(function() {
|
||||
loadData(page)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "dashboardhosting.html",
|
||||
name: globalize.translate("TabHosting")
|
||||
}, {
|
||||
href: "serversecurity.html",
|
||||
name: globalize.translate("TabSecurity")
|
||||
}]
|
||||
}
|
||||
pageIdOn("pageinit", "serverSecurityPage", function() {
|
||||
var page = this;
|
||||
page.querySelector(".btnNewKey").addEventListener("click", function() {
|
||||
showNewKeyPrompt(page)
|
||||
}), page.querySelector(".tblApiKeys").addEventListener("click", function(e) {
|
||||
var btnRevoke = dom.parentWithClass(e.target, "btnRevoke");
|
||||
btnRevoke && revoke(page, btnRevoke.getAttribute("data-token"))
|
||||
})
|
||||
}), pageIdOn("pagebeforeshow", "serverSecurityPage", function() {
|
||||
libraryMenu.setTabs("adminadvanced", 1, getTabs), loadData(this)
|
||||
})
|
||||
});
|
||||
+1108
File diff suppressed because one or more lines are too long
@@ -0,0 +1,127 @@
|
||||
define(["events", "libraryBrowser", "imageLoader", "listView", "loading", "emby-itemscontainer"], function(events, libraryBrowser, imageLoader, listView, loading) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData(context) {
|
||||
var key = getSavedQueryKey(context),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "Album,SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Audio",
|
||||
Recursive: !0,
|
||||
Fields: "AudioInfo,ParentId",
|
||||
Limit: 100,
|
||||
StartIndex: 0,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary"
|
||||
}
|
||||
}, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery(context) {
|
||||
return getPageData(context).query
|
||||
}
|
||||
|
||||
function getSavedQueryKey(context) {
|
||||
return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("songs")), context.savedQueryKey
|
||||
}
|
||||
|
||||
function reloadItems(page) {
|
||||
loading.show();
|
||||
var query = getQuery(page);
|
||||
ApiClient.getItems(Dashboard.getCurrentUserId(), query).then(function(result) {
|
||||
function onNextPageClick() {
|
||||
query.StartIndex += query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
|
||||
function onPreviousPageClick() {
|
||||
query.StartIndex -= query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
window.scrollTo(0, 0);
|
||||
var i, length, pagingHtml = libraryBrowser.getQueryPagingHtml({
|
||||
startIndex: query.StartIndex,
|
||||
limit: query.Limit,
|
||||
totalRecordCount: result.TotalRecordCount,
|
||||
showLimit: !1,
|
||||
updatePageSizeSetting: !1,
|
||||
addLayoutButton: !1,
|
||||
sortButton: !1,
|
||||
filterButton: !1
|
||||
}),
|
||||
html = listView.getListViewHtml({
|
||||
items: result.Items,
|
||||
action: "playallfromhere",
|
||||
smallIcon: !0,
|
||||
artist: !0,
|
||||
addToListButton: !0
|
||||
}),
|
||||
elems = tabContent.querySelectorAll(".paging");
|
||||
for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml;
|
||||
for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick);
|
||||
for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick);
|
||||
var itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(page), query), loading.hide()
|
||||
})
|
||||
}
|
||||
var self = this,
|
||||
data = {};
|
||||
self.showFilterMenu = function() {
|
||||
require(["components/filterdialog/filterdialog"], function(filterDialogFactory) {
|
||||
var filterDialog = new filterDialogFactory({
|
||||
query: getQuery(tabContent),
|
||||
mode: "songs",
|
||||
serverId: ApiClient.serverId()
|
||||
});
|
||||
events.on(filterDialog, "filterchange", function() {
|
||||
getQuery(tabContent).StartIndex = 0, reloadItems(tabContent)
|
||||
}), filterDialog.show()
|
||||
})
|
||||
}, self.getCurrentViewStyle = function() {
|
||||
return getPageData(tabContent).view
|
||||
},
|
||||
function(tabContent) {
|
||||
tabContent.querySelector(".btnFilter").addEventListener("click", function() {
|
||||
self.showFilterMenu()
|
||||
}), tabContent.querySelector(".btnSort").addEventListener("click", function(e) {
|
||||
libraryBrowser.showSortMenu({
|
||||
items: [{
|
||||
name: Globalize.translate("OptionTrackName"),
|
||||
id: "Name"
|
||||
}, {
|
||||
name: Globalize.translate("OptionAlbum"),
|
||||
id: "Album,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionAlbumArtist"),
|
||||
id: "AlbumArtist,Album,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionArtist"),
|
||||
id: "Artist,Album,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDateAdded"),
|
||||
id: "DateCreated,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDatePlayed"),
|
||||
id: "DatePlayed,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionPlayCount"),
|
||||
id: "PlayCount,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionReleaseDate"),
|
||||
id: "PremiereDate,AlbumArtist,Album,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionRuntime"),
|
||||
id: "Runtime,AlbumArtist,Album,SortName"
|
||||
}],
|
||||
callback: function() {
|
||||
getQuery(tabContent).StartIndex = 0, reloadItems(tabContent)
|
||||
},
|
||||
query: getQuery(tabContent),
|
||||
button: e.target
|
||||
})
|
||||
})
|
||||
}(tabContent), self.renderTab = function() {
|
||||
reloadItems(tabContent)
|
||||
}, self.destroy = function() {}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
define(["jQuery", "libraryMenu", "loading"], function($, libraryMenu, loading) {
|
||||
"use strict";
|
||||
|
||||
function loadPage(page, config) {
|
||||
$("#txtRemoteClientBitrateLimit", page).val(config.RemoteClientBitrateLimit / 1e6 || ""), loading.hide()
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
loading.show();
|
||||
var form = this;
|
||||
return ApiClient.getServerConfiguration().then(function(config) {
|
||||
config.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($("#txtRemoteClientBitrateLimit", form).val() || "0")), ApiClient.updateServerConfiguration(config).then(Dashboard.processServerConfigurationUpdateResult)
|
||||
}), !1
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "playbackconfiguration.html",
|
||||
name: Globalize.translate("TabResumeSettings")
|
||||
}, {
|
||||
href: "streamingsettings.html",
|
||||
name: Globalize.translate("TabStreaming")
|
||||
}]
|
||||
}
|
||||
$(document).on("pageinit", "#streamingSettingsPage", function() {
|
||||
var page = this;
|
||||
$("#btnSelectTranscodingTempPath", page).on("click.selectDirectory", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
callback: function(path) {
|
||||
path && $("#txtTranscodingTempPath", page).val(path), picker.close()
|
||||
},
|
||||
validateWriteable: !0,
|
||||
header: Globalize.translate("HeaderSelectTranscodingPath"),
|
||||
instruction: Globalize.translate("HeaderSelectTranscodingPathHelp")
|
||||
})
|
||||
})
|
||||
}), $(".streamingSettingsForm").off("submit", onSubmit).on("submit", onSubmit)
|
||||
}).on("pageshow", "#streamingSettingsPage", function() {
|
||||
loading.show(), libraryMenu.setTabs("playback", 1, getTabs);
|
||||
var page = this;
|
||||
ApiClient.getServerConfiguration().then(function(config) {
|
||||
loadPage(page, config)
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
define(["loading", "libraryMenu", "apphost", "globalize", "syncJobList", "events", "scripts/taskbutton", "localsync", "emby-button", "paper-icon-button-light"], function(loading, libraryMenu, appHost, globalize, syncJobList, events, taskButton) {
|
||||
"use strict";
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "syncactivity.html",
|
||||
name: Globalize.translate("TabSyncJobs")
|
||||
}, {
|
||||
href: "appservices.html?context=sync",
|
||||
name: Globalize.translate("TabServices")
|
||||
}, {
|
||||
href: "syncsettings.html",
|
||||
name: Globalize.translate("TabSettings")
|
||||
}]
|
||||
}
|
||||
return function(view, params) {
|
||||
var mySyncJobList = new syncJobList({
|
||||
mode: params.mode,
|
||||
serverId: ApiClient.serverId(),
|
||||
userId: "offline" === params.mode ? null : ApiClient.getCurrentUserId(),
|
||||
element: view.querySelector(".syncActivity"),
|
||||
mode: params.mode
|
||||
});
|
||||
view.addEventListener("viewshow", function() {
|
||||
libraryMenu.setTabs("syncadmin", 0, getTabs), taskButton({
|
||||
mode: "on",
|
||||
progressElem: view.querySelector(".syncProgress"),
|
||||
taskKey: "SyncPrepare",
|
||||
button: view.querySelector(".btnSync")
|
||||
})
|
||||
}), view.addEventListener("viewbeforehide", function() {
|
||||
taskButton({
|
||||
mode: "off",
|
||||
taskKey: "SyncPrepare",
|
||||
button: view.querySelector(".btnSync")
|
||||
})
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
mySyncJobList.destroy()
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
define(["jQuery", "loading", "libraryMenu", "fnchecked", "emby-select"], function($, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function loadPage(page, config) {
|
||||
$("#txtSyncTempPath", page).val(config.TemporaryPath || ""), $("#txtUploadSpeedLimit", page).val(config.UploadSpeedLimitBytes / 1e6 || ""), $("#selectThreadCount", page).val(config.TranscodingCpuCoreLimit), $("#chkEnableFullSpeedConversion", page).checked(config.EnableFullSpeedTranscoding), loading.hide()
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
loading.show();
|
||||
var form = this;
|
||||
return ApiClient.getNamedConfiguration("sync").then(function(config) {
|
||||
config.TemporaryPath = $("#txtSyncTempPath", form).val(), config.UploadSpeedLimitBytes = parseInt(1e6 * parseFloat($("#txtUploadSpeedLimit", form).val() || "0")), config.TranscodingCpuCoreLimit = parseInt($("#selectThreadCount", form).val()), config.EnableFullSpeedTranscoding = $("#chkEnableFullSpeedConversion", form).checked(), ApiClient.updateNamedConfiguration("sync", config).then(Dashboard.processServerConfigurationUpdateResult)
|
||||
}), !1
|
||||
}
|
||||
|
||||
function getTabs() {
|
||||
return [{
|
||||
href: "syncactivity.html",
|
||||
name: Globalize.translate("TabSyncJobs")
|
||||
}, {
|
||||
href: "appservices.html?context=sync",
|
||||
name: Globalize.translate("TabServices")
|
||||
}, {
|
||||
href: "syncsettings.html",
|
||||
name: Globalize.translate("TabSettings")
|
||||
}]
|
||||
}
|
||||
$(document).on("pageinit", "#syncSettingsPage", function() {
|
||||
var page = this;
|
||||
$("#btnSelectSyncTempPath", page).on("click.selectDirectory", function() {
|
||||
require(["directorybrowser"], function(directoryBrowser) {
|
||||
var picker = new directoryBrowser;
|
||||
picker.show({
|
||||
callback: function(path) {
|
||||
path && $("#txtSyncTempPath", page).val(path), picker.close()
|
||||
},
|
||||
validateWriteable: !0
|
||||
})
|
||||
})
|
||||
}), $(".syncSettingsForm").off("submit", onSubmit).on("submit", onSubmit)
|
||||
}).on("pageshow", "#syncSettingsPage", function() {
|
||||
loading.show(), libraryMenu.setTabs("syncadmin", 2, getTabs);
|
||||
var page = this;
|
||||
ApiClient.getNamedConfiguration("sync").then(function(config) {
|
||||
loadPage(page, config)
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
define(["events", "userSettings", "serverNotifications", "connectionManager", "emby-button"], function(events, userSettings, serverNotifications, connectionManager) {
|
||||
"use strict";
|
||||
return function(options) {
|
||||
function pollTasks() {
|
||||
connectionManager.getApiClient(serverId).getScheduledTasks({
|
||||
IsEnabled: !0
|
||||
}).then(updateTasks)
|
||||
}
|
||||
|
||||
function updateTasks(tasks) {
|
||||
var task = tasks.filter(function(t) {
|
||||
return t.Key == options.taskKey
|
||||
})[0];
|
||||
if (options.panel && (task ? options.panel.classList.remove("hide") : options.panel.classList.add("hide")), task) {
|
||||
"Idle" == task.State ? button.removeAttribute("disabled") : button.setAttribute("disabled", "disabled"), button.setAttribute("data-taskid", task.Id);
|
||||
var progress = (task.CurrentProgressPercentage || 0).toFixed(1);
|
||||
if (options.progressElem && (options.progressElem.value = progress, "Running" == task.State ? options.progressElem.classList.remove("hide") : options.progressElem.classList.add("hide")), options.lastResultElem) {
|
||||
var lastResult = task.LastExecutionResult ? task.LastExecutionResult.Status : "";
|
||||
"Failed" == lastResult ? options.lastResultElem.html('<span style="color:#FF0000;">(' + Globalize.translate("LabelFailed") + ")</span>") : "Cancelled" == lastResult ? options.lastResultElem.html('<span style="color:#0026FF;">(' + Globalize.translate("LabelCancelled") + ")</span>") : "Aborted" == lastResult ? options.lastResultElem.html('<span style="color:#FF0000;">' + Globalize.translate("LabelAbortedByServerShutdown") + "</span>") : options.lastResultElem.html(lastResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onScheduledTaskMessageConfirmed(id) {
|
||||
connectionManager.getApiClient(serverId).startScheduledTask(id).then(pollTasks)
|
||||
}
|
||||
|
||||
function onButtonClick() {
|
||||
onScheduledTaskMessageConfirmed(this.getAttribute("data-taskid"))
|
||||
}
|
||||
|
||||
function onScheduledTasksUpdate(e, apiClient, info) {
|
||||
apiClient.serverId() === serverId && updateTasks(info)
|
||||
}
|
||||
|
||||
function onPollIntervalFired() {
|
||||
connectionManager.getApiClient(serverId).isMessageChannelOpen() || pollTasks()
|
||||
}
|
||||
var pollInterval, button = options.button,
|
||||
serverId = ApiClient.serverId();
|
||||
options.panel && options.panel.classList.add("hide"), "off" == options.mode ? (button.removeEventListener("click", onButtonClick), events.off(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate), function() {
|
||||
connectionManager.getApiClient(serverId).sendMessage("ScheduledTasksInfoStop"), pollInterval && clearInterval(pollInterval)
|
||||
}()) : (button.addEventListener("click", onButtonClick), pollTasks(), function() {
|
||||
var apiClient = connectionManager.getApiClient(serverId);
|
||||
pollInterval && clearInterval(pollInterval), apiClient.sendMessage("ScheduledTasksInfoStart", "1000,1000"), pollInterval = setInterval(onPollIntervalFired, 1e4)
|
||||
}(), events.on(serverNotifications, "ScheduledTasksInfo", onScheduledTasksUpdate))
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
define(["userSettings", "skinManager", "connectionManager", "events"], function(userSettings, skinManager, connectionManager, events) {
|
||||
"use strict";
|
||||
var currentViewType;
|
||||
pageClassOn("viewbeforeshow", "page", function() {
|
||||
var classList = this.classList,
|
||||
viewType = classList.contains("type-interior") || classList.contains("wizardPage") ? "a" : "b";
|
||||
if (viewType !== currentViewType) {
|
||||
currentViewType = viewType;
|
||||
var theme, context;
|
||||
"a" === viewType ? (theme = userSettings.dashboardTheme(), context = "serverdashboard") : theme = userSettings.theme(), skinManager.setTheme(theme, context)
|
||||
}
|
||||
}), events.on(connectionManager, "localusersignedin", function(e, user) {
|
||||
currentViewType = null
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,141 @@
|
||||
define(["layoutManager", "loading", "libraryBrowser", "cardBuilder", "lazyLoader", "apphost", "globalize", "appRouter", "dom", "emby-linkbutton"], function(layoutManager, loading, libraryBrowser, cardBuilder, lazyLoader, appHost, globalize, appRouter, dom) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData() {
|
||||
var key = getSavedQueryKey(),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Series",
|
||||
Recursive: !0,
|
||||
EnableTotalRecordCount: !1
|
||||
},
|
||||
view: "Poster"
|
||||
}, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery() {
|
||||
return getPageData().query
|
||||
}
|
||||
|
||||
function getSavedQueryKey() {
|
||||
return libraryBrowser.getSavedQueryKey("seriesgenres")
|
||||
}
|
||||
|
||||
function getPromise() {
|
||||
loading.show();
|
||||
var query = getQuery();
|
||||
return ApiClient.getGenres(ApiClient.getCurrentUserId(), query)
|
||||
}
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop
|
||||
}
|
||||
|
||||
function getThumbShape() {
|
||||
return enableScrollX() ? "overflowBackdrop" : "backdrop"
|
||||
}
|
||||
|
||||
function getPortraitShape() {
|
||||
return enableScrollX() ? "overflowPortrait" : "portrait"
|
||||
}
|
||||
|
||||
function fillItemsContainer(elem) {
|
||||
var id = elem.getAttribute("data-id"),
|
||||
viewStyle = self.getCurrentViewStyle(),
|
||||
limit = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? 5 : 9;
|
||||
enableScrollX() && (limit = 10);
|
||||
var enableImageTypes = "Thumb" == viewStyle || "ThumbCard" == viewStyle ? "Primary,Backdrop,Thumb" : "Primary",
|
||||
query = {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Series",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo",
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: enableImageTypes,
|
||||
Limit: limit,
|
||||
GenreIds: id,
|
||||
EnableTotalRecordCount: !1,
|
||||
ParentId: params.topParentId
|
||||
};
|
||||
ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) {
|
||||
var supportsImageAnalysis = appHost.supports("imageanalysis");
|
||||
"Thumb" == viewStyle ? cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: elem,
|
||||
shape: getThumbShape(),
|
||||
preferThumb: !0,
|
||||
showTitle: !0,
|
||||
scalable: !0,
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0,
|
||||
allowBottomPadding: !1
|
||||
}) : "ThumbCard" == viewStyle ? cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: elem,
|
||||
shape: getThumbShape(),
|
||||
preferThumb: !0,
|
||||
showTitle: !0,
|
||||
scalable: !0,
|
||||
centerText: !1,
|
||||
cardLayout: !0,
|
||||
vibrant: supportsImageAnalysis,
|
||||
showYear: !0
|
||||
}) : "PosterCard" == viewStyle ? cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: elem,
|
||||
shape: getPortraitShape(),
|
||||
showTitle: !0,
|
||||
scalable: !0,
|
||||
centerText: !1,
|
||||
cardLayout: !0,
|
||||
vibrant: supportsImageAnalysis,
|
||||
showYear: !0
|
||||
}) : "Poster" == viewStyle && cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: elem,
|
||||
shape: getPortraitShape(),
|
||||
scalable: !0,
|
||||
overlayMoreButton: !0,
|
||||
allowBottomPadding: !1
|
||||
}), result.Items.length >= query.Limit && tabContent.querySelector(".btnMoreFromGenre" + id + " i").classList.remove("hide")
|
||||
})
|
||||
}
|
||||
|
||||
function reloadItems(context, promise) {
|
||||
var query = getQuery();
|
||||
promise.then(function(result) {
|
||||
for (var elem = context.querySelector("#items"), html = "", items = result.Items, i = 0, length = items.length; i < length; i++) {
|
||||
var item = items[i];
|
||||
if (html += '<div class="verticalSection">', html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">', html += '<a is="emby-linkbutton" href="' + appRouter.getRouteUrl(item, {
|
||||
context: "tvshows",
|
||||
parentId: params.topParentId
|
||||
}) + '" class="more button-flat button-flat-mini sectionTitleTextButton btnMoreFromGenre' + item.Id + '">', html += '<h2 class="sectionTitle sectionTitle-cards">', html += item.Name, html += "</h2>", html += '<i class="md-icon hide"></i>', html += "</a>", html += "</div>", enableScrollX()) {
|
||||
var scrollXClass = "scrollX hiddenScrollX";
|
||||
layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '<div is="emby-itemscontainer" class="itemsContainer ' + scrollXClass + ' lazy padded-left padded-right" data-id="' + item.Id + '">'
|
||||
} else html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap lazy padded-left padded-right" data-id="' + item.Id + '">';
|
||||
html += "</div>", html += "</div>"
|
||||
}
|
||||
elem.innerHTML = html, lazyLoader.lazyChildren(elem, fillItemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(), query), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function fullyReload() {
|
||||
self.preRender(), self.renderTab()
|
||||
}
|
||||
var self = this,
|
||||
data = {};
|
||||
self.getViewStyles = function() {
|
||||
return "Poster,PosterCard,Thumb,ThumbCard".split(",")
|
||||
}, self.getCurrentViewStyle = function() {
|
||||
return getPageData(tabContent).view
|
||||
}, self.setCurrentViewStyle = function(viewStyle) {
|
||||
getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), fullyReload()
|
||||
}, self.enableViewSelection = !0;
|
||||
var promise;
|
||||
self.preRender = function() {
|
||||
promise = getPromise()
|
||||
}, self.renderTab = function() {
|
||||
reloadItems(tabContent, promise)
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
define(["loading", "components/categorysyncbuttons", "components/groupedcards", "cardBuilder", "apphost", "imageLoader"], function(loading, categorysyncbuttons, groupedcards, cardBuilder, appHost, imageLoader) {
|
||||
"use strict";
|
||||
|
||||
function getLatestPromise(context, params) {
|
||||
loading.show();
|
||||
var userId = ApiClient.getCurrentUserId(),
|
||||
parentId = params.topParentId,
|
||||
options = {
|
||||
IncludeItemTypes: "Episode",
|
||||
Limit: 30,
|
||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
ParentId: parentId,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Thumb"
|
||||
};
|
||||
return ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options))
|
||||
}
|
||||
|
||||
function loadLatest(context, params, promise) {
|
||||
promise.then(function(items) {
|
||||
var html = "";
|
||||
appHost.supports("imageanalysis");
|
||||
html += cardBuilder.getCardsHtml({
|
||||
items: items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
showTitle: !0,
|
||||
showSeriesYear: !0,
|
||||
showParentTitle: !0,
|
||||
overlayText: !1,
|
||||
cardLayout: !1,
|
||||
showUnplayedIndicator: !1,
|
||||
showChildCountIndicator: !0,
|
||||
centerText: !0,
|
||||
lazy: !0,
|
||||
overlayPlayButton: !0,
|
||||
vibrant: !1,
|
||||
lines: 2
|
||||
});
|
||||
var elem = context.querySelector("#latestEpisodes");
|
||||
elem.innerHTML = html, imageLoader.lazyChildren(elem), loading.hide()
|
||||
})
|
||||
}
|
||||
return function(view, params, tabContent) {
|
||||
var self = this;
|
||||
categorysyncbuttons.init(tabContent);
|
||||
var latestPromise;
|
||||
self.preRender = function() {
|
||||
latestPromise = getLatestPromise(view, params)
|
||||
}, self.renderTab = function() {
|
||||
loadLatest(tabContent, params, latestPromise)
|
||||
}, tabContent.querySelector("#latestEpisodes").addEventListener("click", groupedcards.onItemsContainerClick)
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,229 @@
|
||||
define(["events", "inputManager", "libraryMenu", "layoutManager", "loading", "dom", "components/categorysyncbuttons", "userSettings", "cardBuilder", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-button"], function(events, inputManager, libraryMenu, layoutManager, loading, dom, categorysyncbuttons, 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()), categorysyncbuttons.init(tabContent)
|
||||
}, 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()
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,186 @@
|
||||
define(["layoutManager", "loading", "events", "libraryBrowser", "imageLoader", "listView", "cardBuilder", "alphaPicker", "emby-itemscontainer"], function(layoutManager, loading, events, libraryBrowser, imageLoader, listView, cardBuilder, alphaPicker) {
|
||||
"use strict";
|
||||
return function(view, params, tabContent) {
|
||||
function getPageData(context) {
|
||||
var key = getSavedQueryKey(context),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Series",
|
||||
Recursive: !0,
|
||||
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
StartIndex: 0,
|
||||
Limit: pageSize
|
||||
},
|
||||
view: libraryBrowser.getSavedView(key) || "Poster"
|
||||
}, pageData.query.ParentId = params.topParentId, libraryBrowser.loadSavedQueryValues(key, pageData.query)), pageData
|
||||
}
|
||||
|
||||
function getQuery(context) {
|
||||
return getPageData(context).query
|
||||
}
|
||||
|
||||
function getSavedQueryKey(context) {
|
||||
return context.savedQueryKey || (context.savedQueryKey = libraryBrowser.getSavedQueryKey("series")), context.savedQueryKey
|
||||
}
|
||||
|
||||
function onViewStyleChange() {
|
||||
var viewStyle = self.getCurrentViewStyle(),
|
||||
itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
"List" == viewStyle ? (itemsContainer.classList.add("vertical-list"), itemsContainer.classList.remove("vertical-wrap")) : (itemsContainer.classList.remove("vertical-list"), itemsContainer.classList.add("vertical-wrap")), itemsContainer.innerHTML = ""
|
||||
}
|
||||
|
||||
function reloadItems(page) {
|
||||
loading.show();
|
||||
var query = getQuery(page);
|
||||
ApiClient.getItems(ApiClient.getCurrentUserId(), query).then(function(result) {
|
||||
function onNextPageClick() {
|
||||
query.StartIndex += query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
|
||||
function onPreviousPageClick() {
|
||||
query.StartIndex -= query.Limit, reloadItems(tabContent)
|
||||
}
|
||||
window.scrollTo(0, 0), updateFilterControls(page);
|
||||
var html, pagingHtml = libraryBrowser.getQueryPagingHtml({
|
||||
startIndex: query.StartIndex,
|
||||
limit: query.Limit,
|
||||
totalRecordCount: result.TotalRecordCount,
|
||||
showLimit: !1,
|
||||
updatePageSizeSetting: !1,
|
||||
addLayoutButton: !1,
|
||||
sortButton: !1,
|
||||
filterButton: !1
|
||||
}),
|
||||
viewStyle = self.getCurrentViewStyle();
|
||||
html = "Thumb" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
context: "tvshows",
|
||||
overlayMoreButton: !0,
|
||||
showTitle: !0,
|
||||
centerText: !0
|
||||
}) : "ThumbCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
context: "tvshows",
|
||||
cardLayout: !0,
|
||||
showTitle: !0,
|
||||
showYear: !0
|
||||
}) : "Banner" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "banner",
|
||||
preferBanner: !0,
|
||||
context: "tvshows"
|
||||
}) : "List" == viewStyle ? listView.getListViewHtml({
|
||||
items: result.Items,
|
||||
context: "tvshows",
|
||||
sortBy: query.SortBy
|
||||
}) : "PosterCard" == viewStyle ? cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "portrait",
|
||||
context: "tvshows",
|
||||
showTitle: !0,
|
||||
showYear: !0,
|
||||
cardLayout: !0
|
||||
}) : cardBuilder.getCardsHtml({
|
||||
items: result.Items,
|
||||
shape: "portrait",
|
||||
context: "tvshows",
|
||||
centerText: !0,
|
||||
lazy: !0,
|
||||
overlayMoreButton: !0,
|
||||
showTitle: !0
|
||||
});
|
||||
var i, length, elems = tabContent.querySelectorAll(".paging");
|
||||
for (i = 0, length = elems.length; i < length; i++) elems[i].innerHTML = pagingHtml;
|
||||
for (elems = tabContent.querySelectorAll(".btnNextPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onNextPageClick);
|
||||
for (elems = tabContent.querySelectorAll(".btnPreviousPage"), i = 0, length = elems.length; i < length; i++) elems[i].addEventListener("click", onPreviousPageClick);
|
||||
var itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
itemsContainer.innerHTML = html, imageLoader.lazyChildren(itemsContainer), libraryBrowser.saveQueryValues(getSavedQueryKey(page), query), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function updateFilterControls(tabContent) {
|
||||
var query = getQuery(tabContent);
|
||||
self.alphaPicker.value(query.NameStartsWithOrGreater)
|
||||
}
|
||||
var self = this,
|
||||
pageSize = 100,
|
||||
data = {};
|
||||
self.showFilterMenu = function() {
|
||||
require(["components/filterdialog/filterdialog"], function(filterDialogFactory) {
|
||||
var filterDialog = new filterDialogFactory({
|
||||
query: getQuery(tabContent),
|
||||
mode: "series",
|
||||
serverId: ApiClient.serverId()
|
||||
});
|
||||
events.on(filterDialog, "filterchange", function() {
|
||||
getQuery(tabContent).StartIndex = 0, reloadItems(tabContent)
|
||||
}), filterDialog.show()
|
||||
})
|
||||
}, self.getCurrentViewStyle = function() {
|
||||
return getPageData(tabContent).view
|
||||
},
|
||||
function(tabContent) {
|
||||
var alphaPickerElement = tabContent.querySelector(".alphaPicker");
|
||||
if (alphaPickerElement.addEventListener("alphavaluechanged", function(e) {
|
||||
var newValue = e.detail.value,
|
||||
query = getQuery(tabContent);
|
||||
query.NameStartsWithOrGreater = newValue, query.StartIndex = 0, reloadItems(tabContent)
|
||||
}), self.alphaPicker = new alphaPicker({
|
||||
element: alphaPickerElement,
|
||||
valueChangeEvent: "click"
|
||||
}), layoutManager.desktop || layoutManager.mobile) {
|
||||
tabContent.querySelector(".alphaPicker").classList.add("alphabetPicker-right");
|
||||
var itemsContainer = tabContent.querySelector(".itemsContainer");
|
||||
itemsContainer.classList.remove("padded-left-withalphapicker"), itemsContainer.classList.add("padded-right-withalphapicker")
|
||||
}
|
||||
tabContent.querySelector(".btnFilter").addEventListener("click", function() {
|
||||
self.showFilterMenu()
|
||||
}), tabContent.querySelector(".btnSort").addEventListener("click", function(e) {
|
||||
libraryBrowser.showSortMenu({
|
||||
items: [{
|
||||
name: Globalize.translate("OptionNameSort"),
|
||||
id: "SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionImdbRating"),
|
||||
id: "CommunityRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDateAdded"),
|
||||
id: "DateCreated,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionDatePlayed"),
|
||||
id: "DatePlayed,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionParentalRating"),
|
||||
id: "OfficialRating,SortName"
|
||||
}, {
|
||||
name: Globalize.translate("OptionReleaseDate"),
|
||||
id: "PremiereDate,SortName"
|
||||
}],
|
||||
callback: function() {
|
||||
getQuery(tabContent).StartIndex = 0, reloadItems(tabContent)
|
||||
},
|
||||
query: getQuery(tabContent),
|
||||
button: e.target
|
||||
})
|
||||
});
|
||||
var btnSelectView = tabContent.querySelector(".btnSelectView");
|
||||
btnSelectView.addEventListener("click", function(e) {
|
||||
libraryBrowser.showLayoutMenu(e.target, self.getCurrentViewStyle(), "Banner,List,Poster,PosterCard,Thumb,ThumbCard".split(","))
|
||||
}), btnSelectView.addEventListener("layoutchange", function(e) {
|
||||
var viewStyle = e.detail.viewStyle;
|
||||
getPageData(tabContent).view = viewStyle, libraryBrowser.saveViewSetting(getSavedQueryKey(tabContent), viewStyle), getQuery(tabContent).StartIndex = 0, onViewStyleChange(), reloadItems(tabContent)
|
||||
})
|
||||
}(tabContent), onViewStyleChange(), self.renderTab = function() {
|
||||
reloadItems(tabContent), updateFilterControls(tabContent)
|
||||
}, self.destroy = function() {}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
define(["loading", "libraryBrowser", "cardBuilder", "apphost"], function(loading, libraryBrowser, cardBuilder, appHost) {
|
||||
"use strict";
|
||||
|
||||
function getQuery(params) {
|
||||
var key = getSavedQueryKey(),
|
||||
pageData = data[key];
|
||||
return pageData || (pageData = data[key] = {
|
||||
query: {
|
||||
SortBy: "SortName",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: "Series",
|
||||
Recursive: !0,
|
||||
Fields: "DateCreated,PrimaryImageAspectRatio",
|
||||
StartIndex: 0
|
||||
}
|
||||
}, pageData.query.ParentId = params.topParentId), pageData.query
|
||||
}
|
||||
|
||||
function getSavedQueryKey() {
|
||||
return libraryBrowser.getSavedQueryKey("studios")
|
||||
}
|
||||
|
||||
function getPromise(context, params) {
|
||||
var query = getQuery(params);
|
||||
return loading.show(), ApiClient.getStudios(ApiClient.getCurrentUserId(), query)
|
||||
}
|
||||
|
||||
function reloadItems(context, params, promise) {
|
||||
promise.then(function(result) {
|
||||
var elem = context.querySelector("#items");
|
||||
cardBuilder.buildCards(result.Items, {
|
||||
itemsContainer: elem,
|
||||
shape: "backdrop",
|
||||
preferThumb: !0,
|
||||
showTitle: !0,
|
||||
scalable: !0,
|
||||
centerText: !0,
|
||||
overlayMoreButton: !0,
|
||||
context: "tvshows"
|
||||
}), loading.hide()
|
||||
})
|
||||
}
|
||||
var data = {};
|
||||
return function(view, params, tabContent) {
|
||||
var promise, self = this;
|
||||
self.preRender = function() {
|
||||
promise = getPromise(view, params)
|
||||
}, self.renderTab = function() {
|
||||
reloadItems(tabContent, params, promise)
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
define(["layoutManager", "loading", "datetime", "libraryBrowser", "cardBuilder", "apphost", "imageLoader", "scrollStyles", "emby-itemscontainer"], function(layoutManager, loading, datetime, libraryBrowser, cardBuilder, appHost, imageLoader) {
|
||||
"use strict";
|
||||
|
||||
function getUpcomingPromise(context, params) {
|
||||
loading.show();
|
||||
var query = {
|
||||
Limit: 48,
|
||||
Fields: "AirTime,UserData",
|
||||
UserId: ApiClient.getCurrentUserId(),
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
|
||||
EnableTotalRecordCount: !1
|
||||
};
|
||||
return query.ParentId = params.topParentId, ApiClient.getJSON(ApiClient.getUrl("Shows/Upcoming", query))
|
||||
}
|
||||
|
||||
function loadUpcoming(context, params, promise) {
|
||||
promise.then(function(result) {
|
||||
var items = result.Items;
|
||||
items.length ? context.querySelector(".noItemsMessage").style.display = "none" : context.querySelector(".noItemsMessage").style.display = "block", renderUpcoming(context.querySelector("#upcomingItems"), items), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function enableScrollX() {
|
||||
return !layoutManager.desktop
|
||||
}
|
||||
|
||||
function getThumbShape() {
|
||||
return enableScrollX() ? "overflowBackdrop" : "backdrop"
|
||||
}
|
||||
|
||||
function renderUpcoming(elem, items) {
|
||||
var i, length, groups = [],
|
||||
currentGroupName = "",
|
||||
currentGroup = [];
|
||||
for (i = 0, length = items.length; i < length; i++) {
|
||||
var item = items[i],
|
||||
dateText = "";
|
||||
if (item.PremiereDate) try {
|
||||
var premiereDate = datetime.parseISO8601Date(item.PremiereDate, !0);
|
||||
dateText = datetime.isRelativeDay(premiereDate, -1) ? Globalize.translate("Yesterday") : datetime.toLocaleDateString(premiereDate, {
|
||||
weekday: "long",
|
||||
month: "short",
|
||||
day: "numeric"
|
||||
})
|
||||
} catch (err) {}
|
||||
dateText != currentGroupName ? (currentGroup.length && groups.push({
|
||||
name: currentGroupName,
|
||||
items: currentGroup
|
||||
}), currentGroupName = dateText, currentGroup = [item]) : currentGroup.push(item)
|
||||
}
|
||||
var html = "";
|
||||
for (i = 0, length = groups.length; i < length; i++) {
|
||||
var group = groups[i];
|
||||
html += '<div class="verticalSection">', html += '<h2 class="sectionTitle sectionTitle-cards padded-left">' + group.name + "</h2>";
|
||||
var allowBottomPadding = !0;
|
||||
if (enableScrollX()) {
|
||||
allowBottomPadding = !1;
|
||||
var scrollXClass = "scrollX hiddenScrollX";
|
||||
layoutManager.tv && (scrollXClass += " smoothScrollX"), html += '<div is="emby-itemscontainer" class="itemsContainer ' + scrollXClass + ' padded-left padded-right">'
|
||||
} else html += '<div is="emby-itemscontainer" class="itemsContainer vertical-wrap padded-left padded-right">';
|
||||
var supportsImageAnalysis = appHost.supports("imageanalysis");
|
||||
supportsImageAnalysis = !1, html += cardBuilder.getCardsHtml({
|
||||
items: group.items,
|
||||
showLocationTypeIndicator: !1,
|
||||
shape: getThumbShape(),
|
||||
showTitle: !0,
|
||||
preferThumb: !0,
|
||||
lazy: !0,
|
||||
showDetailsMenu: !0,
|
||||
centerText: !supportsImageAnalysis,
|
||||
showParentTitle: !0,
|
||||
overlayText: !1,
|
||||
allowBottomPadding: allowBottomPadding,
|
||||
cardLayout: supportsImageAnalysis,
|
||||
vibrant: supportsImageAnalysis,
|
||||
overlayMoreButton: !0,
|
||||
missingIndicator: !1
|
||||
}), html += "</div>", html += "</div>"
|
||||
}
|
||||
elem.innerHTML = html, imageLoader.lazyChildren(elem)
|
||||
}
|
||||
return function(view, params, tabContent) {
|
||||
var upcomingPromise, self = this;
|
||||
self.preRender = function() {
|
||||
upcomingPromise = getUpcomingPromise(view, params)
|
||||
}, self.renderTab = function() {
|
||||
loadUpcoming(tabContent, params, upcomingPromise)
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,85 @@
|
||||
define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function loadDeleteFolders(page, user, mediaFolders) {
|
||||
ApiClient.getJSON(ApiClient.getUrl("Channels", {
|
||||
SupportsMediaDeletion: !0
|
||||
})).then(function(channelsResult) {
|
||||
var i, length, folder, isChecked, checkedAttribute, html = "";
|
||||
for (i = 0, length = mediaFolders.length; i < length; i++) folder = mediaFolders[i], isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id), checkedAttribute = isChecked ? ' checked="checked"' : "", html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '" ' + checkedAttribute + "><span>" + folder.Name + "</span></label>";
|
||||
for (i = 0, length = channelsResult.Items.length; i < length; i++) folder = channelsResult.Items[i], isChecked = user.Policy.EnableContentDeletion || -1 != user.Policy.EnableContentDeletionFromFolders.indexOf(folder.Id), checkedAttribute = isChecked ? ' checked="checked"' : "", html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '" ' + checkedAttribute + "><span>" + folder.Name + "</span></label>";
|
||||
$(".deleteAccess", page).html(html).trigger("create"), $("#chkEnableDeleteAllFolders", page).checked(user.Policy.EnableContentDeletion).trigger("change")
|
||||
})
|
||||
}
|
||||
|
||||
function loadAuthProviders(page, user, providers) {
|
||||
providers.length > 1 && !user.Policy.IsAdministrator ? page.querySelector(".fldSelectLoginProvider").classList.remove("hide") : page.querySelector(".fldSelectLoginProvider").classList.add("hide");
|
||||
var currentProviderId = user.Policy.AuthenticationProviderId;
|
||||
page.querySelector(".selectLoginProvider").innerHTML = providers.map(function(provider) {
|
||||
var selected = provider.Id === currentProviderId || providers.length < 2 ? " selected" : "";
|
||||
return '<option value="' + provider.Id + '"' + selected + ">" + provider.Name + "</option>"
|
||||
})
|
||||
}
|
||||
|
||||
function loadUser(page, user) {
|
||||
currentUser = user, ApiClient.getJSON(ApiClient.getUrl("Auth/Providers")).then(function(providers) {
|
||||
loadAuthProviders(page, user, providers)
|
||||
}), ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", {
|
||||
IsHidden: !1
|
||||
})).then(function(folders) {
|
||||
loadDeleteFolders(page, user, folders.Items)
|
||||
}), user.Policy.IsDisabled ? $(".disabledUserBanner", page).show() : $(".disabledUserBanner", page).hide(), "Guest" == user.ConnectLinkType ? ($("#fldConnectInfo", page).hide(), $("#txtUserName", page).prop("disabled", "disabled")) : ($("#txtUserName", page).prop("disabled", "").removeAttr("disabled"), $("#fldConnectInfo", page).show()), $(".lnkEditUserPreferences", page).attr("href", "mypreferencesmenu.html?userId=" + user.Id), libraryMenu.setTitle(user.Name), page.querySelector(".username").innerHTML = user.Name, $("#txtUserName", page).val(user.Name), $("#txtConnectUserName", page).val(currentUser.ConnectUserName), $("#chkIsAdmin", page).checked(user.Policy.IsAdministrator), $("#chkDisabled", page).checked(user.Policy.IsDisabled), $("#chkIsHidden", page).checked(user.Policy.IsHidden), $("#chkRemoteControlSharedDevices", page).checked(user.Policy.EnableSharedDeviceControl), $("#chkEnableRemoteControlOtherUsers", page).checked(user.Policy.EnableRemoteControlOfOtherUsers), $("#chkEnableDownloading", page).checked(user.Policy.EnableContentDownloading), $("#chkManageLiveTv", page).checked(user.Policy.EnableLiveTvManagement), $("#chkEnableLiveTvAccess", page).checked(user.Policy.EnableLiveTvAccess), $("#chkEnableMediaPlayback", page).checked(user.Policy.EnableMediaPlayback), $("#chkEnableAudioPlaybackTranscoding", page).checked(user.Policy.EnableAudioPlaybackTranscoding), $("#chkEnableVideoPlaybackTranscoding", page).checked(user.Policy.EnableVideoPlaybackTranscoding), $("#chkEnableVideoPlaybackRemuxing", page).checked(user.Policy.EnablePlaybackRemuxing), $("#chkRemoteAccess", page).checked(null == user.Policy.EnableRemoteAccess || user.Policy.EnableRemoteAccess), $("#chkEnableSyncTranscoding", page).checked(user.Policy.EnableSyncTranscoding), $("#chkEnableConversion", page).checked(user.Policy.EnableMediaConversion || !1), $("#chkEnableSharing", page).checked(user.Policy.EnablePublicSharing), $("#txtRemoteClientBitrateLimit", page).val(user.Policy.RemoteClientBitrateLimit / 1e6 || ""), loading.hide()
|
||||
}
|
||||
|
||||
function onSaveComplete(page, user) {
|
||||
loading.hide(), (currentUser.ConnectUserName || "") == $("#txtConnectUserName", page).val() ? require(["toast"], function(toast) {
|
||||
toast(Globalize.translate("SettingsSaved"))
|
||||
}) : require(["connectHelper"], function(connectHelper) {
|
||||
connectHelper.updateUserLink(ApiClient, user, $("#txtConnectUserName", page).val()).then(function() {
|
||||
loadData(page)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function saveUser(user, page) {
|
||||
user.Name = $("#txtUserName", page).val(), user.Policy.IsAdministrator = $("#chkIsAdmin", page).checked(), user.Policy.IsHidden = $("#chkIsHidden", page).checked(), user.Policy.IsDisabled = $("#chkDisabled", page).checked(), user.Policy.EnableRemoteControlOfOtherUsers = $("#chkEnableRemoteControlOtherUsers", page).checked(), user.Policy.EnableLiveTvManagement = $("#chkManageLiveTv", page).checked(), user.Policy.EnableLiveTvAccess = $("#chkEnableLiveTvAccess", page).checked(), user.Policy.EnableSharedDeviceControl = $("#chkRemoteControlSharedDevices", page).checked(), user.Policy.EnableMediaPlayback = $("#chkEnableMediaPlayback", page).checked(), user.Policy.EnableAudioPlaybackTranscoding = $("#chkEnableAudioPlaybackTranscoding", page).checked(), user.Policy.EnableVideoPlaybackTranscoding = $("#chkEnableVideoPlaybackTranscoding", page).checked(), user.Policy.EnablePlaybackRemuxing = $("#chkEnableVideoPlaybackRemuxing", page).checked(), user.Policy.EnableContentDownloading = $("#chkEnableDownloading", page).checked(), user.Policy.EnableSyncTranscoding = $("#chkEnableSyncTranscoding", page).checked(), user.Policy.EnableMediaConversion = $("#chkEnableConversion", page).checked(), user.Policy.EnablePublicSharing = $("#chkEnableSharing", page).checked(), user.Policy.EnableRemoteAccess = $("#chkRemoteAccess", page).checked(), user.Policy.RemoteClientBitrateLimit = parseInt(1e6 * parseFloat($("#txtRemoteClientBitrateLimit", page).val() || "0")), user.Policy.AuthenticationProviderId = page.querySelector(".selectLoginProvider").value, user.Policy.EnableContentDeletion = $("#chkEnableDeleteAllFolders", page).checked(), user.Policy.EnableContentDeletionFromFolders = user.Policy.EnableContentDeletion ? [] : $(".chkFolder", page).get().filter(function(c) {
|
||||
return c.checked
|
||||
}).map(function(c) {
|
||||
return c.getAttribute("data-id")
|
||||
}), ApiClient.updateUser(user).then(function() {
|
||||
ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() {
|
||||
onSaveComplete(page, user)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
var page = $(this).parents(".page")[0];
|
||||
return loading.show(), getUser().then(function(result) {
|
||||
saveUser(result, page)
|
||||
}), !1
|
||||
}
|
||||
|
||||
function getUser() {
|
||||
var userId = getParameterByName("userId");
|
||||
return ApiClient.getUser(userId)
|
||||
}
|
||||
|
||||
function loadData(page) {
|
||||
loading.show(), getUser().then(function(user) {
|
||||
loadUser(page, user)
|
||||
})
|
||||
}
|
||||
var currentUser;
|
||||
$(document).on("pageinit", "#editUserPage", function() {
|
||||
$(".editUserProfileForm").off("submit", onSubmit).on("submit", onSubmit), this.querySelector(".sharingHelp").innerHTML = Globalize.translate("OptionAllowLinkSharingHelp", 30);
|
||||
var page = this;
|
||||
$("#chkEnableDeleteAllFolders", this).on("change", function() {
|
||||
this.checked ? $(".deleteAccess", page).hide() : $(".deleteAccess", page).show()
|
||||
}), ApiClient.getServerConfiguration().then(function(config) {
|
||||
config.EnableRemoteAccess ? page.querySelector(".fldRemoteAccess").classList.remove("hide") : page.querySelector(".fldRemoteAccess").classList.add("hide")
|
||||
})
|
||||
}).on("pagebeforeshow", "#editUserPage", function() {
|
||||
loadData(this)
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,112 @@
|
||||
define(["jQuery", "loading", "libraryMenu", "fnchecked"], function($, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function triggerChange(select) {
|
||||
var evt = document.createEvent("HTMLEvents");
|
||||
evt.initEvent("change", !1, !0), select.dispatchEvent(evt)
|
||||
}
|
||||
|
||||
function loadMediaFolders(page, user, mediaFolders) {
|
||||
var html = "";
|
||||
html += '<h3 class="checkboxListLabel">' + Globalize.translate("HeaderLibraries") + "</h3>", html += '<div class="checkboxList paperList checkboxList-paperList">';
|
||||
for (var i = 0, length = mediaFolders.length; i < length; i++) {
|
||||
var folder = mediaFolders[i],
|
||||
isChecked = user.Policy.EnableAllFolders || -1 != user.Policy.EnabledFolders.indexOf(folder.Id),
|
||||
checkedAttribute = isChecked ? ' checked="checked"' : "";
|
||||
html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '" ' + checkedAttribute + "><span>" + folder.Name + "</span></label>"
|
||||
}
|
||||
html += "</div>", page.querySelector(".folderAccess").innerHTML = html;
|
||||
var chkEnableAllFolders = page.querySelector("#chkEnableAllFolders");
|
||||
chkEnableAllFolders.checked = user.Policy.EnableAllFolders, triggerChange(chkEnableAllFolders)
|
||||
}
|
||||
|
||||
function loadChannels(page, user, channels) {
|
||||
var html = "";
|
||||
html += '<h3 class="checkboxListLabel">' + Globalize.translate("HeaderChannels") + "</h3>", html += '<div class="checkboxList paperList checkboxList-paperList">';
|
||||
for (var i = 0, length = channels.length; i < length; i++) {
|
||||
var folder = channels[i],
|
||||
isChecked = user.Policy.EnableAllChannels || -1 != user.Policy.EnabledChannels.indexOf(folder.Id),
|
||||
checkedAttribute = isChecked ? ' checked="checked"' : "";
|
||||
html += '<label><input type="checkbox" is="emby-checkbox" class="chkChannel" data-id="' + folder.Id + '" ' + checkedAttribute + "><span>" + folder.Name + "</span></label>"
|
||||
}
|
||||
html += "</div>", $(".channelAccess", page).show().html(html), channels.length ? $(".channelAccessContainer", page).show() : $(".channelAccessContainer", page).hide(), $("#chkEnableAllChannels", page).checked(user.Policy.EnableAllChannels).trigger("change")
|
||||
}
|
||||
|
||||
function loadDevices(page, user, devices) {
|
||||
var html = "";
|
||||
html += '<h3 class="checkboxListLabel">' + Globalize.translate("HeaderDevices") + "</h3>", html += '<div class="checkboxList paperList checkboxList-paperList">';
|
||||
for (var i = 0, length = devices.length; i < length; i++) {
|
||||
var device = devices[i],
|
||||
checkedAttribute = user.Policy.EnableAllDevices || -1 != user.Policy.EnabledDevices.indexOf(device.Id) ? ' checked="checked"' : "";
|
||||
html += '<label><input type="checkbox" is="emby-checkbox" class="chkDevice" data-id="' + device.Id + '" ' + checkedAttribute + "><span>" + device.Name + " - " + device.AppName + "</span></label>"
|
||||
}
|
||||
html += "</div>", $(".deviceAccess", page).show().html(html), $("#chkEnableAllDevices", page).checked(user.Policy.EnableAllDevices).trigger("change"), user.Policy.IsAdministrator ? page.querySelector(".deviceAccessContainer").classList.add("hide") : page.querySelector(".deviceAccessContainer").classList.remove("hide")
|
||||
}
|
||||
|
||||
function loadUser(page, user, loggedInUser, mediaFolders, channels, devices) {
|
||||
page.querySelector(".username").innerHTML = user.Name, libraryMenu.setTitle(user.Name), loadChannels(page, user, channels), loadMediaFolders(page, user, mediaFolders), loadDevices(page, user, devices), loading.hide()
|
||||
}
|
||||
|
||||
function onSaveComplete(page) {
|
||||
loading.hide(), require(["toast"], function(toast) {
|
||||
toast(Globalize.translate("SettingsSaved"))
|
||||
})
|
||||
}
|
||||
|
||||
function saveUser(user, page) {
|
||||
user.Policy.EnableAllFolders = $("#chkEnableAllFolders", page).checked(), user.Policy.EnabledFolders = user.Policy.EnableAllFolders ? [] : $(".chkFolder", page).get().filter(function(c) {
|
||||
return c.checked
|
||||
}).map(function(c) {
|
||||
return c.getAttribute("data-id")
|
||||
}), user.Policy.EnableAllChannels = $("#chkEnableAllChannels", page).checked(), user.Policy.EnabledChannels = user.Policy.EnableAllChannels ? [] : $(".chkChannel", page).get().filter(function(c) {
|
||||
return c.checked
|
||||
}).map(function(c) {
|
||||
return c.getAttribute("data-id")
|
||||
}), user.Policy.EnableAllDevices = $("#chkEnableAllDevices", page).checked(), user.Policy.EnabledDevices = user.Policy.EnableAllDevices ? [] : $(".chkDevice", page).get().filter(function(c) {
|
||||
return c.checked
|
||||
}).map(function(c) {
|
||||
return c.getAttribute("data-id")
|
||||
}), user.Policy.BlockedChannels = null, user.Policy.BlockedMediaFolders = null, ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() {
|
||||
onSaveComplete(page)
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
var page = $(this).parents(".page");
|
||||
loading.show();
|
||||
var userId = getParameterByName("userId");
|
||||
return ApiClient.getUser(userId).then(function(result) {
|
||||
saveUser(result, page)
|
||||
}), !1
|
||||
}
|
||||
$(document).on("pageinit", "#userLibraryAccessPage", function() {
|
||||
var page = this;
|
||||
$("#chkEnableAllDevices", page).on("change", function() {
|
||||
this.checked ? $(".deviceAccessListContainer", page).hide() : $(".deviceAccessListContainer", page).show()
|
||||
}), $("#chkEnableAllChannels", page).on("change", function() {
|
||||
this.checked ? $(".channelAccessListContainer", page).hide() : $(".channelAccessListContainer", page).show()
|
||||
}), page.querySelector("#chkEnableAllFolders").addEventListener("change", function() {
|
||||
this.checked ? page.querySelector(".folderAccessListContainer").classList.add("hide") : page.querySelector(".folderAccessListContainer").classList.remove("hide")
|
||||
}), $(".userLibraryAccessForm").off("submit", onSubmit).on("submit", onSubmit)
|
||||
}).on("pageshow", "#userLibraryAccessPage", function() {
|
||||
var page = this;
|
||||
loading.show();
|
||||
var promise1, userId = getParameterByName("userId");
|
||||
if (userId) promise1 = ApiClient.getUser(userId);
|
||||
else {
|
||||
var deferred = $.Deferred();
|
||||
deferred.resolveWith(null, [{
|
||||
Configuration: {}
|
||||
}]), promise1 = deferred.promise()
|
||||
}
|
||||
var promise2 = Dashboard.getCurrentUser(),
|
||||
promise4 = ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", {
|
||||
IsHidden: !1
|
||||
})),
|
||||
promise5 = ApiClient.getJSON(ApiClient.getUrl("Channels")),
|
||||
promise6 = ApiClient.getJSON(ApiClient.getUrl("Devices"));
|
||||
Promise.all([promise1, promise2, promise4, promise5, promise6]).then(function(responses) {
|
||||
loadUser(page, responses[0], responses[1], responses[2].Items, responses[3].Items, responses[4].Items)
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
define(["jQuery", "loading", "fnchecked", "emby-checkbox"], function($, loading) {
|
||||
"use strict";
|
||||
|
||||
function loadMediaFolders(page, mediaFolders) {
|
||||
var html = "";
|
||||
html += '<h3 class="checkboxListLabel">' + Globalize.translate("HeaderLibraries") + "</h3>", html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
|
||||
for (var i = 0, length = mediaFolders.length; i < length; i++) {
|
||||
var folder = mediaFolders[i];
|
||||
html += '<label><input type="checkbox" is="emby-checkbox" class="chkFolder" data-id="' + folder.Id + '" checked="checked"/><span>' + folder.Name + "</span></label>"
|
||||
}
|
||||
html += "</div>", $(".folderAccess", page).html(html).trigger("create"), $("#chkEnableAllFolders", page).checked(!0).trigger("change")
|
||||
}
|
||||
|
||||
function loadChannels(page, channels) {
|
||||
var html = "";
|
||||
html += '<h3 class="checkboxListLabel">' + Globalize.translate("HeaderChannels") + "</h3>", html += '<div class="checkboxList paperList" style="padding:.5em 1em;">';
|
||||
for (var i = 0, length = channels.length; i < length; i++) {
|
||||
var folder = channels[i];
|
||||
html += '<label><input type="checkbox" is="emby-checkbox" class="chkChannel" data-id="' + folder.Id + '" checked="checked"/><span>' + folder.Name + "</span></label>"
|
||||
}
|
||||
html += "</div>", $(".channelAccess", page).show().html(html).trigger("create"), channels.length ? $(".channelAccessContainer", page).show() : $(".channelAccessContainer", page).hide(), $("#chkEnableAllChannels", page).checked(!0).trigger("change")
|
||||
}
|
||||
|
||||
function loadUser(page) {
|
||||
$("#txtUserName", page).val(""), loading.show();
|
||||
var promise4 = ApiClient.getJSON(ApiClient.getUrl("Library/MediaFolders", {
|
||||
IsHidden: !1
|
||||
})),
|
||||
promise5 = ApiClient.getJSON(ApiClient.getUrl("Channels"));
|
||||
Promise.all([promise4, promise5]).then(function(responses) {
|
||||
loadMediaFolders(page, responses[0].Items), loadChannels(page, responses[1].Items), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function saveUser(page) {
|
||||
var name = $("#txtUserName", page).val();
|
||||
ApiClient.createUser(name).then(function(user) {
|
||||
user.Policy.EnableAllFolders = $("#chkEnableAllFolders", page).checked(), user.Policy.EnabledFolders = user.Policy.EnableAllFolders ? [] : $(".chkFolder", page).get().filter(function(i) {
|
||||
return i.checked
|
||||
}).map(function(i) {
|
||||
return i.getAttribute("data-id")
|
||||
}), user.Policy.EnableAllChannels = $("#chkEnableAllChannels", page).checked(), user.Policy.EnabledChannels = user.Policy.EnableAllChannels ? [] : $(".chkChannel", page).get().filter(function(i) {
|
||||
return i.checked
|
||||
}).map(function(i) {
|
||||
return i.getAttribute("data-id")
|
||||
}), ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() {
|
||||
Dashboard.navigate("useredit.html?userId=" + user.Id)
|
||||
})
|
||||
}, function(response) {
|
||||
400 == response.status ? Dashboard.alert({
|
||||
message: page.querySelector(".labelNewUserNameHelp").innerHTML
|
||||
}) : require(["toast"], function(toast) {
|
||||
toast(Globalize.translate("DefaultErrorMessage"))
|
||||
}), loading.hide()
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit() {
|
||||
var page = $(this).parents(".page")[0];
|
||||
return loading.show(), saveUser(page), !1
|
||||
}
|
||||
|
||||
function loadData(page) {
|
||||
loadUser(page)
|
||||
}
|
||||
$(document).on("pageinit", "#newUserPage", function() {
|
||||
var page = this;
|
||||
$("#chkEnableAllChannels", page).on("change", function() {
|
||||
this.checked ? $(".channelAccessListContainer", page).hide() : $(".channelAccessListContainer", page).show()
|
||||
}), $("#chkEnableAllFolders", page).on("change", function() {
|
||||
this.checked ? $(".folderAccessListContainer", page).hide() : $(".folderAccessListContainer", page).show()
|
||||
}), $(".newUserProfileForm").off("submit", onSubmit).on("submit", onSubmit)
|
||||
}).on("pageshow", "#newUserPage", function() {
|
||||
loadData(this)
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,188 @@
|
||||
define(["jQuery", "datetime", "loading", "libraryMenu", "listViewStyle", "paper-icon-button-light"], function($, datetime, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function populateRatings(allParentalRatings, page) {
|
||||
var html = "";
|
||||
html += "<option value=''></option>";
|
||||
var i, length, rating, ratings = [];
|
||||
for (i = 0, length = allParentalRatings.length; i < length; i++) {
|
||||
if (rating = allParentalRatings[i], ratings.length) {
|
||||
var lastRating = ratings[ratings.length - 1];
|
||||
if (lastRating.Value === rating.Value) {
|
||||
lastRating.Name += "/" + rating.Name;
|
||||
continue
|
||||
}
|
||||
}
|
||||
ratings.push({
|
||||
Name: rating.Name,
|
||||
Value: rating.Value
|
||||
})
|
||||
}
|
||||
for (i = 0, length = ratings.length; i < length; i++) rating = ratings[i], html += "<option value='" + rating.Value + "'>" + rating.Name + "</option>";
|
||||
$("#selectMaxParentalRating", page).html(html)
|
||||
}
|
||||
|
||||
function loadUnratedItems(page, user) {
|
||||
var items = [{
|
||||
name: Globalize.translate("OptionBlockBooks"),
|
||||
value: "Book"
|
||||
}, {
|
||||
name: Globalize.translate("OptionBlockGames"),
|
||||
value: "Game"
|
||||
}, {
|
||||
name: Globalize.translate("OptionBlockChannelContent"),
|
||||
value: "ChannelContent"
|
||||
}, {
|
||||
name: Globalize.translate("OptionBlockLiveTvChannels"),
|
||||
value: "LiveTvChannel"
|
||||
}, {
|
||||
name: Globalize.translate("OptionBlockMovies"),
|
||||
value: "Movie"
|
||||
}, {
|
||||
name: Globalize.translate("OptionBlockMusic"),
|
||||
value: "Music"
|
||||
}, {
|
||||
name: Globalize.translate("OptionBlockTrailers"),
|
||||
value: "Trailer"
|
||||
}, {
|
||||
name: Globalize.translate("OptionBlockTvShows"),
|
||||
value: "Series"
|
||||
}],
|
||||
html = "";
|
||||
html += '<h3 class="checkboxListLabel">' + Globalize.translate("HeaderBlockItemsWithNoRating") + "</h3>", html += '<div class="checkboxList paperList checkboxList-paperList">';
|
||||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
var item = items[i],
|
||||
checkedAttribute = -1 != user.Policy.BlockUnratedItems.indexOf(item.value) ? ' checked="checked"' : "";
|
||||
html += '<label><input type="checkbox" is="emby-checkbox" class="chkUnratedItem" data-itemtype="' + item.value + '" type="checkbox"' + checkedAttribute + "><span>" + item.name + "</span></label>"
|
||||
}
|
||||
html += "</div>", $(".blockUnratedItems", page).html(html).trigger("create")
|
||||
}
|
||||
|
||||
function loadUser(page, user, allParentalRatings) {
|
||||
page.querySelector(".username").innerHTML = user.Name, libraryMenu.setTitle(user.Name), loadUnratedItems(page, user), loadBlockedTags(page, user.Policy.BlockedTags), populateRatings(allParentalRatings, page);
|
||||
var ratingValue = "";
|
||||
if (user.Policy.MaxParentalRating)
|
||||
for (var i = 0, length = allParentalRatings.length; i < length; i++) {
|
||||
var rating = allParentalRatings[i];
|
||||
user.Policy.MaxParentalRating >= rating.Value && (ratingValue = rating.Value)
|
||||
}
|
||||
$("#selectMaxParentalRating", page).val(ratingValue), user.Policy.IsAdministrator ? $(".accessScheduleSection", page).hide() : $(".accessScheduleSection", page).show(), renderAccessSchedule(page, user.Policy.AccessSchedules || []), loading.hide()
|
||||
}
|
||||
|
||||
function loadBlockedTags(page, tags) {
|
||||
var html = tags.map(function(h) {
|
||||
var li = '<div class="listItem">';
|
||||
return li += '<div class="listItemBody">', li += '<h3 class="listItemBodyText">', li += h, li += "</h3>", li += "</div>", li += '<button type="button" is="paper-icon-button-light" class="blockedTag btnDeleteTag listItemButton" data-tag="' + h + '"><i class="md-icon">delete</i></button>', li += "</div>"
|
||||
}).join("");
|
||||
html && (html = '<div class="paperList">' + html + "</div>");
|
||||
var elem = $(".blockedTags", page).html(html).trigger("create");
|
||||
$(".btnDeleteTag", elem).on("click", function() {
|
||||
var tag = this.getAttribute("data-tag"),
|
||||
newTags = tags.filter(function(t) {
|
||||
return t != tag
|
||||
});
|
||||
loadBlockedTags(page, newTags)
|
||||
})
|
||||
}
|
||||
|
||||
function deleteAccessSchedule(page, schedules, index) {
|
||||
schedules.splice(index, 1), renderAccessSchedule(page, schedules)
|
||||
}
|
||||
|
||||
function renderAccessSchedule(page, schedules) {
|
||||
var html = "",
|
||||
index = 0;
|
||||
html += schedules.map(function(a) {
|
||||
var itemHtml = "";
|
||||
return itemHtml += '<div class="liSchedule listItem" data-day="' + a.DayOfWeek + '" data-start="' + a.StartHour + '" data-end="' + a.EndHour + '">', itemHtml += '<div class="listItemBody two-line">', itemHtml += '<h3 class="listItemBodyText">', itemHtml += Globalize.translate("Option" + a.DayOfWeek), itemHtml += "</h3>", itemHtml += '<div class="listItemBodyText secondary">' + getDisplayTime(a.StartHour) + " - " + getDisplayTime(a.EndHour) + "</div>", itemHtml += "</div>", itemHtml += '<button type="button" is="paper-icon-button-light" class="btnDelete listItemButton" data-index="' + index + '"><i class="md-icon">delete</i></button>', itemHtml += "</div>", index++, itemHtml
|
||||
}).join("");
|
||||
var accessScheduleList = page.querySelector(".accessScheduleList");
|
||||
accessScheduleList.innerHTML = html, $(".btnDelete", accessScheduleList).on("click", function() {
|
||||
deleteAccessSchedule(page, schedules, parseInt(this.getAttribute("data-index")))
|
||||
})
|
||||
}
|
||||
|
||||
function onSaveComplete(page) {
|
||||
loading.hide(), require(["toast"], function(toast) {
|
||||
toast(Globalize.translate("SettingsSaved"))
|
||||
})
|
||||
}
|
||||
|
||||
function saveUser(user, page) {
|
||||
user.Policy.MaxParentalRating = $("#selectMaxParentalRating", page).val() || null, user.Policy.BlockUnratedItems = $(".chkUnratedItem", page).get().filter(function(i) {
|
||||
return i.checked
|
||||
}).map(function(i) {
|
||||
return i.getAttribute("data-itemtype")
|
||||
}), user.Policy.AccessSchedules = getSchedulesFromPage(page), user.Policy.BlockedTags = getBlockedTagsFromPage(page), ApiClient.updateUserPolicy(user.Id, user.Policy).then(function() {
|
||||
onSaveComplete(page)
|
||||
})
|
||||
}
|
||||
|
||||
function getDisplayTime(hours) {
|
||||
var minutes = 0,
|
||||
pct = hours % 1;
|
||||
return pct && (minutes = parseInt(60 * pct)), datetime.getDisplayTime(new Date(2e3, 1, 1, hours, minutes, 0, 0))
|
||||
}
|
||||
|
||||
function showSchedulePopup(page, schedule, index) {
|
||||
schedule = schedule || {}, require(["components/accessschedule/accessschedule"], function(accessschedule) {
|
||||
accessschedule.show({
|
||||
schedule: schedule
|
||||
}).then(function(updatedSchedule) {
|
||||
var schedules = getSchedulesFromPage(page); - 1 == index && (index = schedules.length), schedules[index] = updatedSchedule, renderAccessSchedule(page, schedules)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getSchedulesFromPage(page) {
|
||||
return $(".liSchedule", page).map(function() {
|
||||
return {
|
||||
DayOfWeek: this.getAttribute("data-day"),
|
||||
StartHour: this.getAttribute("data-start"),
|
||||
EndHour: this.getAttribute("data-end")
|
||||
}
|
||||
}).get()
|
||||
}
|
||||
|
||||
function getBlockedTagsFromPage(page) {
|
||||
return $(".blockedTag", page).map(function() {
|
||||
return this.getAttribute("data-tag")
|
||||
}).get()
|
||||
}
|
||||
|
||||
function showBlockedTagPopup(page) {
|
||||
require(["prompt"], function(prompt) {
|
||||
prompt({
|
||||
label: Globalize.translate("LabelTag")
|
||||
}).then(function(value) {
|
||||
var tags = getBlockedTagsFromPage(page); - 1 == tags.indexOf(value) && (tags.push(value), loadBlockedTags(page, tags))
|
||||
})
|
||||
})
|
||||
}
|
||||
window.UserParentalControlPage = {
|
||||
onSubmit: function() {
|
||||
var page = $(this).parents(".page");
|
||||
loading.show();
|
||||
var userId = getParameterByName("userId");
|
||||
return ApiClient.getUser(userId).then(function(result) {
|
||||
saveUser(result, page)
|
||||
}), !1
|
||||
}
|
||||
}, $(document).on("pageinit", "#userParentalControlPage", function() {
|
||||
var page = this;
|
||||
$(".btnAddSchedule", page).on("click", function() {
|
||||
showSchedulePopup(page, {}, -1)
|
||||
}), $(".btnAddBlockedTag", page).on("click", function() {
|
||||
showBlockedTagPopup(page)
|
||||
}), $(".userParentalControlForm").off("submit", UserParentalControlPage.onSubmit).on("submit", UserParentalControlPage.onSubmit)
|
||||
}).on("pageshow", "#userParentalControlPage", function() {
|
||||
var page = this;
|
||||
loading.show();
|
||||
var userId = getParameterByName("userId"),
|
||||
promise1 = ApiClient.getUser(userId),
|
||||
promise2 = ApiClient.getParentalRatings();
|
||||
Promise.all([promise1, promise2]).then(function(responses) {
|
||||
loadUser(page, responses[0], responses[1])
|
||||
})
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
define(["jQuery", "loading", "libraryMenu"], function($, loading, libraryMenu) {
|
||||
"use strict";
|
||||
|
||||
function loadUser(page, user) {
|
||||
libraryMenu.setTitle(user.Name), "Guest" == user.ConnectLinkType ? $(".connectMessage", page).show() : $(".connectMessage", page).hide(), loading.hide()
|
||||
}
|
||||
|
||||
function loadData(page) {
|
||||
loading.show();
|
||||
var userId = getParameterByName("userId");
|
||||
ApiClient.getUser(userId).then(function(user) {
|
||||
loadUser(page, user)
|
||||
})
|
||||
}
|
||||
$(document).on("pageinit", "#userPasswordPage", function() {
|
||||
$(".adminUpdatePasswordForm").off("submit", UpdatePasswordPage.onSubmit).on("submit", UpdatePasswordPage.onSubmit), $(".adminLocalAccessForm").off("submit", UpdatePasswordPage.onLocalAccessSubmit).on("submit", UpdatePasswordPage.onLocalAccessSubmit)
|
||||
}).on("pagebeforeshow", "#userPasswordPage", function() {
|
||||
loadData(this)
|
||||
})
|
||||
});
|
||||
@@ -0,0 +1,96 @@
|
||||
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;
|
||||
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)
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,305 @@
|
||||
define(["loading", "dom", "globalize", "humanedate", "paper-icon-button-light", "cardStyle", "emby-linkbutton", "indicators", "flexStyles"], function (loading, dom, globalize) {
|
||||
"use strict";
|
||||
|
||||
function deleteUser(page, id) {
|
||||
var msg = globalize.translate("DeleteUserConfirmation");
|
||||
|
||||
require(["confirm"], function (confirm) {
|
||||
confirm({
|
||||
title: globalize.translate("DeleteUser"),
|
||||
text: msg,
|
||||
confirmText: globalize.translate("ButtonDelete"),
|
||||
primary: "cancel"
|
||||
}).then(function () {
|
||||
loading.show();
|
||||
ApiClient.deleteUser(id).then(function () {
|
||||
loadData(page);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showUserMenu(elem) {
|
||||
var card = dom.parentWithClass(elem, "card");
|
||||
var page = dom.parentWithClass(card, "page");
|
||||
var userId = card.getAttribute("data-userid");
|
||||
var menuItems = [];
|
||||
menuItems.push({
|
||||
name: globalize.translate("ButtonOpen"),
|
||||
id: "open",
|
||||
ironIcon: "mode-edit"
|
||||
});
|
||||
menuItems.push({
|
||||
name: globalize.translate("ButtonLibraryAccess"),
|
||||
id: "access",
|
||||
ironIcon: "lock"
|
||||
});
|
||||
menuItems.push({
|
||||
name: globalize.translate("ButtonParentalControl"),
|
||||
id: "parentalcontrol",
|
||||
ironIcon: "person"
|
||||
});
|
||||
menuItems.push({
|
||||
name: globalize.translate("ButtonDelete"),
|
||||
id: "delete",
|
||||
ironIcon: "delete"
|
||||
});
|
||||
|
||||
require(["actionsheet"], function (actionsheet) {
|
||||
actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: card,
|
||||
callback: function (id) {
|
||||
switch (id) {
|
||||
case "open":
|
||||
Dashboard.navigate("useredit.html?userId=" + userId);
|
||||
break;
|
||||
|
||||
case "access":
|
||||
Dashboard.navigate("userlibraryaccess.html?userId=" + userId);
|
||||
break;
|
||||
|
||||
case "parentalcontrol":
|
||||
Dashboard.navigate("userparentalcontrol.html?userId=" + userId);
|
||||
break;
|
||||
|
||||
case "delete":
|
||||
deleteUser(page, userId);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getUserHtml(user, addConnectIndicator) {
|
||||
var html = "";
|
||||
var cssClass = "card squareCard scalableCard squareCard-scalable";
|
||||
|
||||
if (user.Policy.IsDisabled) {
|
||||
cssClass += " grayscale";
|
||||
}
|
||||
|
||||
html += "<div data-userid='" + user.Id + "' class='" + cssClass + "'>";
|
||||
html += '<div class="cardBox visualCardBox">';
|
||||
html += '<div class="cardScalable visualCardBox-cardScalable">';
|
||||
html += '<div class="cardPadder cardPadder-square"></div>';
|
||||
html += '<a is="emby-linkbutton" class="cardContent" href="useredit.html?userId=' + user.Id + '">';
|
||||
var imgUrl;
|
||||
|
||||
if (user.PrimaryImageTag) {
|
||||
imgUrl = ApiClient.getUserImageUrl(user.Id, {
|
||||
width: 300,
|
||||
tag: user.PrimaryImageTag,
|
||||
type: "Primary"
|
||||
});
|
||||
}
|
||||
|
||||
var imageClass = "cardImage";
|
||||
|
||||
if (user.Policy.IsDisabled) {
|
||||
imageClass += " disabledUser";
|
||||
}
|
||||
|
||||
if (imgUrl) {
|
||||
html += '<div class="' + imageClass + '" style="background-image:url(\'' + imgUrl + "');\">";
|
||||
} else {
|
||||
html += '<div class="' + imageClass + ' flex align-items-center justify-content-center">';
|
||||
html += '<i class="md-icon cardImageIcon">person</i>';
|
||||
}
|
||||
|
||||
html += "</div>";
|
||||
html += "</a>";
|
||||
html += "</div>";
|
||||
html += '<div class="cardFooter visualCardBox-cardFooter">';
|
||||
html += '<div class="cardText flex align-items-center">';
|
||||
html += '<div class="flex-grow" style="overflow:hidden;text-overflow:ellipsis;">';
|
||||
html += user.Name;
|
||||
html += "</div>";
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnUserMenu flex-shrink-zero"><i class="md-icon">more_horiz</i></button>';
|
||||
html += "</div>";
|
||||
html += '<div class="cardText cardText-secondary">';
|
||||
var lastSeen = getLastSeenText(user.LastActivityDate);
|
||||
html += "" != lastSeen ? lastSeen : " ";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
return html + "</div>";
|
||||
}
|
||||
|
||||
function getLastSeenText(lastActivityDate) {
|
||||
if (lastActivityDate) {
|
||||
return "Last seen " + humane_date(lastActivityDate);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
function getUserSectionHtml(users, addConnectIndicator) {
|
||||
return users.map(function (u__q) {
|
||||
return getUserHtml(u__q, addConnectIndicator);
|
||||
}).join("");
|
||||
}
|
||||
|
||||
function renderUsers(page, users) {
|
||||
page.querySelector(".localUsers").innerHTML = getUserSectionHtml(users, true);
|
||||
}
|
||||
|
||||
function showPendingUserMenu(elem) {
|
||||
var menuItems = [];
|
||||
menuItems.push({
|
||||
name: globalize.translate("ButtonCancel"),
|
||||
id: "delete",
|
||||
ironIcon: "delete"
|
||||
});
|
||||
|
||||
require(["actionsheet"], function (actionsheet) {
|
||||
var card = dom.parentWithClass(elem, "card");
|
||||
var page = dom.parentWithClass(card, "page");
|
||||
var id = card.getAttribute("data-id");
|
||||
actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: card,
|
||||
callback: function (menuItemId) {
|
||||
switch (menuItemId) {
|
||||
case "delete":
|
||||
cancelAuthorization(page, id);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getPendingUserHtml(user) {
|
||||
var html = "";
|
||||
html += "<div data-id='" + user.Id + "' class='card squareCard scalableCard squareCard-scalable'>";
|
||||
html += '<div class="cardBox cardBox-bottompadded visualCardBox">';
|
||||
html += '<div class="cardScalable visualCardBox-cardScalable">';
|
||||
html += '<div class="cardPadder cardPadder-square"></div>';
|
||||
html += '<a class="cardContent cardImageContainer" is="emby-linkbutton" href="#">';
|
||||
|
||||
if (user.ImageUrl) {
|
||||
html += '<div class="cardImage" style="background-image:url(\'' + user.ImageUrl + "');\">";
|
||||
html += "</div>";
|
||||
} else {
|
||||
html += '<i class="cardImageIcon md-icon"></i>';
|
||||
}
|
||||
|
||||
html += "</a>";
|
||||
html += "</div>";
|
||||
html += '<div class="cardFooter visualCardBox-cardFooter">';
|
||||
html += '<div class="cardText" style="text-align:right; float:right;padding:0;">';
|
||||
html += '<button type="button" is="paper-icon-button-light" class="btnUserMenu"><i class="md-icon">more_horiz</i></button>';
|
||||
html += "</div>";
|
||||
html += '<div class="cardText" style="padding-top:10px;padding-bottom:10px;">';
|
||||
html += user.UserName;
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
html += "</div>";
|
||||
return html + "</div>";
|
||||
}
|
||||
|
||||
function renderPendingGuests(page, users) {
|
||||
if (users.length) {
|
||||
page.querySelector(".sectionPendingGuests").classList.remove("hide");
|
||||
} else {
|
||||
page.querySelector(".sectionPendingGuests").classList.add("hide");
|
||||
}
|
||||
|
||||
page.querySelector(".pending").innerHTML = users.map(getPendingUserHtml).join("");
|
||||
}
|
||||
|
||||
// TODO cvium: maybe reuse for invitation system
|
||||
function cancelAuthorization(page, id) {
|
||||
loading.show();
|
||||
ApiClient.ajax({
|
||||
type: "DELETE",
|
||||
url: ApiClient.getUrl("Connect/Pending", {
|
||||
Id: id
|
||||
})
|
||||
}).then(function () {
|
||||
loadData(page);
|
||||
});
|
||||
}
|
||||
|
||||
function loadData(page) {
|
||||
loading.show();
|
||||
ApiClient.getUsers().then(function (users) {
|
||||
renderUsers(page, users);
|
||||
loading.hide();
|
||||
});
|
||||
// TODO cvium
|
||||
renderPendingGuests(page, []);
|
||||
// ApiClient.getJSON(ApiClient.getUrl("Connect/Pending")).then(function (pending) {
|
||||
//
|
||||
// });
|
||||
}
|
||||
|
||||
function showInvitePopup(page) {
|
||||
require(["components/guestinviter/guestinviter"], function (guestinviter) {
|
||||
guestinviter.show().then(function () {
|
||||
loadData(page);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showNewUserDialog(e__w) {
|
||||
require(["dialog"], function (dialog) {
|
||||
var items = [];
|
||||
items.push({
|
||||
name: globalize.translate("HeaderAddLocalUser"),
|
||||
id: "manual",
|
||||
type: "submit",
|
||||
description: globalize.translate("AddUserByManually")
|
||||
});
|
||||
// TODO cvium
|
||||
// items.push({
|
||||
// name: globalize.translate("HeaderInviteUser"),
|
||||
// id: "invite",
|
||||
// description: globalize.translate("HeaderInviteUserHelp")
|
||||
// });
|
||||
items.push({
|
||||
name: globalize.translate("sharedcomponents#ButtonCancel"),
|
||||
id: "cancel",
|
||||
type: "cancel"
|
||||
});
|
||||
var options = {
|
||||
title: globalize.translate("ButtonAddUser"),
|
||||
text: globalize.translate("HowWouldYouLikeToAddUser")
|
||||
};
|
||||
options.buttons = items;
|
||||
return dialog(options).then(function (result) {
|
||||
var view = dom.parentWithClass(e__w.target, "page");
|
||||
debugger;
|
||||
if ("invite" === result) {
|
||||
showInvitePopup(view);
|
||||
} else {
|
||||
if ("manual" === result) {
|
||||
Dashboard.navigate("usernew.html");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pageIdOn("pageinit", "userProfilesPage", function () {
|
||||
var page = this;
|
||||
page.querySelector(".btnAddUser").addEventListener("click", showNewUserDialog);
|
||||
page.querySelector(".localUsers").addEventListener("click", function (e__e) {
|
||||
var btnUserMenu = dom.parentWithClass(e__e.target, "btnUserMenu");
|
||||
|
||||
if (btnUserMenu) {
|
||||
showUserMenu(btnUserMenu);
|
||||
}
|
||||
});
|
||||
page.querySelector(".pending").addEventListener("click", function (e__r) {
|
||||
var btnUserMenu = dom.parentWithClass(e__r.target, "btnUserMenu");
|
||||
|
||||
if (btnUserMenu) {
|
||||
showPendingUserMenu(btnUserMenu);
|
||||
}
|
||||
});
|
||||
});
|
||||
pageIdOn("pagebeforeshow", "userProfilesPage", function () {
|
||||
loadData(this);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,724 @@
|
||||
define(["playbackManager", "dom", "inputmanager", "datetime", "itemHelper", "mediaInfo", "focusManager", "imageLoader", "scrollHelper", "events", "connectionManager", "browser", "globalize", "apphost", "layoutManager", "userSettings", "scrollStyles", "emby-slider", "paper-icon-button-light", "css!css/videoosd"], function(playbackManager, dom, inputManager, datetime, itemHelper, mediaInfo, focusManager, imageLoader, scrollHelper, events, connectionManager, browser, globalize, appHost, layoutManager, userSettings) {
|
||||
"use strict";
|
||||
|
||||
function seriesImageUrl(item, options) {
|
||||
if ("Episode" !== item.Type) return null;
|
||||
if (options = options || {}, options.type = options.type || "Primary", "Primary" === options.type && item.SeriesPrimaryImageTag) return options.tag = item.SeriesPrimaryImageTag, connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options);
|
||||
if ("Thumb" === options.type) {
|
||||
if (item.SeriesThumbImageTag) return options.tag = item.SeriesThumbImageTag, connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.SeriesId, options);
|
||||
if (item.ParentThumbImageTag) return options.tag = item.ParentThumbImageTag, connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.ParentThumbItemId, options)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function imageUrl(item, options) {
|
||||
return options = options || {}, options.type = options.type || "Primary", item.ImageTags && item.ImageTags[options.type] ? (options.tag = item.ImageTags[options.type], connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.PrimaryImageItemId || item.Id, options)) : "Primary" === options.type && item.AlbumId && item.AlbumPrimaryImageTag ? (options.tag = item.AlbumPrimaryImageTag, connectionManager.getApiClient(item.ServerId).getScaledImageUrl(item.AlbumId, options)) : null
|
||||
}
|
||||
|
||||
function logoImageUrl(item, apiClient, options) {
|
||||
return options = options || {}, options.type = "Logo", item.ImageTags && item.ImageTags.Logo ? (options.tag = item.ImageTags.Logo, apiClient.getScaledImageUrl(item.Id, options)) : item.ParentLogoImageTag ? (options.tag = item.ParentLogoImageTag, apiClient.getScaledImageUrl(item.ParentLogoItemId, options)) : null
|
||||
}
|
||||
return function(view, params) {
|
||||
function onVerticalSwipe(e, elem, data) {
|
||||
var player = currentPlayer;
|
||||
if (player) {
|
||||
var deltaY = data.currentDeltaY,
|
||||
windowSize = dom.getWindowSize();
|
||||
if (supportsBrightnessChange && data.clientX < windowSize.innerWidth / 2) return void doBrightnessTouch(deltaY, player, windowSize.innerHeight);
|
||||
doVolumeTouch(deltaY, player, windowSize.innerHeight)
|
||||
}
|
||||
}
|
||||
|
||||
function doBrightnessTouch(deltaY, player, viewHeight) {
|
||||
var delta = -deltaY / viewHeight * 100,
|
||||
newValue = playbackManager.getBrightness(player) + delta;
|
||||
newValue = Math.min(newValue, 100), newValue = Math.max(newValue, 0), playbackManager.setBrightness(newValue, player)
|
||||
}
|
||||
|
||||
function doVolumeTouch(deltaY, player, viewHeight) {
|
||||
var delta = -deltaY / viewHeight * 100,
|
||||
newValue = playbackManager.getVolume(player) + delta;
|
||||
newValue = Math.min(newValue, 100), newValue = Math.max(newValue, 0), playbackManager.setVolume(newValue, player)
|
||||
}
|
||||
|
||||
function onDoubleClick(e) {
|
||||
var clientX = e.clientX;
|
||||
if (null != clientX) {
|
||||
clientX < dom.getWindowSize().innerWidth / 2 ? playbackManager.rewind(currentPlayer) : playbackManager.fastForward(currentPlayer), e.preventDefault(), e.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
function getDisplayItem(item) {
|
||||
if ("TvChannel" === item.Type) {
|
||||
var apiClient = connectionManager.getApiClient(item.ServerId);
|
||||
return apiClient.getItem(apiClient.getCurrentUserId(), item.Id).then(function(refreshedItem) {
|
||||
return {
|
||||
originalItem: refreshedItem,
|
||||
displayItem: refreshedItem.CurrentProgram
|
||||
}
|
||||
})
|
||||
}
|
||||
return Promise.resolve({
|
||||
originalItem: item
|
||||
})
|
||||
}
|
||||
|
||||
function updateRecordingButton(item) {
|
||||
if (!item || "Program" !== item.Type) return recordingButtonManager && (recordingButtonManager.destroy(), recordingButtonManager = null), void view.querySelector(".btnRecord").classList.add("hide");
|
||||
connectionManager.getApiClient(item.ServerId).getCurrentUser().then(function(user) {
|
||||
user.Policy.EnableLiveTvManagement && require(["recordingButton"], function(RecordingButton) {
|
||||
if (recordingButtonManager) return void recordingButtonManager.refreshItem(item);
|
||||
recordingButtonManager = new RecordingButton({
|
||||
item: item,
|
||||
button: view.querySelector(".btnRecord")
|
||||
}), view.querySelector(".btnRecord").classList.remove("hide")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function updateDisplayItem(itemInfo) {
|
||||
var item = itemInfo.originalItem;
|
||||
currentItem = item;
|
||||
var displayItem = itemInfo.displayItem || item;
|
||||
updateRecordingButton(displayItem), setPoster(displayItem, item);
|
||||
var parentName = displayItem.SeriesName || displayItem.Album;
|
||||
(displayItem.EpisodeTitle || displayItem.IsSeries) && (parentName = displayItem.Name), setTitle(displayItem, parentName);
|
||||
var titleElement, osdTitle = view.querySelector(".osdTitle");
|
||||
titleElement = osdTitle;
|
||||
var displayName = itemHelper.getDisplayName(displayItem, {
|
||||
includeParentInfo: "Program" !== displayItem.Type,
|
||||
includeIndexNumber: "Program" !== displayItem.Type
|
||||
});
|
||||
!displayName && displayItem.Type, titleElement.innerHTML = displayName, displayName ? titleElement.classList.remove("hide") : titleElement.classList.add("hide");
|
||||
var mediaInfoHtml = mediaInfo.getPrimaryMediaInfoHtml(displayItem, {
|
||||
runtime: !1,
|
||||
subtitles: !1,
|
||||
tomatoes: !1,
|
||||
endsAt: !1,
|
||||
episodeTitle: !1,
|
||||
originalAirDate: "Program" !== displayItem.Type,
|
||||
episodeTitleIndexNumber: "Program" !== displayItem.Type,
|
||||
programIndicator: !1
|
||||
}),
|
||||
osdMediaInfo = view.querySelector(".osdMediaInfo");
|
||||
osdMediaInfo.innerHTML = mediaInfoHtml, mediaInfoHtml ? osdMediaInfo.classList.remove("hide") : osdMediaInfo.classList.add("hide");
|
||||
var secondaryMediaInfo = view.querySelector(".osdSecondaryMediaInfo"),
|
||||
secondaryMediaInfoHtml = mediaInfo.getSecondaryMediaInfoHtml(displayItem, {
|
||||
startDate: !1,
|
||||
programTime: !1
|
||||
});
|
||||
secondaryMediaInfo.innerHTML = secondaryMediaInfoHtml, secondaryMediaInfoHtml ? secondaryMediaInfo.classList.remove("hide") : secondaryMediaInfo.classList.add("hide"), displayName ? view.querySelector(".osdMainTextContainer").classList.remove("hide") : view.querySelector(".osdMainTextContainer").classList.add("hide"), enableProgressByTimeOfDay ? (setDisplayTime(startTimeText, displayItem.StartDate), setDisplayTime(endTimeText, displayItem.EndDate), startTimeText.classList.remove("hide"), endTimeText.classList.remove("hide"), programStartDateMs = displayItem.StartDate ? datetime.parseISO8601Date(displayItem.StartDate).getTime() : 0, programEndDateMs = displayItem.EndDate ? datetime.parseISO8601Date(displayItem.EndDate).getTime() : 0) : (startTimeText.classList.add("hide"), endTimeText.classList.add("hide"), startTimeText.innerHTML = "", endTimeText.innerHTML = "", programStartDateMs = 0, programEndDateMs = 0)
|
||||
}
|
||||
|
||||
function getDisplayTimeWithoutAmPm(date, showSeconds) {
|
||||
return showSeconds ? datetime.toLocaleTimeString(date, {
|
||||
hour: "numeric",
|
||||
minute: "2-digit",
|
||||
second: "2-digit"
|
||||
}).toLowerCase().replace("am", "").replace("pm", "").trim() : datetime.getDisplayTime(date).toLowerCase().replace("am", "").replace("pm", "").trim()
|
||||
}
|
||||
|
||||
function setDisplayTime(elem, date) {
|
||||
var html;
|
||||
date && (date = datetime.parseISO8601Date(date), html = getDisplayTimeWithoutAmPm(date)), elem.innerHTML = html || ""
|
||||
}
|
||||
|
||||
function shouldEnableProgressByTimeOfDay(item) {
|
||||
return !("TvChannel" !== item.Type || !item.CurrentProgram)
|
||||
}
|
||||
|
||||
function updateNowPlayingInfo(player, state) {
|
||||
var item = state.NowPlayingItem;
|
||||
if (currentItem = item, !item) return setPoster(null), updateRecordingButton(null), Emby.Page.setTitle(""), nowPlayingVolumeSlider.disabled = !0, nowPlayingPositionSlider.disabled = !0, btnFastForward.disabled = !0, btnRewind.disabled = !0, view.querySelector(".btnSubtitles").classList.add("hide"), view.querySelector(".btnAudio").classList.add("hide"), view.querySelector(".osdTitle").innerHTML = "", void(view.querySelector(".osdMediaInfo").innerHTML = "");
|
||||
enableProgressByTimeOfDay = shouldEnableProgressByTimeOfDay(item), getDisplayItem(item).then(updateDisplayItem), nowPlayingVolumeSlider.disabled = !1, nowPlayingPositionSlider.disabled = !1, btnFastForward.disabled = !1, btnRewind.disabled = !1, playbackManager.subtitleTracks(player).length ? view.querySelector(".btnSubtitles").classList.remove("hide") : view.querySelector(".btnSubtitles").classList.add("hide"), playbackManager.audioTracks(player).length > 1 ? view.querySelector(".btnAudio").classList.remove("hide") : view.querySelector(".btnAudio").classList.add("hide")
|
||||
}
|
||||
|
||||
function setTitle(item, parentName) {
|
||||
var url = logoImageUrl(item, connectionManager.getApiClient(item.ServerId), {});
|
||||
if (url) {
|
||||
Emby.Page.setTitle("");
|
||||
var pageTitle = document.querySelector(".pageTitle");
|
||||
pageTitle.style.backgroundImage = "url('" + url + "')", pageTitle.classList.add("pageTitleWithLogo"), pageTitle.classList.remove("pageTitleWithDefaultLogo"), pageTitle.innerHTML = ""
|
||||
} else Emby.Page.setTitle(parentName || "");
|
||||
var documentTitle = parentName || (item ? item.Name : null);
|
||||
documentTitle && (document.title = documentTitle)
|
||||
}
|
||||
|
||||
function setPoster(item, secondaryItem) {
|
||||
var osdPoster = view.querySelector(".osdPoster");
|
||||
if (item) {
|
||||
var imgUrl = seriesImageUrl(item, {
|
||||
type: "Primary"
|
||||
}) || seriesImageUrl(item, {
|
||||
type: "Thumb"
|
||||
}) || imageUrl(item, {
|
||||
type: "Primary"
|
||||
});
|
||||
if (!imgUrl && secondaryItem && (imgUrl = seriesImageUrl(secondaryItem, {
|
||||
type: "Primary"
|
||||
}) || seriesImageUrl(secondaryItem, {
|
||||
type: "Thumb"
|
||||
}) || imageUrl(secondaryItem, {
|
||||
type: "Primary"
|
||||
})), imgUrl) return void(osdPoster.innerHTML = '<img src="' + imgUrl + '" />')
|
||||
}
|
||||
osdPoster.innerHTML = ""
|
||||
}
|
||||
|
||||
function showOsd() {
|
||||
slideDownToShow(headerElement), showMainOsdControls(), startOsdHideTimer()
|
||||
}
|
||||
|
||||
function hideOsd() {
|
||||
slideUpToHide(headerElement), hideMainOsdControls()
|
||||
}
|
||||
|
||||
function toggleOsd() {
|
||||
"osd" === currentVisibleMenu ? hideOsd() : currentVisibleMenu || showOsd()
|
||||
}
|
||||
|
||||
function startOsdHideTimer() {
|
||||
stopOsdHideTimer(), osdHideTimeout = setTimeout(hideOsd, 5e3)
|
||||
}
|
||||
|
||||
function stopOsdHideTimer() {
|
||||
osdHideTimeout && (clearTimeout(osdHideTimeout), osdHideTimeout = null)
|
||||
}
|
||||
|
||||
function slideDownToShow(elem) {
|
||||
elem.classList.remove("osdHeader-hidden")
|
||||
}
|
||||
|
||||
function slideUpToHide(elem) {
|
||||
elem.classList.add("osdHeader-hidden")
|
||||
}
|
||||
|
||||
function clearHideAnimationEventListeners(elem) {
|
||||
dom.removeEventListener(elem, transitionEndEventName, onHideAnimationComplete, {
|
||||
once: !0
|
||||
})
|
||||
}
|
||||
|
||||
function onHideAnimationComplete(e) {
|
||||
var elem = e.target;
|
||||
elem.classList.add("hide"), dom.removeEventListener(elem, transitionEndEventName, onHideAnimationComplete, {
|
||||
once: !0
|
||||
})
|
||||
}
|
||||
|
||||
function showMainOsdControls() {
|
||||
if (!currentVisibleMenu) {
|
||||
var elem = osdBottomElement;
|
||||
currentVisibleMenu = "osd", clearHideAnimationEventListeners(elem), elem.classList.remove("hide"), elem.offsetWidth, elem.classList.remove("videoOsdBottom-hidden"), layoutManager.mobile || setTimeout(function() {
|
||||
focusManager.focus(elem.querySelector(".btnPause"))
|
||||
}, 50)
|
||||
}
|
||||
}
|
||||
|
||||
function hideMainOsdControls() {
|
||||
if ("osd" === currentVisibleMenu) {
|
||||
var elem = osdBottomElement;
|
||||
clearHideAnimationEventListeners(elem), elem.offsetWidth, elem.classList.add("videoOsdBottom-hidden"), dom.addEventListener(elem, transitionEndEventName, onHideAnimationComplete, {
|
||||
once: !0
|
||||
}), currentVisibleMenu = null
|
||||
}
|
||||
}
|
||||
|
||||
function onPointerMove(e) {
|
||||
if ("mouse" === (e.pointerType || (layoutManager.mobile ? "touch" : "mouse"))) {
|
||||
var eventX = e.screenX || 0,
|
||||
eventY = e.screenY || 0,
|
||||
obj = lastPointerMoveData;
|
||||
if (!obj) return void(lastPointerMoveData = {
|
||||
x: eventX,
|
||||
y: eventY
|
||||
});
|
||||
if (Math.abs(eventX - obj.x) < 10 && Math.abs(eventY - obj.y) < 10) return;
|
||||
obj.x = eventX, obj.y = eventY, showOsd()
|
||||
}
|
||||
}
|
||||
|
||||
function onInputCommand(e) {
|
||||
var player = currentPlayer;
|
||||
switch (e.detail.command) {
|
||||
case "left":
|
||||
"osd" === currentVisibleMenu ? showOsd() : currentVisibleMenu || (e.preventDefault(), playbackManager.rewind(player));
|
||||
break;
|
||||
case "right":
|
||||
"osd" === currentVisibleMenu ? showOsd() : currentVisibleMenu || (e.preventDefault(), playbackManager.fastForward(player));
|
||||
break;
|
||||
case "pageup":
|
||||
playbackManager.nextChapter(player);
|
||||
break;
|
||||
case "pagedown":
|
||||
playbackManager.previousChapter(player);
|
||||
break;
|
||||
case "up":
|
||||
case "down":
|
||||
case "select":
|
||||
case "menu":
|
||||
case "info":
|
||||
case "play":
|
||||
case "playpause":
|
||||
case "pause":
|
||||
case "fastforward":
|
||||
case "rewind":
|
||||
case "next":
|
||||
case "previous":
|
||||
showOsd();
|
||||
break;
|
||||
case "record":
|
||||
onRecordingCommand(), showOsd();
|
||||
break;
|
||||
case "togglestats":
|
||||
toggleStats()
|
||||
}
|
||||
}
|
||||
|
||||
function onRecordingCommand() {
|
||||
var btnRecord = view.querySelector(".btnRecord");
|
||||
btnRecord.classList.contains("hide") || btnRecord.click()
|
||||
}
|
||||
|
||||
function updateFullscreenIcon() {
|
||||
playbackManager.isFullscreen(currentPlayer) ? (view.querySelector(".btnFullscreen").setAttribute("title", globalize.translate("ExitFullscreen")), view.querySelector(".btnFullscreen i").innerHTML = "") : (view.querySelector(".btnFullscreen").setAttribute("title", globalize.translate("Fullscreen")), view.querySelector(".btnFullscreen i").innerHTML = "")
|
||||
}
|
||||
|
||||
function onPlayerChange() {
|
||||
bindToPlayer(playbackManager.getCurrentPlayer())
|
||||
}
|
||||
|
||||
function onStateChanged(event, state) {
|
||||
var player = this;
|
||||
state.NowPlayingItem && (isEnabled = !0, updatePlayerStateInternal(event, player, state), updatePlaylist(player), enableStopOnBack(!0))
|
||||
}
|
||||
|
||||
function onPlayPauseStateChanged(e) {
|
||||
if (isEnabled) {
|
||||
updatePlayPauseState(this.paused())
|
||||
}
|
||||
}
|
||||
|
||||
function onVolumeChanged(e) {
|
||||
if (isEnabled) {
|
||||
var player = this;
|
||||
updatePlayerVolumeState(player, player.isMuted(), player.getVolume())
|
||||
}
|
||||
}
|
||||
|
||||
function onPlaybackStart(e, state) {
|
||||
console.log("nowplaying event: " + e.type);
|
||||
var player = this;
|
||||
onStateChanged.call(player, e, state), resetUpNextDialog()
|
||||
}
|
||||
|
||||
function resetUpNextDialog() {
|
||||
comingUpNextDisplayed = !1;
|
||||
var dlg = currentUpNextDialog;
|
||||
dlg && (dlg.destroy(), currentUpNextDialog = null)
|
||||
}
|
||||
|
||||
function onPlaybackStopped(e, state) {
|
||||
currentRuntimeTicks = null, resetUpNextDialog(), console.log("nowplaying event: " + e.type), "Video" !== state.NextMediaType && (view.removeEventListener("viewbeforehide", onViewHideStopPlayback), Emby.Page.back())
|
||||
}
|
||||
|
||||
function onMediaStreamsChanged(e) {
|
||||
var player = this,
|
||||
state = playbackManager.getPlayerState(player);
|
||||
onStateChanged.call(player, {
|
||||
type: "init"
|
||||
}, state)
|
||||
}
|
||||
|
||||
function bindToPlayer(player) {
|
||||
if (player !== currentPlayer && (releaseCurrentPlayer(), currentPlayer = player, player)) {
|
||||
var state = playbackManager.getPlayerState(player);
|
||||
onStateChanged.call(player, {
|
||||
type: "init"
|
||||
}, state), events.on(player, "playbackstart", onPlaybackStart), events.on(player, "playbackstop", onPlaybackStopped), events.on(player, "volumechange", onVolumeChanged), events.on(player, "pause", onPlayPauseStateChanged), events.on(player, "unpause", onPlayPauseStateChanged), events.on(player, "timeupdate", onTimeUpdate), events.on(player, "fullscreenchange", updateFullscreenIcon), events.on(player, "mediastreamschange", onMediaStreamsChanged), resetUpNextDialog()
|
||||
}
|
||||
}
|
||||
|
||||
function releaseCurrentPlayer() {
|
||||
destroyStats(), resetUpNextDialog();
|
||||
var player = currentPlayer;
|
||||
player && (events.off(player, "playbackstart", onPlaybackStart), events.off(player, "playbackstop", onPlaybackStopped), events.off(player, "volumechange", onVolumeChanged), events.off(player, "pause", onPlayPauseStateChanged), events.off(player, "unpause", onPlayPauseStateChanged), events.off(player, "timeupdate", onTimeUpdate), events.off(player, "fullscreenchange", updateFullscreenIcon), events.off(player, "mediastreamschange", onMediaStreamsChanged), currentPlayer = null)
|
||||
}
|
||||
|
||||
function onTimeUpdate(e) {
|
||||
if (isEnabled) {
|
||||
var now = (new Date).getTime();
|
||||
if (!(now - lastUpdateTime < 700)) {
|
||||
lastUpdateTime = now;
|
||||
var player = this;
|
||||
currentRuntimeTicks = playbackManager.duration(player);
|
||||
var currentTime = playbackManager.currentTime(player);
|
||||
updateTimeDisplay(currentTime, currentRuntimeTicks, playbackManager.playbackStartTime(player), playbackManager.getBufferedRanges(player));
|
||||
var item = currentItem;
|
||||
refreshProgramInfoIfNeeded(player, item), showComingUpNextIfNeeded(player, item, currentTime, currentRuntimeTicks)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showComingUpNextIfNeeded(player, currentItem, currentTimeTicks, runtimeTicks) {
|
||||
if (runtimeTicks && currentTimeTicks && !comingUpNextDisplayed && !currentVisibleMenu && "Episode" === currentItem.Type && userSettings.enableNextVideoInfoOverlay()) {
|
||||
var showAtSecondsLeft = runtimeTicks >= 3e10 ? 40 : runtimeTicks >= 24e9 ? 35 : 30,
|
||||
showAtTicks = runtimeTicks - 1e3 * showAtSecondsLeft * 1e4,
|
||||
timeRemainingTicks = runtimeTicks - currentTimeTicks;
|
||||
currentTimeTicks >= showAtTicks && runtimeTicks >= 6e9 && timeRemainingTicks >= 2e8 && showComingUpNext(player)
|
||||
}
|
||||
}
|
||||
|
||||
function onUpNextHidden() {
|
||||
"upnext" === currentVisibleMenu && (currentVisibleMenu = null)
|
||||
}
|
||||
|
||||
function showComingUpNext(player) {
|
||||
require(["upNextDialog"], function(UpNextDialog) {
|
||||
currentVisibleMenu || currentUpNextDialog || (currentVisibleMenu = "upnext", comingUpNextDisplayed = !0, playbackManager.nextItem(player).then(function(nextItem) {
|
||||
currentUpNextDialog = new UpNextDialog({
|
||||
parent: view.querySelector(".upNextContainer"),
|
||||
player: player,
|
||||
nextItem: nextItem
|
||||
}), events.on(currentUpNextDialog, "hide", onUpNextHidden)
|
||||
}, onUpNextHidden))
|
||||
})
|
||||
}
|
||||
|
||||
function refreshProgramInfoIfNeeded(player, item) {
|
||||
if ("TvChannel" === item.Type) {
|
||||
var program = item.CurrentProgram;
|
||||
if (program && program.EndDate) try {
|
||||
var endDate = datetime.parseISO8601Date(program.EndDate);
|
||||
if ((new Date).getTime() >= endDate.getTime()) {
|
||||
console.log("program info needs to be refreshed");
|
||||
var state = playbackManager.getPlayerState(player);
|
||||
onStateChanged.call(player, {
|
||||
type: "init"
|
||||
}, state)
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Error parsing date: " + program.EndDate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updatePlayPauseState(isPaused) {
|
||||
view.querySelector(".btnPause i").innerHTML = isPaused ? "" : ""
|
||||
}
|
||||
|
||||
function updatePlayerStateInternal(event, player, state) {
|
||||
var playState = state.PlayState || {};
|
||||
updatePlayPauseState(playState.IsPaused);
|
||||
var supportedCommands = playbackManager.getSupportedCommands(player);
|
||||
currentPlayerSupportedCommands = supportedCommands, supportsBrightnessChange = -1 !== supportedCommands.indexOf("SetBrightness"), updatePlayerVolumeState(player, playState.IsMuted, playState.VolumeLevel), nowPlayingPositionSlider && !nowPlayingPositionSlider.dragging && (nowPlayingPositionSlider.disabled = !playState.CanSeek), btnFastForward.disabled = !playState.CanSeek, btnRewind.disabled = !playState.CanSeek;
|
||||
var nowPlayingItem = state.NowPlayingItem || {};
|
||||
playbackStartTimeTicks = playState.PlaybackStartTimeTicks, updateTimeDisplay(playState.PositionTicks, nowPlayingItem.RunTimeTicks, playState.PlaybackStartTimeTicks, playState.BufferedRanges || []), updateNowPlayingInfo(player, state), state.MediaSource && state.MediaSource.SupportsTranscoding && -1 !== supportedCommands.indexOf("SetMaxStreamingBitrate") ? view.querySelector(".btnVideoOsdSettings").classList.remove("hide") : view.querySelector(".btnVideoOsdSettings").classList.add("hide");
|
||||
var isProgressClear = state.MediaSource && null == state.MediaSource.RunTimeTicks;
|
||||
nowPlayingPositionSlider.setIsClear(isProgressClear), -1 === supportedCommands.indexOf("ToggleFullscreen") || player.isLocalPlayer && layoutManager.tv && playbackManager.isFullscreen(player) ? view.querySelector(".btnFullscreen").classList.add("hide") : view.querySelector(".btnFullscreen").classList.remove("hide"), -1 === supportedCommands.indexOf("PictureInPicture") ? view.querySelector(".btnPip").classList.add("hide") : view.querySelector(".btnPip").classList.remove("hide"), updateFullscreenIcon()
|
||||
}
|
||||
|
||||
function getDisplayPercentByTimeOfDay(programStartDateMs, programRuntimeMs, currentTimeMs) {
|
||||
return (currentTimeMs - programStartDateMs) / programRuntimeMs * 100
|
||||
}
|
||||
|
||||
function updateTimeDisplay(positionTicks, runtimeTicks, playbackStartTimeTicks, bufferedRanges) {
|
||||
if (enableProgressByTimeOfDay) {
|
||||
if (nowPlayingPositionSlider && !nowPlayingPositionSlider.dragging)
|
||||
if (programStartDateMs && programEndDateMs) {
|
||||
var currentTimeMs = (playbackStartTimeTicks + (positionTicks || 0)) / 1e4,
|
||||
programRuntimeMs = programEndDateMs - programStartDateMs;
|
||||
if (nowPlayingPositionSlider.value = getDisplayPercentByTimeOfDay(programStartDateMs, programRuntimeMs, currentTimeMs), bufferedRanges.length) {
|
||||
var rangeStart = getDisplayPercentByTimeOfDay(programStartDateMs, programRuntimeMs, (playbackStartTimeTicks + (bufferedRanges[0].start || 0)) / 1e4),
|
||||
rangeEnd = getDisplayPercentByTimeOfDay(programStartDateMs, programRuntimeMs, (playbackStartTimeTicks + (bufferedRanges[0].end || 0)) / 1e4);
|
||||
nowPlayingPositionSlider.setBufferedRanges([{
|
||||
start: rangeStart,
|
||||
end: rangeEnd
|
||||
}])
|
||||
} else nowPlayingPositionSlider.setBufferedRanges([])
|
||||
} else nowPlayingPositionSlider.value = 0, nowPlayingPositionSlider.setBufferedRanges([]);
|
||||
nowPlayingPositionText.innerHTML = "", nowPlayingDurationText.innerHTML = ""
|
||||
} else {
|
||||
if (nowPlayingPositionSlider && !nowPlayingPositionSlider.dragging) {
|
||||
if (runtimeTicks) {
|
||||
var pct = positionTicks / runtimeTicks;
|
||||
pct *= 100, nowPlayingPositionSlider.value = pct
|
||||
} else nowPlayingPositionSlider.value = 0;
|
||||
runtimeTicks && null != positionTicks && currentRuntimeTicks && !enableProgressByTimeOfDay && currentItem.RunTimeTicks && "Recording" !== currentItem.Type ? endsAtText.innerHTML = " - " + mediaInfo.getEndsAtFromPosition(runtimeTicks, positionTicks, !0) : endsAtText.innerHTML = ""
|
||||
}
|
||||
nowPlayingPositionSlider && nowPlayingPositionSlider.setBufferedRanges(bufferedRanges, runtimeTicks, positionTicks), updateTimeText(nowPlayingPositionText, positionTicks), updateTimeText(nowPlayingDurationText, runtimeTicks, !0)
|
||||
}
|
||||
}
|
||||
|
||||
function updatePlayerVolumeState(player, isMuted, volumeLevel) {
|
||||
var supportedCommands = currentPlayerSupportedCommands,
|
||||
showMuteButton = !0,
|
||||
showVolumeSlider = !0; - 1 === supportedCommands.indexOf("Mute") && (showMuteButton = !1), -1 === supportedCommands.indexOf("SetVolume") && (showVolumeSlider = !1), player.isLocalPlayer && appHost.supports("physicalvolumecontrol") && (showMuteButton = !1, showVolumeSlider = !1), isMuted ? (view.querySelector(".buttonMute").setAttribute("title", globalize.translate("Unmute")), view.querySelector(".buttonMute i").innerHTML = "") : (view.querySelector(".buttonMute").setAttribute("title", globalize.translate("Mute")), view.querySelector(".buttonMute i").innerHTML = ""), showMuteButton ? view.querySelector(".buttonMute").classList.remove("hide") : view.querySelector(".buttonMute").classList.add("hide"), nowPlayingVolumeSlider && (showVolumeSlider ? nowPlayingVolumeSliderContainer.classList.remove("hide") : nowPlayingVolumeSliderContainer.classList.add("hide"), nowPlayingVolumeSlider.dragging || (nowPlayingVolumeSlider.value = volumeLevel || 0))
|
||||
}
|
||||
|
||||
function updatePlaylist(player) {
|
||||
var btnPreviousTrack = view.querySelector(".btnPreviousTrack"),
|
||||
btnNextTrack = view.querySelector(".btnNextTrack");
|
||||
btnPreviousTrack.classList.remove("hide"), btnNextTrack.classList.remove("hide"), btnNextTrack.disabled = !1, btnPreviousTrack.disabled = !1
|
||||
}
|
||||
|
||||
function updateTimeText(elem, ticks, divider) {
|
||||
if (null == ticks) return void(elem.innerHTML = "");
|
||||
var html = datetime.getDisplayRunningTime(ticks);
|
||||
divider && (html = " / " + html), elem.innerHTML = html
|
||||
}
|
||||
|
||||
function onSettingsButtonClick(e) {
|
||||
var btn = this;
|
||||
require(["playerSettingsMenu"], function(playerSettingsMenu) {
|
||||
var player = currentPlayer;
|
||||
player && playerSettingsMenu.show({
|
||||
mediaType: "Video",
|
||||
player: player,
|
||||
positionTo: btn,
|
||||
stats: !0,
|
||||
onOption: onSettingsOption
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onSettingsOption(selectedOption) {
|
||||
"stats" === selectedOption && toggleStats()
|
||||
}
|
||||
|
||||
function toggleStats() {
|
||||
require(["playerStats"], function(PlayerStats) {
|
||||
var player = currentPlayer;
|
||||
player && (statsOverlay ? statsOverlay.toggle() : statsOverlay = new PlayerStats({
|
||||
player: player
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
function destroyStats() {
|
||||
statsOverlay && (statsOverlay.destroy(), statsOverlay = null)
|
||||
}
|
||||
|
||||
function showAudioTrackSelection() {
|
||||
var player = currentPlayer,
|
||||
audioTracks = playbackManager.audioTracks(player),
|
||||
currentIndex = playbackManager.getAudioStreamIndex(player),
|
||||
menuItems = audioTracks.map(function(stream) {
|
||||
var opt = {
|
||||
name: stream.DisplayTitle,
|
||||
id: stream.Index
|
||||
};
|
||||
return stream.Index === currentIndex && (opt.selected = !0), opt
|
||||
}),
|
||||
positionTo = this;
|
||||
require(["actionsheet"], function(actionsheet) {
|
||||
actionsheet.show({
|
||||
items: menuItems,
|
||||
title: globalize.translate("Audio"),
|
||||
positionTo: positionTo
|
||||
}).then(function(id) {
|
||||
var index = parseInt(id);
|
||||
index !== currentIndex && playbackManager.setAudioStreamIndex(index, player)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function showSubtitleTrackSelection() {
|
||||
var player = currentPlayer,
|
||||
streams = playbackManager.subtitleTracks(player),
|
||||
currentIndex = playbackManager.getSubtitleStreamIndex(player);
|
||||
null == currentIndex && (currentIndex = -1), streams.unshift({
|
||||
Index: -1,
|
||||
DisplayTitle: globalize.translate("Off")
|
||||
});
|
||||
var menuItems = streams.map(function(stream) {
|
||||
var opt = {
|
||||
name: stream.DisplayTitle,
|
||||
id: stream.Index
|
||||
};
|
||||
return stream.Index === currentIndex && (opt.selected = !0), opt
|
||||
}),
|
||||
positionTo = this;
|
||||
require(["actionsheet"], function(actionsheet) {
|
||||
actionsheet.show({
|
||||
title: globalize.translate("Subtitles"),
|
||||
items: menuItems,
|
||||
positionTo: positionTo
|
||||
}).then(function(id) {
|
||||
var index = parseInt(id);
|
||||
index !== currentIndex && playbackManager.setSubtitleStreamIndex(index, player)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function onWindowKeyDown(e) {
|
||||
if (!currentVisibleMenu && (32 === e.keyCode || 13 === e.keyCode)) return playbackManager.playPause(currentPlayer), void showOsd();
|
||||
switch (e.key) {
|
||||
case "f":
|
||||
e.ctrlKey || playbackManager.toggleFullscreen(currentPlayer);
|
||||
break;
|
||||
case "m":
|
||||
playbackManager.toggleMute(currentPlayer);
|
||||
break;
|
||||
case "ArrowLeft":
|
||||
case "Left":
|
||||
case "NavigationLeft":
|
||||
case "GamepadDPadLeft":
|
||||
case "GamepadLeftThumbstickLeft":
|
||||
e.shiftKey && playbackManager.rewind(currentPlayer);
|
||||
break;
|
||||
case "ArrowRight":
|
||||
case "Right":
|
||||
case "NavigationRight":
|
||||
case "GamepadDPadRight":
|
||||
case "GamepadLeftThumbstickRight":
|
||||
e.shiftKey && playbackManager.fastForward(currentPlayer)
|
||||
}
|
||||
}
|
||||
|
||||
function getImgUrl(item, chapter, index, maxWidth, apiClient) {
|
||||
return chapter.ImageTag ? apiClient.getScaledImageUrl(item.Id, {
|
||||
maxWidth: maxWidth,
|
||||
tag: chapter.ImageTag,
|
||||
type: "Chapter",
|
||||
index: index
|
||||
}) : null
|
||||
}
|
||||
|
||||
function getChapterBubbleHtml(apiClient, item, chapters, positionTicks) {
|
||||
for (var chapter, index = -1, i = 0, length = chapters.length; i < length; i++) {
|
||||
var currentChapter = chapters[i];
|
||||
positionTicks >= currentChapter.StartPositionTicks && (chapter = currentChapter, index = i)
|
||||
}
|
||||
if (!chapter) return null;
|
||||
var src = getImgUrl(item, chapter, index, 400, apiClient);
|
||||
if (src) {
|
||||
var html = '<div class="chapterThumbContainer">';
|
||||
return html += '<img class="chapterThumb" src="' + src + '" />', html += '<div class="chapterThumbTextContainer">', html += '<div class="chapterThumbText chapterThumbText-dim">', html += chapter.Name, html += "</div>", html += '<h2 class="chapterThumbText">', html += datetime.getDisplayRunningTime(positionTicks), html += "</h2>", html += "</div>", html += "</div>"
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function onViewHideStopPlayback() {
|
||||
if (playbackManager.isPlayingVideo()) {
|
||||
var player = currentPlayer;
|
||||
view.removeEventListener("viewbeforehide", onViewHideStopPlayback), releaseCurrentPlayer(), playbackManager.stop(player)
|
||||
}
|
||||
}
|
||||
|
||||
function enableStopOnBack(enabled) {
|
||||
view.removeEventListener("viewbeforehide", onViewHideStopPlayback), enabled && playbackManager.isPlayingVideo(currentPlayer) && view.addEventListener("viewbeforehide", onViewHideStopPlayback)
|
||||
}
|
||||
var currentPlayer, comingUpNextDisplayed, currentUpNextDialog, isEnabled, currentItem, recordingButtonManager, enableProgressByTimeOfDay, supportsBrightnessChange, currentVisibleMenu, statsOverlay, osdHideTimeout, lastPointerMoveData, self = this,
|
||||
currentPlayerSupportedCommands = [],
|
||||
currentRuntimeTicks = 0,
|
||||
lastUpdateTime = 0,
|
||||
programStartDateMs = 0,
|
||||
programEndDateMs = 0,
|
||||
playbackStartTimeTicks = 0,
|
||||
nowPlayingVolumeSlider = view.querySelector(".osdVolumeSlider"),
|
||||
nowPlayingVolumeSliderContainer = view.querySelector(".osdVolumeSliderContainer"),
|
||||
nowPlayingPositionSlider = view.querySelector(".osdPositionSlider"),
|
||||
nowPlayingPositionText = view.querySelector(".osdPositionText"),
|
||||
nowPlayingDurationText = view.querySelector(".osdDurationText"),
|
||||
startTimeText = view.querySelector(".startTimeText"),
|
||||
endTimeText = view.querySelector(".endTimeText"),
|
||||
endsAtText = view.querySelector(".endsAtText"),
|
||||
btnRewind = view.querySelector(".btnRewind"),
|
||||
btnFastForward = view.querySelector(".btnFastForward"),
|
||||
transitionEndEventName = dom.whichTransitionEvent(),
|
||||
headerElement = document.querySelector(".skinHeader"),
|
||||
osdBottomElement = document.querySelector(".videoOsdBottom-maincontrols");
|
||||
view.addEventListener("viewbeforeshow", function(e) {
|
||||
headerElement.classList.add("osdHeader"), Emby.Page.setTransparency("full")
|
||||
}), view.addEventListener("viewshow", function(e) {
|
||||
events.on(playbackManager, "playerchange", onPlayerChange), bindToPlayer(playbackManager.getCurrentPlayer()), dom.addEventListener(document, window.PointerEvent ? "pointermove" : "mousemove", onPointerMove, {
|
||||
passive: !0
|
||||
}), document.body.classList.add("autoScrollY"), showOsd(), inputManager.on(window, onInputCommand), dom.addEventListener(window, "keydown", onWindowKeyDown, {
|
||||
passive: !0
|
||||
})
|
||||
}), view.addEventListener("viewbeforehide", function() {
|
||||
statsOverlay && statsOverlay.enabled(!1), dom.removeEventListener(window, "keydown", onWindowKeyDown, {
|
||||
passive: !0
|
||||
}), stopOsdHideTimer(), headerElement.classList.remove("osdHeader"), headerElement.classList.remove("osdHeader-hidden"), dom.removeEventListener(document, window.PointerEvent ? "pointermove" : "mousemove", onPointerMove, {
|
||||
passive: !0
|
||||
}), document.body.classList.remove("autoScrollY"), inputManager.off(window, onInputCommand), events.off(playbackManager, "playerchange", onPlayerChange), releaseCurrentPlayer()
|
||||
}), view.querySelector(".btnFullscreen").addEventListener("click", function() {
|
||||
playbackManager.toggleFullscreen(currentPlayer)
|
||||
}), view.querySelector(".btnPip").addEventListener("click", function() {
|
||||
playbackManager.togglePictureInPicture(currentPlayer)
|
||||
}), view.querySelector(".btnVideoOsdSettings").addEventListener("click", onSettingsButtonClick), view.addEventListener("viewhide", function() {
|
||||
headerElement.classList.remove("hide")
|
||||
}), view.addEventListener("viewdestroy", function() {
|
||||
self.touchHelper && (self.touchHelper.destroy(), self.touchHelper = null), recordingButtonManager && (recordingButtonManager.destroy(), recordingButtonManager = null), destroyStats()
|
||||
});
|
||||
var lastPointerDown = 0;
|
||||
dom.addEventListener(view, window.PointerEvent ? "pointerdown" : "click", function(e) {
|
||||
if (dom.parentWithClass(e.target, ["videoOsdBottom", "upNextContainer"])) return void showOsd();
|
||||
var pointerType = e.pointerType || (layoutManager.mobile ? "touch" : "mouse"),
|
||||
now = (new Date).getTime();
|
||||
switch (pointerType) {
|
||||
case "touch":
|
||||
now - lastPointerDown > 300 && (lastPointerDown = now, toggleOsd());
|
||||
break;
|
||||
case "mouse":
|
||||
e.button || (playbackManager.playPause(currentPlayer), showOsd());
|
||||
break;
|
||||
default:
|
||||
playbackManager.playPause(currentPlayer), showOsd()
|
||||
}
|
||||
}, {
|
||||
passive: !0
|
||||
}), browser.touch && dom.addEventListener(view, "dblclick", onDoubleClick, {}), view.querySelector(".buttonMute").addEventListener("click", function() {
|
||||
playbackManager.toggleMute(currentPlayer)
|
||||
}), nowPlayingVolumeSlider.addEventListener("change", function() {
|
||||
playbackManager.setVolume(this.value, currentPlayer)
|
||||
}), nowPlayingPositionSlider.addEventListener("change", function() {
|
||||
var player = currentPlayer;
|
||||
if (player) {
|
||||
var newPercent = parseFloat(this.value);
|
||||
if (enableProgressByTimeOfDay) {
|
||||
var seekAirTimeTicks = newPercent / 100 * (programEndDateMs - programStartDateMs) * 1e4;
|
||||
seekAirTimeTicks += 1e4 * programStartDateMs, seekAirTimeTicks -= playbackStartTimeTicks, playbackManager.seek(seekAirTimeTicks, player)
|
||||
} else playbackManager.seekPercent(newPercent, player)
|
||||
}
|
||||
}), nowPlayingPositionSlider.getBubbleHtml = function(value) {
|
||||
if (showOsd(), enableProgressByTimeOfDay) {
|
||||
if (programStartDateMs && programEndDateMs) {
|
||||
var ms = programEndDateMs - programStartDateMs;
|
||||
ms /= 100, ms *= value, ms += programStartDateMs;
|
||||
return '<h1 class="sliderBubbleText">' + getDisplayTimeWithoutAmPm(new Date(parseInt(ms)), !0) + "</h1>"
|
||||
}
|
||||
return "--:--"
|
||||
}
|
||||
if (!currentRuntimeTicks) return "--:--";
|
||||
var ticks = currentRuntimeTicks;
|
||||
ticks /= 100, ticks *= value;
|
||||
var item = currentItem;
|
||||
if (item && item.Chapters && item.Chapters.length && item.Chapters[0].ImageTag) {
|
||||
var html = getChapterBubbleHtml(connectionManager.getApiClient(item.ServerId), item, item.Chapters, ticks);
|
||||
if (html) return html
|
||||
}
|
||||
return '<h1 class="sliderBubbleText">' + datetime.getDisplayRunningTime(ticks) + "</h1>"
|
||||
}, view.querySelector(".btnPreviousTrack").addEventListener("click", function() {
|
||||
playbackManager.previousTrack(currentPlayer)
|
||||
}), view.querySelector(".btnPause").addEventListener("click", function() {
|
||||
playbackManager.playPause(currentPlayer)
|
||||
}), view.querySelector(".btnNextTrack").addEventListener("click", function() {
|
||||
playbackManager.nextTrack(currentPlayer)
|
||||
}), btnRewind.addEventListener("click", function() {
|
||||
playbackManager.rewind(currentPlayer)
|
||||
}), btnFastForward.addEventListener("click", function() {
|
||||
playbackManager.fastForward(currentPlayer)
|
||||
}), view.querySelector(".btnAudio").addEventListener("click", showAudioTrackSelection), view.querySelector(".btnSubtitles").addEventListener("click", showSubtitleTrackSelection), browser.touch && function() {
|
||||
require(["touchHelper"], function(TouchHelper) {
|
||||
self.touchHelper = new TouchHelper(view, {
|
||||
swipeYThreshold: 30,
|
||||
triggerOnMove: !0,
|
||||
preventDefaultOnMove: !0,
|
||||
ignoreTagNames: ["BUTTON", "INPUT", "TEXTAREA"]
|
||||
}), events.on(self.touchHelper, "swipeup", onVerticalSwipe), events.on(self.touchHelper, "swipedown", onVerticalSwipe)
|
||||
})
|
||||
}()
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
define(["dom", "emby-linkbutton"], function(dom) {
|
||||
"use strict";
|
||||
|
||||
function onSubmit(e) {
|
||||
return dom.parentWithClass(this, "page").querySelector(".chkAccept").checked ? Dashboard.navigate("wizardfinish.html") : Dashboard.alert({
|
||||
message: Globalize.translate("MessagePleaseAcceptTermsOfServiceBeforeContinuing"),
|
||||
title: ""
|
||||
}), e.preventDefault(), !1
|
||||
}
|
||||
return function(view, params) {
|
||||
view.querySelector(".wizardAgreementForm").addEventListener("submit", onSubmit), view.addEventListener("viewshow", function() {
|
||||
document.querySelector(".skinHeader").classList.add("noHomeButtonHeader")
|
||||
}), view.addEventListener("viewhide", function() {
|
||||
document.querySelector(".skinHeader").classList.remove("noHomeButtonHeader")
|
||||
})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
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
|
||||
},
|
||||
url: apiClient.getUrl("Startup/User"),
|
||||
dataType: "json"
|
||||
}).then(onUpdateUserComplete, function(response) {
|
||||
response && response.status;
|
||||
})
|
||||
}
|
||||
|
||||
function onSubmit(e) {
|
||||
return submit(this), e.preventDefault(), !1
|
||||
}
|
||||
|
||||
function onViewShow() {
|
||||
loading.show();
|
||||
var page = this,
|
||||
apiClient = getApiClient();
|
||||
apiClient.getJSON(apiClient.getUrl("Startup/User")).then(function(user) {
|
||||
page.querySelector("#txtUsername").value = user.Name || "", 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)
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user