@ethora/chat-component-rn 26.5.4 → 26.5.5

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/CHANGELOG.md +22 -0
  2. package/README.md +25 -4
  3. package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js +1 -7
  4. package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js.map +1 -1
  5. package/lib/commonjs/components/MessageBubble/MessageInteractions.js +1 -38
  6. package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
  7. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +20 -28
  8. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  9. package/lib/commonjs/components/RoomComponents/styled/LastMessageEmoji.js +9 -6
  10. package/lib/commonjs/components/RoomComponents/styled/LastMessageEmoji.js.map +1 -1
  11. package/lib/commonjs/components/UsersList/Checkbox.js +68 -0
  12. package/lib/commonjs/components/UsersList/Checkbox.js.map +1 -0
  13. package/lib/commonjs/components/UsersList/StyledComponents.js +1 -7
  14. package/lib/commonjs/components/UsersList/StyledComponents.js.map +1 -1
  15. package/lib/commonjs/components/UsersList/UsersList.js +3 -1
  16. package/lib/commonjs/components/UsersList/UsersList.js.map +1 -1
  17. package/lib/module/components/ContextMenu/ContextMenuComponents.js +0 -6
  18. package/lib/module/components/ContextMenu/ContextMenuComponents.js.map +1 -1
  19. package/lib/module/components/MessageBubble/MessageInteractions.js +3 -40
  20. package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
  21. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +21 -29
  22. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  23. package/lib/module/components/RoomComponents/styled/LastMessageEmoji.js +9 -6
  24. package/lib/module/components/RoomComponents/styled/LastMessageEmoji.js.map +1 -1
  25. package/lib/module/components/UsersList/Checkbox.js +63 -0
  26. package/lib/module/components/UsersList/Checkbox.js.map +1 -0
  27. package/lib/module/components/UsersList/StyledComponents.js +0 -6
  28. package/lib/module/components/UsersList/StyledComponents.js.map +1 -1
  29. package/lib/module/components/UsersList/UsersList.js +2 -1
  30. package/lib/module/components/UsersList/UsersList.js.map +1 -1
  31. package/lib/typescript/components/ContextMenu/ContextMenuComponents.d.ts +0 -1
  32. package/lib/typescript/components/ContextMenu/ContextMenuComponents.d.ts.map +1 -1
  33. package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
  34. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
  35. package/lib/typescript/components/RoomComponents/styled/LastMessageEmoji.d.ts +8 -0
  36. package/lib/typescript/components/RoomComponents/styled/LastMessageEmoji.d.ts.map +1 -1
  37. package/lib/typescript/components/UsersList/Checkbox.d.ts +16 -0
  38. package/lib/typescript/components/UsersList/Checkbox.d.ts.map +1 -0
  39. package/lib/typescript/components/UsersList/StyledComponents.d.ts +0 -1
  40. package/lib/typescript/components/UsersList/StyledComponents.d.ts.map +1 -1
  41. package/metro.js +17 -57
  42. package/package.json +1 -1
  43. package/src/components/ContextMenu/ContextMenuComponents.tsx +0 -7
  44. package/src/components/MessageBubble/MessageInteractions.tsx +2 -105
  45. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +20 -41
  46. package/src/components/RoomComponents/styled/LastMessageEmoji.tsx +9 -7
  47. package/src/components/UsersList/Checkbox.tsx +68 -0
  48. package/src/components/UsersList/StyledComponents.ts +0 -8
  49. package/src/components/UsersList/UsersList.tsx +1 -1
  50. package/lib/commonjs/components/InputComponents/AudioInput.js +0 -23
  51. package/lib/commonjs/components/InputComponents/AudioInput.js.map +0 -1
  52. package/lib/commonjs/components/InputComponents/AudioRecorder.js +0 -101
  53. package/lib/commonjs/components/InputComponents/AudioRecorder.js.map +0 -1
  54. package/lib/commonjs/components/InputComponents/MediaInput.js +0 -98
  55. package/lib/commonjs/components/InputComponents/MediaInput.js.map +0 -1
  56. package/lib/commonjs/components/InputComponents/RecordingIndicator.js +0 -70
  57. package/lib/commonjs/components/InputComponents/RecordingIndicator.js.map +0 -1
  58. package/lib/commonjs/components/Modals/ModalSelectMedia/ModalSelectMedia.js +0 -207
  59. package/lib/commonjs/components/Modals/ModalSelectMedia/ModalSelectMedia.js.map +0 -1
  60. package/lib/commonjs/components/OperationalModal/OperationalModal.js +0 -83
  61. package/lib/commonjs/components/OperationalModal/OperationalModal.js.map +0 -1
  62. package/lib/module/components/InputComponents/AudioInput.js +0 -18
  63. package/lib/module/components/InputComponents/AudioInput.js.map +0 -1
  64. package/lib/module/components/InputComponents/AudioRecorder.js +0 -95
  65. package/lib/module/components/InputComponents/AudioRecorder.js.map +0 -1
  66. package/lib/module/components/InputComponents/MediaInput.js +0 -92
  67. package/lib/module/components/InputComponents/MediaInput.js.map +0 -1
  68. package/lib/module/components/InputComponents/RecordingIndicator.js +0 -65
  69. package/lib/module/components/InputComponents/RecordingIndicator.js.map +0 -1
  70. package/lib/module/components/Modals/ModalSelectMedia/ModalSelectMedia.js +0 -200
  71. package/lib/module/components/Modals/ModalSelectMedia/ModalSelectMedia.js.map +0 -1
  72. package/lib/module/components/OperationalModal/OperationalModal.js +0 -77
  73. package/lib/module/components/OperationalModal/OperationalModal.js.map +0 -1
  74. package/lib/typescript/components/InputComponents/AudioInput.d.ts +0 -9
  75. package/lib/typescript/components/InputComponents/AudioInput.d.ts.map +0 -1
  76. package/lib/typescript/components/InputComponents/AudioRecorder.d.ts +0 -9
  77. package/lib/typescript/components/InputComponents/AudioRecorder.d.ts.map +0 -1
  78. package/lib/typescript/components/InputComponents/MediaInput.d.ts +0 -16
  79. package/lib/typescript/components/InputComponents/MediaInput.d.ts.map +0 -1
  80. package/lib/typescript/components/InputComponents/RecordingIndicator.d.ts +0 -4
  81. package/lib/typescript/components/InputComponents/RecordingIndicator.d.ts.map +0 -1
  82. package/lib/typescript/components/Modals/ModalSelectMedia/ModalSelectMedia.d.ts +0 -9
  83. package/lib/typescript/components/Modals/ModalSelectMedia/ModalSelectMedia.d.ts.map +0 -1
  84. package/lib/typescript/components/OperationalModal/OperationalModal.d.ts +0 -9
  85. package/lib/typescript/components/OperationalModal/OperationalModal.d.ts.map +0 -1
  86. package/src/components/InputComponents/AudioInput.tsx +0 -24
  87. package/src/components/InputComponents/AudioRecorder.tsx +0 -100
  88. package/src/components/InputComponents/MediaInput.tsx +0 -113
  89. package/src/components/InputComponents/RecordingIndicator.tsx +0 -77
  90. package/src/components/Modals/ModalSelectMedia/ModalSelectMedia.tsx +0 -283
  91. package/src/components/OperationalModal/OperationalModal.tsx +0 -78
