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

First separation commit.

Added LICENSE, README.md, CONTRIBUTORS.md
This commit is contained in:
Erwin de Haan 2019-01-09 12:36:54 +01:00
parent 09513af31b
commit 4678528d00
657 changed files with 422 additions and 0 deletions

View file

@ -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)
})
})
})
}
});

12
src/scripts/apploader.js Normal file
View file

@ -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)
}()
}();

View file

@ -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)
})
});

View file

@ -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()
})
});

View file

@ -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)
})
}
});

168
src/scripts/connectlogin.js Normal file
View file

@ -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)
})
}
});

View file

@ -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">&#xE034;</i></button>', html += '<button is="paper-icon-button-light" class="sessionCardButton btnSessionStop paper-icon-button-light ' + btnCssClass + '"><i class="md-icon">&#xE047;</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">&#xE88E;</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">&#xE0C9;</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) || "&nbsp;", 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 || "&nbsp;"
},
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 = "&#xE037;" : btnSessionPlayPause.querySelector("i").innerHTML = "&#xE034;", row.querySelector(".sessionNowPlayingStreamInfo").innerHTML = DashboardPage.getSessionNowPlayingStreamInfo(session), row.querySelector(".sessionNowPlayingTime").innerHTML = DashboardPage.getSessionNowPlayingTime(session), row.querySelector(".sessionUserName").innerHTML = DashboardPage.getUsersHtml(session) || "&nbsp;", 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()
})
}
});

371
src/scripts/dlnaprofile.js Normal file
View file

@ -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
}
}
});

View file

@ -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)
})
});

View file

@ -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])
})
})
});

View file

@ -0,0 +1,17 @@
define(["loading"], function(loading) {
"use strict";
function reload(context, itemId) {
loading.show(), itemId ? require(["metadataEditor"], function(metadataEditor) {
metadataEditor.embed(context.querySelector(".editPageInnerContent"), itemId, ApiClient.serverInfo().Id)
}) : (context.querySelector(".editPageInnerContent").innerHTML = "", loading.hide())
}
return function(view, params) {
view.addEventListener("viewshow", function() {
reload(this, MetadataEditor.getCurrentItemId())
}), MetadataEditor.setCurrentItemId(null), view.querySelector(".libraryTree").addEventListener("itemclicked", function(event) {
var data = event.detail;
data.id != MetadataEditor.getCurrentItemId() && (MetadataEditor.setCurrentItemId(data.id), reload(view, data.id))
})
}
});

View file

@ -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
}
});

View file

@ -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)
})
})
})
});

155
src/scripts/episodes.js Normal file
View file

@ -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() {}
}
});

View file

@ -0,0 +1,34 @@
define([], function() {
"use strict";
function processForgotPasswordResult(result) {
if ("ContactAdmin" == result.Action) return void Dashboard.alert({
message: Globalize.translate("MessageContactAdminToResetPassword"),
title: Globalize.translate("HeaderForgotPassword")
});
if ("InNetworkRequired" == result.Action) return void Dashboard.alert({
message: Globalize.translate("MessageForgotPasswordInNetworkRequired"),
title: Globalize.translate("HeaderForgotPassword")
});
if ("PinCode" == result.Action) {
var msg = Globalize.translate("MessageForgotPasswordFileCreated");
return msg += "<br/>", msg += "<br/>", msg += result.PinFile, msg += "<br/>", void Dashboard.alert({
message: msg,
title: Globalize.translate("HeaderForgotPassword")
})
}
}
return function(view, params) {
function onSubmit(e) {
return ApiClient.ajax({
type: "POST",
url: ApiClient.getUrl("Users/ForgotPassword"),
dataType: "json",
data: {
EnteredUsername: view.querySelector("#txtName").value
}
}).then(processForgotPasswordResult), e.preventDefault(), !1
}
view.querySelector("form").addEventListener("submit", onSubmit)
}
});

View file

