react-native-srschat 0.1.18 → 0.1.20

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 (91) hide show
  1. package/README.md +2 -0
  2. package/lib/commonjs/components/email.js +6 -5
  3. package/lib/commonjs/components/email.js.map +1 -1
  4. package/lib/commonjs/components/header.js +12 -20
  5. package/lib/commonjs/components/header.js.map +1 -1
  6. package/lib/commonjs/components/input.js +4 -2
  7. package/lib/commonjs/components/input.js.map +1 -1
  8. package/lib/commonjs/components/productCard.js +5 -1
  9. package/lib/commonjs/components/productCard.js.map +1 -1
  10. package/lib/commonjs/components/progressCircle.js +99 -0
  11. package/lib/commonjs/components/progressCircle.js.map +1 -0
  12. package/lib/commonjs/components/voice.js +96 -0
  13. package/lib/commonjs/components/voice.js.map +1 -0
  14. package/lib/commonjs/components/welcomeInput.js +3 -1
  15. package/lib/commonjs/components/welcomeInput.js.map +1 -1
  16. package/lib/commonjs/contexts/AppContext.js +6 -1
  17. package/lib/commonjs/contexts/AppContext.js.map +1 -1
  18. package/lib/commonjs/hooks/stream.js +9 -9
  19. package/lib/commonjs/hooks/stream.js.map +1 -1
  20. package/lib/commonjs/layout/disclaimer.js +1 -1
  21. package/lib/commonjs/layout/disclaimer.js.map +1 -1
  22. package/lib/commonjs/layout/layout.js +11 -26
  23. package/lib/commonjs/layout/layout.js.map +1 -1
  24. package/lib/commonjs/layout/welcome.js +4 -3
  25. package/lib/commonjs/layout/welcome.js.map +1 -1
  26. package/lib/commonjs/layout/window.js +85 -7
  27. package/lib/commonjs/layout/window.js.map +1 -1
  28. package/lib/commonjs/utils/audioRecorder.js +287 -0
  29. package/lib/commonjs/utils/audioRecorder.js.map +1 -0
  30. package/lib/commonjs/utils/textToSpeech.js +45 -0
  31. package/lib/commonjs/utils/textToSpeech.js.map +1 -0
  32. package/lib/module/components/email.js +6 -5
  33. package/lib/module/components/email.js.map +1 -1
  34. package/lib/module/components/header.js +12 -20
  35. package/lib/module/components/header.js.map +1 -1
  36. package/lib/module/components/input.js +4 -2
  37. package/lib/module/components/input.js.map +1 -1
  38. package/lib/module/components/productCard.js +4 -1
  39. package/lib/module/components/productCard.js.map +1 -1
  40. package/lib/module/components/progressCircle.js +90 -0
  41. package/lib/module/components/progressCircle.js.map +1 -0
  42. package/lib/module/components/voice.js +86 -0
  43. package/lib/module/components/voice.js.map +1 -0
  44. package/lib/module/components/welcomeInput.js +3 -1
  45. package/lib/module/components/welcomeInput.js.map +1 -1
  46. package/lib/module/contexts/AppContext.js +6 -1
  47. package/lib/module/contexts/AppContext.js.map +1 -1
  48. package/lib/module/hooks/stream.js +9 -9
  49. package/lib/module/hooks/stream.js.map +1 -1
  50. package/lib/module/layout/disclaimer.js +1 -1
  51. package/lib/module/layout/disclaimer.js.map +1 -1
  52. package/lib/module/layout/layout.js +11 -26
  53. package/lib/module/layout/layout.js.map +1 -1
  54. package/lib/module/layout/welcome.js +2 -3
  55. package/lib/module/layout/welcome.js.map +1 -1
  56. package/lib/module/layout/window.js +85 -7
  57. package/lib/module/layout/window.js.map +1 -1
  58. package/lib/module/utils/audioRecorder.js +275 -0
  59. package/lib/module/utils/audioRecorder.js.map +1 -0
  60. package/lib/module/utils/textToSpeech.js +34 -0
  61. package/lib/module/utils/textToSpeech.js.map +1 -0
  62. package/lib/typescript/components/input.d.ts.map +1 -1
  63. package/lib/typescript/components/productCard.d.ts.map +1 -1
  64. package/lib/typescript/components/progressCircle.d.ts +3 -0
  65. package/lib/typescript/components/progressCircle.d.ts.map +1 -0
  66. package/lib/typescript/components/voice.d.ts +3 -0
  67. package/lib/typescript/components/voice.d.ts.map +1 -0
  68. package/lib/typescript/components/welcomeInput.d.ts.map +1 -1
  69. package/lib/typescript/contexts/AppContext.d.ts.map +1 -1
  70. package/lib/typescript/layout/layout.d.ts.map +1 -1
  71. package/lib/typescript/layout/window.d.ts.map +1 -1
  72. package/lib/typescript/utils/audioRecorder.d.ts +7 -0
  73. package/lib/typescript/utils/audioRecorder.d.ts.map +1 -0
  74. package/lib/typescript/utils/textToSpeech.d.ts +2 -0
  75. package/lib/typescript/utils/textToSpeech.d.ts.map +1 -0
  76. package/package.json +8 -3
  77. package/src/components/email.js +7 -7
  78. package/src/components/header.js +12 -10
  79. package/src/components/input.js +5 -4
  80. package/src/components/productCard.js +3 -0
  81. package/src/components/progressCircle.js +86 -0
  82. package/src/components/voice.js +111 -0
  83. package/src/components/welcomeInput.js +8 -4
  84. package/src/contexts/AppContext.js +6 -1
  85. package/src/hooks/stream.js +2 -2
  86. package/src/layout/disclaimer.js +1 -1
  87. package/src/layout/layout.js +11 -15
  88. package/src/layout/welcome.js +1 -1
  89. package/src/layout/window.js +65 -7
  90. package/src/utils/audioRecorder.js +320 -0
  91. package/src/utils/textToSpeech.js +38 -0
