@ethora/chat-component-rn 26.7.4 → 26.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/CHANGELOG.md +0 -54
  2. package/README.md +8 -31
  3. package/lib/commonjs/assets/icons.js +2 -7
  4. package/lib/commonjs/assets/icons.js.map +1 -1
  5. package/lib/commonjs/components/Header/HeaderRoomList.js +6 -20
  6. package/lib/commonjs/components/Header/HeaderRoomList.js.map +1 -1
  7. package/lib/commonjs/components/MainComponents/ChatRoom.js +14 -36
  8. package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
  9. package/lib/commonjs/components/MainComponents/MessageList.js +23 -7
  10. package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
  11. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js +13 -14
  12. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  13. package/lib/commonjs/components/MainComponents/RoomList.js +32 -62
  14. package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
  15. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +98 -309
  16. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
  17. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +110 -320
  18. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  19. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +213 -552
  20. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  21. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +2 -6
  22. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  23. package/lib/commonjs/components/Modals/Modal/Modal.js +0 -8
  24. package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
  25. package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js +1 -2
  26. package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js.map +1 -1
  27. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js +104 -202
  28. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  29. package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js +0 -8
  30. package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
  31. package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js +2 -4
  32. package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
  33. package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js +21 -7
  34. package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
  35. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +244 -507
  36. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  37. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +46 -74
  38. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  39. package/lib/commonjs/components/Modals/styledModalComponents.js +2 -9
  40. package/lib/commonjs/components/Modals/styledModalComponents.js.map +1 -1
  41. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +7 -17
  42. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
  43. package/lib/commonjs/components/styled/SendInput.js +11 -80
  44. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  45. package/lib/commonjs/components/styled/StyledComponents.js +3 -9
  46. package/lib/commonjs/components/styled/StyledComponents.js.map +1 -1
  47. package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js +4 -11
  48. package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
  49. package/lib/commonjs/context/xmppProvider.js +35 -6
  50. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  51. package/lib/commonjs/helpers/updateMessagesTillLast.js +40 -12
  52. package/lib/commonjs/helpers/updateMessagesTillLast.js.map +1 -1
  53. package/lib/commonjs/hooks/useChatRoomFocus.js +9 -3
  54. package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -1
  55. package/lib/commonjs/hooks/useLogout.js +5 -0
  56. package/lib/commonjs/hooks/useLogout.js.map +1 -1
  57. package/lib/commonjs/hooks/useSendMessage.js +50 -23
  58. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  59. package/lib/commonjs/i18n/strings.js +1 -121
  60. package/lib/commonjs/i18n/strings.js.map +1 -1
  61. package/lib/commonjs/main.js +0 -6
  62. package/lib/commonjs/main.js.map +1 -1
  63. package/lib/commonjs/networking/api-requests/user.api.js +0 -59
  64. package/lib/commonjs/networking/api-requests/user.api.js.map +1 -1
  65. package/lib/commonjs/networking/outboundQueue.js +18 -0
  66. package/lib/commonjs/networking/outboundQueue.js.map +1 -1
  67. package/lib/commonjs/networking/stanzaHandlers.js +10 -1
  68. package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
  69. package/lib/commonjs/networking/xmppClient.js +107 -7
  70. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  71. package/lib/commonjs/roomStore/chatSettingsSlice.js +1 -3
  72. package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
  73. package/lib/commonjs/roomStore/roomsSlice.js +22 -3
  74. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  75. package/lib/module/assets/icons.js +1 -6
  76. package/lib/module/assets/icons.js.map +1 -1
  77. package/lib/module/components/Header/HeaderRoomList.js +6 -20
  78. package/lib/module/components/Header/HeaderRoomList.js.map +1 -1
  79. package/lib/module/components/MainComponents/ChatRoom.js +14 -36
  80. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  81. package/lib/module/components/MainComponents/MessageList.js +24 -8
  82. package/lib/module/components/MainComponents/MessageList.js.map +1 -1
  83. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js +13 -14
  84. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  85. package/lib/module/components/MainComponents/RoomList.js +32 -62
  86. package/lib/module/components/MainComponents/RoomList.js.map +1 -1
  87. package/lib/module/components/Menu/HeaderRoomListMenu.js +101 -311
  88. package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
  89. package/lib/module/components/Modals/AttachSheet/AttachSheet.js +113 -311
  90. package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  91. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +217 -555
  92. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  93. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +2 -6
  94. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  95. package/lib/module/components/Modals/Modal/Modal.js +1 -9
  96. package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
  97. package/lib/module/components/Modals/NewChatModal/ModalContent.js +1 -2
  98. package/lib/module/components/Modals/NewChatModal/ModalContent.js.map +1 -1
  99. package/lib/module/components/Modals/NewChatModal/NewChatModal.js +106 -205
  100. package/lib/module/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  101. package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js +0 -8
  102. package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
  103. package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js +2 -4
  104. package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
  105. package/lib/module/components/Modals/UserProfileModal/EditUserModal.js +23 -9
  106. package/lib/module/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
  107. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +248 -509
  108. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  109. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +48 -76
  110. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  111. package/lib/module/components/Modals/styledModalComponents.js +2 -9
  112. package/lib/module/components/Modals/styledModalComponents.js.map +1 -1
  113. package/lib/module/components/RoomComponents/ChatRoomItem.js +7 -17
  114. package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
  115. package/lib/module/components/styled/SendInput.js +12 -81
  116. package/lib/module/components/styled/SendInput.js.map +1 -1
  117. package/lib/module/components/styled/StyledComponents.js +3 -9
  118. package/lib/module/components/styled/StyledComponents.js.map +1 -1
  119. package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js +4 -11
  120. package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
  121. package/lib/module/context/xmppProvider.js +35 -6
  122. package/lib/module/context/xmppProvider.js.map +1 -1
  123. package/lib/module/helpers/updateMessagesTillLast.js +41 -13
  124. package/lib/module/helpers/updateMessagesTillLast.js.map +1 -1
  125. package/lib/module/hooks/useChatRoomFocus.js +9 -3
  126. package/lib/module/hooks/useChatRoomFocus.js.map +1 -1
  127. package/lib/module/hooks/useLogout.js +5 -0
  128. package/lib/module/hooks/useLogout.js.map +1 -1
  129. package/lib/module/hooks/useSendMessage.js +51 -24
  130. package/lib/module/hooks/useSendMessage.js.map +1 -1
  131. package/lib/module/i18n/strings.js +1 -121
  132. package/lib/module/i18n/strings.js.map +1 -1
  133. package/lib/module/main.js +1 -1
  134. package/lib/module/main.js.map +1 -1
  135. package/lib/module/networking/api-requests/user.api.js +0 -56
  136. package/lib/module/networking/api-requests/user.api.js.map +1 -1
  137. package/lib/module/networking/outboundQueue.js +17 -0
  138. package/lib/module/networking/outboundQueue.js.map +1 -1
  139. package/lib/module/networking/stanzaHandlers.js +10 -1
  140. package/lib/module/networking/stanzaHandlers.js.map +1 -1
  141. package/lib/module/networking/xmppClient.js +107 -7
  142. package/lib/module/networking/xmppClient.js.map +1 -1
  143. package/lib/module/roomStore/chatSettingsSlice.js +1 -3
  144. package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
  145. package/lib/module/roomStore/roomsSlice.js +20 -2
  146. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  147. package/lib/typescript/assets/icons.d.ts +0 -16
  148. package/lib/typescript/assets/icons.d.ts.map +1 -1
  149. package/lib/typescript/components/Header/HeaderRoomList.d.ts.map +1 -1
  150. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  151. package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
  152. package/lib/typescript/components/MainComponents/ProfileImagePlaceholder.d.ts.map +1 -1
  153. package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
  154. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts +0 -3
  155. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
  156. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts +0 -9
  157. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
  158. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts +0 -10
  159. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
  160. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
  161. package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
  162. package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts +2 -4
  163. package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts.map +1 -1
  164. package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts +1 -1
  165. package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts.map +1 -1
  166. package/lib/typescript/components/Modals/NewChatModal/UpdNewChatModal.d.ts.map +1 -1
  167. package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts +1 -6
  168. package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts.map +1 -1
  169. package/lib/typescript/components/Modals/UserProfileModal/EditUserModal.d.ts.map +1 -1
  170. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts +0 -16
  171. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
  172. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts +0 -1
  173. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
  174. package/lib/typescript/components/Modals/styledModalComponents.d.ts.map +1 -1
  175. package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
  176. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  177. package/lib/typescript/components/styled/StyledComponents.d.ts.map +1 -1
  178. package/lib/typescript/components/styled/StyledInputComponents/StyledInputComponents.d.ts.map +1 -1
  179. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  180. package/lib/typescript/helpers/updateMessagesTillLast.d.ts.map +1 -1
  181. package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -1
  182. package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
  183. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  184. package/lib/typescript/i18n/strings.d.ts.map +1 -1
  185. package/lib/typescript/main.d.ts +1 -1
  186. package/lib/typescript/main.d.ts.map +1 -1
  187. package/lib/typescript/networking/api-requests/user.api.d.ts +0 -27
  188. package/lib/typescript/networking/api-requests/user.api.d.ts.map +1 -1
  189. package/lib/typescript/networking/outboundQueue.d.ts +16 -0
  190. package/lib/typescript/networking/outboundQueue.d.ts.map +1 -1
  191. package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
  192. package/lib/typescript/networking/xmppClient.d.ts +33 -1
  193. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  194. package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
  195. package/lib/typescript/roomStore/roomsSlice.d.ts +18 -1
  196. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  197. package/lib/typescript/types/models/room.model.d.ts +15 -0
  198. package/lib/typescript/types/models/room.model.d.ts.map +1 -1
  199. package/lib/typescript/types/types.d.ts +20 -20
  200. package/lib/typescript/types/types.d.ts.map +1 -1
  201. package/package.json +1 -6
  202. package/src/assets/icons.tsx +9 -48
  203. package/src/components/Header/HeaderRoomList.tsx +5 -20
  204. package/src/components/MainComponents/ChatRoom.tsx +20 -38
  205. package/src/components/MainComponents/MessageList.tsx +24 -8
  206. package/src/components/MainComponents/ProfileImagePlaceholder.tsx +14 -21
  207. package/src/components/MainComponents/RoomList.tsx +34 -65
  208. package/src/components/Menu/HeaderRoomListMenu.tsx +71 -310
  209. package/src/components/Modals/AttachSheet/AttachSheet.tsx +97 -331
  210. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +279 -598
  211. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +2 -4
  212. package/src/components/Modals/Modal/Modal.tsx +0 -7
  213. package/src/components/Modals/NewChatModal/ModalContent.tsx +3 -6
  214. package/src/components/Modals/NewChatModal/NewChatModal.tsx +117 -219
  215. package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +1 -12
  216. package/src/components/Modals/SelectUsersModal/SelectUsersModal.tsx +4 -14
  217. package/src/components/Modals/UserProfileModal/EditUserModal.tsx +25 -9
  218. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +307 -617
  219. package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +58 -75
  220. package/src/components/Modals/styledModalComponents.tsx +2 -9
  221. package/src/components/RoomComponents/ChatRoomItem.tsx +7 -14
  222. package/src/components/styled/SendInput.tsx +12 -83
  223. package/src/components/styled/StyledComponents.ts +3 -9
  224. package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +4 -11
  225. package/src/context/xmppProvider.tsx +41 -8
  226. package/src/helpers/updateMessagesTillLast.tsx +42 -17
  227. package/src/hooks/useChatRoomFocus.ts +11 -3
  228. package/src/hooks/useLogout.tsx +7 -0
  229. package/src/hooks/useSendMessage.tsx +60 -24
  230. package/src/i18n/strings.ts +1 -121
  231. package/src/main.ts +1 -1
  232. package/src/networking/api-requests/user.api.ts +0 -71
  233. package/src/networking/outboundQueue.ts +29 -0
  234. package/src/networking/stanzaHandlers.ts +9 -1
  235. package/src/networking/xmppClient.ts +118 -7
  236. package/src/roomStore/chatSettingsSlice.ts +1 -3
  237. package/src/roomStore/roomsSlice.ts +20 -2
  238. package/src/types/models/room.model.ts +15 -0
  239. package/src/types/types.ts +20 -22
  240. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js +0 -226
  241. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js.map +0 -1
  242. package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js +0 -556
  243. package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js.map +0 -1
  244. package/lib/commonjs/components/Modals/ProfileHeader/ProfileMenu.js +0 -210
  245. package/lib/commonjs/components/Modals/ProfileHeader/ProfileMenu.js.map +0 -1
  246. package/lib/commonjs/helpers/getChatBackground.js +0 -23
  247. package/lib/commonjs/helpers/getChatBackground.js.map +0 -1
  248. package/lib/commonjs/helpers/mediaLibraryRuntime.js +0 -31
  249. package/lib/commonjs/helpers/mediaLibraryRuntime.js.map +0 -1
  250. package/lib/commonjs/helpers/pickImageAsset.js +0 -68
  251. package/lib/commonjs/helpers/pickImageAsset.js.map +0 -1
  252. package/lib/commonjs/helpers/sheetGestures.js +0 -32
  253. package/lib/commonjs/helpers/sheetGestures.js.map +0 -1
  254. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js +0 -223
  255. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js.map +0 -1
  256. package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js +0 -548
  257. package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js.map +0 -1
  258. package/lib/module/components/Modals/ProfileHeader/ProfileMenu.js +0 -205
  259. package/lib/module/components/Modals/ProfileHeader/ProfileMenu.js.map +0 -1
  260. package/lib/module/helpers/getChatBackground.js +0 -18
  261. package/lib/module/helpers/getChatBackground.js.map +0 -1
  262. package/lib/module/helpers/mediaLibraryRuntime.js +0 -25
  263. package/lib/module/helpers/mediaLibraryRuntime.js.map +0 -1
  264. package/lib/module/helpers/pickImageAsset.js +0 -63
  265. package/lib/module/helpers/pickImageAsset.js.map +0 -1
  266. package/lib/module/helpers/sheetGestures.js +0 -26
  267. package/lib/module/helpers/sheetGestures.js.map +0 -1
  268. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts +0 -9
  269. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts.map +0 -1
  270. package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts +0 -75
  271. package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts.map +0 -1
  272. package/lib/typescript/components/Modals/ProfileHeader/ProfileMenu.d.ts +0 -25
  273. package/lib/typescript/components/Modals/ProfileHeader/ProfileMenu.d.ts.map +0 -1
  274. package/lib/typescript/helpers/getChatBackground.d.ts +0 -15
  275. package/lib/typescript/helpers/getChatBackground.d.ts.map +0 -1
  276. package/lib/typescript/helpers/mediaLibraryRuntime.d.ts +0 -3
  277. package/lib/typescript/helpers/mediaLibraryRuntime.d.ts.map +0 -1
  278. package/lib/typescript/helpers/pickImageAsset.d.ts +0 -27
  279. package/lib/typescript/helpers/pickImageAsset.d.ts.map +0 -1
  280. package/lib/typescript/helpers/sheetGestures.d.ts +0 -20
  281. package/lib/typescript/helpers/sheetGestures.d.ts.map +0 -1
  282. package/src/components/Modals/ChatProfileModal/ReportChatModal.tsx +0 -244
  283. package/src/components/Modals/ProfileHeader/ProfileHeader.tsx +0 -615
  284. package/src/components/Modals/ProfileHeader/ProfileMenu.tsx +0 -217
  285. package/src/helpers/getChatBackground.ts +0 -18
  286. package/src/helpers/mediaLibraryRuntime.ts +0 -25
  287. package/src/helpers/pickImageAsset.ts +0 -68
  288. package/src/helpers/sheetGestures.ts +0 -25