@ -0,0 +1,33 @@
define([], function() {
"use strict";
function processForgotPasswordResult(result) {
if (result.Success) {
var msg = Globalize.translate("MessagePasswordResetForUsers");
return msg += "<br/>", msg += "<br/>", msg += result.UsersReset.join("<br/>"), void Dashboard.alert({
message: msg,
title: Globalize.translate("HeaderPasswordReset"),
callback: function() {
window.location.href = "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)
}
});

View file

@ -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

View file

@ -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">&#xE5C4;</i></button>', html += '<button is="paper-icon-button-light" class="btnNextPage autoSize" ' + (startIndex + limit >= totalRecordCount ? "disabled" : "") + '><i class="md-icon">&#xE5C8;</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">&#xE42A;</i></button>'), options.sortButton && (html += '<button is="paper-icon-button-light" class="btnSort autoSize" title="' + Globalize.translate("ButtonSort") + '"><i class="md-icon">&#xE053;</i></button>'), options.filterButton && (html += '<button is="paper-icon-button-light" class="btnFilter autoSize" title="' + Globalize.translate("ButtonFilter") + '"><i class="md-icon">&#xE152;</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
});

451
src/scripts/librarymenu.js Normal file
View file

@ -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">&#xE7FD;</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">&#xE88A;</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">&#xE2C7;</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">&#xE254;</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">&#xE8B8;</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">&#xE2C7;</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">&#xE8B8;</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">&#xE627;</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">&#xE308;</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">&#xE879;</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: "&#xE912;"
}), links.push({
divider: !0,
name: globalize.translate("TabLiveTV")
}), links.push({
name: globalize.translate("TabLiveTV"),
href: "livetvstatus.html",
pageIds: ["liveTvStatusPage", "liveTvTunerPage"],
icon: "&#xE639;"
}), 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 = "&#xE308;", headerCastButton.classList.add("castButton-active"), context.querySelector(".headerSelectedPlayer").innerHTML = info.deviceName || info.name) : (icon.innerHTML = "&#xE307;", 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" : "&#xE5C4;") + "</i></button>", html += '<button type="button" is="paper-icon-button-light" class="headerButton headerHomeButton hide barsMenuButton headerButtonLeft"><i class="md-icon">&#xE88A;</i></button>', html += '<button type="button" is="paper-icon-button-light" class="headerButton mainDrawerButton barsMenuButton headerButtonLeft hide"><i class="md-icon">&#xE5D2;</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">&#xE307;</i></button>', html += '<button type="button" is="paper-icon-button-light" class="headerButton headerButtonRight headerSearchButton hide"><i class="md-icon">&#xE8B6;</i></button>', html += '<button is="paper-icon-button-light" class="headerButton headerButtonRight headerUserButton hide"><i class="md-icon">&#xE7FD;</i></button>', layoutManager.mobile || (html += '<button is="paper-icon-button-light" class="headerButton headerButtonRight headerSettingsButton hide"><i class="md-icon">&#xE8B8;</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
});

View file

@ -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)
}
}
});

View file

@ -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
}
});

View file

@ -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()
}
}
});

View file

@ -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)
})
});

View file

@ -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())
}
}
});

View file

@ -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)
}
}
});

View file

@ -0,0 +1,43 @@
define(["datetime", "cardBuilder", "imageLoader", "apphost", "loading", "paper-icon-button-light", "emby-button"], function(datetime, cardBuilder, imageLoader, appHost, loading) {
"use strict";
function renderTimers(context, timers) {
var html = "";
appHost.supports("imageanalysis");
html += cardBuilder.getCardsHtml({
items: timers,
shape: "auto",
defaultShape: "portrait",
showTitle: !0,
cardLayout: !1,
preferThumb: "auto",
coverImage: !0,
overlayText: !1,
showSeriesTimerTime: !0,
showSeriesTimerChannel: !0,
centerText: !0,
overlayMoreButton: !0,
lines: 3
});
var elem = context.querySelector("#items");
elem.innerHTML = html, imageLoader.lazyChildren(elem), loading.hide()
}
function reload(context, promise) {
loading.show(), promise.then(function(result) {
renderTimers(context, result.Items)
})
}
var query = {
SortBy: "SortName",
SortOrder: "Ascending"
};
return function(view, params, tabContent) {
var timersPromise, self = this;
self.preRender = function() {
timersPromise = ApiClient.getLiveTvSeriesTimers(query)
}, self.renderTab = function() {
reload(tabContent, timersPromise)
}
}
});

View file

@ -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)
})
})
});

260
src/scripts/livetvstatus.js Normal file
View file

@ -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 || "&nbsp;", 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")
})
})
});

View file

@ -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()
})
})
}
});

97
src/scripts/loginpage.js Normal file
View file

@ -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")
})
}
});

View file

@ -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)
})
}
});

View file

@ -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">&#xE5D3;</i></button>', html += "</div>"
}
html += "<div class='cardText'>", virtualFolder.showNameWithIcon ? html += "&nbsp;" : 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 += "&nbsp;" : html += typeName, html += "</div>", !1 === virtualFolder.showLocations ? (html += "<div class='cardText cardText-secondary'>", html += "&nbsp;", 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")
})
})
});

View file

@ -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)
})
});

View file

@ -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])
})
})
});

View file

@ -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() {}
}
});

141
src/scripts/moviegenres.js Normal file
View file