@@ -1 +1 @@
1
- {"version":3,"file":"AppContext.d.ts","sourceRoot":"","sources":["../../../src/contexts/AppContext.js"],"names":[],"mappings":"AAKA,4CAA0C;AAEnC;;;;;;sBAoQN;kBA3Q6E,OAAO"}
1
+ {"version":3,"file":"AppContext.d.ts","sourceRoot":"","sources":["../../../src/contexts/AppContext.js"],"names":[],"mappings":"AAKA,4CAA0C;AAEnC;;;;;;sBAyQN;kBAhR6E,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/layout/layout.js"],"names":[],"mappings":"AAWO,4CAuGN;kBAlH8D,OAAO"}
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/layout/layout.js"],"names":[],"mappings":"AAWO,4CA0GN;kBArH8D,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/layout/window.js"],"names":[],"mappings":"AAcO;;sBAoHN;kBAlI8D,OAAO"}
1
+ {"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/layout/window.js"],"names":[],"mappings":"AAeO;;sBA2IN;kBA1J8D,OAAO"}
@@ -0,0 +1,7 @@
1
+ export function initVoice(onResult: any): Promise<boolean>;
2
+ export function startRecording(): Promise<boolean>;
3
+ export function stopRecording(): Promise<void>;
4
+ export function cancelRecording(): Promise<void>;
5
+ export function requestAudioPermission(): Promise<boolean>;
6
+ export function cleanup(): void;
7
+ //# sourceMappingURL=audioRecorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioRecorder.d.ts","sourceRoot":"","sources":["../../../src/utils/audioRecorder.js"],"names":[],"mappings":"AAaA,2DA4FC;AAuED,mDAmBC;AAED,+CAoCC;AAED,iDASC;AAED,2DAQC;AAuDD,gCASC"}
@@ -0,0 +1,2 @@
1
+ export function TextToSpeech(inputText: any): Promise<void>;
2
+ //# sourceMappingURL=textToSpeech.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textToSpeech.d.ts","sourceRoot":"","sources":["../../../src/utils/textToSpeech.js"],"names":[],"mappings":"AAMO,4DA+BN"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-srschat",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "private": false,
5
5
  "description": "A modern, sophisticated chat interface for React Native",
