@ethora/chat-component-rn 26.7.5 → 26.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (340) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +31 -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 +26 -7
  6. package/lib/commonjs/components/Header/HeaderRoomList.js.map +1 -1
  7. package/lib/commonjs/components/MainComponents/ChatHeader.js +5 -2
  8. package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
  9. package/lib/commonjs/components/MainComponents/ChatRoom.js +36 -14
  10. package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
  11. package/lib/commonjs/components/MainComponents/ChatWrapper.js +2 -0
  12. package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
  13. package/lib/commonjs/components/MainComponents/MessageList.js +7 -23
  14. package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
  15. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js +14 -13
  16. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  17. package/lib/commonjs/components/MainComponents/RoomList.js +208 -35
  18. package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
  19. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +317 -98
  20. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
  21. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +320 -110
  22. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  23. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +552 -213
  24. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  25. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js +226 -0
  26. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -0
  27. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +6 -2
  28. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  29. package/lib/commonjs/components/Modals/Modal/Modal.js +8 -0
  30. package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
  31. package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js +2 -1
  32. package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js.map +1 -1
  33. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js +202 -104
  34. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  35. package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js +8 -0
  36. package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
  37. package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js +556 -0
  38. package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js.map +1 -0
  39. package/lib/commonjs/components/Modals/ProfileHeader/ProfileMenu.js +210 -0
  40. package/lib/commonjs/components/Modals/ProfileHeader/ProfileMenu.js.map +1 -0
  41. package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js +4 -2
  42. package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
  43. package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js +7 -21
  44. package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
  45. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +507 -244
  46. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  47. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +74 -46
  48. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  49. package/lib/commonjs/components/Modals/styledModalComponents.js +9 -2
  50. package/lib/commonjs/components/Modals/styledModalComponents.js.map +1 -1
  51. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +17 -7
  52. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
  53. package/lib/commonjs/components/styled/SendInput.js +80 -11
  54. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  55. package/lib/commonjs/components/styled/StyledComponents.js +9 -3
  56. package/lib/commonjs/components/styled/StyledComponents.js.map +1 -1
  57. package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js +11 -4
  58. package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
  59. package/lib/commonjs/context/xmppProvider.js +32 -39
  60. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  61. package/lib/commonjs/helpers/getChatBackground.js +23 -0
  62. package/lib/commonjs/helpers/getChatBackground.js.map +1 -0
  63. package/lib/commonjs/helpers/mediaLibraryRuntime.js +31 -0
  64. package/lib/commonjs/helpers/mediaLibraryRuntime.js.map +1 -0
  65. package/lib/commonjs/helpers/pickImageAsset.js +68 -0
  66. package/lib/commonjs/helpers/pickImageAsset.js.map +1 -0
  67. package/lib/commonjs/helpers/pushPayload.js +71 -0
  68. package/lib/commonjs/helpers/pushPayload.js.map +1 -0
  69. package/lib/commonjs/helpers/sheetGestures.js +32 -0
  70. package/lib/commonjs/helpers/sheetGestures.js.map +1 -0
  71. package/lib/commonjs/helpers/updateMessagesTillLast.js +12 -40
  72. package/lib/commonjs/helpers/updateMessagesTillLast.js.map +1 -1
  73. package/lib/commonjs/hooks/useChatRoomFocus.js +3 -9
  74. package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -1
  75. package/lib/commonjs/hooks/useLogout.js +0 -5
  76. package/lib/commonjs/hooks/useLogout.js.map +1 -1
  77. package/lib/commonjs/hooks/usePendingNotification.js +8 -11
  78. package/lib/commonjs/hooks/usePendingNotification.js.map +1 -1
  79. package/lib/commonjs/hooks/useSendMessage.js +23 -50
  80. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  81. package/lib/commonjs/i18n/strings.js +121 -1
  82. package/lib/commonjs/i18n/strings.js.map +1 -1
  83. package/lib/commonjs/main.js +19 -0
  84. package/lib/commonjs/main.js.map +1 -1
  85. package/lib/commonjs/networking/api-requests/user.api.js +59 -0
  86. package/lib/commonjs/networking/api-requests/user.api.js.map +1 -1
  87. package/lib/commonjs/networking/authRefresh.js +12 -2
  88. package/lib/commonjs/networking/authRefresh.js.map +1 -1
  89. package/lib/commonjs/networking/outboundQueue.js +0 -18
  90. package/lib/commonjs/networking/outboundQueue.js.map +1 -1
  91. package/lib/commonjs/networking/stanzaHandlers.js +1 -10
  92. package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
  93. package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js +8 -1
  94. package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
  95. package/lib/commonjs/networking/xmpp/subscribeToRoomMessages.xmpp.js +5 -1
  96. package/lib/commonjs/networking/xmpp/subscribeToRoomMessages.xmpp.js.map +1 -1
  97. package/lib/commonjs/networking/xmppClient.js +62 -108
  98. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  99. package/lib/commonjs/roomStore/chatSettingsSlice.js +3 -1
  100. package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
  101. package/lib/commonjs/roomStore/roomsSlice.js +3 -22
  102. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  103. package/lib/commonjs/services/pushSubscriptionService.js +15 -13
  104. package/lib/commonjs/services/pushSubscriptionService.js.map +1 -1
  105. package/lib/module/assets/icons.js +6 -1
  106. package/lib/module/assets/icons.js.map +1 -1
  107. package/lib/module/components/Header/HeaderRoomList.js +26 -7
  108. package/lib/module/components/Header/HeaderRoomList.js.map +1 -1
  109. package/lib/module/components/MainComponents/ChatHeader.js +5 -2
  110. package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
  111. package/lib/module/components/MainComponents/ChatRoom.js +36 -14
  112. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  113. package/lib/module/components/MainComponents/ChatWrapper.js +2 -0
  114. package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
  115. package/lib/module/components/MainComponents/MessageList.js +8 -24
  116. package/lib/module/components/MainComponents/MessageList.js.map +1 -1
  117. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js +14 -13
  118. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  119. package/lib/module/components/MainComponents/RoomList.js +207 -35
  120. package/lib/module/components/MainComponents/RoomList.js.map +1 -1
  121. package/lib/module/components/Menu/HeaderRoomListMenu.js +319 -101
  122. package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
  123. package/lib/module/components/Modals/AttachSheet/AttachSheet.js +311 -113
  124. package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  125. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +555 -217
  126. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  127. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js +223 -0
  128. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -0
  129. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +6 -2
  130. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  131. package/lib/module/components/Modals/Modal/Modal.js +9 -1
  132. package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
  133. package/lib/module/components/Modals/NewChatModal/ModalContent.js +2 -1
  134. package/lib/module/components/Modals/NewChatModal/ModalContent.js.map +1 -1
  135. package/lib/module/components/Modals/NewChatModal/NewChatModal.js +205 -106
  136. package/lib/module/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  137. package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js +8 -0
  138. package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
  139. package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js +548 -0
  140. package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js.map +1 -0
  141. package/lib/module/components/Modals/ProfileHeader/ProfileMenu.js +205 -0
  142. package/lib/module/components/Modals/ProfileHeader/ProfileMenu.js.map +1 -0
  143. package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js +4 -2
  144. package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
  145. package/lib/module/components/Modals/UserProfileModal/EditUserModal.js +9 -23
  146. package/lib/module/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
  147. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +509 -248
  148. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  149. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +76 -48
  150. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  151. package/lib/module/components/Modals/styledModalComponents.js +9 -2
  152. package/lib/module/components/Modals/styledModalComponents.js.map +1 -1
  153. package/lib/module/components/RoomComponents/ChatRoomItem.js +17 -7
  154. package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
  155. package/lib/module/components/styled/SendInput.js +81 -12
  156. package/lib/module/components/styled/SendInput.js.map +1 -1
  157. package/lib/module/components/styled/StyledComponents.js +9 -3
  158. package/lib/module/components/styled/StyledComponents.js.map +1 -1
  159. package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js +11 -4
  160. package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
  161. package/lib/module/context/xmppProvider.js +32 -39
  162. package/lib/module/context/xmppProvider.js.map +1 -1
  163. package/lib/module/helpers/getChatBackground.js +18 -0
  164. package/lib/module/helpers/getChatBackground.js.map +1 -0
  165. package/lib/module/helpers/mediaLibraryRuntime.js +25 -0
  166. package/lib/module/helpers/mediaLibraryRuntime.js.map +1 -0
  167. package/lib/module/helpers/pickImageAsset.js +63 -0
  168. package/lib/module/helpers/pickImageAsset.js.map +1 -0
  169. package/lib/module/helpers/pushPayload.js +63 -0
  170. package/lib/module/helpers/pushPayload.js.map +1 -0
  171. package/lib/module/helpers/sheetGestures.js +26 -0
  172. package/lib/module/helpers/sheetGestures.js.map +1 -0
  173. package/lib/module/helpers/updateMessagesTillLast.js +13 -41
  174. package/lib/module/helpers/updateMessagesTillLast.js.map +1 -1
  175. package/lib/module/hooks/useChatRoomFocus.js +3 -9
  176. package/lib/module/hooks/useChatRoomFocus.js.map +1 -1
  177. package/lib/module/hooks/useLogout.js +0 -5
  178. package/lib/module/hooks/useLogout.js.map +1 -1
  179. package/lib/module/hooks/usePendingNotification.js +8 -11
  180. package/lib/module/hooks/usePendingNotification.js.map +1 -1
  181. package/lib/module/hooks/useSendMessage.js +24 -51
  182. package/lib/module/hooks/useSendMessage.js.map +1 -1
  183. package/lib/module/i18n/strings.js +121 -1
  184. package/lib/module/i18n/strings.js.map +1 -1
  185. package/lib/module/main.js +2 -1
  186. package/lib/module/main.js.map +1 -1
  187. package/lib/module/networking/api-requests/user.api.js +56 -0
  188. package/lib/module/networking/api-requests/user.api.js.map +1 -1
  189. package/lib/module/networking/authRefresh.js +12 -2
  190. package/lib/module/networking/authRefresh.js.map +1 -1
  191. package/lib/module/networking/outboundQueue.js +0 -17
  192. package/lib/module/networking/outboundQueue.js.map +1 -1
  193. package/lib/module/networking/stanzaHandlers.js +1 -10
  194. package/lib/module/networking/stanzaHandlers.js.map +1 -1
  195. package/lib/module/networking/xmpp/presenceInRoom.xmpp.js +8 -1
  196. package/lib/module/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
  197. package/lib/module/networking/xmpp/subscribeToRoomMessages.xmpp.js +5 -1
  198. package/lib/module/networking/xmpp/subscribeToRoomMessages.xmpp.js.map +1 -1
  199. package/lib/module/networking/xmppClient.js +62 -108
  200. package/lib/module/networking/xmppClient.js.map +1 -1
  201. package/lib/module/roomStore/chatSettingsSlice.js +3 -1
  202. package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
  203. package/lib/module/roomStore/roomsSlice.js +2 -20
  204. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  205. package/lib/module/services/pushSubscriptionService.js +15 -13
  206. package/lib/module/services/pushSubscriptionService.js.map +1 -1
  207. package/lib/typescript/assets/icons.d.ts +16 -0
  208. package/lib/typescript/assets/icons.d.ts.map +1 -1
  209. package/lib/typescript/components/Header/HeaderRoomList.d.ts.map +1 -1
  210. package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
  211. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  212. package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
  213. package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
  214. package/lib/typescript/components/MainComponents/ProfileImagePlaceholder.d.ts.map +1 -1
  215. package/lib/typescript/components/MainComponents/RoomList.d.ts +7 -0
  216. package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
  217. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts +3 -0
  218. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
  219. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts +9 -0
  220. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
  221. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts +10 -0
  222. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
  223. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts +9 -0
  224. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts.map +1 -0
  225. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
  226. package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
  227. package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts +4 -2
  228. package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts.map +1 -1
  229. package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts +1 -1
  230. package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts.map +1 -1
  231. package/lib/typescript/components/Modals/NewChatModal/UpdNewChatModal.d.ts.map +1 -1
  232. package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts +75 -0
  233. package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts.map +1 -0
  234. package/lib/typescript/components/Modals/ProfileHeader/ProfileMenu.d.ts +25 -0
  235. package/lib/typescript/components/Modals/ProfileHeader/ProfileMenu.d.ts.map +1 -0
  236. package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts +6 -1
  237. package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts.map +1 -1
  238. package/lib/typescript/components/Modals/UserProfileModal/EditUserModal.d.ts.map +1 -1
  239. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts +16 -0
  240. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
  241. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts +1 -0
  242. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
  243. package/lib/typescript/components/Modals/styledModalComponents.d.ts.map +1 -1
  244. package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
  245. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  246. package/lib/typescript/components/styled/StyledComponents.d.ts.map +1 -1
  247. package/lib/typescript/components/styled/StyledInputComponents/StyledInputComponents.d.ts.map +1 -1
  248. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  249. package/lib/typescript/helpers/getChatBackground.d.ts +15 -0
  250. package/lib/typescript/helpers/getChatBackground.d.ts.map +1 -0
  251. package/lib/typescript/helpers/mediaLibraryRuntime.d.ts +3 -0
  252. package/lib/typescript/helpers/mediaLibraryRuntime.d.ts.map +1 -0
  253. package/lib/typescript/helpers/pickImageAsset.d.ts +27 -0
  254. package/lib/typescript/helpers/pickImageAsset.d.ts.map +1 -0
  255. package/lib/typescript/helpers/pushPayload.d.ts +7 -0
  256. package/lib/typescript/helpers/pushPayload.d.ts.map +1 -0
  257. package/lib/typescript/helpers/sheetGestures.d.ts +20 -0
  258. package/lib/typescript/helpers/sheetGestures.d.ts.map +1 -0
  259. package/lib/typescript/helpers/updateMessagesTillLast.d.ts.map +1 -1
  260. package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -1
  261. package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
  262. package/lib/typescript/hooks/usePendingNotification.d.ts.map +1 -1
  263. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  264. package/lib/typescript/i18n/strings.d.ts.map +1 -1
  265. package/lib/typescript/main.d.ts +3 -1
  266. package/lib/typescript/main.d.ts.map +1 -1
  267. package/lib/typescript/networking/api-requests/user.api.d.ts +27 -0
  268. package/lib/typescript/networking/api-requests/user.api.d.ts.map +1 -1
  269. package/lib/typescript/networking/authRefresh.d.ts +4 -1
  270. package/lib/typescript/networking/authRefresh.d.ts.map +1 -1
  271. package/lib/typescript/networking/outboundQueue.d.ts +0 -16
  272. package/lib/typescript/networking/outboundQueue.d.ts.map +1 -1
  273. package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
  274. package/lib/typescript/networking/xmpp/presenceInRoom.xmpp.d.ts.map +1 -1
  275. package/lib/typescript/networking/xmpp/subscribeToRoomMessages.xmpp.d.ts.map +1 -1
  276. package/lib/typescript/networking/xmppClient.d.ts +8 -33
  277. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  278. package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
  279. package/lib/typescript/roomStore/roomsSlice.d.ts +1 -18
  280. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  281. package/lib/typescript/services/pushSubscriptionService.d.ts +1 -1
  282. package/lib/typescript/services/pushSubscriptionService.d.ts.map +1 -1
  283. package/lib/typescript/types/models/room.model.d.ts +0 -15
  284. package/lib/typescript/types/models/room.model.d.ts.map +1 -1
  285. package/lib/typescript/types/types.d.ts +31 -20
  286. package/lib/typescript/types/types.d.ts.map +1 -1
  287. package/package.json +6 -1
  288. package/src/assets/icons.tsx +48 -9
  289. package/src/components/Header/HeaderRoomList.tsx +24 -6
  290. package/src/components/MainComponents/ChatHeader.tsx +5 -2
  291. package/src/components/MainComponents/ChatRoom.tsx +38 -20
  292. package/src/components/MainComponents/ChatWrapper.tsx +3 -0
  293. package/src/components/MainComponents/MessageList.tsx +8 -24
  294. package/src/components/MainComponents/ProfileImagePlaceholder.tsx +21 -14
  295. package/src/components/MainComponents/RoomList.tsx +236 -39
  296. package/src/components/Menu/HeaderRoomListMenu.tsx +328 -75
  297. package/src/components/Modals/AttachSheet/AttachSheet.tsx +331 -97
  298. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +598 -279
  299. package/src/components/Modals/ChatProfileModal/ReportChatModal.tsx +244 -0
  300. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +4 -2
  301. package/src/components/Modals/Modal/Modal.tsx +7 -0
  302. package/src/components/Modals/NewChatModal/ModalContent.tsx +6 -3
  303. package/src/components/Modals/NewChatModal/NewChatModal.tsx +219 -117
  304. package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +12 -1
  305. package/src/components/Modals/ProfileHeader/ProfileHeader.tsx +615 -0
  306. package/src/components/Modals/ProfileHeader/ProfileMenu.tsx +217 -0
  307. package/src/components/Modals/SelectUsersModal/SelectUsersModal.tsx +14 -4
  308. package/src/components/Modals/UserProfileModal/EditUserModal.tsx +9 -25
  309. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +617 -307
  310. package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +75 -58
  311. package/src/components/Modals/styledModalComponents.tsx +9 -2
  312. package/src/components/RoomComponents/ChatRoomItem.tsx +14 -7
  313. package/src/components/styled/SendInput.tsx +83 -12
  314. package/src/components/styled/StyledComponents.ts +9 -3
  315. package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +11 -4
  316. package/src/context/xmppProvider.tsx +36 -47
  317. package/src/helpers/getChatBackground.ts +18 -0
  318. package/src/helpers/mediaLibraryRuntime.ts +25 -0
  319. package/src/helpers/pickImageAsset.ts +68 -0
  320. package/src/helpers/pushPayload.ts +62 -0
  321. package/src/helpers/sheetGestures.ts +25 -0
  322. package/src/helpers/updateMessagesTillLast.tsx +17 -42
  323. package/src/hooks/useChatRoomFocus.ts +3 -11
  324. package/src/hooks/useLogout.tsx +0 -7
  325. package/src/hooks/usePendingNotification.ts +5 -11
  326. package/src/hooks/useSendMessage.tsx +24 -60
  327. package/src/i18n/strings.ts +121 -1
  328. package/src/main.ts +4 -1
  329. package/src/networking/api-requests/user.api.ts +71 -0
  330. package/src/networking/authRefresh.ts +25 -4
  331. package/src/networking/outboundQueue.ts +0 -29
  332. package/src/networking/stanzaHandlers.ts +1 -9
  333. package/src/networking/xmpp/presenceInRoom.xmpp.ts +6 -1
  334. package/src/networking/xmpp/subscribeToRoomMessages.xmpp.ts +12 -1
  335. package/src/networking/xmppClient.ts +65 -119
  336. package/src/roomStore/chatSettingsSlice.ts +3 -1
  337. package/src/roomStore/roomsSlice.ts +2 -20
  338. package/src/services/pushSubscriptionService.ts +18 -13
  339. package/src/types/models/room.model.ts +0 -15
  340. package/src/types/types.ts +33 -20