@ -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">&#xE5CC;</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)
}
}
});

188
src/scripts/movies.js Normal file
View file

@ -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
}
}
});

View file

@ -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()
})
})
}
});

View file

@ -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() {}
}
});

182
src/scripts/musicalbums.js Normal file
View file

@ -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() {}
}
});

136
src/scripts/musicartists.js Normal file
View file

@ -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() {}
}
});

View file

@ -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)
}
}
});

View file

@ -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)
}
}
});

View file

@ -0,0 +1,279 @@
define(["browser", "layoutManager", "userSettings", "inputManager", "loading", "cardBuilder", "dom", "apphost", "imageLoader", "libraryMenu", "playbackManager", "mainTabsManager", "scrollStyles", "emby-itemscontainer", "emby-tabs", "emby-button", "flexStyles"], function(browser, layoutManager, userSettings, inputManager, loading, cardBuilder, dom, appHost, imageLoader, libraryMenu, playbackManager, mainTabsManager) {
"use strict";
function itemsPerRow() {
var screenWidth = dom.getWindowSize().innerWidth;
return screenWidth >= 1920 ? 9 : screenWidth >= 1200 ? 12 : screenWidth >= 1e3 ? 10 : 8
}
function enableScrollX() {
return !layoutManager.desktop
}
function getSquareShape() {
return enableScrollX() ? "overflowSquare" : "square"
}
function loadLatest(page, parentId) {
loading.show();
var userId = ApiClient.getCurrentUserId(),
options = {
IncludeItemTypes: "Audio",
Limit: enableScrollX() ? 3 * itemsPerRow() : 2 * itemsPerRow(),
Fields: "PrimaryImageAspectRatio,BasicSyncInfo",
ParentId: parentId,
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
EnableTotalRecordCount: !1
};
ApiClient.getJSON(ApiClient.getUrl("Users/" + userId + "/Items/Latest", options)).then(function(items) {
var elem = page.querySelector("#recentlyAddedSongs"),
supportsImageAnalysis = appHost.supports("imageanalysis");
supportsImageAnalysis = !1, elem.innerHTML = cardBuilder.getCardsHtml({
items: items,
showUnplayedIndicator: !1,
showLatestItemsPopup: !1,
shape: getSquareShape(),
showTitle: !0,
showParentTitle: !0,
lazy: !0,
centerText: !supportsImageAnalysis,
overlayPlayButton: !supportsImageAnalysis,
allowBottomPadding: !enableScrollX(),
cardLayout: supportsImageAnalysis,
vibrant: supportsImageAnalysis,
coverImage: !0
}), imageLoader.lazyChildren(elem), loading.hide()
})
}
function loadRecentlyPlayed(page, parentId) {
var options = {
SortBy: "DatePlayed",
SortOrder: "Descending",
IncludeItemTypes: "Audio",
Limit: itemsPerRow(),
Recursive: !0,
Fields: "PrimaryImageAspectRatio,AudioInfo",
Filters: "IsPlayed",
ParentId: parentId,
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
EnableTotalRecordCount: !1
};
ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) {
var elem = page.querySelector("#recentlyPlayed");
result.Items.length ? elem.classList.remove("hide") : elem.classList.add("hide");
var itemsContainer = elem.querySelector(".itemsContainer"),
supportsImageAnalysis = appHost.supports("imageanalysis");
supportsImageAnalysis = !1, itemsContainer.innerHTML = cardBuilder.getCardsHtml({
items: result.Items,
showUnplayedIndicator: !1,
shape: getSquareShape(),
showTitle: !0,
showParentTitle: !0,
action: "instantmix",
lazy: !0,
centerText: !supportsImageAnalysis,
overlayMoreButton: !supportsImageAnalysis,
allowBottomPadding: !enableScrollX(),
cardLayout: supportsImageAnalysis,
vibrant: supportsImageAnalysis,
coverImage: !0
}), imageLoader.lazyChildren(itemsContainer)
})
}
function loadFrequentlyPlayed(page, parentId) {
var options = {
SortBy: "PlayCount",
SortOrder: "Descending",
IncludeItemTypes: "Audio",
Limit: itemsPerRow(),
Recursive: !0,
Fields: "PrimaryImageAspectRatio,AudioInfo",
Filters: "IsPlayed",
ParentId: parentId,
ImageTypeLimit: 1,
EnableImageTypes: "Primary,Backdrop,Banner,Thumb",
EnableTotalRecordCount: !1
};
ApiClient.getItems(ApiClient.getCurrentUserId(), options).then(function(result) {
var elem = page.querySelector("#topPlayed");
result.Items.length ? elem.classList.remove("hide") : elem.classList.add("hide");
var itemsContainer = elem.querySelector(".itemsContainer"),
supportsImageAnalysis = appHost.supports("imageanalysis");
supportsImageAnalysis = !1, itemsContainer.innerHTML = cardBuilder.getCardsHtml({
items: result.Items,
showUnplayedIndicator: !1,
shape: getSquareShape(),
showTitle: !0,
showParentTitle: !0,
action: "instantmix",
lazy: !0,
centerText: !supportsImageAnalysis,
overlayMoreButton: !supportsImageAnalysis,
allowBottomPadding: !enableScrollX(),
cardLayout: supportsImageAnalysis,
vibrant: supportsImageAnalysis,
coverImage: !0
}), imageLoader.lazyChildren(itemsContainer)
})
}
function loadSuggestionsTab(page, tabContent, parentId) {
console.log("loadSuggestionsTab"), loadLatest(tabContent, parentId), loadRecentlyPlayed(tabContent, parentId), loadFrequentlyPlayed(tabContent, parentId), require(["components/favoriteitems"], function(favoriteItems) {
favoriteItems.render(tabContent, ApiClient.getCurrentUserId(), parentId, ["favoriteArtists", "favoriteAlbums", "favoriteSongs"])
})
}
function getTabs() {
return [{
name: Globalize.translate("TabSuggestions")
}, {
name: Globalize.translate("TabAlbums")
}, {
name: Globalize.translate("TabAlbumArtists")
}, {
name: Globalize.translate("TabArtists")
}, {
name: Globalize.translate("TabPlaylists")
}, {
name: Globalize.translate("TabSongs")
}, {
name: Globalize.translate("TabGenres")
}, {
name: Globalize.translate("ButtonSearch"),
cssClass: "searchTabButton"
}]
}
function getDefaultTabIndex(folderId) {
switch (userSettings.get("landing-" + folderId)) {
case "albums":
return 1;
case "albumartists":
return 2;
case "artists":
return 3;
case "playlists":
return 4;
case "songs":
return 5;
case "genres":
return 6;
default:
return 0
}
}
return function(view, params) {
function reload() {
loading.show();
var tabContent = view.querySelector(".pageTabContent[data-index='0']");
loadSuggestionsTab(view, tabContent, params.topParentId)
}
function enableScrollX() {
return browser.mobile
}
function setScrollClasses(elem, scrollX) {
scrollX ? (elem.classList.add("hiddenScrollX"), layoutManager.tv && elem.classList.add("smoothScrollX"), elem.classList.add("scrollX"), elem.classList.remove("vertical-wrap")) : (elem.classList.remove("hiddenScrollX"), elem.classList.remove("smoothScrollX"), elem.classList.remove("scrollX"), elem.classList.add("vertical-wrap"))
}
function onBeforeTabChange(e) {
preLoadTab(view, parseInt(e.detail.selectedTabIndex))
}
function onTabChange(e) {
loadTab(view, parseInt(e.detail.selectedTabIndex))
}
function getTabContainers() {
return view.querySelectorAll(".pageTabContent")
}
function initTabs() {
mainTabsManager.setTabs(view, currentTabIndex, getTabs, getTabContainers, onBeforeTabChange, onTabChange)
}
function getTabController(page, index, callback) {
var depends = [];
switch (index) {
case 0:
break;
case 1:
depends.push("scripts/musicalbums");
break;
case 2:
case 3:
depends.push("scripts/musicartists");
break;
case 4:
depends.push("scripts/musicplaylists");
break;
case 5:
depends.push("scripts/songs");
break;
case 6:
depends.push("scripts/musicgenres");
break;
case 7:
depends.push("scripts/searchtab")
}
require(depends, function(controllerFactory) {
var tabContent;
0 == index && (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), self.tabContent = tabContent);
var controller = tabControllers[index];
controller || (tabContent = view.querySelector(".pageTabContent[data-index='" + index + "']"), controller = 0 === index ? self : 7 === index ? new controllerFactory(view, tabContent, {
collectionType: "music",
parentId: params.topParentId
}) : new controllerFactory(view, params, tabContent), 2 == index ? controller.mode = "albumartists" : 3 == index && (controller.mode = "artists"), tabControllers[index] = controller, controller.initTab && controller.initTab()), callback(controller)
})
}
function preLoadTab(page, index) {
getTabController(page, index, function(controller) {
-1 == renderedTabs.indexOf(index) && controller.preRender && controller.preRender()
})
}
function loadTab(page, index) {
currentTabIndex = index, getTabController(page, index, function(controller) {
initialTabIndex = null, -1 == renderedTabs.indexOf(index) && (renderedTabs.push(index), controller.renderTab())
})
}
function onInputCommand(e) {
switch (e.detail.command) {
case "search":
e.preventDefault(), Dashboard.navigate("search.html?collectionType=music&parentId=" + params.topParentId)
}
}
var isViewRestored, self = this,
currentTabIndex = parseInt(params.tab || getDefaultTabIndex(params.topParentId)),
initialTabIndex = currentTabIndex;
self.initTab = function() {
for (var tabContent = view.querySelector(".pageTabContent[data-index='0']"), containers = tabContent.querySelectorAll(".itemsContainer"), i = 0, length = containers.length; i < length; i++) setScrollClasses(containers[i], enableScrollX())
}, self.renderTab = function() {
reload()
};
var tabControllers = [],
renderedTabs = [];
view.addEventListener("viewshow", function(e) {
if (isViewRestored = e.detail.isRestored, initTabs(), !view.getAttribute("data-title")) {
var parentId = params.topParentId;
parentId ? ApiClient.getItem(ApiClient.getCurrentUserId(), parentId).then(function(item) {
view.setAttribute("data-title", item.Name), libraryMenu.setTitle(item.Name)
}) : (view.setAttribute("data-title", Globalize.translate("TabMusic")), libraryMenu.setTitle(Globalize.translate("TabMusic")))
}
inputManager.on(window, onInputCommand)
}), view.addEventListener("viewbeforehide", function(e) {
inputManager.off(window, onInputCommand)
}), view.addEventListener("viewdestroy", function(e) {
tabControllers.forEach(function(t) {
t.destroy && t.destroy()
})
})
}
});

