Update static/js/04-main.js

This commit is contained in:
dev 2026-09-25 02:39:24 +00:00
parent 5e080893e2
commit 2cb9d0157c

View File

@ -1,6 +1,5 @@
// static/js/04-main.js // static/js/04-main.js
"use strict"; "use strict";
window.Glow = window.Glow || {}; window.Glow = window.Glow || {};
Glow.loadRooms = async () => { Glow.loadRooms = async () => {
@ -27,7 +26,6 @@ Glow.loadRooms = async () => {
null; null;
Glow.state.activeRoom = selected; Glow.state.activeRoom = selected;
Glow.updateViewUI(); Glow.updateViewUI();
Glow.updateChatControls(); Glow.updateChatControls();
}; };
@ -36,7 +34,6 @@ Glow.updateViewUI = () => {
const view = Glow.state.activeView || "feed"; const view = Glow.state.activeView || "feed";
const room = Glow.state.activeRoom; const room = Glow.state.activeRoom;
const dm = Glow.state.activeDm; const dm = Glow.state.activeDm;
const feedActive = view === "feed"; const feedActive = view === "feed";
const dmListActive = view === "dms"; const dmListActive = view === "dms";
const chatActive = view === "room" || view === "channel" || view === "dm"; const chatActive = view === "room" || view === "channel" || view === "dm";
@ -53,14 +50,12 @@ Glow.updateViewUI = () => {
Glow.els.pagesBox?.classList.toggle("hidden", !pagesActive); Glow.els.pagesBox?.classList.toggle("hidden", !pagesActive);
Glow.els.pageDetailBox?.classList.toggle("hidden", !pageActive); Glow.els.pageDetailBox?.classList.toggle("hidden", !pageActive);
Glow.els.profileBox?.classList.toggle("hidden", !(profileActive || settingsActive)); Glow.els.profileBox?.classList.toggle("hidden", !(profileActive || settingsActive));
Glow.els.composerWrap.classList.toggle("hidden", !chatActive); Glow.els.composerWrap.classList.toggle("hidden", !chatActive);
Glow.els.threadComposerWrap?.classList.toggle("hidden", !threadActive); Glow.els.threadComposerWrap?.classList.toggle("hidden", !threadActive);
if (!chatActive) { if (!chatActive) {
Glow.state.typingUsers = []; Glow.state.typingUsers = [];
Glow.state.dmTypingUsers = []; Glow.state.dmTypingUsers = [];
if (Glow.els.typingBar) { if (Glow.els.typingBar) {
Glow.els.typingBar.textContent = ""; Glow.els.typingBar.textContent = "";
Glow.els.typingBar.classList.add("hidden"); Glow.els.typingBar.classList.add("hidden");
@ -90,7 +85,6 @@ Glow.updateViewUI = () => {
Glow.els.headerSubtitle.textContent = Glow.state.currentUser Glow.els.headerSubtitle.textContent = Glow.state.currentUser
? "Recent activity across your accessible rooms" ? "Recent activity across your accessible rooms"
: "Sign in or create an account to personalize your feed"; : "Sign in or create an account to personalize your feed";
Glow.els.roomSelect.disabled = !Glow.state.rooms.length; Glow.els.roomSelect.disabled = !Glow.state.rooms.length;
Glow.els.presenceLabel?.classList.add("hidden"); Glow.els.presenceLabel?.classList.add("hidden");
return; return;
@ -108,9 +102,7 @@ Glow.updateViewUI = () => {
if (threadActive) { if (threadActive) {
Glow.els.headerTitle.textContent = "Thread"; Glow.els.headerTitle.textContent = "Thread";
Glow.els.headerSubtitle.textContent = Glow.els.headerSubtitle.textContent =
dm dm ? "Direct message replies" : room?.name || "Conversation replies";
? "Direct message replies"
: room?.name || "Conversation replies";
Glow.updateThreadControls?.(); Glow.updateThreadControls?.();
return; return;
} }
@ -151,7 +143,6 @@ Glow.updateViewUI = () => {
(dm.members || []).find( (dm.members || []).find(
member => Number(member.id) !== Number(Glow.state.currentUser?.id) member => Number(member.id) !== Number(Glow.state.currentUser?.id)
) || dm.members?.[0]; ) || dm.members?.[0];
Glow.els.headerTitle.textContent = Glow.els.headerTitle.textContent =
peer?.display_name || peer?.username || "Direct message"; peer?.display_name || peer?.username || "Direct message";
Glow.els.headerSubtitle.textContent = Glow.els.headerSubtitle.textContent =
@ -166,7 +157,6 @@ Glow.updateViewUI = () => {
Glow.els.headerSubtitle.textContent = Glow.els.headerSubtitle.textContent =
room.description || room.description ||
(room.visibility === "private" ? "private room" : "public room"); (room.visibility === "private" ? "private room" : "public room");
Glow.els.roomSelect.value = room.slug; Glow.els.roomSelect.value = room.slug;
} else { } else {
Glow.els.headerTitle.textContent = "No rooms"; Glow.els.headerTitle.textContent = "No rooms";
@ -219,7 +209,6 @@ Glow.checkInvite = async () => {
body: JSON.stringify({}) body: JSON.stringify({})
} }
); );
Glow.showToast(`Joined private room: ${data.room.name}`); Glow.showToast(`Joined private room: ${data.room.name}`);
window.history.replaceState({}, "", window.location.pathname); window.history.replaceState({}, "", window.location.pathname);
} catch (error) { } catch (error) {
@ -247,11 +236,11 @@ Glow.checkInvite = async () => {
Glow.checkAuth = async () => { Glow.checkAuth = async () => {
try { try {
const data = await Glow.apiRequest("/api/me"); const data = await Glow.apiRequest("/api/me");
Glow.state.currentUser = data.authenticated ? data.user : null; Glow.state.currentUser = data.authenticated ? data.user : null;
Glow.state.csrfToken = data.csrf_token || ""; Glow.state.csrfToken = data.csrf_token || "";
Glow.updateAuthUI(); Glow.updateAuthUI();
await Glow.checkInvite(); await Glow.checkInvite();
await Glow.loadRooms(); await Glow.loadRooms();
await Glow.loadDms?.().catch(() => {}); await Glow.loadDms?.().catch(() => {});
@ -260,6 +249,8 @@ Glow.checkAuth = async () => {
Glow.updateViewUI(); Glow.updateViewUI();
await Glow.loadFeed(); await Glow.loadFeed();
await Glow.loadMySettings?.().catch(() => {}); await Glow.loadMySettings?.().catch(() => {});
Glow.calls?.scheduleInvitePolling?.();
} catch (error) { } catch (error) {
Glow.showToast(error.message || "Could not connect.", "error"); Glow.showToast(error.message || "Could not connect.", "error");
} finally { } finally {
@ -269,7 +260,6 @@ Glow.checkAuth = async () => {
Glow.authenticate = async endpoint => { Glow.authenticate = async endpoint => {
Glow.clearAuthNotice(); Glow.clearAuthNotice();
const username = Glow.els.usernameInput.value.trim().toLowerCase(); const username = Glow.els.usernameInput.value.trim().toLowerCase();
const password = Glow.els.passwordInput.value; const password = Glow.els.passwordInput.value;
@ -293,6 +283,7 @@ Glow.authenticate = async endpoint => {
Glow.els.passwordInput.value = ""; Glow.els.passwordInput.value = "";
Glow.updateAuthUI(); Glow.updateAuthUI();
await Glow.checkInvite(); await Glow.checkInvite();
await Glow.loadRooms(); await Glow.loadRooms();
await Glow.loadDms?.().catch(() => {}); await Glow.loadDms?.().catch(() => {});
@ -301,6 +292,7 @@ Glow.authenticate = async endpoint => {
Glow.updateViewUI(); Glow.updateViewUI();
await Glow.loadFeed(); await Glow.loadFeed();
await Glow.loadMySettings?.().catch(() => {}); await Glow.loadMySettings?.().catch(() => {});
Glow.calls?.scheduleInvitePolling?.();
Glow.showToast( Glow.showToast(
endpoint.endsWith("register") ? "Account created." : "Signed in." endpoint.endsWith("register") ? "Account created." : "Signed in."
@ -321,9 +313,7 @@ Glow.authenticate = async endpoint => {
Glow.logout = async () => { Glow.logout = async () => {
try { try {
await Glow.apiRequest("/api/logout", { method: "POST" }); await Glow.apiRequest("/api/logout", { method: "POST" });
} catch (_) { } catch (_) {}
// ignore
}
Glow.state.currentUser = null; Glow.state.currentUser = null;
Glow.state.csrfToken = ""; Glow.state.csrfToken = "";
@ -350,6 +340,8 @@ Glow.logout = async () => {
Glow.closeMediaModal?.(); Glow.closeMediaModal?.();
Glow.endLocalCallUi?.(); Glow.endLocalCallUi?.();
clearTimeout(Glow.state.calls?.invitePollTimer);
Glow.updateAuthUI(); Glow.updateAuthUI();
Glow.els.authOverlay.classList.remove("hidden"); Glow.els.authOverlay.classList.remove("hidden");
@ -369,7 +361,6 @@ Glow.toggleNotifications = async () => {
if (!Glow.state.notificationsEnabled) { if (!Glow.state.notificationsEnabled) {
const permission = await Notification.requestPermission(); const permission = await Notification.requestPermission();
if (permission !== "granted") { if (permission !== "granted") {
Glow.showToast("Notification permission was not granted.", "error"); Glow.showToast("Notification permission was not granted.", "error");
return; return;
@ -377,12 +368,10 @@ Glow.toggleNotifications = async () => {
} }
Glow.state.notificationsEnabled = !Glow.state.notificationsEnabled; Glow.state.notificationsEnabled = !Glow.state.notificationsEnabled;
localStorage.setItem( localStorage.setItem(
"glow_notifications_enabled", "glow_notifications_enabled",
String(Glow.state.notificationsEnabled) String(Glow.state.notificationsEnabled)
); );
Glow.updateAdminPreferenceButtons?.(); Glow.updateAdminPreferenceButtons?.();
Glow.showToast( Glow.showToast(
Glow.state.notificationsEnabled Glow.state.notificationsEnabled
@ -393,20 +382,16 @@ Glow.toggleNotifications = async () => {
Glow.toggleTypingIndicators = () => { Glow.toggleTypingIndicators = () => {
Glow.state.typingIndicatorsEnabled = !Glow.state.typingIndicatorsEnabled; Glow.state.typingIndicatorsEnabled = !Glow.state.typingIndicatorsEnabled;
localStorage.setItem( localStorage.setItem(
"glow_typing_enabled", "glow_typing_enabled",
String(Glow.state.typingIndicatorsEnabled) String(Glow.state.typingIndicatorsEnabled)
); );
if (!Glow.state.typingIndicatorsEnabled) { if (!Glow.state.typingIndicatorsEnabled) {
Glow.state.typingUsers = []; Glow.state.typingUsers = [];
Glow.state.dmTypingUsers = []; Glow.state.dmTypingUsers = [];
Glow.renderTyping(); Glow.renderTyping();
} }
Glow.updateAdminPreferenceButtons?.(); Glow.updateAdminPreferenceButtons?.();
Glow.showToast( Glow.showToast(
Glow.state.typingIndicatorsEnabled Glow.state.typingIndicatorsEnabled
? "Typing indicators enabled." ? "Typing indicators enabled."
@ -431,9 +416,7 @@ Glow.pingPresence = async () => {
try { try {
await Glow.apiPingPresence(payload); await Glow.apiPingPresence(payload);
} catch (_) { } catch (_) {}
// non-blocking
}
}; };
Glow.refreshPresence = async () => { Glow.refreshPresence = async () => {
@ -441,8 +424,7 @@ Glow.refreshPresence = async () => {
if (Glow.state.activeDm?.id) { if (Glow.state.activeDm?.id) {
const data = await Glow.apiGetDmPresence(Glow.state.activeDm.id); const data = await Glow.apiGetDmPresence(Glow.state.activeDm.id);
Glow.state.presence.dmOnlineCount = Number(data.online_count) || 0; Glow.state.presence.dmOnlineCount = Number(data.online_count) || 0;
Glow.els.presenceLabel.textContent = Glow.els.presenceLabel.textContent = `${Glow.state.presence.dmOnlineCount} online`;
`${Glow.state.presence.dmOnlineCount} online`;
Glow.els.presenceLabel.classList.remove("hidden"); Glow.els.presenceLabel.classList.remove("hidden");
return; return;
} }
@ -453,8 +435,7 @@ Glow.refreshPresence = async () => {
Glow.state.activeChannel.slug Glow.state.activeChannel.slug
); );
Glow.state.presence.channelOnlineCount = Number(data.online_count) || 0; Glow.state.presence.channelOnlineCount = Number(data.online_count) || 0;
Glow.els.presenceLabel.textContent = Glow.els.presenceLabel.textContent = `${Glow.state.presence.channelOnlineCount} online`;
`${Glow.state.presence.channelOnlineCount} online`;
Glow.els.presenceLabel.classList.remove("hidden"); Glow.els.presenceLabel.classList.remove("hidden");
return; return;
} }
@ -462,8 +443,7 @@ Glow.refreshPresence = async () => {
if (Glow.state.activeRoom?.slug) { if (Glow.state.activeRoom?.slug) {
const data = await Glow.apiGetRoomPresence(Glow.state.activeRoom.slug); const data = await Glow.apiGetRoomPresence(Glow.state.activeRoom.slug);
Glow.state.presence.roomOnlineCount = Number(data.online_count) || 0; Glow.state.presence.roomOnlineCount = Number(data.online_count) || 0;
Glow.els.presenceLabel.textContent = Glow.els.presenceLabel.textContent = `${Glow.state.presence.roomOnlineCount} online`;
`${Glow.state.presence.roomOnlineCount} online`;
Glow.els.presenceLabel.classList.remove("hidden"); Glow.els.presenceLabel.classList.remove("hidden");
return; return;
} }
@ -476,10 +456,7 @@ Glow.refreshPresence = async () => {
Glow.schedulePoll = () => { Glow.schedulePoll = () => {
clearTimeout(Glow.state.pollTimer); clearTimeout(Glow.state.pollTimer);
if (Glow.els.blockedOverlay.classList.contains("hidden") === false) return;
if (Glow.els.blockedOverlay.classList.contains("hidden") === false) {
return;
}
Glow.state.pollTimer = setTimeout(async () => { Glow.state.pollTimer = setTimeout(async () => {
if (Glow.state.activeView === "feed") { if (Glow.state.activeView === "feed") {
@ -500,26 +477,19 @@ Glow.schedulePoll = () => {
await Glow.pingPresence?.(); await Glow.pingPresence?.();
await Glow.refreshPresence?.(); await Glow.refreshPresence?.();
Glow.schedulePoll(); Glow.schedulePoll();
}, document.hidden ? 12000 : 5000); }, document.hidden ? 12000 : 5000);
}; };
Glow.els.chatForm.addEventListener("submit", Glow.sendMessage); Glow.els.chatForm.addEventListener("submit", Glow.sendMessage);
Glow.els.threadForm?.addEventListener("submit", event => Glow.sendThreadReply?.(event));
Glow.els.threadForm?.addEventListener("submit", event =>
Glow.sendThreadReply?.(event)
);
Glow.els.messageInput.addEventListener("input", () => { Glow.els.messageInput.addEventListener("input", () => {
Glow.autoResizeComposer(); Glow.autoResizeComposer();
Glow.updateMessageCount(); Glow.updateMessageCount();
clearTimeout(Glow.state.typingTimer); clearTimeout(Glow.state.typingTimer);
if (Glow.els.messageInput.value.trim()) { if (Glow.els.messageInput.value.trim()) {
Glow.sendTyping(true); Glow.sendTyping(true);
Glow.state.typingTimer = setTimeout(() => { Glow.state.typingTimer = setTimeout(() => {
Glow.sendTyping(false); Glow.sendTyping(false);
}, 2500); }, 2500);
@ -549,12 +519,10 @@ Glow.els.threadInput?.addEventListener("keydown", event => {
Glow.els.attachmentInput.addEventListener("change", () => { Glow.els.attachmentInput.addEventListener("change", () => {
const files = Glow.normalizeSelectedFiles(Glow.els.attachmentInput.files); const files = Glow.normalizeSelectedFiles(Glow.els.attachmentInput.files);
if (!files.length) { if (!files.length) {
Glow.setSelectedAttachment([]); Glow.setSelectedAttachment([]);
return; return;
} }
const invalid = files.find(file => file.size > Glow.MAX_ATTACHMENT_BYTES); const invalid = files.find(file => file.size > Glow.MAX_ATTACHMENT_BYTES);
if (invalid) { if (invalid) {
Glow.showToast("Attachments must be 5 MB or smaller.", "error"); Glow.showToast("Attachments must be 5 MB or smaller.", "error");
@ -562,18 +530,15 @@ Glow.els.attachmentInput.addEventListener("change", () => {
Glow.setSelectedAttachment([]); Glow.setSelectedAttachment([]);
return; return;
} }
Glow.setSelectedAttachment(files); Glow.setSelectedAttachment(files);
}); });
Glow.els.threadAttachmentInput?.addEventListener("change", () => { Glow.els.threadAttachmentInput?.addEventListener("change", () => {
const files = Glow.normalizeSelectedFiles(Glow.els.threadAttachmentInput.files); const files = Glow.normalizeSelectedFiles(Glow.els.threadAttachmentInput.files);
if (!files.length) { if (!files.length) {
Glow.setSelectedThreadAttachment?.([]); Glow.setSelectedThreadAttachment?.([]);
return; return;
} }
const invalid = files.find(file => file.size > Glow.MAX_ATTACHMENT_BYTES); const invalid = files.find(file => file.size > Glow.MAX_ATTACHMENT_BYTES);
if (invalid) { if (invalid) {
Glow.showToast("Attachments must be 5 MB or smaller.", "error"); Glow.showToast("Attachments must be 5 MB or smaller.", "error");
@ -581,7 +546,6 @@ Glow.els.threadAttachmentInput?.addEventListener("change", () => {
Glow.setSelectedThreadAttachment?.([]); Glow.setSelectedThreadAttachment?.([]);
return; return;
} }
Glow.setSelectedThreadAttachment?.(files); Glow.setSelectedThreadAttachment?.(files);
}); });
@ -633,18 +597,16 @@ Glow.els.roomSelect.addEventListener("change", async () => {
const selected = Glow.state.rooms.find( const selected = Glow.state.rooms.find(
room => room.slug === Glow.els.roomSelect.value room => room.slug === Glow.els.roomSelect.value
); );
if (!selected) return; if (!selected) return;
Glow.state.activeDm = null; Glow.state.activeDm = null;
Glow.state.activeRoom = selected; Glow.state.activeRoom = selected;
Glow.state.activeView = "room"; Glow.state.activeView = "room";
Glow.state.typingUsers = []; Glow.state.typingUsers = [];
Glow.state.dmTypingUsers = []; Glow.state.dmTypingUsers = [];
Glow.renderTyping(); Glow.renderTyping();
Glow.updateViewUI(); Glow.updateViewUI();
await Glow.loadMessages(); await Glow.loadMessages();
Glow.pollTyping(); Glow.pollTyping();
Glow.pingPresence?.(); Glow.pingPresence?.();
@ -654,7 +616,6 @@ Glow.els.roomSelect.addEventListener("change", async () => {
Glow.els.teamSelect?.addEventListener("change", () => { Glow.els.teamSelect?.addEventListener("change", () => {
const teams = Glow.state.teams || []; const teams = Glow.state.teams || [];
Glow.state.activeTeam = Glow.state.activeTeam =
teams.find(team => team.slug === Glow.els.teamSelect.value) || null; teams.find(team => team.slug === Glow.els.teamSelect.value) || null;
}); });
@ -776,6 +737,7 @@ document.addEventListener("keydown", event => {
document.addEventListener("visibilitychange", () => { document.addEventListener("visibilitychange", () => {
Glow.schedulePoll(); Glow.schedulePoll();
Glow.calls?.scheduleInvitePolling?.();
if (!document.hidden) { if (!document.hidden) {
Glow.resetUnreadMessages(); Glow.resetUnreadMessages();
@ -824,6 +786,7 @@ window.addEventListener("online", () => {
Glow.pingPresence?.(); Glow.pingPresence?.();
Glow.refreshPresence?.(); Glow.refreshPresence?.();
Glow.calls?.scheduleInvitePolling?.();
}); });
window.addEventListener("offline", () => { window.addEventListener("offline", () => {
@ -856,4 +819,4 @@ Glow.autoResizeComposer();
Glow.updateMessageCount(); Glow.updateMessageCount();
Glow.autoResizeThreadComposer?.(); Glow.autoResizeThreadComposer?.();
Glow.updateThreadMessageCount?.(); Glow.updateThreadMessageCount?.();
Glow.checkAuth(); Glow.checkAuth();