@ethora/chat-component-rn 26.9.0 → 26.10.0

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 (761) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +19 -0
  3. package/lib/commonjs/assets/icons.js +2 -2
  4. package/lib/commonjs/assets/icons.js.map +1 -1
  5. package/lib/commonjs/components/Header/HeaderRoomList.js +22 -6
  6. package/lib/commonjs/components/Header/HeaderRoomList.js.map +1 -1
  7. package/lib/commonjs/components/InputComponents/Search.js +38 -1
  8. package/lib/commonjs/components/InputComponents/Search.js.map +1 -1
  9. package/lib/commonjs/components/MainComponents/ArchivedMessageCard.js +166 -0
  10. package/lib/commonjs/components/MainComponents/ArchivedMessageCard.js.map +1 -0
  11. package/lib/commonjs/components/MainComponents/ChatHeader.js +22 -5
  12. package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
  13. package/lib/commonjs/components/MainComponents/ChatRoom.js +56 -25
  14. package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
  15. package/lib/commonjs/components/MainComponents/ChatWrapper.js +53 -4
  16. package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
  17. package/lib/commonjs/components/MainComponents/MediaMessage.js +18 -3
  18. package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
  19. package/lib/commonjs/components/MainComponents/MessageList.js +739 -42
  20. package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
  21. package/lib/commonjs/components/MainComponents/MessageSearchButton.js +58 -0
  22. package/lib/commonjs/components/MainComponents/MessageSearchButton.js.map +1 -0
  23. package/lib/commonjs/components/MainComponents/ReduxWrapper.js +15 -6
  24. package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
  25. package/lib/commonjs/components/MainComponents/RoomList.js +110 -1
  26. package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
  27. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +14 -3
  28. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
  29. package/lib/commonjs/components/MessageBubble/BubbleHighlight.js +112 -0
  30. package/lib/commonjs/components/MessageBubble/BubbleHighlight.js.map +1 -0
  31. package/lib/commonjs/components/MessageBubble/Message.js +169 -125
  32. package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
  33. package/lib/commonjs/components/MessageBubble/MessageInteractions.js +98 -78
  34. package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
  35. package/lib/commonjs/components/MessageBubble/messageMenuLayout.js +50 -0
  36. package/lib/commonjs/components/MessageBubble/messageMenuLayout.js.map +1 -0
  37. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +73 -37
  38. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  39. package/lib/commonjs/components/Modals/MessageSearchModal/MessageHitResults.js +253 -0
  40. package/lib/commonjs/components/Modals/MessageSearchModal/MessageHitResults.js.map +1 -0
  41. package/lib/commonjs/components/Modals/MessageSearchModal/MessageSearchModal.js +488 -0
  42. package/lib/commonjs/components/Modals/MessageSearchModal/MessageSearchModal.js.map +1 -0
  43. package/lib/commonjs/components/Modals/MessageSearchModal/openHit.js +51 -0
  44. package/lib/commonjs/components/Modals/MessageSearchModal/openHit.js.map +1 -0
  45. package/lib/commonjs/components/Modals/MessageSearchModal/resolveSender.js +47 -0
  46. package/lib/commonjs/components/Modals/MessageSearchModal/resolveSender.js.map +1 -0
  47. package/lib/commonjs/components/Modals/MessageSearchModal/searchFilters.js +83 -0
  48. package/lib/commonjs/components/Modals/MessageSearchModal/searchFilters.js.map +1 -0
  49. package/lib/commonjs/components/Modals/MessageSearchModal/snippet.js +61 -0
  50. package/lib/commonjs/components/Modals/MessageSearchModal/snippet.js.map +1 -0
  51. package/lib/commonjs/components/Modals/MessageSearchModal/useMessageSearch.js +136 -0
  52. package/lib/commonjs/components/Modals/MessageSearchModal/useMessageSearch.js.map +1 -0
  53. package/lib/commonjs/components/Modals/PublicChatsModal/PublicChatsModal.js +306 -0
  54. package/lib/commonjs/components/Modals/PublicChatsModal/PublicChatsModal.js.map +1 -0
  55. package/lib/commonjs/components/Modals/PublicChatsModal/publicChatsLogic.js +36 -0
  56. package/lib/commonjs/components/Modals/PublicChatsModal/publicChatsLogic.js.map +1 -0
  57. package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js +8 -1
  58. package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
  59. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +13 -2
  60. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
  61. package/lib/commonjs/components/RoomComponents/SwipeableRoomRow.js +38 -6
  62. package/lib/commonjs/components/RoomComponents/SwipeableRoomRow.js.map +1 -1
  63. package/lib/commonjs/components/Thread/ThreadHeader.js +3 -1
  64. package/lib/commonjs/components/Thread/ThreadHeader.js.map +1 -1
  65. package/lib/commonjs/components/Thread/ThreadWrapper.js +90 -10
  66. package/lib/commonjs/components/Thread/ThreadWrapper.js.map +1 -1
  67. package/lib/commonjs/components/styled/AudioDecoderHost.js +338 -0
  68. package/lib/commonjs/components/styled/AudioDecoderHost.js.map +1 -0
  69. package/lib/commonjs/components/styled/AudioMessage.js +493 -420
  70. package/lib/commonjs/components/styled/AudioMessage.js.map +1 -1
  71. package/lib/commonjs/components/styled/SendInput.js +31 -5
  72. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  73. package/lib/commonjs/context/MessageNotificationContext.js +14 -4
  74. package/lib/commonjs/context/MessageNotificationContext.js.map +1 -1
  75. package/lib/commonjs/context/xmppProvider.js +54 -79
  76. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  77. package/lib/commonjs/helpers/audioWaveform.js +165 -0
  78. package/lib/commonjs/helpers/audioWaveform.js.map +1 -0
  79. package/lib/commonjs/helpers/backgroundJoinSweep.js +36 -0
  80. package/lib/commonjs/helpers/backgroundJoinSweep.js.map +1 -0
  81. package/lib/commonjs/helpers/bubbleHighlight.js +44 -0
  82. package/lib/commonjs/helpers/bubbleHighlight.js.map +1 -0
  83. package/lib/commonjs/helpers/checkUniqueUsers.js +14 -12
  84. package/lib/commonjs/helpers/checkUniqueUsers.js.map +1 -1
  85. package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js +5 -1
  86. package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
  87. package/lib/commonjs/helpers/constants/MODAL_TYPES.js +3 -1
  88. package/lib/commonjs/helpers/constants/MODAL_TYPES.js.map +1 -1
  89. package/lib/commonjs/helpers/createRoomFromApi.js +40 -3
  90. package/lib/commonjs/helpers/createRoomFromApi.js.map +1 -1
  91. package/lib/commonjs/helpers/dedupeMembers.js +34 -0
  92. package/lib/commonjs/helpers/dedupeMembers.js.map +1 -0
  93. package/lib/commonjs/helpers/ethoraLogger.js +56 -0
  94. package/lib/commonjs/helpers/ethoraLogger.js.map +1 -0
  95. package/lib/commonjs/helpers/getUnnamedUsers.js +9 -4
  96. package/lib/commonjs/helpers/getUnnamedUsers.js.map +1 -1
  97. package/lib/commonjs/helpers/historyPreloadConfig.js +44 -0
  98. package/lib/commonjs/helpers/historyPreloadConfig.js.map +1 -0
  99. package/lib/commonjs/helpers/historyPreloadScheduler.js +372 -137
  100. package/lib/commonjs/helpers/historyPreloadScheduler.js.map +1 -1
  101. package/lib/commonjs/helpers/initRoomsPresence.js +17 -5
  102. package/lib/commonjs/helpers/initRoomsPresence.js.map +1 -1
  103. package/lib/commonjs/helpers/insertMessageWithDelimiter.js +5 -0
  104. package/lib/commonjs/helpers/insertMessageWithDelimiter.js.map +1 -1
  105. package/lib/commonjs/helpers/isLikelyMucJid.js +67 -0
  106. package/lib/commonjs/helpers/isLikelyMucJid.js.map +1 -0
  107. package/lib/commonjs/helpers/isMessageSearchEnabled.js +18 -0
  108. package/lib/commonjs/helpers/isMessageSearchEnabled.js.map +1 -0
  109. package/lib/commonjs/helpers/joiningRoom.js +14 -0
  110. package/lib/commonjs/helpers/joiningRoom.js.map +1 -0
  111. package/lib/commonjs/helpers/jumpThread.js +100 -0
  112. package/lib/commonjs/helpers/jumpThread.js.map +1 -0
  113. package/lib/commonjs/helpers/jumpToMessage.js +58 -0
  114. package/lib/commonjs/helpers/jumpToMessage.js.map +1 -0
  115. package/lib/commonjs/helpers/jumpWindow.js +187 -0
  116. package/lib/commonjs/helpers/jumpWindow.js.map +1 -0
  117. package/lib/commonjs/helpers/loadRoomHistory.js +75 -0
  118. package/lib/commonjs/helpers/loadRoomHistory.js.map +1 -0
  119. package/lib/commonjs/helpers/notificationPolicy.js +77 -0
  120. package/lib/commonjs/helpers/notificationPolicy.js.map +1 -0
  121. package/lib/commonjs/helpers/openRoomAtMessage.js +47 -0
  122. package/lib/commonjs/helpers/openRoomAtMessage.js.map +1 -0
  123. package/lib/commonjs/helpers/openThreadForJump.js +72 -0
  124. package/lib/commonjs/helpers/openThreadForJump.js.map +1 -0
  125. package/lib/commonjs/helpers/parseMessageReference.js +27 -8
  126. package/lib/commonjs/helpers/parseMessageReference.js.map +1 -1
  127. package/lib/commonjs/helpers/publicChatsEntry.js +17 -0
  128. package/lib/commonjs/helpers/publicChatsEntry.js.map +1 -0
  129. package/lib/commonjs/helpers/roomActivityScore.js +37 -0
  130. package/lib/commonjs/helpers/roomActivityScore.js.map +1 -0
  131. package/lib/commonjs/helpers/roomUserCount.js +36 -0
  132. package/lib/commonjs/helpers/roomUserCount.js.map +1 -0
  133. package/lib/commonjs/helpers/runConfiguredHistoryPreload.js +68 -0
  134. package/lib/commonjs/helpers/runConfiguredHistoryPreload.js.map +1 -0
  135. package/lib/commonjs/helpers/sessionAppId.js +24 -0
  136. package/lib/commonjs/helpers/sessionAppId.js.map +1 -0
  137. package/lib/commonjs/helpers/timestamp.js +43 -0
  138. package/lib/commonjs/helpers/timestamp.js.map +1 -0
  139. package/lib/commonjs/helpers/userResolver.js +517 -0
  140. package/lib/commonjs/helpers/userResolver.js.map +1 -0
  141. package/lib/commonjs/helpers/xmppIdShape.js +52 -0
  142. package/lib/commonjs/helpers/xmppIdShape.js.map +1 -0
  143. package/lib/commonjs/hooks/useChatWrapperInit.js +27 -5
  144. package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
  145. package/lib/commonjs/hooks/useHeapSender.js +54 -3
  146. package/lib/commonjs/hooks/useHeapSender.js.map +1 -1
  147. package/lib/commonjs/hooks/useJumpToMessage.js +411 -0
  148. package/lib/commonjs/hooks/useJumpToMessage.js.map +1 -0
  149. package/lib/commonjs/hooks/useMessageLoaderQueue.js +32 -5
  150. package/lib/commonjs/hooks/useMessageLoaderQueue.js.map +1 -1
  151. package/lib/commonjs/hooks/useMessageQueue.js +13 -5
  152. package/lib/commonjs/hooks/useMessageQueue.js.map +1 -1
  153. package/lib/commonjs/hooks/useRoomDirectory.js +29 -0
  154. package/lib/commonjs/hooks/useRoomDirectory.js.map +1 -0
  155. package/lib/commonjs/hooks/useRoomInitialization.js +27 -5
  156. package/lib/commonjs/hooks/useRoomInitialization.js.map +1 -1
  157. package/lib/commonjs/hooks/useRoomMute.js +62 -0
  158. package/lib/commonjs/hooks/useRoomMute.js.map +1 -0
  159. package/lib/commonjs/hooks/useRoomState.js +3 -1
  160. package/lib/commonjs/hooks/useRoomState.js.map +1 -1
  161. package/lib/commonjs/hooks/useSendMessage.js +13 -3
  162. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  163. package/lib/commonjs/i18n/strings.js +318 -6
  164. package/lib/commonjs/i18n/strings.js.map +1 -1
  165. package/lib/commonjs/networking/api-requests/messageSearch.api.js +87 -0
  166. package/lib/commonjs/networking/api-requests/messageSearch.api.js.map +1 -0
  167. package/lib/commonjs/networking/api-requests/publicChats.api.js +48 -0
  168. package/lib/commonjs/networking/api-requests/publicChats.api.js.map +1 -0
  169. package/lib/commonjs/networking/api-requests/roomMembers.api.js +253 -4
  170. package/lib/commonjs/networking/api-requests/roomMembers.api.js.map +1 -1
  171. package/lib/commonjs/networking/api-requests/rooms.api.js +48 -12
  172. package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
  173. package/lib/commonjs/networking/api-requests/xmppToken.api.js +71 -0
  174. package/lib/commonjs/networking/api-requests/xmppToken.api.js.map +1 -0
  175. package/lib/commonjs/networking/ethoraEvents.js +227 -0
  176. package/lib/commonjs/networking/ethoraEvents.js.map +1 -0
  177. package/lib/commonjs/networking/stanzaHandlers.js +153 -16
  178. package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
  179. package/lib/commonjs/networking/xmpp/allRoomPresences.xmpp.js +124 -3
  180. package/lib/commonjs/networking/xmpp/allRoomPresences.xmpp.js.map +1 -1
  181. package/lib/commonjs/networking/xmpp/getHistory.xmpp.js +319 -35
  182. package/lib/commonjs/networking/xmpp/getHistory.xmpp.js.map +1 -1
  183. package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js +7 -0
  184. package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
  185. package/lib/commonjs/networking/xmpp/historyCursor.js +101 -0
  186. package/lib/commonjs/networking/xmpp/historyCursor.js.map +1 -0
  187. package/lib/commonjs/networking/xmpp/mamQueryIds.js +17 -0
  188. package/lib/commonjs/networking/xmpp/mamQueryIds.js.map +1 -0
  189. package/lib/commonjs/networking/xmpp/mamRouter.js +24 -9
  190. package/lib/commonjs/networking/xmpp/mamRouter.js.map +1 -1
  191. package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js +70 -65
  192. package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
  193. package/lib/commonjs/networking/xmpp/roomJoinSweep.js +389 -0
  194. package/lib/commonjs/networking/xmpp/roomJoinSweep.js.map +1 -0
  195. package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js +0 -1
  196. package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
  197. package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js +0 -1
  198. package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
  199. package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +0 -1
  200. package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
  201. package/lib/commonjs/networking/xmppClient.js +269 -41
  202. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  203. package/lib/commonjs/networking/xmppCredentials.js +80 -0
  204. package/lib/commonjs/networking/xmppCredentials.js.map +1 -0
  205. package/lib/commonjs/roomStore/Middleware/jumpThreadMiddleware.js +158 -0
  206. package/lib/commonjs/roomStore/Middleware/jumpThreadMiddleware.js.map +1 -0
  207. package/lib/commonjs/roomStore/Middleware/reactionsMiddleware.js +6 -0
  208. package/lib/commonjs/roomStore/Middleware/reactionsMiddleware.js.map +1 -1
  209. package/lib/commonjs/roomStore/Middleware/unreadMidlleware.js +45 -7
  210. package/lib/commonjs/roomStore/Middleware/unreadMidlleware.js.map +1 -1
  211. package/lib/commonjs/roomStore/chatSettingsSlice.js +15 -1
  212. package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
  213. package/lib/commonjs/roomStore/index.js +13 -3
  214. package/lib/commonjs/roomStore/index.js.map +1 -1
  215. package/lib/commonjs/roomStore/persistence.js +48 -1
  216. package/lib/commonjs/roomStore/persistence.js.map +1 -1
  217. package/lib/commonjs/roomStore/roomsSlice.js +474 -60
  218. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  219. package/lib/commonjs/roomStore/safeKey.js +44 -0
  220. package/lib/commonjs/roomStore/safeKey.js.map +1 -0
  221. package/lib/commonjs/roomStore/usersSetCap.js +37 -0
  222. package/lib/commonjs/roomStore/usersSetCap.js.map +1 -0
  223. package/lib/commonjs/version.js +1 -1
  224. package/lib/commonjs/version.js.map +1 -1
  225. package/lib/module/assets/icons.js +1 -1
  226. package/lib/module/assets/icons.js.map +1 -1
  227. package/lib/module/components/Header/HeaderRoomList.js +23 -7
  228. package/lib/module/components/Header/HeaderRoomList.js.map +1 -1
  229. package/lib/module/components/InputComponents/Search.js +39 -2
  230. package/lib/module/components/InputComponents/Search.js.map +1 -1
  231. package/lib/module/components/MainComponents/ArchivedMessageCard.js +161 -0
  232. package/lib/module/components/MainComponents/ArchivedMessageCard.js.map +1 -0
  233. package/lib/module/components/MainComponents/ChatHeader.js +22 -5
  234. package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
  235. package/lib/module/components/MainComponents/ChatRoom.js +57 -26
  236. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  237. package/lib/module/components/MainComponents/ChatWrapper.js +54 -5
  238. package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
  239. package/lib/module/components/MainComponents/MediaMessage.js +18 -3
  240. package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
  241. package/lib/module/components/MainComponents/MessageList.js +740 -42
  242. package/lib/module/components/MainComponents/MessageList.js.map +1 -1
  243. package/lib/module/components/MainComponents/MessageSearchButton.js +48 -0
  244. package/lib/module/components/MainComponents/MessageSearchButton.js.map +1 -0
  245. package/lib/module/components/MainComponents/ReduxWrapper.js +15 -7
  246. package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
  247. package/lib/module/components/MainComponents/RoomList.js +111 -2
  248. package/lib/module/components/MainComponents/RoomList.js.map +1 -1
  249. package/lib/module/components/Menu/HeaderRoomListMenu.js +15 -4
  250. package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
  251. package/lib/module/components/MessageBubble/BubbleHighlight.js +106 -0
  252. package/lib/module/components/MessageBubble/BubbleHighlight.js.map +1 -0
  253. package/lib/module/components/MessageBubble/Message.js +172 -127
  254. package/lib/module/components/MessageBubble/Message.js.map +1 -1
  255. package/lib/module/components/MessageBubble/MessageInteractions.js +98 -78
  256. package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
  257. package/lib/module/components/MessageBubble/messageMenuLayout.js +45 -0
  258. package/lib/module/components/MessageBubble/messageMenuLayout.js.map +1 -0
  259. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +74 -38
  260. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  261. package/lib/module/components/Modals/MessageSearchModal/MessageHitResults.js +243 -0
  262. package/lib/module/components/Modals/MessageSearchModal/MessageHitResults.js.map +1 -0
  263. package/lib/module/components/Modals/MessageSearchModal/MessageSearchModal.js +482 -0
  264. package/lib/module/components/Modals/MessageSearchModal/MessageSearchModal.js.map +1 -0
  265. package/lib/module/components/Modals/MessageSearchModal/openHit.js +45 -0
  266. package/lib/module/components/Modals/MessageSearchModal/openHit.js.map +1 -0
  267. package/lib/module/components/Modals/MessageSearchModal/resolveSender.js +41 -0
  268. package/lib/module/components/Modals/MessageSearchModal/resolveSender.js.map +1 -0
  269. package/lib/module/components/Modals/MessageSearchModal/searchFilters.js +74 -0
  270. package/lib/module/components/Modals/MessageSearchModal/searchFilters.js.map +1 -0
  271. package/lib/module/components/Modals/MessageSearchModal/snippet.js +57 -0
  272. package/lib/module/components/Modals/MessageSearchModal/snippet.js.map +1 -0
  273. package/lib/module/components/Modals/MessageSearchModal/useMessageSearch.js +131 -0
  274. package/lib/module/components/Modals/MessageSearchModal/useMessageSearch.js.map +1 -0
  275. package/lib/module/components/Modals/PublicChatsModal/PublicChatsModal.js +300 -0
  276. package/lib/module/components/Modals/PublicChatsModal/PublicChatsModal.js.map +1 -0
  277. package/lib/module/components/Modals/PublicChatsModal/publicChatsLogic.js +30 -0
  278. package/lib/module/components/Modals/PublicChatsModal/publicChatsLogic.js.map +1 -0
  279. package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js +8 -1
  280. package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
  281. package/lib/module/components/RoomComponents/ChatRoomItem.js +14 -3
  282. package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
  283. package/lib/module/components/RoomComponents/SwipeableRoomRow.js +39 -7
  284. package/lib/module/components/RoomComponents/SwipeableRoomRow.js.map +1 -1
  285. package/lib/module/components/Thread/ThreadHeader.js +3 -1
  286. package/lib/module/components/Thread/ThreadHeader.js.map +1 -1
  287. package/lib/module/components/Thread/ThreadWrapper.js +89 -9
  288. package/lib/module/components/Thread/ThreadWrapper.js.map +1 -1
  289. package/lib/module/components/styled/AudioDecoderHost.js +332 -0
  290. package/lib/module/components/styled/AudioDecoderHost.js.map +1 -0
  291. package/lib/module/components/styled/AudioMessage.js +495 -422
  292. package/lib/module/components/styled/AudioMessage.js.map +1 -1
  293. package/lib/module/components/styled/SendInput.js +32 -6
  294. package/lib/module/components/styled/SendInput.js.map +1 -1
  295. package/lib/module/context/MessageNotificationContext.js +15 -5
  296. package/lib/module/context/MessageNotificationContext.js.map +1 -1
  297. package/lib/module/context/xmppProvider.js +54 -79
  298. package/lib/module/context/xmppProvider.js.map +1 -1
  299. package/lib/module/helpers/audioWaveform.js +153 -0
  300. package/lib/module/helpers/audioWaveform.js.map +1 -0
  301. package/lib/module/helpers/backgroundJoinSweep.js +30 -0
  302. package/lib/module/helpers/backgroundJoinSweep.js.map +1 -0
  303. package/lib/module/helpers/bubbleHighlight.js +38 -0
  304. package/lib/module/helpers/bubbleHighlight.js.map +1 -0
  305. package/lib/module/helpers/checkUniqueUsers.js +15 -13
  306. package/lib/module/helpers/checkUniqueUsers.js.map +1 -1
  307. package/lib/module/helpers/constants/MODAL_COMPONENTS.js +5 -1
  308. package/lib/module/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
  309. package/lib/module/helpers/constants/MODAL_TYPES.js +3 -1
  310. package/lib/module/helpers/constants/MODAL_TYPES.js.map +1 -1
  311. package/lib/module/helpers/createRoomFromApi.js +37 -3
  312. package/lib/module/helpers/createRoomFromApi.js.map +1 -1
  313. package/lib/module/helpers/dedupeMembers.js +28 -0
  314. package/lib/module/helpers/dedupeMembers.js.map +1 -0
  315. package/lib/module/helpers/ethoraLogger.js +52 -0
  316. package/lib/module/helpers/ethoraLogger.js.map +1 -0
  317. package/lib/module/helpers/getUnnamedUsers.js +9 -4
  318. package/lib/module/helpers/getUnnamedUsers.js.map +1 -1
  319. package/lib/module/helpers/historyPreloadConfig.js +39 -0
  320. package/lib/module/helpers/historyPreloadConfig.js.map +1 -0
  321. package/lib/module/helpers/historyPreloadScheduler.js +368 -134
  322. package/lib/module/helpers/historyPreloadScheduler.js.map +1 -1
  323. package/lib/module/helpers/initRoomsPresence.js +18 -5
  324. package/lib/module/helpers/initRoomsPresence.js.map +1 -1
  325. package/lib/module/helpers/insertMessageWithDelimiter.js +5 -0
  326. package/lib/module/helpers/insertMessageWithDelimiter.js.map +1 -1
  327. package/lib/module/helpers/isLikelyMucJid.js +60 -0
  328. package/lib/module/helpers/isLikelyMucJid.js.map +1 -0
  329. package/lib/module/helpers/isMessageSearchEnabled.js +13 -0
  330. package/lib/module/helpers/isMessageSearchEnabled.js.map +1 -0
  331. package/lib/module/helpers/joiningRoom.js +9 -0
  332. package/lib/module/helpers/joiningRoom.js.map +1 -0
  333. package/lib/module/helpers/jumpThread.js +83 -0
  334. package/lib/module/helpers/jumpThread.js.map +1 -0
  335. package/lib/module/helpers/jumpToMessage.js +52 -0
  336. package/lib/module/helpers/jumpToMessage.js.map +1 -0
  337. package/lib/module/helpers/jumpWindow.js +177 -0
  338. package/lib/module/helpers/jumpWindow.js.map +1 -0
  339. package/lib/module/helpers/loadRoomHistory.js +69 -0
  340. package/lib/module/helpers/loadRoomHistory.js.map +1 -0
  341. package/lib/module/helpers/notificationPolicy.js +70 -0
  342. package/lib/module/helpers/notificationPolicy.js.map +1 -0
  343. package/lib/module/helpers/openRoomAtMessage.js +41 -0
  344. package/lib/module/helpers/openRoomAtMessage.js.map +1 -0
  345. package/lib/module/helpers/openThreadForJump.js +68 -0
  346. package/lib/module/helpers/openThreadForJump.js.map +1 -0
  347. package/lib/module/helpers/parseMessageReference.js +26 -6
  348. package/lib/module/helpers/parseMessageReference.js.map +1 -1
  349. package/lib/module/helpers/publicChatsEntry.js +12 -0
  350. package/lib/module/helpers/publicChatsEntry.js.map +1 -0
  351. package/lib/module/helpers/roomActivityScore.js +30 -0
  352. package/lib/module/helpers/roomActivityScore.js.map +1 -0
  353. package/lib/module/helpers/roomUserCount.js +29 -0
  354. package/lib/module/helpers/roomUserCount.js.map +1 -0
  355. package/lib/module/helpers/runConfiguredHistoryPreload.js +63 -0
  356. package/lib/module/helpers/runConfiguredHistoryPreload.js.map +1 -0
  357. package/lib/module/helpers/sessionAppId.js +20 -0
  358. package/lib/module/helpers/sessionAppId.js.map +1 -0
  359. package/lib/module/helpers/timestamp.js +37 -0
  360. package/lib/module/helpers/timestamp.js.map +1 -0
  361. package/lib/module/helpers/userResolver.js +503 -0
  362. package/lib/module/helpers/userResolver.js.map +1 -0
  363. package/lib/module/helpers/xmppIdShape.js +46 -0
  364. package/lib/module/helpers/xmppIdShape.js.map +1 -0
  365. package/lib/module/hooks/useChatWrapperInit.js +16 -5
  366. package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
  367. package/lib/module/hooks/useHeapSender.js +54 -3
  368. package/lib/module/hooks/useHeapSender.js.map +1 -1
  369. package/lib/module/hooks/useJumpToMessage.js +389 -0
  370. package/lib/module/hooks/useJumpToMessage.js.map +1 -0
  371. package/lib/module/hooks/useMessageLoaderQueue.js +32 -5
  372. package/lib/module/hooks/useMessageLoaderQueue.js.map +1 -1
  373. package/lib/module/hooks/useMessageQueue.js +13 -5
  374. package/lib/module/hooks/useMessageQueue.js.map +1 -1
  375. package/lib/module/hooks/useRoomDirectory.js +24 -0
  376. package/lib/module/hooks/useRoomDirectory.js.map +1 -0
  377. package/lib/module/hooks/useRoomInitialization.js +29 -7
  378. package/lib/module/hooks/useRoomInitialization.js.map +1 -1
  379. package/lib/module/hooks/useRoomMute.js +58 -0
  380. package/lib/module/hooks/useRoomMute.js.map +1 -0
  381. package/lib/module/hooks/useRoomState.js +3 -1
  382. package/lib/module/hooks/useRoomState.js.map +1 -1
  383. package/lib/module/hooks/useSendMessage.js +13 -3
  384. package/lib/module/hooks/useSendMessage.js.map +1 -1
  385. package/lib/module/i18n/strings.js +318 -6
  386. package/lib/module/i18n/strings.js.map +1 -1
  387. package/lib/module/networking/api-requests/messageSearch.api.js +81 -0
  388. package/lib/module/networking/api-requests/messageSearch.api.js.map +1 -0
  389. package/lib/module/networking/api-requests/publicChats.api.js +43 -0
  390. package/lib/module/networking/api-requests/publicChats.api.js.map +1 -0
  391. package/lib/module/networking/api-requests/roomMembers.api.js +248 -4
  392. package/lib/module/networking/api-requests/roomMembers.api.js.map +1 -1
  393. package/lib/module/networking/api-requests/rooms.api.js +48 -12
  394. package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
  395. package/lib/module/networking/api-requests/xmppToken.api.js +66 -0
  396. package/lib/module/networking/api-requests/xmppToken.api.js.map +1 -0
  397. package/lib/module/networking/ethoraEvents.js +220 -0
  398. package/lib/module/networking/ethoraEvents.js.map +1 -0
  399. package/lib/module/networking/stanzaHandlers.js +155 -18
  400. package/lib/module/networking/stanzaHandlers.js.map +1 -1
  401. package/lib/module/networking/xmpp/allRoomPresences.xmpp.js +125 -3
  402. package/lib/module/networking/xmpp/allRoomPresences.xmpp.js.map +1 -1
  403. package/lib/module/networking/xmpp/getHistory.xmpp.js +318 -35
  404. package/lib/module/networking/xmpp/getHistory.xmpp.js.map +1 -1
  405. package/lib/module/networking/xmpp/handleStanzas.xmpp.js +7 -0
  406. package/lib/module/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
  407. package/lib/module/networking/xmpp/historyCursor.js +95 -0
  408. package/lib/module/networking/xmpp/historyCursor.js.map +1 -0
  409. package/lib/module/networking/xmpp/mamQueryIds.js +12 -0
  410. package/lib/module/networking/xmpp/mamQueryIds.js.map +1 -0
  411. package/lib/module/networking/xmpp/mamRouter.js +22 -8
  412. package/lib/module/networking/xmpp/mamRouter.js.map +1 -1
  413. package/lib/module/networking/xmpp/presenceInRoom.xmpp.js +68 -62
  414. package/lib/module/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
  415. package/lib/module/networking/xmpp/roomJoinSweep.js +385 -0
  416. package/lib/module/networking/xmpp/roomJoinSweep.js.map +1 -0
  417. package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js +0 -1
  418. package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
  419. package/lib/module/networking/xmpp/sendTextMessage.xmpp.js +0 -1
  420. package/lib/module/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
  421. package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +0 -1
  422. package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
  423. package/lib/module/networking/xmppClient.js +269 -41
  424. package/lib/module/networking/xmppClient.js.map +1 -1
  425. package/lib/module/networking/xmppCredentials.js +76 -0
  426. package/lib/module/networking/xmppCredentials.js.map +1 -0
  427. package/lib/module/roomStore/Middleware/jumpThreadMiddleware.js +153 -0
  428. package/lib/module/roomStore/Middleware/jumpThreadMiddleware.js.map +1 -0
  429. package/lib/module/roomStore/Middleware/reactionsMiddleware.js +6 -0
  430. package/lib/module/roomStore/Middleware/reactionsMiddleware.js.map +1 -1
  431. package/lib/module/roomStore/Middleware/unreadMidlleware.js +46 -7
  432. package/lib/module/roomStore/Middleware/unreadMidlleware.js.map +1 -1
  433. package/lib/module/roomStore/chatSettingsSlice.js +13 -0
  434. package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
  435. package/lib/module/roomStore/index.js +7 -3
  436. package/lib/module/roomStore/index.js.map +1 -1
  437. package/lib/module/roomStore/persistence.js +46 -1
  438. package/lib/module/roomStore/persistence.js.map +1 -1
  439. package/lib/module/roomStore/roomsSlice.js +459 -58
  440. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  441. package/lib/module/roomStore/safeKey.js +37 -0
  442. package/lib/module/roomStore/safeKey.js.map +1 -0
  443. package/lib/module/roomStore/usersSetCap.js +32 -0
  444. package/lib/module/roomStore/usersSetCap.js.map +1 -0
  445. package/lib/module/version.js +1 -1
  446. package/lib/module/version.js.map +1 -1
  447. package/lib/typescript/assets/icons.d.ts +4 -0
  448. package/lib/typescript/assets/icons.d.ts.map +1 -1
  449. package/lib/typescript/components/Header/HeaderRoomList.d.ts.map +1 -1
  450. package/lib/typescript/components/InputComponents/Search.d.ts.map +1 -1
  451. package/lib/typescript/components/MainComponents/ArchivedMessageCard.d.ts +12 -0
  452. package/lib/typescript/components/MainComponents/ArchivedMessageCard.d.ts.map +1 -0
  453. package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
  454. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  455. package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
  456. package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
  457. package/lib/typescript/components/MainComponents/MessageList.d.ts +22 -1
  458. package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
  459. package/lib/typescript/components/MainComponents/MessageSearchButton.d.ts +7 -0
  460. package/lib/typescript/components/MainComponents/MessageSearchButton.d.ts.map +1 -0
  461. package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
  462. package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
  463. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
  464. package/lib/typescript/components/MessageBubble/BubbleHighlight.d.ts +12 -0
  465. package/lib/typescript/components/MessageBubble/BubbleHighlight.d.ts.map +1 -0
  466. package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
  467. package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts +5 -0
  468. package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
  469. package/lib/typescript/components/MessageBubble/messageMenuLayout.d.ts +29 -0
  470. package/lib/typescript/components/MessageBubble/messageMenuLayout.d.ts.map +1 -0
  471. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts +2 -0
  472. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
  473. package/lib/typescript/components/Modals/MessageSearchModal/MessageHitResults.d.ts +44 -0
  474. package/lib/typescript/components/Modals/MessageSearchModal/MessageHitResults.d.ts.map +1 -0
  475. package/lib/typescript/components/Modals/MessageSearchModal/MessageSearchModal.d.ts +12 -0
  476. package/lib/typescript/components/Modals/MessageSearchModal/MessageSearchModal.d.ts.map +1 -0
  477. package/lib/typescript/components/Modals/MessageSearchModal/openHit.d.ts +15 -0
  478. package/lib/typescript/components/Modals/MessageSearchModal/openHit.d.ts.map +1 -0
  479. package/lib/typescript/components/Modals/MessageSearchModal/resolveSender.d.ts +34 -0
  480. package/lib/typescript/components/Modals/MessageSearchModal/resolveSender.d.ts.map +1 -0
  481. package/lib/typescript/components/Modals/MessageSearchModal/searchFilters.d.ts +41 -0
  482. package/lib/typescript/components/Modals/MessageSearchModal/searchFilters.d.ts.map +1 -0
  483. package/lib/typescript/components/Modals/MessageSearchModal/snippet.d.ts +15 -0
  484. package/lib/typescript/components/Modals/MessageSearchModal/snippet.d.ts.map +1 -0
  485. package/lib/typescript/components/Modals/MessageSearchModal/useMessageSearch.d.ts +23 -0
  486. package/lib/typescript/components/Modals/MessageSearchModal/useMessageSearch.d.ts.map +1 -0
  487. package/lib/typescript/components/Modals/PublicChatsModal/PublicChatsModal.d.ts +16 -0
  488. package/lib/typescript/components/Modals/PublicChatsModal/PublicChatsModal.d.ts.map +1 -0
  489. package/lib/typescript/components/Modals/PublicChatsModal/publicChatsLogic.d.ts +14 -0
  490. package/lib/typescript/components/Modals/PublicChatsModal/publicChatsLogic.d.ts.map +1 -0
  491. package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts.map +1 -1
  492. package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
  493. package/lib/typescript/components/RoomComponents/SwipeableRoomRow.d.ts +5 -1
  494. package/lib/typescript/components/RoomComponents/SwipeableRoomRow.d.ts.map +1 -1
  495. package/lib/typescript/components/Thread/ThreadHeader.d.ts.map +1 -1
  496. package/lib/typescript/components/Thread/ThreadWrapper.d.ts +1 -0
  497. package/lib/typescript/components/Thread/ThreadWrapper.d.ts.map +1 -1
  498. package/lib/typescript/components/styled/AudioDecoderHost.d.ts +39 -0
  499. package/lib/typescript/components/styled/AudioDecoderHost.d.ts.map +1 -0
  500. package/lib/typescript/components/styled/AudioMessage.d.ts +14 -1
  501. package/lib/typescript/components/styled/AudioMessage.d.ts.map +1 -1
  502. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  503. package/lib/typescript/context/MessageNotificationContext.d.ts.map +1 -1
  504. package/lib/typescript/context/xmppProvider.d.ts +2 -0
  505. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  506. package/lib/typescript/helpers/audioWaveform.d.ts +54 -0
  507. package/lib/typescript/helpers/audioWaveform.d.ts.map +1 -0
  508. package/lib/typescript/helpers/backgroundJoinSweep.d.ts +14 -0
  509. package/lib/typescript/helpers/backgroundJoinSweep.d.ts.map +1 -0
  510. package/lib/typescript/helpers/bubbleHighlight.d.ts +17 -0
  511. package/lib/typescript/helpers/bubbleHighlight.d.ts.map +1 -0
  512. package/lib/typescript/helpers/checkUniqueUsers.d.ts +2 -2
  513. package/lib/typescript/helpers/checkUniqueUsers.d.ts.map +1 -1
  514. package/lib/typescript/helpers/constants/MODAL_COMPONENTS.d.ts.map +1 -1
  515. package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts +2 -0
  516. package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts.map +1 -1
  517. package/lib/typescript/helpers/createRoomFromApi.d.ts +25 -0
  518. package/lib/typescript/helpers/createRoomFromApi.d.ts.map +1 -1
  519. package/lib/typescript/helpers/dedupeMembers.d.ts +11 -0
  520. package/lib/typescript/helpers/dedupeMembers.d.ts.map +1 -0
  521. package/lib/typescript/helpers/ethoraLogger.d.ts +13 -0
  522. package/lib/typescript/helpers/ethoraLogger.d.ts.map +1 -0
  523. package/lib/typescript/helpers/getUnnamedUsers.d.ts.map +1 -1
  524. package/lib/typescript/helpers/historyPreloadConfig.d.ts +26 -0
  525. package/lib/typescript/helpers/historyPreloadConfig.d.ts.map +1 -0
  526. package/lib/typescript/helpers/historyPreloadScheduler.d.ts +8 -4
  527. package/lib/typescript/helpers/historyPreloadScheduler.d.ts.map +1 -1
  528. package/lib/typescript/helpers/initRoomsPresence.d.ts +7 -0
  529. package/lib/typescript/helpers/initRoomsPresence.d.ts.map +1 -1
  530. package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts.map +1 -1
  531. package/lib/typescript/helpers/isLikelyMucJid.d.ts +19 -0
  532. package/lib/typescript/helpers/isLikelyMucJid.d.ts.map +1 -0
  533. package/lib/typescript/helpers/isMessageSearchEnabled.d.ts +12 -0
  534. package/lib/typescript/helpers/isMessageSearchEnabled.d.ts.map +1 -0
  535. package/lib/typescript/helpers/joiningRoom.d.ts +7 -0
  536. package/lib/typescript/helpers/joiningRoom.d.ts.map +1 -0
  537. package/lib/typescript/helpers/jumpThread.d.ts +48 -0
  538. package/lib/typescript/helpers/jumpThread.d.ts.map +1 -0
  539. package/lib/typescript/helpers/jumpToMessage.d.ts +26 -0
  540. package/lib/typescript/helpers/jumpToMessage.d.ts.map +1 -0
  541. package/lib/typescript/helpers/jumpWindow.d.ts +74 -0
  542. package/lib/typescript/helpers/jumpWindow.d.ts.map +1 -0
  543. package/lib/typescript/helpers/loadRoomHistory.d.ts +34 -0
  544. package/lib/typescript/helpers/loadRoomHistory.d.ts.map +1 -0
  545. package/lib/typescript/helpers/notificationPolicy.d.ts +42 -0
  546. package/lib/typescript/helpers/notificationPolicy.d.ts.map +1 -0
  547. package/lib/typescript/helpers/openRoomAtMessage.d.ts +17 -0
  548. package/lib/typescript/helpers/openRoomAtMessage.d.ts.map +1 -0
  549. package/lib/typescript/helpers/openThreadForJump.d.ts +27 -0
  550. package/lib/typescript/helpers/openThreadForJump.d.ts.map +1 -0
  551. package/lib/typescript/helpers/parseMessageReference.d.ts +18 -5
  552. package/lib/typescript/helpers/parseMessageReference.d.ts.map +1 -1
  553. package/lib/typescript/helpers/publicChatsEntry.d.ts +11 -0
  554. package/lib/typescript/helpers/publicChatsEntry.d.ts.map +1 -0
  555. package/lib/typescript/helpers/roomActivityScore.d.ts +5 -0
  556. package/lib/typescript/helpers/roomActivityScore.d.ts.map +1 -0
  557. package/lib/typescript/helpers/roomUserCount.d.ts +20 -0
  558. package/lib/typescript/helpers/roomUserCount.d.ts.map +1 -0
  559. package/lib/typescript/helpers/runConfiguredHistoryPreload.d.ts +21 -0
  560. package/lib/typescript/helpers/runConfiguredHistoryPreload.d.ts.map +1 -0
  561. package/lib/typescript/helpers/sessionAppId.d.ts +8 -0
  562. package/lib/typescript/helpers/sessionAppId.d.ts.map +1 -0
  563. package/lib/typescript/helpers/timestamp.d.ts +3 -0
  564. package/lib/typescript/helpers/timestamp.d.ts.map +1 -0
  565. package/lib/typescript/helpers/userResolver.d.ts +58 -0
  566. package/lib/typescript/helpers/userResolver.d.ts.map +1 -0
  567. package/lib/typescript/helpers/xmppIdShape.d.ts +10 -0
  568. package/lib/typescript/helpers/xmppIdShape.d.ts.map +1 -0
  569. package/lib/typescript/hooks/useChatWrapperInit.d.ts +2 -0
  570. package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
  571. package/lib/typescript/hooks/useHeapSender.d.ts.map +1 -1
  572. package/lib/typescript/hooks/useJumpToMessage.d.ts +116 -0
  573. package/lib/typescript/hooks/useJumpToMessage.d.ts.map +1 -0
  574. package/lib/typescript/hooks/useMessageLoaderQueue.d.ts.map +1 -1
  575. package/lib/typescript/hooks/useMessageQueue.d.ts.map +1 -1
  576. package/lib/typescript/hooks/useRoomDirectory.d.ts +12 -0
  577. package/lib/typescript/hooks/useRoomDirectory.d.ts.map +1 -0
  578. package/lib/typescript/hooks/useRoomInitialization.d.ts.map +1 -1
  579. package/lib/typescript/hooks/useRoomMute.d.ts +8 -0
  580. package/lib/typescript/hooks/useRoomMute.d.ts.map +1 -0
  581. package/lib/typescript/hooks/useRoomState.d.ts +1 -0
  582. package/lib/typescript/hooks/useRoomState.d.ts.map +1 -1
  583. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  584. package/lib/typescript/i18n/strings.d.ts.map +1 -1
  585. package/lib/typescript/networking/api-requests/messageSearch.api.d.ts +57 -0
  586. package/lib/typescript/networking/api-requests/messageSearch.api.d.ts.map +1 -0
  587. package/lib/typescript/networking/api-requests/publicChats.api.d.ts +24 -0
  588. package/lib/typescript/networking/api-requests/publicChats.api.d.ts.map +1 -0
  589. package/lib/typescript/networking/api-requests/roomMembers.api.d.ts +19 -1
  590. package/lib/typescript/networking/api-requests/roomMembers.api.d.ts.map +1 -1
  591. package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
  592. package/lib/typescript/networking/api-requests/xmppToken.api.d.ts +2 -0
  593. package/lib/typescript/networking/api-requests/xmppToken.api.d.ts.map +1 -0
  594. package/lib/typescript/networking/ethoraEvents.d.ts +45 -0
  595. package/lib/typescript/networking/ethoraEvents.d.ts.map +1 -0
  596. package/lib/typescript/networking/stanzaHandlers.d.ts +1 -1
  597. package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
  598. package/lib/typescript/networking/xmpp/allRoomPresences.xmpp.d.ts +32 -1
  599. package/lib/typescript/networking/xmpp/allRoomPresences.xmpp.d.ts.map +1 -1
  600. package/lib/typescript/networking/xmpp/getHistory.xmpp.d.ts +64 -0
  601. package/lib/typescript/networking/xmpp/getHistory.xmpp.d.ts.map +1 -1
  602. package/lib/typescript/networking/xmpp/handleStanzas.xmpp.d.ts.map +1 -1
  603. package/lib/typescript/networking/xmpp/historyCursor.d.ts +35 -0
  604. package/lib/typescript/networking/xmpp/historyCursor.d.ts.map +1 -0
  605. package/lib/typescript/networking/xmpp/mamQueryIds.d.ts +10 -0
  606. package/lib/typescript/networking/xmpp/mamQueryIds.d.ts.map +1 -0
  607. package/lib/typescript/networking/xmpp/mamRouter.d.ts +7 -0
  608. package/lib/typescript/networking/xmpp/mamRouter.d.ts.map +1 -1
  609. package/lib/typescript/networking/xmpp/presenceInRoom.xmpp.d.ts +13 -2
  610. package/lib/typescript/networking/xmpp/presenceInRoom.xmpp.d.ts.map +1 -1
  611. package/lib/typescript/networking/xmpp/roomJoinSweep.d.ts +82 -0
  612. package/lib/typescript/networking/xmpp/roomJoinSweep.d.ts.map +1 -0
  613. package/lib/typescript/networking/xmpp/sendMediaMessage.xmpp.d.ts.map +1 -1
  614. package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts.map +1 -1
  615. package/lib/typescript/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts.map +1 -1
  616. package/lib/typescript/networking/xmppClient.d.ts +90 -4
  617. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  618. package/lib/typescript/networking/xmppCredentials.d.ts +12 -0
  619. package/lib/typescript/networking/xmppCredentials.d.ts.map +1 -0
  620. package/lib/typescript/roomStore/Middleware/jumpThreadMiddleware.d.ts +3 -0
  621. package/lib/typescript/roomStore/Middleware/jumpThreadMiddleware.d.ts.map +1 -0
  622. package/lib/typescript/roomStore/Middleware/reactionsMiddleware.d.ts.map +1 -1
  623. package/lib/typescript/roomStore/Middleware/unreadMidlleware.d.ts.map +1 -1
  624. package/lib/typescript/roomStore/chatSettingsSlice.d.ts +8 -1
  625. package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
  626. package/lib/typescript/roomStore/index.d.ts +2 -1
  627. package/lib/typescript/roomStore/index.d.ts.map +1 -1
  628. package/lib/typescript/roomStore/persistence.d.ts +8 -0
  629. package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
  630. package/lib/typescript/roomStore/roomsSlice.d.ts +138 -2
  631. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  632. package/lib/typescript/roomStore/safeKey.d.ts +13 -0
  633. package/lib/typescript/roomStore/safeKey.d.ts.map +1 -0
  634. package/lib/typescript/roomStore/usersSetCap.d.ts +16 -0
  635. package/lib/typescript/roomStore/usersSetCap.d.ts.map +1 -0
  636. package/lib/typescript/types/models/media.model.d.ts +2 -0
  637. package/lib/typescript/types/models/media.model.d.ts.map +1 -1
  638. package/lib/typescript/types/models/room.model.d.ts +18 -5
  639. package/lib/typescript/types/models/room.model.d.ts.map +1 -1
  640. package/lib/typescript/types/models/xmpp.model.d.ts +8 -1
  641. package/lib/typescript/types/models/xmpp.model.d.ts.map +1 -1
  642. package/lib/typescript/types/types.d.ts +90 -5
  643. package/lib/typescript/types/types.d.ts.map +1 -1
  644. package/lib/typescript/version.d.ts +1 -1
  645. package/lib/typescript/version.d.ts.map +1 -1
  646. package/package.json +1 -1
  647. package/src/assets/icons.tsx +13 -0
  648. package/src/components/Header/HeaderRoomList.tsx +21 -4
  649. package/src/components/InputComponents/Search.tsx +33 -0
  650. package/src/components/MainComponents/ArchivedMessageCard.tsx +139 -0
  651. package/src/components/MainComponents/ChatHeader.tsx +19 -3
  652. package/src/components/MainComponents/ChatRoom.tsx +60 -23
  653. package/src/components/MainComponents/ChatWrapper.tsx +50 -9
  654. package/src/components/MainComponents/MediaMessage.tsx +17 -0
  655. package/src/components/MainComponents/MessageList.tsx +823 -84
  656. package/src/components/MainComponents/MessageSearchButton.tsx +48 -0
  657. package/src/components/MainComponents/ReduxWrapper.tsx +16 -5
  658. package/src/components/MainComponents/RoomList.tsx +125 -0
  659. package/src/components/Menu/HeaderRoomListMenu.tsx +26 -2
  660. package/src/components/MessageBubble/BubbleHighlight.tsx +106 -0
  661. package/src/components/MessageBubble/Message.tsx +265 -177
  662. package/src/components/MessageBubble/MessageInteractions.tsx +109 -86
  663. package/src/components/MessageBubble/messageMenuLayout.ts +59 -0
  664. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +92 -21
  665. package/src/components/Modals/MessageSearchModal/MessageHitResults.tsx +271 -0
  666. package/src/components/Modals/MessageSearchModal/MessageSearchModal.tsx +487 -0
  667. package/src/components/Modals/MessageSearchModal/openHit.ts +50 -0
  668. package/src/components/Modals/MessageSearchModal/resolveSender.ts +57 -0
  669. package/src/components/Modals/MessageSearchModal/searchFilters.ts +109 -0
  670. package/src/components/Modals/MessageSearchModal/snippet.ts +58 -0
  671. package/src/components/Modals/MessageSearchModal/useMessageSearch.ts +151 -0
  672. package/src/components/Modals/PublicChatsModal/PublicChatsModal.tsx +288 -0
  673. package/src/components/Modals/PublicChatsModal/publicChatsLogic.ts +36 -0
  674. package/src/components/Modals/SelectUsersModal/SelectUsersModal.tsx +8 -1
  675. package/src/components/RoomComponents/ChatRoomItem.tsx +16 -3
  676. package/src/components/RoomComponents/SwipeableRoomRow.tsx +39 -6
  677. package/src/components/Thread/ThreadHeader.tsx +3 -1
  678. package/src/components/Thread/ThreadWrapper.tsx +96 -10
  679. package/src/components/styled/AudioDecoderHost.tsx +351 -0
  680. package/src/components/styled/AudioMessage.tsx +482 -425
  681. package/src/components/styled/SendInput.tsx +42 -4
  682. package/src/context/MessageNotificationContext.tsx +19 -5
  683. package/src/context/xmppProvider.tsx +56 -91
  684. package/src/helpers/audioWaveform.ts +142 -0
  685. package/src/helpers/backgroundJoinSweep.ts +35 -0
  686. package/src/helpers/bubbleHighlight.ts +47 -0
  687. package/src/helpers/checkUniqueUsers.tsx +15 -17
  688. package/src/helpers/constants/MODAL_COMPONENTS.tsx +4 -0
  689. package/src/helpers/constants/MODAL_TYPES.ts +3 -0
  690. package/src/helpers/createRoomFromApi.tsx +45 -4
  691. package/src/helpers/dedupeMembers.ts +29 -0
  692. package/src/helpers/ethoraLogger.ts +50 -0
  693. package/src/helpers/getUnnamedUsers.ts +7 -4
  694. package/src/helpers/historyPreloadConfig.ts +68 -0
  695. package/src/helpers/historyPreloadScheduler.ts +437 -199
  696. package/src/helpers/initRoomsPresence.ts +20 -7
  697. package/src/helpers/insertMessageWithDelimiter.ts +3 -0
  698. package/src/helpers/isLikelyMucJid.ts +72 -0
  699. package/src/helpers/isMessageSearchEnabled.ts +18 -0
  700. package/src/helpers/joiningRoom.ts +13 -0
  701. package/src/helpers/jumpThread.ts +102 -0
  702. package/src/helpers/jumpToMessage.ts +57 -0
  703. package/src/helpers/jumpWindow.ts +212 -0
  704. package/src/helpers/loadRoomHistory.ts +83 -0
  705. package/src/helpers/notificationPolicy.ts +82 -0
  706. package/src/helpers/openRoomAtMessage.ts +38 -0
  707. package/src/helpers/openThreadForJump.ts +96 -0
  708. package/src/helpers/parseMessageReference.ts +37 -8
  709. package/src/helpers/publicChatsEntry.ts +15 -0
  710. package/src/helpers/roomActivityScore.ts +45 -0
  711. package/src/helpers/roomUserCount.ts +44 -0
  712. package/src/helpers/runConfiguredHistoryPreload.ts +76 -0
  713. package/src/helpers/sessionAppId.ts +17 -0
  714. package/src/helpers/timestamp.ts +44 -0
  715. package/src/helpers/userResolver.ts +542 -0
  716. package/src/helpers/xmppIdShape.ts +46 -0
  717. package/src/hooks/useChatWrapperInit.ts +22 -4
  718. package/src/hooks/useHeapSender.tsx +54 -3
  719. package/src/hooks/useJumpToMessage.ts +538 -0
  720. package/src/hooks/useMessageLoaderQueue.tsx +40 -4
  721. package/src/hooks/useMessageQueue.ts +9 -5
  722. package/src/hooks/useRoomDirectory.ts +39 -0
  723. package/src/hooks/useRoomInitialization.tsx +33 -7
  724. package/src/hooks/useRoomMute.ts +42 -0
  725. package/src/hooks/useRoomState.tsx +6 -0
  726. package/src/hooks/useSendMessage.tsx +14 -2
  727. package/src/i18n/strings.ts +312 -0
  728. package/src/networking/api-requests/messageSearch.api.ts +130 -0
  729. package/src/networking/api-requests/publicChats.api.ts +71 -0
  730. package/src/networking/api-requests/roomMembers.api.ts +263 -11
  731. package/src/networking/api-requests/rooms.api.ts +52 -12
  732. package/src/networking/api-requests/xmppToken.api.ts +62 -0
  733. package/src/networking/ethoraEvents.ts +262 -0
  734. package/src/networking/stanzaHandlers.ts +145 -19
  735. package/src/networking/xmpp/allRoomPresences.xmpp.ts +155 -5
  736. package/src/networking/xmpp/getHistory.xmpp.ts +433 -47
  737. package/src/networking/xmpp/handleStanzas.xmpp.ts +8 -0
  738. package/src/networking/xmpp/historyCursor.ts +124 -0
  739. package/src/networking/xmpp/mamQueryIds.ts +11 -0
  740. package/src/networking/xmpp/mamRouter.ts +24 -10
  741. package/src/networking/xmpp/presenceInRoom.xmpp.ts +91 -68
  742. package/src/networking/xmpp/roomJoinSweep.ts +412 -0
  743. package/src/networking/xmpp/sendMediaMessage.xmpp.ts +0 -1
  744. package/src/networking/xmpp/sendTextMessage.xmpp.ts +0 -1
  745. package/src/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.ts +0 -1
  746. package/src/networking/xmppClient.ts +323 -47
  747. package/src/networking/xmppCredentials.ts +87 -0
  748. package/src/roomStore/Middleware/jumpThreadMiddleware.ts +163 -0
  749. package/src/roomStore/Middleware/reactionsMiddleware.tsx +4 -0
  750. package/src/roomStore/Middleware/unreadMidlleware.tsx +59 -11
  751. package/src/roomStore/chatSettingsSlice.ts +11 -0
  752. package/src/roomStore/index.ts +10 -3
  753. package/src/roomStore/persistence.ts +54 -0
  754. package/src/roomStore/roomsSlice.ts +547 -65
  755. package/src/roomStore/safeKey.ts +49 -0
  756. package/src/roomStore/usersSetCap.ts +37 -0
  757. package/src/types/models/media.model.ts +4 -0
  758. package/src/types/models/room.model.ts +18 -5
  759. package/src/types/models/xmpp.model.ts +15 -1
  760. package/src/types/types.ts +95 -5
  761. package/src/version.ts +1 -1
