condense: Fix long unread message collapses after initial render.

After narrowing to a long unread message, the message gets marked
as read and can be collapsed when rerender happens since the
cutoff of read message is different.

Fixed by tracking which messages were unread during initial
render and using the unread cutoff for them until user narrows
again.
This commit is contained in:
Aman Agrawal
2025-07-22 09:14:25 +05:30
committed by Tim Abbott
parent c90f3682bc
commit 17a126a926

View File

@@ -4,6 +4,7 @@ import assert from "minimalistic-assert";
import render_message_length_toggle from "../templates/message_length_toggle.hbs";
import * as message_flags from "./message_flags.ts";
import type {MessageList} from "./message_list.ts";
import * as message_lists from "./message_lists.ts";
import type {Message} from "./message_store.ts";
import * as message_viewport from "./message_viewport.ts";
@@ -23,6 +24,14 @@ This library implements two related, similar concepts:
*/
const state: {
message_list: MessageList | undefined;
has_unread_cutoff_by_message_id: Set<number>;
} = {
message_list: undefined,
has_unread_cutoff_by_message_id: new Set<number>(),
};
export function show_message_expander($row: JQuery): void {
$row.find(".message_length_controller").html(
render_message_length_toggle({toggle_type: "expander"}),
@@ -170,6 +179,11 @@ export function condense_and_collapse(elems: JQuery): void {
return;
}
if (message_lists.current !== state.message_list) {
state.message_list = message_lists.current;
state.has_unread_cutoff_by_message_id = new Set();
}
// For unread messages, we allow them to expand to most of a
// desktop monitor's height, with stricter limits for mobile web
// devices, especially in landscape mode.
@@ -222,7 +236,14 @@ export function condense_and_collapse(elems: JQuery): void {
// changing the layout of the page, which is more performanant.
// More information here: https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/#avoid-layout-thrashing
for (const {elem, $content, message, message_height} of rows_to_resize) {
const height_cutoff = message.unread ? height_cutoff_unread : height_cutoff_read;
// Track which messages were unread when initially rendered so that subsequent
// re-renders don't collapse the message while user is reading it.
if (message.unread) {
state.has_unread_cutoff_by_message_id.add(message.id);
}
const height_cutoff = state.has_unread_cutoff_by_message_id.has(message.id)
? height_cutoff_unread
: height_cutoff_read;
const long_message = message_height > height_cutoff;
if (long_message) {
// All long messages are flagged as such.