22
33import { CloseIcon } from "@/components/CloseIcon" ;
44import { NoAgentNotification } from "@/components/NoAgentNotification" ;
5+ import TranscriptionView from "@/components/TranscriptionView" ;
6+ import useCombinedTranscriptions from "@/hooks/useCombinedTranscriptions" ;
57import {
68 AgentState ,
79 BarVisualizer ,
@@ -18,8 +20,6 @@ import { useCallback, useEffect, useState } from "react";
1820import type { ConnectionDetails } from "./api/connection-details/route" ;
1921
2022export default function Page ( ) {
21- const [ agentState , setAgentState ] = useState < AgentState > ( "disconnected" ) ;
22-
2323 const [ room ] = useState ( new Room ( ) ) ;
2424
2525 const onConnectButtonClicked = useCallback ( async ( ) => {
@@ -40,6 +40,7 @@ export default function Page() {
4040 const connectionDetailsData : ConnectionDetails = await response . json ( ) ;
4141
4242 await room . connect ( connectionDetailsData . serverUrl , connectionDetailsData . participantToken ) ;
43+ await room . localParticipant . setMicrophoneEnabled ( true ) ;
4344 } , [ room ] ) ;
4445
4546 useEffect ( ( ) => {
@@ -53,36 +54,46 @@ export default function Page() {
5354 return (
5455 < main data-lk-theme = "default" className = "h-full grid content-center bg-[var(--lk-bg)]" >
5556 < RoomContext . Provider value = { room } >
56- < div className = "lk-room-container grid grid-rows-[2fr_1fr] items-center" >
57- < SimpleVoiceAssistant onStateChange = { setAgentState } />
58- < ControlBar onConnectButtonClicked = { onConnectButtonClicked } agentState = { agentState } />
59- < RoomAudioRenderer />
60- < NoAgentNotification state = { agentState } />
57+ < div className = "lk-room-container" >
58+ < SimpleVoiceAssistant onConnectButtonClicked = { onConnectButtonClicked } />
6159 </ div >
6260 </ RoomContext . Provider >
6361 </ main >
6462 ) ;
6563}
6664
67- function SimpleVoiceAssistant ( props : { onStateChange : ( state : AgentState ) => void } ) {
68- const { state, audioTrack } = useVoiceAssistant ( ) ;
69- useEffect ( ( ) => {
70- props . onStateChange ( state ) ;
71- } , [ props , state ] ) ;
65+ function SimpleVoiceAssistant ( props : { onConnectButtonClicked : ( ) => void } ) {
66+ const { state : agentState } = useVoiceAssistant ( ) ;
7267 return (
73- < div className = "h-[300px] max-w-[90vw] mx-auto" >
74- < BarVisualizer
75- state = { state }
76- barCount = { 5 }
77- trackRef = { audioTrack }
78- className = "agent-visualizer"
79- options = { { minHeight : 24 } }
80- />
81- </ div >
68+ < >
69+ < AnimatePresence >
70+ { agentState === "disconnected" && (
71+ < motion . button
72+ initial = { { opacity : 0 , top : 0 } }
73+ animate = { { opacity : 1 } }
74+ exit = { { opacity : 0 , top : "-10px" } }
75+ transition = { { duration : 1 , ease : [ 0.09 , 1.04 , 0.245 , 1.055 ] } }
76+ className = "uppercase absolute left-1/2 -translate-x-1/2 px-4 py-2 bg-white text-black rounded-md"
77+ onClick = { ( ) => props . onConnectButtonClicked ( ) }
78+ >
79+ Start a conversation
80+ </ motion . button >
81+ ) }
82+ < div className = "w-3/4 lg:w-1/2 mx-auto" >
83+ < TranscriptionView />
84+ </ div >
85+ </ AnimatePresence >
86+
87+ < RoomAudioRenderer />
88+ < NoAgentNotification state = { agentState } />
89+ < div className = "fixed bottom-0 w-full" >
90+ < ControlBar onConnectButtonClicked = { props . onConnectButtonClicked } />
91+ </ div >
92+ </ >
8293 ) ;
8394}
8495
85- function ControlBar ( props : { onConnectButtonClicked : ( ) => void ; agentState : AgentState } ) {
96+ function ControlBar ( props : { onConnectButtonClicked : ( ) => void } ) {
8697 /**
8798 * Use Krisp background noise reduction when available.
8899 * Note: This is only available on Scale plan, see {@link https://livekit.io/pricing | LiveKit Pricing} for more details.
@@ -92,35 +103,32 @@ function ControlBar(props: { onConnectButtonClicked: () => void; agentState: Age
92103 krisp . setNoiseFilterEnabled ( true ) ;
93104 } , [ ] ) ;
94105
106+ const { state : agentState , audioTrack } = useVoiceAssistant ( ) ;
107+
95108 return (
96109 < div className = "relative h-[100px]" >
97110 < AnimatePresence >
98- { props . agentState === "disconnected" && (
99- < motion . button
100- initial = { { opacity : 0 , top : 0 } }
101- animate = { { opacity : 1 } }
102- exit = { { opacity : 0 , top : "-10px" } }
103- transition = { { duration : 1 , ease : [ 0.09 , 1.04 , 0.245 , 1.055 ] } }
104- className = "uppercase absolute left-1/2 -translate-x-1/2 px-4 py-2 bg-white text-black rounded-md"
105- onClick = { ( ) => props . onConnectButtonClicked ( ) }
106- >
107- Start a conversation
108- </ motion . button >
109- ) }
110- </ AnimatePresence >
111- < AnimatePresence >
112- { props . agentState !== "disconnected" && props . agentState !== "connecting" && (
111+ { agentState !== "disconnected" && agentState !== "connecting" && (
113112 < motion . div
114113 initial = { { opacity : 0 , top : "10px" } }
115114 animate = { { opacity : 1 , top : 0 } }
116115 exit = { { opacity : 0 , top : "-10px" } }
117116 transition = { { duration : 0.4 , ease : [ 0.09 , 1.04 , 0.245 , 1.055 ] } }
118- className = "flex h-8 absolute left-1/2 -translate-x-1/2 justify-center "
117+ className = "flex absolute w-full h-full justify-between px-8 sm:px-4 "
119118 >
120- < VoiceAssistantControlBar controls = { { leave : false } } />
121- < DisconnectButton >
122- < CloseIcon />
123- </ DisconnectButton >
119+ < BarVisualizer
120+ state = { agentState }
121+ barCount = { 5 }
122+ trackRef = { audioTrack }
123+ className = "agent-visualizer w-32 gap-2"
124+ options = { { minHeight : 12 } }
125+ />
126+ < div className = "flex items-center" >
127+ < VoiceAssistantControlBar controls = { { leave : false } } />
128+ < DisconnectButton >
129+ < CloseIcon />
130+ </ DisconnectButton >
131+ </ div >
124132 </ motion . div >
125133 ) }
126134 </ AnimatePresence >
0 commit comments