Update static/js/04-main.js
This commit is contained in:
parent
18f2670519
commit
8a3358aec7
@ -2,36 +2,13 @@
|
||||
"use strict";
|
||||
window.Glow = window.Glow || {};
|
||||
|
||||
Glow.presenceModeLabel = mode => {
|
||||
switch (String(mode || "").toLowerCase()) {
|
||||
case "silent":
|
||||
return "silent";
|
||||
case "focus":
|
||||
return "focus";
|
||||
case "dnd":
|
||||
return "do not disturb";
|
||||
default:
|
||||
return "online";
|
||||
}
|
||||
};
|
||||
|
||||
const originalUpdateAuthUI = Glow.updateAuthUI;
|
||||
Glow.updateAuthUI = () => {
|
||||
if (typeof originalUpdateAuthUI === "function") {
|
||||
originalUpdateAuthUI();
|
||||
}
|
||||
const user = Glow.state.currentUser;
|
||||
if (user && Glow.els.headerAccount) {
|
||||
const mode = Glow.presenceModeLabel(user.presence_mode);
|
||||
Glow.els.headerAccount.textContent = `${user.username} · ${user.role} · ${mode}`;
|
||||
}
|
||||
};
|
||||
|
||||
Glow.loadRooms = async () => {
|
||||
const previousSlug = Glow.state.activeRoom?.slug;
|
||||
const data = await Glow.apiRequest("/api/rooms");
|
||||
|
||||
Glow.state.rooms = data.rooms || [];
|
||||
Glow.els.roomSelect.replaceChildren();
|
||||
|
||||
for (const room of Glow.state.rooms) {
|
||||
const option = document.createElement("option");
|
||||
option.value = room.slug;
|
||||
@ -39,61 +16,20 @@ Glow.loadRooms = async () => {
|
||||
`${room.name}${room.visibility === "private" ? " (private)" : ""}`;
|
||||
Glow.els.roomSelect.append(option);
|
||||
}
|
||||
|
||||
Glow.els.roomSelect.disabled = !Glow.state.rooms.length;
|
||||
|
||||
const selected =
|
||||
Glow.state.rooms.find(room => room.slug === previousSlug) ||
|
||||
Glow.state.rooms.find(room => room.slug === "general") ||
|
||||
Glow.state.rooms[0] ||
|
||||
null;
|
||||
|
||||
Glow.state.activeRoom = selected;
|
||||
Glow.updateViewUI();
|
||||
Glow.updateChatControls();
|
||||
};
|
||||
|
||||
Glow.renderEmojiAutocomplete = (input, query) => {
|
||||
const box = Glow.els.emojiAutocomplete;
|
||||
if (!box || !input) return;
|
||||
const value = String(query || "").toLowerCase();
|
||||
const entries = Object.entries(Glow.EMOJI_ALIASES)
|
||||
.filter(([alias]) => alias.includes(value))
|
||||
.slice(0, 8);
|
||||
Glow.state.emojiSuggestions = entries;
|
||||
if (!entries.length) {
|
||||
box.classList.add("hidden");
|
||||
box.replaceChildren();
|
||||
return;
|
||||
}
|
||||
box.replaceChildren();
|
||||
for (const [alias, emoji] of entries) {
|
||||
const button = document.createElement("button");
|
||||
button.className = "emoji-suggestion";
|
||||
button.type = "button";
|
||||
button.textContent = `${emoji} ::${alias}`;
|
||||
button.addEventListener("click", () => {
|
||||
const target = Glow.state.emojiActiveInput || input;
|
||||
const current = target.value;
|
||||
const replaced = current.replace(/::([a-z0-9_+-]*)$/i, `${emoji} `);
|
||||
target.value = replaced;
|
||||
target.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
box.classList.add("hidden");
|
||||
target.focus();
|
||||
});
|
||||
box.append(button);
|
||||
}
|
||||
Glow.state.emojiActiveInput = input;
|
||||
box.classList.remove("hidden");
|
||||
};
|
||||
|
||||
Glow.maybeShowEmojiAutocomplete = input => {
|
||||
const text = String(input?.value || "");
|
||||
const match = text.match(/::([a-z0-9_+-]*)$/i);
|
||||
if (!match) {
|
||||
Glow.els.emojiAutocomplete?.classList.add("hidden");
|
||||
return;
|
||||
}
|
||||
Glow.renderEmojiAutocomplete(input, match[1]);
|
||||
};
|
||||
|
||||
Glow.updateViewUI = () => {
|
||||
const view = Glow.state.activeView || "feed";
|
||||
const room = Glow.state.activeRoom;
|
||||
@ -106,6 +42,7 @@ Glow.updateViewUI = () => {
|
||||
const pageActive = view === "page";
|
||||
const profileActive = view === "profile";
|
||||
const settingsActive = view === "settings";
|
||||
|
||||
Glow.els.feedBox.classList.toggle("hidden", !feedActive);
|
||||
Glow.els.dmBox?.classList.toggle("hidden", !dmListActive);
|
||||
Glow.els.chatBox.classList.toggle("hidden", !chatActive);
|
||||
@ -115,6 +52,7 @@ Glow.updateViewUI = () => {
|
||||
Glow.els.profileBox?.classList.toggle("hidden", !(profileActive || settingsActive));
|
||||
Glow.els.composerWrap.classList.toggle("hidden", !chatActive);
|
||||
Glow.els.threadComposerWrap?.classList.toggle("hidden", !threadActive);
|
||||
|
||||
if (!chatActive) {
|
||||
Glow.state.typingUsers = [];
|
||||
Glow.state.dmTypingUsers = [];
|
||||
@ -123,19 +61,25 @@ Glow.updateViewUI = () => {
|
||||
Glow.els.typingBar.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
Glow.els.feedButton.classList.toggle("active", feedActive);
|
||||
Glow.els.feedButton.setAttribute("aria-pressed", String(feedActive));
|
||||
|
||||
Glow.els.pagesButton?.classList.toggle("active", pagesActive || pageActive);
|
||||
Glow.els.pagesButton?.setAttribute("aria-pressed", String(pagesActive || pageActive));
|
||||
|
||||
Glow.els.dmsButton?.classList.toggle("active", dmListActive || view === "dm");
|
||||
Glow.els.dmsButton?.setAttribute("aria-pressed", String(dmListActive || view === "dm"));
|
||||
|
||||
Glow.els.backButton?.classList.toggle(
|
||||
"hidden",
|
||||
!(threadActive || pageActive || profileActive || settingsActive || view === "dm")
|
||||
);
|
||||
|
||||
Glow.els.roomSelect.classList.toggle("active", chatActive && !dm);
|
||||
Glow.els.teamSelect?.classList.toggle("hidden", dmListActive || view === "dm");
|
||||
Glow.els.roomSelect?.classList.toggle("hidden", dmListActive || view === "dm");
|
||||
|
||||
if (feedActive) {
|
||||
Glow.els.headerTitle.textContent = "Feed";
|
||||
Glow.els.headerSubtitle.textContent = Glow.state.currentUser
|
||||
@ -143,35 +87,45 @@ Glow.updateViewUI = () => {
|
||||
: "Sign in or create an account to personalize your feed";
|
||||
Glow.els.roomSelect.disabled = !Glow.state.rooms.length;
|
||||
Glow.els.presenceLabel?.classList.add("hidden");
|
||||
Glow.calls?.renderHeaderCallChip?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (dmListActive) {
|
||||
Glow.els.headerTitle.textContent = "Direct messages";
|
||||
Glow.els.headerSubtitle.textContent = Glow.state.currentUser
|
||||
? "Private conversations"
|
||||
: "Sign in to open private conversations";
|
||||
Glow.els.presenceLabel?.classList.add("hidden");
|
||||
Glow.calls?.renderHeaderCallChip?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (threadActive) {
|
||||
Glow.els.headerTitle.textContent = "Thread";
|
||||
Glow.els.headerSubtitle.textContent =
|
||||
dm ? "Direct message replies" : room?.name || "Conversation replies";
|
||||
Glow.updateThreadControls?.();
|
||||
Glow.calls?.renderHeaderCallChip?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (pagesActive) {
|
||||
Glow.els.headerTitle.textContent = "Pages";
|
||||
Glow.els.headerSubtitle.textContent = "Shared knowledge and resources";
|
||||
Glow.els.presenceLabel?.classList.add("hidden");
|
||||
Glow.calls?.renderHeaderCallChip?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (pageActive) {
|
||||
Glow.els.headerTitle.textContent = Glow.state.activePage?.title || "Page";
|
||||
Glow.els.headerSubtitle.textContent = "Shared knowledge and resources";
|
||||
Glow.els.presenceLabel?.classList.add("hidden");
|
||||
Glow.calls?.renderHeaderCallChip?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (profileActive) {
|
||||
Glow.els.headerTitle.textContent =
|
||||
Glow.state.activeProfile?.display_name ||
|
||||
@ -179,29 +133,33 @@ Glow.updateViewUI = () => {
|
||||
"Profile";
|
||||
Glow.els.headerSubtitle.textContent = "User profile";
|
||||
Glow.els.presenceLabel?.classList.add("hidden");
|
||||
Glow.calls?.renderHeaderCallChip?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (settingsActive) {
|
||||
Glow.els.headerTitle.textContent = "Settings";
|
||||
Glow.els.headerSubtitle.textContent = "Appearance, profile, and preferences";
|
||||
Glow.els.presenceLabel?.classList.add("hidden");
|
||||
Glow.calls?.renderHeaderCallChip?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (view === "dm" && dm) {
|
||||
const peer =
|
||||
(dm.members || []).find(
|
||||
member => Number(member.id) !== Number(Glow.state.currentUser?.id)
|
||||
) ||
|
||||
dm.other_user ||
|
||||
dm.members?.[0];
|
||||
) || dm.members?.[0];
|
||||
Glow.els.headerTitle.textContent =
|
||||
peer?.display_name || peer?.username || "Direct message";
|
||||
Glow.els.headerSubtitle.textContent =
|
||||
peer?.username ? `@${peer.username}` : "Private conversation";
|
||||
Glow.refreshPresence?.();
|
||||
Glow.updateChatControls();
|
||||
Glow.calls?.renderHeaderCallChip?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (room) {
|
||||
Glow.els.headerTitle.textContent = room.name;
|
||||
Glow.els.headerSubtitle.textContent =
|
||||
@ -212,24 +170,33 @@ Glow.updateViewUI = () => {
|
||||
Glow.els.headerTitle.textContent = "No rooms";
|
||||
Glow.els.headerSubtitle.textContent = "No accessible chat rooms";
|
||||
}
|
||||
|
||||
Glow.updateChatControls();
|
||||
Glow.calls?.renderHeaderCallChip?.();
|
||||
};
|
||||
|
||||
Glow.updateAuthUI = () => {
|
||||
const user = Glow.state.currentUser;
|
||||
const authenticated = Boolean(user);
|
||||
|
||||
Glow.els.authOverlay.classList.toggle("hidden", authenticated);
|
||||
Glow.els.logoutButton.classList.toggle("hidden", !authenticated);
|
||||
|
||||
Glow.els.headerAccount.textContent =
|
||||
user ? `${user.username} · ${user.role}` : "not signed in";
|
||||
|
||||
document.body.classList.toggle("is-moderator", Glow.canModerate());
|
||||
document.body.classList.toggle("is-admin", Glow.isAdmin());
|
||||
|
||||
Glow.els.adminFab.classList.toggle("visible", Glow.canModerate());
|
||||
|
||||
Glow.els.presenceDot.classList.toggle("online", authenticated);
|
||||
Glow.els.presenceDot.classList.toggle("new", Boolean(user?.status === "restricted"));
|
||||
|
||||
if (user?.status === "restricted") {
|
||||
Glow.showToast("Your account is temporarily restricted.", "error");
|
||||
}
|
||||
|
||||
Glow.updateViewUI();
|
||||
Glow.updateChatControls();
|
||||
Glow.updateThreadControls?.();
|
||||
@ -240,6 +207,7 @@ Glow.checkInvite = async () => {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const roomToken = params.get("invite");
|
||||
const teamToken = params.get("team_invite");
|
||||
|
||||
if (roomToken) {
|
||||
try {
|
||||
const data = await Glow.apiRequest(
|
||||
@ -259,6 +227,7 @@ Glow.checkInvite = async () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (teamToken) {
|
||||
try {
|
||||
const data = await Glow.apiAcceptTeamInvite(teamToken);
|
||||
@ -278,14 +247,18 @@ Glow.checkAuth = async () => {
|
||||
const data = await Glow.apiRequest("/api/me");
|
||||
Glow.state.currentUser = data.authenticated ? data.user : null;
|
||||
Glow.state.csrfToken = data.csrf_token || "";
|
||||
|
||||
Glow.updateAuthUI();
|
||||
|
||||
await Glow.checkInvite();
|
||||
await Glow.loadRooms();
|
||||
await Glow.loadDms?.().catch(() => {});
|
||||
|
||||
Glow.state.activeView = "feed";
|
||||
Glow.updateViewUI();
|
||||
await Glow.loadFeed();
|
||||
await Glow.loadMySettings?.().catch(() => {});
|
||||
|
||||
Glow.calls?.scheduleInvitePolling?.();
|
||||
} catch (error) {
|
||||
Glow.showToast(error.message || "Could not connect.", "error");
|
||||
@ -299,30 +272,38 @@ Glow.authenticate = async endpoint => {
|
||||
const accessKey = Glow.els.accessKeyInput.value;
|
||||
const username = Glow.els.usernameInput.value.trim().toLowerCase();
|
||||
const password = Glow.els.passwordInput.value;
|
||||
|
||||
if (!accessKey || !username || !password) {
|
||||
Glow.showAuthNotice("Enter the private access key, username, and password.");
|
||||
return;
|
||||
}
|
||||
|
||||
Glow.els.loginButton.disabled = true;
|
||||
Glow.els.registerButton.disabled = true;
|
||||
|
||||
try {
|
||||
const data = await Glow.apiRequest(endpoint, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ access_key: accessKey, username, password })
|
||||
});
|
||||
|
||||
Glow.state.currentUser = data.user;
|
||||
Glow.state.csrfToken = data.csrf_token || "";
|
||||
Glow.els.passwordInput.value = "";
|
||||
|
||||
Glow.updateAuthUI();
|
||||
|
||||
await Glow.checkInvite();
|
||||
await Glow.loadRooms();
|
||||
await Glow.loadDms?.().catch(() => {});
|
||||
|
||||
Glow.state.activeView = "feed";
|
||||
Glow.updateViewUI();
|
||||
await Glow.loadFeed();
|
||||
await Glow.loadMySettings?.().catch(() => {});
|
||||
Glow.calls?.scheduleInvitePolling?.();
|
||||
|
||||
Glow.showToast(
|
||||
endpoint.endsWith("register") ? "Account created." : "Signed in."
|
||||
);
|
||||
@ -340,9 +321,28 @@ Glow.authenticate = async endpoint => {
|
||||
};
|
||||
|
||||
Glow.logout = async () => {
|
||||
if (Glow.state.calls.activeCall?.groupSession?.id) {
|
||||
const values = await Glow.openDialog({
|
||||
title: "Leave active call and sign out?",
|
||||
body: "You are currently in a voice call. Signing out will disconnect you from the call.",
|
||||
confirmText: "Leave and sign out",
|
||||
cancelText: "Stay signed in",
|
||||
danger: true
|
||||
});
|
||||
|
||||
if (!values) return;
|
||||
}
|
||||
|
||||
try {
|
||||
await Glow.apiRequest("/api/logout", { method: "POST" });
|
||||
} catch (_) {}
|
||||
|
||||
if (Glow.state.calls.activeCall?.groupSession?.id) {
|
||||
try {
|
||||
await Glow.apiLeaveGroupCall(Glow.state.calls.activeCall.groupSession.id);
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
Glow.state.currentUser = null;
|
||||
Glow.state.csrfToken = "";
|
||||
Glow.state.rooms = [];
|
||||
@ -359,6 +359,7 @@ Glow.logout = async () => {
|
||||
Glow.state.activePage = null;
|
||||
Glow.state.activeProfile = null;
|
||||
Glow.state.settings = null;
|
||||
|
||||
Glow.clearMessages();
|
||||
Glow.clearFeed();
|
||||
Glow.clearDms();
|
||||
@ -366,12 +367,19 @@ Glow.logout = async () => {
|
||||
Glow.closeReactionPopup?.();
|
||||
Glow.closeMediaModal?.();
|
||||
Glow.endLocalCallUi?.();
|
||||
|
||||
clearTimeout(Glow.state.calls?.invitePollTimer);
|
||||
clearTimeout(Glow.state.calls?.participantPollTimer);
|
||||
clearTimeout(Glow.state.calls?.heartbeatTimer);
|
||||
|
||||
Glow.updateAuthUI();
|
||||
|
||||
Glow.els.authOverlay.classList.remove("hidden");
|
||||
Glow.els.accessKeyInput.focus();
|
||||
|
||||
await Glow.refreshCsrfToken().catch(() => {});
|
||||
await Glow.loadFeed().catch(() => {});
|
||||
|
||||
Glow.showToast("Signed out.");
|
||||
};
|
||||
|
||||
@ -380,6 +388,7 @@ Glow.toggleNotifications = async () => {
|
||||
Glow.showToast("Browser notifications are not supported.", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Glow.state.notificationsEnabled) {
|
||||
const permission = await Notification.requestPermission();
|
||||
if (permission !== "granted") {
|
||||
@ -387,6 +396,7 @@ Glow.toggleNotifications = async () => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Glow.state.notificationsEnabled = !Glow.state.notificationsEnabled;
|
||||
localStorage.setItem(
|
||||
"glow_notifications_enabled",
|
||||
@ -421,9 +431,11 @@ Glow.toggleTypingIndicators = () => {
|
||||
|
||||
Glow.pingPresence = async () => {
|
||||
if (!Glow.state.currentUser) return;
|
||||
|
||||
const payload = {
|
||||
view: Glow.state.activeView
|
||||
};
|
||||
|
||||
if (Glow.state.activeDm?.id) {
|
||||
payload.dm_id = Glow.state.activeDm.id;
|
||||
} else if (Glow.state.activeChannel?.id) {
|
||||
@ -431,6 +443,7 @@ Glow.pingPresence = async () => {
|
||||
} else if (Glow.state.activeRoom?.id) {
|
||||
payload.room_id = Glow.state.activeRoom.id;
|
||||
}
|
||||
|
||||
try {
|
||||
await Glow.apiPingPresence(payload);
|
||||
} catch (_) {}
|
||||
@ -445,6 +458,7 @@ Glow.refreshPresence = async () => {
|
||||
Glow.els.presenceLabel.classList.remove("hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Glow.state.activeTeam?.slug && Glow.state.activeChannel?.slug) {
|
||||
const data = await Glow.apiGetChannelPresence(
|
||||
Glow.state.activeTeam.slug,
|
||||
@ -455,6 +469,7 @@ Glow.refreshPresence = async () => {
|
||||
Glow.els.presenceLabel.classList.remove("hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Glow.state.activeRoom?.slug) {
|
||||
const data = await Glow.apiGetRoomPresence(Glow.state.activeRoom.slug);
|
||||
Glow.state.presence.roomOnlineCount = Number(data.online_count) || 0;
|
||||
@ -462,6 +477,7 @@ Glow.refreshPresence = async () => {
|
||||
Glow.els.presenceLabel.classList.remove("hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
Glow.els.presenceLabel.classList.add("hidden");
|
||||
} catch (_) {
|
||||
Glow.els.presenceLabel?.classList.add("hidden");
|
||||
@ -471,6 +487,7 @@ Glow.refreshPresence = async () => {
|
||||
Glow.schedulePoll = () => {
|
||||
clearTimeout(Glow.state.pollTimer);
|
||||
if (Glow.els.blockedOverlay.classList.contains("hidden") === false) return;
|
||||
|
||||
Glow.state.pollTimer = setTimeout(async () => {
|
||||
if (Glow.state.activeView === "feed") {
|
||||
await Glow.pollFeed();
|
||||
@ -480,13 +497,12 @@ Glow.schedulePoll = () => {
|
||||
Glow.state.activeView === "dm"
|
||||
) {
|
||||
await Glow.pollMessages();
|
||||
await Glow.pollCallSignals?.();
|
||||
} else if (Glow.state.activeView === "thread") {
|
||||
await Glow.pollThread?.();
|
||||
await Glow.pollCallSignals?.();
|
||||
} else if (Glow.state.activeView === "dms") {
|
||||
await Glow.loadDms?.().catch(() => {});
|
||||
}
|
||||
|
||||
await Glow.pingPresence?.();
|
||||
await Glow.refreshPresence?.();
|
||||
Glow.schedulePoll();
|
||||
@ -495,10 +511,10 @@ Glow.schedulePoll = () => {
|
||||
|
||||
Glow.els.chatForm.addEventListener("submit", Glow.sendMessage);
|
||||
Glow.els.threadForm?.addEventListener("submit", event => Glow.sendThreadReply?.(event));
|
||||
|
||||
Glow.els.messageInput.addEventListener("input", () => {
|
||||
Glow.autoResizeComposer();
|
||||
Glow.updateMessageCount();
|
||||
Glow.maybeShowEmojiAutocomplete?.(Glow.els.messageInput);
|
||||
clearTimeout(Glow.state.typingTimer);
|
||||
if (Glow.els.messageInput.value.trim()) {
|
||||
Glow.sendTyping(true);
|
||||
@ -509,23 +525,26 @@ Glow.els.messageInput.addEventListener("input", () => {
|
||||
Glow.sendTyping(false);
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.threadInput?.addEventListener("input", () => {
|
||||
Glow.autoResizeThreadComposer?.();
|
||||
Glow.updateThreadMessageCount?.();
|
||||
Glow.maybeShowEmojiAutocomplete?.(Glow.els.threadInput);
|
||||
});
|
||||
|
||||
Glow.els.messageInput.addEventListener("keydown", event => {
|
||||
if (event.key === "Enter" && !event.shiftKey) {
|
||||
event.preventDefault();
|
||||
Glow.sendMessage(event);
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.threadInput?.addEventListener("keydown", event => {
|
||||
if (event.key === "Enter" && !event.shiftKey) {
|
||||
event.preventDefault();
|
||||
Glow.sendThreadReply?.(event);
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.attachmentInput.addEventListener("change", () => {
|
||||
const files = Glow.normalizeSelectedFiles(Glow.els.attachmentInput.files);
|
||||
if (!files.length) {
|
||||
@ -541,6 +560,7 @@ Glow.els.attachmentInput.addEventListener("change", () => {
|
||||
}
|
||||
Glow.setSelectedAttachment(files);
|
||||
});
|
||||
|
||||
Glow.els.threadAttachmentInput?.addEventListener("change", () => {
|
||||
const files = Glow.normalizeSelectedFiles(Glow.els.threadAttachmentInput.files);
|
||||
if (!files.length) {
|
||||
@ -556,16 +576,20 @@ Glow.els.threadAttachmentInput?.addEventListener("change", () => {
|
||||
}
|
||||
Glow.setSelectedThreadAttachment?.(files);
|
||||
});
|
||||
|
||||
Glow.els.feedButton.addEventListener("click", Glow.openFeed);
|
||||
|
||||
Glow.els.dmsButton?.addEventListener("click", async () => {
|
||||
Glow.state.activeView = "dms";
|
||||
Glow.updateViewUI();
|
||||
await Glow.loadDms?.();
|
||||
Glow.schedulePoll();
|
||||
});
|
||||
|
||||
Glow.els.pagesButton?.addEventListener("click", () => {
|
||||
Glow.openPages?.();
|
||||
});
|
||||
|
||||
Glow.els.backButton?.addEventListener("click", async () => {
|
||||
if (Glow.state.activeView === "thread") {
|
||||
await Glow.returnToChannel?.();
|
||||
@ -579,24 +603,30 @@ Glow.els.backButton?.addEventListener("click", async () => {
|
||||
await Glow.loadDms?.();
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.loginButton.addEventListener("click", () => {
|
||||
Glow.authenticate("/api/login");
|
||||
});
|
||||
|
||||
Glow.els.registerButton.addEventListener("click", () => {
|
||||
Glow.authenticate("/api/register");
|
||||
});
|
||||
|
||||
Glow.els.passwordInput.addEventListener("keydown", event => {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
Glow.authenticate("/api/login");
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.logoutButton.addEventListener("click", Glow.logout);
|
||||
|
||||
Glow.els.roomSelect.addEventListener("change", async () => {
|
||||
const selected = Glow.state.rooms.find(
|
||||
room => room.slug === Glow.els.roomSelect.value
|
||||
);
|
||||
if (!selected) return;
|
||||
|
||||
Glow.state.activeDm = null;
|
||||
Glow.state.activeRoom = selected;
|
||||
Glow.state.activeView = "room";
|
||||
@ -604,17 +634,20 @@ Glow.els.roomSelect.addEventListener("change", async () => {
|
||||
Glow.state.dmTypingUsers = [];
|
||||
Glow.renderTyping();
|
||||
Glow.updateViewUI();
|
||||
|
||||
await Glow.loadMessages();
|
||||
Glow.pollTyping();
|
||||
Glow.pingPresence?.();
|
||||
Glow.refreshPresence?.();
|
||||
Glow.schedulePoll();
|
||||
});
|
||||
|
||||
Glow.els.teamSelect?.addEventListener("change", () => {
|
||||
const teams = Glow.state.teams || [];
|
||||
Glow.state.activeTeam =
|
||||
teams.find(team => team.slug === Glow.els.teamSelect.value) || null;
|
||||
});
|
||||
|
||||
Glow.els.adminFab.addEventListener("click", Glow.openAdminPanel);
|
||||
Glow.els.closeAdminButton.addEventListener("click", Glow.closeAdminPanel);
|
||||
Glow.els.createRoomButton.addEventListener("click", Glow.createRoom);
|
||||
@ -622,99 +655,125 @@ Glow.els.clearMessagesButton.addEventListener("click", Glow.clearActiveRoom);
|
||||
Glow.els.typingToggleButton.addEventListener("click", Glow.toggleTypingIndicators);
|
||||
Glow.els.notificationsToggleButton.addEventListener("click", Glow.toggleNotifications);
|
||||
Glow.els.themeButton?.addEventListener("click", Glow.openAccentColorPicker);
|
||||
|
||||
Glow.els.settingsButton?.addEventListener("click", () => {
|
||||
Glow.toggleHeaderMenu?.();
|
||||
});
|
||||
|
||||
Glow.els.callStatusChip?.addEventListener("click", () => {
|
||||
Glow.openCallPanel?.();
|
||||
});
|
||||
|
||||
Glow.els.jumpToLatestButton.addEventListener("click", () => {
|
||||
Glow.els.chatBox.scrollTop = Glow.els.chatBox.scrollHeight;
|
||||
Glow.resetUnreadMessages();
|
||||
});
|
||||
|
||||
Glow.els.chatBox.addEventListener("scroll", () => {
|
||||
if (Glow.isNearBottom()) {
|
||||
Glow.resetUnreadMessages();
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.adminPanel.addEventListener("click", event => {
|
||||
if (event.target === Glow.els.adminPanel) {
|
||||
Glow.closeAdminPanel();
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.dialogOverlay.addEventListener("click", event => {
|
||||
if (event.target === Glow.els.dialogOverlay) {
|
||||
Glow.closeDialog(null);
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.headerMenuOverlay?.addEventListener("click", event => {
|
||||
if (event.target === Glow.els.headerMenuOverlay) {
|
||||
Glow.closeHeaderMenu?.();
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.closeReactionPopupButton?.addEventListener("click", () => {
|
||||
Glow.closeReactionPopup?.();
|
||||
});
|
||||
|
||||
Glow.els.reactionPopupOverlay?.addEventListener("click", event => {
|
||||
if (event.target === Glow.els.reactionPopupOverlay) {
|
||||
Glow.closeReactionPopup?.();
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.closeMediaButton?.addEventListener("click", () => {
|
||||
Glow.closeMediaModal?.();
|
||||
});
|
||||
|
||||
Glow.els.mediaOverlay?.addEventListener("click", event => {
|
||||
if (event.target === Glow.els.mediaOverlay) {
|
||||
Glow.closeMediaModal?.();
|
||||
}
|
||||
});
|
||||
|
||||
Glow.els.closeCallPanelButton?.addEventListener("click", () => {
|
||||
Glow.els.callOverlay?.classList.add("hidden");
|
||||
});
|
||||
|
||||
document.addEventListener("keydown", event => {
|
||||
if (event.key === "Escape") {
|
||||
if (event.key !== "Escape") return;
|
||||
|
||||
if (!Glow.els.dialogOverlay.classList.contains("hidden")) {
|
||||
Glow.closeDialog(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Glow.els.mediaOverlay?.classList.contains("hidden")) {
|
||||
Glow.closeMediaModal?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Glow.els.reactionPopupOverlay?.classList.contains("hidden")) {
|
||||
Glow.closeReactionPopup?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Glow.els.headerMenuOverlay?.classList.contains("hidden")) {
|
||||
Glow.closeHeaderMenu?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Glow.els.callOverlay?.classList.contains("hidden")) {
|
||||
Glow.els.callOverlay.classList.add("hidden");
|
||||
return;
|
||||
}
|
||||
Glow.els.emojiAutocomplete?.classList.add("hidden");
|
||||
|
||||
if (Glow.state.activeView === "thread") {
|
||||
Glow.returnToChannel?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Glow.state.activeView === "page") {
|
||||
Glow.openPages?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Glow.state.activeView === "dm") {
|
||||
Glow.state.activeView = "dms";
|
||||
Glow.updateViewUI();
|
||||
Glow.loadDms?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Glow.els.adminPanel.classList.contains("open")) {
|
||||
Glow.closeAdminPanel();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
Glow.schedulePoll();
|
||||
Glow.calls?.scheduleInvitePolling?.();
|
||||
|
||||
if (!document.hidden) {
|
||||
Glow.resetUnreadMessages();
|
||||
|
||||
if (Glow.state.activeView === "feed") {
|
||||
Glow.pollFeed();
|
||||
} else if (
|
||||
@ -724,19 +783,20 @@ document.addEventListener("visibilitychange", () => {
|
||||
) {
|
||||
Glow.pollMessages();
|
||||
Glow.pollTyping();
|
||||
Glow.pollCallSignals?.();
|
||||
} else if (Glow.state.activeView === "thread") {
|
||||
Glow.pollThread?.();
|
||||
Glow.pollCallSignals?.();
|
||||
} else if (Glow.state.activeView === "dms") {
|
||||
Glow.loadDms?.();
|
||||
}
|
||||
|
||||
Glow.pingPresence?.();
|
||||
Glow.refreshPresence?.();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("online", () => {
|
||||
Glow.showToast("Back online.");
|
||||
|
||||
if (Glow.state.activeView === "feed") {
|
||||
Glow.pollFeed();
|
||||
} else if (
|
||||
@ -746,20 +806,21 @@ window.addEventListener("online", () => {
|
||||
) {
|
||||
Glow.pollMessages();
|
||||
Glow.pollTyping();
|
||||
Glow.pollCallSignals?.();
|
||||
} else if (Glow.state.activeView === "thread") {
|
||||
Glow.pollThread?.();
|
||||
Glow.pollCallSignals?.();
|
||||
} else if (Glow.state.activeView === "dms") {
|
||||
Glow.loadDms?.();
|
||||
}
|
||||
|
||||
Glow.pingPresence?.();
|
||||
Glow.refreshPresence?.();
|
||||
Glow.calls?.scheduleInvitePolling?.();
|
||||
});
|
||||
|
||||
window.addEventListener("offline", () => {
|
||||
Glow.showToast("You are offline.", "error");
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
if (
|
||||
Glow.state.activeView === "room" ||
|
||||
@ -769,6 +830,7 @@ setInterval(() => {
|
||||
Glow.pollTyping();
|
||||
}
|
||||
}, 2500);
|
||||
|
||||
setInterval(() => {
|
||||
if (
|
||||
Glow.state.activeView === "room" ||
|
||||
@ -779,6 +841,34 @@ setInterval(() => {
|
||||
Glow.refreshPresence?.();
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
window.addEventListener("beforeunload", () => {
|
||||
const sessionId = Glow.state.calls.activeCall?.groupSession?.id;
|
||||
if (!sessionId || !navigator.sendBeacon) return;
|
||||
|
||||
const csrf = Glow.state.csrfToken || "";
|
||||
const blob = new Blob([JSON.stringify({})], {
|
||||
type: "application/json"
|
||||
});
|
||||
|
||||
navigator.sendBeacon(
|
||||
`/api/group-calls/${encodeURIComponent(sessionId)}/leave`,
|
||||
blob
|
||||
);
|
||||
|
||||
fetch(`/api/group-calls/${encodeURIComponent(sessionId)}/leave`, {
|
||||
method: "POST",
|
||||
credentials: "same-origin",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-CSRF-Token": csrf,
|
||||
Accept: "application/json"
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
keepalive: true
|
||||
}).catch(() => {});
|
||||
});
|
||||
|
||||
Glow.applyAccentColor(Glow.state.accentColor);
|
||||
Glow.autoResizeComposer();
|
||||
Glow.updateMessageCount();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user