fix(timeline): read-position membership listener actually fires

RoomMemberEvent.Membership is emitted on RoomMember/MatrixClient, never
on Room, so the (room as any).on() handler was dead. Subscribe on the
client filtered by roomId; drop the cast.

Fixes #61

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
2026-09-12 20:28:41 -04:00
co-authored by Claude Opus 5
parent 49c4641ca8
commit 8f92029b47
+11 -5
View File
@@ -1,4 +1,4 @@
import { Room, RoomEvent, RoomMemberEvent, MatrixEvent } from 'matrix-js-sdk';
import { Room, RoomEvent, RoomMember, RoomMemberEvent, MatrixEvent } from 'matrix-js-sdk';
import { useEffect, useState } from 'react';
import { useMatrixClient } from './useMatrixClient';
import { reactionOrEditEvent } from '../utils/room';
@@ -52,15 +52,21 @@ export function useRoomReadPositions(room: Room): Map<string, string[]> {
debounceTimer = null;
}, 150);
};
const onMembership = (): void => setPositions(computePositions(room, myUserId));
// RoomMemberEvent.Membership is emitted on the RoomMember (and re-emitted on the
// MatrixClient), never on Room — listening on `room` never fired. Subscribe on
// the client and filter to this room (Gitea #61).
const onMembership = (_ev: MatrixEvent, member: RoomMember): void => {
if (member.roomId !== room.roomId) return;
setPositions(computePositions(room, myUserId));
};
room.on(RoomEvent.Receipt, onReceipt);
(room as any).on(RoomMemberEvent.Membership, onMembership);
mx.on(RoomMemberEvent.Membership, onMembership);
return () => {
if (debounceTimer !== null) clearTimeout(debounceTimer);
room.removeListener(RoomEvent.Receipt, onReceipt);
(room as any).removeListener(RoomMemberEvent.Membership, onMembership);
mx.removeListener(RoomMemberEvent.Membership, onMembership);
};
}, [room, myUserId]);
}, [room, myUserId, mx]);
return positions;
}