@@ -3,14 +3,14 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.default = exports.WINDOW_SETTLE_MS = exports.WINDOW_RETRY_AFTER_FAILURE_MS = exports.WINDOW_EXIT_GRACE_MS = exports.PREFETCH_SCREENS = exports.PREFETCH_MIN_DISTANCE = exports.NO_PROGRESS_RETRY_MS = exports.MAX_IDLE_AUTO_PAGES = exports.HISTORY_PAGE_SIZE = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
+ var _reactRedux = require("react-redux");
9
10
  var _roomsSlice = require("../../roomStore/roomsSlice");
10
11
  var _Composing = _interopRequireDefault(require("../styled/StyledInputComponents/Composing"));
11
12
  var _TreadLabel = _interopRequireDefault(require("../styled/TreadLabel"));
12
13
  var _MessageContainer = require("./MessageContainer");
13
- var _reactRedux = require("react-redux");
14
14
  var _Loader = _interopRequireDefault(require("../styled/Loader"));
15
15
  var _icons = require("../../assets/icons");
16
16
  var _CustomTypingIndicator = _interopRequireDefault(require("../styled/StyledInputComponents/CustomTypingIndicator"));
@@ -18,11 +18,46 @@ var _getIconColor = require("../../helpers/getIconColor");
18
18
  var _getChatBackground = require("../../helpers/getChatBackground");
