fix(desktop): render thread facepile oldest-replier-first (#1595)

Signed-off-by: Fizz <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
klopez4212
2026-07-08 07:18:22 -07:00
committed by GitHub
co-authored by npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5
parent 943d7a6630
commit f9701a3860
2 changed files with 40 additions and 6 deletions
@@ -631,13 +631,40 @@ test("buildMainTimelineEntries renders a relay-only thread summary", () => {
threadHeadId: "root",
replyCount: 4,
lastReplyAt: 9,
// Relay returns participants most-recent-first (["alice", "bob"]); the
// facepile renders them oldest-first so the last replier lands rightmost.
participants: [
{ id: "alice", author: "Alice", avatarUrl: "alice.png" },
{ id: "bob", author: "bob", avatarUrl: null },
{ id: "alice", author: "Alice", avatarUrl: "alice.png" },
],
});
});
test("buildMainTimelineEntries keeps the 3 most-recent relay participants oldest-first", () => {
const root = message({ id: "root", createdAt: 1 });
const summaries = new Map([
[
"root",
{
replyCount: 4,
descendantCount: 4,
lastReplyAt: 9,
// Relay order is most-recent-first; only the top 3 are displayed.
participantPubkeys: ["newest", "middle", "oldest-shown", "dropped"],
},
],
]);
const [entry] = buildMainTimelineEntries([root], new Set(), summaries);
// Top-3 taken (drops "dropped"), then reversed to oldest-first so the last
// replier ("newest") renders rightmost.
assert.deepEqual(
entry.summary?.participants.map((participant) => participant.id),
["oldest-shown", "middle", "newest"],
);
});
test("buildMainTimelineEntries merges local knowledge over the relay floor", () => {
const root = message({ id: "root", createdAt: 1 });
const localReply = message({
@@ -392,11 +392,18 @@ function buildRelayThreadSummary(
threadHeadId: messageId,
replyCount: summary.descendantCount,
lastReplyAt: summary.lastReplyAt,
participants: summary.participantPubkeys.slice(0, 3).map((pubkey) => ({
id: pubkey,
author: profiles?.[pubkey.toLowerCase()]?.displayName ?? pubkey,
avatarUrl: profiles?.[pubkey.toLowerCase()]?.avatarUrl ?? null,
})),
// The relay returns `participantPubkeys` most-recent-first. Take the 3 most
// recent, then reverse to oldest-first so the facepile renders the last
// replier at the end (rightmost) — matching the client-assembled path
// (`buildSummaryForDirectReplies`, which also reverses to oldest-first).
participants: summary.participantPubkeys
.slice(0, 3)
.reverse()
.map((pubkey) => ({
id: pubkey,
author: profiles?.[pubkey.toLowerCase()]?.displayName ?? pubkey,
avatarUrl: profiles?.[pubkey.toLowerCase()]?.avatarUrl ?? null,
})),
};
}