362f4943d4
P4-3 — Knock-to-join Notifications for Admins: - usePendingKnocks() hook reactively tracks knocking members via RoomMemberEvent.Membership; returns empty array if user lacks invite power - Members icon in RoomViewHeader shows a Warning badge with the knock count when there are pending requests; badge updates in real time without needing to open the drawer; aria-label updated to describe pending count P5-11 — AFK Auto-Mute in Voice: - useAfkAutoMute() hook opens a monitoring-only getUserMedia stream, connects it to an AnalyserNode, and polls RMS every 500ms - If mic is on and RMS stays below threshold for the configured timeout, calls callEmbed.control.setMicrophone(false) and shows an in-app toast - Hook is called inside CallControls so monitoring is only active during calls - Settings: afkAutoMute toggle + afkTimeoutMinutes select (1/5/10/20/30 min, default 10) added to Settings → Calls Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
33 lines
1.3 KiB
TypeScript
33 lines
1.3 KiB
TypeScript
import { useEffect, useReducer } from 'react';
|
|
import { MatrixEvent, Room, RoomMember, RoomMemberEvent } from 'matrix-js-sdk';
|
|
import { Membership } from '../../types/matrix/room';
|
|
import { useMatrixClient } from './useMatrixClient';
|
|
import { readPowerLevel, usePowerLevelsContext } from './usePowerLevels';
|
|
|
|
/**
|
|
* Returns the list of members currently knocking on the room, reactively.
|
|
* Returns an empty array if the current user lacks invite power level.
|
|
*/
|
|
export function usePendingKnocks(room: Room): RoomMember[] {
|
|
const mx = useMatrixClient();
|
|
const powerLevels = usePowerLevelsContext();
|
|
const [, forceUpdate] = useReducer((n: number) => n + 1, 0);
|
|
|
|
useEffect(() => {
|
|
const handler = (_evt: MatrixEvent, member: RoomMember) => {
|
|
if (member.roomId === room.roomId) forceUpdate();
|
|
};
|
|
mx.on(RoomMemberEvent.Membership, handler);
|
|
return () => {
|
|
mx.removeListener(RoomMemberEvent.Membership, handler);
|
|
};
|
|
}, [mx, room.roomId]);
|
|
|
|
const myUserId = mx.getUserId();
|
|
const myPowerLevel = readPowerLevel.user(powerLevels, myUserId ?? undefined);
|
|
const invitePowerLevel = readPowerLevel.action(powerLevels, 'invite');
|
|
const canApprove = myPowerLevel >= invitePowerLevel;
|
|
|
|
return canApprove ? room.getMembersWithMembership(Membership.Knock) : [];
|
|
}
|