View file

@ -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")
})
}
});

View file

@ -0,0 +1,28 @@
define(["displaySettings", "userSettingsBuilder", "userSettings"], function(DisplaySettings, userSettingsBuilder, currentUserSettings) {
"use strict";
return function(view, params) {
function onBeforeUnload(e) {
hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?")
}
var settingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(),
userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder;
view.addEventListener("viewshow", function() {
window.addEventListener("beforeunload", onBeforeUnload), settingsInstance ? settingsInstance.loadData() : settingsInstance = new DisplaySettings({
serverId: ApiClient.serverId(),
userId: userId,
element: view.querySelector(".settingsContainer"),
userSettings: userSettings,
enableSaveButton: !1,
enableSaveConfirmation: !1
})
}), view.addEventListener("change", function() {
hasChanges = !0
}), view.addEventListener("viewbeforehide", function() {
window.removeEventListener("beforeunload", onBeforeUnload), hasChanges = !1, settingsInstance && settingsInstance.submit()
}), view.addEventListener("viewdestroy", function() {
settingsInstance && (settingsInstance.destroy(), settingsInstance = null)
}), view.addEventListener("viewdestroy", function() {
settingsInstance && (settingsInstance.destroy(), settingsInstance = null)
})
}
});

View file

@ -0,0 +1,26 @@
define(["homescreenSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function(HomescreenSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) {
"use strict";
return function(view, params) {
function onBeforeUnload(e) {
hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?")
}
var homescreenSettingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(),
userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder;
view.addEventListener("viewshow", function() {
window.addEventListener("beforeunload", onBeforeUnload), homescreenSettingsInstance ? homescreenSettingsInstance.loadData() : homescreenSettingsInstance = new HomescreenSettings({
serverId: ApiClient.serverId(),
userId: userId,
element: view.querySelector(".homeScreenSettingsContainer"),
userSettings: userSettings,
enableSaveButton: !1,
enableSaveConfirmation: !1
})
}), view.addEventListener("change", function() {
hasChanges = !0
}), view.addEventListener("viewbeforehide", function() {
hasChanges = !1, homescreenSettingsInstance && homescreenSettingsInstance.submit()
}), view.addEventListener("viewdestroy", function() {
homescreenSettingsInstance && (homescreenSettingsInstance.destroy(), homescreenSettingsInstance = null)
})
}
});

