diff --git a/src/app/app.ts b/src/app/app.ts index de7e654..c261582 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -216,10 +216,17 @@ export default class Enclave
{ server.voiceChatUsers[msg.channel_id] = []; server.voiceChatUsers[msg.channel_id].push(msg.pubkey); + this.server?.getUsers([msg.pubkey]); return; case "Speaking": - server.voiceChatSpeaker(msg.pubkey); + clearTimeout(server.voiceChatSpeakers[msg.pubkey]); + + server.voiceChatSpeakers[msg.pubkey] = setTimeout(() => { + delete server.voiceChatSpeakers[msg.pubkey]; + this.forceRender(); + }, 800); + this.forceRender(); return; } } diff --git a/src/app/server.ts b/src/app/server.ts index 35efabf..19442f1 100644 --- a/src/app/server.ts +++ b/src/app/server.ts @@ -113,12 +113,4 @@ export default class EnclaveServer { this.websocket?.send({ method: "GetUsers", pubkeys: filteredPubkeys }); } - - public voiceChatSpeaker(pubkey: string) { - clearTimeout(this.voiceChatSpeakers[pubkey]); - - this.voiceChatSpeakers[pubkey] = setTimeout(() => { - delete this.voiceChatSpeakers[pubkey]; - }, 1000); - } } diff --git a/src/components/page/channel/VoiceChannel.tsx b/src/components/page/channel/VoiceChannel.tsx index 2d7a576..f29e13f 100644 --- a/src/components/page/channel/VoiceChannel.tsx +++ b/src/components/page/channel/VoiceChannel.tsx @@ -2,6 +2,8 @@ import Enclave from "@/app/app"; import { ChannelPageProps } from "../PageView"; import { useEffect, useRef } from "react"; import { invoke } from "@tauri-apps/api/core"; +import { cn } from "@/lib/utils"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; export default function VoiceChannel({ appRef, @@ -35,13 +37,85 @@ export default function VoiceChannel({ }); }, [channel.id]); + const speakers = + appRef.current?.server?.voiceChatSpeakers && + Object.keys(appRef.current?.server?.voiceChatSpeakers); + + const users = appRef.current?.server?.voiceChatUsers[channel.id]; + + const usersLength = users?.length || 0; + + // Dynamic grid column layout based on user count + const getGridCols = () => { + if (usersLength <= 3) return "grid-cols-1"; + if (usersLength <= 6) return "grid-cols-3"; + if (usersLength <= 9) return "grid-cols-3"; + return "grid-cols-5"; + }; + + // Avatar sizing scales up for fewer participants + const getAvatarSize = () => { + if (usersLength <= 2) return "h-24 w-24 text-3xl"; + if (usersLength <= 4) return "h-20 w-20 text-2xl"; + return "h-14 w-14 text-lg"; + }; + return (