Working UI

This commit is contained in:
2026-01-06 20:27:37 +01:00
parent e40884ba7f
commit df16effa4b
8 changed files with 89 additions and 41 deletions
+1
View File
@@ -47,6 +47,7 @@ export default function ChannelView({
<VoiceBox
app={app}
channelName={app.currentChannel.name}
channelId={app.currentChannel.id}
messages={messages}
sendRequest={(req) => {
while (serverRef.current?.CONNECTING) {}
+17 -22
View File
@@ -6,13 +6,7 @@ import { Message } from "@/types/types";
import { useEffect, useState } from "react";
import { startMic } from "@/lib/audio";
import { Button } from "../../ui/button";
import {
ChevronLeftIcon,
Phone,
PhoneCall,
PhoneOff,
Volume2Icon,
} from "lucide-react";
import { ChevronLeftIcon, Phone, Volume2Icon } from "lucide-react";
import VoiceGrid from "./VoiceGrid";
export default function VoiceBox({
@@ -20,10 +14,12 @@ export default function VoiceBox({
app,
channelName,
sendRequest,
channelId,
}: {
channelName?: string;
app: App;
sendRequest: (req: ClientMessage) => void;
channelName?: string;
channelId: string;
messages: Message[];
indicators: IndicatorContext[];
sendVoice: (data: Int16Array) => void;
@@ -54,25 +50,26 @@ export default function VoiceBox({
</span>
</header>
)}
<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 },
]}
/>
{app.voiceConns[channelId] && (
<VoiceGrid
users={Object.entries(app.voiceConns[channelId]).map(
([userId, _]) => ({
id: userId,
speaking: false,
})
)}
app={app}
/>
)}
<footer className="mt-auto h-max w-max mx-auto">
{voiceConn ? (
<Button
className="mx-auto my-auto h-max bg-transparent text-destructive border border-destructive hover:bg-destructive/20 rounded-full aspect-square w-12"
onClick={() => {
if (!app.currentChannel) return;
setVoiceConn(false);
sendRequest({
type: "leave_voice",
params: { channel_id: app.currentChannel.id },
params: { channel_id: channelId },
});
}}
>
@@ -82,12 +79,10 @@ export default function VoiceBox({
<Button
className="mx-auto my-auto h-max bg-transparent text-chart-2 border border-chart-2 hover:bg-chart-2/20 rounded-full aspect-square w-12"
onClick={() => {
if (!app.currentChannel) return;
setVoiceConn(true);
sendRequest({
type: "join_voice",
params: { channel_id: app.currentChannel.id },
params: { channel_id: channelId },
});
}}
>
+9 -2
View File
@@ -1,6 +1,13 @@
import App from "@/types/app";
import { VoiceTile, VoiceUser } from "./VoiceTile";
export default function VoiceGrid({ users }: { users: VoiceUser[] }) {
export default function VoiceGrid({
app,
users,
}: {
app: App;
users: VoiceUser[];
}) {
return (
<div className="h-full overflow-y-auto p-4">
<div
@@ -13,7 +20,7 @@ export default function VoiceGrid({ users }: { users: VoiceUser[] }) {
"
>
{users.map((user) => (
<VoiceTile key={user.id} user={user} />
<VoiceTile key={user.id} user={user} app={app} />
))}
</div>
</div>
+20 -15
View File
@@ -1,11 +1,13 @@
import AsyncValue from "@/components/AsyncValue";
import App from "@/types/app";
export type VoiceUser = {
id: string;
name: string;
speaking: boolean;
muted?: boolean;
};
export function VoiceTile({ user }: { user: VoiceUser }) {
export function VoiceTile({ user, app }: { app: App; user: VoiceUser }) {
return (
<div
className={`
@@ -21,20 +23,23 @@ export function VoiceTile({ user }: { user: VoiceUser }) {
${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>
{/* Avatar and name */}
<AsyncValue
func={() => app.getUserById(user.id)}
render={({ value }) => (
<>
<img
src={value?.avatar_url}
alt="Pfp"
className="h-20 w-20 rounded-full"
/>
{/* Name */}
<div className="mt-3 text-sm font-medium">{user.name}</div>
<div className="mt-3 text-sm font-medium">
{value?.display_name}
</div>
</>
)}
/>
{/* Speaking indicator */}
{user.speaking && (