@@ -1,615 +0,0 @@
1
- /** @format */
2
-
3
- import React from 'react';
4
- import {
5
- Animated,
6
- Image,
7
- StyleProp,
8
- StyleSheet,
9
- Text,
10
- TextStyle,
11
- TouchableOpacity,
12
- View,
13
- } from 'react-native';
14
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
15
- import { BackIcon } from '../../../assets/icons';
16
- import { getAvatarTextColor } from '../../../helpers/getAvatarColor';
17
-
18
- /** Height of the expanded photo hero. */
19
- export const HERO_HEIGHT = 320;
20
- /** Back / "…" row, directly below the status-bar inset. */
21
- export const TOP_BAR_BUTTONS = 60;
22
- /**
23
- * Avatar + name row underneath it, revealed as the header collapses.
24
- * Taller than the 48pt avatar it holds, so the row breathes: the extra
25
- * height splits evenly above and below (the row centres its content),
26
- * putting real space between the avatar and both the buttons above and
27
- * the content below.
28
- */
29
- export const TOP_BAR_NAME = 92;
30
- /** Content band of the collapsed bar, below the status-bar inset. */
31
- export const TOP_BAR_BAND = TOP_BAR_BUTTONS + TOP_BAR_NAME;
32
- /** How far above the fully-collapsed point the bar starts fading in. */
33
- const COLLAPSE_RAMP = 48;
34
- /**
35
- * Blur strength once the header is fully collapsed. The design's collapsed
36
- * bar is frosted heavily — the picture is a mood, not a subject — so this
37
- * sits near the top of expo-blur's 0-100 range, with a dim over it to keep
38
- * the white text and the sharp round avatar reading against it.
39
- */
40
- const BLUR_INTENSITY = 92;
41
- /** Darkening applied on top of the blur (and used alone without it). */
42
- const FROST_DIM = 'rgba(0,0,0,0.28)';
43
- /** Height of the readability gradient under the name and buttons. */
44
- const SCRIM_HEIGHT = 220;
45
- /** Bands the gradient is built from — enough that no step is visible. */
46
- const SCRIM_BANDS = 16;
47
- /** Darkest the gradient gets, at the very bottom of the hero. */
48
- const SCRIM_MAX_ALPHA = 0.45;
49
-
50
- /**
51
- * How far above the hero its backdrop reaches. Over-scrolling downwards
52
- * exposes that band, and the picture grows into it (anchored at its own
53
- * bottom edge) rather than a second copy being painted there.
54
- */
55
- const OVERSCROLL_REACH = 400;
56
-
57
- // expo-blur is an OPTIONAL peer. Having the JS package is not enough — the
58
- // native view has to be in the binary too, and an app that installed the
59
- // package without rebuilding renders a red "Unimplemented component:
60
- // ExpoBlurView" box instead of a blur. `requireNativeModule` throws when
61
- // that native half is missing, which is the only reliable way to tell the
62
- // two apart, so probe it once and fall back to a plain dim otherwise.
63
- let BlurView: any = null;
64
- try {
65
- const { requireNativeModule } = require('expo-modules-core');
66
- requireNativeModule('ExpoBlur');
67
- BlurView = require('expo-blur').BlurView ?? null;
68
- } catch {
69
- BlurView = null;
70
- }
71
-
72
- /** True when the frosted-glass layer is the real thing, not the dim. */
73
- export const hasNativeBlur = () => !!BlurView;
74
-
75
- /**
76
- * Bottom-up darkening so white text stays readable over a photo.
77
- *
78
- * A single flat overlay (what this was) has a hard top edge that reads as
79
- * "the bottom half of the picture is dark". There is no gradient
80
- * dependency in this package, so it is stacked out of thin bands whose
81
- * alpha ramps quadratically — at 16 bands over 220 pt the steps are below
82
- * what the eye picks up on a photo.
83
- */
84
- const ScrimGradient: React.FC = () => (
85
- <View pointerEvents="none" style={styles.scrim}>
86
- {Array.from({ length: SCRIM_BANDS }, (_, i) => (
87
- <View
88
- key={i}
89
- style={{
90
- height: SCRIM_HEIGHT / SCRIM_BANDS,
91
- backgroundColor: `rgba(0,0,0,${(
92
- SCRIM_MAX_ALPHA * ((i + 1) / SCRIM_BANDS) ** 2
93
- ).toFixed(3)})`,
94
- }}
95
- />
96
- ))}
97
- </View>
98
- );
99
-
100
- const FrostLayer: React.FC<{ tint?: 'dark' | 'light' }> = ({ tint = 'dark' }) =>
101
- BlurView ? (
102
- <>
103
- <BlurView
104
- intensity={BLUR_INTENSITY}
105
- tint={tint}
106
- style={StyleSheet.absoluteFill}
107
- />
108
- <View style={[StyleSheet.absoluteFill, styles.frostDim]} />
109
- </>
110
- ) : (
111
- <View style={[StyleSheet.absoluteFill, styles.frostFallback]} />
112
- );
113
-
114
- export interface HeroAction {
115
- key: string;
116
- label: string;
117
- /** Rendered inside a circle tinted for the current background. */
118
- icon: (color: string) => React.ReactNode;
119
- onPress: () => void;
120
- }
121
-
122
- interface CommonProps {
123
- title: string;
124
- subtitle?: string;
125
- imageUri?: string | null;
126
- /** Background when the chat has no picture — one flat colour, no scrims. */
127
- fallbackColor: string;
128
- /** Two uppercase letters shown on that background. */
129
- initials: string;
130
- scrollY: Animated.Value;
131
- /** Prefixes every testID, so each screen's tests address their own. */
132
- testIDPrefix?: string;
133
- }
134
-
135
- /** Everything the screen needs to line its scroll content up with the bar. */
136
- export const useHeaderMetrics = () => {
137
- const insets = useSafeAreaInsets();
138
- const barHeight = insets.top + TOP_BAR_BAND;
139
- return {
140
- insets,
141
- barHeight,
142
- /** Scroll distance between the expanded hero and the collapsed bar. */
143
- collapseDistance: Math.max(HERO_HEIGHT - barHeight, 1),
144
- };
145
- };
146
-
147
- const useCollapse = (scrollY: Animated.Value, collapseDistance: number) =>
148
- scrollY.interpolate({
149
- inputRange: [
150
- Math.max(collapseDistance - COLLAPSE_RAMP, 0),
151
- collapseDistance,
152
- ],
153
- outputRange: [0, 1],
154
- extrapolate: 'clamp',
155
- });
156
-
157
- /**
158
- * The chat picture, blown up to a full-bleed hero with the name, member
159
- * count and the round action buttons on top of it.
160
- *
161
- * It lives INSIDE the ScrollView (rather than behind it) so the action
162
- * buttons stay tappable — an absolutely-positioned hero would sit under a
163
- * full-screen scroll surface that swallows every touch. Parallax is done
164
- * on the inner image instead: the wrapper keeps its layout height while
165
- * the picture drifts at ~⅓ of the scroll speed, and over-scrolling
166
- * upwards scales it up the way iOS profile headers do.
167
- */
168
- export const ProfileHero: React.FC<
169
- CommonProps & {
170
- actions: HeroAction[];
171
- /** Rendered to the right of the name (the profile's Leave button). */
172
- titleAccessory?: React.ReactNode;
173
- titleStyle?: StyleProp<TextStyle>;
174
- subtitleStyle?: StyleProp<TextStyle>;
175
- }
176
- > = ({
177
- title,
178
- subtitle,
179
- imageUri,
180
- fallbackColor,
181
- initials,
182
- scrollY,
183
- actions,
184
- titleAccessory,
185
- titleStyle,
186
- subtitleStyle,
187
- testIDPrefix = 'chat-profile',
188
- }) => {
189
- const { collapseDistance } = useHeaderMetrics();
190
- const parallax = scrollY.interpolate({
191
- inputRange: [0, HERO_HEIGHT],
192
- outputRange: [0, HERO_HEIGHT * 0.35],
193
- // Clamped on the left: with `extend` an over-scroll pulled the picture
194
- // UP off its own bottom edge, exposing a band of the backdrop colour
195
- // under it. Pulling down is the scale's job alone.
196
- extrapolateLeft: 'clamp',
197
- extrapolateRight: 'clamp',
198
- });
199
- const scale = scrollY.interpolate({
200
- inputRange: [-HERO_HEIGHT, 0],
201
- outputRange: [2, 1],
202
- extrapolateRight: 'clamp',
203
- });
204
- // The name and buttons are gone well before the collapsed bar arrives,
205
- // so the two never overlap mid-scroll.
206
- const contentOpacity = scrollY.interpolate({
207
- inputRange: [0, HERO_HEIGHT * 0.4],
208
- outputRange: [1, 0],
209
- extrapolate: 'clamp',
210
- });
211
- const collapsed = useCollapse(scrollY, collapseDistance);
212
-
213
- // On a photo everything is white over a bottom scrim. On the flat
214
- // fallback colour there is no scrim at all — that double-tone banding
215
- // was two stacked scrims showing their seam — so the text takes
216
- // whichever of black/white reads on that colour.
217
- const onPhoto = !!imageUri;
218
- const contentColor = onPhoto ? '#FFFFFF' : getAvatarTextColor(fallbackColor);
219
- // The glyphs inside the circles are always white — several of the SDK's
220
- // icons paint white regardless of their `color` prop, so tinting the
221
- // rest to match the title left a mix of black and white glyphs in one
222
- // row. The circle darkens instead, which keeps them readable on a light
223
- // fill as well as on a photo.
224
- const iconColor = '#FFFFFF';
225
- const circleTint = onPhoto
226
- ? 'rgba(255,255,255,0.22)'
227
- : contentColor === '#FFFFFF'
228
- ? 'rgba(255,255,255,0.22)'
229
- : 'rgba(0,0,0,0.22)';
230
-
231
- return (
232
- <View style={[styles.hero, { backgroundColor: fallbackColor }]}>
233
- <View style={[styles.backdropClip, { backgroundColor: fallbackColor }]}>
234
- <Animated.View
235
- style={[
236
- styles.backdrop,
237
- {
238
- transform: [
239
- { translateY: parallax },
240
- // Scale about the bottom edge (translate → scale →
241
- // translate back, RN has no transform-origin) so pulling
242
- // down grows the picture upwards into the exposed band by
243
- // exactly the amount that band opened.
244
- { translateY: HERO_HEIGHT / 2 },
245
- { scale },
246
- { translateY: -HERO_HEIGHT / 2 },
247
- ],
248
- },
249
- ]}
250
- >
251
- {onPhoto ? (
252
- <Image
253
- testID={`${testIDPrefix}-hero-image`}
254
- source={{ uri: imageUri as string }}
255
- style={StyleSheet.absoluteFill}
256
- resizeMode="cover"
257
- />
258
- ) : (
259
- <View style={styles.initialsWrap}>
260
- <Text
261
- testID={`${testIDPrefix}-hero-initials`}
262
- style={[styles.heroInitials, { color: contentColor }]}
263
- >
264
- {initials}
265
- </Text>
266
- </View>
267
- )}
268
- </Animated.View>
269
-
270
- {/* Frosts the picture as the header collapses — the same layer the
271
- * collapsed bar sits on, so the transition reads as one motion.
272
- * Only over a photo: there is nothing to blur on a flat colour,
273
- * and the dim fallback would just darken it into a second shade
274
- * of itself. */}
275
- {onPhoto && (
276
- <Animated.View
277
- testID={`${testIDPrefix}-hero-blur`}
278
- pointerEvents="none"
279
- style={[StyleSheet.absoluteFill, { opacity: collapsed }]}
280
- >
281
- <FrostLayer />
282
- </Animated.View>
283
- )}
284
-
285
- {onPhoto && <ScrimGradient />}
286
- </View>
287
-
288
- <Animated.View style={[styles.heroContent, { opacity: contentOpacity }]}>
289
- <View style={styles.titleRow}>
290
- <Text
291
- numberOfLines={2}
292
- style={[
293
- styles.heroTitle,
294
- styles.titleText,
295
- { color: contentColor },
296
- titleStyle,
297
- ]}
298
- >
299
- {title}
300
- </Text>
301
- {titleAccessory}
302
- </View>
303
- {!!subtitle && (
304
- <Text
305
- style={[
306
- styles.heroSubtitle,
307
- { color: contentColor, opacity: 0.85 },
308
- subtitleStyle,
309
- ]}
310
- >
311
- {subtitle}
312
- </Text>
313
- )}
314
- {actions.length > 0 && (
315
- <View style={styles.actionsRow}>
316
- {actions.map((action) => (
317
- <TouchableOpacity
318
- key={action.key}
319
- testID={`${testIDPrefix}-action-${action.key}`}
320
- activeOpacity={0.7}
321
- style={styles.action}
322
- onPress={action.onPress}
323
- >
324
- <View
325
- style={[styles.actionCircle, { backgroundColor: circleTint }]}
326
- >
327
- {action.icon(iconColor)}
328
- </View>
329
- <Text style={[styles.actionLabel, { color: contentColor }]}>
330
- {action.label}
331
- </Text>
332
- </TouchableOpacity>
333
- ))}
334
- </View>
335
- )}
336
- </Animated.View>
337
- </View>
338
- );
339
- };
340
-
341
- /**
342
- * The bar pinned over the hero: back button and the "…" menu are always
343
- * there, while the frosted picture, small avatar and name fade in as the
344
- * hero scrolls away — the collapsed state from the design's third screen.
345
- */
346
- export const ProfileTopBar: React.FC<
347
- CommonProps & {
348
- onBack: () => void;
349
- menu?: React.ReactNode;
350
- titleStyle?: StyleProp<TextStyle>;
351
- }
352
- > = ({
353
- title,
354
- subtitle,
355
- imageUri,
356
- fallbackColor,
357
- initials,
358
- scrollY,
359
- onBack,
360
- menu,
361
- titleStyle,
362
- testIDPrefix = 'chat-profile',
363
- }) => {
364
- const { insets, barHeight, collapseDistance } = useHeaderMetrics();
365
- const collapsed = useCollapse(scrollY, collapseDistance);
366
- const rise = collapsed.interpolate({
367
- inputRange: [0, 1],
368
- outputRange: [10, 0],
369
- });
370
- const onPhoto = !!imageUri;
371
- const contentColor = onPhoto ? '#FFFFFF' : getAvatarTextColor(fallbackColor);
372
-
373
- return (
374
- <View
375
- pointerEvents="box-none"
376
- style={[styles.topBar, { height: barHeight, paddingTop: insets.top }]}
377
- >
378
- {/* Background layer: the same picture, cropped to the bar and frosted,
379
- * so nothing flips colour mid-scroll. */}
380
- <Animated.View
381
- pointerEvents="none"
382
- style={[
383
- StyleSheet.absoluteFill,
384
- { backgroundColor: fallbackColor, opacity: collapsed },
385
- ]}
386
- >
387
- {onPhoto && (
388
- <>
389
- <Image
390
- source={{ uri: imageUri as string }}
391
- style={StyleSheet.absoluteFill}
392
- resizeMode="cover"
393
- />
394
- <FrostLayer />
395
- </>
396
- )}
397
- </Animated.View>
398
-
399
- <View style={styles.topBarButtons}>
400
- <TouchableOpacity
401
- testID={`${testIDPrefix}-back`}
402
- activeOpacity={0.7}
403
- onPress={onBack}
404
- style={styles.roundButton}
405
- hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
406
- >
407
- <BackIcon color="#FFFFFF" />
408
- </TouchableOpacity>
409
- <View style={styles.topBarRight}>{menu}</View>
410
- </View>
411
-
412
- {/* Avatar + name on their own row, as in the design's collapsed
413
- * screen. It only appears once the hero has scrolled away, so it
414
- * never competes with the big title over the picture. */}
415
- <Animated.View
416
- testID={`${testIDPrefix}-collapsed-title`}
417
- pointerEvents="none"
418
- style={[
419
- styles.collapsedTitle,
420
- { opacity: collapsed, transform: [{ translateY: rise }] },
421
- ]}
422
- >
423
- <View style={styles.collapsedAvatar}>
424
- {onPhoto ? (
425
- <Image
426
- source={{ uri: imageUri as string }}
427
- style={styles.collapsedAvatarImage}
428
- />
429
- ) : (
430
- <View
431
- style={[
432
- styles.collapsedAvatarImage,
433
- styles.initialsWrap,
434
- { backgroundColor: fallbackColor },
435
- ]}
436
- >
437
- <Text style={[styles.collapsedInitials, { color: contentColor }]}>
438
- {initials}
439
- </Text>
440
- </View>
441
- )}
442
- </View>
443
- <View style={styles.collapsedText}>
444
- <Text numberOfLines={1} style={[styles.collapsedName, titleStyle]}>
445
- {title}
446
- </Text>
447
- {!!subtitle && (
448
- <Text numberOfLines={1} style={styles.collapsedSubtitle}>
449
- {subtitle}
450
- </Text>
451
- )}
452
- </View>
453
- </Animated.View>
454
- </View>
455
- );
456
- };
457
-
458
- const styles = StyleSheet.create({
459
- hero: {
460
- width: '100%',
461
- height: HERO_HEIGHT,
462
- justifyContent: 'flex-end',
463
- },
464
- // Reaches above the hero and clips its own contents, so the picture can
465
- // grow up into the over-scroll band without spilling over the cards
466
- // below when it parallaxes down.
467
- backdropClip: {
468
- position: 'absolute',
469
- left: 0,
470
- right: 0,
471
- bottom: 0,
472
- height: HERO_HEIGHT + OVERSCROLL_REACH,
473
- overflow: 'hidden',
474
- },
475
- backdrop: {
476
- position: 'absolute',
477
- left: 0,
478
- right: 0,
479
- bottom: 0,
480
- height: HERO_HEIGHT,
481
- },
482
- initialsWrap: {
483
- ...StyleSheet.absoluteFill,
484
- alignItems: 'center',
485
- justifyContent: 'center',
486
- },
487
- heroInitials: {
488
- fontSize: 64,
489
- fontWeight: '600',
490
- // Sit in the upper half so the name below never collides with it.
491
- marginBottom: 120,
492
- },
493
- frostDim: {
494
- backgroundColor: FROST_DIM,
495
- },
496
- frostFallback: {
497
- backgroundColor: 'rgba(0,0,0,0.35)',
498
- },
499
- // Only over a photo: keeps white text readable without tinting the flat
500
- // fallback colour.
501
- scrim: {
502
- ...StyleSheet.absoluteFill,
503
- top: undefined,
504
- height: SCRIM_HEIGHT,
505
- justifyContent: 'flex-end',
506
- },
507
- heroContent: {
508
- paddingHorizontal: 20,
509
- paddingBottom: 20,
510
- },
511
- // The accessory (the profile's Leave button) is pushed to the far right;
512
- // the name takes what is left of the row.
513
- titleRow: {
514
- flexDirection: 'row',
515
- alignItems: 'center',
516
- justifyContent: 'space-between',
517
- gap: 12,
518
- },
519
- titleText: {
520
- flexShrink: 1,
521
- },
522
- heroTitle: {
523
- fontSize: 26,
524
- fontWeight: '600',
525
- },
526
- heroSubtitle: {
527
- fontSize: 14,
528
- marginTop: 2,
529
- },
530
- // Centred: Search / Leave / Report.
531
- actionsRow: {
532
- flexDirection: 'row',
533
- justifyContent: 'center',
534
- marginTop: 20,
535
- gap: 16,
536
- },
537
- action: {
538
- alignItems: 'center',
539
- width: 64,
540
- },
541
- actionCircle: {
542
- width: 56,
543
- height: 56,
544
- borderRadius: 28,
545
- alignItems: 'center',
546
- justifyContent: 'center',
547
- },
548
- actionLabel: {
549
- fontSize: 12,
550
- marginTop: 6,
551
- },
552
- topBar: {
553
- position: 'absolute',
554
- top: 0,
555
- left: 0,
556
- right: 0,
557
- zIndex: 10,
558
- },
559
- topBarButtons: {
560
- height: TOP_BAR_BUTTONS,
561
- flexDirection: 'row',
562
- alignItems: 'flex-end',
563
- paddingBottom: 4,
564
- // 20 = the collapsed row's 16pt inset + half the difference between
565
- // the 48pt avatar and these 40pt buttons, so a button's centre line
566
- // matches the avatar's once the header is collapsed.
567
- paddingHorizontal: 20,
568
- },
569
- roundButton: {
570
- width: 40,
571
- height: 40,
572
- borderRadius: 20,
573
- backgroundColor: 'rgba(0,0,0,0.28)',
574
- alignItems: 'center',
575
- justifyContent: 'center',
576
- },
577
- topBarRight: {
578
- marginLeft: 'auto',
579
- },
580
- collapsedTitle: {
581
- height: TOP_BAR_NAME,
582
- flexDirection: 'row',
583
- alignItems: 'center',
584
- paddingHorizontal: 16,
585
- gap: 12,
586
- },
587
- collapsedAvatar: {
588
- width: 48,
589
- height: 48,
590
- borderRadius: 24,
591
- overflow: 'hidden',
592
- backgroundColor: 'rgba(255,255,255,0.2)',
593
- },
594
- collapsedAvatarImage: {
595
- width: '100%',
596
- height: '100%',
597
- },
598
- collapsedInitials: {
599
- fontSize: 18,
600
- fontWeight: '600',
601
- },
602
- collapsedText: {
603
- flex: 1,
604
- },
605
- collapsedName: {
606
- color: '#FFFFFF',
607
- fontSize: 20,
608
- fontWeight: '600',
609
- },
610
- collapsedSubtitle: {
611
- color: 'rgba(255,255,255,0.8)',
612
- fontSize: 13,
613
- marginTop: 1,
614
- },
615
- });