@ethora/chat-component-rn 26.4.1

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 (273) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +148 -0
  3. package/empty-shim.js +15 -0
  4. package/index.js +13 -0
  5. package/metro.js +72 -0
  6. package/package.json +99 -0
  7. package/src/api.config.ts +34 -0
  8. package/src/assets/BG.png +0 -0
  9. package/src/assets/BG.tsx +56 -0
  10. package/src/assets/File.svg +4 -0
  11. package/src/assets/ForzaCare.png +0 -0
  12. package/src/assets/ForzaCare.tsx +27 -0
  13. package/src/assets/icons.tsx +685 -0
  14. package/src/assets/images.tsx +41 -0
  15. package/src/assets/test.xml +243 -0
  16. package/src/components/AuthForms/Login.tsx +295 -0
  17. package/src/components/AuthForms/LoginAnonym.tsx +68 -0
  18. package/src/components/AuthForms/Register.tsx +8 -0
  19. package/src/components/ContextMenu/ContextMenuComponents.tsx +87 -0
  20. package/src/components/DropdownMenu/DropdownMenu.tsx +244 -0
  21. package/src/components/ExampleComponents/CustomMessage.tsx +92 -0
  22. package/src/components/ExampleComponents/CustomTypingIndicatorExamples.tsx +239 -0
  23. package/src/components/Header/HeaderRoomList.tsx +104 -0
  24. package/src/components/InputComponents/AudioInput.tsx +24 -0
  25. package/src/components/InputComponents/AudioRecorder.tsx +100 -0
  26. package/src/components/InputComponents/MediaInput.tsx +114 -0
  27. package/src/components/InputComponents/RecordingIndicator.tsx +77 -0
  28. package/src/components/InputComponents/Search.tsx +135 -0
  29. package/src/components/InputComponents/TextInput.tsx +66 -0
  30. package/src/components/MainComponents/ChatHeader.tsx +163 -0
  31. package/src/components/MainComponents/ChatRoom.tsx +392 -0
  32. package/src/components/MainComponents/ChatWrapper.tsx +318 -0
  33. package/src/components/MainComponents/ChooseChatMessage.tsx +44 -0
  34. package/src/components/MainComponents/ConnectionBanner.tsx +33 -0
  35. package/src/components/MainComponents/EditWrapper.tsx +72 -0
  36. package/src/components/MainComponents/LoginWrapper.tsx +134 -0
  37. package/src/components/MainComponents/MediaMessage.tsx +55 -0
  38. package/src/components/MainComponents/MessageContainer.tsx +122 -0
  39. package/src/components/MainComponents/MessageList.tsx +429 -0
  40. package/src/components/MainComponents/NoMessagesPlaceholder.tsx +49 -0
  41. package/src/components/MainComponents/ProfileImagePlaceholder.tsx +143 -0
  42. package/src/components/MainComponents/RNStyled.tsx +34 -0
  43. package/src/components/MainComponents/ReduxWrapper.tsx +40 -0
  44. package/src/components/MainComponents/RoomList.tsx +246 -0
  45. package/src/components/MainComponents/Select.tsx +165 -0
  46. package/src/components/MainComponents/Switch.tsx +73 -0
  47. package/src/components/MainComponents/SystemMessage.tsx +42 -0
  48. package/src/components/Menu/HeaderRoomListMenu.tsx +169 -0
  49. package/src/components/MenuRoom/MenuRoom.tsx +46 -0
  50. package/src/components/MessageBubble/Avatar.tsx +84 -0
  51. package/src/components/MessageBubble/BottomReplyContainer.tsx +117 -0
  52. package/src/components/MessageBubble/CustomDivider.tsx +10 -0
  53. package/src/components/MessageBubble/DeletedMessage.tsx +36 -0
  54. package/src/components/MessageBubble/Message.tsx +400 -0
  55. package/src/components/MessageBubble/MessageInteractions.tsx +247 -0
  56. package/src/components/MessageBubble/MessageReaction.tsx +149 -0
  57. package/src/components/MessageBubble/MessageReply.tsx +50 -0
  58. package/src/components/MessageBubble/MessageTranslations.tsx +30 -0
  59. package/src/components/Modals/AddMembersModal/AddMembersModal.tsx +142 -0
  60. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +471 -0
  61. package/src/components/Modals/ChatProfileModal/DeleteChatModal.tsx +91 -0
  62. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +298 -0
  63. package/src/components/Modals/Modal/Modal.tsx +52 -0
  64. package/src/components/Modals/ModalHeaderComponent.tsx +41 -0
  65. package/src/components/Modals/ModalSelectMedia/ModalSelectMedia.tsx +285 -0
  66. package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +103 -0
  67. package/src/components/Modals/NewChatModal/ModalContent.tsx +151 -0
  68. package/src/components/Modals/NewChatModal/NewChatModal.tsx +391 -0
  69. package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +136 -0
  70. package/src/components/Modals/SelectUsersModal/SelectUsersModal.tsx +134 -0
  71. package/src/components/Modals/SettingsModals/BlockedUsers/BlockedUsersModal.tsx +63 -0
  72. package/src/components/Modals/SettingsModals/DocumentShares/DocumentSharesModal.tsx +115 -0
  73. package/src/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.tsx +121 -0
  74. package/src/components/Modals/SettingsModals/ManageDataModal/StyledComponents.ts +0 -0
  75. package/src/components/Modals/SettingsModals/ProfileShares/ProfileShares.tsx +65 -0
  76. package/src/components/Modals/SettingsModals/Referrals/Referrals.tsx +90 -0
  77. package/src/components/Modals/SettingsModals/SharedStyledComponents.ts +74 -0
  78. package/src/components/Modals/SettingsModals/Visibility/RadioInput.tsx +59 -0
  79. package/src/components/Modals/SettingsModals/Visibility/StyledComponents.ts +32 -0
  80. package/src/components/Modals/SettingsModals/Visibility/VisibilityModal.tsx +146 -0
  81. package/src/components/Modals/UserProfileModal/EditUserModal.tsx +163 -0
  82. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +410 -0
  83. package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +85 -0
  84. package/src/components/Modals/styledModalComponents.tsx +181 -0
  85. package/src/components/OperationalModal/OperationalModal.tsx +78 -0
  86. package/src/components/RoomComponents/ChatRoomItem.tsx +219 -0
  87. package/src/components/RoomComponents/LastMessageItem.tsx +47 -0
  88. package/src/components/RoomComponents/styled/LastAudioMessage.tsx +62 -0
  89. package/src/components/RoomComponents/styled/LastMessageEmoji.tsx +26 -0
  90. package/src/components/RoomComponents/styled/LastMessageFile.tsx +54 -0
  91. package/src/components/RoomComponents/styled/LastMessagePhoto.tsx +54 -0
  92. package/src/components/RoomComponents/styled/LastMessageVideo.tsx +70 -0
  93. package/src/components/RoomComponents/styled/LastTextMessage.tsx +65 -0
  94. package/src/components/RoomComponents/styled/StyledRoomComponents.ts +53 -0
  95. package/src/components/SortDropDown/index.tsx +76 -0
  96. package/src/components/Thread/ThreadHeader.tsx +41 -0
  97. package/src/components/Thread/ThreadWrapper.tsx +270 -0
  98. package/src/components/Toast/Toast.tsx +128 -0
  99. package/src/components/Toast/index.ts +13 -0
  100. package/src/components/UsersList/StyledComponents.ts +30 -0
  101. package/src/components/UsersList/UsersList.tsx +112 -0
  102. package/src/components/styled/ActionButton.tsx +40 -0
  103. package/src/components/styled/AudioMessage.tsx +82 -0
  104. package/src/components/styled/Button.tsx +107 -0
  105. package/src/components/styled/ChatWrapperBox.tsx +9 -0
  106. package/src/components/styled/DateLabel.tsx +77 -0
  107. package/src/components/styled/Loader.tsx +65 -0
  108. package/src/components/styled/MediaFilePreview.tsx +42 -0
  109. package/src/components/styled/MediaModal.tsx +54 -0
  110. package/src/components/styled/MessageImage.tsx +54 -0
  111. package/src/components/styled/NewMessageLabel.tsx +50 -0
  112. package/src/components/styled/RoomListComponents/index.tsx +164 -0
  113. package/src/components/styled/SendInput.tsx +297 -0
  114. package/src/components/styled/StyledComponents.ts +320 -0
  115. package/src/components/styled/StyledInput.tsx +101 -0
  116. package/src/components/styled/StyledInputComponents/AudioComponents.tsx +1 -0
  117. package/src/components/styled/StyledInputComponents/Composing.tsx +97 -0
  118. package/src/components/styled/StyledInputComponents/CustomTypingIndicator.tsx +261 -0
  119. package/src/components/styled/StyledInputComponents/MediaComponents.tsx +90 -0
  120. package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +131 -0
  121. package/src/components/styled/StyledInputComponents/VideoComponents.tsx +49 -0
  122. package/src/components/styled/TreadLabel.tsx +50 -0
  123. package/src/components/styled/UnsupportedType.tsx +95 -0
  124. package/src/components/styled/VideoMessage.tsx +68 -0
  125. package/src/context/MessageNotificationContext.tsx +335 -0
  126. package/src/context/PushNotificationProvider.tsx +78 -0
  127. package/src/context/ToastContext.tsx +63 -0
  128. package/src/context/toastProvider.tsx +0 -0
  129. package/src/context/xmppProvider.tsx +364 -0
  130. package/src/helpers/block_scroll.ts +95 -0
  131. package/src/helpers/chatAutoEnterer.ts +46 -0
  132. package/src/helpers/checkUniqueUsers.tsx +31 -0
  133. package/src/helpers/constants/CHAT_TYPES.ts +6 -0
  134. package/src/helpers/constants/LANGUAGE_OPTIONS.ts +14 -0
  135. package/src/helpers/constants/LOCAL_STORAGE.ts +3 -0
  136. package/src/helpers/constants/MESSAGE_INTERACTIONS.ts +29 -0
  137. package/src/helpers/constants/MODAL_TYPES.ts +57 -0
  138. package/src/helpers/constants/PLATFORM_CONSTANTS.ts +3 -0
  139. package/src/helpers/createMainMessageForThread.ts +23 -0
  140. package/src/helpers/createMessageFromXml.ts +118 -0
  141. package/src/helpers/createRoomFromApi.tsx +27 -0
  142. package/src/helpers/createUserNameFromSetUser.ts +15 -0
  143. package/src/helpers/dateComparison.ts +12 -0
  144. package/src/helpers/debounce.ts +10 -0
  145. package/src/helpers/ensureScopedChatCache.ts +61 -0
  146. package/src/helpers/extractUniqueMembersFromRooms.ts +45 -0
  147. package/src/helpers/formatNumberWithCommas.ts +3 -0
  148. package/src/helpers/getBooleanFromString.ts +7 -0
  149. package/src/helpers/getDataFromXml.ts +80 -0
  150. package/src/helpers/getNumberFromString.ts +5 -0
  151. package/src/helpers/getRoomsWithRetry.ts +45 -0
  152. package/src/helpers/getTintedColor.ts +28 -0
  153. package/src/helpers/getUnnamedUsers.ts +39 -0
  154. package/src/helpers/handleCopyClick.ts +3 -0
  155. package/src/helpers/handleXmppError.ts +14 -0
  156. package/src/helpers/hashcolor.ts +34 -0
  157. package/src/helpers/historyPreloadScheduler.ts +264 -0
  158. package/src/helpers/initRoomsPresence.ts +32 -0
  159. package/src/helpers/initXmppRooms.tsx +71 -0
  160. package/src/helpers/insertMessageWithDelimiter.ts +96 -0
  161. package/src/helpers/isChatIdPresentInArray.ts +54 -0
  162. package/src/helpers/localStorageUser.ts +9 -0
  163. package/src/helpers/markdownParser.tsx +295 -0
  164. package/src/helpers/nanoToMs.ts +3 -0
  165. package/src/helpers/parseMessageBody.tsx +516 -0
  166. package/src/helpers/parseUrls.tsx +42 -0
  167. package/src/helpers/resolveInitBeforeLoadUser.ts +240 -0
  168. package/src/helpers/storeConsole.ts +26 -0
  169. package/src/helpers/transformTranslatations.ts +16 -0
  170. package/src/helpers/updateMessagesTillLast.tsx +104 -0
  171. package/src/helpers/updatedChatLastTimestamps.ts +29 -0
  172. package/src/helpers/validator.ts +20 -0
  173. package/src/helpers/walletUsername.ts +12 -0
  174. package/src/hooks/hooks.ts +6 -0
  175. package/src/hooks/useChatSettingState.tsx +38 -0
  176. package/src/hooks/useChatWrapperInit.ts +266 -0
  177. package/src/hooks/useComposing.tsx +59 -0
  178. package/src/hooks/useCustomTypingIndicator.tsx +193 -0
  179. package/src/hooks/useEventHandlers.tsx +81 -0
  180. package/src/hooks/useGetNewArchRoom.tsx +57 -0
  181. package/src/hooks/useHeapSender.tsx +88 -0
  182. package/src/hooks/useLocalStorage.tsx +53 -0
  183. package/src/hooks/useLogout.tsx +31 -0
  184. package/src/hooks/useMessageHeapState.tsx +11 -0
  185. package/src/hooks/useMessageLoaderQueue.tsx +90 -0
  186. package/src/hooks/useMessageQueue.ts +146 -0
  187. package/src/hooks/usePendingNotification.ts +49 -0
  188. package/src/hooks/usePrevious.tsx +15 -0
  189. package/src/hooks/usePushNotifications.ts +106 -0
  190. package/src/hooks/useQRCodeChatHandler.ts +58 -0
  191. package/src/hooks/useRoomInitialization.tsx +160 -0
  192. package/src/hooks/useRoomState.tsx +47 -0
  193. package/src/hooks/useRoomUrl.tsx +41 -0
  194. package/src/hooks/useSendMessage.tsx +306 -0
  195. package/src/hooks/useUnreadMessagesCounter.ts +55 -0
  196. package/src/hooks/useXmppInitialization.ts +148 -0
  197. package/src/main.ts +45 -0
  198. package/src/networking/api-requests/auth.api.ts +140 -0
  199. package/src/networking/api-requests/push.api.ts +55 -0
  200. package/src/networking/api-requests/roomMembers.api.ts +20 -0
  201. package/src/networking/api-requests/rooms.api.ts +142 -0
  202. package/src/networking/api-requests/user.api.ts +65 -0
  203. package/src/networking/apiClient.ts +149 -0
  204. package/src/networking/helpers/refreshChecker.ts +13 -0
  205. package/src/networking/stanzaHandlers.ts +418 -0
  206. package/src/networking/xmpp/actionSetTimestampToPrivateStore.xmpp.ts +37 -0
  207. package/src/networking/xmpp/allRoomPresences.xmpp.ts +10 -0
  208. package/src/networking/xmpp/createPrivateRoom.xmpp.ts +26 -0
  209. package/src/networking/xmpp/createRoom.xmpp.ts +35 -0
  210. package/src/networking/xmpp/createRoomPresence.xmpp.ts +74 -0
  211. package/src/networking/xmpp/createTimeoutPromise.xmpp.ts +15 -0
  212. package/src/networking/xmpp/deleteMessage.xmpp.ts +19 -0
  213. package/src/networking/xmpp/editMessage.xmpp.ts +46 -0
  214. package/src/networking/xmpp/getChatsPrivateStoreRequest.xmpp.ts +57 -0
  215. package/src/networking/xmpp/getHistory.xmpp.ts +140 -0
  216. package/src/networking/xmpp/getLastMessageArchive.xmpp.ts +24 -0
  217. package/src/networking/xmpp/getRoomInfo.xmpp.ts +15 -0
  218. package/src/networking/xmpp/getRoomMembers.xmpp.ts +13 -0
  219. package/src/networking/xmpp/getRooms.xmpp.ts +43 -0
  220. package/src/networking/xmpp/getRoomsPaged.xmpp.ts +59 -0
  221. package/src/networking/xmpp/handlePong.xmpp.ts +7 -0
  222. package/src/networking/xmpp/handleStanzas.xmpp.ts +55 -0
  223. package/src/networking/xmpp/inviteRoomRequest.xmpp.ts +25 -0
  224. package/src/networking/xmpp/leaveTheRoom.xmpp.ts +15 -0
  225. package/src/networking/xmpp/listenerManager.ts +116 -0
  226. package/src/networking/xmpp/presenceInRoom.xmpp.ts +57 -0
  227. package/src/networking/xmpp/roomConfig.xmpp.ts +71 -0
  228. package/src/networking/xmpp/sendMediaMessage.xmpp.ts +97 -0
  229. package/src/networking/xmpp/sendMessageReaction.xmpp.ts +41 -0
  230. package/src/networking/xmpp/sendPing.xmpp.ts +21 -0
  231. package/src/networking/xmpp/sendTextMessage.xmpp.ts +99 -0
  232. package/src/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.ts +44 -0
  233. package/src/networking/xmpp/sendTypingRequest.xmpp.ts +26 -0
  234. package/src/networking/xmpp/setChatsPrivateStoreRequest.xmpp.ts +48 -0
  235. package/src/networking/xmpp/setMeAsOwner.xmpp.ts +52 -0
  236. package/src/networking/xmpp/setRoomImage.xmpp.ts +26 -0
  237. package/src/networking/xmpp/setVCard.xmpp.ts +19 -0
  238. package/src/networking/xmpp/subscribeToRoomMessages.xmpp.ts +75 -0
  239. package/src/networking/xmppClient.ts +603 -0
  240. package/src/roomStore/Middleware/logoutMiddleware.tsx +24 -0
  241. package/src/roomStore/Middleware/newMessageMidlleware.tsx +87 -0
  242. package/src/roomStore/Middleware/reactionsMiddleware.tsx +77 -0
  243. package/src/roomStore/Middleware/testMiddleware.tsx +20 -0
  244. package/src/roomStore/Middleware/unreadMidlleware.tsx +58 -0
  245. package/src/roomStore/chatSettingsSlice.ts +178 -0
  246. package/src/roomStore/index.ts +68 -0
  247. package/src/roomStore/persistence.ts +152 -0
  248. package/src/roomStore/roomHeapSlice.ts +37 -0
  249. package/src/roomStore/roomsSlice.ts +353 -0
  250. package/src/services/pushNotifications.ts +170 -0
  251. package/src/services/pushSubscriptionService.ts +145 -0
  252. package/src/types/messages.ts +61 -0
  253. package/src/types/models/action.model.ts +30 -0
  254. package/src/types/models/config.model.ts +16 -0
  255. package/src/types/models/customComponents.model.ts +53 -0
  256. package/src/types/models/language.model.ts +11 -0
  257. package/src/types/models/media.model.ts +5 -0
  258. package/src/types/models/message.model.ts +69 -0
  259. package/src/types/models/modal.model.ts +9 -0
  260. package/src/types/models/room.model.ts +120 -0
  261. package/src/types/models/user.model.ts +90 -0
  262. package/src/types/models/xmpp.model.ts +155 -0
  263. package/src/types/types.ts +505 -0
  264. package/src/utils/PriorityQueue.ts +47 -0
  265. package/src/utils/actionHelpers.ts +40 -0
  266. package/src/utils/actionLogger.ts +64 -0
  267. package/src/utils/clientRegistry.ts +80 -0
  268. package/src/utils/devLogger.ts +197 -0
  269. package/src/utils/messageNotificationManager.ts +108 -0
  270. package/src/utils/resendMessage.ts +87 -0
  271. package/src/utils/toastEmitter.ts +27 -0
  272. package/src/utils/xmppMemoryMonitor.ts +63 -0
  273. package/src/version.ts +1 -0
