@ethora/chat-component-rn 26.7.2 → 26.7.4

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 (263) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +9 -8
  3. package/lib/commonjs/assets/icons.js +7 -2
  4. package/lib/commonjs/assets/icons.js.map +1 -1
  5. package/lib/commonjs/components/Header/HeaderRoomList.js +20 -6
  6. package/lib/commonjs/components/Header/HeaderRoomList.js.map +1 -1
  7. package/lib/commonjs/components/MainComponents/ChatRoom.js +86 -7
  8. package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
  9. package/lib/commonjs/components/MainComponents/ChatWrapper.js +18 -0
  10. package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
  11. package/lib/commonjs/components/MainComponents/MessageList.js +11 -4
  12. package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
  13. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js +5 -5
  14. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  15. package/lib/commonjs/components/MainComponents/RoomList.js +62 -32
  16. package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
  17. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +208 -70
  18. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
  19. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +307 -99
  20. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  21. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +544 -200
  22. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  23. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js +226 -0
  24. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -0
  25. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +6 -2
  26. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  27. package/lib/commonjs/components/Modals/Modal/Modal.js +8 -0
  28. package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
  29. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js +202 -104
  30. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  31. package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js +556 -0
  32. package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js.map +1 -0
  33. package/lib/commonjs/components/Modals/ProfileHeader/ProfileMenu.js +210 -0
  34. package/lib/commonjs/components/Modals/ProfileHeader/ProfileMenu.js.map +1 -0
  35. package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js +4 -2
  36. package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
  37. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +507 -244
  38. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  39. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +74 -46
  40. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  41. package/lib/commonjs/components/Modals/styledModalComponents.js +9 -2
  42. package/lib/commonjs/components/Modals/styledModalComponents.js.map +1 -1
  43. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +17 -7
  44. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
  45. package/lib/commonjs/components/styled/SendInput.js +80 -1
  46. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  47. package/lib/commonjs/components/styled/StyledComponents.js +9 -3
  48. package/lib/commonjs/components/styled/StyledComponents.js.map +1 -1
  49. package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js +11 -4
  50. package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
  51. package/lib/commonjs/context/xmppProvider.js +12 -0
  52. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  53. package/lib/commonjs/helpers/getChatBackground.js +23 -0
  54. package/lib/commonjs/helpers/getChatBackground.js.map +1 -0
  55. package/lib/commonjs/helpers/historyPreloadScheduler.js +65 -2
  56. package/lib/commonjs/helpers/historyPreloadScheduler.js.map +1 -1
  57. package/lib/commonjs/helpers/mediaLibraryRuntime.js +31 -0
  58. package/lib/commonjs/helpers/mediaLibraryRuntime.js.map +1 -0
  59. package/lib/commonjs/helpers/shallowEqual.js +36 -0
  60. package/lib/commonjs/helpers/shallowEqual.js.map +1 -0
  61. package/lib/commonjs/helpers/sheetGestures.js +32 -0
  62. package/lib/commonjs/helpers/sheetGestures.js.map +1 -0
  63. package/lib/commonjs/hooks/useChatWrapperInit.js +15 -0
  64. package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
  65. package/lib/commonjs/hooks/useComposing.js +27 -0
  66. package/lib/commonjs/hooks/useComposing.js.map +1 -1
  67. package/lib/commonjs/hooks/useSendMessage.js +27 -1
  68. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  69. package/lib/commonjs/hooks/useUnreadMessagesCounter.js +6 -1
  70. package/lib/commonjs/hooks/useUnreadMessagesCounter.js.map +1 -1
  71. package/lib/commonjs/i18n/strings.js +121 -1
  72. package/lib/commonjs/i18n/strings.js.map +1 -1
  73. package/lib/commonjs/networking/api-requests/user.api.js +59 -0
  74. package/lib/commonjs/networking/api-requests/user.api.js.map +1 -1
  75. package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js +6 -2
  76. package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
  77. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  78. package/lib/commonjs/roomStore/chatSettingsSlice.js +3 -1
  79. package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
  80. package/lib/commonjs/roomStore/roomsSlice.js +2 -2
  81. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  82. package/lib/module/assets/icons.js +6 -1
  83. package/lib/module/assets/icons.js.map +1 -1
  84. package/lib/module/components/Header/HeaderRoomList.js +20 -6
  85. package/lib/module/components/Header/HeaderRoomList.js.map +1 -1
  86. package/lib/module/components/MainComponents/ChatRoom.js +87 -8
  87. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  88. package/lib/module/components/MainComponents/ChatWrapper.js +19 -1
  89. package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
  90. package/lib/module/components/MainComponents/MessageList.js +11 -4
  91. package/lib/module/components/MainComponents/MessageList.js.map +1 -1
  92. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js +5 -5
  93. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  94. package/lib/module/components/MainComponents/RoomList.js +62 -32
  95. package/lib/module/components/MainComponents/RoomList.js.map +1 -1
  96. package/lib/module/components/Menu/HeaderRoomListMenu.js +211 -73
  97. package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
  98. package/lib/module/components/Modals/AttachSheet/AttachSheet.js +298 -102
  99. package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  100. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +547 -204
  101. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  102. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js +223 -0
  103. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -0
  104. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +6 -2
  105. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  106. package/lib/module/components/Modals/Modal/Modal.js +9 -1
  107. package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
  108. package/lib/module/components/Modals/NewChatModal/NewChatModal.js +205 -106
  109. package/lib/module/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  110. package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js +548 -0
  111. package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js.map +1 -0
  112. package/lib/module/components/Modals/ProfileHeader/ProfileMenu.js +205 -0
  113. package/lib/module/components/Modals/ProfileHeader/ProfileMenu.js.map +1 -0
  114. package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js +4 -2
  115. package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
  116. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +509 -248
  117. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  118. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +76 -48
  119. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  120. package/lib/module/components/Modals/styledModalComponents.js +9 -2
  121. package/lib/module/components/Modals/styledModalComponents.js.map +1 -1
  122. package/lib/module/components/RoomComponents/ChatRoomItem.js +17 -7
  123. package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
  124. package/lib/module/components/styled/SendInput.js +80 -1
  125. package/lib/module/components/styled/SendInput.js.map +1 -1
  126. package/lib/module/components/styled/StyledComponents.js +9 -3
  127. package/lib/module/components/styled/StyledComponents.js.map +1 -1
  128. package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js +11 -4
  129. package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
  130. package/lib/module/context/xmppProvider.js +12 -0
  131. package/lib/module/context/xmppProvider.js.map +1 -1
  132. package/lib/module/helpers/getChatBackground.js +18 -0
  133. package/lib/module/helpers/getChatBackground.js.map +1 -0
  134. package/lib/module/helpers/historyPreloadScheduler.js +66 -3
  135. package/lib/module/helpers/historyPreloadScheduler.js.map +1 -1
  136. package/lib/module/helpers/mediaLibraryRuntime.js +25 -0
  137. package/lib/module/helpers/mediaLibraryRuntime.js.map +1 -0
  138. package/lib/module/helpers/shallowEqual.js +31 -0
  139. package/lib/module/helpers/shallowEqual.js.map +1 -0
  140. package/lib/module/helpers/sheetGestures.js +26 -0
  141. package/lib/module/helpers/sheetGestures.js.map +1 -0
  142. package/lib/module/hooks/useChatWrapperInit.js +15 -0
  143. package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
  144. package/lib/module/hooks/useComposing.js +28 -1
  145. package/lib/module/hooks/useComposing.js.map +1 -1
  146. package/lib/module/hooks/useSendMessage.js +28 -2
  147. package/lib/module/hooks/useSendMessage.js.map +1 -1
  148. package/lib/module/hooks/useUnreadMessagesCounter.js +6 -1
  149. package/lib/module/hooks/useUnreadMessagesCounter.js.map +1 -1
  150. package/lib/module/i18n/strings.js +121 -1
  151. package/lib/module/i18n/strings.js.map +1 -1
  152. package/lib/module/networking/api-requests/user.api.js +56 -0
  153. package/lib/module/networking/api-requests/user.api.js.map +1 -1
  154. package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js +6 -2
  155. package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
  156. package/lib/module/networking/xmppClient.js.map +1 -1
  157. package/lib/module/roomStore/chatSettingsSlice.js +3 -1
  158. package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
  159. package/lib/module/roomStore/roomsSlice.js +1 -1
  160. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  161. package/lib/typescript/assets/icons.d.ts +12 -0
  162. package/lib/typescript/assets/icons.d.ts.map +1 -1
  163. package/lib/typescript/components/Header/HeaderRoomList.d.ts.map +1 -1
  164. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  165. package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
  166. package/lib/typescript/components/MainComponents/MessageList.d.ts +10 -1
  167. package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
  168. package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
  169. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
  170. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts +9 -0
  171. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
  172. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts +10 -0
  173. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
  174. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts +9 -0
  175. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts.map +1 -0
  176. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
  177. package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
  178. package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts +1 -1
  179. package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts.map +1 -1
  180. package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts +75 -0
  181. package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts.map +1 -0
  182. package/lib/typescript/components/Modals/ProfileHeader/ProfileMenu.d.ts +25 -0
  183. package/lib/typescript/components/Modals/ProfileHeader/ProfileMenu.d.ts.map +1 -0
  184. package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts +6 -1
  185. package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts.map +1 -1
  186. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts +16 -0
  187. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
  188. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts +1 -0
  189. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
  190. package/lib/typescript/components/Modals/styledModalComponents.d.ts.map +1 -1
  191. package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
  192. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  193. package/lib/typescript/components/styled/StyledComponents.d.ts.map +1 -1
  194. package/lib/typescript/components/styled/StyledInputComponents/StyledInputComponents.d.ts.map +1 -1
  195. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  196. package/lib/typescript/helpers/getChatBackground.d.ts +15 -0
  197. package/lib/typescript/helpers/getChatBackground.d.ts.map +1 -0
  198. package/lib/typescript/helpers/historyPreloadScheduler.d.ts.map +1 -1
  199. package/lib/typescript/helpers/mediaLibraryRuntime.d.ts +3 -0
  200. package/lib/typescript/helpers/mediaLibraryRuntime.d.ts.map +1 -0
  201. package/lib/typescript/helpers/shallowEqual.d.ts +11 -0
  202. package/lib/typescript/helpers/shallowEqual.d.ts.map +1 -0
  203. package/lib/typescript/helpers/sheetGestures.d.ts +20 -0
  204. package/lib/typescript/helpers/sheetGestures.d.ts.map +1 -0
  205. package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
  206. package/lib/typescript/hooks/useComposing.d.ts.map +1 -1
  207. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  208. package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts +1 -0
  209. package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts.map +1 -1
  210. package/lib/typescript/i18n/strings.d.ts.map +1 -1
  211. package/lib/typescript/networking/api-requests/user.api.d.ts +27 -0
  212. package/lib/typescript/networking/api-requests/user.api.d.ts.map +1 -1
  213. package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts +1 -0
  214. package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts.map +1 -1
  215. package/lib/typescript/networking/xmppClient.d.ts +1 -0
  216. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  217. package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
  218. package/lib/typescript/roomStore/roomsSlice.d.ts +1 -0
  219. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  220. package/lib/typescript/types/types.d.ts +9 -5
  221. package/lib/typescript/types/types.d.ts.map +1 -1
  222. package/package.json +6 -1
  223. package/src/assets/icons.tsx +29 -9
  224. package/src/components/Header/HeaderRoomList.tsx +20 -5
  225. package/src/components/MainComponents/ChatRoom.tsx +92 -8
  226. package/src/components/MainComponents/ChatWrapper.tsx +19 -1
  227. package/src/components/MainComponents/MessageList.tsx +21 -3
  228. package/src/components/MainComponents/ProfileImagePlaceholder.tsx +5 -5
  229. package/src/components/MainComponents/RoomList.tsx +65 -34
  230. package/src/components/Menu/HeaderRoomListMenu.tsx +209 -64
  231. package/src/components/Modals/AttachSheet/AttachSheet.tsx +318 -86
  232. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +599 -278
  233. package/src/components/Modals/ChatProfileModal/ReportChatModal.tsx +244 -0
  234. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +4 -2
  235. package/src/components/Modals/Modal/Modal.tsx +7 -0
  236. package/src/components/Modals/NewChatModal/NewChatModal.tsx +219 -117
  237. package/src/components/Modals/ProfileHeader/ProfileHeader.tsx +615 -0
  238. package/src/components/Modals/ProfileHeader/ProfileMenu.tsx +217 -0
  239. package/src/components/Modals/SelectUsersModal/SelectUsersModal.tsx +14 -4
  240. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +617 -307
  241. package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +75 -58
  242. package/src/components/Modals/styledModalComponents.tsx +9 -2
  243. package/src/components/RoomComponents/ChatRoomItem.tsx +14 -7
  244. package/src/components/styled/SendInput.tsx +83 -2
  245. package/src/components/styled/StyledComponents.ts +9 -3
  246. package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +11 -4
  247. package/src/context/xmppProvider.tsx +14 -0
  248. package/src/helpers/getChatBackground.ts +18 -0
  249. package/src/helpers/historyPreloadScheduler.ts +80 -3
  250. package/src/helpers/mediaLibraryRuntime.ts +25 -0
  251. package/src/helpers/shallowEqual.ts +33 -0
  252. package/src/helpers/sheetGestures.ts +25 -0
  253. package/src/hooks/useChatWrapperInit.ts +15 -0
  254. package/src/hooks/useComposing.tsx +37 -1
  255. package/src/hooks/useSendMessage.tsx +32 -2
  256. package/src/hooks/useUnreadMessagesCounter.ts +11 -0
  257. package/src/i18n/strings.ts +121 -1
  258. package/src/networking/api-requests/user.api.ts +71 -0
  259. package/src/networking/xmpp/flushLastViewedToPrivateStore.ts +17 -3
  260. package/src/networking/xmppClient.ts +5 -1
  261. package/src/roomStore/chatSettingsSlice.ts +3 -1
  262. package/src/roomStore/roomsSlice.ts +1 -1
  263. package/src/types/types.ts +16 -5
