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
26 lines
1.0 KiB
TypeScript
26 lines
1.0 KiB
TypeScript
/**
|
|
* [Gitea #342] Whether a voice channel with an `io.lotus.voice_limit` is full.
|
|
* Counts distinct PEOPLE, not call memberships: a MatrixRTC membership is per
|
|
* device, so one user on desktop + phone (or with a crashed tab's membership
|
|
* not yet expired) used to fill two slots. This matches the server-side guard
|
|
* (matrix `voice-limit-guard.py`, which reduces LiveKit identities to users).
|
|
*/
|
|
export type VoiceChannelOccupancy = {
|
|
channelFull: boolean;
|
|
/** Distinct users in the call. */
|
|
current: number;
|
|
max: number;
|
|
};
|
|
|
|
export const voiceChannelOccupancy = (
|
|
memberSenders: Array<string | undefined>,
|
|
myUserId: string,
|
|
maxUsers: number,
|
|
): VoiceChannelOccupancy => {
|
|
const users = new Set(memberSenders.filter((s): s is string => !!s));
|
|
// A user already in the call (another device, or rejoining) is never blocked.
|
|
const alreadyMember = users.has(myUserId);
|
|
const channelFull = maxUsers > 0 && !alreadyMember && users.size >= maxUsers;
|
|
return { channelFull, current: users.size, max: maxUsers };
|
|
};
|