@@ -0,0 +1,104 @@
1
+ /** @format */
2
+
3
+ import React, { FC, useMemo } from 'react';
4
+ import { View, StyleSheet, Image, Text } from 'react-native';
5
+ import { ProfileImagePlaceholder } from '../MainComponents/ProfileImagePlaceholder';
6
+ import { useChatSettingState } from '../../hooks/useChatSettingState';
7
+ import { BurgerMenuIcon } from '../../assets/icons';
8
+ import Button from '../styled/Button';
9
+
10
+ interface HeaderRoomListProps {
11
+ setDrawerOpen: () => void;
12
+ }
13
+
14
+ export const HeaderRoomList: FC<HeaderRoomListProps> = ({ setDrawerOpen }) => {
15
+ const { config, user, selectedUser } = useChatSettingState();
16
+
17
+ const modalUser: any = selectedUser ?? user;
18
+
19
+ const HeaderLogo = useMemo(() => {
20
+ const image = config?.headerLogo;
21
+
22
+ if (image) {
23
+ if (typeof image === 'function') {
24
+ const SvgComponent = image as React.FC<React.SVGProps<SVGSVGElement>>;
25
+ return <SvgComponent />;
26
+ } else if (typeof image === 'string') {
27
+ return <Image source={{ uri: image }} />;
28
+ } else {
29
+ return image;
30
+ }
31
+ }
32
+
33
+ return <View />;
34
+ }, [config?.backgroundChat?.image]);
35
+
36
+ return (
37
+ <View style={styles.headerContainer}>
38
+ {!config?.disableRoomMenu && config?.headerMenu ? (
39
+ <View style={styles.leftContainer}>
40
+ <Button
41
+ style={styles.menuButton}
42
+ color="black"
43
+ unstyled
44
+ EndIcon={<BurgerMenuIcon color={config?.colors?.primary} />}
45
+ onPress={() => config?.headerMenu && config?.headerMenu()}
46
+ />
47
+ </View>
48
+ ) : (
49
+ <View style={styles.leftContainer} />
50
+ )}
51
+ <View style={styles.centerContainer}>
52
+ {config?.headerLogo ? (
53
+ HeaderLogo
54
+ ) : (
55
+ <Text style={{ fontWeight: 500, fontSize: 18 }}>Chats</Text>
56
+ )}
57
+ </View>
58
+ <View style={styles.rightContainer}>
59
+ <ProfileImagePlaceholder
60
+ icon={modalUser?.profileImage ?? null}
61
+ name={modalUser?.name ?? modalUser?.firstName}
62
+ size={30}
63
+ click={{
64
+ isClick: true,
65
+ onPress: setDrawerOpen,
66
+ }}
67
+ />
68
+ </View>
69
+ </View>
70
+ );
71
+ };
72
+
73
+ const styles = StyleSheet.create({
74
+ headerContainer: {
75
+ flexDirection: 'row',
76
+ alignItems: 'center',
77
+ paddingHorizontal: 8,
78
+ paddingVertical: 2,
79
+ paddingTop: 62, // 60px top padding + 2px for header content
80
+ maxHeight: 24,
81
+ minHeight: 24,
82
+ justifyContent: 'space-between',
83
+ },
84
+ menuButton: {
85
+ padding: 8,
86
+ borderRadius: 16,
87
+ backgroundColor: 'transparent',
88
+ },
89
+ leftContainer: {
90
+ flex: 1,
91
+ alignItems: 'flex-start',
92
+ },
93
+ centerContainer: {
94
+ position: 'absolute',
95
+ left: 0,
96
+ right: 0,
97
+ alignItems: 'center',
98
+ justifyContent: 'center',
99
+ },
100
+ rightContainer: {
101
+ flex: 1,
102
+ alignItems: 'flex-end',
103
+ },
104
+ });
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import AudioRecorder from '../InputComponents/AudioRecorder';
3
+
4
+ interface AudioInputProps {
5
+ isRecording: boolean;
6
+ setIsRecording: (value: boolean) => void;
7
+ handleSendClick: (audioUrl?: string) => void;
8
+ }
9
+
10
+ const AudioInput: React.FC<AudioInputProps> = ({
11
+ isRecording,
12
+ setIsRecording,
13
+ handleSendClick,
14
+ }) => {
15
+ return (
16
+ <AudioRecorder
17
+ setIsRecording={setIsRecording}
18
+ isRecording={isRecording}
19
+ handleSendClick={handleSendClick}
20
+ />
21
+ );
22
+ };
23
+
24
+ export default AudioInput;
@@ -0,0 +1,100 @@
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) => {
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;
@@ -0,0 +1,114 @@
1
+ import React, { useCallback } from 'react';
2
+ import { View, Image, TouchableOpacity } from 'react-native';
3
+ import Video from 'react-native-video';
4
+ import { AttachIcon, RemoveIcon } from '../../assets/icons';
5
+ import Button from '../styled/Button';
6
+ import { launchImageLibrary } from 'react-native-image-picker';
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(() => {
31
+ launchImageLibrary(
32
+ {
33
+ mediaType: 'mixed',
34
+ selectionLimit: 5,
35
+ },
36
+ (response) => {
37
+ if (response.assets) {
38
+ const newFiles = response.assets.map((asset) => ({
39
+ uri: asset.uri!,
40
+ name: asset.fileName!,
41
+ type: asset.type!,
42
+ }));
43
+ setFilePreviews((prevFiles: FilePreview[]) =>
44
+ [...prevFiles, ...newFiles].slice(0, 5)
45
+ );
46
+ }
47
+ }
48
+ );
49
+ }, [setFilePreviews]);
50
+
51
+ const handleRemoveFile = useCallback(
52
+ (file: FilePreview) => {
53
+ setFilePreviews((prevFiles: FilePreview[]) =>
54
+ prevFiles.filter((f) => f.uri !== file.uri)
55
+ );
56
+ },
57
+ [setFilePreviews]
58
+ );
59
+
60
+ const renderFilePreview = useCallback((file: FilePreview) => {
61
+ if (file.type?.startsWith('image/')) {
62
+ return (
63
+ <Image source={{ uri: file.uri }} style={{ width: 50, height: 50 }} />
64
+ );
65
+ } else if (file.type?.startsWith('video/')) {
66
+ return (
67
+ <Video
68
+ source={{ uri: file.uri }}
69
+ style={{ width: 50, height: 50 }}
70
+ controls
71
+ resizeMode="cover"
72
+ />
73
+ );
74
+ }
75
+ return null;
76
+ }, []);
77
+
78
+ return (
79
+ <View>
80
+ <Button
81
+ onPress={handleAttachClick}
82
+ disabled={config?.disableMedia}
83
+ EndIcon={<AttachIcon />}
84
+ />
85
+ {filePreviews.length > 0 && (
86
+ <View>
87
+ {filePreviews.map((file) => (
88
+ <View key={file.uri} style={{ position: 'relative', margin: 8 }}>
89
+ {renderFilePreview(file)}
90
+ <TouchableOpacity
91
+ onPress={() => handleRemoveFile(file)}
92
+ style={{
93
+ position: 'absolute',
94
+ top: 4,
95
+ right: 4,
96
+ width: 20,
97
+ height: 20,
98
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
99
+ justifyContent: 'center',
100
+ alignItems: 'center',
101
+ borderRadius: 10,
102
+ }}
103
+ >
104
+ <RemoveIcon />
105
+ </TouchableOpacity>
106
+ </View>
107
+ ))}
108
+ </View>
109
+ )}
110
+ </View>
111
+ );
112
+ };
113
+
114
+ export default MediaInput;
@@ -0,0 +1,77 @@
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;
@@ -0,0 +1,135 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import styled, { css } from 'styled-components/native';
3
+ import {
4
+ TextInput,
5
+ View,
6
+ TouchableOpacity,
7
+ TextInputProps,
8
+ } from 'react-native';
9
+
10
+ const shouldForwardProp = (prop: string) =>
11
+ prop !== 'animated' && prop !== 'expanded' && prop !== 'direction';
12
+
13
+ const SearchInputWrapper = styled.View.withConfig({ shouldForwardProp })<{
14
+ animated?: boolean;
15
+ direction?: string;
16
+ expanded?: boolean;
17
+ }>`
18
+ position: relative;
19
+ flex-direction: row;
20
+ align-items: center;
21
+ background-color: #fff;
22
+ border-radius: 16px;
23
+ height: 48px;
24
+ padding: 0 16px;
25
+ margin: 0 6px 16px 6px;
26
+ flex: 1;
27
+ ${({ animated, expanded }) =>
28
+ animated &&
29
+ css`
30
+ justify-content: ${expanded ? 'flex-start' : 'center'};
31
+ transition: width 0.7s ease-in-out;
32
+ `};
33
+ `;
34
+
35
+ const SearchIcon = styled(TouchableOpacity)<{
36
+ animated?: boolean;
37
+ expanded?: boolean;
38
+ }>`
39
+ padding: 3.5px;
40
+ color: #999;
41
+ `;
42
+
43
+ const StyledInput = styled(TextInput)<{
44
+ animated?: boolean;
45
+ expanded?: boolean;
46
+ }>`
47
+ background-color: transparent;
48
+ border: none;
49
+ flex: 1;
50
+ font-size: 16px;
51
+ color: #000;
52
+ opacity: ${({ animated, expanded }) => (animated && !expanded ? 0 : 1)};
53
+ display: ${({ animated, expanded }) =>
54
+ animated && !expanded ? 'none' : 'flex'};
55
+ ${({ animated }) =>
56
+ animated &&
57
+ css`
58
+ transition: opacity 0.7s ease-in-out;
59
+ `}
60
+ `;
61
+
62
+ interface SearchInputProps extends TextInputProps {
63
+ icon?: React.ReactNode;
64
+ animated?: boolean;
65
+ direction?: 'left' | 'right';
66
+ placeholder?: string;
67
+ value: string;
68
+ }
69
+
70
+ const SearchInput: React.FC<SearchInputProps> = ({
71
+ icon,
72
+ animated = false,
73
+ direction = 'left',
74
+ placeholder,
75
+ ...props
76
+ }) => {
77
+ const [isExpanded, setIsExpanded] = useState(false);
78
+ const [isTyping, setIsTyping] = useState(false);
79
+ const inputRef = useRef<TextInput | null>(null);
80
+
81
+ const handleFocus = () => {
82
+ setIsExpanded(true);
83
+ };
84
+
85
+ const handleBlur = () => {
86
+ if (!isTyping) {
87
+ setIsExpanded(false);
88
+ }
89
+ };
90
+
91
+ const handleInput = (text: string) => {
92
+ setIsTyping(!!text);
93
+ };
94
+
95
+ useEffect(() => {
96
+ if (isExpanded && animated) {
97
+ const timeout = setTimeout(() => {
98
+ inputRef.current?.focus();
99
+ }, 250);
100
+
101
+ return () => clearTimeout(timeout);
102
+ }
103
+ }, [isExpanded, animated]);
104
+
105
+ return (
106
+ <SearchInputWrapper
107
+ animated={animated}
108
+ direction={direction}
109
+ expanded={isExpanded}
110
+ onTouchStart={handleFocus}
111
+ >
112
+ {icon && (
113
+ <SearchIcon
114
+ animated={animated}
115
+ expanded={isExpanded}
116
+ onPress={() => inputRef.current?.focus()}
117
+ >
118
+ {icon}
119
+ </SearchIcon>
120
+ )}
121
+ <StyledInput
122
+ ref={inputRef}
123
+ onBlur={handleBlur}
124
+ animated={animated}
125
+ expanded={isExpanded}
126
+ onChangeText={handleInput}
127
+ placeholder={placeholder}
128
+ placeholderTextColor="#999"
129
+ {...props}
130
+ />
131
+ </SearchInputWrapper>
132
+ );
133
+ };
134
+
135
+ export { SearchInput };
@@ -0,0 +1,66 @@
1
+ import React, { useCallback } from 'react';
2
+ import { SendIcon } from '../../assets/icons';
3
+ import { IConfig } from '../../types/types';
4
+ import Button from '../styled/Button';
5
+ import { MessageInput } from '../styled/StyledInputComponents/StyledInputComponents';
6
+
7
+ interface TextInputProps {
8
+ message: string;
9
+ setMessage: (value: string) => void;
10
+ handleSendClick: () => void;
11
+ isLoading: boolean;
12
+ config?: IConfig;
13
+ onFocus?: () => void;
14
+ onBlur?: () => void;
15
+ }
16
+
17
+ const TextInput: React.FC<TextInputProps> = ({
18
+ message,
19
+ setMessage,
20
+ handleSendClick,
21
+ config,
22
+ isLoading,
23
+ onFocus,
24
+ onBlur,
25
+ }) => {
26
+ const handleInputChange = useCallback(
27
+ (text: string) => {
28
+ setMessage(text);
29
+ },
30
+ [setMessage]
31
+ );
32
+
33
+ const handleKeyDown = useCallback(
34
+ (event: { nativeEvent: { key: string } }) => {
35
+ if (event.nativeEvent.key === 'Enter' && message) {
36
+ handleSendClick();
37
+ }
38
+ },
39
+ [handleSendClick, message]
40
+ );
41
+
42
+ return (
43
+ <>
44
+ <MessageInput
45
+ color={config?.colors?.primary}
46
+ placeholder="Type message"
47
+ value={message}
48
+ onChangeText={handleInputChange}
49
+ onSubmitEditing={handleSendClick}
50
+ onFocus={onFocus}
51
+ onBlur={onBlur}
52
+ editable={isLoading}
53
+ />
54
+ <Button
55
+ onPress={handleSendClick}
56
+ EndIcon={<SendIcon color={!message ? '#D4D4D8' : '#fff'} />}
57
+ style={{
58
+ borderRadius: 100,
59
+ backgroundColor: !message ? 'transparent' : config?.colors?.primary,
60
+ }}
61
+ />
62
+ </>
63
+ );
64
+ };
65
+
66
+ export default TextInput;