another sad try to make the sidebar better
This commit is contained in:
@@ -3147,7 +3147,8 @@ window.cancelAnimFrame = (function () {
|
|||||||
if (visualizerRafId) window.cancelAnimFrame(visualizerRafId);
|
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 => {
|
media.forEach(m => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -511,7 +511,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<span class="comment-time timeago" tooltip="${fullDate}" style="font-size: 0.75em;"${tsAttr}>${timeStr}</span>
|
<span class="comment-time timeago" tooltip="${fullDate}" style="font-size: 0.75em;"${tsAttr}>${timeStr}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="comment-content has-overflow"><div class="comment-content-inner">${displayContent}${attachmentsHtml}${pollHtml}</div><button class="read-more-btn" style="display:block">${window.f0ckI18n?.sidebar_read_more || 'read more'}</button></div>
|
<div class="comment-content${c.is_long ? ' has-overflow' : ''}"><div class="comment-content-inner">${displayContent}${attachmentsHtml}${pollHtml}</div><button class="read-more-btn"${c.is_long ? ' style="display:block"' : ''}>${window.f0ckI18n?.sidebar_read_more || 'read more'}</button></div>
|
||||||
${itemPreview}
|
${itemPreview}
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
@@ -644,13 +644,14 @@
|
|||||||
container.appendChild(ioSentinel);
|
container.appendChild(ioSentinel);
|
||||||
}
|
}
|
||||||
attachMediaLoadListeners(container);
|
attachMediaLoadListeners(container);
|
||||||
// has-overflow is set by default in the HTML template so all comments start
|
// has-overflow is now set per-comment by the server (via is_long) so the
|
||||||
// clamped with the "read more" button visible. We must NOT run checkOverflow
|
// correct clamped/unclamped state is baked into the HTML on first paint.
|
||||||
// synchronously here — the browser has not yet laid out the freshly injected
|
// checkOverflow still runs deferred to handle two edge cases:
|
||||||
// innerHTML, so scrollHeight / clientHeight are 0 and checkOverflow would
|
// 1. Comments with images whose heights are 0 at inject time — the server
|
||||||
// incorrectly hide every button. Instead we defer to after the first layout
|
// correctly marks them is_long:true, but images that load extra-tall
|
||||||
// frame so measurements are accurate and short comments get their buttons
|
// still need a re-check after load (handled by attachMediaLoadListeners).
|
||||||
// removed while long comments keep them visible from the very first paint.
|
// 2. Any mis-estimates: content that the heuristic got wrong is corrected
|
||||||
|
// after layout so measurements are accurate.
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
checkOverflow();
|
checkOverflow();
|
||||||
// After 1s, re-check everything — by then even slow ctrl+F5 images will
|
// After 1s, re-check everything — by then even slow ctrl+F5 images will
|
||||||
@@ -843,7 +844,11 @@
|
|||||||
|
|
||||||
// Update DOM if visible
|
// Update DOM if visible
|
||||||
if (container) {
|
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');
|
const temp = document.createElement('div');
|
||||||
temp.innerHTML = html;
|
temp.innerHTML = html;
|
||||||
const node = temp.firstElementChild;
|
const node = temp.firstElementChild;
|
||||||
|
|||||||
@@ -610,6 +610,11 @@ export default (router, tpl) => {
|
|||||||
db.notify('comments', JSON.stringify(livePayload));
|
db.notify('comments', JSON.stringify(livePayload));
|
||||||
|
|
||||||
// 2. Sidebar activity update
|
// 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({
|
db.notify('activity', JSON.stringify({
|
||||||
user_id: req.session.id,
|
user_id: req.session.id,
|
||||||
item_id: item_id,
|
item_id: item_id,
|
||||||
@@ -623,7 +628,8 @@ export default (router, tpl) => {
|
|||||||
username: req.session.user,
|
username: req.session.user,
|
||||||
username_color: req.session.username_color,
|
username_color: req.session.username_color,
|
||||||
display_name: req.session.display_name || null,
|
display_name: req.session.display_name || null,
|
||||||
files: activityFiles
|
files: activityFiles,
|
||||||
|
is_long: activityIsLong
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Automatically subscribe user to the thread
|
// 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 == 2) { ratingLabel = 'NSFW'; ratingClass = 'nsfw'; }
|
||||||
else if (c.rating_tag_id == (cfg.nsfl_tag_id || 3)) { ratingLabel = 'NSFL'; ratingClass = 'nsfl'; }
|
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 {
|
return {
|
||||||
...c,
|
...c,
|
||||||
content: (c.content || '').trim(),
|
content: commentContent,
|
||||||
username_color: c.username_color,
|
username_color: c.username_color,
|
||||||
item_rating_class: ratingClass,
|
item_rating_class: ratingClass,
|
||||||
item_rating_label: ratingLabel,
|
item_rating_label: ratingLabel,
|
||||||
files: filesMap.get(c.id) || [],
|
files: commentFiles,
|
||||||
poll: pollMap.get(c.id) || null
|
poll: pollMap.get(c.id) || null,
|
||||||
|
is_long: isLong
|
||||||
// created_at stays as the raw ISO timestamp so the frontend f0ckTimeAgo can localize it
|
// created_at stays as the raw ISO timestamp so the frontend f0ckTimeAgo can localize it
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user