View file

@ -0,0 +1,26 @@
define(["playbackSettings", "userSettingsBuilder", "dom", "globalize", "loading", "userSettings", "listViewStyle"], function(PlaybackSettings, userSettingsBuilder, dom, globalize, loading, currentUserSettings) {
"use strict";
return function(view, params) {
function onBeforeUnload(e) {
hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?")
}
var settingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(),
userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder;
view.addEventListener("viewshow", function() {
window.addEventListener("beforeunload", onBeforeUnload), settingsInstance ? settingsInstance.loadData() : settingsInstance = new PlaybackSettings({
serverId: ApiClient.serverId(),
userId: userId,
element: view.querySelector(".settingsContainer"),
userSettings: userSettings,
enableSaveButton: !1,
enableSaveConfirmation: !1
})
}), view.addEventListener("change", function() {
hasChanges = !0
}), view.addEventListener("viewbeforehide", function() {
hasChanges = !1, settingsInstance && settingsInstance.submit()
}), view.addEventListener("viewdestroy", function() {
settingsInstance && (settingsInstance.destroy(), settingsInstance = null)
})
}
});

View file

@ -0,0 +1,26 @@
define(["subtitleSettings", "userSettingsBuilder", "userSettings"], function(SubtitleSettings, userSettingsBuilder, currentUserSettings) {
"use strict";
return function(view, params) {
function onBeforeUnload(e) {
hasChanges && (e.returnValue = "You currently have unsaved changes. Are you sure you wish to leave?")
}
var subtitleSettingsInstance, hasChanges, userId = params.userId || ApiClient.getCurrentUserId(),
userSettings = userId === ApiClient.getCurrentUserId() ? currentUserSettings : new userSettingsBuilder;
view.addEventListener("viewshow", function() {
window.addEventListener("beforeunload", onBeforeUnload), subtitleSettingsInstance ? subtitleSettingsInstance.loadData() : subtitleSettingsInstance = new SubtitleSettings({
serverId: ApiClient.serverId(),
userId: userId,
element: view.querySelector(".settingsContainer"),
userSettings: userSettings,
enableSaveButton: !1,
enableSaveConfirmation: !1
})
}), view.addEventListener("change", function() {
hasChanges = !0
}), view.addEventListener("viewbeforehide", function() {
hasChanges = !1, subtitleSettingsInstance && subtitleSettingsInstance.submit()
}), view.addEventListener("viewdestroy", function() {
subtitleSettingsInstance && (subtitleSettingsInstance.destroy(), subtitleSettingsInstance = null)
})
}
});

