From d6e2ebf750cd16d07842d9d1fb53d653c40b3962 Mon Sep 17 00:00:00 2001 From: dev Date: Sat, 31 Oct 2026 08:52:14 +0000 Subject: [PATCH] Update static/js/05-feed.js --- static/js/05-feed.js | 176 +++++++++++++++++++------------------------ 1 file changed, 79 insertions(+), 97 deletions(-) diff --git a/static/js/05-feed.js b/static/js/05-feed.js index 47f0f7e..5399040 100644 --- a/static/js/05-feed.js +++ b/static/js/05-feed.js @@ -99,14 +99,36 @@ Glow.openFeedEntry = async entry => { Glow.showToast("This conversation is no longer available.", "error"); }; +Glow.feedAttachmentSummary = entry => { + const attachments = Array.isArray(entry.attachments) + ? entry.attachments + : entry.attachment + ? [entry.attachment] + : []; + + if (!attachments.length) return ""; + + if (attachments.length > 1) { + return `${attachments.length} attachments`; + } + + const item = attachments[0]; + const mime = String(item?.mime_type || "").toLowerCase(); + + if (mime.startsWith("image/")) return "image attachment"; + if (mime.startsWith("audio/")) return "audio attachment"; + if (mime.startsWith("video/")) return "video attachment"; + return "file attachment"; +}; + Glow.buildFeedReactions = entry => { const reactions = Array.isArray(entry.reactions) ? entry.reactions : []; if (!reactions.length) return null; const row = document.createElement("div"); - row.className = "feed-entry-reactions"; + row.className = "feed-entry-reactions compact"; - for (const reaction of reactions) { + for (const reaction of reactions.slice(0, 6)) { const chip = document.createElement("button"); chip.className = "reaction-chip"; chip.type = "button"; @@ -136,97 +158,35 @@ Glow.buildFeedReactions = entry => { return row; }; -Glow.buildFeedAttachmentBlock = entry => { - const attachments = Array.isArray(entry.attachments) - ? entry.attachments - : entry.attachment - ? [entry.attachment] - : []; - - if (!attachments.length) return null; - - const wrap = document.createElement("div"); - wrap.className = "message-attachments-list"; - - for (const attachment of attachments) { - if (String(attachment.mime_type || "").startsWith("image/")) { - const imageButton = document.createElement("button"); - imageButton.className = "message-image-link"; - imageButton.type = "button"; - - const image = document.createElement("img"); - image.className = "message-image-preview"; - image.src = attachment.url; - image.alt = attachment.original_name || "Image attachment"; - image.loading = "lazy"; - - imageButton.append(image); - imageButton.addEventListener("click", () => { - Glow.openMediaModal?.({ - url: attachment.url, - name: attachment.original_name, - mimeType: attachment.mime_type - }); - }); - - wrap.append(imageButton); - } else if (String(attachment.mime_type || "").startsWith("audio/")) { - const audio = document.createElement("audio"); - audio.controls = true; - audio.preload = "metadata"; - audio.src = attachment.url; - wrap.append(audio); - } else if (String(attachment.mime_type || "").startsWith("video/")) { - const video = document.createElement("video"); - video.controls = true; - video.preload = "metadata"; - video.src = attachment.url; - video.className = "message-video-preview"; - wrap.append(video); - } - - const link = document.createElement("a"); - link.className = "message-attachment"; - link.href = attachment.url; - link.target = "_blank"; - link.rel = "noopener noreferrer"; - link.download = attachment.original_name; - link.textContent = `Attachment: ${attachment.original_name}`; - wrap.append(link); - } - - return wrap; -}; - Glow.buildFeedEntry = entry => { - const card = document.createElement("article"); - card.className = "feed-entry"; + const row = document.createElement("article"); + row.className = "feed-entry timeline-row"; if (entry.is_mention) { - card.classList.add("mention"); + row.classList.add("mention"); } - card.dataset.messageId = String(entry.id); + row.dataset.messageId = String(entry.id); - if (entry.room_slug) card.dataset.roomSlug = entry.room_slug; - if (entry.team_slug) card.dataset.teamSlug = entry.team_slug; - if (entry.channel_slug) card.dataset.channelSlug = entry.channel_slug; + if (entry.room_slug) row.dataset.roomSlug = entry.room_slug; + if (entry.team_slug) row.dataset.teamSlug = entry.team_slug; + if (entry.channel_slug) row.dataset.channelSlug = entry.channel_slug; - const heading = document.createElement("div"); - heading.className = "feed-entry-heading"; + const top = document.createElement("div"); + top.className = "feed-entry-top"; - const room = document.createElement("button"); - room.className = "feed-room-link"; - room.type = "button"; + const context = document.createElement("button"); + context.className = "feed-room-link"; + context.type = "button"; if (entry.team_name && entry.channel_name) { - room.textContent = `${entry.team_name} · # ${entry.channel_name}`; + context.textContent = `${entry.team_name} · # ${entry.channel_name}`; } else { - room.textContent = + context.textContent = `${entry.room_visibility === "private" ? "(private) " : "# "}${entry.room_name || "channel"}`; } - room.addEventListener("click", () => { + context.addEventListener("click", () => { Glow.openFeedEntry(entry); }); @@ -236,7 +196,7 @@ Glow.buildFeedEntry = entry => { time.textContent = Glow.relativeTime(entry.created_at); time.title = new Date(entry.created_at).toLocaleString(); - heading.append(room, time); + top.append(context, time); const author = document.createElement("button"); author.className = "feed-entry-author profile-link"; @@ -248,37 +208,59 @@ Glow.buildFeedEntry = entry => { }); const body = document.createElement("div"); - body.className = "feed-entry-body"; - body.textContent = entry.text; + body.className = "feed-entry-body clamp-2"; + body.textContent = entry.text || ""; + + const footer = document.createElement("div"); + footer.className = "feed-entry-footer"; + + const meta = document.createElement("div"); + meta.className = "feed-entry-meta"; + + const attachmentSummary = Glow.feedAttachmentSummary(entry); + if (attachmentSummary) { + const attachmentButton = document.createElement("button"); + attachmentButton.className = "small-button feed-attachment-summary"; + attachmentButton.type = "button"; + attachmentButton.textContent = attachmentSummary; + attachmentButton.addEventListener("click", () => { + Glow.openFeedEntry(entry); + }); + meta.append(attachmentButton); + } - const attachmentBlock = Glow.buildFeedAttachmentBlock(entry); const reactions = Glow.buildFeedReactions(entry); + if (reactions) { + meta.append(reactions); + } const openButton = document.createElement("button"); openButton.className = "small-button feed-open-room"; openButton.type = "button"; - openButton.textContent = "Open channel"; + openButton.textContent = "Open"; openButton.addEventListener("click", () => { Glow.openFeedEntry(entry); }); - card.addEventListener("dblclick", () => { + footer.append(meta, openButton); + + row.addEventListener("dblclick", () => { Glow.openFeedEntry(entry); }); - card.append(heading, author, body); + row.addEventListener("click", event => { + if ( + event.target instanceof HTMLElement && + (event.target.closest("button") || event.target.closest("a")) + ) { + return; + } + Glow.openFeedEntry(entry); + }); - if (attachmentBlock) { - card.append(attachmentBlock); - } + row.append(top, author, body, footer); - if (reactions) { - card.append(reactions); - } - - card.append(openButton); - - return card; + return row; }; Glow.appendFeedEntries = (entries, forceScroll = false) => { @@ -427,4 +409,4 @@ Glow.openFeed = async () => { Glow.updateViewUI(); await Glow.loadFeed(); Glow.schedulePoll(); -}; +}; \ No newline at end of file