This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

cinny-threads: refresh thread unread badge on read receipts

The thread unread badge in RoomViewHeader only recomputed on
ThreadEvent.New/Update/NewReply. Marking a thread read emits
RoomEvent.Receipt / RoomEvent.UnreadNotifications instead, so the badge
kept a stale count until unrelated thread activity fired a recompute -
the notification appeared persistent and laggy. Subscribe the badge
effect to those receipt events too.

Assisted-by: Claude Code (claude-opus-4-8[1m])

+13 -5
+13 -5
2configs/services/matrix/cinny-threads-ui.patch
··· 946 946 <> 947 947 {eventId && ( 948 948 diff --git a/src/app/features/room/RoomViewHeader.tsx b/src/app/features/room/RoomViewHeader.tsx 949 - index 8089b5e..0ed8efd 100644 949 + index 8089b5e..754d44a 100644 950 950 --- a/src/app/features/room/RoomViewHeader.tsx 951 951 +++ b/src/app/features/room/RoomViewHeader.tsx 952 952 @@ -1,5 +1,6 @@ ··· 987 987 988 988 const pinnedEvents = useRoomPinnedEvents(room); 989 989 const encryptionEvent = useStateEvent(room, StateEvent.RoomEncryption); 990 - @@ -416,6 +424,106 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) { 990 + @@ -416,6 +424,114 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) { 991 991 : undefined; 992 992 993 993 const [peopleDrawer, setPeopleDrawer] = useSetting(settingsAtom, 'isPeopleDrawer'); ··· 1084 1084 + room.on(ThreadEvent.New, updateThreadCounts as any); 1085 1085 + room.on(ThreadEvent.Update, updateThreadCounts as any); 1086 1086 + room.on(ThreadEvent.NewReply, updateThreadCounts as any); 1087 + + // Read receipts (including our own local echo when a thread is marked read) 1088 + + // and notification-count recomputes do not emit ThreadEvent.*, so subscribe 1089 + + // to them too — otherwise the badge keeps a stale count until unrelated 1090 + + // thread activity happens to fire. 1091 + + room.on(RoomEvent.Receipt, updateThreadCounts as any); 1092 + + room.on(RoomEvent.UnreadNotifications, updateThreadCounts as any); 1087 1093 + 1088 1094 + return () => { 1089 1095 + room.removeListener(ThreadEvent.New, updateThreadCounts as any); 1090 1096 + room.removeListener(ThreadEvent.Update, updateThreadCounts as any); 1091 1097 + room.removeListener(ThreadEvent.NewReply, updateThreadCounts as any); 1098 + + room.removeListener(RoomEvent.Receipt, updateThreadCounts as any); 1099 + + room.removeListener(RoomEvent.UnreadNotifications, updateThreadCounts as any); 1092 1100 + }; 1093 1101 + }, [room]); 1094 1102 1095 1103 const handleSearchClick = () => { 1096 1104 const searchParams: _SearchPathSearchParams = { 1097 - @@ -442,6 +550,10 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) { 1105 + @@ -442,6 +558,10 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) { 1098 1106 openSettings(room.roomId, parentSpace?.roomId, RoomSettingsPage.MembersPage); 1099 1107 return; 1100 1108 } ··· 1105 1113 setPeopleDrawer(!peopleDrawer); 1106 1114 }; 1107 1115 1108 - @@ -597,6 +709,56 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) { 1116 + @@ -597,6 +717,56 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) { 1109 1117 {!room.isCallRoom() && livekitSupported && rtcSupported && hasCallPermission && ( 1110 1118 <CallButton /> 1111 1119 )} ··· 1162 1170 {screenSize === ScreenSize.Desktop && ( 1163 1171 <TooltipProvider 1164 1172 position="Bottom" 1165 - @@ -612,8 +774,17 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) { 1173 + @@ -612,8 +782,17 @@ export function RoomViewHeader({ callView }: { callView?: boolean }) { 1166 1174 } 1167 1175 > 1168 1176 {(triggerRef) => (