95
src/scripts/myprofile.js Normal file
View file

@ -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)
})
}
});

18
src/scripts/mysync.js Normal file
View file

@ -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()
})
}
});

View file

@ -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)
})
}
});

View file

@ -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)
})
});

View file

@ -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)
})
}
});

View file

@ -0,0 +1,11 @@
define(["components/remotecontrol", "libraryMenu", "emby-button"], function(remotecontrolFactory, libraryMenu) {
"use strict";
return function(view, params) {
var remoteControl = new remotecontrolFactory;
remoteControl.init(view, view.querySelector(".remoteControlContent")), view.addEventListener("viewshow", function(e) {
libraryMenu.setTransparentMenu(!0), remoteControl && remoteControl.onShow()
}), view.addEventListener("viewbeforehide", function(e) {
libraryMenu.setTransparentMenu(!1), remoteControl && remoteControl.destroy()
})
}
});

View file

@ -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)
})
})
});

View file

@ -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()
}
}
});

126
src/scripts/playlists.js Normal file
View file

@ -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()
}
});

View file

@ -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">&#xE2C7;</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) : "&nbsp;", 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)
})
}
});

120
src/scripts/pluginspage.js Normal file
View file

@ -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">&#xE2C7;</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
}
});

View file

@ -0,0 +1,111 @@
define(["jQuery", "loading", "datetime", "dom", "globalize", "emby-input", "emby-button", "emby-select"], function($, loading, datetime, dom, globalize) {
"use strict";
function fillTimeOfDay(select) {
for (var options = [], i = 0; i < 864e5; i += 9e5) options.push({
name: ScheduledTaskPage.getDisplayTime(1e4 * i),
value: 1e4 * i
});
select.innerHTML = options.map(function(o) {
return '<option value="' + o.value + '">' + o.name + "</option>"
}).join("")
}
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
return this.length = from < 0 ? this.length + from : from, this.push.apply(this, rest)
};
var ScheduledTaskPage = {
refreshScheduledTask: function(view) {
loading.show();
var id = getParameterByName("id");
ApiClient.getScheduledTask(id).then(function(task) {
ScheduledTaskPage.loadScheduledTask(view, task)
})
},
loadScheduledTask: function(view, task) {
$(".taskName", view).html(task.Name), $("#pTaskDescription", view).html(task.Description), require(["listViewStyle"], function() {
ScheduledTaskPage.loadTaskTriggers(view, task)
}), loading.hide()
},
loadTaskTriggers: function(context, task) {
var html = "";
html += '<div class="paperList">';
for (var i = 0, length = task.Triggers.length; i < length; i++) {
var trigger = task.Triggers[i];
if (html += '<div class="listItem listItem-border">', html += '<i class="md-icon listItemIcon">schedule</i>', trigger.MaxRuntimeTicks ? html += '<div class="listItemBody two-line">' : html += '<div class="listItemBody">', html += "<div class='listItemBodyText'>" + ScheduledTaskPage.getTriggerFriendlyName(trigger) + "</div>", trigger.MaxRuntimeTicks) {
html += '<div class="listItemBodyText secondary">';
var hours = trigger.MaxRuntimeTicks / 36e9;
html += 1 == hours ? globalize.translate("ValueTimeLimitSingleHour") : globalize.translate("ValueTimeLimitMultiHour", hours), html += "</div>"
}
html += "</div>", html += '<button class="btnDeleteTrigger" data-index="' + i + '" type="button" is="paper-icon-button-light" title="' + globalize.translate("ButtonDelete") + '"><i class="md-icon">delete</i></button>', html += "</div>"
}
html += "</div>", context.querySelector(".taskTriggers").innerHTML = html
},
getTriggerFriendlyName: function(trigger) {
if ("DailyTrigger" == trigger.Type) return "Daily at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks);
if ("WeeklyTrigger" == trigger.Type) return trigger.DayOfWeek + "s at " + ScheduledTaskPage.getDisplayTime(trigger.TimeOfDayTicks);
if ("SystemEventTrigger" == trigger.Type && "WakeFromSleep" == trigger.SystemEvent) return "On wake from sleep";
if ("IntervalTrigger" == trigger.Type) {
var hours = trigger.IntervalTicks / 36e9;
return .25 == hours ? "Every 15 minutes" : .5 == hours ? "Every 30 minutes" : .75 == hours ? "Every 45 minutes" : 1 == hours ? "Every hour" : "Every " + hours + " hours"
}
return "StartupTrigger" == trigger.Type ? "On application startup" : trigger.Type
},
getDisplayTime: function(ticks) {
var ms = ticks / 1e4,
now = new Date;
return now.setHours(0, 0, 0, 0), now.setTime(now.getTime() + ms), datetime.getDisplayTime(now)
},
showAddTriggerPopup: function(view) {
$("#selectTriggerType", view).val("DailyTrigger"), view.querySelector("#selectTriggerType").dispatchEvent(new CustomEvent("change", {})), $("#popupAddTrigger", view).removeClass("hide")
},
confirmDeleteTrigger: function(view, index) {
require(["confirm"], function(confirm) {
confirm(globalize.translate("MessageDeleteTaskTrigger"), globalize.translate("HeaderDeleteTaskTrigger")).then(function() {
ScheduledTaskPage.deleteTrigger(view, index)
})
})
},
deleteTrigger: function(view, index) {
loading.show();
var id = getParameterByName("id");
ApiClient.getScheduledTask(id).then(function(task) {
task.Triggers.remove(index), ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function() {
ScheduledTaskPage.refreshScheduledTask(view)
})
})
},
refreshTriggerFields: function(page, triggerType) {
"DailyTrigger" == triggerType ? ($("#fldTimeOfDay", page).show(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).attr("required", "required")) : "WeeklyTrigger" == triggerType ? ($("#fldTimeOfDay", page).show(), $("#fldDayOfWeek", page).show(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).attr("required", "required")) : "SystemEventTrigger" == triggerType ? ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).show(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).removeAttr("required")) : "IntervalTrigger" == triggerType ? ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).show(), $("#selectTimeOfDay", page).removeAttr("required")) : "StartupTrigger" == triggerType && ($("#fldTimeOfDay", page).hide(), $("#fldDayOfWeek", page).hide(), $("#fldSelectSystemEvent", page).hide(), $("#fldSelectInterval", page).hide(), $("#selectTimeOfDay", page).removeAttr("required"))
},
getTriggerToAdd: function(page) {
var trigger = {
Type: $("#selectTriggerType", page).val()
};
"DailyTrigger" == trigger.Type ? trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val() : "WeeklyTrigger" == trigger.Type ? (trigger.DayOfWeek = $("#selectDayOfWeek", page).val(), trigger.TimeOfDayTicks = $("#selectTimeOfDay", page).val()) : "SystemEventTrigger" == trigger.Type ? trigger.SystemEvent = $("#selectSystemEvent", page).val() : "IntervalTrigger" == trigger.Type && (trigger.IntervalTicks = $("#selectInterval", page).val());
var timeLimit = $("#txtTimeLimit", page).val() || "0";
return timeLimit = 36e5 * parseFloat(timeLimit), trigger.MaxRuntimeMs = timeLimit || null, trigger
}
};
return function(view, params) {
function onSubmit(e) {
loading.show();
var id = getParameterByName("id");
ApiClient.getScheduledTask(id).then(function(task) {
task.Triggers.push(ScheduledTaskPage.getTriggerToAdd(view)), ApiClient.updateScheduledTaskTriggers(task.Id, task.Triggers).then(function() {
$("#popupAddTrigger").addClass("hide"), ScheduledTaskPage.refreshScheduledTask(view)
})
}), e.preventDefault()
}
view.querySelector(".addTriggerForm").addEventListener("submit", onSubmit), fillTimeOfDay(view.querySelector("#selectTimeOfDay")), $(view.querySelector("#popupAddTrigger").parentNode).trigger("create"), view.querySelector(".selectTriggerType").addEventListener("change", function() {
ScheduledTaskPage.refreshTriggerFields(view, this.value)
}), view.querySelector(".btnAddTrigger").addEventListener("click", function() {
ScheduledTaskPage.showAddTriggerPopup(view)
}), view.addEventListener("click", function(e) {
var btnDeleteTrigger = dom.parentWithClass(e.target, "btnDeleteTrigger");
btnDeleteTrigger && ScheduledTaskPage.confirmDeleteTrigger(view, parseInt(btnDeleteTrigger.getAttribute("data-index")))
}), view.addEventListener("viewshow", function() {
ScheduledTaskPage.refreshScheduledTask(view)
})
}
});

