Skip to content

Commit 9fd6637

Browse files
BarVisualizer
1 parent b2fdb7c commit 9fd6637

File tree

7 files changed

+124
-79
lines changed

7 files changed

+124
-79
lines changed

app/ui/_components.tsx

Lines changed: 78 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import {
1212
import { MicrophoneIcon } from '@phosphor-icons/react/dist/ssr';
1313
import { useSession } from '@/components/app/session-provider';
1414
import { AgentControlBar } from '@/components/livekit/agent-control-bar/agent-control-bar';
15+
import { TrackControl } from '@/components/livekit/agent-control-bar/track-control';
1516
import { TrackDeviceSelect } from '@/components/livekit/agent-control-bar/track-device-select';
16-
import { TrackSelector } from '@/components/livekit/agent-control-bar/track-selector';
1717
import { TrackToggle } from '@/components/livekit/agent-control-bar/track-toggle';
1818
import { Alert, AlertDescription, AlertTitle, alertVariants } from '@/components/livekit/alert';
1919
import { AlertToast } from '@/components/livekit/alert-toast';
@@ -285,15 +285,17 @@ export const COMPONENTS = {
285285
</div>
286286

287287
<div className="relative flex flex-col justify-center gap-4">
288-
<AudioBarVisualizer
289-
size={size as audioBarVisualizerVariantsSizeType}
290-
state={state}
291-
audioTrack={micTrackRef!}
292-
barCount={parseInt(barCount) || undefined}
293-
className="mx-auto"
294-
/>
295-
<div className="border-border space-y-4 rounded-xl border p-4">
296-
<div className="text-center">Original BarVisualizer</div>
288+
<div className="grid h-40 place-items-center">
289+
<AudioBarVisualizer
290+
size={size as audioBarVisualizerVariantsSizeType}
291+
state={state}
292+
audioTrack={micTrackRef!}
293+
barCount={parseInt(barCount) || undefined}
294+
className="mx-auto"
295+
/>
296+
</div>
297+
<div className="text-center">Original BarVisualizer</div>
298+
<div className="border-border grid h-40 place-items-center space-y-4 rounded-xl border p-4">
297299
<BarVisualizer
298300
size={size as audioBarVisualizerVariantsSizeType}
299301
state={state}
@@ -330,52 +332,76 @@ export const COMPONENTS = {
330332
},
331333

332334
// Track device select
333-
TrackDeviceSelect: () => (
334-
<Container componentName="TrackDeviceSelect">
335-
<div className="grid grid-cols-2 gap-4">
336-
<div>
337-
<StoryTitle>Size default</StoryTitle>
338-
<TrackDeviceSelect kind="audioinput" />
339-
</div>
340-
<div>
341-
<StoryTitle>Size sm</StoryTitle>
342-
<TrackDeviceSelect size="sm" kind="audioinput" />
343-
</div>
344-
</div>
345-
</Container>
346-
),
335+
// TrackDeviceSelect: () => (
336+
// <Container componentName="TrackDeviceSelect">
337+
// <div className="grid grid-cols-2 gap-4">
338+
// <div>
339+
// <StoryTitle>Size default</StoryTitle>
340+
// <TrackDeviceSelect kind="audioinput" />
341+
// </div>
342+
// <div>
343+
// <StoryTitle>Size sm</StoryTitle>
344+
// <TrackDeviceSelect size="sm" kind="audioinput" />
345+
// </div>
346+
// </div>
347+
// </Container>
348+
// ),
347349

348350
// Track toggle
349-
TrackToggle: () => (
350-
<Container componentName="TrackToggle">
351-
<div className="grid grid-cols-2 gap-4">
352-
<div>
353-
<StoryTitle>Track.Source.Microphone</StoryTitle>
354-
<TrackToggle variant="outline" source={Track.Source.Microphone} />
355-
</div>
356-
<div>
357-
<StoryTitle>Track.Source.Camera</StoryTitle>
358-
<TrackToggle variant="outline" source={Track.Source.Camera} />
359-
</div>
360-
</div>
361-
</Container>
362-
),
351+
// TrackToggle: () => (
352+
// <Container componentName="TrackToggle">
353+
// <div className="grid grid-cols-2 gap-4">
354+
// <div>
355+
// <StoryTitle>Track.Source.Microphone</StoryTitle>
356+
// <TrackToggle variant="outline" source={Track.Source.Microphone} />
357+
// </div>
358+
// <div>
359+
// <StoryTitle>Track.Source.Camera</StoryTitle>
360+
// <TrackToggle variant="outline" source={Track.Source.Camera} />
361+
// </div>
362+
// </div>
363+
// </Container>
364+
// ),
363365

364-
// Track selector
365-
TrackSelector: () => (
366-
<Container componentName="TrackSelector">
367-
<div className="grid grid-cols-2 gap-4">
368-
<div>
369-
<StoryTitle>Track.Source.Camera</StoryTitle>
370-
<TrackSelector kind="videoinput" source={Track.Source.Camera} />
371-
</div>
372-
<div>
373-
<StoryTitle>Track.Source.Microphone</StoryTitle>
374-
<TrackSelector kind="audioinput" source={Track.Source.Microphone} />
366+
// Track control
367+
TrackControl: () => {
368+
const { microphoneTrack, localParticipant } = useLocalParticipant();
369+
const micTrackRef = useMemo<TrackReferenceOrPlaceholder | undefined>(() => {
370+
return {
371+
participant: localParticipant,
372+
source: Track.Source.Microphone,
373+
publication: microphoneTrack,
374+
} as TrackReference;
375+
}, [localParticipant, microphoneTrack]);
376+
377+
useMicrophone();
378+
379+
return (
380+
<Container componentName="TrackSelector">
381+
<div className="grid grid-cols-2 gap-8">
382+
<div className="flex flex-col gap-8">
383+
<div>
384+
<StoryTitle>Track.Source.Microphone</StoryTitle>
385+
<TrackControl kind="audioinput" source={Track.Source.Microphone} />
386+
</div>
387+
<div>
388+
<StoryTitle>Track.Source.Microphone</StoryTitle>
389+
<TrackControl
390+
kind="audioinput"
391+
source={Track.Source.Microphone}
392+
audioTrackRef={micTrackRef}
393+
/>
394+
</div>
395+
</div>
396+
397+
<div>
398+
<StoryTitle>Track.Source.Camera</StoryTitle>
399+
<TrackControl kind="videoinput" source={Track.Source.Camera} />
400+
</div>
375401
</div>
376-
</div>
377-
</Container>
378-
),
402+
</Container>
403+
);
404+
},
379405

380406
// Chat entry
381407
ChatEntry: () => (

app/ui/components/[[...slug]]/page.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ export default function Page() {
1414

1515
return (
1616
<>
17-
<div className="py-8">
18-
<h1 className="text-foreground mb-8 text-5xl font-bold">{componentName}</h1>
19-
{component()}
20-
</div>
17+
<h1 className="text-foreground mb-8 text-5xl font-bold">{componentName}</h1>
18+
{component()}
2119
</>
2220
);
2321
}

app/ui/components/layout.tsx

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

33
import Link from 'next/link';
4+
import { usePathname } from 'next/navigation';
5+
import { cn } from '@/lib/utils';
46
import { COMPONENTS } from '../_components';
57

68
export default function Layout({ children }: { children: React.ReactNode }) {
9+
const pathname = usePathname();
10+
const isActive = (path: string) => pathname === path;
11+
712
return (
813
<div className="grid grid-cols-1 gap-8 md:grid-cols-[100px_1fr_100px]">
9-
<aside className="sticky top-0 hidden md:block">
10-
<div className="flex flex-col gap-1 space-y-4 py-8">
11-
<div className="flex flex-col gap-2">
12-
<h2 className="text-muted-foreground text-sm font-semibold">Components</h2>
13-
{Object.entries(COMPONENTS).map(([componentName]) => (
14+
<aside className="sticky top-0 hidden py-10 md:block">
15+
<div className="flex flex-col gap-2">
16+
<h2 className="text-muted-foreground text-sm font-semibold">
17+
<Link
18+
href="/ui/components"
19+
className={cn(
20+
'text-sm font-semibold underline-offset-4 hover:underline focus:underline',
21+
isActive('/ui/components') && 'underline'
22+
)}
23+
>
24+
Components
25+
</Link>
26+
</h2>
27+
{Object.entries(COMPONENTS)
28+
.sort(([a], [b]) => a.localeCompare(b))
29+
.map(([componentName]) => (
1430
<Link
1531
href={`/ui/components/${componentName}`}
1632
key={componentName}
17-
className="text-sm font-semibold underline-offset-4 hover:underline focus:underline"
33+
className={cn(
34+
'text-sm font-semibold underline-offset-4 hover:underline focus:underline',
35+
isActive(`/ui/components/${componentName}`) && 'underline'
36+
)}
1837
>
1938
{componentName}
2039
</Link>
2140
))}
22-
</div>
2341
</div>
2442
</aside>
2543

app/ui/components/page.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,17 @@ export default function Page() {
1414
</p>
1515

1616
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
17-
{Object.entries(COMPONENTS).map(([componentName]) => (
18-
<Link
19-
href={`/ui/components/${componentName}`}
20-
key={componentName}
21-
className="font-semibold underline-offset-4 hover:underline focus:underline"
22-
>
23-
{componentName}
24-
</Link>
25-
))}
17+
{Object.entries(COMPONENTS)
18+
.sort(([a], [b]) => a.localeCompare(b))
19+
.map(([componentName]) => (
20+
<Link
21+
href={`/ui/components/${componentName}`}
22+
key={componentName}
23+
className="font-semibold underline-offset-4 hover:underline focus:underline"
24+
>
25+
{componentName}
26+
</Link>
27+
))}
2628
</div>
2729

2830
<div className="space-y-20 py-20">

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { cn } from '@/lib/utils';
1212
import { ChatInput } from './chat-input';
1313
import { UseInputControlsProps, useInputControls } from './hooks/use-input-controls';
1414
import { usePublishPermissions } from './hooks/use-publish-permissions';
15-
import { TrackSelector } from './track-selector';
15+
import { TrackControl } from './track-control';
1616

1717
export interface ControlBarControls {
1818
leave?: boolean;
@@ -107,7 +107,7 @@ export function AgentControlBar({
107107
<div className="flex grow gap-1">
108108
{/* Toggle Microphone */}
109109
{visibleControls.microphone && (
110-
<TrackSelector
110+
<TrackControl
111111
kind="audioinput"
112112
aria-label="Toggle microphone"
113113
source={Track.Source.Microphone}
@@ -122,7 +122,7 @@ export function AgentControlBar({
122122

123123
{/* Toggle Camera */}
124124
{visibleControls.camera && (
125-
<TrackSelector
125+
<TrackControl
126126
kind="videoinput"
127127
aria-label="Toggle camera"
128128
source={Track.Source.Camera}

components/livekit/agent-control-bar/track-selector.tsx renamed to components/livekit/agent-control-bar/track-control.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { TrackToggle } from '@/components/livekit/agent-control-bar/track-toggle
66
import { AudioBarVisualizer } from '@/components/livekit/audio-visualizer/audio-bar-visualizer/audio-bar-visualizer';
77
import { cn } from '@/lib/utils';
88

9-
interface TrackSelectorProps {
9+
interface TrackControlProps {
1010
kind: MediaDeviceKind;
1111
source: Parameters<typeof useTrackToggle>[0]['source'];
1212
pressed?: boolean;
@@ -19,7 +19,7 @@ interface TrackSelectorProps {
1919
onActiveDeviceChange?: (deviceId: string) => void;
2020
}
2121

22-
export function TrackSelector({
22+
export function TrackControl({
2323
kind,
2424
source,
2525
pressed,
@@ -30,7 +30,7 @@ export function TrackSelector({
3030
onPressedChange,
3131
onMediaDeviceError,
3232
onActiveDeviceChange,
33-
}: TrackSelectorProps) {
33+
}: TrackControlProps) {
3434
return (
3535
<div className={cn('flex items-center gap-0', className)}>
3636
<TrackToggle

components/livekit/audio-visualizer/audio-bar-visualizer/audio-bar-visualizer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useMemo } from 'react';
22
import { type VariantProps, cva } from 'class-variance-authority';
3+
import { type LocalAudioTrack, type RemoteAudioTrack } from 'livekit-client';
34
import {
45
type AgentState,
56
type TrackReferenceOrPlaceholder,
@@ -77,7 +78,7 @@ export const audioBarVisualizerBarVariants = cva(
7778
interface AudioBarVisualizerProps {
7879
state?: AgentState;
7980
barCount?: number;
80-
audioTrack?: TrackReferenceOrPlaceholder;
81+
audioTrack?: LocalAudioTrack | RemoteAudioTrack | TrackReferenceOrPlaceholder;
8182
className?: string;
8283
barClassName?: string;
8384
}

0 commit comments

Comments
 (0)