@@ -1,113 +0,0 @@
1
- import React, { useCallback } from 'react';
2
- import { View, Image, TouchableOpacity } from 'react-native';
3
- import { Video, ResizeMode } from 'expo-av';
4
- import * as ImagePicker from 'expo-image-picker';
5
- import { AttachIcon, RemoveIcon } from '../../assets/icons';
6
- import Button from '../styled/Button';
7
- import { IConfig } from '../../types/types';
8
-
9
- interface FilePreview {
10
- uri: string;
11
- name: string;
12
- type: string;
13
- }
14
-
15
- interface MediaInputProps {
16
- filePreviews: FilePreview[];
17
- setFilePreviews: (
18
- update: FilePreview[] | ((prev: FilePreview[]) => FilePreview[])
19
- ) => void;
20
- handleSendClick: () => void;
21
- config?: IConfig;
22
- }
23
-
24
- const MediaInput: React.FC<MediaInputProps> = ({
25
- filePreviews,
26
- setFilePreviews,
27
- handleSendClick,
28
- config,
29
- }) => {
30
- const handleAttachClick = useCallback(async () => {
31
- const result = await ImagePicker.launchImageLibraryAsync({
32
- mediaTypes: ['images', 'videos'],
33
- allowsMultipleSelection: true,
34
- selectionLimit: 5,
35
- quality: 0.8,
36
- });
37
-
38
- if (!result.canceled && result.assets) {
39
- const newFiles = result.assets.map((asset) => ({
40
- uri: asset.uri,
41
- name: asset.fileName || asset.uri.split('/').pop() || `file_${Date.now()}`,
42
- type: asset.mimeType || 'application/octet-stream',
43
- }));
44
- setFilePreviews((prevFiles: FilePreview[]) =>
45
- [...prevFiles, ...newFiles].slice(0, 5)
46
- );
47
- }
48
- }, [setFilePreviews]);
49
-
50
- const handleRemoveFile = useCallback(
51
- (file: FilePreview) => {
52
- setFilePreviews((prevFiles: FilePreview[]) =>
53
- prevFiles.filter((f) => f.uri !== file.uri)
54
- );
55
- },
56
- [setFilePreviews]
57
- );
58
-
59
- const renderFilePreview = useCallback((file: FilePreview) => {
60
- if (file.type?.startsWith('image/')) {
61
- return (
62
- <Image source={{ uri: file.uri }} style={{ width: 50, height: 50 }} />
63
- );
64
- } else if (file.type?.startsWith('video/')) {
65
- return (
66
- <Video
67
- source={{ uri: file.uri }}
68
- style={{ width: 50, height: 50 }}
69
- useNativeControls
70
- resizeMode={ResizeMode.COVER}
71
- />
72
- );
73
- }
74
- return null;
75
- }, []);
76
-
77
- return (
78
- <View>
79
- <Button
80
- onPress={handleAttachClick}
81
- disabled={config?.disableMedia}
82
- EndIcon={<AttachIcon />}
83
- />
84
- {filePreviews.length > 0 && (
85
- <View>
86
- {filePreviews.map((file) => (
87
- <View key={file.uri} style={{ position: 'relative', margin: 8 }}>
88
- {renderFilePreview(file)}
89
- <TouchableOpacity
90
- onPress={() => handleRemoveFile(file)}
91
- style={{
92
- position: 'absolute',
93
- top: 4,
94
- right: 4,
95
- width: 20,
96
- height: 20,
97
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
98
- justifyContent: 'center',
99
- alignItems: 'center',
100
- borderRadius: 10,
101
- }}
102
- >
103
- <RemoveIcon />
104
- </TouchableOpacity>
105
- </View>
106
- ))}
107
- </View>
108
- )}
109
- </View>
110
- );
111
- };
112
-
113
- export default MediaInput;
@@ -1,77 +0,0 @@
1
- import React, {useEffect, useRef} from 'react';
2
- import {View, StyleSheet, Animated} from 'react-native';
3
-
4
- const RecordingIndicator = () => {
5
- const scaleAnim = useRef(new Animated.Value(1)).current; // For scaling the circle
6
- const opacityAnim = useRef(new Animated.Value(1)).current; // For pulsating effect
7
-
8
- useEffect(() => {
9
- Animated.loop(
10
- Animated.sequence([
11
- Animated.parallel([
12
- Animated.timing(scaleAnim, {
13
- toValue: 1.3,
14
- duration: 750,
15
- useNativeDriver: true,
16
- }),
17
- Animated.timing(opacityAnim, {
18
- toValue: 0.6,
19
- duration: 750,
20
- useNativeDriver: true,
21
- }),
22
- ]),
23
- Animated.parallel([
24
- Animated.timing(scaleAnim, {
25
- toValue: 1,
26
- duration: 750,
27
- useNativeDriver: true,
28
- }),
29
- Animated.timing(opacityAnim, {
30
- toValue: 1,
31
- duration: 750,
32
- useNativeDriver: true,
33
- }),
34
- ]),
35
- ]),
36
- ).start();
37
- }, [scaleAnim, opacityAnim]);
38
-
39
- return (
40
- <View style={styles.wrapper}>
41
- <Animated.View
42
- style={[
43
- styles.outerCircle,
44
- {
45
- transform: [{scale: scaleAnim}],
46
- opacity: opacityAnim,
47
- },
48
- ]}
49
- />
50
- <View style={styles.innerCircle} />
51
- </View>
52
- );
53
- };
54
-
55
- const styles = StyleSheet.create({
56
- wrapper: {
57
- justifyContent: 'center',
58
- alignItems: 'center',
59
- marginRight: 10,
60
- },
61
- outerCircle: {
62
- width: 18,
63
- height: 18,
64
- borderRadius: 9,
65
- backgroundColor: 'rgba(255, 0, 0, 0.6)',
66
- position: 'absolute',
67
- },
68
- innerCircle: {
69
- width: 16,
70
- height: 16,
71
- borderRadius: 8,
72
- backgroundColor: 'red',
73
- position: 'relative',
74
- },
75
- });
76
-
77
- export default RecordingIndicator;
@@ -1,283 +0,0 @@
1
- import React, { FC, useMemo } from 'react';
2
- import { Alert, Linking, Platform } from 'react-native';
3
- import Button from '../../styled/Button';
4
- import DropdownMenu from '../../DropdownMenu/DropdownMenu';
5
- import DocumentPicker from 'react-native-document-picker';
6
- import ImagePicker from 'react-native-image-crop-picker';
7
- import {
8
- check,
9
- request,
10
- PERMISSIONS,
11
- RESULTS,
12
- Permission,
13
- } from 'react-native-permissions';
14
- import {
15
- AttachIcon,
16
- CameraIcon,
17
- DocumentIcon,
18
- MediaIcon,
19
- } from '../../../assets/icons';
20
- import { MediaFile } from '../../../types/types';
21
-
22
- interface ModalSelectMediaProps {
23
- onFileSelect: (files: MediaFile[]) => void;
24
- config?: any;
25
- }
26
-
27
- interface Permissions {
28
- UNAVAILABLE: 'unavailable';
29
- BLOCKED: 'blocked';
30
- DENIED: 'denied';
31
- GRANTED: 'granted';
32
- LIMITED: 'limited';
33
- }
34
-
35
- export const ModalSelectMedia: FC<ModalSelectMediaProps> = ({
36
- onFileSelect,
37
- config,
38
- }) => {
39
- const checkPermission = async (permission: Permission) => {
40
- const status = await check(permission);
41
-
42
- if (status === RESULTS.GRANTED) {
43
- return status;
44
- } else if (status === RESULTS.DENIED) {
45
- const requestStatus = await request(permission);
46
- if (requestStatus === RESULTS.GRANTED) {
47
- return requestStatus;
48
- } else if (requestStatus === RESULTS.DENIED) {
49
- return requestStatus;
50
- }
51
- } else if (status === RESULTS.UNAVAILABLE) {
52
- return status;
53
- } else {
54
- return status;
55
- }
56
- };
57
-
58
- const handleCameraSelection = async () => {
59
- const permission =
60
- Platform.OS === 'ios'
61
- ? PERMISSIONS.IOS.CAMERA
62
- : PERMISSIONS.ANDROID.CAMERA;
63
- const permissionStatus = await checkPermission(permission);
64
-
65
- if (permissionStatus !== RESULTS.GRANTED) {
66
- Alert.alert(
67
- 'Permission required',
68
- 'Camera permission is needed to take photos.',
69
- [
70
- {
71
- text: 'Cancel',
72
- onPress: () => console.log('Camera permission cancelled'),
73
- style: 'cancel',
74
- },
75
- {
76
- text: 'Open Settings',
77
- onPress: () => Linking.openSettings(),
78
- },
79
- ]
80
- );
81
- return;
82
- }
83
-
84
- try {
85
- const image = await ImagePicker.openCamera({
86
- width: 300,
87
- height: 400,
88
- cropping: true,
89
- });
90
-
91
- const originalName = image.path.split('/').pop();
92
- const file = {
93
- uri: image.path,
94
- type: image.mime,
95
- name: originalName || `camera_${Date.now()}.jpg`,
96
- };
97
- onFileSelect([file]);
98
- } catch (error: any) {
99
- const errorMessage = error?.message || String(error);
100
- const isSimulatorError =
101
- errorMessage.includes('simulator') ||
102
- errorMessage.includes('Cannot run camera') ||
103
- errorMessage.includes('Camera not available');
104
-
105
- if (isSimulatorError) {
106
- Alert.alert(
107
- 'Camera unavailable',
108
- 'Camera is not available on iOS Simulator. Please test on a real device.',
109
- [{ text: 'OK' }]
110
- );
111
- } else if (error?.code !== 'E_PICKER_CANCELLED') {
112
- console.error('Camera error:', error);
113
- Alert.alert(
114
- 'Camera error',
115
- errorMessage || 'Failed to open camera. Please try again.',
116
- [{ text: 'OK' }]
117
- );
118
- }
119
- }
120
- };
121
-
122
- const handleGallerySelection = async () => {
123
- try {
124
- let permission: Permission;
125
-
126
- if (Platform.OS === 'ios') {
127
- permission = PERMISSIONS.IOS.PHOTO_LIBRARY;
128
- } else if (Number(Platform.Version) >= 33) {
129
- permission = PERMISSIONS.ANDROID.READ_MEDIA_IMAGES;
130
- } else {
131
- permission = PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE;
132
- }
133
-
134
- console.log('handleGallerySelection - checking permission:', permission);
135
- const permissionStatus = await checkPermission(permission);
136
- console.log('handleGallerySelection - permission status:', permissionStatus);
137
-
138
- if (permissionStatus !== RESULTS.GRANTED) {
139
- console.log('handleGallerySelection - permission not granted, showing alert');
140
- Alert.alert(
141
- 'Permission required',
142
- 'Gallery permission is needed to select photos.',
143
- [
144
- {
145
- text: 'Cancel',
146
- onPress: () => console.log('Gallery permission cancelled'),
147
- style: 'cancel',
148
- },
149
- {
150
- text: 'Open Settings',
151
- onPress: () => Linking.openSettings(),
152
- },
153
- ]
154
- );
155
- return;
156
- }
157
-
158
- await new Promise(resolve => setTimeout(resolve, 300));
159
- const image = await ImagePicker.openPicker({
160
- multiple: false,
161
- mediaType: 'any',
162
- });
163
- console.log('handleGallerySelection - image selected:', image);
164
-
165
- const originalName = image.path.split('/').pop();
166
- const file = {
167
- uri: image.path,
168
- type: image.mime,
169
- name:
170
- originalName ||
171
- `gallery_${Date.now()}${
172
- image.mime.includes('video') ? '.mp4' : '.jpg'
173
- }`,
174
- };
175
-
176
- onFileSelect([file]);
177
- } catch (error: any) {
178
- if (error?.code === 'E_PICKER_CANCELLED') {
179
- return;
180
- }
181
-
182
- console.error('Gallery error:', error);
183
- console.error('Gallery error code:', error?.code);
184
- console.error('Gallery error message:', error?.message);
185
-
186
- const errorMessage = error?.message || String(error);
187
- Alert.alert(
188
- 'Gallery error',
189
- errorMessage || 'Failed to open gallery. Please try again.',
190
- [{ text: 'OK' }]
191
- );
192
- }
193
- };
194
-
195
- const handleFileSelection = async () => {
196
- try {
197
- const result = await DocumentPicker.pick({
198
- type: [DocumentPicker.types.allFiles],
199
- allowMultiSelection: false,
200
- });
201
-
202
- const files = result.map((file: any) => {
203
- const originalName = file.name;
204
- return {
205
- uri: file.uri,
206
- type: file.type || 'unknown',
207
- name: originalName || `file_${Date.now()}`,
208
- };
209
- });
210
-
211
- onFileSelect(files);
212
- } catch (err: any) {
213
- if (DocumentPicker.isCancel(err)) {
214
- console.log('User cancelled file picker');
215
- } else {
216
- console.error('DocumentPicker Error:', err);
217
- const errorMessage = err?.message || String(err);
218
- Alert.alert(
219
- 'File selection error',
220
- errorMessage || 'Failed to select file. Please try again.',
221
- [{ text: 'OK' }]
222
- );
223
- }
224
- }
225
- };
226
-
227
- const menuOptions = useMemo(
228
- () => [
229
- {
230
- label: 'Camera',
231
- icon: <CameraIcon />,
232
- onClick: async () => {
233
- setTimeout(async () => {
234
- await handleCameraSelection();
235
- }, 500);
236
- },
237
- },
238
- {
239
- label: 'Media File',
240
- icon: <MediaIcon />,
241
- onClick: async () => {
242
- await handleGallerySelection();
243
- },
244
- },
245
- {
246
- label: 'Document',
247
- icon: <DocumentIcon />,
248
- onClick: async () => {
249
- setTimeout(async () => {
250
- await handleFileSelection();
251
- }, 500);
252
- },
253
- },
254
- ],
255
- []
256
- );
257
-
258
- return (
259
- <DropdownMenu
260
- position="leftBottom"
261
- options={menuOptions}
262
- openButton={(onPress) => {
263
- return (
264
- <Button
265
- style={{
266
- padding: 0,
267
- height: 40,
268
- width: 40,
269
- justifyContent: 'center',
270
- alignItems: 'center',
271
- backgroundColor: 'transparent',
272
- margin: 0,
273
- }}
274
- EndIcon={<AttachIcon color={config?.colors?.primary || '#0052CD'} />}
275
- onPress={() => {
276
- onPress();
277
- }}
278
- />
279
- );
280
- }}
281
- />
282
- );
283
- };
@@ -1,78 +0,0 @@
1
- import React, { useState } from 'react';
2
- // import QRCode from 'react-qr-code';
3
- import { CloseButton } from '../Modals/styledModalComponents';
4
- import { Overlay, StyledModal } from '../styled/MediaModal';
5
- import { StyledInput } from '../styled/StyledInputComponents/StyledInputComponents';
6
- import Button from '../styled/Button';
7
- import { Text, View } from 'react-native';
8
- import { QRCODE_URL } from '../../helpers/constants/PLATFORM_CONSTANTS';
9
- import Clipboard from '@react-native-clipboard/clipboard';
10
-
11
- interface OperationalModalProps {
12
- isVisible: boolean;
13
- chatJid: string;
14
- setVisible: React.Dispatch<React.SetStateAction<boolean>>;
15
- }
16
-
17
- const OperationalModal: React.FC<OperationalModalProps> = ({
18
- isVisible,
19
- chatJid,
20
- setVisible,
21
- }) => {
22
- const handleCopyClick = () => {
23
- Clipboard.setString(`${QRCODE_URL}${chatJid}`);
24
- };
25
-
26
- return (
27
- isVisible && (
28
- <Overlay
29
- style={{
30
- position: 'absolute',
31
- }}
32
- >
33
- <StyledModal
34
- style={{
35
- borderRadius: 16,
36
- width: 'auto',
37
- height: 'auto',
38
- paddingHorizontal: 64,
39
- paddingVertical: 32,
40
- minWidth: 480,
41
- }}
42
- >
43
- <CloseButton onPress={() => setVisible(false)}>
44
- <Text style={{ fontSize: 24 }}>&times;</Text>
45
- </CloseButton>
46
- <View
47
- style={{
48
- display: 'flex',
49
- flexDirection: 'column',
50
- gap: 16,
51
- alignItems: 'center',
52
- }}
53
- >
54
- <View style={{ width: '70%', position: 'relative' }} />
55
-
56
- <View
57
- style={{
58
- display: 'flex',
59
- gap: 8,
60
- alignItems: 'center',
61
- minWidth: 400,
62
- }}
63
- >
64
- <StyledInput
65
- value={chatJid}
66
- editable={true}
67
- style={{ width: '80%' }}
68
- />
69
- <Button text="Copy" onPress={handleCopyClick} />
70
- </View>
71
- </View>
72
- </StyledModal>
73
- </Overlay>
74
- )
75
- );
76
- };
77
-
78
- export default OperationalModal;