CI / Build & Quality Checks (pull_request) Successful in 3m9s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 8s
CI / Playwright smoke (e2e) (pull_request) Successful in 11m44s
useVoiceChannelFull compared the number of MatrixRTC memberships (one per device) with io.lotus.voice_limit, so one person on desktop + phone, or a crashed tab whose membership hadn't expired, filled two slots and locked others out, while the server-side guard (which counts distinct users) would have admitted them. utils/voiceChannelFull.ts (unit-tested) counts distinct senders; the header/sidebar counter shows people too. Verified on the local stack: limit 2, @aud_main in the call on two devices; @aud_bob's prescreen now shows 1/2 with Join enabled (was "Channel Full (2/2)"), matching the guard's 200. Fixes #342 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
38 lines
1.4 KiB
TypeScript
38 lines
1.4 KiB
TypeScript
import { Room } from 'matrix-js-sdk';
|
|
import { useMemo } from 'react';
|
|
import { useStateEvent } from './useStateEvent';
|
|
import { StateEvent } from '../../types/matrix/room';
|
|
import { VoiceLimitContent } from '../features/common-settings/general/RoomVoiceLimit';
|
|
import { useCallMembers, useCallSession } from './useCall';
|
|
import { useMatrixClient } from './useMatrixClient';
|
|
import { voiceChannelOccupancy } from '../utils/voiceChannelFull';
|
|
|
|
export type VoiceChannelFull = {
|
|
channelFull: boolean;
|
|
current: number;
|
|
max: number;
|
|
};
|
|
|
|
/**
|
|
* [Gitea #30] Voice channel user limit (`io.lotus.voice_limit`), shared between
|
|
* `CallPrescreen` and any other join path (e.g. the room-nav second-click join)
|
|
* so they agree on when a channel is full. 0/absent `max_users` means no limit.
|
|
*/
|
|
export const useVoiceChannelFull = (room: Room): VoiceChannelFull => {
|
|
const mx = useMatrixClient();
|
|
const callSession = useCallSession(room);
|
|
const callMembers = useCallMembers(callSession);
|
|
|
|
const limitEvent = useStateEvent(room, StateEvent.LotusVoiceLimit);
|
|
|
|
return useMemo(() => {
|
|
const maxUsers = limitEvent?.getContent<VoiceLimitContent>().max_users ?? 0;
|
|
// Distinct people, not per-device memberships (Gitea #342).
|
|
return voiceChannelOccupancy(
|
|
callMembers.map((m) => m.sender),
|
|
mx.getSafeUserId(),
|
|
maxUsers,
|
|
);
|
|
}, [limitEvent, callMembers, mx]);
|
|
};
|