Update static/js/00-config.js

This commit is contained in:
dev 2026-09-25 02:40:21 +00:00
parent 2cb9d0157c
commit 09c873e620

View File

@ -36,9 +36,7 @@ Glow.els = {
clearMessagesButton: document.getElementById("clearMessagesButton"), clearMessagesButton: document.getElementById("clearMessagesButton"),
createRoomButton: document.getElementById("createRoomButton"), createRoomButton: document.getElementById("createRoomButton"),
typingToggleButton: document.getElementById("typingToggleButton"), typingToggleButton: document.getElementById("typingToggleButton"),
notificationsToggleButton: document.getElementById( notificationsToggleButton: document.getElementById("notificationsToggleButton"),
"notificationsToggleButton"
),
themeButton: document.getElementById("themeButton"), themeButton: document.getElementById("themeButton"),
adminUsers: document.getElementById("adminUsers"), adminUsers: document.getElementById("adminUsers"),
adminRooms: document.getElementById("adminRooms"), adminRooms: document.getElementById("adminRooms"),
@ -52,7 +50,6 @@ Glow.els = {
dialogTitle: document.getElementById("dialogTitle"), dialogTitle: document.getElementById("dialogTitle"),
dialogBody: document.getElementById("dialogBody"), dialogBody: document.getElementById("dialogBody"),
dialogActions: document.getElementById("dialogActions"), dialogActions: document.getElementById("dialogActions"),
teamSelect: document.getElementById("teamSelect"), teamSelect: document.getElementById("teamSelect"),
pagesButton: document.getElementById("pagesButton"), pagesButton: document.getElementById("pagesButton"),
backButton: document.getElementById("backButton"), backButton: document.getElementById("backButton"),
@ -67,22 +64,16 @@ Glow.els = {
threadAttachmentName: document.getElementById("threadAttachmentName"), threadAttachmentName: document.getElementById("threadAttachmentName"),
pagesBox: document.getElementById("pagesBox"), pagesBox: document.getElementById("pagesBox"),
pageDetailBox: document.getElementById("pageDetailBox"), pageDetailBox: document.getElementById("pageDetailBox"),
settingsButton: document.getElementById("settingsButton"), settingsButton: document.getElementById("settingsButton"),
profileBox: document.getElementById("profileBox"), profileBox: document.getElementById("profileBox"),
headerMenuOverlay: document.getElementById("headerMenuOverlay"), headerMenuOverlay: document.getElementById("headerMenuOverlay"),
headerMenuList: document.getElementById("headerMenuList"), headerMenuList: document.getElementById("headerMenuList"),
reactionPopupOverlay: document.getElementById("reactionPopupOverlay"), reactionPopupOverlay: document.getElementById("reactionPopupOverlay"),
reactionPopupGrid: document.getElementById("reactionPopupGrid"), reactionPopupGrid: document.getElementById("reactionPopupGrid"),
reactionPopupList: document.getElementById("reactionPopupList"), reactionPopupList: document.getElementById("reactionPopupList"),
reactionCustomInput: document.getElementById("reactionCustomInput"), reactionCustomInput: document.getElementById("reactionCustomInput"),
reactionCustomButton: document.getElementById("reactionCustomButton"), reactionCustomButton: document.getElementById("reactionCustomButton"),
closeReactionPopupButton: document.getElementById( closeReactionPopupButton: document.getElementById("closeReactionPopupButton"),
"closeReactionPopupButton"
),
mediaOverlay: document.getElementById("mediaOverlay"), mediaOverlay: document.getElementById("mediaOverlay"),
mediaTitle: document.getElementById("mediaTitle"), mediaTitle: document.getElementById("mediaTitle"),
mediaImage: document.getElementById("mediaImage"), mediaImage: document.getElementById("mediaImage"),
@ -92,12 +83,12 @@ Glow.els = {
mediaFallbackLink: document.getElementById("mediaFallbackLink"), mediaFallbackLink: document.getElementById("mediaFallbackLink"),
mediaDownloadLink: document.getElementById("mediaDownloadLink"), mediaDownloadLink: document.getElementById("mediaDownloadLink"),
closeMediaButton: document.getElementById("closeMediaButton"), closeMediaButton: document.getElementById("closeMediaButton"),
callOverlay: document.getElementById("callOverlay"), callOverlay: document.getElementById("callOverlay"),
callStatus: document.getElementById("callStatus"), callStatus: document.getElementById("callStatus"),
callPeerLabel: document.getElementById("callPeerLabel"), callPeerLabel: document.getElementById("callPeerLabel"),
startCallButton: document.getElementById("startCallButton"), startCallButton: document.getElementById("startCallButton"),
answerCallButton: document.getElementById("answerCallButton"), answerCallButton: document.getElementById("answerCallButton"),
addToCallButton: document.getElementById("addToCallButton"),
muteCallButton: document.getElementById("muteCallButton"), muteCallButton: document.getElementById("muteCallButton"),
hangupCallButton: document.getElementById("hangupCallButton"), hangupCallButton: document.getElementById("hangupCallButton"),
closeCallPanelButton: document.getElementById("closeCallPanelButton"), closeCallPanelButton: document.getElementById("closeCallPanelButton"),
@ -107,20 +98,15 @@ Glow.els = {
Glow.state = { Glow.state = {
currentUser: null, currentUser: null,
csrfToken: "", csrfToken: "",
rooms: [], rooms: [],
activeRoom: null, activeRoom: null,
teams: [], teams: [],
activeTeam: null, activeTeam: null,
channels: [], channels: [],
activeChannel: null, activeChannel: null,
dms: [], dms: [],
activeDm: null, activeDm: null,
activeView: "feed", activeView: "feed",
lastSeenId: 0, lastSeenId: 0,
knownMessageIds: new Set(), knownMessageIds: new Set(),
renderedMessages: [], renderedMessages: [],
@ -130,68 +116,57 @@ Glow.state = {
pollInFlight: false, pollInFlight: false,
channelPollInFlight: false, channelPollInFlight: false,
dmPollInFlight: false, dmPollInFlight: false,
feedLastSeenId: 0, feedLastSeenId: 0,
feedKnownMessageIds: new Set(), feedKnownMessageIds: new Set(),
feedEntries: [], feedEntries: [],
feedRequestId: 0, feedRequestId: 0,
feedPollInFlight: false, feedPollInFlight: false,
activeThread: null, activeThread: null,
threadReplies: [], threadReplies: [],
threadRequestId: 0, threadRequestId: 0,
threadPollInFlight: false, threadPollInFlight: false,
pages: [], pages: [],
activePage: null, activePage: null,
pageTypeFilter: "", pageTypeFilter: "",
activeProfile: null, activeProfile: null,
settings: null, settings: null,
pollTimer: null, pollTimer: null,
initialized: false, initialized: false,
toastTimer: null, toastTimer: null,
selectedAttachment: [], selectedAttachment: [],
selectedThreadAttachment: [], selectedThreadAttachment: [],
typingTimer: null, typingTimer: null,
typingLastSent: 0, typingLastSent: 0,
typingUsers: [], typingUsers: [],
dmTypingUsers: [], dmTypingUsers: [],
typingIndicatorsEnabled: typingIndicatorsEnabled:
localStorage.getItem("glow_typing_enabled") !== "false", localStorage.getItem("glow_typing_enabled") !== "false",
notificationsEnabled: notificationsEnabled:
localStorage.getItem("glow_notifications_enabled") === "true", localStorage.getItem("glow_notifications_enabled") === "true",
accentColor: accentColor:
localStorage.getItem("glow_accent_color") || "#f7dce8", localStorage.getItem("glow_accent_color") || "#f7dce8",
unreadMessages: 0, unreadMessages: 0,
originalTitle: document.title, originalTitle: document.title,
dialogResolver: null, dialogResolver: null,
lastFocusedElement: null, lastFocusedElement: null,
presence: { presence: {
roomOnlineCount: 0, roomOnlineCount: 0,
channelOnlineCount: 0, channelOnlineCount: 0,
dmOnlineCount: 0 dmOnlineCount: 0
}, },
calls: { calls: {
activeCall: null, activeCall: null,
peerConnection: null, ws: null,
session: null,
localStream: null, localStream: null,
muted: false, muted: false,
signalLastSeenId: 0, selfPeerId: null,
pollTimer: null, peerConnections: new Map(),
incomingCall: null, remoteStreams: new Map(),
pendingOffer: null peers: [],
reconnectTimer: null,
invites: [],
invitePollTimer: null
} }
}; };
@ -200,43 +175,23 @@ Glow.MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
Glow.DEFAULT_ACCENT_COLOR = "#f7dce8"; Glow.DEFAULT_ACCENT_COLOR = "#f7dce8";
Glow.normalizeAccentColor = value => { Glow.normalizeAccentColor = value => {
if (typeof value !== "string") { if (typeof value !== "string") return null;
return null;
}
const color = value.trim(); const color = value.trim();
if (!/^#[0-9a-fA-F]{6}$/.test(color)) return null;
if (!/^#[0-9a-fA-F]{6}$/.test(color)) {
return null;
}
return color.toLowerCase(); return color.toLowerCase();
}; };
Glow.normalizeNameColor = value => { Glow.normalizeNameColor = value => {
if (value == null || value === "") { if (value == null || value === "") return null;
return null; if (typeof value !== "string") return null;
}
if (typeof value !== "string") {
return null;
}
const color = value.trim(); const color = value.trim();
if (!/^#[0-9a-fA-F]{6}$/.test(color)) { if (!/^#[0-9a-fA-F]{6}$/.test(color)) return null;
return null;
}
return color.toLowerCase(); return color.toLowerCase();
}; };
Glow.hexToRgb = hex => { Glow.hexToRgb = hex => {
const normalized = Glow.normalizeAccentColor(hex); const normalized = Glow.normalizeAccentColor(hex);
if (!normalized) return null;
if (!normalized) {
return null;
}
return { return {
r: parseInt(normalized.slice(1, 3), 16), r: parseInt(normalized.slice(1, 3), 16),
g: parseInt(normalized.slice(3, 5), 16), g: parseInt(normalized.slice(3, 5), 16),
@ -246,19 +201,13 @@ Glow.hexToRgb = hex => {
Glow.relativeLuminance = hex => { Glow.relativeLuminance = hex => {
const rgb = Glow.hexToRgb(hex); const rgb = Glow.hexToRgb(hex);
if (!rgb) return 0;
if (!rgb) {
return 0;
}
const channel = value => { const channel = value => {
const normalized = value / 255; const normalized = value / 255;
return normalized <= 0.03928 return normalized <= 0.03928
? normalized / 12.92 ? normalized / 12.92
: Math.pow((normalized + 0.055) / 1.055, 2.4); : Math.pow((normalized + 0.055) / 1.055, 2.4);
}; };
return ( return (
0.2126 * channel(rgb.r) + 0.2126 * channel(rgb.r) +
0.7152 * channel(rgb.g) + 0.7152 * channel(rgb.g) +
@ -273,12 +222,9 @@ Glow.accentTextColor = hex => {
Glow.applyAccentColor = value => { Glow.applyAccentColor = value => {
const accent = const accent =
Glow.normalizeAccentColor(value) || Glow.DEFAULT_ACCENT_COLOR; Glow.normalizeAccentColor(value) || Glow.DEFAULT_ACCENT_COLOR;
const rgb = Glow.hexToRgb(accent); const rgb = Glow.hexToRgb(accent);
const root = document.documentElement; const root = document.documentElement;
Glow.state.accentColor = accent; Glow.state.accentColor = accent;
root.style.setProperty("--accent", accent); root.style.setProperty("--accent", accent);
root.style.setProperty("--accent-active", Glow.accentTextColor(accent)); root.style.setProperty("--accent-active", Glow.accentTextColor(accent));
root.style.setProperty( root.style.setProperty(
@ -289,9 +235,7 @@ Glow.applyAccentColor = value => {
"--accent-hover", "--accent-hover",
`rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.28)` `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.28)`
); );
localStorage.setItem("glow_accent_color", accent); localStorage.setItem("glow_accent_color", accent);
Glow.updateThemeButton?.(); Glow.updateThemeButton?.();
}; };
@ -315,19 +259,12 @@ Glow.resolveUserNameColor = userish => {
const explicit = const explicit =
Glow.normalizeNameColor(userish?.name_color) || Glow.normalizeNameColor(userish?.name_color) ||
Glow.normalizeNameColor(userish?.user_name_color); Glow.normalizeNameColor(userish?.user_name_color);
if (explicit) return explicit;
if (explicit) {
return explicit;
}
return Glow.roleDefaultNameColor(userish?.role || userish?.user_role); return Glow.roleDefaultNameColor(userish?.role || userish?.user_role);
}; };
Glow.applyUserColor = (element, userish) => { Glow.applyUserColor = (element, userish) => {
if (!(element instanceof HTMLElement)) { if (!(element instanceof HTMLElement)) return;
return;
}
element.style.color = Glow.resolveUserNameColor(userish); element.style.color = Glow.resolveUserNameColor(userish);
}; };
@ -343,10 +280,8 @@ Glow.isAdmin = () => {
Glow.showToast = (message, type = "") => { Glow.showToast = (message, type = "") => {
clearTimeout(Glow.state.toastTimer); clearTimeout(Glow.state.toastTimer);
Glow.els.statusToast.textContent = String(message); Glow.els.statusToast.textContent = String(message);
Glow.els.statusToast.className = `status-toast show ${type}`.trim(); Glow.els.statusToast.className = `status-toast show ${type}`.trim();
Glow.state.toastTimer = setTimeout(() => { Glow.state.toastTimer = setTimeout(() => {
Glow.els.statusToast.className = "status-toast"; Glow.els.statusToast.className = "status-toast";
}, 3500); }, 3500);
@ -364,17 +299,13 @@ Glow.clearAuthNotice = () => {
Glow.showBlocked = message => { Glow.showBlocked = message => {
Glow.els.blockedMessage.textContent = message || "Access has been blocked."; Glow.els.blockedMessage.textContent = message || "Access has been blocked.";
Glow.els.blockedOverlay.classList.remove("hidden"); Glow.els.blockedOverlay.classList.remove("hidden");
Glow.els.authOverlay.classList.add("hidden"); Glow.els.authOverlay.classList.add("hidden");
Glow.els.messageInput.disabled = true; Glow.els.messageInput.disabled = true;
Glow.els.sendButton.disabled = true; Glow.els.sendButton.disabled = true;
Glow.els.roomSelect.disabled = true; Glow.els.roomSelect.disabled = true;
Glow.els.attachmentInput.disabled = true; Glow.els.attachmentInput.disabled = true;
Glow.els.attachmentButton.classList.add("disabled"); Glow.els.attachmentButton.classList.add("disabled");
clearTimeout(Glow.state.pollTimer); clearTimeout(Glow.state.pollTimer);
}; };
@ -383,52 +314,23 @@ Glow.relativeTime = iso => {
0, 0,
Math.floor((Date.now() - new Date(iso).getTime()) / 1000) Math.floor((Date.now() - new Date(iso).getTime()) / 1000)
); );
if (seconds < 5) return "now";
if (seconds < 5) { if (seconds < 60) return `${seconds}s`;
return "now";
}
if (seconds < 60) {
return `${seconds}s`;
}
const minutes = Math.floor(seconds / 60); const minutes = Math.floor(seconds / 60);
if (minutes < 60) return `${minutes}m`;
if (minutes < 60) {
return `${minutes}m`;
}
const hours = Math.floor(minutes / 60); const hours = Math.floor(minutes / 60);
if (hours < 24) return `${hours}h`;
if (hours < 24) {
return `${hours}h`;
}
return `${Math.floor(hours / 24)}d`; return `${Math.floor(hours / 24)}d`;
}; };
Glow.formatDateLabel = iso => { Glow.formatDateLabel = iso => {
const date = new Date(iso); const date = new Date(iso);
const now = new Date(); const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const target = new Date(date.getFullYear(), date.getMonth(), date.getDate());
const target = new Date(
date.getFullYear(),
date.getMonth(),
date.getDate()
);
const diff = Math.round((today - target) / 86400000); const diff = Math.round((today - target) / 86400000);
if (diff === 0) return "Today";
if (diff === 0) { if (diff === 1) return "Yesterday";
return "Today";
}
if (diff === 1) {
return "Yesterday";
}
return date.toLocaleDateString(undefined, { return date.toLocaleDateString(undefined, {
weekday: "long", weekday: "long",
year: "numeric", year: "numeric",
@ -439,7 +341,6 @@ Glow.formatDateLabel = iso => {
Glow.dateKey = iso => { Glow.dateKey = iso => {
const date = new Date(iso); const date = new Date(iso);
return [ return [
date.getFullYear(), date.getFullYear(),
String(date.getMonth() + 1).padStart(2, "0"), String(date.getMonth() + 1).padStart(2, "0"),
@ -456,11 +357,7 @@ Glow.isNearBottom = () => {
: Glow.state.activeView === "dms" : Glow.state.activeView === "dms"
? Glow.els.dmBox ? Glow.els.dmBox
: Glow.els.chatBox; : Glow.els.chatBox;
if (!activeBox) return true;
if (!activeBox) {
return true;
}
return activeBox.scrollHeight - activeBox.scrollTop - activeBox.clientHeight < 100; return activeBox.scrollHeight - activeBox.scrollTop - activeBox.clientHeight < 100;
}; };
@ -480,8 +377,7 @@ Glow.updateDocumentTitle = () => {
document.title = Glow.state.originalTitle; document.title = Glow.state.originalTitle;
return; return;
} }
document.title = `(${Glow.state.unreadMessages})` + Glow.state.originalTitle;
document.title = `(${Glow.state.unreadMessages}) ` + Glow.state.originalTitle;
}; };
Glow.resetUnreadMessages = () => { Glow.resetUnreadMessages = () => {
@ -495,10 +391,7 @@ Glow.showNewMessages = () => {
}; };
Glow.normalizeSelectedFiles = fileList => { Glow.normalizeSelectedFiles = fileList => {
if (!fileList) { if (!fileList) return [];
return [];
}
return [...fileList].filter(Boolean); return [...fileList].filter(Boolean);
}; };
@ -515,7 +408,6 @@ Glow.openDialog = ({
} }
Glow.state.lastFocusedElement = document.activeElement; Glow.state.lastFocusedElement = document.activeElement;
Glow.els.dialogTitle.textContent = title; Glow.els.dialogTitle.textContent = title;
Glow.els.dialogBody.replaceChildren(); Glow.els.dialogBody.replaceChildren();
Glow.els.dialogActions.replaceChildren(); Glow.els.dialogActions.replaceChildren();
@ -529,7 +421,6 @@ Glow.openDialog = ({
} }
const fieldElements = {}; const fieldElements = {};
for (const field of fields) { for (const field of fields) {
const label = document.createElement("label"); const label = document.createElement("label");
label.className = "dialog-label"; label.className = "dialog-label";
@ -537,7 +428,6 @@ Glow.openDialog = ({
const isMultiline = Boolean(field.multiline); const isMultiline = Boolean(field.multiline);
const input = document.createElement(isMultiline ? "textarea" : "input"); const input = document.createElement(isMultiline ? "textarea" : "input");
input.className = "field"; input.className = "field";
input.name = field.name; input.name = field.name;
input.value = field.value || ""; input.value = field.value || "";
@ -549,7 +439,6 @@ Glow.openDialog = ({
} else { } else {
input.type = field.type || "text"; input.type = field.type || "text";
input.maxLength = field.maxLength || 300; input.maxLength = field.maxLength || 300;
if (field.type === "number") { if (field.type === "number") {
input.min = field.min || "1"; input.min = field.min || "1";
input.max = field.max || "43200"; input.max = field.max || "43200";
@ -573,31 +462,23 @@ Glow.openDialog = ({
confirmButton.textContent = confirmText; confirmButton.textContent = confirmText;
Glow.els.dialogActions.append(cancel, confirmButton); Glow.els.dialogActions.append(cancel, confirmButton);
Glow.els.dialogOverlay.classList.remove("hidden"); Glow.els.dialogOverlay.classList.remove("hidden");
return new Promise(resolve => { return new Promise(resolve => {
Glow.state.dialogResolver = resolve; Glow.state.dialogResolver = resolve;
cancel.addEventListener("click", () => Glow.closeDialog(null), { once: true });
cancel.addEventListener(
"click",
() => Glow.closeDialog(null),
{ once: true }
);
confirmButton.addEventListener( confirmButton.addEventListener(
"click", "click",
() => { () => {
const values = {}; const values = {};
for (const [name, input] of Object.entries(fieldElements)) { for (const [name, input] of Object.entries(fieldElements)) {
values[name] = input.value.trim(); values[name] = input.value.trim();
} }
Glow.closeDialog(values); Glow.closeDialog(values);
}, },
{ once: true } { once: true }
); );
setTimeout(() => { setTimeout(() => {
const first = Object.values(fieldElements)[0] || confirmButton; const first = Object.values(fieldElements)[0] || confirmButton;
first.focus(); first.focus();
@ -607,14 +488,9 @@ Glow.openDialog = ({
Glow.closeDialog = (result = null) => { Glow.closeDialog = (result = null) => {
Glow.els.dialogOverlay.classList.add("hidden"); Glow.els.dialogOverlay.classList.add("hidden");
const resolve = Glow.state.dialogResolver; const resolve = Glow.state.dialogResolver;
Glow.state.dialogResolver = null; Glow.state.dialogResolver = null;
if (resolve) resolve(result);
if (resolve) {
resolve(result);
}
if (Glow.state.lastFocusedElement instanceof HTMLElement) { if (Glow.state.lastFocusedElement instanceof HTMLElement) {
Glow.state.lastFocusedElement.focus(); Glow.state.lastFocusedElement.focus();
} }