Update static/js/00-config.js
This commit is contained in:
parent
627a08ced6
commit
0b45bd657c
@ -1,8 +1,6 @@
|
|||||||
// static/js/00-config.js
|
// static/js/00-config.js
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
window.Glow = window.Glow || {};
|
window.Glow = window.Glow || {};
|
||||||
|
|
||||||
Glow.els = {
|
Glow.els = {
|
||||||
chatBox: document.getElementById("chatBox"),
|
chatBox: document.getElementById("chatBox"),
|
||||||
dmBox: document.getElementById("dmBox"),
|
dmBox: document.getElementById("dmBox"),
|
||||||
@ -93,9 +91,9 @@ Glow.els = {
|
|||||||
muteCallButton: document.getElementById("muteCallButton"),
|
muteCallButton: document.getElementById("muteCallButton"),
|
||||||
hangupCallButton: document.getElementById("hangupCallButton"),
|
hangupCallButton: document.getElementById("hangupCallButton"),
|
||||||
closeCallPanelButton: document.getElementById("closeCallPanelButton"),
|
closeCallPanelButton: document.getElementById("closeCallPanelButton"),
|
||||||
remoteAudio: document.getElementById("remoteAudio")
|
remoteAudio: document.getElementById("remoteAudio"),
|
||||||
|
emojiAutocomplete: document.getElementById("emojiAutocomplete")
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.state = {
|
Glow.state = {
|
||||||
currentUser: null,
|
currentUser: null,
|
||||||
csrfToken: "",
|
csrfToken: "",
|
||||||
@ -150,6 +148,8 @@ Glow.state = {
|
|||||||
originalTitle: document.title,
|
originalTitle: document.title,
|
||||||
dialogResolver: null,
|
dialogResolver: null,
|
||||||
lastFocusedElement: null,
|
lastFocusedElement: null,
|
||||||
|
emojiSuggestions: [],
|
||||||
|
emojiActiveInput: null,
|
||||||
presence: {
|
presence: {
|
||||||
roomOnlineCount: 0,
|
roomOnlineCount: 0,
|
||||||
channelOnlineCount: 0,
|
channelOnlineCount: 0,
|
||||||
@ -170,18 +170,34 @@ Glow.state = {
|
|||||||
invitePollTimer: null
|
invitePollTimer: null
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.MAX_MESSAGE_LENGTH = 1000;
|
Glow.MAX_MESSAGE_LENGTH = 1000;
|
||||||
Glow.MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
|
Glow.MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
|
||||||
Glow.DEFAULT_ACCENT_COLOR = "#f7dce8";
|
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 => {
|
Glow.normalizeAccentColor = value => {
|
||||||
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)) 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 === "") return null;
|
if (value == null || value === "") return null;
|
||||||
if (typeof value !== "string") 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;
|
if (!/^#[0-9a-fA-F]{6}$/.test(color)) 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;
|
||||||
@ -199,7 +214,6 @@ Glow.hexToRgb = hex => {
|
|||||||
b: parseInt(normalized.slice(5, 7), 16)
|
b: parseInt(normalized.slice(5, 7), 16)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.relativeLuminance = hex => {
|
Glow.relativeLuminance = hex => {
|
||||||
const rgb = Glow.hexToRgb(hex);
|
const rgb = Glow.hexToRgb(hex);
|
||||||
if (!rgb) return 0;
|
if (!rgb) return 0;
|
||||||
@ -215,11 +229,9 @@ Glow.relativeLuminance = hex => {
|
|||||||
0.0722 * channel(rgb.b)
|
0.0722 * channel(rgb.b)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.accentTextColor = hex => {
|
Glow.accentTextColor = hex => {
|
||||||
return Glow.relativeLuminance(hex) >= 0.18 ? hex : "#f2f2f4";
|
return Glow.relativeLuminance(hex) >= 0.18 ? hex : "#f2f2f4";
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.applyAccentColor = value => {
|
Glow.applyAccentColor = value => {
|
||||||
const accent =
|
const accent =
|
||||||
Glow.normalizeAccentColor(value) || Glow.DEFAULT_ACCENT_COLOR;
|
Glow.normalizeAccentColor(value) || Glow.DEFAULT_ACCENT_COLOR;
|
||||||
@ -239,12 +251,10 @@ Glow.applyAccentColor = value => {
|
|||||||
localStorage.setItem("glow_accent_color", accent);
|
localStorage.setItem("glow_accent_color", accent);
|
||||||
Glow.updateThemeButton?.();
|
Glow.updateThemeButton?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.resetAccentColor = () => {
|
Glow.resetAccentColor = () => {
|
||||||
localStorage.removeItem("glow_accent_color");
|
localStorage.removeItem("glow_accent_color");
|
||||||
Glow.applyAccentColor(Glow.DEFAULT_ACCENT_COLOR);
|
Glow.applyAccentColor(Glow.DEFAULT_ACCENT_COLOR);
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.roleDefaultNameColor = role => {
|
Glow.roleDefaultNameColor = role => {
|
||||||
switch (String(role || "").toLowerCase()) {
|
switch (String(role || "").toLowerCase()) {
|
||||||
case "admin":
|
case "admin":
|
||||||
@ -255,7 +265,6 @@ Glow.roleDefaultNameColor = role => {
|
|||||||
return "#f5f5f7";
|
return "#f5f5f7";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.resolveUserNameColor = userish => {
|
Glow.resolveUserNameColor = userish => {
|
||||||
const explicit =
|
const explicit =
|
||||||
Glow.normalizeNameColor(userish?.name_color) ||
|
Glow.normalizeNameColor(userish?.name_color) ||
|
||||||
@ -263,22 +272,18 @@ Glow.resolveUserNameColor = userish => {
|
|||||||
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)) return;
|
if (!(element instanceof HTMLElement)) return;
|
||||||
element.style.color = Glow.resolveUserNameColor(userish);
|
element.style.color = Glow.resolveUserNameColor(userish);
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.canModerate = () => {
|
Glow.canModerate = () => {
|
||||||
const user = Glow.state.currentUser;
|
const user = Glow.state.currentUser;
|
||||||
return Boolean(user && ["moderator", "admin"].includes(user.role));
|
return Boolean(user && ["moderator", "admin"].includes(user.role));
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.isAdmin = () => {
|
Glow.isAdmin = () => {
|
||||||
const user = Glow.state.currentUser;
|
const user = Glow.state.currentUser;
|
||||||
return Boolean(user && user.role === "admin");
|
return Boolean(user && user.role === "admin");
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
@ -287,17 +292,14 @@ Glow.showToast = (message, type = "") => {
|
|||||||
Glow.els.statusToast.className = "status-toast";
|
Glow.els.statusToast.className = "status-toast";
|
||||||
}, 3500);
|
}, 3500);
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.showAuthNotice = (message, type = "error") => {
|
Glow.showAuthNotice = (message, type = "error") => {
|
||||||
Glow.els.authNotice.textContent = String(message);
|
Glow.els.authNotice.textContent = String(message);
|
||||||
Glow.els.authNotice.className = `notice show ${type}`;
|
Glow.els.authNotice.className = `notice show ${type}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.clearAuthNotice = () => {
|
Glow.clearAuthNotice = () => {
|
||||||
Glow.els.authNotice.textContent = "";
|
Glow.els.authNotice.textContent = "";
|
||||||
Glow.els.authNotice.className = "notice";
|
Glow.els.authNotice.className = "notice";
|
||||||
};
|
};
|
||||||
|
|
||||||
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");
|
||||||
@ -309,7 +311,6 @@ Glow.showBlocked = message => {
|
|||||||
Glow.els.attachmentButton.classList.add("disabled");
|
Glow.els.attachmentButton.classList.add("disabled");
|
||||||
clearTimeout(Glow.state.pollTimer);
|
clearTimeout(Glow.state.pollTimer);
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.relativeTime = iso => {
|
Glow.relativeTime = iso => {
|
||||||
const seconds = Math.max(
|
const seconds = Math.max(
|
||||||
0,
|
0,
|
||||||
@ -323,7 +324,6 @@ Glow.relativeTime = iso => {
|
|||||||
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();
|
||||||
@ -339,7 +339,6 @@ Glow.formatDateLabel = iso => {
|
|||||||
day: "numeric"
|
day: "numeric"
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.dateKey = iso => {
|
Glow.dateKey = iso => {
|
||||||
const date = new Date(iso);
|
const date = new Date(iso);
|
||||||
return [
|
return [
|
||||||
@ -348,7 +347,6 @@ Glow.dateKey = iso => {
|
|||||||
String(date.getDate()).padStart(2, "0")
|
String(date.getDate()).padStart(2, "0")
|
||||||
].join("-");
|
].join("-");
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.isNearBottom = () => {
|
Glow.isNearBottom = () => {
|
||||||
const activeBox =
|
const activeBox =
|
||||||
Glow.state.activeView === "feed"
|
Glow.state.activeView === "feed"
|
||||||
@ -361,41 +359,34 @@ Glow.isNearBottom = () => {
|
|||||||
if (!activeBox) return true;
|
if (!activeBox) return true;
|
||||||
return activeBox.scrollHeight - activeBox.scrollTop - activeBox.clientHeight < 100;
|
return activeBox.scrollHeight - activeBox.scrollTop - activeBox.clientHeight < 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.autoResizeComposer = () => {
|
Glow.autoResizeComposer = () => {
|
||||||
const input = Glow.els.messageInput;
|
const input = Glow.els.messageInput;
|
||||||
input.style.height = "auto";
|
input.style.height = "auto";
|
||||||
input.style.height = `${Math.min(input.scrollHeight, 150)}px`;
|
input.style.height = `${Math.min(input.scrollHeight, 150)}px`;
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.updateMessageCount = () => {
|
Glow.updateMessageCount = () => {
|
||||||
const count = Glow.els.messageInput.value.length;
|
const count = Glow.els.messageInput.value.length;
|
||||||
Glow.els.messageCount.textContent = `${count} / ${Glow.MAX_MESSAGE_LENGTH}`;
|
Glow.els.messageCount.textContent = `${count} / ${Glow.MAX_MESSAGE_LENGTH}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.updateDocumentTitle = () => {
|
Glow.updateDocumentTitle = () => {
|
||||||
if (!Glow.state.unreadMessages) {
|
if (!Glow.state.unreadMessages) {
|
||||||
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 = () => {
|
||||||
Glow.state.unreadMessages = 0;
|
Glow.state.unreadMessages = 0;
|
||||||
Glow.updateDocumentTitle();
|
Glow.updateDocumentTitle();
|
||||||
Glow.els.newMessagesBar.classList.add("hidden");
|
Glow.els.newMessagesBar.classList.add("hidden");
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.showNewMessages = () => {
|
Glow.showNewMessages = () => {
|
||||||
Glow.els.newMessagesBar.classList.remove("hidden");
|
Glow.els.newMessagesBar.classList.remove("hidden");
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.normalizeSelectedFiles = fileList => {
|
Glow.normalizeSelectedFiles = fileList => {
|
||||||
if (!fileList) return [];
|
if (!fileList) return [];
|
||||||
return [...fileList].filter(Boolean);
|
return [...fileList].filter(Boolean);
|
||||||
};
|
};
|
||||||
|
|
||||||
Glow.openDialog = ({
|
Glow.openDialog = ({
|
||||||
title,
|
title,
|
||||||
body,
|
body,
|
||||||
@ -407,12 +398,10 @@ Glow.openDialog = ({
|
|||||||
if (Glow.state.dialogResolver) {
|
if (Glow.state.dialogResolver) {
|
||||||
Glow.closeDialog(null);
|
Glow.closeDialog(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
if (typeof body === "string") {
|
if (typeof body === "string") {
|
||||||
const paragraph = document.createElement("p");
|
const paragraph = document.createElement("p");
|
||||||
paragraph.textContent = body;
|
paragraph.textContent = body;
|
||||||
@ -420,20 +409,17 @@ Glow.openDialog = ({
|
|||||||
} else if (body instanceof Node) {
|
} else if (body instanceof Node) {
|
||||||
Glow.els.dialogBody.append(body);
|
Glow.els.dialogBody.append(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
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";
|
||||||
label.textContent = field.label;
|
label.textContent = field.label;
|
||||||
|
|
||||||
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 || "";
|
||||||
input.placeholder = field.placeholder || "";
|
input.placeholder = field.placeholder || "";
|
||||||
|
|
||||||
if (isMultiline) {
|
if (isMultiline) {
|
||||||
input.rows = field.rows || 3;
|
input.rows = field.rows || 3;
|
||||||
input.maxLength = field.maxLength || 300;
|
input.maxLength = field.maxLength || 300;
|
||||||
@ -446,26 +432,20 @@ Glow.openDialog = ({
|
|||||||
input.step = field.step || "1";
|
input.step = field.step || "1";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label.append(input);
|
label.append(input);
|
||||||
Glow.els.dialogBody.append(label);
|
Glow.els.dialogBody.append(label);
|
||||||
fieldElements[field.name] = input;
|
fieldElements[field.name] = input;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cancel = document.createElement("button");
|
const cancel = document.createElement("button");
|
||||||
cancel.className = "button secondary";
|
cancel.className = "button secondary";
|
||||||
cancel.type = "button";
|
cancel.type = "button";
|
||||||
cancel.textContent = cancelText;
|
cancel.textContent = cancelText;
|
||||||
|
|
||||||
const confirmButton = document.createElement("button");
|
const confirmButton = document.createElement("button");
|
||||||
confirmButton.className = danger ? "danger-button" : "button";
|
confirmButton.className = danger ? "danger-button" : "button";
|
||||||
confirmButton.type = "button";
|
confirmButton.type = "button";
|
||||||
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 });
|
||||||
@ -486,7 +466,6 @@ Glow.openDialog = ({
|
|||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user