mirror of
https://github.com/imgfloat/server.git
synced 2026-02-05 11:49:25 +00:00
231 lines
7.4 KiB
JavaScript
231 lines
7.4 KiB
JavaScript
function buildIdentity(admin) {
|
|
const identity = document.createElement("div");
|
|
identity.className = "identity-row";
|
|
|
|
const avatar = document.createElement(admin.avatarUrl ? "img" : "div");
|
|
avatar.className = "avatar";
|
|
if (admin.avatarUrl) {
|
|
avatar.src = admin.avatarUrl;
|
|
avatar.alt = `${admin.displayName || admin.login} avatar`;
|
|
} else {
|
|
avatar.classList.add("avatar-fallback");
|
|
avatar.textContent = (admin.displayName || admin.login || "?").charAt(0).toUpperCase();
|
|
}
|
|
|
|
const details = document.createElement("div");
|
|
details.className = "identity-text";
|
|
const title = document.createElement("p");
|
|
title.className = "list-title";
|
|
title.textContent = admin.displayName || admin.login;
|
|
const subtitle = document.createElement("p");
|
|
subtitle.className = "muted";
|
|
subtitle.textContent = `@${admin.login}`;
|
|
|
|
details.appendChild(title);
|
|
details.appendChild(subtitle);
|
|
identity.appendChild(avatar);
|
|
identity.appendChild(details);
|
|
return identity;
|
|
}
|
|
|
|
function renderAdmins(list) {
|
|
const adminList = document.getElementById("admin-list");
|
|
if (!adminList) return;
|
|
adminList.innerHTML = "";
|
|
if (!list || list.length === 0) {
|
|
const empty = document.createElement("li");
|
|
empty.textContent = "No channel admins yet";
|
|
adminList.appendChild(empty);
|
|
return;
|
|
}
|
|
|
|
list.forEach((admin) => {
|
|
const li = document.createElement("li");
|
|
li.className = "stacked-list-item";
|
|
|
|
li.appendChild(buildIdentity(admin));
|
|
|
|
const actions = document.createElement("div");
|
|
actions.className = "actions";
|
|
|
|
const removeBtn = document.createElement("button");
|
|
removeBtn.type = "button";
|
|
removeBtn.className = "secondary";
|
|
removeBtn.textContent = "Remove";
|
|
removeBtn.addEventListener("click", () => removeAdmin(admin.login));
|
|
|
|
actions.appendChild(removeBtn);
|
|
li.appendChild(actions);
|
|
adminList.appendChild(li);
|
|
});
|
|
}
|
|
|
|
function renderSuggestedAdmins(list) {
|
|
const suggestionList = document.getElementById("admin-suggestions");
|
|
if (!suggestionList) return;
|
|
|
|
suggestionList.innerHTML = "";
|
|
if (!list || list.length === 0) {
|
|
const empty = document.createElement("li");
|
|
empty.className = "stacked-list-item";
|
|
empty.textContent = "No moderator suggestions right now";
|
|
suggestionList.appendChild(empty);
|
|
return;
|
|
}
|
|
|
|
list.forEach((admin) => {
|
|
const li = document.createElement("li");
|
|
li.className = "stacked-list-item";
|
|
|
|
li.appendChild(buildIdentity(admin));
|
|
|
|
const actions = document.createElement("div");
|
|
actions.className = "actions";
|
|
|
|
const addBtn = document.createElement("button");
|
|
addBtn.type = "button";
|
|
addBtn.className = "ghost";
|
|
addBtn.textContent = "Add channel admin";
|
|
addBtn.addEventListener("click", () => addAdmin(admin.login));
|
|
|
|
actions.appendChild(addBtn);
|
|
li.appendChild(actions);
|
|
suggestionList.appendChild(li);
|
|
});
|
|
}
|
|
|
|
function fetchSuggestedAdmins() {
|
|
fetch(`/api/channels/${broadcaster}/admins/suggestions`)
|
|
.then((r) => {
|
|
if (!r.ok) {
|
|
throw new Error("Failed to load admin suggestions");
|
|
}
|
|
return r.json();
|
|
})
|
|
.then(renderSuggestedAdmins)
|
|
.catch(() => {
|
|
renderSuggestedAdmins([]);
|
|
});
|
|
}
|
|
|
|
function fetchAdmins() {
|
|
fetch(`/api/channels/${broadcaster}/admins`)
|
|
.then((r) => {
|
|
if (!r.ok) {
|
|
throw new Error("Failed to load admins");
|
|
}
|
|
return r.json();
|
|
})
|
|
.then(renderAdmins)
|
|
.catch(() => {
|
|
renderAdmins([]);
|
|
showToast("Unable to load admins right now. Please try again.", "error");
|
|
});
|
|
}
|
|
|
|
function removeAdmin(username) {
|
|
if (!username) return;
|
|
fetch(`/api/channels/${encodeURIComponent(broadcaster)}/admins/${encodeURIComponent(username)}`, {
|
|
method: "DELETE",
|
|
})
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw new Error();
|
|
}
|
|
fetchAdmins();
|
|
fetchSuggestedAdmins();
|
|
})
|
|
.catch(() => {
|
|
showToast("Failed to remove admin. Please retry.", "error");
|
|
});
|
|
}
|
|
|
|
function addAdmin(usernameFromAction) {
|
|
const input = document.getElementById("new-admin");
|
|
const username = (usernameFromAction || input?.value || "").trim();
|
|
if (!username) {
|
|
showToast("Enter a Twitch username to add as an admin.", "info");
|
|
return;
|
|
}
|
|
|
|
fetch(`/api/channels/${broadcaster}/admins`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ username }),
|
|
})
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw new Error("Add admin failed");
|
|
}
|
|
if (input) {
|
|
input.value = "";
|
|
}
|
|
showToast(`Added @${username} as an admin.`, "success");
|
|
fetchAdmins();
|
|
fetchSuggestedAdmins();
|
|
})
|
|
.catch(() => showToast("Unable to add admin right now. Please try again.", "error"));
|
|
}
|
|
|
|
function renderCanvasSettings(settings) {
|
|
const widthInput = document.getElementById("canvas-width");
|
|
const heightInput = document.getElementById("canvas-height");
|
|
if (widthInput) widthInput.value = Math.round(settings.width);
|
|
if (heightInput) heightInput.value = Math.round(settings.height);
|
|
}
|
|
|
|
function fetchCanvasSettings() {
|
|
fetch(`/api/channels/${broadcaster}/canvas`)
|
|
.then((r) => {
|
|
if (!r.ok) {
|
|
throw new Error("Failed to load canvas settings");
|
|
}
|
|
return r.json();
|
|
})
|
|
.then(renderCanvasSettings)
|
|
.catch(() => {
|
|
renderCanvasSettings({ width: 1920, height: 1080 });
|
|
showToast("Using default canvas size. Unable to load saved settings.", "warning");
|
|
});
|
|
}
|
|
|
|
function saveCanvasSettings() {
|
|
const widthInput = document.getElementById("canvas-width");
|
|
const heightInput = document.getElementById("canvas-height");
|
|
const status = document.getElementById("canvas-status");
|
|
const width = parseFloat(widthInput?.value) || 0;
|
|
const height = parseFloat(heightInput?.value) || 0;
|
|
if (width <= 0 || height <= 0) {
|
|
showToast("Please enter a valid width and height.", "info");
|
|
return;
|
|
}
|
|
if (status) status.textContent = "Saving...";
|
|
fetch(`/api/channels/${broadcaster}/canvas`, {
|
|
method: "PUT",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ width, height }),
|
|
})
|
|
.then((r) => {
|
|
if (!r.ok) {
|
|
throw new Error("Failed to save canvas");
|
|
}
|
|
return r.json();
|
|
})
|
|
.then((settings) => {
|
|
renderCanvasSettings(settings);
|
|
if (status) status.textContent = "Saved.";
|
|
showToast("Canvas size saved successfully.", "success");
|
|
setTimeout(() => {
|
|
if (status) status.textContent = "";
|
|
}, 2000);
|
|
})
|
|
.catch(() => {
|
|
if (status) status.textContent = "Unable to save right now.";
|
|
showToast("Unable to save canvas size. Please retry.", "error");
|
|
});
|
|
}
|
|
|
|
fetchAdmins();
|
|
fetchSuggestedAdmins();
|
|
fetchCanvasSettings();
|