View file

@ -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)
})
}
});

21
src/scripts/searchpage.js Normal file
View file

@ -0,0 +1,21 @@
define(["focusManager", "searchFields", "searchResults", "events"], function(focusManager, SearchFields, SearchResults, events) {
"use strict";
return function(view, params) {
function onSearch(e, value) {
self.searchResults.search(value)
}
var self = this;
view.addEventListener("viewshow", function() {
self.searchFields || (self.searchFields = new SearchFields({
element: view.querySelector(".searchFields")
}), self.searchResults = new SearchResults({
element: view.querySelector(".searchResults"),
serverId: params.serverId || ApiClient.serverId(),
parentId: params.parentId,
collectionType: params.collectionType
}), events.on(self.searchFields, "search", onSearch))
}), view.addEventListener("viewdestroy", function() {
self.searchFields && (self.searchFields.destroy(), self.searchFields = null), self.searchResults && (self.searchResults.destroy(), self.searchResults = null)
})
}
});

30
src/scripts/searchtab.js Normal file
View file

@ -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
});

244
src/scripts/selectserver.js Normal file
View file

@ -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: "&#xE307;",
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">&#xE1BA;</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)
})
}
});

View file

@ -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
src/scripts/site.js Normal file

File diff suppressed because one or more lines are too long

