@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
@@ -0,0 +1,244 @@
1
+ /** @format */
2
+
3
+ import React, { useState } from 'react';
4
+ import {
5
+ ActivityIndicator,
6
+ Modal,
7
+ StyleSheet,
8
+ Text,
9
+ TextInput,
10
+ TouchableOpacity,
11
+ View,
12
+ } from 'react-native';
13
+ import { useSelector } from 'react-redux';
14
+ import { getActiveRoom, RootState } from '../../../roomStore';
15
+ import { postReportRoom } from '../../../networking/api-requests/rooms.api';
16
+ import { useToast } from '../../../context/ToastContext';
17
+ import { useT } from '../../../i18n/useT';
18
+ import { getIconColor } from '../../../helpers/getIconColor';
19
+ import { useChatSettingState } from '../../../hooks/useChatSettingState';
20
+
21
+ /**
22
+ * Category ids go to `POST /v1/chats/reports/{chatName}` as-is; the labels
23
+ * come from the i18n table, which already carried `report.category.*`
24
+ * strings in all six locales with nothing rendering them until now.
25
+ */
26
+ const CATEGORIES = [
27
+ 'spam',
28
+ 'violence',
29
+ 'childAbuse',
30
+ 'pornography',
31
+ 'personalDetails',
32
+ 'illegalDrugs',
33
+ 'other',
34
+ ] as const;
35
+
36
+ interface ReportChatModalProps {
37
+ visible: boolean;
38
+ onClose: () => void;
39
+ }
40
+
41
+ const ReportChatModal: React.FC<ReportChatModalProps> = ({
42
+ visible,
43
+ onClose,
44
+ }) => {
45
+ const t = useT();
46
+ const { showToast } = useToast();
47
+ const { config } = useChatSettingState();
48
+ const activeRoom = useSelector((state: RootState) => getActiveRoom(state));
49
+ const [category, setCategory] = useState<string | null>(null);
50
+ const [details, setDetails] = useState('');
51
+ const [sending, setSending] = useState(false);
52
+ const primary = getIconColor(config);
53
+
54
+ const close = () => {
55
+ setCategory(null);
56
+ setDetails('');
57
+ onClose();
58
+ };
59
+
60
+ const submit = async () => {
61
+ if (!category || sending) {return;}
62
+ setSending(true);
63
+ try {
64
+ await postReportRoom({
65
+ chatName: activeRoom?.jid?.split('@')[0] || '',
66
+ category,
67
+ text: details.trim() || undefined,
68
+ });
69
+ showToast({
70
+ id: Date.now().toString(),
71
+ title: 'Success',
72
+ message: t('modal.report.chatTitle'),
73
+ type: 'success',
74
+ });
75
+ close();
76
+ } catch (error) {
77
+ console.error('Failed to report chat:', error);
78
+ showToast({
79
+ id: Date.now().toString(),
80
+ title: 'Error',
81
+ message: t('modal.report.chatTitle'),
82
+ type: 'error',
83
+ });
84
+ } finally {
85
+ setSending(false);
86
+ }
87
+ };
88
+
89
+ return (
90
+ <Modal
91
+ transparent
92
+ visible={visible}
93
+ animationType="fade"
94
+ onRequestClose={close}
95
+ >
96
+ <View style={styles.backdrop}>
97
+ <TouchableOpacity
98
+ testID="report-backdrop"
99
+ style={StyleSheet.absoluteFill}
100
+ activeOpacity={1}
101
+ onPress={close}
102
+ />
103
+ <View style={styles.card}>
104
+ <Text style={styles.title}>{t('modal.report.chatTitle')}</Text>
105
+ <View style={styles.categories}>
106
+ {CATEGORIES.map((id) => {
107
+ const selected = category === id;
108
+ return (
109
+ <TouchableOpacity
110
+ key={id}
111
+ testID={`report-category-${id}`}
112
+ activeOpacity={0.7}
113
+ onPress={() => setCategory(id)}
114
+ style={[
115
+ styles.category,
116
+ selected && { borderColor: primary, backgroundColor: primary + '14' },
117
+ ]}
118
+ >
119
+ <Text
120
+ style={[styles.categoryLabel, selected && { color: primary }]}
121
+ >
122
+ {t(`report.category.${id}`)}
123
+ </Text>
124
+ </TouchableOpacity>
125
+ );
126
+ })}
127
+ </View>
128
+ {category === 'other' && (
129
+ <TextInput
130
+ testID="report-details"
131
+ style={styles.input}
132
+ placeholder={t('modal.report.otherDetails')}
133
+ placeholderTextColor="#8C8C8C"
134
+ value={details}
135
+ onChangeText={setDetails}
136
+ multiline
137
+ />
138
+ )}
139
+ <View style={styles.buttons}>
140
+ <TouchableOpacity
141
+ activeOpacity={0.7}
142
+ style={[styles.button, styles.cancel]}
143
+ onPress={close}
144
+ >
145
+ <Text style={styles.cancelLabel}>{t('action.cancel')}</Text>
146
+ </TouchableOpacity>
147
+ <TouchableOpacity
148
+ testID="report-submit"
149
+ activeOpacity={0.7}
150
+ disabled={!category || sending}
151
+ style={[
152
+ styles.button,
153
+ { backgroundColor: primary, opacity: !category || sending ? 0.5 : 1 },
154
+ ]}
155
+ onPress={submit}
156
+ >
157
+ {sending ? (
158
+ <ActivityIndicator color="#FFFFFF" />
159
+ ) : (
160
+ <Text style={styles.submitLabel}>{t('action.send')}</Text>
161
+ )}
162
+ </TouchableOpacity>
163
+ </View>
164
+ </View>
165
+ </View>
166
+ </Modal>
167
+ );
168
+ };
169
+
170
+ const styles = StyleSheet.create({
171
+ backdrop: {
172
+ flex: 1,
173
+ backgroundColor: 'rgba(15,15,20,0.45)',
174
+ alignItems: 'center',
175
+ justifyContent: 'center',
176
+ padding: 24,
177
+ },
178
+ card: {
179
+ width: '100%',
180
+ borderRadius: 16,
181
+ backgroundColor: '#FFFFFF',
182
+ padding: 20,
183
+ },
184
+ title: {
185
+ fontSize: 18,
186
+ fontWeight: '600',
187
+ color: '#141414',
188
+ marginBottom: 16,
189
+ },
190
+ categories: {
191
+ flexDirection: 'row',
192
+ flexWrap: 'wrap',
193
+ gap: 8,
194
+ },
195
+ category: {
196
+ paddingHorizontal: 12,
197
+ paddingVertical: 8,
198
+ borderRadius: 20,
199
+ borderWidth: 1,
200
+ borderColor: '#E4E4E9',
201
+ },
202
+ categoryLabel: {
203
+ fontSize: 14,
204
+ color: '#141414',
205
+ },
206
+ input: {
207
+ marginTop: 16,
208
+ minHeight: 80,
209
+ borderRadius: 12,
210
+ borderWidth: 1,
211
+ borderColor: '#E4E4E9',
212
+ padding: 12,
213
+ fontSize: 14,
214
+ color: '#141414',
215
+ textAlignVertical: 'top',
216
+ },
217
+ buttons: {
218
+ flexDirection: 'row',
219
+ gap: 12,
220
+ marginTop: 20,
221
+ },
222
+ button: {
223
+ flex: 1,
224
+ height: 44,
225
+ borderRadius: 12,
226
+ alignItems: 'center',
227
+ justifyContent: 'center',
228
+ },
229
+ cancel: {
230
+ backgroundColor: '#F2F2F7',
231
+ },
232
+ cancelLabel: {
233
+ fontSize: 16,
234
+ fontWeight: '500',
235
+ color: '#141414',
236
+ },
237
+ submitLabel: {
238
+ fontSize: 16,
239
+ fontWeight: '600',
240
+ color: '#FFFFFF',
241
+ },
242
+ });
243
+
244
+ export default ReportChatModal;
@@ -26,7 +26,7 @@ import {
26
26
  import { useVideoPlayer, VideoView } from 'expo-video';
27
27
  import { PlayIcon } from '../../../assets/icons';
28
28
  import * as FileSystem from 'expo-file-system/legacy';
29
- import * as MediaLibrary from 'expo-media-library';
29
+ import { getMediaLibrary } from '../../../helpers/mediaLibraryRuntime';
30
30
  import { useToast } from '../../../context/ToastContext';
31
31
  import PdfViewer from './PdfView';
32
32
  import DocumentViewer from './DocumentViewer';
@@ -129,6 +129,8 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
129
129
  if (!activeFile) {return null;}
130
130
 
131
131
  const requestStoragePermission = async () => {
132
+ const MediaLibrary = getMediaLibrary();
133
+ if (!MediaLibrary?.requestPermissionsAsync) {return false;}
132
134
  try {
133
135
  const { status } = await MediaLibrary.requestPermissionsAsync();
134
136
  return status === 'granted';
@@ -158,7 +160,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
158
160
  const download = await FileSystem.downloadAsync(withFileToken(activeFile.fileURL), filePath);
159
161
 
160
162
  if (download.status === 200) {
161
- await MediaLibrary.saveToLibraryAsync(download.uri);
163
+ await getMediaLibrary()?.saveToLibraryAsync(download.uri);
162
164
  showToast({
163
165
  id: Date.now().toString(),
164
166
  title: 'Success',
@@ -37,6 +37,13 @@ const Modal: React.FC<ModalProps> = ({ children, modal, setOpenModal }) => {
37
37
 
38
38
  return <ModalComponent handleCloseModal={handleClose} />;
39
39
  };
40
+ // Modals that present themselves (a real RN <Modal>, so the dim covers
41
+ // the whole window rather than stopping at this component's frame) must
42
+ // not also sit inside the shared in-tree backdrop — that would dim twice.
43
+ if (modal === MODAL_TYPES.NEW_CHAT) {
44
+ return <>{renderModalContent()}{children}</>;
45
+ }
46
+
40
47
  return (
41
48
  modal && (
42
49
  <ModalBackground
@@ -1,20 +1,24 @@
1
- import React, { useState, useEffect, useMemo } from 'react';
2
- import Button from '../../styled/Button';
3
- import { AddNewIcon, AddPhotoIcon } from '../../../assets/icons';
1
+ import React, { useState, useMemo } from 'react';
2
+ import { CameraIcon } from '../../../assets/icons';
4
3
  import { RootState } from '../../../roomStore';
5
4
  import { useXmppClient } from '../../../context/xmppProvider';
6
- import {
7
- CloseButton,
8
- GroupContainer,
9
- ModalBackground,
10
- ModalContainer,
11
- ModalTitle,
12
- } from '../styledModalComponents';
13
5
  import { addRoomViaApi, setCurrentRoom, updateRoom } from '../../../roomStore/roomsSlice';
14
- import InputWithLabel from '../../styled/StyledInput';
15
6
  import { uploadFile } from '../../../networking/api-requests/auth.api';
16
- import { ProfileImagePlaceholder } from '../../MainComponents/ProfileImagePlaceholder';
17
- import { Text, Alert, Linking } from 'react-native';
7
+ import {
8
+ ActivityIndicator,
9
+ Alert,
10
+ Image,
11
+ Linking,
12
+ Modal,
13
+ Pressable,
14
+ StyleSheet,
15
+ Text,
16
+ TextInput,
17
+ TouchableOpacity,
18
+ View,
19
+ } from 'react-native';
20
+ import { getIconColor } from '../../../helpers/getIconColor';
21
+ import { useT } from '../../../i18n/useT';
18
22
  import * as ImagePicker from 'expo-image-picker';
19
23
  import { ApiRoom, ChatAccessOption, RoomMember } from '../../../types/models/room.model';
20
24
  import { createRoomFromApi } from '../../../helpers/createRoomFromApi';
@@ -24,16 +28,16 @@ import { useChatSettingState } from '../../../hooks/useChatSettingState';
24
28
  import { useToast } from '../../../context/ToastContext';
25
29
 
26
30
  interface NewChatModalProps {
27
- handleCloseModal?: any;
31
+ handleCloseModal?: () => void;
28
32
  }
29
33
 
30
34
  const NewChatModal: React.FC<NewChatModalProps> = ({
31
35
  // Some call sites mount `<NewChatModal />` with no props (e.g. the
32
- // empty-state in ChatRoom when roomsList is empty). Default to a noop
33
- // so the Close/Cancel buttons don't throw "handleClose is not a
34
- // function".
35
- handleCloseModal: handleClose = () => {},
36
+ // empty-state in ChatRoom when roomsList is empty). There is nothing to
37
+ // dismiss back to there, so Cancel just resets the form.
38
+ handleCloseModal: handleClose,
36
39
  }) => {
40
+ const t = useT();
37
41
  const config = useAppSelector(
38
42
  (state: RootState) => state.chatSettingStore.config
39
43
  );
@@ -43,9 +47,7 @@ const NewChatModal: React.FC<NewChatModalProps> = ({
43
47
  const { user } = useChatSettingState();
44
48
  const { showToast } = useToast();
45
49
 
46
- const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
47
50
  const [loading, setLoading] = useState<boolean>(false);
48
- const [activeTab, setActiveTab] = useState<'0' | '1' | null>('0');
49
51
 
50
52
  const [roomName, setRoomName] = useState<string>('');
51
53
  const [roomDescription, setRoomDescription] = useState<string>('');
@@ -65,7 +67,7 @@ const NewChatModal: React.FC<NewChatModalProps> = ({
65
67
 
66
68
  const validateRoomName = (name: string) => {
67
69
  if (name.trim().length < 3) {
68
- return 'Room name must be at least 3 characters.';
70
+ return t('modal.newChat.nameTooShort');
69
71
  }
70
72
  return '';
71
73
  };
@@ -97,13 +99,17 @@ const NewChatModal: React.FC<NewChatModalProps> = ({
97
99
  }));
98
100
  };
99
101
 
100
- const handleOpenModal = () => setIsModalOpen(true);
101
- const handleCloseModal = () => {
102
- handleClose();
103
- setActiveTab('0');
104
- setIsModalOpen(false);
102
+ const resetForm = () => {
105
103
  setRoomName('');
104
+ setRoomDescription('');
105
+ setProfileImage(null);
106
106
  setSelectedUsers([]);
107
+ setErrors({ name: '', description: '' });
108
+ };
109
+
110
+ const handleCloseModal = () => {
111
+ resetForm();
112
+ handleClose?.();
107
113
  };
108
114
 
109
115
  const onUpload = async () => {
@@ -129,7 +135,7 @@ const NewChatModal: React.FC<NewChatModalProps> = ({
129
135
  quality: 0.8,
130
136
  });
131
137
 
132
- if (result.canceled) return;
138
+ if (result.canceled) {return;}
133
139
 
134
140
  const asset = result.assets[0];
135
141
  const originalName = asset.uri.split('/').pop();
@@ -161,7 +167,7 @@ const NewChatModal: React.FC<NewChatModalProps> = ({
161
167
  usersArrayLength
162
168
  );
163
169
 
164
- if (!normalizedChat || !client) return;
170
+ if (!normalizedChat || !client) {return;}
165
171
 
166
172
  dispatch(
167
173
  addRoomViaApi({
@@ -261,103 +267,199 @@ const NewChatModal: React.FC<NewChatModalProps> = ({
261
267
  }
262
268
  }
263
269
 
264
- setIsModalOpen(false);
265
- setErrors({ name: '', description: '' });
266
- setProfileImage(null);
267
- setRoomName('');
268
- setRoomDescription('');
270
+ resetForm();
269
271
  setLoading(false);
270
272
  }
271
273
  };
272
274
 
275
+ const primary = getIconColor(config);
276
+ const pickedUri =
277
+ profileImage && typeof profileImage === 'object' && 'uri' in profileImage
278
+ ? profileImage.uri
279
+ : typeof profileImage === 'string'
280
+ ? profileImage
281
+ : null;
282
+
273
283
  return (
274
- <>
275
- {/* <Button
276
- style={{
277
- padding: 8,
278
- borderRadius: 16,
279
- backgroundColor: "transparent",
280
- }}
281
- color="black"
282
- unstyled
283
- EndIcon={<AddNewIcon color={config?.colors?.primary} />}
284
- onPress={handleOpenModal}
285
- /> */}
286
-
287
- <ModalBackground
288
- // visible={isModalOpen}
289
- // transparent={true}
290
- // animationType="fade"
291
- // onRequestClose={handleCloseModal}
292
- >
293
- <ModalContainer>
294
- <CloseButton onPress={handleCloseModal}>
295
- <Text style={{ fontSize: 24, padding: 5 }}>&times;</Text>
296
- </CloseButton>
297
- <ModalTitle>Create New Chat</ModalTitle>
298
- <ProfileImagePlaceholder
299
- size={120}
300
- upload={{ active: true, onUpload }}
301
- remove={{ enabled: true, onRemoveClick }}
302
- placeholderIcon={<AddPhotoIcon color="#0052CD" />}
303
- icon={
304
- profileImage && typeof profileImage === 'object' && 'uri' in profileImage
305
- ? { uri: profileImage.uri }
306
- : profileImage
307
- }
308
- disableOverlay={!profileImage}
309
- role="user"
310
- />
311
- <GroupContainer
312
- style={{
313
- flexDirection: 'column',
314
- position: 'relative',
315
- width: '100%',
316
- }}
284
+ // A real <Modal> rather than an in-tree overlay: the SDK renders inside
285
+ // whatever frame the host gives it, so an in-tree backdrop stopped at
286
+ // the component's edge and left the host's own chrome (tab bars and
287
+ // such) lit. This one dims the whole window.
288
+ <Modal
289
+ transparent
290
+ visible
291
+ animationType="fade"
292
+ statusBarTranslucent
293
+ onRequestClose={handleCloseModal}
294
+ >
295
+ <View style={styles.backdrop}>
296
+ <Pressable
297
+ testID="new-chat-backdrop"
298
+ style={StyleSheet.absoluteFill}
299
+ onPress={handleCloseModal}
300
+ />
301
+ <View style={styles.card}>
302
+ <Text style={styles.title}>{t('modal.newChat.title')}</Text>
303
+
304
+ <TouchableOpacity
305
+ testID="new-chat-picture"
306
+ activeOpacity={0.8}
307
+ onPress={onUpload}
308
+ onLongPress={pickedUri ? onRemoveClick : undefined}
309
+ style={[styles.picture, { backgroundColor: primary }]}
317
310
  >
318
- <InputWithLabel
319
- color="#F5F7F9"
320
- id="roomName"
321
- value={roomName}
322
- onChangeText={handleRoomNameChange}
323
- placeholder="Enter Room Name"
324
- helperText={errors.name}
325
- error={!!errors.name}
326
- />
327
- <InputWithLabel
328
- color="#F5F7F9"
329
- id="roomDescription"
330
- value={roomDescription}
331
- onChangeText={handleRoomDescriptionChange}
332
- placeholder="Enter Description"
333
- helperText={errors.description}
334
- error={!!errors.description}
335
- />
336
- </GroupContainer>
337
-
338
- <GroupContainer>
339
- <Button
340
- onPress={handleCreateRoom}
341
- text={'Create'}
342
- style={{ width: '100%' }}
343
- unstyled
344
- variant="filled"
345
- disabled={!isValid}
346
- color="#fff"
347
- />
348
- <Button
311
+ {pickedUri ? (
312
+ <Image source={{ uri: pickedUri }} style={styles.pictureImage} />
313
+ ) : (
314
+ <CameraIcon color="#FFFFFF" width={26} height={26} />
315
+ )}
316
+ </TouchableOpacity>
317
+
318
+ <TextInput
319
+ testID="new-chat-name"
320
+ style={styles.input}
321
+ value={roomName}
322
+ onChangeText={handleRoomNameChange}
323
+ placeholder={t('modal.newChat.roomNamePlaceholder')}
324
+ placeholderTextColor="#8C8C8C"
325
+ returnKeyType="next"
326
+ />
327
+ {!!errors.name && roomName.length > 0 && (
328
+ <Text testID="new-chat-name-error" style={styles.error}>
329
+ {errors.name}
330
+ </Text>
331
+ )}
332
+
333
+ <TextInput
334
+ testID="new-chat-description"
335
+ style={[styles.input, styles.textArea]}
336
+ value={roomDescription}
337
+ onChangeText={handleRoomDescriptionChange}
338
+ placeholder={t('modal.newChat.descriptionPlaceholder')}
339
+ placeholderTextColor="#8C8C8C"
340
+ multiline
341
+ />
342
+
343
+ <View style={styles.buttons}>
344
+ <TouchableOpacity
345
+ testID="new-chat-cancel"
346
+ activeOpacity={0.7}
347
+ style={[styles.button, styles.cancel]}
349
348
  onPress={handleCloseModal}
350
- text={'Cancel'}
351
- style={{ width: '100%' }}
352
- unstyled
353
- variant="outlined"
354
- color="#0052CD"
355
- />
356
- </GroupContainer>
357
- </ModalContainer>
358
- </ModalBackground>
359
- </>
349
+ >
350
+ <Text style={styles.cancelLabel}>{t('action.cancel')}</Text>
351
+ </TouchableOpacity>
352
+ <TouchableOpacity
353
+ testID="new-chat-submit"
354
+ activeOpacity={0.7}
355
+ disabled={!isValid || loading}
356
+ style={[
357
+ styles.button,
358
+ { backgroundColor: primary, opacity: !isValid || loading ? 0.5 : 1 },
359
+ ]}
360
+ onPress={handleCreateRoom}
361
+ >
362
+ {loading ? (
363
+ <ActivityIndicator color="#FFFFFF" />
364
+ ) : (
365
+ <Text style={styles.submitLabel}>
366
+ {t('modal.newChat.createButton')}
367
+ </Text>
368
+ )}
369
+ </TouchableOpacity>
370
+ </View>
371
+ </View>
372
+ </View>
373
+ </Modal>
360
374
  );
361
375
  };
362
376
 
377
+ const styles = StyleSheet.create({
378
+ backdrop: {
379
+ flex: 1,
380
+ // Opaque, per the design: the chat list behind stays hidden rather
381
+ // than showing through a translucent dim.
382
+ backgroundColor: '#E9EDF2',
383
+ alignItems: 'center',
384
+ justifyContent: 'center',
385
+ padding: 24,
386
+ },
387
+ card: {
388
+ width: '100%',
389
+ maxWidth: 380,
390
+ borderRadius: 20,
391
+ backgroundColor: '#FFFFFF',
392
+ padding: 20,
393
+ shadowColor: '#121219',
394
+ shadowOffset: { width: 0, height: 8 },
395
+ shadowOpacity: 0.08,
396
+ shadowRadius: 24,
397
+ elevation: 6,
398
+ },
399
+ title: {
400
+ fontSize: 17,
401
+ fontWeight: '700',
402
+ color: '#141414',
403
+ textAlign: 'center',
404
+ },
405
+ picture: {
406
+ alignSelf: 'center',
407
+ width: 72,
408
+ height: 72,
409
+ borderRadius: 36,
410
+ marginVertical: 18,
411
+ alignItems: 'center',
412
+ justifyContent: 'center',
413
+ overflow: 'hidden',
414
+ },
415
+ pictureImage: {
416
+ width: '100%',
417
+ height: '100%',
418
+ },
419
+ input: {
420
+ borderRadius: 12,
421
+ backgroundColor: '#F4F5F7',
422
+ paddingHorizontal: 14,
423
+ paddingVertical: 12,
424
+ fontSize: 15,
425
+ color: '#141414',
426
+ marginTop: 10,
427
+ },
428
+ textArea: {
429
+ minHeight: 84,
430
+ textAlignVertical: 'top',
431
+ },
432
+ error: {
433
+ color: '#E53935',
434
+ fontSize: 12,
435
+ marginTop: 6,
436
+ marginLeft: 4,
437
+ },
438
+ buttons: {
439
+ flexDirection: 'row',
440
+ gap: 12,
441
+ marginTop: 20,
442
+ },
443
+ button: {
444
+ flex: 1,
445
+ height: 44,
446
+ borderRadius: 12,
447
+ alignItems: 'center',
448
+ justifyContent: 'center',
449
+ },
450
+ cancel: {
451
+ backgroundColor: '#E7E8EA',
452
+ },
453
+ cancelLabel: {
454
+ fontSize: 15,
455
+ fontWeight: '500',
456
+ color: '#8C8C8C',
457
+ },
458
+ submitLabel: {
459
+ fontSize: 15,
460
+ fontWeight: '600',
461
+ color: '#FFFFFF',
462
+ },
463
+ });
464
+
363
465
  export default NewChatModal;