6
6
  "main": "lib/commonjs/index",
@@ -46,7 +46,7 @@
46
46
  "eslint-plugin-react-native": "^4.0.0",
47
47
  "metro-react-native-babel-preset": "^0.77.0",
48
48
  "react": "18.2.0",
49
- "react-native": "0.73.6",
49
+ "react-native": "^0.73.6",
50
50
  "react-native-builder-bob": "^0.20.0",
51
51
  "typescript": "^5.0.0"
52
52
  },
@@ -61,12 +61,17 @@
61
61
  "dependencies": {
62
62
  "@babel/runtime": "^7.20.0",
63
63
  "@react-native-async-storage/async-storage": "^2.1.1",
64
+ "@react-native-community/audio-toolkit": "^2.0.3",
65
+ "@react-native-community/voice": "^1.1.9",
64
66
  "@react-native-picker/picker": "^2.11.0",
65
67
  "axios": "^1.7.9",
68
+ "react-native-audio-recorder-player": "^3.6.12",
66
69
  "react-native-keyboard-aware-scroll-view": "^0.9.5",
67
70
  "react-native-markdown-display": "^7.0.2",
71
+ "react-native-permissions": "^5.2.6",
68
72
  "react-native-uuid": "^2.0.3",
69
- "react-native-vector-icons": "^10.2.0"
73
+ "react-native-vector-icons": "^10.2.0",
74
+ "react-native-video": "^6.10.2"
70
75
  },
