From 91125372c8600424d137a1c6d5926c1cc31140da Mon Sep 17 00:00:00 2001 From: Kibi Kelburton Date: Thu, 16 Jul 2026 21:55:09 +0200 Subject: [PATCH] another sad try to make the sidebar better --- public/s/js/f0ckm.js | 3 ++- public/s/js/sidebar-activity.js | 23 ++++++++++++++--------- src/inc/routes/comments.mjs | 24 ++++++++++++++++++++---- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/public/s/js/f0ckm.js b/public/s/js/f0ckm.js index f779a65..fb655f5 100644 --- a/public/s/js/f0ckm.js +++ b/public/s/js/f0ckm.js @@ -3147,7 +3147,8 @@ window.cancelAnimFrame = (function () { if (visualizerRafId) window.cancelAnimFrame(visualizerRafId); - const media = document.querySelectorAll('video:not(#gchat-messages video), audio:not(#gchat-messages audio)'); + const media = [...document.querySelectorAll('video:not(#gchat-messages video), audio:not(#gchat-messages audio)')] + .filter(m => !m.classList.contains('emoji') || !m.closest('.sidebar-activity')); media.forEach(m => { try { diff --git a/public/s/js/sidebar-activity.js b/public/s/js/sidebar-activity.js index 2fe7923..3b65396 100644 --- a/public/s/js/sidebar-activity.js +++ b/public/s/js/sidebar-activity.js @@ -511,7 +511,7 @@ ${timeStr} -
${displayContent}${attachmentsHtml}${pollHtml}
+
${displayContent}${attachmentsHtml}${pollHtml}
${itemPreview} `; @@ -644,13 +644,14 @@ container.appendChild(ioSentinel); } attachMediaLoadListeners(container); - // has-overflow is set by default in the HTML template so all comments start - // clamped with the "read more" button visible. We must NOT run checkOverflow - // synchronously here — the browser has not yet laid out the freshly injected - // innerHTML, so scrollHeight / clientHeight are 0 and checkOverflow would - // incorrectly hide every button. Instead we defer to after the first layout - // frame so measurements are accurate and short comments get their buttons - // removed while long comments keep them visible from the very first paint. + // has-overflow is now set per-comment by the server (via is_long) so the + // correct clamped/unclamped state is baked into the HTML on first paint. + // checkOverflow still runs deferred to handle two edge cases: + // 1. Comments with images whose heights are 0 at inject time — the server + // correctly marks them is_long:true, but images that load extra-tall + // still need a re-check after load (handled by attachMediaLoadListeners). + // 2. Any mis-estimates: content that the heuristic got wrong is corrected + // after layout so measurements are accurate. requestAnimationFrame(() => { checkOverflow(); // After 1s, re-check everything — by then even slow ctrl+F5 images will @@ -843,7 +844,11 @@ // Update DOM if visible if (container) { - const html = renderActivityItem(newItem); + // is_long may be provided by the server (SSE payload) or absent for legacy events. + // Default to true so the button is always visible; checkOverflow will hide it + // if the rendered content is actually short. + const itemWithLong = { ...newItem, is_long: newItem.is_long !== false }; + const html = renderActivityItem(itemWithLong); const temp = document.createElement('div'); temp.innerHTML = html; const node = temp.firstElementChild; diff --git a/src/inc/routes/comments.mjs b/src/inc/routes/comments.mjs index a331d36..1cd0ad0 100644 --- a/src/inc/routes/comments.mjs +++ b/src/inc/routes/comments.mjs @@ -610,6 +610,11 @@ export default (router, tpl) => { db.notify('comments', JSON.stringify(livePayload)); // 2. Sidebar activity update + // Compute is_long using the full content (not the truncated notifyBody) so the + // sidebar renders the correct clamped state immediately on first paint. + const activityIsLong = content.length > 120 + || content.split('\n').length > 2 + || activityFiles.length > 0; db.notify('activity', JSON.stringify({ user_id: req.session.id, item_id: item_id, @@ -623,7 +628,8 @@ export default (router, tpl) => { username: req.session.user, username_color: req.session.username_color, display_name: req.session.display_name || null, - files: activityFiles + files: activityFiles, + is_long: activityIsLong })); // Automatically subscribe user to the thread @@ -1090,14 +1096,24 @@ export default (router, tpl) => { else if (c.rating_tag_id == 2) { ratingLabel = 'NSFW'; ratingClass = 'nsfw'; } else if (c.rating_tag_id == (cfg.nsfl_tag_id || 3)) { ratingLabel = 'NSFL'; ratingClass = 'nsfl'; } + const commentContent = (c.content || '').trim(); + const commentFiles = filesMap.get(c.id) || []; + // Compute overflow hint: true if content is likely taller than the 80px clamp. + // ~120 chars ≈ 2-3 wrapped lines in the sidebar; any newlines > 2 or file + // attachments (images/video) will also push height above the limit. + const isLong = commentContent.length > 120 + || commentContent.split('\n').length > 2 + || commentFiles.length > 0; + return { ...c, - content: (c.content || '').trim(), + content: commentContent, username_color: c.username_color, item_rating_class: ratingClass, item_rating_label: ratingLabel, - files: filesMap.get(c.id) || [], - poll: pollMap.get(c.id) || null + files: commentFiles, + poll: pollMap.get(c.id) || null, + is_long: isLong // created_at stays as the raw ISO timestamp so the frontend f0ckTimeAgo can localize it }; });