19
19
  var _useTheme = require("../../hooks/useTheme");
20
20
  var _isOwnMessage = require("../../helpers/isOwnMessage");
21
+ var _useJumpToMessage = require("../../hooks/useJumpToMessage");
22
+ var _jumpToMessage = require("../../helpers/jumpToMessage");
23
+ var _jumpWindow = require("../../helpers/jumpWindow");
24
+ var _jumpThread = require("../../helpers/jumpThread");
25
+ var _openThreadForJump = require("../../helpers/openThreadForJump");
26
+ var _bubbleHighlight = require("../../helpers/bubbleHighlight");
27
+ var _userResolver = require("../../helpers/userResolver");
28
+ var _useT = require("../../i18n/useT");
21
29
  var _jsxRuntime = require("react/jsx-runtime");
22
30
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
23
31
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
24
32
  /** @format */
25
33
 
34
+ // Older history is requested while the reader is still this far from the top
35
+ // (or 3 screens, whichever is more), so a normal scroll finds it already there
36
+ // and never sees a spinner. The spinner is for a reader who outruns the
37
+ // request and reaches the very top while it is in flight.
38
+ const PREFETCH_MIN_DISTANCE = exports.PREFETCH_MIN_DISTANCE = 1200;
39
+ const PREFETCH_SCREENS = exports.PREFETCH_SCREENS = 3;
40
+ // FlatList's own trigger distance, in screens: generous on purpose.
41
+ const END_REACHED_THRESHOLD = 4;
42
+ const HISTORY_PAGE_SIZE = exports.HISTORY_PAGE_SIZE = 100;
43
+ // Consecutive history pages that added nothing to the list before auto-paging
44
+ // stops (a reader scroll re-arms it).
45
+ const MAX_IDLE_AUTO_PAGES = exports.MAX_IDLE_AUTO_PAGES = 40;
46
+ // A request that settled without moving the oldest message or the cursor gets
47
+ // exactly one more try after this long.
48
+ const NO_PROGRESS_RETRY_MS = exports.NO_PROGRESS_RETRY_MS = 1000;
49
+ const AUTO_FILL_DELAY_MS = 100;
50
+ // After a page lands, the content size change it causes is not new content.
51
+ const GROWTH_GUARD_MS = 500;
52
+ // A window page that failed is not retried in a hot loop.
53
+ const WINDOW_RETRY_AFTER_FAILURE_MS = exports.WINDOW_RETRY_AFTER_FAILURE_MS = 3000;
54
+ // The scroll that centres the target must not be read as the reader scrolling
55
+ // toward an edge (it would page, or leave the window).
56
+ const WINDOW_SETTLE_MS = exports.WINDOW_SETTLE_MS = 600;
57
+ const WINDOW_EXIT_GRACE_MS = exports.WINDOW_EXIT_GRACE_MS = 1500;
58
+
59
+ /** The slice of the XMPP client the list needs. */
60
+
26
61
  const mainIdCache = new WeakMap();