@@ -1,18 +1,16 @@
1
- import React, { useCallback, useMemo } from 'react';
1
+ /** @format */
2
2
 
3
- import {
4
- ModalContainerFullScreen,
5
- Viewider,
6
- Label,
7
- LabelData,
8
- BorderedContainer,
9
- CenterContainer,
10
- } from '../styledModalComponents';
11
- import ModalHeaderComponent from '../ModalHeaderComponent';
12
- import Button from '../../styled/Button';
3
+ import React, { useCallback, useMemo } from 'react';
4
+ import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
13
5
  import { useDispatch } from 'react-redux';
6
+ import { ModalContainerFullScreen } from '../styledModalComponents';
7
+ import ModalHeaderComponent from '../ModalHeaderComponent';
8
+ import { ArowDownIcon } from '../../../assets/icons';
14
9
  import { setActiveModal } from '../../../roomStore/chatSettingsSlice';
15
10
  import { MODAL_TYPES } from '../../../helpers/constants/MODAL_TYPES';
11
+ import { useChatSettingState } from '../../../hooks/useChatSettingState';
12
+ import { chatTextStyle } from '../../../helpers/typography';
13
+ import { useT } from '../../../i18n/useT';
16
14
 
17
15
  interface UserSettingsModalProps {
18
16
  handleCloseModal: any;
@@ -21,65 +19,84 @@ interface UserSettingsModalProps {
21
19
  const UserSettingsModal: React.FC<UserSettingsModalProps> = ({
22
20
  handleCloseModal,
23
21
  }) => {
22
+ const t = useT();
23
+ const dispatch = useDispatch();
24
+ const { config } = useChatSettingState();
25
+
24
26
  const options = useMemo(
25
27
  () => [
26
- { value: 'Manage Data', key: MODAL_TYPES.MANAGE_DATA },
27
- { value: 'Visiblility', key: MODAL_TYPES.VISIBILITY },
28
- // { value: 'Profile Shares', key: MODAL_TYPES.PROFILE_SHARES },
29
- // { value: 'Document Shares', key: MODAL_TYPES.DOCUMENT_SHARES },
30
- // { value: 'Blocked Users', key: MODAL_TYPES.BLOCKED_USERS },
31
- // { value: 'Referrals', key: MODAL_TYPES.REFERRALS },
28
+ { label: t('settings.manageData.title'), key: MODAL_TYPES.MANAGE_DATA },
29
+ { label: t('settings.visibility.title'), key: MODAL_TYPES.VISIBILITY },
32
30
  ],
33
- []
31
+ [t]
34
32
  );
35
33
 
36
- const dispatch = useDispatch();
37
-
38
- const handleClick = useCallback((key: string) => {
39
- dispatch(setActiveModal(key as any));
40
- }, []);
34
+ const handleClick = useCallback(
35
+ (key: string) => {
36
+ dispatch(setActiveModal(key as any));
37
+ },
38
+ [dispatch]
39
+ );
41
40
 
42
41
  return (
43
- <ModalContainerFullScreen>
42
+ <ModalContainerFullScreen style={styles.screen}>
44
43
  <ModalHeaderComponent
45
44
  handleCloseModal={handleCloseModal}
46
- headerTitle={'Settings'}
45
+ headerTitle={t('settings.menu.title')}
46
+ titleStyle={chatTextStyle(config?.typography?.profile?.screenTitle)}
47
47
  />
48
- <CenterContainer>
49
- <BorderedContainer
50
- style={{
51
- padding: 16,
52
- display: 'flex',
53
- flexDirection: 'column',
54
- gap: 8,
55
- }}
56
- >
57
- {options.map((option: { value: string; key: string }, index) => (
58
- <>
59
- <Button
60
- variant="default"
61
- style={{
62
- minHeight: 40,
63
- display: 'flex',
64
- flexDirection: 'column',
65
- gap: 2,
66
- width: '100%',
67
- justifyContent: 'center',
68
- borderRadius: 0,
69
- alignItems: 'flex-start',
70
- }}
71
- onPress={() => handleClick(option.key)}
72
- >
73
- <Label style={{ textAlign: 'center' }}>{option.value}</Label>
74
- {[2, 3, 4].includes(index) && <LabelData>0</LabelData>}
75
- </Button>
76
- {index < 5 && <Viewider />}
77
- </>
78
- ))}
79
- </BorderedContainer>
80
- </CenterContainer>
48
+ {/* One card per entry, rather than a single bordered block with
49
+ * hairline dividers — the rows are separate destinations, and the
50
+ * design gives each its own surface. */}
51
+ <View style={styles.body}>
52
+ {options.map((option) => (
53
+ <TouchableOpacity
54
+ key={option.key}
55
+ testID={`settings-row-${option.key}`}
56
+ activeOpacity={0.7}
57
+ style={styles.card}
58
+ onPress={() => handleClick(option.key)}
59
+ >
60
+ <Text style={styles.label}>{option.label}</Text>
61
+ <ArowDownIcon color="#8C8C8C" width={20} height={20} style={styles.chevron} />
62
+ </TouchableOpacity>
63
+ ))}
64
+ </View>
81
65
  </ModalContainerFullScreen>
82
66
  );
83
67
  };
84
68
 
69
+ const styles = StyleSheet.create({
70
+ screen: {
71
+ backgroundColor: '#E8EDF2',
72
+ },
73
+ body: {
74
+ width: '100%',
75
+ padding: 12,
76
+ gap: 12,
77
+ },
78
+ card: {
79
+ flexDirection: 'row',
80
+ alignItems: 'center',
81
+ justifyContent: 'space-between',
82
+ backgroundColor: '#FFFFFF',
83
+ borderRadius: 20,
84
+ paddingHorizontal: 20,
85
+ paddingVertical: 22,
86
+ shadowColor: '#101828',
87
+ shadowOffset: { width: 0, height: 4 },
88
+ shadowOpacity: 0.06,
89
+ shadowRadius: 12,
90
+ elevation: 3,
91
+ },
92
+ label: {
93
+ fontSize: 17,
94
+ fontWeight: '500',
95
+ color: '#141414',
96
+ },
97
+ chevron: {
98
+ transform: [{ rotate: '-90deg' }],
99
+ },
100
+ });
101
+
85
102
  export default UserSettingsModal;
@@ -86,8 +86,15 @@ export const HeaderContainer = styled.View`
86
86
  * button and 8px below — properly sized and properly centered. */
87
87
  padding: 8px 16px;
88
88
  background-color: #fff;
89
- border-bottom-width: 1px;
90
- border-bottom-color: #f0f0f0;
89
+ /* Same card treatment as the room-list header: rounded bottom corners
90
+ * and a soft drop shadow instead of a hairline rule. */
91
+ border-bottom-left-radius: 20px;
92
+ border-bottom-right-radius: 20px;
93
+ shadow-color: #101828;
94
+ shadow-offset: 0px 4px;
95
+ shadow-opacity: 0.06;
96
+ shadow-radius: 12px;
97
+ elevation: 4;
91
98
  z-index: 1;
92
99
  flex-direction: row;
93
100
  justify-content: space-between;
@@ -90,11 +90,13 @@ const ChatRoomItem: React.FC<ChatRoomItemProps> = ({
90
90
 
91
91
  return (
92
92
  <ChatItem key={index}>
93
- <ProfileImagePlaceholder
94
- name={displayName}
95
- icon={appendFileToken(chat?.icon, fileToken)}
96
- active={false}
97
- />
93
+ <View pointerEvents="none">
94
+ <ProfileImagePlaceholder
95
+ name={displayName}
96
+ icon={appendFileToken(chat?.icon, fileToken)}
97
+ active={false}
98
+ />
99
+ </View>
98
100
  <View
99
101
  style={{
100
102
  flexDirection: 'column',
@@ -104,7 +106,9 @@ const ChatRoomItem: React.FC<ChatRoomItemProps> = ({
104
106
  paddingVertical: 8,
105
107
  paddingRight: 8,
106
108
  borderBottomWidth: 1,
107
- borderBottomColor: '#F0F0F0',
109
+ // Reads against the list's #E8EDF2 ground; #F0F0F0 was lighter
110
+ // than the ground itself, so the row separators vanished.
111
+ borderBottomColor: '#C6CFDA',
108
112
  }}
109
113
  >
110
114
  <View
@@ -215,8 +219,11 @@ const ChatRoomItem: React.FC<ChatRoomItemProps> = ({
215
219
  ) : null}
216
220
  </View>
217
221
  {isDriver && (
222
+ // Darker than the list's own ground (#E8EDF2), otherwise the
223
+ // separator disappears into it — white and the old #0052CD0D
224
+ // hairline both did.
218
225
  <View
219
- style={{ height: 1, backgroundColor: '#0052CD0D', marginTop: 8 }}
226
+ style={{ height: 1, backgroundColor: '#C6CFDA', marginTop: 8 }}
220
227
  />
221
228
  )}
222
229
  </View>
@@ -10,14 +10,16 @@ import { IConfig, MediaFile } from '../../types/types';
10
10
  import Button from './Button';
11
11
  import { SendIcon, AttachIcon, RecordIcon } from '../../assets/icons';
12
12
  import { KeyboardAvoidingView, Platform, View, Text, TouchableOpacity, Alert, Linking } from 'react-native';
13
- import AttachSheet from '../Modals/AttachSheet/AttachSheet';
13
+ import AttachSheet, { PickedMedia } from '../Modals/AttachSheet/AttachSheet';
14
14
  import { MediaFilePreview } from './MediaFilePreview';
15
15
  import { getIconColor } from '../../helpers/getIconColor';
16
16
  import { getElementFont } from '../../helpers/getElementFont';
17
17
  import { useT } from '../../i18n/useT';
18
+ import { getMediaLibrary } from '../../helpers/mediaLibraryRuntime';
18
19
  import * as ImagePicker from 'expo-image-picker';
19
20
  import * as DocumentPicker from 'expo-document-picker';
20
21
  import * as ImageManipulator from 'expo-image-manipulator';
22
+ import * as FileSystem from 'expo-file-system/legacy';
21
23
  // expo-audio replaces the discontinued expo-av: `useAudioRecorder` owns a
22
24
  // single reusable recorder for this input's lifetime (prepare → record →
23
25
  // stop → prepare again), and the module-level helpers cover permissions
@@ -259,22 +261,59 @@ const SendInput: React.FC<SendInputProps> = ({
259
261
  }
260
262
  };
261
263
 
264
+ // A tap on a thumbnail in the attach sheet's recents strip. The sheet
265
+ // already resolved the asset to a real on-disk uri (iOS `ph://` ids are
266
+ // not uploadable); here we apply the same treatment the full-blown
267
+ // pickers get — HEIC→JPEG for images, and a size probe so the 50 MB cap
268
+ // is enforced before anything hits the network.
269
+ const handleRecentMediaSelection = async (media: PickedMedia) => {
270
+ try {
271
+ let size: number | undefined;
272
+ try {
273
+ const info = await FileSystem.getInfoAsync(media.uri);
274
+ if (info.exists && typeof (info as any).size === 'number') {
275
+ size = (info as any).size;
276
+ }
277
+ } catch {
278
+ // Size is a nice-to-have; the backend still rejects oversized bodies.
279
+ }
280
+
281
+ if (media.isVideo) {
282
+ handleFileSelect([
283
+ {
284
+ uri: media.uri,
285
+ type: media.mimeType || 'video/mp4',
286
+ name: media.name,
287
+ size,
288
+ },
289
+ ]);
290
+ return;
291
+ }
292
+
293
+ const normalized = await normalizeImageAsset({
294
+ uri: media.uri,
295
+ mimeType: media.mimeType,
296
+ fileName: media.name,
297
+ } as ImagePicker.ImagePickerAsset);
298
+ handleFileSelect([
299
+ {
300
+ uri: normalized.uri,
301
+ type: normalized.mime,
302
+ name: normalized.name,
303
+ size,
304
+ },
305
+ ]);
306
+ } catch (error) {
307
+ console.error('Recent media error:', error);
308
+ }
309
+ };
310
+
262
311
  const handleFileSelection = async () => {
263
312
  // Drop overlapping invocations — a second getDocumentAsync while the
264
313
  // first is still presented throws PickingInProgressException on iOS.
265
314
  if (pickingDocRef.current) {return;}
266
315
  pickingDocRef.current = true;
267
316
  try {
268
- // Let the attach-sheet's modal finish its NATIVE dismissal before we
269
- // present the picker. The sheet fires this handler right after its
270
- // slide-out animation, but the underlying RN Modal view-controller
271
- // dismissal is async — presenting the document picker over a still-
272
- // dismissing modal makes iOS tear it down without a cancel callback,
273
- // which strands expo-document-picker's pickingContext and makes every
274
- // subsequent open throw "Different document picking in progress".
275
- if (Platform.OS === 'ios') {
276
- await new Promise((resolve) => setTimeout(resolve, 350));
277
- }
278
317
  const result = await DocumentPicker.getDocumentAsync({
279
318
  type: '*/*',
280
319
  multiple: false,
@@ -297,8 +336,39 @@ const SendInput: React.FC<SendInputProps> = ({
297
336
  }
298
337
  };
299
338
 
339
+ // Photo-library access is requested HERE, not inside the sheet: iOS
340
+ // cannot present the permission alert while an RN <Modal> owns the
341
+ // screen (the same UIKit limitation that used to swallow the pickers),
342
+ // so asking from inside resolved to a silent "denied" and the recents
343
+ // strip stayed empty forever. Asking on the paperclip tap puts the
344
+ // system alert over the plain chat screen, where it can actually show.
345
+ // Only the first tap ever waits on it — afterwards the status is
346
+ // already determined and `getPermissionsAsync` returns immediately.
347
+ const ensureLibraryPermission = async () => {
348
+ const MediaLibrary = getMediaLibrary();
349
+ if (!MediaLibrary?.getPermissionsAsync) {return;}
350
+ try {
351
+ const perm = await MediaLibrary.getPermissionsAsync();
352
+ if (perm?.granted || perm?.canAskAgain === false) {return;}
353
+ await MediaLibrary.requestPermissionsAsync();
354
+ } catch (err) {
355
+ // Optional peer / unsupported platform: the sheet just shows the
356
+ // camera tile and the full-library route.
357
+ console.warn('Media library permission check failed:', err);
358
+ }
359
+ };
360
+
361
+ // Only the very first tap of a session goes through the permission
362
+ // check; afterwards the sheet opens with zero added latency.
363
+ const libraryPermissionCheckedRef = useRef(false);
364
+
300
365
  const handleAttachPress = () => {
301
- setShowMediaMenu(true);
366
+ if (libraryPermissionCheckedRef.current) {
367
+ setShowMediaMenu(true);
368
+ return;
369
+ }
370
+ libraryPermissionCheckedRef.current = true;
371
+ ensureLibraryPermission().finally(() => setShowMediaMenu(true));
302
372
  };
303
373
 
304
374
  // ─── Voice recording ──────────────────────────────────────────────
@@ -702,6 +772,7 @@ const SendInput: React.FC<SendInputProps> = ({
702
772
  onCamera={handleCameraSelection}
703
773
  onGallery={handleGallerySelection}
704
774
  onDocument={handleFileSelection}
775
+ onPickMedia={handleRecentMediaSelection}
705
776
  primaryColor={getIconColor(config)}
706
777
  />
707
778
  </InputContainer>
@@ -28,9 +28,15 @@ export const ChatContainerHeader = styled.View`
28
28
  background-color: #ffffff;
29
29
  align-items: center;
30
30
  justify-content: space-between;
31
- border-bottom-width: 1px;
32
- border-bottom-color: #e5e7eb;
33
- border-style: solid;
31
+ /* Rounded bottom corners + a soft drop shadow instead of the hairline
32
+ * rule, so the header reads as a card over the conversation. */
33
+ border-bottom-left-radius: 20px;
34
+ border-bottom-right-radius: 20px;
35
+ shadow-color: #101828;
36
+ shadow-offset: 0px 4px;
37
+ shadow-opacity: 0.06;
38
+ shadow-radius: 12px;
39
+ elevation: 4;
34
40
  z-index: 1000;
35
41
  `;
36
42
 
@@ -13,14 +13,21 @@ const colors = {
13
13
 
14
14
  export const InputContainer = styled.View<{ isText?: boolean }>`
15
15
  flex-direction: column;
16
- padding: 8px 16px 4px 16px;
17
- background-color: ${colors.white};
16
+ padding: 12px 16px 8px 16px;
17
+ /* Transparent, so the dock's white surface — and its rounded top
18
+ * corners — are what shows. An opaque child painted straight over those
19
+ * corners (a parent's border radius does not clip children without
20
+ * overflow:hidden, and that would clip the dock's shadow too). */
21
+ background-color: transparent;
18
22
  z-index: 100;
19
23
  width: 100%;
20
24
  bottom: 0;
21
25
  left: 0;
22
- border-top-width: 1px;
23
- border-top-color: #e5e7eb;
26
+ /* No radius or shadow here: the dock this sits in (ChatRoom's
27
+ * InputDockTag) is the composer's outer surface and carries both. Having
28
+ * them on this inner view too drew its shadow onto the dock's white
29
+ * background — the faint seam that made the strip below look like a
30
+ * different colour. */
24
31
  `;
25
32
 
26
33
  export const MediaContainer = styled.View`
@@ -37,6 +37,7 @@ import {
37
37
  import { ensureScopedChatCache } from '../helpers/ensureScopedChatCache';
38
38
  import { getRooms as prefetchRoomsViaRest } from '../networking/api-requests/rooms.api';
39
39
  import { allRoomPresences } from '../networking/xmpp/allRoomPresences.xmpp';
40
+ import { pushSubscriptionService } from '../services/pushSubscriptionService';
40
41
  import { store } from '../roomStore';
41
42
  import { logout, setStoreClient, setConfig } from '../roomStore/chatSettingsSlice';
42
43
  import {
@@ -83,6 +84,16 @@ interface XmppProviderProps {
83
84
 
84
85
  const LOGOUT_EVENT = 'ethora-xmpp-logout';
85
86
 
87
+ const subscribeAllRoomsForPush = (client: any, reason: string) => {
88
+ const rooms = Object.keys(store.getState().rooms.rooms || {});
89
+ if (!client || !rooms.length) {return;}
90
+ const nick = client.jid?.getLocal();
91
+ pushSubscriptionService
92
+ .subscribeToRooms(client, rooms, nick)
93
+ .then(() => devPushLog('xmpp', `${reason}: mucsub ok for ${rooms.length} rooms`))
94
+ .catch((e) => devPushLog('warn', `${reason}: mucsub subscribe failed`, e));
95
+ };
96
+
86
97
  export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, isVisible }) => {
87
98
  const [client, setClient] = useState<XmppClient | null>(null);
88
99
  const [providerBootstrapStatus, setProviderBootstrapStatus] =
@@ -115,7 +126,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
115
126
  // the shared rotation point covers both the consumer-supplied
116
127
  // function and the built-in endpoint.
117
128
  if (config?.refreshTokens?.enabled) {
118
- const rotated = await refreshAuthTokensQuietly();
129
+ const rotated = await refreshAuthTokensQuietly({ force: true });
119
130
 
120
131
  if (rotated?.xmppPassword) {
121
132
  const rotatedUser = store.getState().chatSettingStore.user;
@@ -229,9 +240,11 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
229
240
  created.setOnOnline(() => {
230
241
  const underlying = (created as any).client;
231
242
  if (!underlying) {return;}
232
- allRoomPresences(underlying).catch((e) =>
233
- devPushLog('warn', 'reconnect: allRoomPresences re-join failed', e)
234
- );
243
+ allRoomPresences(underlying)
244
+ .catch((e) =>
245
+ devPushLog('warn', 'reconnect: allRoomPresences re-join failed', e)
246
+ )
247
+ .finally(() => subscribeAllRoomsForPush(underlying, 'reconnect'));
235
248
  // Also refresh the private store so unread / lastViewed markers
236
249
  // are accurate after a long reconnect — the MUC re-join above only
237
250
  // restores delivery, not unread state. Idempotent on first connect.
@@ -384,7 +397,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
384
397
  // jwtLogin is skipped: /users/client just minted fresh creds.
385
398
  let connectPassword = resolved.xmppPassword;
386
399
  if (config?.refreshTokens?.enabled && !config?.jwtLogin?.enabled) {
387
- const rotated = await refreshAuthTokensQuietly();
400
+ const rotated = await refreshAuthTokensQuietly({ force: true });
388
401
  if (cancelled) {return;}
389
402
  if (rotated?.xmppPassword) {
390
403
  connectPassword = rotated.xmppPassword;
@@ -436,6 +449,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
436
449
  } catch (e) {
437
450
  devPushLog('warn', 'initBeforeLoad: allRoomPresences failed', e);
438
451
  }
452
+ subscribeAllRoomsForPush((c as any).client, 'initBeforeLoad');
439
453
 
440
454
  store.dispatch(setStoreClient(c));
441
455
  completedBootstrapKeyRef.current = key;
@@ -557,9 +571,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
557
571
  devPushLog('rn', `watchdog: client ${client.status} → forceReconnect`);
558
572
  client.forceReconnect();
559
573
  } else {
560
- // The periodic health check is the probe's primary owner, so it
561
- // bypasses the throttle that keeps send-path probes rare.
562
- client.ensureStreamAlive?.({ force: true, reason: 'watchdog' });
574
+ client.ensureStreamAlive?.();
563
575
  }
564
576
  }, 30000);
565
577
  return () => clearInterval(id);
@@ -582,9 +594,14 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
582
594
  // be re-marked visible on return. Lives in the effect closure (one per
583
595
  // client) — persists across the listener's many invocations.
584
596
  let visibleBeforeBackground: string | null = null;
597
+ const suspendInBackground = !config?.xmppSettings?.keepAliveInBackground;
585
598
  const sub = AppState.addEventListener('change', (next) => {
586
599
  const c = client;
587
600
  if (next === 'active') {
601
+ if (c?.isSuspended) {
602
+ devPushLog('rn', 'AppState active: resuming suspended XMPP client');
603
+ c.resume();
604
+ }
588
605
  // Returned to foreground. If the socket died while backgrounded
589
606
  // (iOS suspends the WebSocket; long background kills it), the
590
607
  // status may still read 'online' until xmpp.js notices the dead
@@ -612,6 +629,9 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
612
629
  }
613
630
  // Going to background/inactive (sleep / app switcher / tray):
614
631
  if (!c) {return;}
632
+ if (next === 'background' && suspendInBackground) {
633
+ c.suspend().catch(() => undefined);
634
+ }
615
635
  const state = store.getState();
616
636
  const rooms = state.rooms?.rooms;
617
637
  const visibleRoomJID = state.rooms?.visibleRoomJID || null;
@@ -624,19 +644,9 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
624
644
  // the provider so consumers using the component as a package get
625
645
  // correct unread without reaching into the chat store themselves.
626
646
  visibleBeforeBackground = visibleRoomJID;
627
- // Prefer the read boundary the user actually reached. Stamping
628
- // `Date.now()` while they are scrolled up marks unseen messages as
629
- // read, and because we flush to the server private store below the
630
- // loss survives an app restart. Customer-reported #33.
631
- const bgBoundaryTs = visibleRoomJID
632
- ? rooms?.[visibleRoomJID]?.readBoundaryTs ?? null
633
- : null;
634
647
  if (visibleRoomJID) {
635
648
  store.dispatch(
636
- setLastViewedTimestamp({
637
- chatJID: visibleRoomJID,
638
- timestamp: bgBoundaryTs ?? Date.now(),
639
- })
649
+ setLastViewedTimestamp({ chatJID: visibleRoomJID, timestamp: Date.now() })
640
650
  );
641
651
  // Drop the "New messages" divider for the room we're leaving so it
642
652
  // doesn't linger when the user comes back (mirrors ChatRoom's
@@ -648,13 +658,12 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
648
658
  }
649
659
  // Fire-and-forget — we're going to the background and don't
650
660
  // care about the resolution path.
651
- c.flushLastViewedToPrivateStoreStanza(rooms, {
652
- visibleRoomJID,
653
- visibleRoomTs: bgBoundaryTs,
654
- }).catch(() => {});
661
+ c.flushLastViewedToPrivateStoreStanza(rooms, { visibleRoomJID }).catch(
662
+ () => {}
663
+ );
655
664
  });
656
665
  return () => sub.remove();
657
- }, [client]);
666
+ }, [client, config?.xmppSettings?.keepAliveInBackground]);
658
667
 
659
668
  // -----------------------------------------------------------
660
669
  // Consumer visibility signal (`isVisible` prop). For hosts that keep
@@ -682,16 +691,9 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
682
691
  store.dispatch(setVisibleRoom({ roomJID: activeRoomJID }));
683
692
  }
684
693
  } else {
685
- // Same read-boundary rule as the AppState path above (#33).
686
- const hideBoundaryTs = activeRoomJID
687
- ? rooms?.[activeRoomJID]?.readBoundaryTs ?? null
688
- : null;
689
694
  if (wasVisible && activeRoomJID) {
690
695
  store.dispatch(
691
- setLastViewedTimestamp({
692
- chatJID: activeRoomJID,
693
- timestamp: hideBoundaryTs ?? Date.now(),
694
- })
696
+ setLastViewedTimestamp({ chatJID: activeRoomJID, timestamp: Date.now() })
695
697
  );
696
698
  // Drop the "New messages" divider so it's gone when the user
697
699
  // returns to the chat (mirrors ChatRoom's unmount cleanup).
@@ -703,10 +705,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
703
705
  store.dispatch(clearVisibleRoom());
704
706
  if (wasVisible && client?.flushLastViewedToPrivateStoreStanza) {
705
707
  client
706
- .flushLastViewedToPrivateStoreStanza(rooms, {
707
- visibleRoomJID: activeRoomJID,
708
- visibleRoomTs: hideBoundaryTs,
709
- })
708
+ .flushLastViewedToPrivateStoreStanza(rooms, { visibleRoomJID: activeRoomJID })
710
709
  .catch(() => {});
711
710
  }
712
711
  }
@@ -727,15 +726,6 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
727
726
  if (room.messages === lastMessagesRef) {return;}
728
727
  lastMessagesRef = room.messages;
729
728
 
730
- // "Chat is on screen" does NOT mean "user is looking at the newest
731
- // message". While they are scrolled up, MessageList publishes a read
732
- // boundary; advancing the marker to `now` here would clear the very
733
- // unread messages the scroll-up state exists to preserve — and the
734
- // 2s flush below would push that loss to the server, making it
735
- // survive an app restart. Leave the marker alone until they come
736
- // back to the bottom (boundary back to null). Customer-reported #33.
737
- if (room.readBoundaryTs != null) {return;}
738
-
739
729
  let newest = 0;
740
730
  const list = room.messages || [];
741
731
  for (const m of list) {
@@ -794,8 +784,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
794
784
  devPushLog('rn', `NetInfo: reachable & client ${client.status} → forceReconnect`);
795
785
  client.forceReconnect();
796
786
  } else if (client.status === 'online') {
797
- // Connectivity just came back — worth an immediate check.
798
- client.ensureStreamAlive?.({ force: true, reason: 'netinfo' });
787
+ client.ensureStreamAlive?.();
799
788
  }
800
789
  });
801
790
  return () => unsub();
@@ -0,0 +1,18 @@
1
+ /** @format */
2
+
3
+ import type { IConfig } from '../types/types';
4
+
5
+ /** Ground behind the conversation, and behind the rounded corners of the
6
+ * header and the composer that sit over it. */
7
+ export const DEFAULT_CHAT_BACKGROUND = '#F3F6FC';
8
+
9
+ /**
10
+ * One place for the conversation's background colour.
11
+ *
12
+ * The message list has always painted it; the chat container behind it was
13
+ * plain white, which is what made the header's rounded bottom corners and
14
+ * the composer's rounded top corners invisible — the corners revealed the
15
+ * white parent, not the conversation.
16
+ */
17
+ export const getChatBackgroundColor = (config?: IConfig): string =>
18
+ config?.backgroundChat?.color || DEFAULT_CHAT_BACKGROUND;
@@ -0,0 +1,25 @@
1
+ let cached: any | undefined;
2
+
3
+ export const getMediaLibrary = (): any | null => {
4
+ if (cached !== undefined) {return cached;}
5
+ try {
6
+ const legacy = require('expo-media-library/legacy');
7
+
8
+ if (legacy?.getAssetsAsync) {
9
+ cached = legacy;
10
+ return cached;
11
+ }
12
+ } catch {
13
+ }
14
+
15
+ try {
16
+ cached = require('expo-media-library') ?? null;
17
+ } catch {
18
+ cached = null;
19
+ }
20
+ return cached;
21
+ };
22
+
23
+ export const __resetMediaLibraryCache = () => {
24
+ cached = undefined;
25
+ };