@revrag-ai/embed-react-native 1.0.5 → 1.0.6

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.
Files changed (75) hide show
  1. package/dist/commonjs/Event/onwid.js +70 -0
  2. package/dist/commonjs/NativeOnwid.js +5 -0
  3. package/dist/commonjs/button.json +1 -0
  4. package/dist/commonjs/component/OnwidButton.js +507 -0
  5. package/dist/commonjs/component/audiowave.js +153 -0
  6. package/dist/commonjs/component/voice.js +127 -0
  7. package/dist/commonjs/hooks/initialize.js +96 -0
  8. package/dist/commonjs/hooks/initialize.types.js +2 -0
  9. package/{lib/module → dist/commonjs}/hooks/initializelivekit.js +7 -4
  10. package/dist/commonjs/hooks/voiceAgent.js +353 -0
  11. package/dist/commonjs/hooks/voiceAgent.types.js +4 -0
  12. package/dist/commonjs/index.d.js +22 -0
  13. package/dist/commonjs/index.js +34 -0
  14. package/dist/commonjs/onwidApi/api.js +185 -0
  15. package/dist/commonjs/onwidApi/api.types.js +2 -0
  16. package/dist/commonjs/package.json +1 -0
  17. package/dist/commonjs/store.key.js +38 -0
  18. package/dist/commonjs/style/onwidButton.style.js +243 -0
  19. package/dist/commonjs/utils/reanimatedHelpers.js +94 -0
  20. package/dist/commonjs/utils/utils.js +2 -0
  21. package/dist/module/Event/onwid.js +70 -0
  22. package/dist/module/NativeOnwid.js +5 -0
  23. package/dist/module/button.json +1 -0
  24. package/dist/module/component/OnwidButton.js +507 -0
  25. package/dist/module/component/audiowave.js +153 -0
  26. package/dist/module/component/voice.js +127 -0
  27. package/dist/module/hooks/initialize.js +96 -0
  28. package/dist/module/hooks/initialize.types.js +2 -0
  29. package/dist/module/hooks/initializelivekit.js +17 -0
  30. package/dist/module/hooks/voiceAgent.js +353 -0
  31. package/dist/module/hooks/voiceAgent.types.js +4 -0
  32. package/dist/module/index.d.js +22 -0
  33. package/dist/module/index.js +34 -0
  34. package/dist/module/onwidApi/api.js +185 -0
  35. package/dist/module/onwidApi/api.types.js +2 -0
  36. package/dist/module/store.key.js +38 -0
  37. package/dist/module/style/onwidButton.style.js +243 -0
  38. package/dist/module/utils/reanimatedHelpers.js +94 -0
  39. package/dist/module/utils/utils.js +2 -0
  40. package/{lib → dist}/typescript/Event/onwid.d.ts +1 -0
  41. package/{lib → dist}/typescript/NativeOnwid.d.ts +1 -0
  42. package/{lib → dist}/typescript/component/OnwidButton.d.ts +1 -0
  43. package/{lib → dist}/typescript/component/audiowave.d.ts +1 -0
  44. package/{lib → dist}/typescript/component/voice.d.ts +1 -0
  45. package/{lib → dist}/typescript/hooks/initialize.d.ts +1 -0
  46. package/{lib → dist}/typescript/hooks/initialize.types.d.ts +1 -0
  47. package/{lib → dist}/typescript/hooks/initializelivekit.d.ts +1 -0
  48. package/{lib → dist}/typescript/hooks/voiceAgent.d.ts +1 -0
  49. package/{lib → dist}/typescript/hooks/voiceAgent.types.d.ts +1 -0
  50. package/{lib → dist}/typescript/index.d.ts +3 -3
  51. package/{lib → dist}/typescript/onwidApi/api.d.ts +1 -0
  52. package/{lib → dist}/typescript/onwidApi/api.types.d.ts +1 -0
  53. package/{lib → dist}/typescript/store.key.d.ts +1 -0
  54. package/{lib → dist}/typescript/style/onwidButton.style.d.ts +1 -0
  55. package/{lib → dist}/typescript/utils/reanimatedHelpers.d.ts +1 -0
  56. package/dist/typescript/utils/utils.d.ts +1 -0
  57. package/package.json +29 -21
  58. package/lib/index.d.ts +0 -77
  59. package/lib/module/Event/onwid.js +0 -74
  60. package/lib/module/NativeOnwid.js +0 -4
  61. package/lib/module/component/OnwidButton.js +0 -366
  62. package/lib/module/component/audiowave.js +0 -137
  63. package/lib/module/component/voice.js +0 -103
  64. package/lib/module/hooks/initialize.js +0 -92
  65. package/lib/module/hooks/initialize.types.js +0 -2
  66. package/lib/module/hooks/voiceAgent.js +0 -334
  67. package/lib/module/hooks/voiceAgent.types.js +0 -2
  68. package/lib/module/index.js +0 -61
  69. package/lib/module/onwidApi/api.js +0 -184
  70. package/lib/module/onwidApi/api.types.js +0 -2
  71. package/lib/module/store.key.js +0 -47
  72. package/lib/module/style/onwidButton.style.js +0 -230
  73. package/lib/module/utils/reanimatedHelpers.js +0 -87
  74. package/lib/module/utils/utils.js +0 -1
  75. package/lib/typescript/utils/utils.d.ts +0 -0
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+
3
+ import { AudioSession, LiveKitRoom } from '@livekit/react-native';
4
+ import { useEffect, useRef, useState } from 'react';
5
+
6
+ // export interface VoiceProps {
7
+ // url: string;
8
+ // token: string;
9
+ // onDisconnected: (data: string) => void;
10
+ // onConnected: (data: string) => void;
11
+ // }
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ // Track audio session state globally to prevent multiple starts/stops
14
+ let audioSessionActive = false;
15
+ let audioSessionStarting = false;
16
+ let audioSessionStopping = false;
17
+
18
+ // Track connection to prevent unmounting while connected
19
+ let activeConnectionToken = null;
20
+ const Voice = props => {
21
+ const {
22
+ url,
23
+ token,
24
+ onDisconnected,
25
+ onConnected,
26
+ roomRef
27
+ } = props;
28
+ const [audioSessionStarted, setAudioSessionStarted] = useState(audioSessionActive);
29
+ const mountedRef = useRef(true);
30
+ const connectedRef = useRef(false);
31
+
32
+ // Start audio session safely - prevent multiple simultaneous starts
33
+ const startAudioSession = async () => {
34
+ if (audioSessionActive || audioSessionStarting) {
35
+ console.log('Audio session already active or starting, skipping');
36
+ return;
37
+ }
38
+ try {
39
+ audioSessionStarting = true;
40
+ console.log('Starting audio session');
41
+ await AudioSession.startAudioSession();
42
+ audioSessionActive = true;
43
+ if (mountedRef.current) {
44
+ setAudioSessionStarted(true);
45
+ }
46
+ } catch (err) {
47
+ console.error('Failed to start audio session:', err);
48
+ } finally {
49
+ audioSessionStarting = false;
50
+ }
51
+ };
52
+
53
+ // Stop audio session safely - prevent multiple simultaneous stops
54
+ const stopAudioSession = async () => {
55
+ if (!audioSessionActive || audioSessionStopping) {
56
+ console.log('Audio session already inactive or stopping, skipping');
57
+ return;
58
+ }
59
+ try {
60
+ audioSessionStopping = true;
61
+ console.log('Stopping audio session');
62
+ await AudioSession.stopAudioSession();
63
+ audioSessionActive = false;
64
+ } catch (err) {
65
+ console.error('Failed to stop audio session:', err);
66
+ } finally {
67
+ audioSessionStopping = false;
68
+ }
69
+ };
70
+
71
+ // Setup audio session
72
+ useEffect(() => {
73
+ mountedRef.current = true;
74
+ startAudioSession();
75
+ return () => {
76
+ mountedRef.current = false;
77
+
78
+ // IMPORTANT: Don't stop the audio session on unmount if there might be an active call
79
+ // This prevents audio session start/stop loops when components remount
80
+ if (roomRef.current?.state !== 'connected' && !connectedRef.current) {
81
+ stopAudioSession();
82
+ } else {
83
+ console.log('Skipping audio session stop because room is still connected');
84
+ }
85
+ };
86
+ }, []);
87
+
88
+ // Track connection state changes to avoid unmounting while connected
89
+ useEffect(() => {
90
+ if (token) {
91
+ activeConnectionToken = token;
92
+ }
93
+ return () => {
94
+ // Only clear token when unmounting with this specific token
95
+ if (activeConnectionToken === token) {
96
+ activeConnectionToken = null;
97
+ }
98
+ };
99
+ }, [token]);
100
+
101
+ // Only render LiveKitRoom when audio session is ready
102
+ if (!audioSessionStarted) {
103
+ return null;
104
+ }
105
+
106
+ // IMPORTANT: Never return empty fragment when connected!
107
+ // Instead, always render the LiveKitRoom component to maintain the connection
108
+ return /*#__PURE__*/_jsx(LiveKitRoom, {
109
+ serverUrl: url,
110
+ token: token,
111
+ screen: false,
112
+ audio: true,
113
+ onConnected: () => {
114
+ console.log('LiveKitRoom connected');
115
+ connectedRef.current = true;
116
+ onConnected('connected');
117
+ },
118
+ room: roomRef.current || undefined,
119
+ onDisconnected: () => {
120
+ console.log('LiveKitRoom disconnected');
121
+ connectedRef.current = false;
122
+ onDisconnected('disconnected');
123
+ }
124
+ });
125
+ };
126
+ export default Voice;
127
+ //# sourceMappingURL=voice.js.map
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Custom hook for initializing the OnWid SDK
5
+ *
6
+ * Required Parameters:
7
+ * - apiKey: string - Unique identifier for the user
8
+ * - deviceId: string - Unique identifier for the device
9
+ * - metadata: object - Additional device/user information
10
+ *
11
+ * The initialization process:
12
+ * 1. Validates required input parameters
13
+ * 2. Stores API key securely in keychain
14
+ * 3. Registers the device with provided details
15
+ */
16
+ import { setAgentData } from '../store.key';
17
+ import { APIService } from '../onwidApi/api';
18
+ import registerAgent from './initializelivekit';
19
+ import { PermissionsAndroid, Platform } from 'react-native';
20
+ export function useInitialize({
21
+ apiKey,
22
+ onwidUrl,
23
+ metadata
24
+ }) {
25
+ const checkPermissions = async () => {
26
+ try {
27
+ // Check for required permissions on Android
28
+ if (Platform.OS === 'android') {
29
+ const recordAudioPermission = PermissionsAndroid.PERMISSIONS.RECORD_AUDIO;
30
+ if (!recordAudioPermission) {
31
+ throw new Error('RECORD_AUDIO permission not available');
32
+ }
33
+ const permissions = [recordAudioPermission];
34
+ const results = await Promise.all(permissions.map(permission => PermissionsAndroid.request(permission)));
35
+ const allGranted = results.every(result => result === PermissionsAndroid.RESULTS.GRANTED);
36
+ if (!allGranted) {
37
+ throw new Error('Required permissions not granted');
38
+ }
39
+ }
40
+ } catch (err) {
41
+ const errorMessage = err instanceof Error ? err.message : 'Failed to check permissions';
42
+ throw new Error(errorMessage);
43
+ }
44
+ };
45
+
46
+ /**
47
+ * Validates required initialization parameters
48
+ * @throws Error if any required parameter is missing or invalid
49
+ */
50
+ const validateInputs = () => {
51
+ if (!apiKey || typeof apiKey !== 'string') {
52
+ throw new Error('apiKey is required and must be a string');
53
+ }
54
+ if (!onwidUrl || typeof onwidUrl !== 'string') {
55
+ throw new Error('onwidUrl is required and must be a string');
56
+ }
57
+ if (metadata && typeof metadata === 'object' && !metadata.config) {
58
+ throw new Error('metadata must contain a config object');
59
+ }
60
+ };
61
+ const initialize = async () => {
62
+ try {
63
+ await checkPermissions();
64
+ registerAgent();
65
+
66
+ // Validate required parameters before proceeding
67
+ validateInputs();
68
+
69
+ // Store API key in keychain
70
+ await setAgentData({
71
+ apiKey,
72
+ onwidUrl
73
+ });
74
+
75
+ // Get the APIService instance and initialize it
76
+ const apiService = APIService.getInstance();
77
+ await apiService.initialize();
78
+ console.log('registerOnInitialize');
79
+ // Register new device with provided details
80
+ const registerResponse = await apiService.registerOnInitialize();
81
+ if (!registerResponse.success) {
82
+ throw new Error(registerResponse.error || 'Device registration failed');
83
+ }
84
+ if (registerResponse.data) {
85
+ // todo: store config
86
+ }
87
+ } catch (err) {
88
+ const errorMessage = err instanceof Error ? err.message : 'Initialization failed';
89
+ throw new Error(errorMessage);
90
+ }
91
+ };
92
+
93
+ // Initialize immediately when hook is called
94
+ initialize().catch(console.error);
95
+ }
96
+ //# sourceMappingURL=initialize.js.map
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=initialize.types.js.map
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ // This module imports the `registerGlobals` function from the LiveKit React Native library.
4
+ // The `registerGlobals` function is used to register global settings and configurations
5
+ // for the LiveKit service, which is essential for managing real-time audio and video
6
+ // communication in the application. The `registerAgent` constant is created as an alias
7
+ // for `registerGlobals`, allowing for easier reference in other parts of the application.
8
+ // Finally, the `registerAgent` is exported as the default export of this module, making
9
+ // it available for use in other modules that require the registration of LiveKit globals.
10
+
11
+ import { registerGlobals } from '@livekit/react-native';
12
+
13
+ // The registerAgent constant is an alias for the registerGlobals function,
14
+ // which is used to set up global configurations for the LiveKit service.
15
+ const registerAgent = registerGlobals;
16
+ export default registerAgent;
17
+ //# sourceMappingURL=initializelivekit.js.map
@@ -0,0 +1,353 @@
1
+ "use strict";
2
+
3
+ import { ConnectionState, Room } from 'livekit-client';
4
+ import { useEffect, useState } from 'react';
5
+ import { EventKeys } from '../Event/onwid';
6
+ import { APIService } from '../onwidApi/api';
7
+ import { getAgentData } from '../store.key';
8
+ // Create a singleton instance of Room that persists across hook instances
9
+ // This ensures we don't create multiple Room instances that could conflict
10
+ let roomInstance = null;
11
+ let isConnecting = false;
12
+ let isDisconnecting = false;
13
+ let hasListeners = false;
14
+ let connectionAttempts = 0;
15
+ let stableConnectionTimerId = null;
16
+ const MAX_CONNECTION_ATTEMPTS = 3;
17
+ const STABLE_CONNECTION_TIMEOUT = 5000; // 5 seconds
18
+
19
+ // Create getters for the room instance
20
+ const getRoomInstance = () => {
21
+ if (!roomInstance) {
22
+ console.log('Creating new Room instance');
23
+ // Configure the room with the right options at creation time
24
+ roomInstance = new Room({
25
+ adaptiveStream: true,
26
+ dynacast: true,
27
+ // Using the most stable configuration for React Native
28
+ publishDefaults: {
29
+ simulcast: false // Disable simulcast to reduce SDP complexity
30
+ }
31
+ });
32
+ }
33
+ return roomInstance;
34
+ };
35
+
36
+ // Reset connection attempt counter
37
+ const resetConnectionAttempts = () => {
38
+ connectionAttempts = 0;
39
+
40
+ // Clear any pending stable connection timer
41
+ if (stableConnectionTimerId) {
42
+ clearTimeout(stableConnectionTimerId);
43
+ stableConnectionTimerId = null;
44
+ }
45
+ };
46
+
47
+ // Cleanup function to reset the room state
48
+ const resetRoomState = () => {
49
+ if (roomInstance) {
50
+ try {
51
+ console.log('Resetting room state');
52
+ console.log('isDisconnecting', isDisconnecting);
53
+
54
+ // Only disconnect if currently connected
55
+ if (roomInstance.state !== ConnectionState.Disconnected && !isDisconnecting) {
56
+ isDisconnecting = true;
57
+ roomInstance.disconnect().finally(() => {
58
+ isDisconnecting = false;
59
+ });
60
+ }
61
+
62
+ // Don't destroy the room instance, just reset its state
63
+ hasListeners = false;
64
+ resetConnectionAttempts();
65
+ } catch (e) {
66
+ console.error('Error resetting room state:', e);
67
+ }
68
+ }
69
+ };
70
+ export const useVoiceAgent = () => {
71
+ const [isLoading, setIsLoading] = useState(false);
72
+ const [error, setError] = useState(null);
73
+ const [tokenDetails, setTokenDetails] = useState(null);
74
+ const [isMicMuted, setIsMicMuted] = useState(false);
75
+ const [connectionState, setConnectionState] = useState(() => {
76
+ // Initialize with the current room state if it exists
77
+ const room = getRoomInstance();
78
+ return room ? room.state : ConnectionState.Disconnected;
79
+ });
80
+ const [stableConnection, setStableConnection] = useState(false);
81
+ console.log('ConnectionState_connected', connectionState
82
+ // tokenDetails?.token
83
+ );
84
+
85
+ // Setup event listeners for the room
86
+ const setupRoomListeners = () => {
87
+ if (hasListeners || !roomInstance) return;
88
+ console.log('Setting up room listeners');
89
+ const handleConnectionChange = state => {
90
+ console.log('Connection state changed:', state);
91
+ // Use a function to ensure we're setting with the latest state
92
+ setConnectionState(() => state);
93
+
94
+ // Handle connection state changes
95
+ if (state === ConnectionState.Connected) {
96
+ // Reset connection attempts when connected successfully
97
+ resetConnectionAttempts();
98
+
99
+ // Set up a timer to mark the connection as stable after a few seconds
100
+ // This prevents immediate disconnections from being treated as stable
101
+ if (stableConnectionTimerId) {
102
+ clearTimeout(stableConnectionTimerId);
103
+ }
104
+ stableConnectionTimerId = setTimeout(() => {
105
+ console.log('Connection marked as stable');
106
+ setStableConnection(true);
107
+ }, STABLE_CONNECTION_TIMEOUT);
108
+ } else if (state === ConnectionState.Disconnected) {
109
+ // Mark connection as unstable
110
+ setStableConnection(false);
111
+
112
+ // Clear any pending stable connection timer
113
+ if (stableConnectionTimerId) {
114
+ clearTimeout(stableConnectionTimerId);
115
+ stableConnectionTimerId = null;
116
+ }
117
+
118
+ // If disconnected unexpectedly and we have token details, don't automatically reconnect
119
+ // This prevents connection loops
120
+ if (tokenDetails && !isDisconnecting) {
121
+ console.log('Room disconnected unexpectedly - not auto-reconnecting');
122
+ }
123
+ }
124
+ };
125
+ const handleTrackSubscribed = track => {
126
+ if (track.kind === 'audio') {
127
+ track.setVolume(1.0);
128
+ }
129
+ };
130
+
131
+ // Handle participant disconnected - this could be helpful to detect server-side kicks
132
+ roomInstance.on('participantDisconnected', () => {
133
+ console.log('Participant disconnected from room');
134
+ });
135
+ roomInstance.on('connectionStateChanged', handleConnectionChange);
136
+ roomInstance.on('trackSubscribed', handleTrackSubscribed);
137
+
138
+ // Listen for SDP negotiation errors to handle them better
139
+ roomInstance.on('mediaDevicesError', e => {
140
+ console.log('Media devices error:', e.message);
141
+ });
142
+ hasListeners = true;
143
+ };
144
+
145
+ // Initialize room and listeners
146
+ useEffect(() => {
147
+ const room = getRoomInstance();
148
+ setupRoomListeners();
149
+
150
+ // Sync local state with room state
151
+ setConnectionState(room.state);
152
+ return () => {
153
+ // Do NOT disconnect or destroy the room on component unmount
154
+ // This ensures the singleton persists across component lifecycle
155
+ // But we do want to update local state if the component is unmounted
156
+ if (!tokenDetails) {
157
+ setTokenDetails(null);
158
+ }
159
+ };
160
+ }, []);
161
+
162
+ // Connect to LiveKit when token is set
163
+ useEffect(() => {
164
+ const room = getRoomInstance();
165
+ if (!tokenDetails || isConnecting) return;
166
+
167
+ // Always sync our state with the room's current state
168
+ setConnectionState(room.state);
169
+ const connectToRoom = async () => {
170
+ // Prevent multiple connection attempts
171
+ if (isConnecting) return;
172
+
173
+ // Limit connection attempts to prevent infinite loops
174
+ if (connectionAttempts >= MAX_CONNECTION_ATTEMPTS) {
175
+ console.log(`Maximum connection attempts (${MAX_CONNECTION_ATTEMPTS}) reached. Not trying again.`);
176
+ setError(`Failed to connect after ${MAX_CONNECTION_ATTEMPTS} attempts`);
177
+ return;
178
+ }
179
+ connectionAttempts++;
180
+ try {
181
+ isConnecting = true;
182
+ console.log(`Connecting to LiveKit room... (attempt ${connectionAttempts})`);
183
+
184
+ // Only attempt to connect if we're disconnected
185
+ if (room.state === ConnectionState.Disconnected) {
186
+ // Update state before connection attempt
187
+ setConnectionState(ConnectionState.Connecting);
188
+ await room.connect(tokenDetails.server_url, tokenDetails.token, {
189
+ autoSubscribe: true // Ensure we subscribe to tracks automatically
190
+ });
191
+
192
+ // Explicitly set to connected if connection was successful
193
+ setConnectionState(room.state);
194
+ console.log('Connected to LiveKit room');
195
+ } else if (room.state === ConnectionState.Connected) {
196
+ console.log('Room is already connected');
197
+ // Ensure our state matches
198
+ setConnectionState(ConnectionState.Connected);
199
+ } else {
200
+ console.log('Room is in transition state:', room.state);
201
+ // Sync our state with the room's current state
202
+ setConnectionState(room.state);
203
+ }
204
+ } catch (err) {
205
+ const message = err instanceof Error ? err.message : 'Failed to connect to room';
206
+ setError(message);
207
+ console.error('Connection error:', message);
208
+
209
+ // Sync state to disconnected if we failed to connect
210
+ setConnectionState(room.state);
211
+
212
+ // Don't keep retrying if we hit an SDP error
213
+ if (message.includes('SDP') || message.includes('sdp')) {
214
+ console.log('SDP error detected, will not retry automatically');
215
+ }
216
+ } finally {
217
+ isConnecting = false;
218
+ }
219
+ };
220
+ connectToRoom();
221
+
222
+ // No cleanup here - we don't want to disconnect when token changes or component unmounts
223
+ }, [tokenDetails]);
224
+
225
+ // Log connection status periodically for debugging
226
+ useEffect(() => {
227
+ const debugInterval = setInterval(() => {
228
+ if (roomInstance) {
229
+ const state = roomInstance.state;
230
+ const participantCount = roomInstance.numParticipants;
231
+ console.log(`[DEBUG] Room state: ${state}, Participants: ${participantCount}, Stable: ${stableConnection}`);
232
+ }
233
+ }, 10000); // Every 10 seconds
234
+
235
+ return () => clearInterval(debugInterval);
236
+ }, [stableConnection]);
237
+
238
+ // Generate token and connect
239
+ const generateVoiceToken = async () => {
240
+ console.log('generateVoiceToken');
241
+
242
+ // Don't generate a new token if we're already connecting/connected
243
+ if (isConnecting || isLoading) {
244
+ console.log('Already connecting or loading, skipping token generation');
245
+ return;
246
+ }
247
+
248
+ // Reset connection attempts when starting fresh
249
+ resetConnectionAttempts();
250
+ setStableConnection(false);
251
+ const userData = await getAgentData(EventKeys.USER_DATA);
252
+ setIsLoading(true);
253
+ setError(null);
254
+ console.log('userData', userData);
255
+ try {
256
+ const apiService = APIService.getInstance();
257
+ const response = await apiService.getTokenDetails({
258
+ app_user_id: userData?.app_user_id,
259
+ call_type: 'EMBEDDED'
260
+ });
261
+ if (!response.data) throw new Error('No voice token found');
262
+
263
+ // Only set token details if we're not already connected
264
+ const room = getRoomInstance();
265
+ if (room.state !== ConnectionState.Connected) {
266
+ setTokenDetails(response.data);
267
+ } else {
268
+ console.log('Room already connected, skipping token update');
269
+ }
270
+ } catch (err) {
271
+ const message = err instanceof Error ? err.message : 'Failed to generate voice token';
272
+ setError(message);
273
+ throw new Error(message);
274
+ } finally {
275
+ setIsLoading(false);
276
+ }
277
+ };
278
+
279
+ // End call
280
+ const endCall = async () => {
281
+ if (isDisconnecting) {
282
+ console.log('Already disconnecting, skipping');
283
+ return;
284
+ }
285
+ try {
286
+ console.log('Ending call');
287
+ isDisconnecting = true;
288
+ setTokenDetails(null);
289
+ setIsMicMuted(false);
290
+ resetConnectionAttempts();
291
+ setStableConnection(false);
292
+ const room = getRoomInstance();
293
+ if (room.state !== ConnectionState.Disconnected) {
294
+ // Update state before disconnection
295
+ setConnectionState(ConnectionState.Connecting);
296
+ await room.disconnect();
297
+
298
+ // Update state after disconnection
299
+ setConnectionState(ConnectionState.Disconnected);
300
+ }
301
+ } catch (err) {
302
+ setError(err instanceof Error ? err.message : 'Failed to end call');
303
+ // Make sure state is correctly reflected even if there's an error
304
+ const room = getRoomInstance();
305
+ setConnectionState(room.state);
306
+ } finally {
307
+ isDisconnecting = false;
308
+ }
309
+ };
310
+
311
+ // Mute microphone
312
+ const muteMic = () => {
313
+ const room = getRoomInstance();
314
+ if (room.localParticipant) {
315
+ room.localParticipant.setMicrophoneEnabled(false);
316
+ setIsMicMuted(true);
317
+ console.log('Microphone muted');
318
+ }
319
+ };
320
+
321
+ // Unmute microphone
322
+ const unmuteMic = () => {
323
+ const room = getRoomInstance();
324
+ if (room.localParticipant) {
325
+ room.localParticipant.setMicrophoneEnabled(true);
326
+ setIsMicMuted(false);
327
+ console.log('Microphone unmuted');
328
+ }
329
+ };
330
+
331
+ // Clean up everything (use only when the app is shutting down)
332
+ const cleanup = () => {
333
+ endCall();
334
+ resetRoomState();
335
+ };
336
+ return {
337
+ initializeVoiceAgent: generateVoiceToken,
338
+ endCall,
339
+ muteMic,
340
+ unmuteMic,
341
+ isMicMuted,
342
+ connectionState,
343
+ room: getRoomInstance(),
344
+ tokenDetails,
345
+ isLoading,
346
+ error,
347
+ roomRef: {
348
+ current: getRoomInstance()
349
+ },
350
+ cleanup
351
+ };
352
+ };
353
+ //# sourceMappingURL=voiceAgent.js.map
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=voiceAgent.types.js.map
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * @file index.d.ts
5
+ * @description TypeScript declarations for the Onwid React Native library.
6
+ */
7
+
8
+ // Component declarations
9
+
10
+ // Hook type declarations
11
+
12
+ // Hook declarations
13
+
14
+ // API type declarations
15
+
16
+ // Event system declarations
17
+ export let EventKeys = /*#__PURE__*/function (EventKeys) {
18
+ EventKeys["USER_DATA"] = "user_data";
19
+ EventKeys["SCREEN_STATE"] = "state_data";
20
+ return EventKeys;
21
+ }({});
22
+ //# sourceMappingURL=index.d.js.map
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * @file index.tsx
5
+ * @description Main entry point for the Onwid React Native library.
6
+ * This file exports the core components and utilities for the Onwid SDK.
7
+ */
8
+
9
+ import { OnwidButton as OnwidButtonComponent } from './component/OnwidButton';
10
+ import onwid, { EventKeys } from './Event/onwid';
11
+ import { useInitialize } from './hooks/initialize';
12
+ import registerAgent from './hooks/initializelivekit';
13
+ import { jsx as _jsx } from "react/jsx-runtime";
14
+ /**
15
+ * OnwidButton component that provides a customizable button with menu functionality
16
+ * @returns React component
17
+ */
18
+ export function OnwidButton() {
19
+ return /*#__PURE__*/_jsx(OnwidButtonComponent, {});
20
+ }
21
+
22
+ /**
23
+ * Core exports from the Onwid library
24
+ * @exports
25
+ * @property {OnwidButton} OnwidButton - Custom button component with menu functionality
26
+ * @property {Function} registerAgent - Function to register the Agent (Optional)
27
+ * @property {OnWid} onwid - Event management system instance
28
+ * @property {useInitialize} useInitialize - Hook to initialize the Onwid SDK
29
+ * @property {EventKeys} EventKeys - Available event types
30
+ */
31
+ export { EventKeys, onwid, registerAgent, useInitialize };
32
+
33
+ // Export types for TypeScript projects
34
+ //# sourceMappingURL=index.js.map