71
76
  "react-native-builder-bob": {
72
77
  "source": "src",
@@ -6,18 +6,18 @@ import { AppContext } from "../contexts/AppContext";
6
6
  import { Header } from "./header";
7
7
 
8
8
  export const EmailForm = ({ panHandlers }) => {
9
- const { BASE_URL, setShowModal, messages, formatChatHistory, conversationStartTime } = useContext(AppContext);
9
+ const { data, BASE_URL, setShowModal, messages, formatChatHistory, conversationStartTime } = useContext(AppContext);
10
10
  const [subject, setSubject] = useState("");
11
11
  const [message, setMessage] = useState("");
12
12
  const [userEmail, setUserEmail] = useState("");
13
- const [branchEmail, setBranchEmail] = useState("");
13
+ const [branchEmail, setBranchEmail] = useState(data.branch_email || "");
14
14
  const [isLoading, setIsLoading] = useState(false);
15
15
  const [error, setError] = useState("");
16
16
  const [success, setSuccess] = useState(false);
17
17
  const [isComposing, setIsComposing] = useState(false);
18
18
 
19
19
  const handleComposeEmail = async () => {
20
- setIsComposing(true);
20
+ setIsComposing(true);
21
21
  setError("");
22
22
 
23
23
  try {
@@ -26,7 +26,7 @@ export const EmailForm = ({ panHandlers }) => {
26
26
  chat_history: chatHistory,
27
27
  conversation_start_time: conversationStartTime,
28
28
  customer_name: '',
29
- branch_email: "",
29
+ branch_email: branchEmail,
30
30
  };
31
31
 
32
32
  const response = await axios.post(`https://${BASE_URL}/compose-email`, payload);
@@ -55,13 +55,13 @@ export const EmailForm = ({ panHandlers }) => {
55
55
  try {
56
56
  const chatHistory = formatChatHistory();
57
57
  await axios.post(`https://${BASE_URL}/send-email`, {
58
- user_email: 'cristin@instalily.ai',
58
+ user_email: userEmail,
59
59
  subject,
60
60
  message,
61
61
  chat_history: chatHistory,
62
62
  conversation_start_time: conversationStartTime,
63
63
  customer_name: '',
64
- branch_email: "",
64
+ branch_email: branchEmail,
65
65
  });
66
66
 
67
67
  setSuccess(true);
@@ -78,7 +78,7 @@ export const EmailForm = ({ panHandlers }) => {
78
78
 
79
79
  return (
80
80
  <View style={styles.container}>
81
- <View {...panHandlers}>
81
+ <View>
82
82
  <Header />
83
83
  </View>
84
84
  <View style={styles.topBar}>
@@ -18,33 +18,33 @@ export const Header = () => {
18
18
  <View style={styles.header}>
19
19
  {/* Logo on the left */}
20
20
  <View style={styles.section}>
21
- <Image source={require('../assets/heritage.png')} style={styles.logo} />
21
+ <Image source={require('../assets/heritage.png')} style={[styles.logo, { tintColor: "white" }]} />
22
22
  </View>
23
23
 
24
24
  {/* Title in the center */}
25
- <View style={[styles.section, styles.titleContainer]}>
25
+ {/* <View style={[styles.section, styles.titleContainer]}>
26
26
  <View style={styles.titleWrapper}>
27
27
  <Text style={styles.title}>
28
28
  Poseidon
29
29
  </Text>
30
30
  <Text style={styles.betaText}><Ionicons name="sparkles-outline" size={10} color="#007AFF" />beta</Text>
31
31
  </View>
32
- </View>
32
+ </View> */}
33
33
 
34
34
  {/* Close button on the right */}
35
35
  <View style={styles.iconsSection}>
36
36
  {showModal !== "Form" && showModal !== "Email" &&
37
37
  <>
38
38
  <TouchableOpacity onPress={() => setShowModal("Email")}>
39
- <Ionicons name="mail" size={24} color="gray" />
39
+ <Ionicons name="mail" size={24} color="white" />
40
40
  </TouchableOpacity>
41
41
  <TouchableOpacity onPress={() => handleClearState()}>
42
- <Ionicons name="trash" size={24} color="gray" />
42
+ <Ionicons name="trash" size={24} color="white" />
43
43
  </TouchableOpacity>
44
44
  </>
45
45
  }
46
46
  <TouchableOpacity onPress={() => handleClick()}>
47
- <Ionicons name="chevron-down" size={24} color="gray" />
47
+ <Ionicons name="chevron-down" size={24} color="white" />
48
48
  </TouchableOpacity>
49
49
  </View>
50
50
  </View>
@@ -55,14 +55,16 @@ const styles = StyleSheet.create({
55
55
  header: {
56
56
  flexDirection: 'row',
57
57
  alignItems: 'center',
58
- backgroundColor: '#f6f6f6',
58
+ backgroundColor: '#186494',
59
59
  padding: 16,
60
+ paddingTop: 60,
60
61
  borderBottomWidth: 1,
61
62
  borderBottomColor: '#ddd',
63
+ justifyContent: 'space-between'
62
64
  },
63
65
  section: {
64
66
  flex: 1,
65
- alignItems: 'center',
67
+ alignItems: 'flex-start'
66
68
  },
67
69
  iconsSection: {
68
70
  flex: 1,
@@ -71,13 +73,13 @@ const styles = StyleSheet.create({
71
73
  alignItems: 'center',
72
74
  justifyContent: 'flex-end',
73
75
  marginRight: 10,
74
- gap: 4,
76
+ gap: 8,
75
77
  },
76
78
  logo: {
77
79
  width: 110,
78
80
  height: 40,
79
81
  marginLeft: 10,
80
- resizeMode: 'contain',
82
+ resizeMode: 'contain'
81
83
  },
82
84
  titleContainer: {
83
85
  flex: 2, // Slightly larger space for the title
@@ -12,9 +12,10 @@ import {
12
12
  import { Header } from '../components/header';
13
13
  import { AppContext } from '../contexts/AppContext';
14
14
  import Ionicons from 'react-native-vector-icons/Ionicons';
15
+ import { VoiceButton } from './voice';
15
16
 
16
17
  export const ChatInput = ({ onProductCardClick, onAddToCartClick }) => {
17
- const { handleSend, input, setInput, showModal } = useContext(AppContext);
18
+ const { handleSend, input, setInput, showModal, data } = useContext(AppContext);
18
19
 
19
20
  return (
20
21
  <>
@@ -29,9 +30,9 @@ export const ChatInput = ({ onProductCardClick, onAddToCartClick }) => {
29
30
  placeholderTextColor="#999"
30
31
  multiline
31
32
  />
32
- {/* <TouchableOpacity style={styles.inputButton}>
33
- <Ionicons name="mic-outline" size={24} color="#8E8E93" />
34
- </TouchableOpacity> */}
33
+ {data.openai_key &&
34
+ <VoiceButton/>
35
+ }
35
36
  <TouchableOpacity style={styles.sendButton} onPress={() => handleSend(input)} >
36
37
  <Ionicons name="paper-plane-outline" size={24} color='#8E8E93' />
37
38
  </TouchableOpacity>
@@ -1,6 +1,7 @@
1
1
  import React, { useState, useContext } from "react";
2
2
  import { View, Text, Image, TouchableOpacity, TextInput, StyleSheet, Platform } from "react-native";
3
3
  import { AppContext } from "../contexts/AppContext";
4
+ import Ionicons from 'react-native-vector-icons/Ionicons';
4
5
 
5
6
  export const ProductCard = ({ prod }) => {
6
7
  const { onProductCardClick, onAddToCartClick } = useContext(AppContext);
@@ -188,6 +189,8 @@ const styles = StyleSheet.create({
188
189
  fontWeight: "medium",
189
190
  color: "#161616",
190
191
  marginBottom: 5,
192
+ textDecorationLine: "underline",
193
+ textDecorationColor: "#367CB6"
191
194
  },
192
195
  details: {
193
196
  fontSize: 13,
@@ -0,0 +1,86 @@
1
+ import React, { useEffect, useRef, useContext } from "react";
2
+ import { View, Animated, StyleSheet, Pressable, Text } from "react-native";
3
+ import { AppContext } from "../contexts/AppContext";
4
+
5
+ export const ProgressCircle = () => {
6
+ const { stopGenerating } = useContext(AppContext);
7
+ const spinValue = useRef(new Animated.Value(0)).current;
8
+
9
+ useEffect(() => {
10
+ const spinAnimation = Animated.loop(
11
+ Animated.timing(spinValue, {
12
+ toValue: 1,
13
+ duration: 1400,
14
+ useNativeDriver: true,
15
+ })
16
+ );
17
+ spinAnimation.start();
18
+
19
+ return () => spinAnimation.stop(); // Cleanup on unmount
20
+ }, [spinValue]);
21
+
22
+ const spin = spinValue.interpolate({
23
+ inputRange: [0, 1],
24
+ outputRange: ["0deg", "360deg"],
25
+ });
26
+
27
+ return (
28
+ <>
29
+ <Text style={styles.textBeta}>Beta version. Poseidon is learning!</Text>
30
+ <View style={styles.container}>
31
+ <Pressable style={styles.circleContainer} onPress={stopGenerating}>
32
+ <Animated.View style={[styles.circle, { transform: [{ rotate: spin }] }]} />
33
+ <View style={styles.stopSquare} />
34
+ </Pressable>
35
+ </View>
36
+ </>
37
+ );
38
+ };
39
+
40
+ const styles = StyleSheet.create({
41
+ container: {
42
+ flexDirection: "row",
43
+ justifyContent: "flex-end",
44
+ alignItems: "center",
45
+ paddingHorizontal: 6,
46
+ paddingVertical: 6,
47
+ backgroundColor: "#f6f6f6",
48
+ borderTopWidth: 1,
49
+ borderTopColor: "rgba(0, 0, 0, 0.1)",
50
+ paddingBottom: 35,
51
+ paddingTop: 15
52
+ },
53
+ circleContainer: {
54
+ justifyContent: "center",
55
+ alignItems: "center",
56
+ width: 50,
57
+ height: 50,
58
+ marginRight: 20,
59
+ position: "relative",
60
+ },
61
+ circle: {
62
+ borderWidth: 4,
63
+ borderColor: "#dddbd9",
64
+ borderTopColor: "#666666",
65
+ borderRadius: 50,
66
+ width: 40,
67
+ height: 40,
68
+ },
69
+ stopSquare: {
70
+ width: 13,
71
+ height: 13,
72
+ backgroundColor: "#666666",
73
+ position: "absolute",
74
+ top: "50%",
75
+ left: "50%",
76
+ transform: [{ translateX: -6.5 }, { translateY: -6.5 }],
77
+ },
78
+ textBeta: {
79
+ textAlign: 'center',
80
+ fontSize: 11,
81
+ color: '#808080',
82
+ fontWeight: '400',
83
+ marginTop: 5,
84
+ marginBottom: 2
85
+ },
86
+ });
@@ -0,0 +1,111 @@
1
+ // VoiceButton.js
2
+
3
+ import React, { useState, useContext, useEffect } from 'react';
4
+ import { TouchableOpacity, ActivityIndicator, StyleSheet, Alert } from 'react-native';
5
+ import Ionicons from 'react-native-vector-icons/Ionicons';
6
+
7
+ import {
8
+ startRecording,
9
+ stopRecording,
10
+ cancelRecording,
11
+ requestAudioPermission,
12
+ cleanup,
13
+ initVoice
14
+ } from '../utils/audioRecorder';
15
+ import { AppContext } from '../contexts/AppContext';
16
+
17
+ export const VoiceButton = () => {
18
+ const { handleVoiceSend } = useContext(AppContext);
19
+ const [isListening, setIsListening] = useState(false);
20
+ const [loading, setLoading] = useState(false);
21
+
22
+ useEffect(() => {
23
+ const setupVoice = async () => {
24
+ const initialized = await initVoice((result, error) => {
25
+ if (error) {
26
+ Alert.alert('Error', error);
27
+ setIsListening(false);
28
+ setLoading(false);
29
+ return;
30
+ }
31
+ if (result) {
32
+ handleVoiceSend(null, result);
33
+ setIsListening(false);
34
+ setLoading(false);
35
+ }
36
+ });
37
+
38
+ if (!initialized) {
39
+ Alert.alert(
40
+ 'Error',
41
+ 'Speech recognition is not available on this device'
42
+ );
43
+ }
44
+ };
45
+
46
+ setupVoice();
47
+
48
+ return () => {
49
+ cleanup();
50
+ };
51
+ }, []);
52
+
53
+ const toggleRecording = async () => {
54
+ try {
55
+ if (!isListening) {
56
+ const hasPermission = await requestAudioPermission();
57
+ if (!hasPermission) {
58
+ Alert.alert('Permission Denied', 'Microphone permission is required for voice recognition');
59
+ return;
60
+ }
61
+
62
+ setLoading(true);
63
+ const started = await startRecording();
64
+ if (started) {
65
+ setIsListening(true);
66
+ } else {
67
+ Alert.alert('Error', 'Failed to start voice recognition');
68
+ }
69
+ } else {
70
+ setLoading(true);
71
+ setIsListening(false);
72
+ await stopRecording();
73
+ }
74
+ } catch (error) {
75
+ console.error('Error in toggleRecording:', error);
76
+ Alert.alert('Error', 'An error occurred while managing voice recognition');
77
+ setIsListening(false);
78
+ await cleanup();
79
+ } finally {
80
+ setLoading(false);
81
+
82
+ }
83
+ };
84
+
85
+ return (
86
+ <TouchableOpacity
87
+ style={styles.button}
88
+ onPress={toggleRecording}
89
+ disabled={loading}
90
+ >
91
+ {loading ? (
92
+ <ActivityIndicator size="small" color="#8E8E93" />
93
+ ) : (
94
+ <Ionicons
95
+ name={isListening ? 'stop-circle' : 'mic-outline'}
96
+ size={24}
97
+ color="#8E8E93"
98
+ />
99
+
100
+ )}
101
+ </TouchableOpacity>
102
+ );
103
+ };
104
+
105
+ const styles = StyleSheet.create({
106
+ button: {
107
+ justifyContent: 'center',
108
+ alignItems: 'center',
109
+ },
110
+ });
111
+
@@ -12,9 +12,11 @@ import {
12
12
  import { Header } from '../components/header';
13
13
  import { AppContext } from '../contexts/AppContext';
14
14
  import Ionicons from 'react-native-vector-icons/Ionicons';
15
+ import { VoiceButton } from './voice';
15
16
 
16
17
  export const WelcomeInput = ({ onProductCardClick, onAddToCartClick }) => {
17
- const { handleSend, input, setInput, showModal, theme } = useContext(AppContext);
18
+
19
+ const { data, handleSend, input, setInput, showModal, theme } = useContext(AppContext);
18
20
 
19
21
  return (
20
22
  <View style={styles.inputContainer}>
@@ -26,9 +28,11 @@ export const WelcomeInput = ({ onProductCardClick, onAddToCartClick }) => {
26
28
  placeholderTextColor="#999"
27
29
  multiline
28
30
  />
29
- {/* <TouchableOpacity style={styles.inputButton}>
30
- <Ionicons name="mic-outline" size={24} color="#8E8E93" />
31
- </TouchableOpacity> */}
31
+ {data.openai_key &&
32
+
33
+ <VoiceButton/>
34
+
35
+ }
32
36
  <TouchableOpacity
33
37
  style={styles.sendButton}
34
38
  onPress={() => handleSend(input)}
@@ -250,6 +250,11 @@ export const AppProvider = ({ data, onProductCardClick, onAddToCartClick, uiConf
250
250
  };
251
251
  });
252
252
  };
253
+
254
+ function handleVoiceSend(audio, transcription) {
255
+ //setReadAloud(true)
256
+ handleSend(transcription)
257
+ }
253
258
 
254
259
  return (
255
260
  <AppContext.Provider
@@ -259,7 +264,7 @@ export const AppProvider = ({ data, onProductCardClick, onAddToCartClick, uiConf
259
264
  startStreaming, setStartStreaming, maintenance, setMaintenance, feedback, setFeedback, handleFeedback, feedbackOpen, setFeedbackOpen,
260
265
  writeFeedback, setWriteFeedback, writeAnswer, setWriteAnswer, BASE_URL, lastMessageId, setLastMessageId,
261
266
  onProductCardClick, onAddToCartClick, data, sessionId, setSessionId, handleWrittenFeedback, switchFeedbackOpen, confirmDisclaimer,
262
- formatChatHistory, uiConfig
267
+ formatChatHistory, uiConfig, handleVoiceSend
263
268
  }}
264
269
  >
265
270
  {children}
@@ -80,7 +80,7 @@ export function useWebSocketMessage() {
80
80
  console.log(response)
81
81
  }
82
82
  switch (response.type) {
83
- /* case 'middle_message':
83
+ case 'middle_message':
84
84
  const middleMessage = {
85
85
  type: "middle",
86
86
  text: response.message,
@@ -88,7 +88,7 @@ export function useWebSocketMessage() {
88
88
  product_cards: "False",
89
89
  }
90
90
  setMessages([...messages, middleMessage])
91
- break; */
91
+ break;
92
92
  case 'message':
93
93
  if (response.product_cards == "False" || response.product_cards == false ) {
94
94
  setGhostMessage(false);
@@ -28,7 +28,7 @@ export const Disclaimer = ({ panHandlers }) => {
28
28
 
29
29
  return (
30
30
  <View style={styles.container}>
31
- <View {...panHandlers}>
31
+ <View>
32
32
  <Header />
33
33
  </View>
34
34
  <ScrollView contentContainerStyle={styles.scrollContainer}>
@@ -22,7 +22,10 @@ export const Layout = () => {
22
22
  setShowModal("Icon");
23
23
  }
24
24
  };
25
-
25
+
26
+ /* Currently removed this from the child components.
27
+ If activating drag to close, put {...panHandlers} in the view around the
28
+ header on each page (welcome, window, disclaimer) */
26
29
  const panResponder = PanResponder.create({
27
30
  onStartShouldSetPanResponder: () => true,
28
31
  onMoveShouldSetPanResponder: () => true,
@@ -80,7 +83,7 @@ export const Layout = () => {
80
83
  )}
81
84
  {showModal === "ChatWindow" && (
82
85
  <>
83
- <Pressable style={styles.outsideTouchable} onPress={() => handleClick()} />
86
+ {/* <Pressable style={styles.outsideTouchable} onPress={() => handleClick()} /> */}
84
87
  <Animated.View style={[styles.container, { transform: [{ translateY: panY }] }]}>
85
88
  <ChatWindow panHandlers={panResponder.panHandlers} />
86
89
  </Animated.View>
@@ -88,7 +91,7 @@ export const Layout = () => {
88
91
  )}
89
92
  {showModal === "Welcome" && (
90
93
  <>
91
- <Pressable style={styles.outsideTouchable} onPress={() => handleClick()} />
94
+ {/* <Pressable style={styles.outsideTouchable} onPress={() => handleClick()} /> */}
92
95
  <Animated.View style={[styles.container, { transform: [{ translateY: panY }] }]}>
93
96
  <Welcome panHandlers={panResponder.panHandlers} />
94
97
  </Animated.View>
@@ -96,7 +99,7 @@ export const Layout = () => {
96
99
  )}
97
100
  {showModal === "Form" &&
98
101
  <>
99
- <Pressable style={styles.outsideTouchable} onPress={() => handleClick()} />
102
+ {/* <Pressable style={styles.outsideTouchable} onPress={() => handleClick()} /> */}
100
103
  <Animated.View style={[styles.container, { transform: [{ translateY: panY }] }]}>
101
104
  <Disclaimer panHandlers={panResponder.panHandlers} />
102
105
  </Animated.View>
@@ -104,7 +107,7 @@ export const Layout = () => {
104
107
  }
105
108
  {showModal === "Email" &&
106
109
  <>
107
- <Pressable style={styles.outsideTouchable} onPress={() => handleClick()} />
110
+ {/* <Pressable style={styles.outsideTouchable} onPress={() => handleClick()} /> */}
108
111
  <Animated.View style={[styles.container, { transform: [{ translateY: panY }] }]}>
109
112
  <EmailForm panHandlers={panResponder.panHandlers} />
110
113
  </Animated.View>
@@ -133,22 +136,15 @@ const styles = StyleSheet.create({
133
136
  left: 0,
134
137
  right: 0,
135
138
  bottom: 0,
136
- top: 140,
139
+ top: 0,
137
140
  pointerEvents: 'box-none',
138
- borderTopWidth: 1,
141
+ /* borderTopWidth: 1,
139
142
  borderTopColor: '#DDD',
140
143
  borderTopLeftRadius: 16,
141
- borderTopRightRadius: 16,
144
+ borderTopRightRadius: 16, */
142
145
  overflow: 'hidden',
143
146
  },
144
147
  outsideTouchable: {
145
148
  flex: 1,
146
149
  },
147
- dragHandle: {
148
- height: 20,
149
- width: '100%',
150
- backgroundColor: '#DDD',
151
- borderTopLeftRadius: 16,
152
- borderTopRightRadius: 16,
153
- }
154
150
  });
@@ -24,7 +24,7 @@ export const Welcome = ({ panHandlers }) => {
24
24
 
25
25
  {/* Top section */}
26
26
  <View style={styles.topContainer}>
27
- <View style={styles.topHeader} {...panHandlers}>
27
+ <View style={styles.topHeader}>
28
28
  <Image
29
29
  source={require('../assets/heritage.png')}
30
30
  style={[styles.logo, { tintColor: "white" }]}