Skip to content

Commit abca768

Browse files
chore: migrate to useSession hook
1 parent 11fc465 commit abca768

File tree

14 files changed

+163
-256
lines changed

14 files changed

+163
-256
lines changed

app/ui/layout.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1-
import * as React from 'react';
21
import { headers } from 'next/headers';
3-
import { SessionProvider } from '@/components/app/session-provider';
2+
import { ConnectionProvider } from '@/hooks/useConnection';
43
import { getAppConfig } from '@/lib/utils';
54

6-
export default async function ComponentsLayout({ children }: { children: React.ReactNode }) {
5+
interface LayoutProps {
6+
children: React.ReactNode;
7+
}
8+
9+
export default async function Layout({ children }: LayoutProps) {
710
const hdrs = await headers();
811
const appConfig = await getAppConfig(hdrs);
912

1013
return (
11-
<SessionProvider appConfig={appConfig}>
14+
<ConnectionProvider appConfig={appConfig}>
1215
<div className="bg-muted/20 min-h-svh p-8">
1316
<div className="mx-auto max-w-3xl space-y-8">
1417
<header className="space-y-2">
1518
<h1 className="text-5xl font-bold tracking-tight">LiveKit UI</h1>
1619
<p className="text-muted-foreground max-w-80 leading-tight text-pretty">
17-
A set of UI components for building LiveKit-powered voice experiences.
20+
A set of UI Layouts for building LiveKit-powered voice experiences.
1821
</p>
1922
<p className="text-muted-foreground max-w-prose text-balance">
2023
Built with{' '}
@@ -37,6 +40,6 @@ export default async function ComponentsLayout({ children }: { children: React.R
3740
<main className="space-y-20">{children}</main>
3841
</div>
3942
</div>
40-
</SessionProvider>
43+
</ConnectionProvider>
4144
);
4245
}

components/app/app.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,23 @@
22

33
import { RoomAudioRenderer, StartAudio } from '@livekit/components-react';
44
import type { AppConfig } from '@/app-config';
5-
import { SessionProvider } from '@/components/app/session-provider';
65
import { ViewController } from '@/components/app/view-controller';
76
import { Toaster } from '@/components/livekit/toaster';
7+
import { ConnectionProvider } from '@/hooks/useConnection';
88

99
interface AppProps {
1010
appConfig: AppConfig;
1111
}
1212

1313
export function App({ appConfig }: AppProps) {
1414
return (
15-
<SessionProvider appConfig={appConfig}>
15+
<ConnectionProvider appConfig={appConfig}>
1616
<main className="grid h-svh grid-cols-1 place-content-center">
17-
<ViewController />
17+
<ViewController appConfig={appConfig} />
1818
</main>
1919
<StartAudio label="Start Audio" />
2020
<RoomAudioRenderer />
2121
<Toaster />
22-
</SessionProvider>
22+
</ConnectionProvider>
2323
);
2424
}

components/app/chat-transcript.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client';
22

33
import { AnimatePresence, type HTMLMotionProps, motion } from 'motion/react';
4-
import { type ReceivedChatMessage } from '@livekit/components-react';
4+
import { type ReceivedMessage } from '@livekit/components-react';
55
import { ChatEntry } from '@/components/livekit/chat-entry';
66

77
const MotionContainer = motion.create('div');
@@ -50,7 +50,7 @@ const MESSAGE_MOTION_PROPS = {
5050

5151
interface ChatTranscriptProps {
5252
hidden?: boolean;
53-
messages?: ReceivedChatMessage[];
53+
messages?: ReceivedMessage[];
5454
}
5555

5656
export function ChatTranscript({
@@ -62,10 +62,9 @@ export function ChatTranscript({
6262
<AnimatePresence>
6363
{!hidden && (
6464
<MotionContainer {...CONTAINER_MOTION_PROPS} {...props}>
65-
{messages.map(({ id, timestamp, from, message, editTimestamp }: ReceivedChatMessage) => {
65+
{messages.map(({ id, timestamp, from, message }: ReceivedMessage) => {
6666
const locale = navigator?.language ?? 'en-US';
6767
const messageOrigin = from?.isLocal ? 'local' : 'remote';
68-
const hasBeenEdited = !!editTimestamp;
6968

7069
return (
7170
<MotionChatEntry
@@ -74,7 +73,6 @@ export function ChatTranscript({
7473
timestamp={timestamp}
7574
message={message}
7675
messageOrigin={messageOrigin}
77-
hasBeenEdited={hasBeenEdited}
7876
{...MESSAGE_MOTION_PROPS}
7977
/>
8078
);

components/app/preconnect-message.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client';
22

33
import { AnimatePresence, motion } from 'motion/react';
4-
import { type ReceivedChatMessage } from '@livekit/components-react';
4+
import { type ReceivedMessage } from '@livekit/components-react';
55
import { ShimmerText } from '@/components/livekit/shimmer-text';
66
import { cn } from '@/lib/utils';
77

@@ -32,7 +32,7 @@ const VIEW_MOTION_PROPS = {
3232
};
3333

3434
interface PreConnectMessageProps {
35-
messages?: ReceivedChatMessage[];
35+
messages?: ReceivedMessage[];
3636
className?: string;
3737
}
3838

components/app/session-provider.tsx

Lines changed: 0 additions & 41 deletions
This file was deleted.

components/app/session-view.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import React, { useEffect, useRef, useState } from 'react';
44
import { motion } from 'motion/react';
5+
import { useSessionContext, useSessionMessages } from '@livekit/components-react';
56
import type { AppConfig } from '@/app-config';
67
import { ChatTranscript } from '@/components/app/chat-transcript';
78
import { PreConnectMessage } from '@/components/app/preconnect-message';
@@ -10,7 +11,6 @@ import {
1011
AgentControlBar,
1112
type ControlBarControls,
1213
} from '@/components/livekit/agent-control-bar/agent-control-bar';
13-
import { useChatMessages } from '@/hooks/useChatMessages';
1414
import { useConnectionTimeout } from '@/hooks/useConnectionTimout';
1515
import { useDebugMode } from '@/hooks/useDebug';
1616
import { cn } from '@/lib/utils';
@@ -58,6 +58,7 @@ export function Fade({ top = false, bottom = false, className }: FadeProps) {
5858
/>
5959
);
6060
}
61+
6162
interface SessionViewProps {
6263
appConfig: AppConfig;
6364
}
@@ -66,10 +67,11 @@ export const SessionView = ({
6667
appConfig,
6768
...props
6869
}: React.ComponentProps<'section'> & SessionViewProps) => {
69-
useConnectionTimeout(200_000);
70+
useConnectionTimeout(20_000);
7071
useDebugMode({ enabled: IN_DEVELOPMENT });
7172

72-
const messages = useChatMessages();
73+
const session = useSessionContext();
74+
const { messages } = useSessionMessages(session);
7375
const [chatOpen, setChatOpen] = useState(false);
7476
const scrollAreaRef = useRef<HTMLDivElement>(null);
7577

components/app/view-controller.tsx

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
'use client';
22

3-
import { useRef } from 'react';
4-
import { AnimatePresence, motion } from 'motion/react';
5-
import { useRoomContext } from '@livekit/components-react';
6-
import { useSession } from '@/components/app/session-provider';
3+
import { useCallback } from 'react';
4+
import { AnimatePresence, type AnimationDefinition, motion } from 'motion/react';
5+
import { useSessionContext } from '@livekit/components-react';
6+
import { AppConfig } from '@/app-config';
77
import { SessionView } from '@/components/app/session-view';
88
import { WelcomeView } from '@/components/app/welcome-view';
9+
import { useConnection } from '@/hooks/useConnection';
910

1011
const MotionWelcomeView = motion.create(WelcomeView);
1112
const MotionSessionView = motion.create(SessionView);
@@ -28,34 +29,36 @@ const VIEW_MOTION_PROPS = {
2829
},
2930
};
3031

31-
export function ViewController() {
32-
const room = useRoomContext();
33-
const isSessionActiveRef = useRef(false);
34-
const { appConfig, isSessionActive, startSession } = useSession();
32+
interface ViewControllerProps {
33+
appConfig: AppConfig;
34+
}
3535

36-
// animation handler holds a reference to stale isSessionActive value
37-
isSessionActiveRef.current = isSessionActive;
36+
export function ViewController({ appConfig }: ViewControllerProps) {
37+
const session = useSessionContext();
38+
const { isConnected, connect } = useConnection();
3839

39-
// disconnect room after animation completes
40-
const handleAnimationComplete = () => {
41-
if (!isSessionActiveRef.current && room.state !== 'disconnected') {
42-
room.disconnect();
43-
}
44-
};
40+
const handleAnimationComplete = useCallback(
41+
(definition: AnimationDefinition) => {
42+
if (definition === 'hidden') {
43+
session.end();
44+
}
45+
},
46+
[session]
47+
);
4548

4649
return (
4750
<AnimatePresence mode="wait">
4851
{/* Welcome screen */}
49-
{!isSessionActive && (
52+
{!isConnected && (
5053
<MotionWelcomeView
5154
key="welcome"
5255
{...VIEW_MOTION_PROPS}
53-
startButtonText={appConfig.startButtonText}
54-
onStartCall={startSession}
56+
startButtonText={appConfig?.startButtonText ?? ''}
57+
onStartCall={connect}
5558
/>
5659
)}
5760
{/* Session view */}
58-
{isSessionActive && (
61+
{isConnected && (
5962
<MotionSessionView
6063
key="session-view"
6164
{...VIEW_MOTION_PROPS}

components/livekit/agent-control-bar/agent-control-bar.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { type HTMLAttributes, useCallback, useState } from 'react';
44
import { Track } from 'livekit-client';
55
import { useChat, useRemoteParticipants } from '@livekit/components-react';
66
import { ChatTextIcon, PhoneDisconnectIcon } from '@phosphor-icons/react/dist/ssr';
7-
import { useSession } from '@/components/app/session-provider';
87
import { TrackToggle } from '@/components/livekit/agent-control-bar/track-toggle';
98
import { Button } from '@/components/livekit/button';
109
import { Toggle } from '@/components/livekit/toggle';
10+
import { useConnection } from '@/hooks/useConnection';
1111
import { cn } from '@/lib/utils';
1212
import { ChatInput } from './chat-input';
1313
import { UseInputControlsProps, useInputControls } from './hooks/use-input-controls';
@@ -24,7 +24,6 @@ export interface ControlBarControls {
2424

2525
export interface AgentControlBarProps extends UseInputControlsProps {
2626
controls?: ControlBarControls;
27-
onDisconnect?: () => void;
2827
onChatOpenChange?: (open: boolean) => void;
2928
onDeviceError?: (error: { source: Track.Source; error: Error }) => void;
3029
}
@@ -36,7 +35,6 @@ export function AgentControlBar({
3635
controls,
3736
saveUserChoices = true,
3837
className,
39-
onDisconnect,
4038
onDeviceError,
4139
onChatOpenChange,
4240
...props
@@ -45,8 +43,7 @@ export function AgentControlBar({
4543
const participants = useRemoteParticipants();
4644
const [chatOpen, setChatOpen] = useState(false);
4745
const publishPermissions = usePublishPermissions();
48-
const { isSessionActive, endSession } = useSession();
49-
46+
const { isConnected, disconnect } = useConnection();
5047
const {
5148
micTrackRef,
5249
cameraToggle,
@@ -70,11 +67,6 @@ export function AgentControlBar({
7067
[onChatOpenChange, setChatOpen]
7168
);
7269

73-
const handleDisconnect = useCallback(async () => {
74-
endSession();
75-
onDisconnect?.();
76-
}, [endSession, onDisconnect]);
77-
7870
const visibleControls = {
7971
leave: controls?.leave ?? true,
8072
microphone: controls?.microphone ?? publishPermissions.microphone,
@@ -164,8 +156,8 @@ export function AgentControlBar({
164156
{visibleControls.leave && (
165157
<Button
166158
variant="destructive"
167-
onClick={handleDisconnect}
168-
disabled={!isSessionActive}
159+
onClick={disconnect}
160+
disabled={!isConnected}
169161
className="font-mono"
170162
>
171163
<PhoneDisconnectIcon weight="bold" />

hooks/useChatMessages.ts

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)