27
62
  const mainMessageIdOf = m => {
28
63
  if (!m?.mainMessage) {
@@ -75,17 +110,21 @@ const MessageList = ({
75
110
  loading,
76
111
  isReply,
77
112
  activeMessage,
113
+ client,
78
114
  onReadBoundaryChange
79
115
  }) => {
80
116
  const room = (0, _reactRedux.useSelector)(state => state.rooms.rooms?.[roomJID]);
81
117
  const composing = room?.composing;
82
118
  const composingList = room?.composingList;
83
119
  const messages = room?.messages || EMPTY_LIST;
120
+ const historyComplete = room?.historyComplete;
84
121
  const theme = (0, _useTheme.useTheme)();
122
+ const t = (0, _useT.useT)();
123
+ const dispatch = (0, _reactRedux.useDispatch)();
124
+ const reduxStore = (0, _reactRedux.useStore)();
85
125
  const [isUserAtBottom, setIsUserAtBottom] = (0, _react.useState)(true);
86
126
  const [showNewMessageIndicator, setShowNewMessageIndicator] = (0, _react.useState)(false);
87
127
  const [isLoadingMore, setIsLoadingMore] = (0, _react.useState)(false);
88
- const [isScrollBlocked, setIsScrollBlocked] = (0, _react.useState)(false);
89
128
  // Count of messages that arrived while the user was scrolled up.
90
129
  // Renders as a badge on the scroll-to-bottom arrow so they know how
91
130
  // much they're missing without having to scroll to find out.
@@ -102,10 +141,57 @@ const MessageList = ({
102
141
  // to jump back to the bottom when a new message landed mid-scroll.
103
142
  const isUserAtBottomRef = (0, _react.useRef)(true);
104
143
  const hasUserScrolledRef = (0, _react.useRef)(false);
144
+ const mountedRef = (0, _react.useRef)(true);
145
+ (0, _react.useEffect)(() => () => {
146
+ mountedRef.current = false;
147
+ }, []);
105
148
  const flatListRef = (0, _react.useRef)(null);
149
+
150
+ // Viewport metrics, kept in refs: the loaders read them from timers and
151
+ // FlatList callbacks, never from a stale render closure.
152
+ const scrollOffsetRef = (0, _react.useRef)(0);
153
+ const contentHeightRef = (0, _react.useRef)(0);
154
+ const viewportHeightRef = (0, _react.useRef)(0);
155
+
156
+ // A short slice of archive around a far jump target, shown instead of the
157
+ // live list until the reader returns to the latest messages. Not for threads.
158
+ const jumpWindow = (0, _reactRedux.useSelector)(state => state.rooms.jumpWindow);
159
+ const joiningRoomJID = (0, _reactRedux.useSelector)(state => typeof state.rooms.joiningRoomJID === 'string' ? state.rooms.joiningRoomJID : null);
160
+ const windowActive = !isReply && jumpWindow?.roomJID === roomJID;
161
+ const windowActiveRef = (0, _react.useRef)(windowActive);
162
+ windowActiveRef.current = windowActive;
163
+ const loadingPropRef = (0, _react.useRef)(loading);
164
+ loadingPropRef.current = loading;
165
+
166
+ // A thread list also sees what a jump to one of its replies brought in (and
167
+ // any window on screen): those replies may be older than the live list.
168
+ const jumpThread = (0, _jumpThread.useJumpThread)();
169
+ const threadExtras = (0, _react.useMemo)(() => {
170
+ if (!isReply || !activeMessage) {
171
+ return null;
172
+ }
173
+ const fromWindow = jumpWindow?.roomJID === roomJID ? jumpWindow.messages : [];
174
+ const fromJump = jumpThread && jumpThread.roomJID === roomJID && jumpThread.parentId === String(activeMessage.id) ? jumpThread.replies : [];
175
+ if (fromWindow.length === 0 && fromJump.length === 0) {
176
+ return null;
177
+ }
178
+ return (0, _jumpThread.mergeById)(fromWindow, fromJump);
179
+ }, [isReply, activeMessage, jumpWindow, jumpThread, roomJID]);
180
+ const sourceMessages = (0, _react.useMemo)(() => {
181
+ if (windowActive && jumpWindow) {
182
+ return jumpWindow.messages;
183
+ }
184
+ if (threadExtras) {
185
+ return (0, _jumpThread.mergeById)(messages ?? [], threadExtras);
186
+ }
187
+ return messages;
188
+ }, [windowActive, jumpWindow, threadExtras, messages]);
106
189
  const addReplyMessages = (0, _react.useMemo)(() => {
190
+ // Index replies by their parent once instead of filtering the whole list
191
+ // per message. Only a message that has replies is copied, so the others
192
+ // keep their identity (memoized rows do not re-render).
107
193
  const repliesByParent = new Map();
108
- for (const mess of messages) {
194
+ for (const mess of sourceMessages) {
109
195
  if (!mess?.mainMessage || mess.isDeleted) {
110
196
  continue;
111
197
  }
@@ -121,16 +207,16 @@ const MessageList = ({
121
207
  }
122
208
  }
123
209
  if (repliesByParent.size === 0) {
124
- return messages;
210
+ return sourceMessages;
125
211
  }
126
- return messages.map(message => {
212
+ return sourceMessages.map(message => {
127
213
  const reply = repliesByParent.get(String(message.id));
128
214
  return reply ? {
129
215
  ...message,
130
216
  reply
131
217
  } : message;
132
218
  });
133
- }, [messages]);
219
+ }, [sourceMessages]);
134
220
  const memoizedMessages = (0, _react.useMemo)(() => {
135
221
  const nonDeletedMessages = addReplyMessages.filter(item => !item.isDeleted);
136
222
  let filtered;
@@ -147,8 +233,8 @@ const MessageList = ({
147
233
  // matching their date.toString() comparison, but redux state can
148
234
  // emit intermediate snapshots between dispatches, so the FlatList
149
235
  // briefly renders messages out-of-order until the final batch
150
- // settles. Sorting here makes each render a stable, ordered view —
151
- // even mid-stream — so the user sees them appear from oldest to
236
+ // settles. Sorting here makes each render a stable, ordered view,
237
+ // even mid-stream, so the user sees them appear from oldest to
152
238
  // newest with no swap animation.
153
239
  let sorted = filtered;
154
240
  for (let i = 1; i < filtered.length; i++) {
@@ -169,31 +255,460 @@ const MessageList = ({
169
255
  }
170
256
  return deduped;
171
257
  }, [addReplyMessages, isReply, roomJID, activeMessage]);
172
- const handleLoadMore = (0, _react.useCallback)(async () => {
173
- if (loading || isLoadingMore || !memoizedMessages.length || isScrollBlocked) {
258
+ const memoizedMessagesRef = (0, _react.useRef)(memoizedMessages);
259
+ memoizedMessagesRef.current = memoizedMessages;
260
+
261
+ // ---------------------------------------------------------------------
262
+ // History loading (live list)
263
+ // ---------------------------------------------------------------------
264
+
265
+ const isLoadingMoreRef = (0, _react.useRef)(false);
266
+ const growthGuardUntilRef = (0, _react.useRef)(0);
267
+ // The request key (oldest displayed message + cursor) last kicked off.
268
+ // Guards against a busy loop: a short conversation that never fills the
269
+ // viewport keeps asking, and a request that settles without moving anything
270
+ // would be asked again immediately, forever.
271
+ const lastRequestedKeyRef = (0, _react.useRef)(null);
272
+ const idleLoadsRef = (0, _react.useRef)(0);
273
+ const idleLoadsLenRef = (0, _react.useRef)(-1);
274
+ // Request keys that already got their one delayed retry.
275
+ const retriedKeysRef = (0, _react.useRef)(new Set());
276
+ const retryTimerRef = (0, _react.useRef)(null);
277
+ const autoFillTimerRef = (0, _react.useRef)(null);
278
+ const checkLoadMoreRef = (0, _react.useRef)(() => {});
279
+ const checkWindowLoadMoreRef = (0, _react.useRef)(() => {});
280
+
281
+ // The paging cursor moved (or regressed through another path) or the
282
+ // history completed: the repeat guard no longer describes the room, so a key
283
+ // seen before is allowed again. The idle page cap still bounds any loop.
284
+ const pagingCursor = (0, _reactRedux.useSelector)(state => state.rooms.rooms[roomJID]?.messageStats?.firstMessageTimestamp);
285
+ const roomHistoryComplete = (0, _reactRedux.useSelector)(state => Boolean(state.rooms.rooms[roomJID]?.historyComplete));
286
+ (0, _react.useEffect)(() => {
287
+ lastRequestedKeyRef.current = null;
288
+ retriedKeysRef.current = new Set();
289
+ }, [pagingCursor, roomHistoryComplete]);
290
+ (0, _react.useEffect)(() => {
291
+ // A new room's oldest message is unrelated to whatever the previous room
292
+ // last attempted: do not let a stale guard block its first load.
293
+ lastRequestedKeyRef.current = null;
294
+ retriedKeysRef.current = new Set();
295
+ idleLoadsRef.current = 0;
296
+ idleLoadsLenRef.current = -1;
297
+ if (retryTimerRef.current) {
298
+ clearTimeout(retryTimerRef.current);
299
+ retryTimerRef.current = null;
300
+ }
301
+ }, [roomJID]);
302
+ (0, _react.useEffect)(() => () => {
303
+ if (retryTimerRef.current) {
304
+ clearTimeout(retryTimerRef.current);
305
+ }
306
+ if (autoFillTimerRef.current) {
307
+ clearTimeout(autoFillTimerRef.current);
308
+ }
309
+ }, []);
310
+ const prefetchDistance = () => Math.max(PREFETCH_MIN_DISTANCE, viewportHeightRef.current * PREFETCH_SCREENS);
311
+ // Inverted list: offset 0 is the newest end; older history is at the far end.
312
+ const distanceToOlderEdge = () => contentHeightRef.current - viewportHeightRef.current - scrollOffsetRef.current;
313
+
314
+ // After a request settled, if the guard still holds the same key nothing
315
+ // moved (oldest id and cursor identical). Allow exactly one retry per key
316
+ // after ~1 s, then stay stopped until the cursor, historyComplete or the
317
+ // room changes (those clear the retried set).
318
+ const scheduleNoProgressRetry = (0, _react.useCallback)(key => {
319
+ if (retriedKeysRef.current.has(key)) {
320
+ return;
321
+ }
322
+ if (retryTimerRef.current) {
323
+ clearTimeout(retryTimerRef.current);
324
+ }
325
+ const forRoom = roomJID;
326
+ retryTimerRef.current = setTimeout(() => {
327
+ retryTimerRef.current = null;
328
+ if (forRoom !== roomJID || !mountedRef.current) {
329
+ return;
330
+ }
331
+ if (lastRequestedKeyRef.current !== key) {
332
+ return;
333
+ }
334
+ if (reduxStore.getState().rooms.rooms[forRoom]?.historyComplete) {
335
+ return;
336
+ }
337
+ retriedKeysRef.current.add(key);
338
+ lastRequestedKeyRef.current = null;
339
+ checkLoadMoreRef.current();
340
+ }, NO_PROGRESS_RETRY_MS);
341
+ }, [roomJID, reduxStore]);
342
+ const checkIfLoadMore = (0, _react.useCallback)((assumeNear = false) => {
343
+ // While a jump window is on screen the live list is not what the reader
344
+ // is looking at: no background prefetch of it, the window pages instead.
345
+ if (windowActiveRef.current) {
346
+ checkWindowLoadMoreRef.current();
347
+ return;
348
+ }
349
+ if (isLoadingMoreRef.current) {
174
350
  return;
175
351
  }
176
- const oldestMessage = memoizedMessages[0];
177
- if (!oldestMessage || !oldestMessage.id) {
352
+ const state = reduxStore.getState().rooms;
353
+ // A jump is already paging this room's history. A second request in
354
+ // flight at the same time makes the server's answers interleave and one
355
+ // of them time out, which the jump reads as the history being
356
+ // unreachable.
357
+ if (state.pendingJump?.roomJID === roomJID) {
178
358
  return;
179
359
  }
360
+ // Read the room at call time: a closure over an old render would act on
361
+ // an old cursor.
362
+ const room = state.rooms[roomJID];
363
+ if (!room || room.historyComplete) {
364
+ return;
365
+ }
366
+ if (!assumeNear && viewportHeightRef.current > 0 && distanceToOlderEdge() >= prefetchDistance()) {
367
+ return;
368
+ }
369
+ const displayed = memoizedMessagesRef.current;
370
+ const first = displayed.find(message => !String(message.id).startsWith('delimiter-new'));
371
+ // Continue from the server's own cursor (the oldest ROW the last page
372
+ // returned), never from the oldest DISPLAYED message alone: a page made
373
+ // only of receipts or reactions displays nothing, the oldest message
374
+ // does not change, and paging would stall with plenty of history left.
375
+ const serverCursor = room.messageStats?.firstMessageTimestamp;
376
+ const oldestDisplayed = first ? Number(first.id) : NaN;
377
+ let before;
378
+ if (Number.isFinite(oldestDisplayed)) {
379
+ before = typeof serverCursor === 'number' && serverCursor < oldestDisplayed ? serverCursor : oldestDisplayed;
380
+ } else if (typeof serverCursor === 'number' && Number.isFinite(serverCursor)) {
381
+ before = serverCursor;
382
+ } else {
383
+ return;
384
+ }
385
+
386
+ // A repeat of the same request (same oldest message AND same cursor) is
387
+ // what the guard stops; a page that only moved the cursor is progress.
388
+ const key = `${first ? first.id : 'none'}|${before}`;
389
+ if (key === lastRequestedKeyRef.current) {
390
+ return;
391
+ }
392
+
393
+ // Hard stop for a long run of pages that add nothing to the list (an
394
+ // archive that is almost all receipts): a reader scroll re-arms it.
395
+ if (displayed.length !== idleLoadsLenRef.current) {
396
+ idleLoadsLenRef.current = displayed.length;
397
+ idleLoadsRef.current = 0;
398
+ }
399
+ if (idleLoadsRef.current >= MAX_IDLE_AUTO_PAGES) {
400
+ return;
401
+ }
402
+ idleLoadsRef.current += 1;
403
+ isLoadingMoreRef.current = true;
404
+ lastRequestedKeyRef.current = key;
180
405
  setIsLoadingMore(true);
181
- setIsScrollBlocked(true);
406
+ let request;
182
407
  try {
183
- await loadMoreMessages(oldestMessage.roomJid || roomJID, 15, Number(oldestMessage.id));
408
+ request = Promise.resolve(loadMoreMessages(roomJID, HISTORY_PAGE_SIZE, before));
184
409
  } catch (error) {
185
- console.error(error);
410
+ request = Promise.reject(error);
411
+ }
412
+ request.catch(() => undefined).then(() => {
413
+ isLoadingMoreRef.current = false;
414
+ growthGuardUntilRef.current = Date.now() + GROWTH_GUARD_MS;
415
+ if (mountedRef.current) {
416
+ setIsLoadingMore(false);
417
+ }
418
+ scheduleNoProgressRetry(key);
419
+ // Keep the buffer above the reader topped up without waiting for the
420
+ // next scroll event: a reader still inside the prefetch distance
421
+ // once this page is in gets the next page right away, so a
422
+ // normal-speed scroll never catches up with the loader. Deferred so
423
+ // the new page has been rendered and measured first.
424
+ setTimeout(() => {
425
+ if (mountedRef.current) {
426
+ checkLoadMoreRef.current();
427
+ }
428
+ }, 80);
429
+ });
430
+ }, [loadMoreMessages, roomJID, reduxStore, scheduleNoProgressRetry]);
431
+ checkLoadMoreRef.current = checkIfLoadMore;
432
+
433
+ // A list that does not fill the viewport cannot scroll, so no scroll event
434
+ // ever asks for older history (a first page made of receipts displays one
435
+ // message and the archive behind it stays unreachable). Ask without one; the
436
+ // chain in checkIfLoadMore then pages until the viewport fills. Threads load
437
+ // through their own wrapper; a jump window pages itself.
438
+ const scheduleAutoFill = (0, _react.useCallback)(() => {
439
+ if (isReply || windowActiveRef.current || !roomJID) {
440
+ return;
441
+ }
442
+ if (autoFillTimerRef.current) {
443
+ clearTimeout(autoFillTimerRef.current);
444
+ }
445
+ autoFillTimerRef.current = setTimeout(() => {
446
+ autoFillTimerRef.current = null;
447
+ if (!mountedRef.current) {
448
+ return;
449
+ }
450
+ if (windowActiveRef.current || isLoadingMoreRef.current) {
451
+ return;
452
+ }
453
+ const state = reduxStore.getState().rooms;
454
+ if (state.pendingJump?.roomJID === roomJID) {
455
+ return;
456
+ }
457
+ if (state.rooms[roomJID]?.historyComplete) {
458
+ return;
459
+ }
460
+ // Not laid out yet: nothing to compare against.
461
+ if (viewportHeightRef.current <= 0 || contentHeightRef.current <= 0) {
462
+ return;
463
+ }
464
+ const unfilled = contentHeightRef.current <= viewportHeightRef.current || distanceToOlderEdge() < prefetchDistance();
465
+ if (!unfilled || !isUserAtBottomRef.current) {
466
+ return;
467
+ }
468
+ checkLoadMoreRef.current();
469
+ }, AUTO_FILL_DELAY_MS);
470
+ }, [isReply, roomJID, reduxStore]);
471
+ (0, _react.useEffect)(() => {
472
+ if (isReply || windowActive || loading || historyComplete) {
473
+ return;
474
+ }
475
+ scheduleAutoFill();
476
+ }, [roomJID, isReply, windowActive, loading, historyComplete, memoizedMessages.length, pagingCursor, scheduleAutoFill]);
477
+ const handleLoadMore = (0, _react.useCallback)(() => {
478
+ // FlatList says the reader is near the older end.
479
+ checkLoadMoreRef.current(true);
480
+ }, []);
481
+
482
+ // ---------------------------------------------------------------------
483
+ // Jump window (a far jump shows a short slice of the archive around it)
484
+ // ---------------------------------------------------------------------
485
+
486
+ const [windowLoading, setWindowLoading] = (0, _react.useState)(null);
487
+ const windowBusyRef = (0, _react.useRef)(null);
488
+ const windowFailedAtRef = (0, _react.useRef)({
489
+ older: 0,
490
+ newer: 0
491
+ });
492
+ const windowOpenedAtRef = (0, _react.useRef)(0);
493
+ const pendingExitScrollRef = (0, _react.useRef)(false);
494
+ const prevWindowActiveRef = (0, _react.useRef)(windowActive);
495
+ const exitWindow = (0, _react.useCallback)(() => {
496
+ if (!windowActiveRef.current) {
497
+ return;
498
+ }
499
+ isUserAtBottomRef.current = true;
500
+ hasUserScrolledRef.current = false;
501
+ pendingExitScrollRef.current = true;
502
+ setShowNewMessageIndicator(false);
503
+ setIsUserAtBottom(true);
504
+ setUnreadWhileScrolledUp(0);
505
+ newestSeenTsRef.current = null;
506
+ onReadBoundaryChange?.(null);
507
+ dispatch((0, _roomsSlice.clearJumpWindow)());
508
+ }, [dispatch, onReadBoundaryChange]);
509
+
510
+ // Back on the live list: land on its newest message.
511
+ (0, _react.useEffect)(() => {
512
+ const was = prevWindowActiveRef.current;
513
+ prevWindowActiveRef.current = windowActive;
514
+ if (windowActive || !was) {
515
+ return;
516
+ }
517
+ // A new jump is about to scroll somewhere else: leave the position to it.
518
+ if (reduxStore.getState().rooms.pendingJump?.roomJID === roomJID) {
519
+ return;
520
+ }
521
+ isUserAtBottomRef.current = true;
522
+ pendingExitScrollRef.current = false;
523
+ setIsUserAtBottom(true);
524
+ const toLiveEnd = () => flatListRef.current?.scrollToOffset({
525
+ offset: 0,
526
+ animated: false
527
+ });
528
+ toLiveEnd();
529
+ // The list swaps its data a frame later on a slow device: once more.
530
+ const timer = setTimeout(toLiveEnd, 50);
531
+ return () => clearTimeout(timer);
532
+ }, [windowActive, roomJID, reduxStore]);
533
+
534
+ // A window must not outlive the list that showed it.
535
+ (0, _react.useEffect)(() => () => {
536
+ if (windowActiveRef.current) {
537
+ dispatch((0, _roomsSlice.clearJumpWindow)());
538
+ }
539
+ }, [dispatch]);
540
+ (0, _react.useEffect)(() => {
541
+ if (!jumpWindow?.targetId || !windowActive) {
542
+ return;
543
+ }
544
+ windowOpenedAtRef.current = Date.now();
545
+ windowFailedAtRef.current = {
546
+ older: 0,
547
+ newer: 0
548
+ };
549
+ isUserAtBottomRef.current = false;
550
+ setIsUserAtBottom(false);
551
+ setShowNewMessageIndicator(false);
552
+ // Reading a window of old history is not reading the latest messages: from
553
+ // here on the read boundary is the newest live message the reader had
554
+ // reached, never "everything".
555
+ if (newestSeenTsRef.current === null) {
556
+ const newest = (messages ?? []).reduce((mx, m) => Math.max(mx, (0, _roomsSlice.msgSortableMs)(m)), 0);
557
+ if (newest > 0) {
558
+ newestSeenTsRef.current = newest;
559
+ onReadBoundaryChange?.(newest);
560
+ }
561
+ }
562
+ // A window that does not fill the viewport never scrolls, so nothing would
563
+ // ask for the next page: look once it has settled.
564
+ const timer = setTimeout(() => checkWindowLoadMoreRef.current(), WINDOW_SETTLE_MS + 100);
565
+ return () => clearTimeout(timer);
566
+ // eslint-disable-next-line react-hooks/exhaustive-deps
567
+ }, [jumpWindow?.targetId, windowActive]);
568
+ const loadWindowPage = (0, _react.useCallback)(async direction => {
569
+ const win = reduxStore.getState().rooms.jumpWindow;
570
+ if (!win || win.roomJID !== roomJID || !client) {
571
+ return;
572
+ }
573
+ if (windowBusyRef.current) {
574
+ return;
575
+ }
576
+ windowBusyRef.current = direction;
577
+ setWindowLoading(direction);
578
+ try {
579
+ const page = direction === 'older' ? await (0, _jumpWindow.loadOlderWindowPage)(client, win) : await (0, _jumpWindow.loadNewerWindowPage)(client, win);
580
+ const current = reduxStore.getState().rooms.jumpWindow;
581
+ // The reader left, or opened another window, while this was in flight.
582
+ if (!current || current.targetId !== win.targetId) {
583
+ return;
584
+ }
585
+ if (!page) {
586
+ windowFailedAtRef.current[direction] = Date.now();
587
+ return;
588
+ }
589
+ (0, _userResolver.requestSendersOf)(page.messages);
590
+ if ('olderCursor' in page) {
591
+ dispatch((0, _roomsSlice.prependJumpWindowMessages)({
592
+ roomJID,
593
+ ...page
594
+ }));
595
+ } else {
596
+ dispatch((0, _roomsSlice.appendJumpWindowMessages)({
597
+ roomJID,
598
+ ...page
599
+ }));
600
+ }
601
+ } catch {
602
+ windowFailedAtRef.current[direction] = Date.now();
186
603
  } finally {
604
+ windowBusyRef.current = null;
605
+ if (mountedRef.current) {
606
+ setWindowLoading(null);
607
+ }
187
608
  setTimeout(() => {
188
- setIsLoadingMore(false);
189
- setIsScrollBlocked(false);
190
- }, 500);
609
+ if (mountedRef.current) {
610
+ checkWindowLoadMoreRef.current();
611
+ }
612
+ }, 80);
613
+ }
614
+ }, [client, roomJID, dispatch, reduxStore]);
615
+ checkWindowLoadMoreRef.current = (fromUserScroll = false) => {
616
+ const win = reduxStore.getState().rooms.jumpWindow;
617
+ if (!win || win.roomJID !== roomJID) {
618
+ return;
619
+ }
620
+ const now = Date.now();
621
+ if (now - windowOpenedAtRef.current < WINDOW_SETTLE_MS) {
622
+ return;
623
+ }
624
+ // Not laid out yet: there is nothing to measure a distance against.
625
+ if (viewportHeightRef.current <= 0 || contentHeightRef.current <= 0) {
626
+ return;
627
+ }
628
+ const prefetch = prefetchDistance();
629
+ const olderDistance = distanceToOlderEdge();
630
+ const newerDistance = scrollOffsetRef.current;
631
+ if (win.hasOlder && olderDistance < prefetch && now - windowFailedAtRef.current.older > WINDOW_RETRY_AFTER_FAILURE_MS) {
632
+ loadWindowPage('older');
633
+ } else if (win.hasNewer && newerDistance < prefetch && now - windowFailedAtRef.current.newer > WINDOW_RETRY_AFTER_FAILURE_MS) {
634
+ loadWindowPage('newer');
635
+ } else if (!win.hasNewer && fromUserScroll && newerDistance <= 5 && now - windowOpenedAtRef.current > WINDOW_EXIT_GRACE_MS) {
636
+ // Nothing newer than this is left to load: that is the live tail.
637
+ exitWindow();
638
+ }
639
+ };
640
+ const handleStartReached = (0, _react.useCallback)(() => {
641
+ checkWindowLoadMoreRef.current();
642
+ }, []);
643
+
644
+ // A jump whose target is a thread reply opens the parent's thread (the main
645
+ // list never shows replies); the thread list then highlights the reply.
646
+ const resolveReply = (0, _react.useCallback)((jump, reply, nearby) => (0, _openThreadForJump.openThreadForJump)({
647
+ client,
648
+ dispatch: dispatch,
649
+ roomJID,
650
+ at: jump.at,
651
+ reply,
652
+ live: messages ?? [],
653
+ nearby
654
+ }), [client, dispatch, roomJID, messages]);
655
+ const fetchWindow = (0, _react.useCallback)(async jump => {
656
+ if (isReply || !client?.getHistoryWindow) {
657
+ return 'unavailable';
658
+ }
659
+ const result = await (0, _jumpWindow.loadJumpWindow)(client, roomJID, jump.ids, {
660
+ createdAt: jump.createdAt,
661
+ body: jump.body
662
+ });
663
+ if (result.status !== 'found') {
664
+ return result.status;
665
+ }
666
+ const target = result.window.messages.find(message => String(message.id) === result.window.targetId);
667
+ if (target && (0, _jumpThread.replyParentId)(target)) {
668
+ // Not a main-list message: the window is only used to learn what the
669
+ // reply belongs to; it is not put on screen.
670
+ const opened = await resolveReply(jump, target, result.window.messages).catch(() => false);
671
+ return opened ? 'found' : 'missing';
672
+ }
673
+ isUserAtBottomRef.current = false;
674
+ (0, _userResolver.requestSendersOf)(result.window.messages);
675
+ dispatch((0, _roomsSlice.setJumpWindow)(result.window));
676
+ return 'found';
677
+ }, [client, roomJID, isReply, dispatch, resolveReply]);
678
+ const fetchOlderPage = (0, _react.useCallback)(async (jid, before, max) => {
679
+ if (!client) {
680
+ return {
681
+ ok: false
682
+ };
683
+ }
684
+ const page = await client.getHistoryStanza(jid, max, before, undefined, {
685
+ source: 'active'
686
+ });
687
+ // The page is in the store by now, and so is the server's cursor for it
688
+ // (the <fin> handler writes it to messageStats).
689
+ const room = reduxStore.getState().rooms.rooms[jid];
690
+ return {
691
+ ok: page !== undefined,
692
+ cursor: room?.messageStats?.firstMessageTimestamp,
693
+ complete: Boolean(room?.historyComplete)
694
+ };
695
+ }, [client, reduxStore]);
696
+
697
+ // The own message that was just sent is on the live list: leave the window
698
+ // for it (the composer already clears it; this covers other send paths).
699
+ const lastNewestIdRef = (0, _react.useRef)(messages[messages.length - 1]?.id);
700
+ (0, _react.useEffect)(() => {
701
+ const newest = messages[messages.length - 1];
702
+ const changed = newest && String(newest.id) !== lastNewestIdRef.current;
703
+ lastNewestIdRef.current = newest ? String(newest.id) : undefined;
704
+ if (changed && windowActiveRef.current && (0, _isOwnMessage.isOwnMessage)(newest, user.xmppUsername || user.walletAddress)) {
705
+ exitWindow();
191
706
  }
192
- }, [memoizedMessages, loadMoreMessages, loading, isLoadingMore, isScrollBlocked, roomJID]);
707
+ }, [messages, user.xmppUsername, user.walletAddress, exitWindow]);
193
708
  const dataMessages = (0, _react.useMemo)(() => {
194
709
  const base = memoizedMessages.slice().reverse();
195
710
  const boundaryTs = newestSeenTsRef.current;
196
- if (isUserAtBottomRef.current || boundaryTs === null || unreadWhileScrolledUp === 0) {
711
+ if (windowActive || isUserAtBottomRef.current || boundaryTs === null || unreadWhileScrolledUp === 0) {
197
712
  return base;
198
713
  }
199
714
  let lastNewIndex = -1;
@@ -221,7 +736,58 @@ const MessageList = ({
221
736
  roomJid: roomJID
222
737
  });
223
738
  return withDivider;
224
- }, [memoizedMessages, isUserAtBottom, roomJID, unreadWhileScrolledUp]);
739
+ // eslint-disable-next-line react-hooks/exhaustive-deps
740
+ }, [memoizedMessages, isUserAtBottom, roomJID, unreadWhileScrolledUp, windowActive]);
741
+
742
+ // Jump-to-message (search hit, notification): scroll to the row, then pulse
743
+ // the bubble. The retry budget is for scrolling to a row the virtualised
744
+ // list has not measured yet.
745
+ const scrollRetryRef = (0, _react.useRef)(0);
746
+ const scrollToRow = (0, _react.useCallback)(index => {
747
+ scrollRetryRef.current = 0;
748
+ flatListRef.current?.scrollToIndex({
749
+ index,
750
+ viewPosition: 0.5,
751
+ animated: false
752
+ });
753
+ }, []);
754
+ const handleScrollToIndexFailed = (0, _react.useCallback)(info => {
755
+ const offset = (0, _jumpToMessage.scrollRetryOffset)(info, scrollRetryRef.current);
756
+ if (offset === null) {
757
+ return;
758
+ }
759
+ scrollRetryRef.current += 1;
760
+ flatListRef.current?.scrollToOffset({
761
+ offset,
762
+ animated: false
763
+ });
764
+ setTimeout(() => {
765
+ flatListRef.current?.scrollToIndex({
766
+ index: info.index,
767
+ viewPosition: 0.5,
768
+ animated: false
769
+ });
770
+ }, 120);
771
+ }, []);
772
+ (0, _useJumpToMessage.useJumpToMessage)({
773
+ roomJID,
774
+ messages: memoizedMessages,
775
+ listData: dataMessages,
776
+ scrollToIndex: scrollToRow,
777
+ onHighlight: _bubbleHighlight.setBubbleHighlight,
778
+ loadMoreMessages,
779
+ fetchOlderPage: client ? fetchOlderPage : undefined,
780
+ historyComplete,
781
+ isUserAtBottomRef,
782
+ jumpWindowActive: windowActive,
783
+ fetchWindow: isReply || !client ? undefined : fetchWindow,
784
+ scope: isReply && activeMessage ? {
785
+ threadId: String(activeMessage.id)
786
+ } : 'main',
787
+ allMessages: sourceMessages,
788
+ resolveReply: isReply ? undefined : (jump, reply) => resolveReply(jump, reply),
789
+ roomOpening: !isReply && (Boolean(loading) || joiningRoomJID === roomJID || sourceMessages.length === 0 && !historyComplete)
790
+ });
225
791
  const dateLabelIds = (0, _react.useMemo)(() => {
226
792
  const ids = new Set();
227
793
  let nextDay = null;
@@ -255,6 +821,9 @@ const MessageList = ({
255
821
  });
256
822
  }
257
823
  const showDateLabel = dateLabelIds.has(String(item.id));
824
+
825
+ // The jump highlight is drawn by the message bubble itself (see
826
+ // BubbleHighlight), so the row, its date label and its avatar stay put.
258
827
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_MessageContainer.MessageContainer, {
259
828
  CustomMessage: CustomMessage,
260
829
  CustomDaySeparator: CustomDaySeparator,
@@ -275,29 +844,58 @@ const MessageList = ({
275
844
  });
276
845
  }
277
846
  }, [flatListRef]);
278
- const handleContentSizeChange = (0, _react.useCallback)(() => {
279
- if (!isLoadingMore && flatListRef.current && isUserAtBottomRef.current) {
847
+ const handleContentSizeChange = (0, _react.useCallback)((_width, height) => {
848
+ if (typeof height === 'number' && height > 0) {
849
+ contentHeightRef.current = height;
850
+ }
851
+ if (windowActiveRef.current) {
852
+ // Reading a window of old history: never stick to the bottom.
853
+ checkWindowLoadMoreRef.current();
854
+ return;
855
+ }
856
+ const growing = isLoadingMoreRef.current || Date.now() < growthGuardUntilRef.current;
857
+ if (!growing && flatListRef.current && isUserAtBottomRef.current) {
280
858
  scrollToBottom();
281
- } else if (!isLoadingMore && hasUserScrolledRef.current) {
859
+ } else if (!growing && hasUserScrolledRef.current) {
282
860
  setShowNewMessageIndicator(true);
283
861
  }
284
- }, [scrollToBottom, isLoadingMore]);
862
+ scheduleAutoFill();
863
+ }, [scrollToBottom, scheduleAutoFill]);
285
864
  const handleScroll = (0, _react.useCallback)(event => {
286
- const contentOffset = event.nativeEvent.contentOffset.y;
865
+ const {
866
+ contentOffset,
867
+ contentSize,
868
+ layoutMeasurement
869
+ } = event.nativeEvent;
870
+ const offsetY = contentOffset.y;
871
+ scrollOffsetRef.current = offsetY;
872
+ if (contentSize?.height > 0) {
873
+ contentHeightRef.current = contentSize.height;
874
+ }
875
+ if (layoutMeasurement?.height > 0) {
876
+ viewportHeightRef.current = layoutMeasurement.height;
877
+ }
878
+ if (windowActiveRef.current) {
879
+ // Reading a window of old history: never "at the bottom", always the
880
+ // way back to the latest messages, and page both ways.
881
+ isUserAtBottomRef.current = false;
882
+ checkWindowLoadMoreRef.current(true);
883
+ return;
884
+ }
287
885
 
288
- // Don't force-dismiss the keyboard on every scroll event — any
886
+ // Don't force-dismiss the keyboard on every scroll event, any
289
887
  // touch on the message list used to close it, which made replying
290
888
  // to a long thread feel broken. Drag-to-dismiss still works via
291
889
  // FlatList's keyboardDismissMode="interactive" below.
292
890
 
293
- if (contentOffset > 150 && !hasUserScrolledRef.current) {
891
+ if (offsetY > 150 && !hasUserScrolledRef.current) {
294
892
  hasUserScrolledRef.current = true;
295
893
  }
296
- if (contentOffset < 150) {
894
+ if (offsetY < 150) {
297
895
  isUserAtBottomRef.current = true;
298
896
  setShowNewMessageIndicator(false);
299
897
  setIsUserAtBottom(true);
300
- // Back at the bottom — clear the unread-while-scrolled-up
898
+ // Back at the bottom, clear the unread-while-scrolled-up
301
899
  // counter so the badge disappears with the arrow.
302
900
  setUnreadWhileScrolledUp(0);
303
901
  newestSeenTsRef.current = null;
@@ -313,8 +911,8 @@ const MessageList = ({
313
911
  // arrives later is genuinely "new"; older history loaded by
314
912
  // back-pagination is < this and never counts.
315
913
  newestSeenTsRef.current = memoizedMessages.reduce((mx, m) => {
316
- const t = (0, _roomsSlice.msgSortableMs)(m);
317
- return t > mx ? t : mx;
914
+ const ts = (0, _roomsSlice.msgSortableMs)(m);
915
+ return ts > mx ? ts : mx;
318
916
  }, 0);
319
917
  onReadBoundaryChange?.(newestSeenTsRef.current);
320
918
  }
@@ -324,8 +922,11 @@ const MessageList = ({
324
922
 
325
923
  // Keep the badge in sync with messages that arrive while the user is
326
924
  // scrolled up. Count ONLY messages newer than the newest-seen snapshot
327
- // — so loading older history (back-pagination) doesn't inflate it.
925
+ //, so loading older history (back-pagination) doesn't inflate it.
328
926
  (0, _react.useEffect)(() => {
927
+ if (windowActiveRef.current) {
928
+ return;
929
+ }
329
930
  if (isUserAtBottomRef.current) {
330
931
  return;
331
932
  }
@@ -336,10 +937,17 @@ const MessageList = ({
336
937
  const count = memoizedMessages.reduce((n, m) => (0, _roomsSlice.msgSortableMs)(m) > since ? n + 1 : n, 0);
337
938
  setUnreadWhileScrolledUp(count);
338
939
  }, [memoizedMessages, isUserAtBottom]);
339
- const handleLayout = () => {
340
- isUserAtBottomRef.current = true;
341
- hasUserScrolledRef.current = false;
342
- setIsUserAtBottom(true);
940
+ const handleLayout = event => {
941
+ const height = event?.nativeEvent?.layout?.height;
942
+ if (typeof height === 'number' && height > 0) {
943
+ viewportHeightRef.current = height;
944
+ }
945
+ if (!windowActiveRef.current) {
946
+ isUserAtBottomRef.current = true;
947
+ hasUserScrolledRef.current = false;
948
+ setIsUserAtBottom(true);
949
+ scheduleAutoFill();
950
+ }
343
951
  };
344
952
  const handleNewMessageIndicatorPress = () => {
345
953
  isUserAtBottomRef.current = true;
@@ -400,20 +1008,69 @@ const MessageList = ({
400
1008
  initialNumToRender: 15,
401
1009
  maxToRenderPerBatch: 10,
402
1010
  windowSize: 7,
403
- onEndReached: handleLoadMore,
1011
+ onEndReached: windowActive ? handleStartReached : handleLoadMore,
1012
+ onStartReached: windowActive ? handleStartReached : undefined,
404
1013
  onScroll: handleScroll,
405
1014
  onContentSizeChange: handleContentSizeChange,
406
- onEndReachedThreshold: 0.1,
1015
+ onScrollToIndexFailed: handleScrollToIndexFailed
1016
+ // Prefetch well ahead of the viewport (screens, not pixels) so a
1017
+ // normal scroll finds older history already there.
1018
+ ,
1019
+ onEndReachedThreshold: END_REACHED_THRESHOLD,
1020
+ onStartReachedThreshold: END_REACHED_THRESHOLD
1021
+ // In a jump window newer messages arrive at the near (offset 0) end:
1022
+ // keep what the reader is looking at where it is instead of letting
1023
+ // the content slide. The live list stays unanchored on purpose, it
1024
+ // follows its own newest end (handleContentSizeChange).
1025
+ ,
1026
+ maintainVisibleContentPosition: windowActive ? {
1027
+ minIndexForVisible: 0
1028
+ } : undefined,
407
1029
  scrollEventThrottle: 16,
408
1030
  onLayout: handleLayout,
409
1031
  inverted: true,
410
1032
  keyboardShouldPersistTaps: "handled",
411
1033
  keyboardDismissMode: config?.keepKeyboardOpenOnScroll ? 'none' : 'interactive',
412
1034
  contentContainerStyle: styles.flatListContent,
413
- ListFooterComponent: loading && memoizedMessages.length > 15 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Loader.default, {
1035
+ ListFooterComponent: (loading || isLoadingMore) && !windowActive && memoizedMessages.length > 15 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Loader.default, {
414
1036
  color: config?.colors?.primary
415
1037
  }) : null
416
- }), showNewMessageIndicator && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
1038
+ }), windowActive && windowLoading === 'older' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
1039
+ testID: "history-loader-older",
1040
+ pointerEvents: "none",
1041
+ style: styles.loaderTop,
1042
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Loader.default, {
1043
+ size: 24,
1044
+ color: config?.colors?.primary
1045
+ })
1046
+ }), windowActive && windowLoading === 'newer' && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
1047
+ testID: "history-loader-newer",
1048
+ pointerEvents: "none",
1049
+ style: styles.loaderBottom,
1050
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Loader.default, {
1051
+ size: 24,
1052
+ color: config?.colors?.primary
1053
+ })
1054
+ }), windowActive ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
1055
+ testID: "jump-to-latest",
1056
+ accessibilityRole: "button",
1057
+ accessibilityLabel: t('action.jumpToLatest'),
1058
+ style: [styles.jumpToLatest, {
1059
+ backgroundColor: (0, _getIconColor.getIconColor)(config),
1060
+ shadowColor: theme.shadow
1061
+ }],
1062
+ onPress: exitWindow,
1063
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.ArowDownIcon, {
1064
+ color: theme.textOnPrimary,
1065
+ width: 18,
1066
+ height: 18
1067
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
1068
+ style: [styles.jumpToLatestText, {
1069
+ color: theme.textOnPrimary
1070
+ }],
1071
+ children: t('action.jumpToLatest')
1072
+ })]
1073
+ }) : showNewMessageIndicator && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
417
1074
  style: [styles.newMessageIndicator, {
418
1075
  backgroundColor: (0, _getIconColor.getIconColor)(config),
419
1076
  shadowColor: theme.shadow
@@ -476,6 +1133,46 @@ const styles = _reactNative.StyleSheet.create({
476
1133
  width: '100%',
477
1134
  height: '100%'
478
1135
  },
1136
+ // Float over the list so showing or hiding them never moves the messages.
1137
+ loaderTop: {
1138
+ position: 'absolute',
1139
+ top: 8,
1140
+ left: 0,
1141
+ right: 0,
1142
+ alignItems: 'center',
1143
+ zIndex: 2
1144
+ },
1145
+ loaderBottom: {
1146
+ position: 'absolute',
1147
+ bottom: 8,
1148
+ left: 0,
1149
+ right: 0,
1150
+ alignItems: 'center',
1151
+ zIndex: 2
1152
+ },
1153
+ jumpToLatest: {
1154
+ position: 'absolute',
1155
+ bottom: 20,
1156
+ right: 20,
1157
+ height: 40,
1158
+ paddingHorizontal: 14,
1159
+ borderRadius: 20,
1160
+ flexDirection: 'row',
1161
+ alignItems: 'center',
1162
+ justifyContent: 'center',
1163
+ gap: 6,
1164
+ shadowOffset: {
1165
+ width: 0,
1166
+ height: 2
1167
+ },
1168
+ shadowOpacity: 0.2,
1169
+ shadowRadius: 3,
1170
+ elevation: 4
1171
+ },
1172
+ jumpToLatestText: {
1173
+ fontSize: 13,
1174
+ fontWeight: '600'
1175
+ },
479
1176
  newMessageIndicator: {
480
1177
  position: 'absolute',
481
1178
  width: 40,