@@ -1,51 +1,67 @@
1
1
  "use strict";
2
2
 
3
- import React, { useEffect, useMemo, useState } from 'react';
3
+ /** @format */
4
+
5
+ import React, { useEffect, useMemo, useRef, useState } from 'react';
6
+ import { Alert, Animated, Keyboard, Linking, Pressable, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
7
+ import { useDispatch, useSelector } from 'react-redux';
8
+ import * as ImagePicker from 'expo-image-picker';
4
9
  import { useFileToken } from '../../../hooks/useFileToken';
5
10
  import { appendFileToken } from '../../../helpers/secureFileUrl';
6
- import { CenterContainer, UserInfo, UserName, UserStatus, ModalContainerFullScreen, Label, BorderedContainer, LabelData, Divider } from '../styledModalComponents';
7
- import { Pressable, View, Text, ScrollView, Alert, Linking } from 'react-native';
8
- import ModalHeaderComponent from '../ModalHeaderComponent';
11
+ import { ModalContainerFullScreen } from '../styledModalComponents';
9
12
  import { ProfileImagePlaceholder } from '../../MainComponents/ProfileImagePlaceholder';
10
- import { useDispatch, useSelector } from 'react-redux';
11
13
  import { getActiveRoom } from '../../../roomStore';
12
14
  import { uploadFile } from '../../../networking/api-requests/auth.api';
13
15
  import { useXmppClient } from '../../../context/xmppProvider';
14
- import { updateRoom } from '../../../roomStore/roomsSlice';
15
- import * as ImagePicker from 'expo-image-picker';
16
+ import { deleteRoom, updateRoom } from '../../../roomStore/roomsSlice';
16
17
  import Loader from '../../styled/Loader';
17
- import Button from '../../styled/Button';
18
- import { DeleteIcon, MoreIcon, QrIcon } from '../../../assets/icons';
18
+ import { AddNewIcon, DeleteIcon, EditIcon, LeaveIcon, ReportIcon, SearchIcon } from '../../../assets/icons';
19
19
  import { useChatSettingState } from '../../../hooks/useChatSettingState';
20
20
  import { chatTextStyle } from '../../../helpers/typography';
21
21
  import { getElementFont } from '../../../helpers/getElementFont';
22
+ import { getIconColor } from '../../../helpers/getIconColor';
22
23
  import { deleteRoomMember } from '../../../networking/api-requests/rooms.api';
23
24
  import { setActiveModal, setSelectedUser } from '../../../roomStore/chatSettingsSlice';
24
25
  import { MODAL_TYPES } from '../../../helpers/constants/MODAL_TYPES';
25
- import DropdownMenu from '../../DropdownMenu/DropdownMenu';
26
26
  import SelectUsersModal from '../SelectUsersModal/SelectUsersModal';
27
27
  import { useToast } from '../../../context/ToastContext';
28
+ import { useT } from '../../../i18n/useT';
28
29
  import DeleteChatModal from './DeleteChatModal';
29
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
30
+ import ReportChatModal from './ReportChatModal';
31
+ import { ProfileHero, ProfileTopBar, useHeaderMetrics } from '../ProfileHeader/ProfileHeader';
32
+ import ProfileMenu from '../ProfileHeader/ProfileMenu';
33
+
34
+ /**
35
+ * Where the header should sit when search opens: tucked away at the
36
+ * collapsed offset when the picture is still expanded, and left exactly
37
+ * where it is when the user already scrolled it away.
38
+ */
39
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
40
+ export const searchScrollTarget = (isCollapsed, collapseDistance) => isCollapsed ? null : collapseDistance;
41
+
42
+ /** Two uppercase letters for a chat without a picture, same rule the
43
+ * avatar placeholder uses for people. */
44
+ export const chatInitials = name => {
45
+ const words = (name || '').trim().split(/\s+/).filter(Boolean);
46
+ const letters = (words.length >= 2 ? [words[0][0], words[1][0]] : [words[0]?.[0], words[0]?.[1]]).filter(c => !!c && /[\p{L}\p{N}]/u.test(c));
47
+ return letters.join('').toUpperCase();
48
+ };
30
49
  const ChatProfileModal = ({
31
50
  handleCloseModal
32
51
  }) => {
52
+ const t = useT();
33
53
  const [loading, setLoading] = useState(false);
34
- const [visible, setVisible] = useState(false);
35
- const [isModalOpen, setIsModalOpen] = useState(false);
54
+ const [isDeleteOpen, setIsDeleteOpen] = useState(false);
55
+ const [isReportOpen, setIsReportOpen] = useState(false);
56
+ const [memberQuery, setMemberQuery] = useState('');
57
+ const [isSearchOpen, setIsSearchOpen] = useState(false);
58
+ // Measured, not guessed: this screen renders inside whatever frame the
59
+ // host gives it (the demo app keeps its own tab bar above), so the
60
+ // window height would overshoot.
61
+ const [viewportHeight, setViewportHeight] = useState(0);
36
62
  const {
37
63
  showToast
38
64
  } = useToast();
39
- const chatMenuOptions = useMemo(() => [{
40
- label: 'Delete chat',
41
- icon: /*#__PURE__*/_jsx(DeleteIcon, {}),
42
- onClick: () => {
43
- setIsModalOpen(true);
44
- },
45
- styles: {
46
- color: 'red'
47
- }
48
- }], []);
49
65
  const dispatch = useDispatch();
50
66
  const {
51
67
  client
@@ -57,6 +73,22 @@ const ChatProfileModal = ({
57
73
  const activeRoom = useSelector(state => getActiveRoom(state));
58
74
  const fileToken = useFileToken();
59
75
 
76
+ // Drives both the hero's parallax and the collapsed bar's fade-in. One
77
+ // shared value, written natively by the ScrollView.
78
+ const scrollY = useRef(new Animated.Value(0)).current;
79
+ const scrollRef = useRef(null);
80
+ const searchInputRef = useRef(null);
81
+ const {
82
+ collapseDistance
83
+ } = useHeaderMetrics();
84
+ // `scrollY` is driven natively, so its value can't be read back with
85
+ // addListener. The Animated.event's `listener` still fires on the JS
86
+ // side, which is enough to know which state the header is in.
87
+ const [isCollapsed, setIsCollapsed] = useState(false);
88
+ // Set when search collapsed the header itself, so only then does
89
+ // dismissing search (or the keyboard) expand it again.
90
+ const collapsedForSearchRef = useRef(false);
91
+
60
92
  // Pull live member list from the MUC when the modal opens — REST
61
93
  // hydration only fills the *count* (item.participants /
62
94
  // item.members.length); the actual roster comes from a `getRoomMembers`
@@ -70,6 +102,11 @@ const ChatProfileModal = ({
70
102
  }
71
103
  }
72
104
  }, [client, activeRoom?.jid]);
105
+ useEffect(() => {
106
+ if (!activeRoom) {
107
+ dispatch(setActiveModal(undefined));
108
+ }
109
+ }, [activeRoom, dispatch]);
73
110
  const onUpload = async () => {
74
111
  let loadingSet = false;
75
112
  try {
@@ -82,7 +119,7 @@ const ChatProfileModal = ({
82
119
  const perm = await ImagePicker.requestMediaLibraryPermissionsAsync();
83
120
  if (!perm.granted) {
84
121
  Alert.alert('Permission required', 'Photo library permission is needed to select images.', [{
85
- text: 'Cancel',
122
+ text: t('action.cancel'),
86
123
  onPress: () => setLoading(false),
87
124
  style: 'cancel'
88
125
  }, {
@@ -144,7 +181,17 @@ const ChatProfileModal = ({
144
181
  }
145
182
  }
146
183
  };
147
- const handleDeleteUser = async userId => {
184
+ const onRemoveIcon = () => {
185
+ client?.setRoomImageStanza(activeRoom?.jid || '', '', 'icon', 'none');
186
+ dispatch(updateRoom({
187
+ jid: activeRoom?.jid || '',
188
+ updates: {
189
+ icon: null
190
+ }
191
+ }));
192
+ };
193
+ const handleDeleteUser = async user => {
194
+ const userId = user.xmppUsername;
148
195
  try {
149
196
  await deleteRoomMember({
150
197
  roomId: activeRoom?.jid?.split('@')[0] || '',
@@ -153,7 +200,7 @@ const ChatProfileModal = ({
153
200
  dispatch(updateRoom({
154
201
  jid: activeRoom?.jid || '',
155
202
  updates: {
156
- roomMembers: activeRoom?.roomMembers?.filter(user => user.xmppUsername !== userId)
203
+ roomMembers: activeRoom?.roomMembers?.filter(member => member.xmppUsername !== userId)
157
204
  }
158
205
  }));
159
206
  showToast({
@@ -172,14 +219,15 @@ const ChatProfileModal = ({
172
219
  });
173
220
  }
174
221
  };
175
- const onRemoveClick = async () => {
176
- client?.setRoomImageStanza(activeRoom?.jid || '', '', 'icon', 'none');
177
- dispatch(updateRoom({
178
- jid: activeRoom?.jid || '',
179
- updates: {
180
- icon: null
181
- }
182
- }));
222
+ const confirmRemoveMember = user => {
223
+ Alert.alert(t('modal.chatProfile.removeMember'), `${user.firstName} ${user.lastName}`.trim(), [{
224
+ text: t('action.cancel'),
225
+ style: 'cancel'
226
+ }, {
227
+ text: t('action.delete'),
228
+ style: 'destructive',
229
+ onPress: () => handleDeleteUser(user)
230
+ }]);
183
231
  };
184
232
  const handleUserAvatarClick = user => {
185
233
  dispatch(setActiveModal(MODAL_TYPES.PROFILE));
@@ -193,152 +241,311 @@ const ChatProfileModal = ({
193
241
  refreshToken: ''
194
242
  }));
195
243
  };
196
- const menuOptions = useMemo(() => userId => [{
197
- label: 'Appoint as an admin',
198
- icon: null,
199
- onClick: () => {
200
- dispatch(setActiveModal(MODAL_TYPES.PROFILE));
201
- console.log('Profile clicked');
244
+
245
+ // Leaving is XMPP-side (an unavailable presence to the MUC); dropping the
246
+ // room from the store is what actually takes the user out of the chat in
247
+ // the UI, and the `!activeRoom` effect above then closes this modal.
248
+ const handleLeave = () => {
249
+ Alert.alert(t('modal.leaveChat.title'), t('modal.leaveChat.description'), [{
250
+ text: t('action.cancel'),
251
+ style: 'cancel'
252
+ }, {
253
+ text: t('action.leave'),
254
+ style: 'destructive',
255
+ onPress: () => {
256
+ try {
257
+ client?.leaveTheRoomStanza?.(activeRoom?.jid || '');
258
+ } catch (error) {
259
+ console.error('Failed to leave the room:', error);
260
+ }
261
+ dispatch(deleteRoom({
262
+ jid: activeRoom?.jid || ''
263
+ }));
264
+ handleCloseModal?.();
265
+ }
266
+ }]);
267
+ };
268
+ const isModerator = activeRoom?.role === 'moderator';
269
+ const canEditIcon = !config?.disableChatInfo?.disableIconEdit && activeRoom?.role !== 'participant';
270
+ const canAddMembers = isModerator && activeRoom?.type === 'group';
271
+ const canDeleteChat = isModerator && activeRoom?.type !== 'private';
272
+ const hasIcon = !!activeRoom?.icon;
273
+ const scrollHeaderTo = y => scrollRef.current?.scrollTo?.({
274
+ y,
275
+ animated: true
276
+ });
277
+
278
+ // Opening search from an expanded header tucks the picture away so the
279
+ // results and the keyboard have room; from an already-collapsed header
280
+ // it just opens the field. Whatever it collapsed, it puts back.
281
+ const openMemberSearch = () => {
282
+ const target = searchScrollTarget(isCollapsed, collapseDistance);
283
+ if (target !== null) {
284
+ collapsedForSearchRef.current = true;
285
+ scrollHeaderTo(target);
202
286
  }
203
- }, {
204
- label: 'Unban',
205
- icon: null,
206
- onClick: () => {
207
- dispatch(setActiveModal(MODAL_TYPES.SETTINGS));
208
- console.log('Settings clicked');
287
+ setIsSearchOpen(true);
288
+ setTimeout(() => searchInputRef.current?.focus(), 50);
289
+ };
290
+ const restoreHeader = () => {
291
+ if (!collapsedForSearchRef.current) {
292
+ return;
293
+ }
294
+ collapsedForSearchRef.current = false;
295
+ scrollHeaderTo(0);
296
+ };
297
+ const closeMemberSearch = () => {
298
+ setMemberQuery('');
299
+ setIsSearchOpen(false);
300
+ Keyboard.dismiss();
301
+ restoreHeader();
302
+ };
303
+
304
+ // Putting the keyboard away is the other way out of search, so it
305
+ // restores the header too — the field stays, results and all.
306
+ useEffect(() => {
307
+ if (!isSearchOpen) {
308
+ return undefined;
209
309
  }
310
+ const sub = Keyboard.addListener('keyboardDidHide', restoreHeader);
311
+ return () => sub.remove();
312
+ }, [isSearchOpen]); // eslint-disable-line react-hooks/exhaustive-deps
313
+
314
+ const heroActions = useMemo(() => [{
315
+ key: 'search',
316
+ label: t('action.search'),
317
+ icon: color => /*#__PURE__*/_jsx(SearchIcon, {
318
+ color: color
319
+ }),
320
+ onPress: openMemberSearch
210
321
  }, {
211
- label: 'Delete',
212
- icon: null,
213
- onClick: e => {
214
- e?.preventDefault();
215
- handleDeleteUser(userId);
322
+ key: 'leave',
323
+ label: t('action.leave'),
324
+ icon: color => /*#__PURE__*/_jsx(LeaveIcon, {
325
+ color: color
326
+ }),
327
+ onPress: handleLeave
328
+ }, {
329
+ key: 'report',
330
+ label: t('action.report'),
331
+ icon: color => /*#__PURE__*/_jsx(ReportIcon, {
332
+ color: color
333
+ }),
334
+ onPress: () => setIsReportOpen(true)
335
+ }], [t, activeRoom?.jid] // eslint-disable-line react-hooks/exhaustive-deps
336
+ );
337
+
338
+ // "…" menu. Edit is the chat picture — the only chat detail this SDK can
339
+ // actually change (there is no update-chat endpoint for title/description),
340
+ // so it is only offered when the picture is editable.
341
+ const menuItems = useMemo(() => {
342
+ const items = [];
343
+ if (canEditIcon) {
344
+ items.push({
345
+ key: 'edit',
346
+ label: t('action.edit'),
347
+ icon: /*#__PURE__*/_jsx(EditIcon, {
348
+ color: "#141414",
349
+ width: 18,
350
+ height: 18
351
+ }),
352
+ onPress: onUpload
353
+ });
354
+ if (hasIcon) {
355
+ items.push({
356
+ key: 'remove-photo',
357
+ label: t('modal.chatProfile.removePhoto'),
358
+ icon: /*#__PURE__*/_jsx(DeleteIcon, {
359
+ width: 18,
360
+ height: 18
361
+ }),
362
+ onPress: onRemoveIcon
363
+ });
364
+ }
216
365
  }
217
- }], []);
218
- useEffect(() => {
219
- if (!activeRoom) {
220
- dispatch(setActiveModal(undefined));
366
+ // The hero's Search button is off-screen once collapsed, so the menu
367
+ // carries it — the design's collapsed menu does the same.
368
+ if (isCollapsed) {
369
+ items.push({
370
+ key: 'search',
371
+ label: t('action.search'),
372
+ icon: /*#__PURE__*/_jsx(SearchIcon, {
373
+ color: "#141414",
374
+ width: 18,
375
+ height: 18
376
+ }),
377
+ onPress: openMemberSearch
378
+ });
221
379
  }
222
- }, [activeRoom, dispatch]);
380
+ items.push({
381
+ key: 'report',
382
+ label: t('action.report'),
383
+ icon: /*#__PURE__*/_jsx(ReportIcon, {
384
+ color: "#141414",
385
+ width: 18,
386
+ height: 18
387
+ }),
388
+ onPress: () => setIsReportOpen(true)
389
+ });
390
+ if (canDeleteChat) {
391
+ items.push({
392
+ key: 'delete-and-leave',
393
+ label: t('action.deleteAndLeave'),
394
+ icon: /*#__PURE__*/_jsx(DeleteIcon, {
395
+ width: 18,
396
+ height: 18
397
+ }),
398
+ destructive: true,
399
+ onPress: () => setIsDeleteOpen(true)
400
+ });
401
+ }
402
+ return items;
403
+ }, [canEditIcon, canDeleteChat, hasIcon, isCollapsed, t]); // eslint-disable-line react-hooks/exhaustive-deps
404
+
223
405
  if (!activeRoom) {
224
406
  return null;
225
407
  }
408
+ const title = activeRoom.title || activeRoom.name;
409
+ const memberCount = activeRoom.usersCnt ?? 0;
410
+ const subtitle = t(memberCount === 1 ? 'modal.chatProfile.memberCountSingular' : 'modal.chatProfile.memberCountPlural', {
411
+ count: memberCount
412
+ });
413
+ const heroImage = appendFileToken(activeRoom.icon, fileToken) || null;
414
+ // A single flat colour behind the initials — the config's avatar colour
415
+ // when set, otherwise the primary. (The old per-name hash colour is what
416
+ // made the header read as two different greens next to the members' own
417
+ // avatars.)
418
+ const heroColor = config?.colors?.avatar || getIconColor(config);
419
+ const members = activeRoom.roomMembers ?? [];
420
+ const query = memberQuery.trim().toLowerCase();
421
+ const visibleMembers = query ? members.filter(user => `${user.firstName ?? ''} ${user.lastName ?? ''}`.toLowerCase().includes(query)) : members;
226
422
  return /*#__PURE__*/_jsxs(ModalContainerFullScreen, {
227
- style: {
228
- position: 'relative'
229
- },
230
- children: [/*#__PURE__*/_jsx(ModalHeaderComponent, {
231
- handleCloseModal: handleCloseModal,
232
- headerTitle: 'Chat Profile',
233
- titleStyle: chatTextStyle(config?.typography?.profile?.screenTitle),
234
- rightMenu: /*#__PURE__*/_jsxs(_Fragment, {
235
- children: [activeRoom?.type === 'public' && /*#__PURE__*/_jsx(Button, {
236
- EndIcon: /*#__PURE__*/_jsx(QrIcon, {}),
237
- onPress: () => setVisible(true)
238
- }), activeRoom.role === 'moderator' && activeRoom.type !== 'private' && /*#__PURE__*/_jsx(DropdownMenu, {
239
- position: "right",
240
- options: chatMenuOptions,
241
- openButton: /*#__PURE__*/_jsx(Button, {
242
- style: {
243
- padding: 8,
244
- height: 40
245
- },
246
- EndIcon: /*#__PURE__*/_jsx(MoreIcon, {}),
247
- unstyled: true
248
- })
249
- })]
250
- })
251
- }), /*#__PURE__*/_jsxs(CenterContainer, {
252
- children: [/*#__PURE__*/_jsx(ProfileImagePlaceholder, {
253
- name: activeRoom.title || activeRoom.name,
254
- icon: appendFileToken(activeRoom.icon, fileToken)
255
- // Two gates control whether the icon is editable:
256
- // 1. role — only non-participants could edit before.
257
- // 2. NEW: `disableChatInfo.disableIconEdit` — hard kill from
258
- // config so a consumer can make the icon read-only for
259
- // everyone (e.g. branded rooms, patient-facing apps).
260
- // Both must allow it for the picker/remove affordances to show.
261
- ,
262
- upload: {
263
- onUpload,
264
- active: !config?.disableChatInfo?.disableIconEdit && activeRoom?.role !== 'participant'
265
- },
266
- remove: {
267
- enabled: !config?.disableChatInfo?.disableIconEdit,
268
- onRemoveClick
269
- },
270
- role: activeRoom?.role,
271
- size: 128
272
- }), /*#__PURE__*/_jsxs(UserInfo, {
273
- children: [/*#__PURE__*/_jsx(UserName, {
274
- fontSize: config?.typography?.profile?.title?.fontSize,
275
- fontWeight: config?.typography?.profile?.title?.fontWeight,
276
- children: activeRoom.title || activeRoom.name
277
- }), /*#__PURE__*/_jsxs(UserStatus, {
278
- style: getElementFont(config, 'profileStatus'),
279
- children: [activeRoom.usersCnt, ' ', activeRoom.usersCnt > 1 ? 'members' : 'member']
280
- })]
281
- }), activeRoom.role === 'moderator' && activeRoom.type === 'group' && /*#__PURE__*/_jsx(_Fragment, {
282
- children: /*#__PURE__*/_jsx(SelectUsersModal, {})
283
- }), !config?.disableChatInfo?.disableDescription && /*#__PURE__*/_jsxs(BorderedContainer, {
284
- children: [/*#__PURE__*/_jsx(LabelData, {
285
- style: getElementFont(config, 'profileSectionLabel'),
286
- children: "Description"
287
- }), /*#__PURE__*/_jsx(Label, {
288
- children: activeRoom?.description || '—'
289
- })]
290
- }), !config?.disableChatInfo?.disableType && /*#__PURE__*/_jsxs(BorderedContainer, {
291
- children: [/*#__PURE__*/_jsx(LabelData, {
292
- style: getElementFont(config, 'profileSectionLabel'),
293
- children: "Chat type"
294
- }), /*#__PURE__*/_jsx(Label, {
295
- children: activeRoom.type || '—'
296
- })]
297
- }), !config?.disableChatInfo?.hideMembers && /*#__PURE__*/_jsx(BorderedContainer, {
298
- style: {
299
- paddingHorizontal: 16,
300
- paddingVertical: 8
301
- },
302
- children: loading ? /*#__PURE__*/_jsx(Loader, {}) : (activeRoom?.roomMembers?.length ?? 0) === 0 ? /*#__PURE__*/_jsx(Label, {
303
- style: {
304
- opacity: 0.6,
305
- textAlign: 'center',
306
- paddingVertical: 8
307
- },
308
- children: "Member list unavailable"
309
- }) : /*#__PURE__*/_jsx(ScrollView, {
310
- style: {
311
- maxHeight: 400
312
- },
313
- showsVerticalScrollIndicator: true,
314
- nestedScrollEnabled: true,
315
- children: activeRoom?.roomMembers?.map((user, index) => /*#__PURE__*/_jsxs(View, {
316
- style: {
317
- flexDirection: 'column',
318
- alignItems: 'flex-start'
319
- },
320
- children: [/*#__PURE__*/_jsxs(View, {
321
- style: {
322
- flexDirection: 'row',
323
- justifyContent: 'flex-start',
324
- paddingHorizontal: 8,
325
- paddingVertical: 0,
326
- alignItems: 'center',
327
- width: '100%'
423
+ style: styles.screen,
424
+ children: [/*#__PURE__*/_jsxs(Animated.ScrollView, {
425
+ ref: scrollRef,
426
+ style: styles.scroll
427
+ // The collapsed state has to be reachable even when the member list
428
+ // is short: without this the content was shorter than the viewport,
429
+ // so the scroll had nowhere to go and simply bounced back.
430
+ ,
431
+ contentContainerStyle: [styles.scrollContent, viewportHeight > 0 && {
432
+ minHeight: viewportHeight + collapseDistance
433
+ }],
434
+ onLayout: e => setViewportHeight(e.nativeEvent.layout.height),
435
+ showsVerticalScrollIndicator: false,
436
+ keyboardShouldPersistTaps: "handled",
437
+ scrollEventThrottle: 16,
438
+ onScroll: Animated.event([{
439
+ nativeEvent: {
440
+ contentOffset: {
441
+ y: scrollY
442
+ }
443
+ }
444
+ }], {
445
+ useNativeDriver: true,
446
+ listener: e => {
447
+ const y = e?.nativeEvent?.contentOffset?.y ?? 0;
448
+ setIsCollapsed(y >= collapseDistance - 8);
449
+ }
450
+ }),
451
+ children: [/*#__PURE__*/_jsx(ProfileHero, {
452
+ title: title,
453
+ subtitle: subtitle,
454
+ imageUri: heroImage,
455
+ fallbackColor: heroColor,
456
+ initials: chatInitials(title),
457
+ scrollY: scrollY,
458
+ actions: heroActions,
459
+ titleStyle: chatTextStyle(config?.typography?.profile?.title),
460
+ subtitleStyle: getElementFont(config, 'profileStatus')
461
+ }), /*#__PURE__*/_jsxs(View, {
462
+ style: styles.body,
463
+ children: [!config?.disableChatInfo?.disableDescription && /*#__PURE__*/_jsxs(View, {
464
+ style: styles.card,
465
+ children: [/*#__PURE__*/_jsx(Text, {
466
+ style: [styles.cardLabel, getElementFont(config, 'profileSectionLabel')],
467
+ children: t('modal.chatProfile.description')
468
+ }), /*#__PURE__*/_jsx(Text, {
469
+ style: styles.cardValue,
470
+ children: activeRoom.description || '—'
471
+ })]
472
+ }), !config?.disableChatInfo?.disableType && /*#__PURE__*/_jsxs(View, {
473
+ style: styles.card,
474
+ children: [/*#__PURE__*/_jsx(Text, {
475
+ style: [styles.cardLabel, getElementFont(config, 'profileSectionLabel')],
476
+ children: t('modal.chatProfile.chatType')
477
+ }), /*#__PURE__*/_jsx(Text, {
478
+ style: styles.cardValue,
479
+ children: activeRoom.type || '—'
480
+ })]
481
+ }), !config?.disableChatInfo?.hideMembers && /*#__PURE__*/_jsxs(View, {
482
+ style: styles.card,
483
+ children: [canAddMembers && /*#__PURE__*/_jsx(SelectUsersModal, {
484
+ trigger: open => /*#__PURE__*/_jsxs(TouchableOpacity, {
485
+ testID: "chat-profile-add-members",
486
+ activeOpacity: 0.7,
487
+ style: styles.addMembersRow,
488
+ onPress: open,
489
+ children: [/*#__PURE__*/_jsx(AddNewIcon, {
490
+ color: getIconColor(config)
491
+ }), /*#__PURE__*/_jsx(Text, {
492
+ style: styles.addMembersLabel,
493
+ children: t('modal.chatProfile.addMembers')
494
+ })]
495
+ })
496
+ }), /*#__PURE__*/_jsx(Text, {
497
+ style: [styles.cardLabel, getElementFont(config, 'profileSectionLabel')],
498
+ children: t('modal.chatProfile.membersLabel', {
499
+ count: memberCount
500
+ })
501
+ }), isSearchOpen && /*#__PURE__*/_jsxs(View, {
502
+ style: styles.searchRow,
503
+ children: [/*#__PURE__*/_jsx(SearchIcon, {
504
+ color: "#8C8C8C",
505
+ width: 18,
506
+ height: 18
507
+ }), /*#__PURE__*/_jsx(TextInput, {
508
+ testID: "chat-profile-member-search",
509
+ ref: searchInputRef,
510
+ style: styles.searchInput,
511
+ value: memberQuery,
512
+ onChangeText: setMemberQuery,
513
+ placeholder: t('search.members'),
514
+ placeholderTextColor: "#8C8C8C",
515
+ autoCorrect: false,
516
+ returnKeyType: "search"
517
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
518
+ testID: "chat-profile-search-close",
519
+ activeOpacity: 0.7,
520
+ hitSlop: {
521
+ top: 8,
522
+ bottom: 8,
523
+ left: 8,
524
+ right: 8
328
525
  },
526
+ onPress: closeMemberSearch,
527
+ children: /*#__PURE__*/_jsx(Text, {
528
+ style: styles.searchClose,
529
+ children: "\xD7"
530
+ })
531
+ })]
532
+ }), loading ? /*#__PURE__*/_jsx(Loader, {}) : visibleMembers.length === 0 ? /*#__PURE__*/_jsx(Text, {
533
+ testID: "chat-profile-members-empty",
534
+ style: styles.emptyMembers,
535
+ children: members.length === 0 ? t('modal.chatProfile.membersUnavailable') : t('search.noResults')
536
+ }) : visibleMembers.map((user, index) => {
537
+ const banned = user.ban_status === 'banned';
538
+ const roleLabel = user.role && user.role !== 'none' && user.role !== 'participant' ? user.role : null;
539
+ return /*#__PURE__*/_jsxs(View, {
540
+ style: [styles.memberRow, index > 0 && styles.memberDivider],
329
541
  children: [/*#__PURE__*/_jsxs(Pressable, {
330
- style: {
331
- flexDirection: 'row',
332
- alignItems: 'center',
333
- justifyContent: 'flex-start',
334
- gap: 16
335
- }
336
- // `disableChatInfo.disableMemberTap` blocks the
337
- // tap entirely so the user-profile popup never
338
- // opens. `disableMemberProfileActions` only hid
339
- // the action buttons INSIDE that popup, leaving
340
- // the popup itself to open on tap — this gate
341
- // closes the door. Customer-reported #16.
542
+ style: styles.memberMain
543
+ // `disableChatInfo.disableMemberTap` blocks the tap
544
+ // entirely so the user-profile popup never opens.
545
+ // `disableMemberProfileActions` only hid the action
546
+ // buttons INSIDE that popup, leaving the popup itself
547
+ // to open on tap — this gate closes the door.
548
+ // Customer-reported #16.
342
549
  ,
343
550
  onPress: config?.disableChatInfo?.disableMemberTap ? undefined : () => handleUserAvatarClick(user),
344
551
  disabled: !!config?.disableChatInfo?.disableMemberTap,
@@ -346,51 +553,187 @@ const ChatProfileModal = ({
346
553
  name: `${user.firstName} ${user.lastName}`,
347
554
  size: 40
348
555
  }), /*#__PURE__*/_jsxs(View, {
349
- style: {
350
- flexDirection: 'column',
351
- gap: 2,
352
- alignItems: 'flex-start',
353
- justifyContent: 'center'
354
- },
355
- children: [/*#__PURE__*/_jsxs(Label, {
356
- style: [{
357
- fontSize: 16,
358
- fontWeight: 600
359
- }, chatTextStyle(config?.typography?.profile?.memberName)],
556
+ style: styles.memberText,
557
+ children: [/*#__PURE__*/_jsxs(Text, {
558
+ numberOfLines: 1,
559
+ style: [styles.memberName, chatTextStyle(config?.typography?.profile?.memberName)],
360
560
  children: [user.firstName, " ", user.lastName]
361
- }), user.last_active && /*#__PURE__*/_jsx(LabelData, {
362
- style: getElementFont(config, 'profileSectionLabel'),
561
+ }), !!user.last_active && /*#__PURE__*/_jsx(Text, {
562
+ numberOfLines: 1,
563
+ style: [styles.memberStatus, getElementFont(config, 'profileSectionLabel')],
363
564
  children: new Date(user.last_active * 1000).toLocaleString()
364
565
  })]
365
566
  })]
366
- }), user.role && user.role !== 'none' && /*#__PURE__*/_jsx(Text, {
367
- style: {
368
- backgroundColor: user.ban_status !== 'banned' ? '#F3F6FC' : '#FFEBEE',
369
- color: user.ban_status !== 'banned' ? '#0052CD' : '#F44336',
370
- padding: 5,
371
- borderRadius: 16,
372
- fontSize: 12
567
+ }), (banned || roleLabel) && /*#__PURE__*/_jsx(Text, {
568
+ style: [styles.memberRole, banned && styles.memberBanned],
569
+ children: banned ? t('status.banned') : roleLabel
570
+ }), isModerator && activeRoom.type !== 'private' && stateUser.xmppUsername !== user.xmppUsername && /*#__PURE__*/_jsx(TouchableOpacity, {
571
+ testID: `chat-profile-remove-${user.xmppUsername}`,
572
+ activeOpacity: 0.7,
573
+ hitSlop: {
574
+ top: 8,
575
+ bottom: 8,
576
+ left: 8,
577
+ right: 8
373
578
  },
374
- children: user.role
375
- }), stateUser.xmppUsername !== user.xmppUsername && activeRoom.role === 'moderator' && activeRoom.type !== 'private' && /*#__PURE__*/_jsx(DropdownMenu, {
376
- options: menuOptions(user.xmppUsername),
377
- openButton: /*#__PURE__*/_jsx(Button, {
378
- onPress: () => {},
379
- children: /*#__PURE__*/_jsx(Text, {
380
- children: "More Options"
381
- })
382
- }),
383
- onClose: () => console.log('Dropdown closed')
579
+ style: styles.memberRemove,
580
+ onPress: () => confirmRemoveMember(user),
581
+ children: /*#__PURE__*/_jsx(DeleteIcon, {
582
+ width: 20,
583
+ height: 20
584
+ })
384
585
  })]
385
- }), index < (activeRoom?.roomMembers?.length || 0) - 1 && /*#__PURE__*/_jsx(Divider, {})]
386
- }, user.xmppUsername))
387
- })
586
+ }, user.xmppUsername);
587
+ })]
588
+ })]
388
589
  })]
590
+ }), /*#__PURE__*/_jsx(ProfileTopBar, {
591
+ title: title,
592
+ subtitle: subtitle,
593
+ imageUri: heroImage,
594
+ fallbackColor: heroColor,
595
+ initials: chatInitials(title),
596
+ scrollY: scrollY,
597
+ onBack: handleCloseModal,
598
+ titleStyle: chatTextStyle(config?.typography?.profile?.screenTitle),
599
+ menu: /*#__PURE__*/_jsx(ProfileMenu, {
600
+ items: menuItems
601
+ })
389
602
  }), /*#__PURE__*/_jsx(DeleteChatModal, {
390
- isModalOpen: isModalOpen,
391
- setIsModalOpen: setIsModalOpen
603
+ isModalOpen: isDeleteOpen,
604
+ setIsModalOpen: setIsDeleteOpen
605
+ }), /*#__PURE__*/_jsx(ReportChatModal, {
606
+ visible: isReportOpen,
607
+ onClose: () => setIsReportOpen(false)
392
608
  })]
393
609
  });
394
610
  };
611
+ const styles = StyleSheet.create({
612
+ screen: {
613
+ position: 'relative',
614
+ backgroundColor: '#F2F3F5'
615
+ },
616
+ scroll: {
617
+ width: '100%',
618
+ flex: 1
619
+ },
620
+ scrollContent: {
621
+ paddingBottom: 32
622
+ },
623
+ body: {
624
+ padding: 12,
625
+ gap: 12
626
+ },
627
+ card: {
628
+ backgroundColor: '#FFFFFF',
629
+ borderRadius: 14,
630
+ padding: 16,
631
+ shadowColor: '#000',
632
+ shadowOffset: {
633
+ width: 0,
634
+ height: 1
635
+ },
636
+ shadowOpacity: 0.05,
637
+ shadowRadius: 4,
638
+ elevation: 1
639
+ },
640
+ cardLabel: {
641
+ color: '#8C8C8C',
642
+ fontSize: 14
643
+ },
644
+ cardValue: {
645
+ color: '#141414',
646
+ fontSize: 16,
647
+ marginTop: 4
648
+ },
649
+ addMembersRow: {
650
+ flexDirection: 'row',
651
+ alignItems: 'center',
652
+ gap: 12,
653
+ paddingBottom: 14,
654
+ marginBottom: 10,
655
+ borderBottomWidth: StyleSheet.hairlineWidth,
656
+ borderBottomColor: '#EFEFF2'
657
+ },
658
+ addMembersLabel: {
659
+ fontSize: 16,
660
+ fontWeight: '500',
661
+ color: '#141414'
662
+ },
663
+ searchRow: {
664
+ flexDirection: 'row',
665
+ alignItems: 'center',
666
+ gap: 8,
667
+ marginTop: 10,
668
+ paddingHorizontal: 12,
669
+ height: 40,
670
+ borderRadius: 12,
671
+ backgroundColor: '#F2F3F5'
672
+ },
673
+ searchInput: {
674
+ flex: 1,
675
+ fontSize: 15,
676
+ color: '#141414',
677
+ padding: 0
678
+ },
679
+ searchClose: {
680
+ fontSize: 22,
681
+ lineHeight: 24,
682
+ color: '#8C8C8C'
683
+ },
684
+ emptyMembers: {
685
+ opacity: 0.6,
686
+ textAlign: 'center',
687
+ paddingVertical: 8,
688
+ color: '#141414'
689
+ },
690
+ memberRow: {
691
+ flexDirection: 'row',
692
+ alignItems: 'center',
693
+ paddingVertical: 10
694
+ },
695
+ memberDivider: {
696
+ borderTopWidth: StyleSheet.hairlineWidth,
697
+ borderTopColor: '#EFEFF2'
698
+ },
699
+ memberMain: {
700
+ flex: 1,
701
+ flexDirection: 'row',
702
+ alignItems: 'center',
703
+ gap: 12
704
+ },
705
+ memberText: {
706
+ flex: 1
707
+ },
708
+ memberName: {
709
+ fontSize: 16,
710
+ fontWeight: '600',
711
+ color: '#141414'
712
+ },
713
+ memberStatus: {
714
+ fontSize: 13,
715
+ color: '#8C8C8C',
716
+ marginTop: 2
717
+ },
718
+ memberRole: {
719
+ fontSize: 13,
720
+ color: '#8C8C8C',
721
+ marginLeft: 8
722
+ },
723
+ memberBanned: {
724
+ color: '#E53935'
725
+ },
726
+ memberRemove: {
727
+ marginLeft: 12
728
+ },
729
+ menuButton: {
730
+ width: 40,
731
+ height: 40,
732
+ borderRadius: 20,
733
+ backgroundColor: 'rgba(0,0,0,0.28)',
734
+ alignItems: 'center',
735
+ justifyContent: 'center'
736
+ }
737
+ });
395
738
  export default ChatProfileModal;
396
739
  //# sourceMappingURL=ChatProfileModal.js.map