Update static/js/00-config.js

This commit is contained in:
admin 2026-10-08 00:38:02 +00:00
parent 627a08ced6
commit 0b45bd657c

View File

@ -1,8 +1,6 @@
// static/js/00-config.js
"use strict";
window.Glow = window.Glow || {};
Glow.els = {
chatBox: document.getElementById("chatBox"),
dmBox: document.getElementById("dmBox"),
@ -93,9 +91,9 @@ Glow.els = {
muteCallButton: document.getElementById("muteCallButton"),
hangupCallButton: document.getElementById("hangupCallButton"),
closeCallPanelButton: document.getElementById("closeCallPanelButton"),
remoteAudio: document.getElementById("remoteAudio")
remoteAudio: document.getElementById("remoteAudio"),
emojiAutocomplete: document.getElementById("emojiAutocomplete")
};
Glow.state = {
currentUser: null,
csrfToken: "",
@ -150,6 +148,8 @@ Glow.state = {
originalTitle: document.title,
dialogResolver: null,
lastFocusedElement: null,
emojiSuggestions: [],
emojiActiveInput: null,
presence: {
roomOnlineCount: 0,
channelOnlineCount: 0,
@ -170,18 +170,34 @@ Glow.state = {
invitePollTimer: null
}
};
Glow.MAX_MESSAGE_LENGTH = 1000;
Glow.MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
Glow.DEFAULT_ACCENT_COLOR = "#f7dce8";
Glow.EMOJI_ALIASES = {
smile: "😄",
grin: "😁",
joy: "😂",
heart: "❤️",
thumbs_up: "👍",
fire: "🔥",
tada: "🎉",
clap: "👏",
eyes: "👀",
rocket: "🚀",
wave: "👋",
sparkles: "✨",
thinking: "🤔",
cry: "😢",
check: "✅",
bulb: "💡",
shrug: "¯\\_(ツ)_/¯"
};
Glow.normalizeAccentColor = value => {
if (typeof value !== "string") return null;
const color = value.trim();
if (!/^#[0-9a-fA-F]{6}$/.test(color)) return null;
return color.toLowerCase();
};
Glow.normalizeNameColor = value => {
if (value == null || value === "") return null;
if (typeof value !== "string") return null;
@ -189,7 +205,6 @@ Glow.normalizeNameColor = value => {
if (!/^#[0-9a-fA-F]{6}$/.test(color)) return null;
return color.toLowerCase();
};
Glow.hexToRgb = hex => {
const normalized = Glow.normalizeAccentColor(hex);
if (!normalized) return null;
@ -199,7 +214,6 @@ Glow.hexToRgb = hex => {
b: parseInt(normalized.slice(5, 7), 16)
};
};
Glow.relativeLuminance = hex => {
const rgb = Glow.hexToRgb(hex);
if (!rgb) return 0;
@ -215,11 +229,9 @@ Glow.relativeLuminance = hex => {
0.0722 * channel(rgb.b)
);
};
Glow.accentTextColor = hex => {
return Glow.relativeLuminance(hex) >= 0.18 ? hex : "#f2f2f4";
};
Glow.applyAccentColor = value => {
const accent =
Glow.normalizeAccentColor(value) || Glow.DEFAULT_ACCENT_COLOR;
@ -239,12 +251,10 @@ Glow.applyAccentColor = value => {
localStorage.setItem("glow_accent_color", accent);
Glow.updateThemeButton?.();
};
Glow.resetAccentColor = () => {
localStorage.removeItem("glow_accent_color");
Glow.applyAccentColor(Glow.DEFAULT_ACCENT_COLOR);
};
Glow.roleDefaultNameColor = role => {
switch (String(role || "").toLowerCase()) {
case "admin":
@ -255,7 +265,6 @@ Glow.roleDefaultNameColor = role => {
return "#f5f5f7";
}
};
Glow.resolveUserNameColor = userish => {
const explicit =
Glow.normalizeNameColor(userish?.name_color) ||
@ -263,22 +272,18 @@ Glow.resolveUserNameColor = userish => {
if (explicit) return explicit;
return Glow.roleDefaultNameColor(userish?.role || userish?.user_role);
};
Glow.applyUserColor = (element, userish) => {
if (!(element instanceof HTMLElement)) return;
element.style.color = Glow.resolveUserNameColor(userish);
};
Glow.canModerate = () => {
const user = Glow.state.currentUser;
return Boolean(user && ["moderator", "admin"].includes(user.role));
};
Glow.isAdmin = () => {
const user = Glow.state.currentUser;
return Boolean(user && user.role === "admin");
};
Glow.showToast = (message, type = "") => {
clearTimeout(Glow.state.toastTimer);
Glow.els.statusToast.textContent = String(message);
@ -287,17 +292,14 @@ Glow.showToast = (message, type = "") => {
Glow.els.statusToast.className = "status-toast";
}, 3500);
};
Glow.showAuthNotice = (message, type = "error") => {
Glow.els.authNotice.textContent = String(message);
Glow.els.authNotice.className = `notice show ${type}`;
};
Glow.clearAuthNotice = () => {
Glow.els.authNotice.textContent = "";
Glow.els.authNotice.className = "notice";
};
Glow.showBlocked = message => {
Glow.els.blockedMessage.textContent = message || "Access has been blocked.";
Glow.els.blockedOverlay.classList.remove("hidden");
@ -309,7 +311,6 @@ Glow.showBlocked = message => {
Glow.els.attachmentButton.classList.add("disabled");
clearTimeout(Glow.state.pollTimer);
};
Glow.relativeTime = iso => {
const seconds = Math.max(
0,
@ -323,7 +324,6 @@ Glow.relativeTime = iso => {
if (hours < 24) return `${hours}h`;
return `${Math.floor(hours / 24)}d`;
};
Glow.formatDateLabel = iso => {
const date = new Date(iso);
const now = new Date();
@ -339,7 +339,6 @@ Glow.formatDateLabel = iso => {
day: "numeric"
});
};
Glow.dateKey = iso => {
const date = new Date(iso);
return [
@ -348,7 +347,6 @@ Glow.dateKey = iso => {
String(date.getDate()).padStart(2, "0")
].join("-");
};
Glow.isNearBottom = () => {
const activeBox =
Glow.state.activeView === "feed"
@ -361,41 +359,34 @@ Glow.isNearBottom = () => {
if (!activeBox) return true;
return activeBox.scrollHeight - activeBox.scrollTop - activeBox.clientHeight < 100;
};
Glow.autoResizeComposer = () => {
const input = Glow.els.messageInput;
input.style.height = "auto";
input.style.height = `${Math.min(input.scrollHeight, 150)}px`;
};
Glow.updateMessageCount = () => {
const count = Glow.els.messageInput.value.length;
Glow.els.messageCount.textContent = `${count} / ${Glow.MAX_MESSAGE_LENGTH}`;
};
Glow.updateDocumentTitle = () => {
if (!Glow.state.unreadMessages) {
document.title = Glow.state.originalTitle;
return;
}
document.title = `(${Glow.state.unreadMessages})` + Glow.state.originalTitle;
document.title = `(${Glow.state.unreadMessages}) ${Glow.state.originalTitle}`;
};
Glow.resetUnreadMessages = () => {
Glow.state.unreadMessages = 0;
Glow.updateDocumentTitle();
Glow.els.newMessagesBar.classList.add("hidden");
};
Glow.showNewMessages = () => {
Glow.els.newMessagesBar.classList.remove("hidden");
};
Glow.normalizeSelectedFiles = fileList => {
if (!fileList) return [];
return [...fileList].filter(Boolean);
};
Glow.openDialog = ({
title,
body,
@ -407,12 +398,10 @@ Glow.openDialog = ({
if (Glow.state.dialogResolver) {
Glow.closeDialog(null);
}
Glow.state.lastFocusedElement = document.activeElement;
Glow.els.dialogTitle.textContent = title;
Glow.els.dialogBody.replaceChildren();
Glow.els.dialogActions.replaceChildren();
if (typeof body === "string") {
const paragraph = document.createElement("p");
paragraph.textContent = body;
@ -420,20 +409,17 @@ Glow.openDialog = ({
} else if (body instanceof Node) {
Glow.els.dialogBody.append(body);
}
const fieldElements = {};
for (const field of fields) {
const label = document.createElement("label");
label.className = "dialog-label";
label.textContent = field.label;
const isMultiline = Boolean(field.multiline);
const input = document.createElement(isMultiline ? "textarea" : "input");
input.className = "field";
input.name = field.name;
input.value = field.value || "";
input.placeholder = field.placeholder || "";
if (isMultiline) {
input.rows = field.rows || 3;
input.maxLength = field.maxLength || 300;
@ -446,26 +432,20 @@ Glow.openDialog = ({
input.step = field.step || "1";
}
}
label.append(input);
Glow.els.dialogBody.append(label);
fieldElements[field.name] = input;
}
const cancel = document.createElement("button");
cancel.className = "button secondary";
cancel.type = "button";
cancel.textContent = cancelText;
const confirmButton = document.createElement("button");
confirmButton.className = danger ? "danger-button" : "button";
confirmButton.type = "button";
confirmButton.textContent = confirmText;
Glow.els.dialogActions.append(cancel, confirmButton);
Glow.els.dialogOverlay.classList.remove("hidden");
return new Promise(resolve => {
Glow.state.dialogResolver = resolve;
cancel.addEventListener("click", () => Glow.closeDialog(null), { once: true });
@ -486,7 +466,6 @@ Glow.openDialog = ({
}, 0);
});
};
Glow.closeDialog = (result = null) => {
Glow.els.dialogOverlay.classList.add("hidden");
const resolve = Glow.state.dialogResolver;