Testing speaking UI

This commit is contained in:
2026-01-06 19:56:49 +01:00
parent 16bcf25391
commit e40884ba7f
4 changed files with 77 additions and 3 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ import App from "@/types/app";
import React from "react"; import React from "react";
import PluginChannel from "./PluginChannel"; import PluginChannel from "./PluginChannel";
import { IndicatorContext } from "@/types/protocol"; import { IndicatorContext } from "@/types/protocol";
import VoiceBox from "./VoiceBox"; import VoiceBox from "./voice/VoiceBox";
import { sendVoice } from "@/lib/audio"; import { sendVoice } from "@/lib/audio";
export default function ChannelView({ export default function ChannelView({
@@ -5,7 +5,7 @@ import { ClientMessage, IndicatorContext } from "@/types/protocol";
import { Message } from "@/types/types"; import { Message } from "@/types/types";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { startMic } from "@/lib/audio"; import { startMic } from "@/lib/audio";
import { Button } from "../ui/button"; import { Button } from "../../ui/button";
import { import {
ChevronLeftIcon, ChevronLeftIcon,
Phone, Phone,
@@ -13,6 +13,7 @@ import {
PhoneOff, PhoneOff,
Volume2Icon, Volume2Icon,
} from "lucide-react"; } from "lucide-react";
import VoiceGrid from "./VoiceGrid";
export default function VoiceBox({ export default function VoiceBox({
sendVoice, sendVoice,
@@ -53,7 +54,14 @@ export default function VoiceBox({
</span> </span>
</header> </header>
)} )}
<div className="h-full overflow-y-scroll"></div> <VoiceGrid
users={[
{ id: "1", name: "Klesty", speaking: true },
{ id: "2", name: "Alex", speaking: false },
{ id: "3", name: "Mia", speaking: true },
{ id: "4", name: "John", speaking: false },
]}
/>
<footer className="mt-auto h-max w-max mx-auto"> <footer className="mt-auto h-max w-max mx-auto">
{voiceConn ? ( {voiceConn ? (
<Button <Button
@@ -0,0 +1,21 @@
import { VoiceTile, VoiceUser } from "./VoiceTile";
export default function VoiceGrid({ users }: { users: VoiceUser[] }) {
return (
<div className="h-full overflow-y-auto p-4">
<div
className="
grid gap-4
grid-cols-1
sm:grid-cols-2
md:grid-cols-3
lg:grid-cols-4
"
>
{users.map((user) => (
<VoiceTile key={user.id} user={user} />
))}
</div>
</div>
);
}
@@ -0,0 +1,45 @@
export type VoiceUser = {
id: string;
name: string;
speaking: boolean;
muted?: boolean;
};
export function VoiceTile({ user }: { user: VoiceUser }) {
return (
<div
className={`
relative flex flex-col items-center justify-center
aspect-square rounded-xl
bg-muted/40
transition-all
${
user.speaking
? "ring-4 ring-green-500 animate-pulse"
: "ring-1 ring-border"
}
${user.muted ? "opacity-50" : ""}
`}
>
{/* Avatar */}
<div
className={`
h-20 w-20 rounded-full
flex items-center justify-center
text-2xl font-semibold
bg-background
`}
>
{user.name[0].toUpperCase()}
</div>
{/* Name */}
<div className="mt-3 text-sm font-medium">{user.name}</div>
{/* Speaking indicator */}
{user.speaking && (
<div className="absolute bottom-3 text-xs text-green-400">Speaking</div>
)}
</div>
);
}