127
src/scripts/songs.js Normal file
View file

@ -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() {}
}
});

View file

@ -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)
})
})
});

View file

@ -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()
})
}
});

View file

@ -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)
})
})
});

48
src/scripts/taskbutton.js Normal file
View file

@ -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))
}
});

View file

@ -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
})
});

141
src/scripts/tvgenres.js Normal file
View file

@ -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">&#xE5CC;</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)
}
}
});

54
src/scripts/tvlatest.js Normal file
View file

@ -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)
}
});

View file

@ -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()
})
})
}
});

186
src/scripts/tvshows.js Normal file
View file

@ -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() {}
}
});

52
src/scripts/tvstudios.js Normal file
View file

@ -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)
}
}
});

91
src/scripts/tvupcoming.js Normal file
View file

@ -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)
}
}
});

85
src/scripts/useredit.js Normal file
View file

@ -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)
})
});

View file

@ -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)
})
})
});

76
src/scripts/usernew.js Normal file
View file

@ -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)
})
});

View file

@ -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])
})
})
});

View file

@ -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)
})
});

View file

@ -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)
})
}
});

View file

@ -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 : "&nbsp;";
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">&#xE7FD;</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);
});
});

724
src/scripts/videoosd.js Normal file
View file

@ -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 = "&#xE5D1;") : (view.querySelector(".btnFullscreen").setAttribute("title", globalize.translate("Fullscreen")), view.querySelector(".btnFullscreen i").innerHTML = "&#xE5D0;")
}
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 ? "&#xE037;" : "&#xE034;"
}
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 = "&nbsp;&nbsp;-&nbsp;&nbsp;" + 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 = "&#xE04F;") : (view.querySelector(".buttonMute").setAttribute("title", globalize.translate("Mute")), view.querySelector(".buttonMute i").innerHTML = "&#xE050;"), 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 = "&nbsp;/&nbsp;" + 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)
})
}()
}
});

View file

@ -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")
})
}
});

View file

@ -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)
}
});