Update static/js/05-feed.js

This commit is contained in:
dev 2026-10-31 08:52:14 +00:00
parent 8e93be2307
commit d6e2ebf750

View File

@ -99,14 +99,36 @@ Glow.openFeedEntry = async entry => {
Glow.showToast("This conversation is no longer available.", "error"); 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 => { Glow.buildFeedReactions = entry => {
const reactions = Array.isArray(entry.reactions) ? entry.reactions : []; const reactions = Array.isArray(entry.reactions) ? entry.reactions : [];
if (!reactions.length) return null; if (!reactions.length) return null;
const row = document.createElement("div"); 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"); const chip = document.createElement("button");
chip.className = "reaction-chip"; chip.className = "reaction-chip";
chip.type = "button"; chip.type = "button";
@ -136,97 +158,35 @@ Glow.buildFeedReactions = entry => {
return row; 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 => { Glow.buildFeedEntry = entry => {
const card = document.createElement("article"); const row = document.createElement("article");
card.className = "feed-entry"; row.className = "feed-entry timeline-row";
if (entry.is_mention) { 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.room_slug) row.dataset.roomSlug = entry.room_slug;
if (entry.team_slug) card.dataset.teamSlug = entry.team_slug; if (entry.team_slug) row.dataset.teamSlug = entry.team_slug;
if (entry.channel_slug) card.dataset.channelSlug = entry.channel_slug; if (entry.channel_slug) row.dataset.channelSlug = entry.channel_slug;
const heading = document.createElement("div"); const top = document.createElement("div");
heading.className = "feed-entry-heading"; top.className = "feed-entry-top";
const room = document.createElement("button"); const context = document.createElement("button");
room.className = "feed-room-link"; context.className = "feed-room-link";
room.type = "button"; context.type = "button";
if (entry.team_name && entry.channel_name) { if (entry.team_name && entry.channel_name) {
room.textContent = `${entry.team_name} · # ${entry.channel_name}`; context.textContent = `${entry.team_name} · # ${entry.channel_name}`;
} else { } else {
room.textContent = context.textContent =
`${entry.room_visibility === "private" ? "(private) " : "# "}${entry.room_name || "channel"}`; `${entry.room_visibility === "private" ? "(private) " : "# "}${entry.room_name || "channel"}`;
} }
room.addEventListener("click", () => { context.addEventListener("click", () => {
Glow.openFeedEntry(entry); Glow.openFeedEntry(entry);
}); });
@ -236,7 +196,7 @@ Glow.buildFeedEntry = entry => {
time.textContent = Glow.relativeTime(entry.created_at); time.textContent = Glow.relativeTime(entry.created_at);
time.title = new Date(entry.created_at).toLocaleString(); time.title = new Date(entry.created_at).toLocaleString();
heading.append(room, time); top.append(context, time);
const author = document.createElement("button"); const author = document.createElement("button");
author.className = "feed-entry-author profile-link"; author.className = "feed-entry-author profile-link";
@ -248,37 +208,59 @@ Glow.buildFeedEntry = entry => {
}); });
const body = document.createElement("div"); const body = document.createElement("div");
body.className = "feed-entry-body"; body.className = "feed-entry-body clamp-2";
body.textContent = entry.text; 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); const reactions = Glow.buildFeedReactions(entry);
if (reactions) {
meta.append(reactions);
}
const openButton = document.createElement("button"); const openButton = document.createElement("button");
openButton.className = "small-button feed-open-room"; openButton.className = "small-button feed-open-room";
openButton.type = "button"; openButton.type = "button";
openButton.textContent = "Open channel"; openButton.textContent = "Open";
openButton.addEventListener("click", () => { openButton.addEventListener("click", () => {
Glow.openFeedEntry(entry); Glow.openFeedEntry(entry);
}); });
card.addEventListener("dblclick", () => { footer.append(meta, openButton);
row.addEventListener("dblclick", () => {
Glow.openFeedEntry(entry); 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) { row.append(top, author, body, footer);
card.append(attachmentBlock);
}
if (reactions) { return row;
card.append(reactions);
}
card.append(openButton);
return card;
}; };
Glow.appendFeedEntries = (entries, forceScroll = false) => { Glow.appendFeedEntries = (entries, forceScroll = false) => {
@ -427,4 +409,4 @@ Glow.openFeed = async () => {
Glow.updateViewUI(); Glow.updateViewUI();
await Glow.loadFeed(); await Glow.loadFeed();
Glow.schedulePoll(); Glow.schedulePoll();
}; };