feat: one-click join + live pod presence
Join UX: click a member's name to join directly, or type a name and "Join" (adds to roster + joins) — removes the redundant dropdown step. "Add" still adds to the roster without joining. Presence: new GET /api/presence (LiveKit RoomServiceClient) reports who's connected per pod. The pod list polls it and shows a "N in room" badge plus a green dot on members currently connected, so people can see active pods and jump in. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { RoomServiceClient } from 'livekit-server-sdk';
|
||||
import { env } from '../env.js';
|
||||
|
||||
function isConfigured(): boolean {
|
||||
return !!env.LIVEKIT_URL && !env.LIVEKIT_URL.includes('REPLACE_ME');
|
||||
}
|
||||
|
||||
let client: RoomServiceClient | null = null;
|
||||
function svc(): RoomServiceClient {
|
||||
if (!client) {
|
||||
const httpUrl = env.LIVEKIT_URL.replace(/^wss:/, 'https:').replace(/^ws:/, 'http:');
|
||||
client = new RoomServiceClient(httpUrl, env.LIVEKIT_API_KEY, env.LIVEKIT_API_SECRET);
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Who is currently connected in each pod's LiveKit room, as display names,
|
||||
* keyed by pod id (= room name). Empty rooms are omitted. Returns {} if
|
||||
* LiveKit isn't configured or the API call fails (presence is best-effort).
|
||||
*/
|
||||
export async function getPresence(): Promise<Record<string, string[]>> {
|
||||
if (!isConfigured()) return {};
|
||||
const out: Record<string, string[]> = {};
|
||||
const rooms = await svc().listRooms();
|
||||
await Promise.all(
|
||||
rooms
|
||||
.filter((r) => r.numParticipants > 0)
|
||||
.map(async (r) => {
|
||||
try {
|
||||
const ps = await svc().listParticipants(r.name);
|
||||
out[r.name] = ps.map((p) => p.name || p.identity);
|
||||
} catch {
|
||||
out[r.name] = [];
|
||||
}
|
||||
}),
|
||||
);
|
||||
return out;
|
||||
}
|
||||
Reference in New Issue
Block a user