react-native-srschat 0.1.42 → 0.1.44
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 +18 -0
- package/lib/commonjs/components/email.js +50 -24
- package/lib/commonjs/components/email.js.map +1 -1
- package/lib/commonjs/components/productCard.js +2 -6
- package/lib/commonjs/components/productCard.js.map +1 -1
- package/lib/commonjs/layout/welcome.js +17 -14
- package/lib/commonjs/layout/welcome.js.map +1 -1
- package/lib/commonjs/utils/audioRecorder.js +49 -21
- package/lib/commonjs/utils/audioRecorder.js.map +1 -1
- package/lib/module/components/email.js +51 -25
- package/lib/module/components/email.js.map +1 -1
- package/lib/module/components/productCard.js +2 -6
- package/lib/module/components/productCard.js.map +1 -1
- package/lib/module/layout/welcome.js +17 -14
- package/lib/module/layout/welcome.js.map +1 -1
- package/lib/module/utils/audioRecorder.js +50 -22
- package/lib/module/utils/audioRecorder.js.map +1 -1
- package/lib/typescript/components/email.d.ts +1 -0
- package/lib/typescript/components/email.d.ts.map +1 -1
- package/lib/typescript/layout/welcome.d.ts +1 -0
- package/lib/typescript/layout/welcome.d.ts.map +1 -1
- package/lib/typescript/utils/audioRecorder.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/components/email.js +113 -55
- package/src/components/productCard.js +2 -2
- package/src/layout/welcome.js +24 -26
- package/src/utils/audioRecorder.js +52 -27
package/src/layout/welcome.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
// Welcome.js
|
|
2
2
|
import React, { useContext } from 'react';
|
|
3
|
-
import { View, Text,
|
|
3
|
+
import { View, Text, TouchableOpacity, ScrollView, StyleSheet } from 'react-native';
|
|
4
4
|
import Ionicons from 'react-native-vector-icons/Ionicons';
|
|
5
5
|
import { AppContext } from '../contexts/AppContext';
|
|
6
6
|
import { WelcomeInput } from '../components/welcomeInput';
|
|
7
7
|
import ButtonComponent from '../components/welcomeButton';
|
|
8
|
-
import { Testing } from '../components/testing';
|
|
9
8
|
import CloudinaryImage from '../utils/cloudinary';
|
|
10
|
-
// import { PoseidonLogo } from '../components/PoseidonLogo';
|
|
11
9
|
|
|
12
10
|
export const Welcome = ({ panHandlers }) => {
|
|
13
11
|
const { setShowModal, uiConfig, onProductCardClick, onAddToCartClick } = useContext(AppContext);
|
|
@@ -19,30 +17,25 @@ export const Welcome = ({ panHandlers }) => {
|
|
|
19
17
|
setShowModal("Icon");
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
// Reset toggleChat in the parent component
|
|
23
20
|
if (typeof uiConfig.setToggleChat === 'function') {
|
|
24
21
|
uiConfig.setToggleChat(false);
|
|
25
22
|
}
|
|
26
23
|
};
|
|
27
24
|
|
|
28
25
|
return (
|
|
29
|
-
<View
|
|
26
|
+
<View style={styles.container}>
|
|
30
27
|
<View style={styles.parentContainer}>
|
|
31
|
-
|
|
32
28
|
{/* Top section */}
|
|
33
29
|
<View style={styles.topContainer}>
|
|
34
30
|
<View style={styles.topHeader}>
|
|
35
|
-
{/*
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
imageStyle={{ width: 150, height: 35 }}
|
|
44
|
-
/>
|
|
45
|
-
<TouchableOpacity onPress={() => handleClick()} style={styles.collapseButton}>
|
|
31
|
+
{/* Logo container with absolute positioning */}
|
|
32
|
+
<View style={styles.logoContainer}>
|
|
33
|
+
<CloudinaryImage
|
|
34
|
+
cldImg="posiden"
|
|
35
|
+
imageStyle={{ width: 150, height: 35 }}
|
|
36
|
+
/>
|
|
37
|
+
</View>
|
|
38
|
+
<TouchableOpacity onPress={handleClick} style={styles.collapseButton}>
|
|
46
39
|
<Ionicons name="close" size={26} color="white" />
|
|
47
40
|
</TouchableOpacity>
|
|
48
41
|
</View>
|
|
@@ -50,8 +43,7 @@ export const Welcome = ({ panHandlers }) => {
|
|
|
50
43
|
<View style={styles.blueContainer}>
|
|
51
44
|
<Text style={styles.welcomeHeader}>Hi 👋</Text>
|
|
52
45
|
<Text style={styles.welcomeBody2}>
|
|
53
|
-
I'm Poseidon, your Heritage Pool+ AI Agent. I can help you during your online
|
|
54
|
-
visit with Product and Account information.
|
|
46
|
+
I'm Poseidon, your Heritage Pool+ AI Agent. I can help you during your online visit with Product and Account information.
|
|
55
47
|
</Text>
|
|
56
48
|
<WelcomeInput />
|
|
57
49
|
<Text style={styles.textBeta}>Beta version. Poseidon is learning!</Text>
|
|
@@ -75,7 +67,7 @@ const styles = StyleSheet.create({
|
|
|
75
67
|
parentContainer: {
|
|
76
68
|
flexGrow: 1,
|
|
77
69
|
backgroundColor: '#004687',
|
|
78
|
-
paddingTop: 60
|
|
70
|
+
paddingTop: 60,
|
|
79
71
|
},
|
|
80
72
|
topContainer: {
|
|
81
73
|
backgroundColor: '#004687',
|
|
@@ -83,14 +75,19 @@ const styles = StyleSheet.create({
|
|
|
83
75
|
},
|
|
84
76
|
topHeader: {
|
|
85
77
|
flexDirection: 'row',
|
|
86
|
-
justifyContent: 'flex-end',
|
|
87
78
|
alignItems: 'center',
|
|
88
79
|
paddingHorizontal: 15,
|
|
89
80
|
paddingTop: 10,
|
|
81
|
+
justifyContent: 'flex-end',
|
|
82
|
+
position: 'relative',
|
|
90
83
|
},
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
logoContainer: {
|
|
85
|
+
position: 'absolute',
|
|
86
|
+
left: 15,
|
|
87
|
+
top: 10,
|
|
88
|
+
// left: '50%',
|
|
89
|
+
// transform: [{ translateX: -65 }],
|
|
90
|
+
// top: 10,
|
|
94
91
|
},
|
|
95
92
|
collapseButton: {
|
|
96
93
|
paddingHorizontal: 15,
|
|
@@ -121,12 +118,12 @@ const styles = StyleSheet.create({
|
|
|
121
118
|
fontSize: 11,
|
|
122
119
|
color: '#f6f6f6',
|
|
123
120
|
fontWeight: '400',
|
|
124
|
-
marginTop: 5
|
|
121
|
+
marginTop: 5,
|
|
125
122
|
},
|
|
126
123
|
bottomContainer: {
|
|
127
124
|
paddingHorizontal: 25,
|
|
128
125
|
backgroundColor: "#f6f6f6",
|
|
129
|
-
paddingTop: 30
|
|
126
|
+
paddingTop: 30,
|
|
130
127
|
},
|
|
131
128
|
welcomeBody: {
|
|
132
129
|
fontSize: 13,
|
|
@@ -137,3 +134,4 @@ const styles = StyleSheet.create({
|
|
|
137
134
|
},
|
|
138
135
|
});
|
|
139
136
|
|
|
137
|
+
export default Welcome;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// audioRecorder.js
|
|
2
2
|
|
|
3
|
-
import { Platform
|
|
4
|
-
import Voice from '@react-native-
|
|
3
|
+
import { Platform } from 'react-native';
|
|
4
|
+
import Voice from '@react-native-voice/voice';
|
|
5
5
|
import { check, PERMISSIONS, request, RESULTS } from 'react-native-permissions';
|
|
6
6
|
import useAsyncStorage from '../hooks/useAsyncStorage';
|
|
7
7
|
|
|
@@ -30,6 +30,12 @@ export async function initVoice(onResult) {
|
|
|
30
30
|
resultCallback = onResult;
|
|
31
31
|
finalResult = '';
|
|
32
32
|
|
|
33
|
+
// Check if Voice module is available
|
|
34
|
+
if (!Voice) {
|
|
35
|
+
console.error('Voice module is not available');
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
33
39
|
// First check if speech recognition is available
|
|
34
40
|
const isAvailable = await Voice.isAvailable();
|
|
35
41
|
if (!isAvailable) {
|
|
@@ -72,7 +78,7 @@ export async function initVoice(onResult) {
|
|
|
72
78
|
};
|
|
73
79
|
|
|
74
80
|
Voice.onSpeechError = async (e) => {
|
|
75
|
-
console.error('onSpeechError: ', e);
|
|
81
|
+
// console.error('onSpeechError: ', e);
|
|
76
82
|
|
|
77
83
|
if (silenceTimer) {
|
|
78
84
|
clearTimeout(silenceTimer);
|
|
@@ -86,13 +92,13 @@ export async function initVoice(onResult) {
|
|
|
86
92
|
await cleanupVoiceSession();
|
|
87
93
|
|
|
88
94
|
// Only send error to callback if it's not a "No speech detected" error
|
|
89
|
-
if (!isNoSpeechError) {
|
|
90
|
-
|
|
91
|
-
} else {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
95
|
+
// if (!isNoSpeechError) {
|
|
96
|
+
// resultCallback(null, e.error?.message || 'Speech recognition error');
|
|
97
|
+
// } else {
|
|
98
|
+
// console.log('No speech detected, ignoring error');
|
|
99
|
+
// // Optionally, call the callback with null parameters or a special indicator
|
|
100
|
+
// resultCallback(null, null); // This won't trigger an error alert in the component
|
|
101
|
+
// }
|
|
96
102
|
};
|
|
97
103
|
|
|
98
104
|
Voice.onSpeechResults = (e) => {
|
|
@@ -164,6 +170,12 @@ const cleanupVoiceSession = async () => {
|
|
|
164
170
|
}
|
|
165
171
|
|
|
166
172
|
try {
|
|
173
|
+
// Check if Voice module is available
|
|
174
|
+
if (!Voice) {
|
|
175
|
+
console.log('Voice module not available during cleanup');
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
167
179
|
// First try to stop if still recognizing
|
|
168
180
|
const isRecognizing = await Voice.isRecognizing();
|
|
169
181
|
if (isRecognizing) {
|
|
@@ -189,7 +201,9 @@ const cleanupVoiceSession = async () => {
|
|
|
189
201
|
console.error('Error in cleanupVoiceSession:', error);
|
|
190
202
|
// Final attempt to destroy on error
|
|
191
203
|
try {
|
|
192
|
-
|
|
204
|
+
if (Voice) {
|
|
205
|
+
await Voice.destroy();
|
|
206
|
+
}
|
|
193
207
|
} catch (e) {
|
|
194
208
|
console.error('Final destroy attempt failed:', e);
|
|
195
209
|
}
|
|
@@ -200,6 +214,12 @@ const cleanupVoiceSession = async () => {
|
|
|
200
214
|
|
|
201
215
|
export async function startRecording() {
|
|
202
216
|
try {
|
|
217
|
+
// Check if Voice module is available
|
|
218
|
+
if (!Voice) {
|
|
219
|
+
console.error('Voice module is not available');
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
|
|
203
223
|
// Ensure cleanup of any existing session
|
|
204
224
|
await cleanupVoiceSession();
|
|
205
225
|
|
|
@@ -221,7 +241,7 @@ export async function startRecording() {
|
|
|
221
241
|
|
|
222
242
|
export async function stopRecording() {
|
|
223
243
|
try {
|
|
224
|
-
if (!isCurrentlyRecording) return;
|
|
244
|
+
if (!isCurrentlyRecording || !Voice) return;
|
|
225
245
|
|
|
226
246
|
// Set this first to prevent race conditions
|
|
227
247
|
isCurrentlyRecording = false;
|
|
@@ -259,13 +279,13 @@ export async function stopRecording() {
|
|
|
259
279
|
|
|
260
280
|
export async function cancelRecording() {
|
|
261
281
|
try {
|
|
282
|
+
if (!Voice) return;
|
|
262
283
|
await Voice.cancel();
|
|
263
284
|
await cleanupVoiceSession();
|
|
264
285
|
} catch (error) {
|
|
265
286
|
console.error('Error canceling voice recognition:', error);
|
|
266
287
|
await cleanupVoiceSession();
|
|
267
288
|
}
|
|
268
|
-
|
|
269
289
|
}
|
|
270
290
|
|
|
271
291
|
export async function requestAudioPermission() {
|
|
@@ -299,24 +319,22 @@ export async function requestAudioPermission() {
|
|
|
299
319
|
|
|
300
320
|
async function requestAndroidPermission() {
|
|
301
321
|
try {
|
|
302
|
-
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
// Request microphone permission
|
|
325
|
+
const micPermission = await request(PERMISSIONS.ANDROID.RECORD_AUDIO);
|
|
326
|
+
if (micPermission !== RESULTS.GRANTED) {
|
|
327
|
+
console.log('Microphone permission denied');
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Skip checking speech recognition services which is causing errors
|
|
303
332
|
const services = await Voice.getSpeechRecognitionServices();
|
|
304
333
|
if (!services || services.length === 0) {
|
|
305
334
|
console.error('No speech recognition services available');
|
|
306
335
|
return false;
|
|
307
336
|
}
|
|
308
|
-
|
|
309
|
-
const granted = await PermissionsAndroid.request(
|
|
310
|
-
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
|
|
311
|
-
{
|
|
312
|
-
title: 'Microphone Permission',
|
|
313
|
-
message: 'This app needs access to your microphone for voice recognition.',
|
|
314
|
-
buttonPositive: 'OK',
|
|
315
|
-
buttonNegative: 'Cancel',
|
|
316
|
-
}
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
return granted === PermissionsAndroid.RESULTS.GRANTED;
|
|
337
|
+
return true;
|
|
320
338
|
} catch (error) {
|
|
321
339
|
console.error('Error requesting Android permission:', error);
|
|
322
340
|
return false;
|
|
@@ -355,13 +373,20 @@ export function resetStoredPermission() {
|
|
|
355
373
|
}
|
|
356
374
|
|
|
357
375
|
export function cleanup() {
|
|
376
|
+
if (!Voice) {
|
|
377
|
+
console.log('Voice module not available during cleanup');
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
|
|
358
381
|
Voice.destroy().then(() => {
|
|
359
382
|
Voice.removeAllListeners();
|
|
360
383
|
cleanupVoiceSession();
|
|
361
384
|
}).catch(error => {
|
|
362
385
|
console.error('Error in cleanup:', error);
|
|
363
386
|
// Try one more time
|
|
364
|
-
Voice
|
|
387
|
+
if (Voice) {
|
|
388
|
+
Voice.destroy().catch(e => console.error('Final cleanup attempt failed:', e));
|
|
389
|
+
}
|
|
365
390
|
});
|
|
366
391
|
}
|
|
367
392
|
|