@tavus/cvi-ui 0.0.1-beta.3 → 0.0.1-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -59
- package/dev-components/components/README.md +95 -70
- package/dev-components/components/conversation-01/conversation.module.css +7 -1
- package/dev-components/components/conversation-01/index.tsx +38 -45
- package/dev-components/components/{controls → device-select}/index.tsx +5 -5
- package/dev-components/components/hair-check-01/hair-check.module.css +1 -1
- package/dev-components/components/hair-check-01/index.tsx +3 -3
- package/dev-components/components/media-controls/index.tsx +207 -0
- package/dev-components/components/media-controls/media-controls.module.css +49 -0
- package/dev-components/hooks/cvi-events-hooks.tsx +6 -6
- package/dev-components/hooks/use-cvi-call.tsx +7 -0
- package/dist/index.js +173 -134
- package/dist/types/templates/components.d.ts +6 -3
- package/dist/types/templates/jsx/index.d.ts +2 -1
- package/dist/types/templates/tsx/index.d.ts +2 -1
- package/package.json +4 -2
- package/prepare-scripts/create-templates.js +1 -1
- package/src/templates/components.ts +2 -1
- package/src/templates/jsx/components/conversation-01.json +6 -4
- package/src/templates/jsx/components/device-select.json +10 -0
- package/src/templates/jsx/components/hair-check-01.json +5 -4
- package/src/templates/jsx/components/media-controls.json +10 -0
- package/src/templates/jsx/hooks/cvi-events-hooks.json +1 -1
- package/src/templates/jsx/hooks/use-cvi-call.json +1 -1
- package/src/templates/jsx/index.ts +2 -1
- package/src/templates/tsx/components/conversation-01.json +6 -4
- package/src/templates/tsx/components/device-select.json +10 -0
- package/src/templates/tsx/components/hair-check-01.json +5 -4
- package/src/templates/tsx/components/media-controls.json +10 -0
- package/src/templates/tsx/hooks/cvi-events-hooks.json +1 -1
- package/src/templates/tsx/hooks/use-cvi-call.json +1 -1
- package/src/templates/tsx/index.ts +2 -1
- package/dist/templates/components/controls.tsx +0 -279
- package/dist/templates/components/cvi-provider.tsx +0 -9
- package/dist/templates/controls.tsx +0 -279
- package/dist/templates/cvi-hooks.tsx +0 -38
- package/dist/templates/cvi-provider.tsx +0 -9
- package/dist/templates/hooks/cvi-hooks.tsx +0 -38
- package/dist/templates/tsx/components/controls.tsx +0 -279
- package/dist/templates/tsx/components/cvi-provider.tsx +0 -9
- package/dist/types/constants/components.d.ts +0 -59
- package/dist/types/utils/resolve-import.d.ts +0 -2
- package/dist/typescript-XxXP1Woc.js +0 -14
- package/src/templates/jsx/components/controls.json +0 -10
- package/src/templates/tsx/components/controls.json +0 -10
- /package/dev-components/components/{controls/controls.module.css → device-select/device-select.module.css} +0 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A CLI tool for installing and managing CVI (Conversational Video Interface) components for React applications. This library provides pre-built components for creating real-time multimodal video conversations with AI replicas.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quick Start
|
|
6
6
|
|
|
7
7
|
**Initialize the project**:
|
|
8
8
|
|
|
@@ -41,74 +41,30 @@ function App() {
|
|
|
41
41
|
```tsx
|
|
42
42
|
import { Conversation } from './components/cvi/components/conversation';
|
|
43
43
|
|
|
44
|
-
function
|
|
44
|
+
function CVI() {
|
|
45
45
|
return (
|
|
46
|
-
<div
|
|
47
|
-
|
|
46
|
+
<div
|
|
47
|
+
style={{
|
|
48
|
+
width: '100%',
|
|
49
|
+
height: '100%',
|
|
50
|
+
maxWidth: '1200px',
|
|
51
|
+
margin: '0 auto',
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
<Conversation conversationUrl='YOUR_TAVUS_MEETING_URL' onLeave={() => {}} />
|
|
48
55
|
</div>
|
|
49
56
|
);
|
|
50
57
|
}
|
|
51
58
|
```
|
|
52
59
|
|
|
53
|
-
##
|
|
60
|
+
## Documentation
|
|
54
61
|
|
|
55
|
-
|
|
62
|
+
- [CVI Documentation](https://docs.tavus.io/sections/conversational-video-interface/component-library/overview)
|
|
56
63
|
|
|
57
|
-
|
|
64
|
+
## Examples
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- **`controls`** - Video chat control buttons with device selection capabilities
|
|
62
|
-
|
|
63
|
-
- `MicrophoneButton` - Toggle microphone with device dropdown
|
|
64
|
-
- `CameraButton` - Toggle camera with device dropdown
|
|
65
|
-
- `ScreenShareButton` - Toggle screen sharing
|
|
66
|
-
|
|
67
|
-
- **`hair-check-01`** - Pre-call interface for testing and configuring audio/video devices
|
|
68
|
-
|
|
69
|
-
- Live camera preview with mirror effect
|
|
70
|
-
- Permission management and device controls
|
|
71
|
-
- Join interface with loading states
|
|
72
|
-
|
|
73
|
-
- **`conversation-01`** - Conversation component for video chat
|
|
74
|
-
|
|
75
|
-
- Video chat with audio wave indicator
|
|
76
|
-
- Device selection and permission management
|
|
77
|
-
- Screen sharing support
|
|
78
|
-
- Error handling
|
|
79
|
-
|
|
80
|
-
- **`audio-wave`** - Audio wave indicator for conversation
|
|
81
|
-
- Shows active speaker audio level
|
|
82
|
-
|
|
83
|
-
### Hooks
|
|
84
|
-
|
|
85
|
-
#### Core Call Management
|
|
86
|
-
|
|
87
|
-
- **`use-cvi-call`** – Provides basic join and leave functionality for CVI calls.
|
|
88
|
-
- **`use-start-haircheck`** – Manages device-permission checks and initializes the camera to start a haircheck session.
|
|
89
|
-
|
|
90
|
-
#### Media Controls
|
|
91
|
-
|
|
92
|
-
- **`use-local-camera`** – Manages local camera state and toggle functionality.
|
|
93
|
-
- **`use-local-microphone`** – Manages local microphone state and toggle functionality.
|
|
94
|
-
- **`use-local-screenshare`** – Manages screen-share state and toggle functionality.
|
|
95
|
-
- **`use-request-permissions`** – Requests permissions and handles audio processing setup.
|
|
96
|
-
|
|
97
|
-
#### Participant Management
|
|
98
|
-
|
|
99
|
-
- **`use-replica-ids`** – Retrieves Tavus–replica participant IDs.
|
|
100
|
-
- **`use-remote-participant-ids`** – Retrieves remote participant IDs.
|
|
101
|
-
|
|
102
|
-
#### Conversation & Events
|
|
103
|
-
|
|
104
|
-
- **`use-observable-event`** – Listens for CVI events.
|
|
105
|
-
- **`use-send-app-message`** – Sends CVI app messages.
|
|
66
|
+
- [Tavus Examples](https://github.com/Tavus-Engineering/tavus-examples)
|
|
106
67
|
|
|
107
68
|
## License
|
|
108
69
|
|
|
109
70
|
MIT License - see the [LICENSE](LICENSE) file for details.
|
|
110
|
-
|
|
111
|
-
## Related Links
|
|
112
|
-
|
|
113
|
-
- [CVI Documentation](https://docs.tavus.io/sections/conversational-video-interface/cvi-overview)
|
|
114
|
-
- [Tavus Examples](https://github.com/Tavus-Engineering/tavus-examples)
|
|
@@ -2,67 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
## Components
|
|
4
4
|
|
|
5
|
-
### Controls
|
|
6
|
-
|
|
7
|
-
The `Controls` component provides a set of video chat control buttons with integrated device selection capabilities.
|
|
8
|
-
|
|
9
|
-
#### Exported Components:
|
|
10
|
-
|
|
11
|
-
- **`MicrophoneButton`**: A button component that toggles microphone on/off with a dropdown for device selection
|
|
12
|
-
- **`CameraButton`**: A button component that toggles camera on/off with a dropdown for device selection
|
|
13
|
-
- **`ScreenShareButton`**: A button component that toggles screen sharing on/off
|
|
14
|
-
- **`SelectDevice`**: A reusable dropdown component for selecting camera and microphone devices
|
|
15
|
-
|
|
16
|
-
#### Usage:
|
|
17
|
-
|
|
18
|
-
```tsx
|
|
19
|
-
import { MicrophoneButton, CameraButton, ScreenShareButton } from './controls';
|
|
20
|
-
|
|
21
|
-
// Use individual control buttons
|
|
22
|
-
<MicrophoneButton />
|
|
23
|
-
<CameraButton />
|
|
24
|
-
<ScreenShareButton />
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
#### Component Details:
|
|
28
|
-
|
|
29
|
-
**MicrophoneButton**
|
|
30
|
-
|
|
31
|
-
- Toggles microphone mute/unmute state
|
|
32
|
-
- Shows visual indicators for muted/unmuted states
|
|
33
|
-
- Includes device selection dropdown
|
|
34
|
-
- Disabled when microphone is not ready
|
|
35
|
-
- Uses `useLocalMicrophone` and `useDevices` hooks
|
|
36
|
-
|
|
37
|
-
**CameraButton**
|
|
38
|
-
|
|
39
|
-
- Toggles camera on/off
|
|
40
|
-
- Shows visual indicators for camera muted/unmuted states
|
|
41
|
-
- Includes device selection dropdown
|
|
42
|
-
- Disabled when camera is not ready or no camera is available
|
|
43
|
-
- Uses `useLocalCamera` and `useDevices` hooks
|
|
44
|
-
|
|
45
|
-
**ScreenShareButton**
|
|
46
|
-
|
|
47
|
-
- Toggles screen sharing on/off
|
|
48
|
-
- Shows visual feedback with different icons for active/inactive states
|
|
49
|
-
- Uses `useLocalScreenshare` hook
|
|
50
|
-
|
|
51
|
-
**SelectDevice**
|
|
52
|
-
|
|
53
|
-
- Reusable dropdown component for device selection
|
|
54
|
-
- Accepts devices array, current value, disabled state, and onChange handler
|
|
55
|
-
- Includes custom dropdown arrow styling
|
|
56
|
-
|
|
57
|
-
#### Key Features:
|
|
58
|
-
|
|
59
|
-
- Automatic device detection and switching via Daily.co hooks
|
|
60
|
-
- Visual state indicators with SVG icons
|
|
61
|
-
- Accessibility support with screen reader labels (`srOnly` class)
|
|
62
|
-
- Responsive design with mobile-friendly controls
|
|
63
|
-
- Integration with Daily.co device management system
|
|
64
|
-
- CSS modules for scoped styling
|
|
65
|
-
|
|
66
5
|
### Hair Check 01
|
|
67
6
|
|
|
68
7
|
The `HairCheck` component provides a pre-call interface for users to test and configure their audio/video devices before joining a video chat.
|
|
@@ -120,21 +59,14 @@ The `Conversation` component provides a complete video chat interface for one-to
|
|
|
120
59
|
import { Conversation } from './conversation-01';
|
|
121
60
|
|
|
122
61
|
<Conversation
|
|
123
|
-
|
|
62
|
+
conversationUrl={conversationUrl}
|
|
124
63
|
onLeave={() => handleLeaveCall()}
|
|
125
64
|
/>
|
|
126
65
|
```
|
|
127
66
|
|
|
128
67
|
#### Props:
|
|
129
68
|
|
|
130
|
-
- `
|
|
131
|
-
- `conversation_id` (string): Unique identifier for the conversation
|
|
132
|
-
- `conversation_name` (string): Display name for the conversation
|
|
133
|
-
- `status` ('active' | 'ended' | 'error'): Current conversation status
|
|
134
|
-
- `conversation_url` (string): Daily.co room URL for joining
|
|
135
|
-
- `replica_id` (string | null): ID of the AI replica participant
|
|
136
|
-
- `persona_id` (string | null): ID of the persona being used
|
|
137
|
-
- `created_at` (string): Timestamp of conversation creation
|
|
69
|
+
- `conversationUrl` (string): Daily.co room URL for joining
|
|
138
70
|
- `onLeave` (function): Callback when user leaves the conversation
|
|
139
71
|
|
|
140
72
|
### Audio Wave
|
|
@@ -160,3 +92,96 @@ import { AudioWave } from './audio-wave';
|
|
|
160
92
|
#### Props:
|
|
161
93
|
|
|
162
94
|
- `id` (string): The participant's session ID to monitor audio levels for
|
|
95
|
+
|
|
96
|
+
### Media Controls
|
|
97
|
+
|
|
98
|
+
The `media-controls` module provides simple toggle buttons for microphone, camera, and screen sharing, designed for direct use in video chat interfaces.
|
|
99
|
+
|
|
100
|
+
#### Exported Components:
|
|
101
|
+
|
|
102
|
+
- **`MicToggleButton`**: Toggles microphone mute/unmute state
|
|
103
|
+
- **`CameraToggleButton`**: Toggles camera on/off
|
|
104
|
+
- **`ScreenShareButton`**: Toggles screen sharing on/off
|
|
105
|
+
|
|
106
|
+
#### Usage:
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
import { MicToggleButton, CameraToggleButton, ScreenShareButton } from './media-controls';
|
|
110
|
+
|
|
111
|
+
<MicToggleButton />
|
|
112
|
+
<CameraToggleButton />
|
|
113
|
+
<ScreenShareButton />
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### Key Features:
|
|
117
|
+
|
|
118
|
+
- Simple, accessible toggle buttons
|
|
119
|
+
- Visual state indicators (muted, unmuted, on/off)
|
|
120
|
+
- Disabled state when device is not ready
|
|
121
|
+
- Uses Daily.co hooks for device state
|
|
122
|
+
- CSS modules for styling
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
### Device Select
|
|
127
|
+
|
|
128
|
+
The `device-select` module provides advanced device selection controls, including dropdowns for choosing microphones and cameras, and integrated toggle buttons.
|
|
129
|
+
|
|
130
|
+
#### Exported Components:
|
|
131
|
+
|
|
132
|
+
- **`SelectDevice`**: Dropdown for selecting a device from a list
|
|
133
|
+
- **`MicSelectBtn`**: Microphone toggle button with device selection
|
|
134
|
+
- **`CameraSelectBtn`**: Camera toggle button with device selection
|
|
135
|
+
- **`ScreenShareButton`**: Button to toggle screen sharing
|
|
136
|
+
|
|
137
|
+
#### Usage:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { SelectDevice, MicSelectBtn, CameraSelectBtn, ScreenShareButton } from './device-select';
|
|
141
|
+
|
|
142
|
+
<SelectDevice value={currentDeviceId} devices={devices} disabled={false} onChange={setDevice} />
|
|
143
|
+
<MicSelectBtn />
|
|
144
|
+
<CameraSelectBtn />
|
|
145
|
+
<ScreenShareButton />
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### Props (SelectDevice):
|
|
149
|
+
|
|
150
|
+
- `value` (string): Currently selected device ID
|
|
151
|
+
- `devices` (array): List of device objects `{ device: MediaDeviceInfo }[]`
|
|
152
|
+
- `disabled` (boolean): Whether the dropdown is disabled
|
|
153
|
+
- `onChange` (function): Callback when device is changed
|
|
154
|
+
|
|
155
|
+
#### Key Features:
|
|
156
|
+
|
|
157
|
+
- Integrated device selection and toggling
|
|
158
|
+
- Dropdowns for camera/microphone selection
|
|
159
|
+
- Visual state indicators and accessibility support
|
|
160
|
+
- Uses Daily.co device management hooks
|
|
161
|
+
- CSS modules for styling
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
### CVI Provider
|
|
166
|
+
|
|
167
|
+
The `CVIProvider` component wraps your app with the Daily.co provider context, enabling all Daily React hooks and components to function.
|
|
168
|
+
|
|
169
|
+
#### Usage:
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
import { CVIProvider } from './cvi-provider';
|
|
173
|
+
|
|
174
|
+
<CVIProvider>
|
|
175
|
+
{/* your app components */}
|
|
176
|
+
</CVIProvider>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Props:
|
|
180
|
+
|
|
181
|
+
- `children` (ReactNode): Components to be wrapped by the provider
|
|
182
|
+
|
|
183
|
+
#### Key Features:
|
|
184
|
+
|
|
185
|
+
- Provides Daily.co context to all child components
|
|
186
|
+
- Required for using Daily React hooks and video/audio components
|
|
187
|
+
- Simple wrapper for app-level integration
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
overflow: hidden;
|
|
11
11
|
border-radius: 0.5rem;
|
|
12
12
|
max-height: 90vh;
|
|
13
|
-
|
|
13
|
+
background: linear-gradient(135deg, #4b5563 0%, #1f2937 100%);
|
|
14
14
|
background-size: 400% 400%;
|
|
15
15
|
animation: gradient 15s ease infinite;
|
|
16
16
|
}
|
|
@@ -76,6 +76,12 @@
|
|
|
76
76
|
opacity: 0.8;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
.leaveButtonIcon {
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
justify-content: center;
|
|
83
|
+
}
|
|
84
|
+
|
|
79
85
|
/* ReplicaVideo styles */
|
|
80
86
|
.mainVideoContainer {
|
|
81
87
|
background: transparent;
|
|
@@ -1,34 +1,24 @@
|
|
|
1
|
-
import React, { useEffect } from "react";
|
|
1
|
+
import React, { useEffect, useCallback } from "react";
|
|
2
2
|
import {
|
|
3
3
|
DailyAudio,
|
|
4
4
|
DailyVideo,
|
|
5
|
-
useDaily,
|
|
6
5
|
useDevices,
|
|
7
6
|
useLocalSessionId,
|
|
8
7
|
useMeetingState,
|
|
9
8
|
useScreenVideoTrack,
|
|
10
9
|
useVideoTrack
|
|
11
10
|
} from "@daily-co/daily-react";
|
|
12
|
-
import {
|
|
11
|
+
import { MicSelectBtn, CameraSelectBtn, ScreenShareButton } from '../device-select'
|
|
13
12
|
import { useLocalScreenshare } from "../../hooks/use-local-screenshare";
|
|
14
13
|
import { useReplicaIDs } from "../../hooks/use-replica-ids";
|
|
14
|
+
import { useCVICall } from "../../hooks/use-cvi-call";
|
|
15
15
|
import { AudioWave } from "../audio-wave";
|
|
16
16
|
|
|
17
17
|
import styles from "./conversation.module.css";
|
|
18
18
|
|
|
19
|
-
interface ConversationData {
|
|
20
|
-
conversation_id: string;
|
|
21
|
-
conversation_name: string;
|
|
22
|
-
status: 'active' | 'ended' | 'error';
|
|
23
|
-
conversation_url: string;
|
|
24
|
-
replica_id: string | null;
|
|
25
|
-
persona_id: string | null;
|
|
26
|
-
created_at: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
19
|
interface ConversationProps {
|
|
30
20
|
onLeave: () => void;
|
|
31
|
-
|
|
21
|
+
conversationUrl: string;
|
|
32
22
|
}
|
|
33
23
|
|
|
34
24
|
const VideoPreview = React.memo(({ id }: { id: string }) => {
|
|
@@ -76,7 +66,7 @@ const MainVideo = React.memo(() => {
|
|
|
76
66
|
const videoState = useVideoTrack(replicaIds[0]);
|
|
77
67
|
const screenVideoState = useScreenVideoTrack(localId);
|
|
78
68
|
const isScreenSharing = !screenVideoState.isOff;
|
|
79
|
-
// This is one
|
|
69
|
+
// This is one-to-one call, so we can use the first replica id
|
|
80
70
|
const replicaId = replicaIds[0];
|
|
81
71
|
|
|
82
72
|
if (!replicaId) {
|
|
@@ -96,16 +86,16 @@ const MainVideo = React.memo(() => {
|
|
|
96
86
|
automirror
|
|
97
87
|
sessionId={isScreenSharing ? localId : replicaId}
|
|
98
88
|
type={isScreenSharing ? "screenVideo" : "video"}
|
|
99
|
-
className={`${styles.mainVideo}
|
|
100
|
-
${isScreenSharing ? styles.mainVideoScreenSharing : ''}
|
|
89
|
+
className={`${styles.mainVideo}
|
|
90
|
+
${isScreenSharing ? styles.mainVideoScreenSharing : ''}
|
|
101
91
|
${videoState.isOff ? styles.mainVideoHidden : ''}`}
|
|
102
92
|
/>
|
|
103
93
|
</div>
|
|
104
94
|
);
|
|
105
95
|
});
|
|
106
96
|
|
|
107
|
-
export const Conversation = React.memo(({ onLeave,
|
|
108
|
-
const
|
|
97
|
+
export const Conversation = React.memo(({ onLeave, conversationUrl }: ConversationProps) => {
|
|
98
|
+
const { joinCall, leaveCall } = useCVICall();
|
|
109
99
|
const meetingState = useMeetingState();
|
|
110
100
|
const { hasMicError } = useDevices()
|
|
111
101
|
|
|
@@ -117,12 +107,13 @@ export const Conversation = React.memo(({ onLeave, conversation }: ConversationP
|
|
|
117
107
|
|
|
118
108
|
// Initialize call when conversation is available
|
|
119
109
|
useEffect(() => {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
110
|
+
joinCall({ url: conversationUrl });
|
|
111
|
+
}, []);
|
|
112
|
+
|
|
113
|
+
const handleLeave = useCallback(() => {
|
|
114
|
+
leaveCall();
|
|
115
|
+
onLeave();
|
|
116
|
+
}, [leaveCall, onLeave]);
|
|
126
117
|
|
|
127
118
|
return (
|
|
128
119
|
<div className={styles.container}>
|
|
@@ -149,27 +140,29 @@ export const Conversation = React.memo(({ onLeave, conversation }: ConversationP
|
|
|
149
140
|
|
|
150
141
|
<div className={styles.footer}>
|
|
151
142
|
<div className={styles.footerControls}>
|
|
152
|
-
<
|
|
153
|
-
<
|
|
143
|
+
<MicSelectBtn />
|
|
144
|
+
<CameraSelectBtn />
|
|
154
145
|
<ScreenShareButton />
|
|
155
|
-
<button type="button" className={styles.leaveButton} onClick={
|
|
156
|
-
<
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
146
|
+
<button type="button" className={styles.leaveButton} onClick={handleLeave}>
|
|
147
|
+
<span className={styles.leaveButtonIcon}>
|
|
148
|
+
<svg
|
|
149
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
150
|
+
width="24"
|
|
151
|
+
height="24"
|
|
152
|
+
viewBox="0 0 24 24"
|
|
153
|
+
fill="none"
|
|
154
|
+
role="img"
|
|
155
|
+
aria-label="Leave Call"
|
|
156
|
+
>
|
|
157
|
+
<path
|
|
158
|
+
d="M18 6L6 18M6 6L18 18"
|
|
159
|
+
stroke="currentColor"
|
|
160
|
+
strokeWidth="2"
|
|
161
|
+
strokeLinecap="round"
|
|
162
|
+
strokeLinejoin="round"
|
|
163
|
+
/>
|
|
164
|
+
</svg>
|
|
165
|
+
</span>
|
|
173
166
|
</button>
|
|
174
167
|
</div>
|
|
175
168
|
</div>
|
|
@@ -3,7 +3,7 @@ import { useDevices } from "@daily-co/daily-react";
|
|
|
3
3
|
import { useLocalCamera } from "../../hooks/use-local-camera";
|
|
4
4
|
import { useLocalMicrophone } from "../../hooks/use-local-microphone";
|
|
5
5
|
import { useLocalScreenshare } from "../../hooks/use-local-screenshare";
|
|
6
|
-
import styles from "./
|
|
6
|
+
import styles from "./device-select.module.css";
|
|
7
7
|
|
|
8
8
|
export const SelectDevice = ({
|
|
9
9
|
value,
|
|
@@ -39,7 +39,7 @@ export const SelectDevice = ({
|
|
|
39
39
|
);
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
export const
|
|
42
|
+
export const MicSelectBtn = memo(() => {
|
|
43
43
|
const { onToggleMicrophone, isMicReady, isMicMuted } = useLocalMicrophone();
|
|
44
44
|
const { microphones, currentMic, setMicrophone } = useDevices();
|
|
45
45
|
|
|
@@ -129,9 +129,9 @@ export const MicrophoneButton = memo(() => {
|
|
|
129
129
|
);
|
|
130
130
|
});
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
MicSelectBtn.displayName = "MicSelectBtn";
|
|
133
133
|
|
|
134
|
-
export const
|
|
134
|
+
export const CameraSelectBtn = memo(() => {
|
|
135
135
|
const { onToggleCamera, isCamReady, isCamMuted } = useLocalCamera();
|
|
136
136
|
const { currentCam, cameras, setCamera } = useDevices();
|
|
137
137
|
|
|
@@ -209,7 +209,7 @@ export const CameraButton = memo(() => {
|
|
|
209
209
|
);
|
|
210
210
|
});
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
CameraSelectBtn.displayName = "CameraSelectBtn";
|
|
213
213
|
|
|
214
214
|
export const ScreenShareButton = memo(() => {
|
|
215
215
|
const { onToggleScreenshare, isScreenSharing } = useLocalScreenshare();
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
DailyVideo,
|
|
4
4
|
useDaily,
|
|
5
5
|
} from "@daily-co/daily-react";
|
|
6
|
-
import {
|
|
6
|
+
import { CameraSelectBtn, MicSelectBtn } from "../device-select";
|
|
7
7
|
import { useStartHaircheck } from "../../hooks/use-start-haircheck";
|
|
8
8
|
import { useLocalCamera } from "../../hooks/use-local-camera";
|
|
9
9
|
|
|
@@ -172,8 +172,8 @@ export const HairCheck = memo(({
|
|
|
172
172
|
/>}
|
|
173
173
|
</div>
|
|
174
174
|
<div className={styles.haircheckControls}>
|
|
175
|
-
<
|
|
176
|
-
<
|
|
175
|
+
<MicSelectBtn />
|
|
176
|
+
<CameraSelectBtn />
|
|
177
177
|
</div>
|
|
178
178
|
</div>
|
|
179
179
|
</div>
|