diff --git a/web/src/features/groups/GroupAdminModal.tsx b/web/src/features/groups/GroupAdminModal.tsx index 950f368c..53aab35a 100644 --- a/web/src/features/groups/GroupAdminModal.tsx +++ b/web/src/features/groups/GroupAdminModal.tsx @@ -410,6 +410,13 @@ function MutesSubView({ topicId, muted, onClose }: { topicId: string; muted: Gro const queryClient = useQueryClient(); const [adding, setAdding] = useState(false); const [error, setError] = useState(''); + // `GroupMute` itself carries only a bare `user_id` (see its own type comment) -- resolve a real + // name/avatar the same way ConversationView.tsx's `memberByUserId` does, rather than rendering the + // raw id (this list previously crashed outright reading a `.user.display_name` that never existed + // on the real response, confirmed live: `Cannot read properties of undefined (reading 'user_id')` + // the moment a real muted member was ever rendered here). + const membersQuery = useQuery({ queryKey: ['group-members', topicId], queryFn: () => getAllGroupMembers(topicId) }); + const memberByUserId = new Map((membersQuery.data || []).map((m) => [m.user_id, m])); const invalidate = () => queryClient.invalidateQueries({ queryKey: ['group-mutes', topicId] }); const muteMutation = useMutation({ mutationFn: (userId: string) => muteGroupMembers(topicId, [{ user_id: userId, expires_at: null }]), @@ -439,22 +446,25 @@ function MutesSubView({ topicId, muted, onClose }: { topicId: string; muted: Gro /> ) : ( <> - {muted.map((m) => ( -
- - {avatarLetter(m.user.display_name)} - - {m.user.display_name || m.user.user_id} - -
- ))} + {muted.map((m) => { + const name = memberByUserId.get(m.user_id)?.display_name || m.user_id; + return ( +
+ + {avatarLetter(name)} + + {name} + +
+ ); + })}