@ethora/chat-component-rn 26.5.4 → 26.5.7
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/CHANGELOG.md +66 -0
- package/README.md +25 -4
- package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js +1 -7
- package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js +7 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +8 -2
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +2 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js +11 -5
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageList.js +10 -2
- package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/Message.js +60 -7
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js +1 -38
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +20 -28
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +35 -16
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js +11 -2
- package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessageEmoji.js +9 -6
- package/lib/commonjs/components/RoomComponents/styled/LastMessageEmoji.js.map +1 -1
- package/lib/commonjs/components/UsersList/Checkbox.js +68 -0
- package/lib/commonjs/components/UsersList/Checkbox.js.map +1 -0
- package/lib/commonjs/components/UsersList/StyledComponents.js +1 -7
- package/lib/commonjs/components/UsersList/StyledComponents.js.map +1 -1
- package/lib/commonjs/components/UsersList/UsersList.js +3 -1
- package/lib/commonjs/components/UsersList/UsersList.js.map +1 -1
- package/lib/commonjs/components/styled/MediaFilePreview.js +96 -5
- package/lib/commonjs/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/commonjs/components/styled/MessageImage.js +1 -2
- package/lib/commonjs/components/styled/MessageImage.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +4 -2
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/components/styled/VideoMessage.js +2 -10
- package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +71 -2
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/mimeToExtension.js +131 -0
- package/lib/commonjs/helpers/mimeToExtension.js.map +1 -0
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js +73 -1
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/commonjs/hooks/useChatWrapperInit.js +22 -10
- package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/commonjs/hooks/useEventHandlers.js +9 -1
- package/lib/commonjs/hooks/useEventHandlers.js.map +1 -1
- package/lib/commonjs/hooks/useMessageHeapState.js +6 -2
- package/lib/commonjs/hooks/useMessageHeapState.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +48 -4
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/networking/api-requests/auth.api.js +7 -1
- package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +87 -1
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/roomHeapSlice.js +26 -8
- package/lib/commonjs/roomStore/roomHeapSlice.js.map +1 -1
- package/lib/module/components/ContextMenu/ContextMenuComponents.js +0 -6
- package/lib/module/components/ContextMenu/ContextMenuComponents.js.map +1 -1
- package/lib/module/components/MainComponents/ChatHeader.js +7 -1
- package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +8 -2
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +2 -1
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +11 -5
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MainComponents/MessageList.js +11 -3
- package/lib/module/components/MainComponents/MessageList.js.map +1 -1
- package/lib/module/components/MessageBubble/Message.js +60 -7
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js +3 -40
- package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +21 -29
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +36 -17
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js +11 -2
- package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessageEmoji.js +9 -6
- package/lib/module/components/RoomComponents/styled/LastMessageEmoji.js.map +1 -1
- package/lib/module/components/UsersList/Checkbox.js +63 -0
- package/lib/module/components/UsersList/Checkbox.js.map +1 -0
- package/lib/module/components/UsersList/StyledComponents.js +0 -6
- package/lib/module/components/UsersList/StyledComponents.js.map +1 -1
- package/lib/module/components/UsersList/UsersList.js +2 -1
- package/lib/module/components/UsersList/UsersList.js.map +1 -1
- package/lib/module/components/styled/MediaFilePreview.js +97 -6
- package/lib/module/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/module/components/styled/MessageImage.js +1 -2
- package/lib/module/components/styled/MessageImage.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +4 -2
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/components/styled/VideoMessage.js +2 -10
- package/lib/module/components/styled/VideoMessage.js.map +1 -1
- package/lib/module/context/xmppProvider.js +73 -3
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/mimeToExtension.js +124 -0
- package/lib/module/helpers/mimeToExtension.js.map +1 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js +71 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/module/hooks/useChatWrapperInit.js +22 -10
- package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/module/hooks/useEventHandlers.js +9 -1
- package/lib/module/hooks/useEventHandlers.js.map +1 -1
- package/lib/module/hooks/useMessageHeapState.js +6 -2
- package/lib/module/hooks/useMessageHeapState.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +49 -5
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/networking/api-requests/auth.api.js +7 -1
- package/lib/module/networking/api-requests/auth.api.js.map +1 -1
- package/lib/module/networking/xmppClient.js +87 -1
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/roomHeapSlice.js +24 -7
- package/lib/module/roomStore/roomHeapSlice.js.map +1 -1
- package/lib/typescript/components/ContextMenu/ContextMenuComponents.d.ts +0 -1
- package/lib/typescript/components/ContextMenu/ContextMenuComponents.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts +6 -0
- package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessageEmoji.d.ts +8 -0
- package/lib/typescript/components/RoomComponents/styled/LastMessageEmoji.d.ts.map +1 -1
- package/lib/typescript/components/UsersList/Checkbox.d.ts +16 -0
- package/lib/typescript/components/UsersList/Checkbox.d.ts.map +1 -0
- package/lib/typescript/components/UsersList/StyledComponents.d.ts +0 -1
- package/lib/typescript/components/UsersList/StyledComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/MediaFilePreview.d.ts.map +1 -1
- package/lib/typescript/components/styled/MessageImage.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/mimeToExtension.d.ts +37 -0
- package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts +18 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
- package/lib/typescript/hooks/useEventHandlers.d.ts +6 -0
- package/lib/typescript/hooks/useEventHandlers.d.ts.map +1 -1
- package/lib/typescript/hooks/useMessageHeapState.d.ts +2 -0
- package/lib/typescript/hooks/useMessageHeapState.d.ts.map +1 -1
- package/lib/typescript/hooks/useSendMessage.d.ts +2 -1
- package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts +25 -1
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomHeapSlice.d.ts +22 -1
- package/lib/typescript/roomStore/roomHeapSlice.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +6 -0
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/metro.js +17 -57
- package/package.json +1 -1
- package/src/components/ContextMenu/ContextMenuComponents.tsx +0 -7
- package/src/components/MainComponents/ChatHeader.tsx +5 -1
- package/src/components/MainComponents/ChatRoom.tsx +6 -1
- package/src/components/MainComponents/ChatWrapper.tsx +1 -0
- package/src/components/MainComponents/MediaMessage.tsx +15 -8
- package/src/components/MainComponents/MessageList.tsx +10 -3
- package/src/components/MessageBubble/Message.tsx +64 -10
- package/src/components/MessageBubble/MessageInteractions.tsx +2 -105
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +20 -41
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +30 -12
- package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +22 -1
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +1 -1
- package/src/components/RoomComponents/styled/LastMessageEmoji.tsx +9 -7
- package/src/components/UsersList/Checkbox.tsx +68 -0
- package/src/components/UsersList/StyledComponents.ts +0 -8
- package/src/components/UsersList/UsersList.tsx +1 -1
- package/src/components/styled/MediaFilePreview.tsx +91 -5
- package/src/components/styled/MessageImage.tsx +1 -2
- package/src/components/styled/SendInput.tsx +3 -0
- package/src/components/styled/VideoMessage.tsx +3 -10
- package/src/context/xmppProvider.tsx +90 -2
- package/src/helpers/mimeToExtension.ts +135 -0
- package/src/helpers/resolveInitBeforeLoadUser.ts +79 -0
- package/src/hooks/useChatWrapperInit.ts +51 -46
- package/src/hooks/useEventHandlers.tsx +24 -1
- package/src/hooks/useMessageHeapState.tsx +6 -2
- package/src/hooks/useSendMessage.tsx +75 -4
- package/src/networking/api-requests/auth.api.ts +5 -1
- package/src/networking/xmppClient.ts +95 -1
- package/src/roomStore/roomHeapSlice.ts +47 -4
- package/src/types/types.ts +10 -0
- package/lib/commonjs/components/InputComponents/AudioInput.js +0 -23
- package/lib/commonjs/components/InputComponents/AudioInput.js.map +0 -1
- package/lib/commonjs/components/InputComponents/AudioRecorder.js +0 -101
- package/lib/commonjs/components/InputComponents/AudioRecorder.js.map +0 -1
- package/lib/commonjs/components/InputComponents/MediaInput.js +0 -98
- package/lib/commonjs/components/InputComponents/MediaInput.js.map +0 -1
- package/lib/commonjs/components/InputComponents/RecordingIndicator.js +0 -70
- package/lib/commonjs/components/InputComponents/RecordingIndicator.js.map +0 -1
- package/lib/commonjs/components/Modals/ModalSelectMedia/ModalSelectMedia.js +0 -207
- package/lib/commonjs/components/Modals/ModalSelectMedia/ModalSelectMedia.js.map +0 -1
- package/lib/commonjs/components/OperationalModal/OperationalModal.js +0 -83
- package/lib/commonjs/components/OperationalModal/OperationalModal.js.map +0 -1
- package/lib/module/components/InputComponents/AudioInput.js +0 -18
- package/lib/module/components/InputComponents/AudioInput.js.map +0 -1
- package/lib/module/components/InputComponents/AudioRecorder.js +0 -95
- package/lib/module/components/InputComponents/AudioRecorder.js.map +0 -1
- package/lib/module/components/InputComponents/MediaInput.js +0 -92
- package/lib/module/components/InputComponents/MediaInput.js.map +0 -1
- package/lib/module/components/InputComponents/RecordingIndicator.js +0 -65
- package/lib/module/components/InputComponents/RecordingIndicator.js.map +0 -1
- package/lib/module/components/Modals/ModalSelectMedia/ModalSelectMedia.js +0 -200
- package/lib/module/components/Modals/ModalSelectMedia/ModalSelectMedia.js.map +0 -1
- package/lib/module/components/OperationalModal/OperationalModal.js +0 -77
- package/lib/module/components/OperationalModal/OperationalModal.js.map +0 -1
- package/lib/typescript/components/InputComponents/AudioInput.d.ts +0 -9
- package/lib/typescript/components/InputComponents/AudioInput.d.ts.map +0 -1
- package/lib/typescript/components/InputComponents/AudioRecorder.d.ts +0 -9
- package/lib/typescript/components/InputComponents/AudioRecorder.d.ts.map +0 -1
- package/lib/typescript/components/InputComponents/MediaInput.d.ts +0 -16
- package/lib/typescript/components/InputComponents/MediaInput.d.ts.map +0 -1
- package/lib/typescript/components/InputComponents/RecordingIndicator.d.ts +0 -4
- package/lib/typescript/components/InputComponents/RecordingIndicator.d.ts.map +0 -1
- package/lib/typescript/components/Modals/ModalSelectMedia/ModalSelectMedia.d.ts +0 -9
- package/lib/typescript/components/Modals/ModalSelectMedia/ModalSelectMedia.d.ts.map +0 -1
- package/lib/typescript/components/OperationalModal/OperationalModal.d.ts +0 -9
- package/lib/typescript/components/OperationalModal/OperationalModal.d.ts.map +0 -1
- package/src/components/InputComponents/AudioInput.tsx +0 -24
- package/src/components/InputComponents/AudioRecorder.tsx +0 -100
- package/src/components/InputComponents/MediaInput.tsx +0 -113
- package/src/components/InputComponents/RecordingIndicator.tsx +0 -77
- package/src/components/Modals/ModalSelectMedia/ModalSelectMedia.tsx +0 -283
- package/src/components/OperationalModal/OperationalModal.tsx +0 -78
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import React, { useState, useRef, useCallback, useEffect } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
RecordContainer,
|
|
4
|
-
Timer,
|
|
5
|
-
} from '../styled/StyledInputComponents/StyledInputComponents';
|
|
6
|
-
import { RecordIcon, RemoveIcon, SendIcon } from '../../assets/icons';
|
|
7
|
-
import Button from '../styled/Button';
|
|
8
|
-
import RecordingIndicator from './RecordingIndicator';
|
|
9
|
-
import { Platform, View } from 'react-native';
|
|
10
|
-
import AudioRecorderPlayer from 'react-native-audio-recorder-player';
|
|
11
|
-
import RNFS from 'react-native-fs';
|
|
12
|
-
|
|
13
|
-
interface AudioRecorderProps {
|
|
14
|
-
setIsRecording: (state: boolean) => void;
|
|
15
|
-
isRecording: boolean;
|
|
16
|
-
handleSendClick: (audioBlob?: any) => void;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const AudioRecorder: React.FC<AudioRecorderProps> = ({
|
|
20
|
-
setIsRecording,
|
|
21
|
-
isRecording,
|
|
22
|
-
handleSendClick,
|
|
23
|
-
}) => {
|
|
24
|
-
const audioRecorderPlayer = useRef(new AudioRecorderPlayer()).current;
|
|
25
|
-
const [timer, setTimer] = useState('00:00');
|
|
26
|
-
const [audioPath, setAudioPath] = useState<string | null>(null);
|
|
27
|
-
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
return () => {
|
|
30
|
-
audioRecorderPlayer.stopRecorder();
|
|
31
|
-
audioRecorderPlayer.removeRecordBackListener();
|
|
32
|
-
};
|
|
33
|
-
}, [audioRecorderPlayer]);
|
|
34
|
-
|
|
35
|
-
const startRecording = async () => {
|
|
36
|
-
try {
|
|
37
|
-
const path = Platform.select({
|
|
38
|
-
ios: `${RNFS.DocumentDirectoryPath}/recording.m4a`,
|
|
39
|
-
android: `${RNFS.CachesDirectoryPath}/recording.mp4`,
|
|
40
|
-
});
|
|
41
|
-
const uri = await audioRecorderPlayer.startRecorder(path);
|
|
42
|
-
setAudioPath(uri);
|
|
43
|
-
|
|
44
|
-
audioRecorderPlayer.addRecordBackListener((e: any) => {
|
|
45
|
-
const minutes = Math.floor(e.currentPosition / 60000);
|
|
46
|
-
const seconds = Math.floor((e.currentPosition % 60000) / 1000);
|
|
47
|
-
setTimer(
|
|
48
|
-
`${minutes.toString().padStart(2, '0')}:${seconds
|
|
49
|
-
.toString()
|
|
50
|
-
.padStart(2, '0')}`
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
setIsRecording(true);
|
|
55
|
-
} catch (error) {
|
|
56
|
-
console.error('Error starting recording:', error);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
const stopRecording = async () => {
|
|
61
|
-
try {
|
|
62
|
-
await audioRecorderPlayer.stopRecorder();
|
|
63
|
-
audioRecorderPlayer.removeRecordBackListener();
|
|
64
|
-
setIsRecording(false);
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error('Error stopping recording:', error);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const sendAudio = () => {
|
|
71
|
-
if (audioPath) {
|
|
72
|
-
console.log('Audio sent:', audioPath);
|
|
73
|
-
handleSendClick(audioPath);
|
|
74
|
-
resetState();
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const resetState = () => {
|
|
79
|
-
setAudioPath(null);
|
|
80
|
-
setTimer('00:00');
|
|
81
|
-
setIsRecording(false);
|
|
82
|
-
};
|
|
83
|
-
return isRecording ? (
|
|
84
|
-
<RecordContainer>
|
|
85
|
-
<View style={{ display: 'flex', alignItems: 'center' }}>
|
|
86
|
-
{isRecording && <RecordingIndicator />}
|
|
87
|
-
<Timer>{timer}</Timer>
|
|
88
|
-
</View>
|
|
89
|
-
|
|
90
|
-
<View style={{ display: 'flex', gap: 8 }}>
|
|
91
|
-
<Button onPress={stopRecording} EndIcon={<RemoveIcon />} unstyled />
|
|
92
|
-
<Button onPress={sendAudio} EndIcon={<SendIcon />} unstyled />
|
|
93
|
-
</View>
|
|
94
|
-
</RecordContainer>
|
|
95
|
-
) : (
|
|
96
|
-
<Button onPress={startRecording} EndIcon={<RecordIcon />} />
|
|
97
|
-
);
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
export default AudioRecorder;
|
|
@@ -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 }}>×</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;
|