From ff575212ee82d323f42781562c0bfe58ec4a3d7e Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Sat, 12 Sep 2026 20:28:42 -0400 Subject: [PATCH] fix(moderation): neutral phrasing for paginated member events without prev_content Fixes #82 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA --- .../room-settings/RoomActivityLog.tsx | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/app/features/room-settings/RoomActivityLog.tsx b/src/app/features/room-settings/RoomActivityLog.tsx index 09489ebdc..a8f72f547 100644 --- a/src/app/features/room-settings/RoomActivityLog.tsx +++ b/src/app/features/room-settings/RoomActivityLog.tsx @@ -63,8 +63,26 @@ function describeEvent(mx: ReturnType, ev: MatrixEvent): const prevMembership = prevContent.membership as string | undefined; const reason = content.reason as string | undefined; const targetName = getDisplayName(mx, stateKey); + // getPrevContent() falls back to {} when unsigned.prev_content is missing, + // which is common for state events fetched via back-pagination (homeservers + // don't always include it in /messages). That makes prevMembership + // indistinguishable from "no prior membership" (fresh join). Check the raw + // unsigned field so we only apply the join/leave-transition assumptions + // below to events where the SDK actually gave us prior state. + const hasPrevContent = ev.getUnsigned().prev_content !== undefined; if (membership === 'join') { + if (!hasPrevContent) { + return { + text: ( + <> + {targetName}'s membership changed to joined + + ), + iconSrc: Icons.User, + filter: 'members', + }; + } if ( prevMembership === 'invite' || prevMembership === 'knock' || @@ -94,6 +112,17 @@ function describeEvent(mx: ReturnType, ev: MatrixEvent): } if (membership === 'leave') { + if (!hasPrevContent) { + return { + text: ( + <> + {targetName}'s membership changed to left + + ), + iconSrc: Icons.User, + filter: 'members', + }; + } if (prevMembership === 'ban') { return { text: (