Spaces:
Sleeping
Sleeping
"use client"; | |
import { | |
DailyVideo, | |
useAppMessage, | |
useLocalSessionId, | |
useParticipantIds, | |
} from "@daily-co/daily-react"; | |
import { useCallback, useEffect, useState } from "react"; | |
import Avatar from "../components/Avatar"; | |
import Card from "../components/Card"; | |
import CreateRoom from "../components/CreateRoom"; | |
import Join from "../components/Joining"; | |
import { apiUrl } from "../utils"; | |
const STATE_IDLE = "idle"; | |
const STATE_JOINING = "joining"; | |
const STATE_JOINED = "joined"; | |
const STATE_LEFT = "left"; | |
const BOT_STATE_STARTING = "bot_starting"; | |
const BOT_STATE_STARTED = "bot_started"; | |
export default function Call() { | |
const [callState, setCallState] = useState(STATE_IDLE); | |
const [roomUrl, setRoomUrl] = useState(); | |
const [botState, setBotState] = useState(BOT_STATE_STARTING); | |
const [params, setParams] = useState({}); | |
const localSessionId = useLocalSessionId(); | |
const participantIds = useParticipantIds({ filter: "remote" }); | |
const sendAppMessage = useAppMessage({ | |
onAppMessage: useCallback((ev) => setParams(ev.data), []), | |
}); | |
const start = useCallback(async () => { | |
if (!process.env.NEXT_PUBLIC_DISABLE_LOCAL_AGENT) return; | |
const resp = await fetch(`${apiUrl}/start`, { | |
method: "POST", | |
mode: "cors", | |
cache: "no-cache", | |
credentials: "same-origin", | |
headers: { | |
"Content-Type": "application/json", | |
}, | |
body: JSON.stringify({ room_url: roomUrl }), | |
}); | |
const data = await resp.json(); | |
return data; | |
}, [roomUrl]); | |
useEffect(() => { | |
if (callState !== STATE_JOINED || botState === BOT_STATE_STARTED) return; | |
start(); | |
}, [callState, botState, start]); | |
if (callState === STATE_IDLE) { | |
return ( | |
<CreateRoom | |
onCreateRoom={(roomUrl) => { | |
setRoomUrl(roomUrl); | |
setCallState(STATE_JOINING); | |
}} | |
/> | |
); | |
} | |
if (callState === STATE_JOINING) { | |
return <Join roomUrl={roomUrl} onJoin={() => setCallState(STATE_JOINED)} />; | |
} | |
// Main call loop | |
return ( | |
<main className="container py-12"> | |
<div className="grid grid-cols-2 grid-flow-col gap-12"> | |
<div> | |
<Card headerText="Local Webcam"> | |
<div className="overflow-hidden bg-gray-50 sm:rounded-lg"> | |
<div className="aspect-video flex items-center justify-center"> | |
<DailyVideo automirror sessionId={localSessionId} /> | |
</div> | |
</div> | |
</Card> | |
<div className="relative"> | |
<div> | |
<label | |
htmlFor="comment" | |
className="block text-sm font-medium leading-6 text-gray-900" | |
> | |
Add your comment | |
</label> | |
<div className="mt-2"> | |
<textarea | |
rows={4} | |
name="comment" | |
id="comment" | |
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" | |
defaultValue={params.prompt || ""} | |
/> | |
</div> | |
</div> | |
Config - Resolution, Mbps, FPS | |
<button | |
onClick={() => sendAppMessage({ prompt: "Big ol' car" }, "*")} | |
> | |
Send test app message | |
</button> | |
</div> | |
</div> | |
<div> | |
<Card headerText="Inference"> | |
<div className="overflow-hidden bg-gray-50 sm:rounded-lg"> | |
<div className="aspect-video flex items-center justify-center"> | |
{participantIds.length ? ( | |
<DailyVideo sessionId={participantIds[0]} /> | |
) : ( | |
<Avatar /> | |
)} | |
</div> | |
</div> | |
</Card> | |
</div> | |
</div> | |
</main> | |
); | |
} | |