@ethora/chat-component-rn 26.5.16 → 26.5.18

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 (215) hide show
  1. package/lib/commonjs/assets/EmptyChatIllustration.js +106 -0
  2. package/lib/commonjs/assets/EmptyChatIllustration.js.map +1 -0
  3. package/lib/commonjs/assets/icons.js +13 -2
  4. package/lib/commonjs/assets/icons.js.map +1 -1
  5. package/lib/commonjs/components/DropdownMenu/DropdownMenu.js +2 -1
  6. package/lib/commonjs/components/DropdownMenu/DropdownMenu.js.map +1 -1
  7. package/lib/commonjs/components/MainComponents/ChatHeader.js +2 -1
  8. package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
  9. package/lib/commonjs/components/MainComponents/ChatRoom.js +5 -2
  10. package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
  11. package/lib/commonjs/components/MainComponents/ChooseChatMessage.js +9 -2
  12. package/lib/commonjs/components/MainComponents/ChooseChatMessage.js.map +1 -1
  13. package/lib/commonjs/components/MainComponents/EditWrapper.js +12 -4
  14. package/lib/commonjs/components/MainComponents/EditWrapper.js.map +1 -1
  15. package/lib/commonjs/components/MainComponents/MessageList.js +2 -1
  16. package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
  17. package/lib/commonjs/components/MainComponents/NoMessagesPlaceholder.js +11 -3
  18. package/lib/commonjs/components/MainComponents/NoMessagesPlaceholder.js.map +1 -1
  19. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js +12 -7
  20. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  21. package/lib/commonjs/components/MainComponents/ReduxWrapper.js +4 -0
  22. package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
  23. package/lib/commonjs/components/MainComponents/RoomList.js +2 -1
  24. package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
  25. package/lib/commonjs/components/MessageBubble/Avatar.js +16 -7
  26. package/lib/commonjs/components/MessageBubble/Avatar.js.map +1 -1
  27. package/lib/commonjs/components/MessageBubble/Message.js +16 -1
  28. package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
  29. package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js +9 -0
  30. package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
  31. package/lib/commonjs/components/styled/Button.js +4 -2
  32. package/lib/commonjs/components/styled/Button.js.map +1 -1
  33. package/lib/commonjs/components/styled/DateLabel.js +12 -4
  34. package/lib/commonjs/components/styled/DateLabel.js.map +1 -1
  35. package/lib/commonjs/components/styled/SendInput.js +4 -3
  36. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  37. package/lib/commonjs/context/xmppProvider.js +12 -1
  38. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  39. package/lib/commonjs/helpers/getAvatarColor.js +33 -0
  40. package/lib/commonjs/helpers/getAvatarColor.js.map +1 -0
  41. package/lib/commonjs/helpers/getDateLabelColor.js +9 -0
  42. package/lib/commonjs/helpers/getDateLabelColor.js.map +1 -0
  43. package/lib/commonjs/helpers/getIconColor.js +9 -0
  44. package/lib/commonjs/helpers/getIconColor.js.map +1 -0
  45. package/lib/commonjs/helpers/getSenderNameColor.js +9 -0
  46. package/lib/commonjs/helpers/getSenderNameColor.js.map +1 -0
  47. package/lib/commonjs/helpers/historyPreloadScheduler.js +118 -113
  48. package/lib/commonjs/helpers/historyPreloadScheduler.js.map +1 -1
  49. package/lib/commonjs/hooks/useChatFonts.js +137 -0
  50. package/lib/commonjs/hooks/useChatFonts.js.map +1 -0
  51. package/lib/commonjs/hooks/useSendMessage.js +72 -22
  52. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  53. package/lib/commonjs/hooks/useUnreadMessagesCounter.js +4 -2
  54. package/lib/commonjs/hooks/useUnreadMessagesCounter.js.map +1 -1
  55. package/lib/commonjs/main.js +7 -0
  56. package/lib/commonjs/main.js.map +1 -1
  57. package/lib/commonjs/networking/outboundQueue.js +22 -4
  58. package/lib/commonjs/networking/outboundQueue.js.map +1 -1
  59. package/lib/commonjs/networking/xmppClient.js +50 -0
  60. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  61. package/lib/commonjs/roomStore/Middleware/newMessageMidlleware.js +22 -0
  62. package/lib/commonjs/roomStore/Middleware/newMessageMidlleware.js.map +1 -1
  63. package/lib/commonjs/roomStore/roomsSlice.js +22 -2
  64. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  65. package/lib/module/assets/EmptyChatIllustration.js +99 -0
  66. package/lib/module/assets/EmptyChatIllustration.js.map +1 -0
  67. package/lib/module/assets/icons.js +13 -2
  68. package/lib/module/assets/icons.js.map +1 -1
  69. package/lib/module/components/DropdownMenu/DropdownMenu.js +2 -1
  70. package/lib/module/components/DropdownMenu/DropdownMenu.js.map +1 -1
  71. package/lib/module/components/MainComponents/ChatHeader.js +2 -1
  72. package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
  73. package/lib/module/components/MainComponents/ChatRoom.js +5 -2
  74. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  75. package/lib/module/components/MainComponents/ChooseChatMessage.js +9 -2
  76. package/lib/module/components/MainComponents/ChooseChatMessage.js.map +1 -1
  77. package/lib/module/components/MainComponents/EditWrapper.js +12 -4
  78. package/lib/module/components/MainComponents/EditWrapper.js.map +1 -1
  79. package/lib/module/components/MainComponents/MessageList.js +2 -1
  80. package/lib/module/components/MainComponents/MessageList.js.map +1 -1
  81. package/lib/module/components/MainComponents/NoMessagesPlaceholder.js +11 -3
  82. package/lib/module/components/MainComponents/NoMessagesPlaceholder.js.map +1 -1
  83. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js +12 -7
  84. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  85. package/lib/module/components/MainComponents/ReduxWrapper.js +4 -0
  86. package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
  87. package/lib/module/components/MainComponents/RoomList.js +2 -1
  88. package/lib/module/components/MainComponents/RoomList.js.map +1 -1
  89. package/lib/module/components/MessageBubble/Avatar.js +16 -7
  90. package/lib/module/components/MessageBubble/Avatar.js.map +1 -1
  91. package/lib/module/components/MessageBubble/Message.js +16 -1
  92. package/lib/module/components/MessageBubble/Message.js.map +1 -1
  93. package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js +9 -0
  94. package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
  95. package/lib/module/components/styled/Button.js +4 -2
  96. package/lib/module/components/styled/Button.js.map +1 -1
  97. package/lib/module/components/styled/DateLabel.js +12 -4
  98. package/lib/module/components/styled/DateLabel.js.map +1 -1
  99. package/lib/module/components/styled/SendInput.js +4 -3
  100. package/lib/module/components/styled/SendInput.js.map +1 -1
  101. package/lib/module/context/xmppProvider.js +13 -2
  102. package/lib/module/context/xmppProvider.js.map +1 -1
  103. package/lib/module/helpers/getAvatarColor.js +28 -0
  104. package/lib/module/helpers/getAvatarColor.js.map +1 -0
  105. package/lib/module/helpers/getDateLabelColor.js +4 -0
  106. package/lib/module/helpers/getDateLabelColor.js.map +1 -0
  107. package/lib/module/helpers/getIconColor.js +4 -0
  108. package/lib/module/helpers/getIconColor.js.map +1 -0
  109. package/lib/module/helpers/getSenderNameColor.js +4 -0
  110. package/lib/module/helpers/getSenderNameColor.js.map +1 -0
  111. package/lib/module/helpers/historyPreloadScheduler.js +119 -114
  112. package/lib/module/helpers/historyPreloadScheduler.js.map +1 -1
  113. package/lib/module/hooks/useChatFonts.js +132 -0
  114. package/lib/module/hooks/useChatFonts.js.map +1 -0
  115. package/lib/module/hooks/useSendMessage.js +72 -22
  116. package/lib/module/hooks/useSendMessage.js.map +1 -1
  117. package/lib/module/hooks/useUnreadMessagesCounter.js +4 -2
  118. package/lib/module/hooks/useUnreadMessagesCounter.js.map +1 -1
  119. package/lib/module/main.js +2 -0
  120. package/lib/module/main.js.map +1 -1
  121. package/lib/module/networking/outboundQueue.js +21 -4
  122. package/lib/module/networking/outboundQueue.js.map +1 -1
  123. package/lib/module/networking/xmppClient.js +50 -0
  124. package/lib/module/networking/xmppClient.js.map +1 -1
  125. package/lib/module/roomStore/Middleware/newMessageMidlleware.js +22 -0
  126. package/lib/module/roomStore/Middleware/newMessageMidlleware.js.map +1 -1
  127. package/lib/module/roomStore/roomsSlice.js +20 -1
  128. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  129. package/lib/typescript/assets/EmptyChatIllustration.d.ts +10 -0
  130. package/lib/typescript/assets/EmptyChatIllustration.d.ts.map +1 -0
  131. package/lib/typescript/assets/icons.d.ts +3 -12
  132. package/lib/typescript/assets/icons.d.ts.map +1 -1
  133. package/lib/typescript/components/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  134. package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
  135. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  136. package/lib/typescript/components/MainComponents/ChooseChatMessage.d.ts.map +1 -1
  137. package/lib/typescript/components/MainComponents/EditWrapper.d.ts +5 -1
  138. package/lib/typescript/components/MainComponents/EditWrapper.d.ts.map +1 -1
  139. package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
  140. package/lib/typescript/components/MainComponents/NoMessagesPlaceholder.d.ts.map +1 -1
  141. package/lib/typescript/components/MainComponents/ProfileImagePlaceholder.d.ts.map +1 -1
  142. package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
  143. package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
  144. package/lib/typescript/components/MessageBubble/Avatar.d.ts.map +1 -1
  145. package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
  146. package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts.map +1 -1
  147. package/lib/typescript/components/styled/Button.d.ts +1 -0
  148. package/lib/typescript/components/styled/Button.d.ts.map +1 -1
  149. package/lib/typescript/components/styled/DateLabel.d.ts +9 -8
  150. package/lib/typescript/components/styled/DateLabel.d.ts.map +1 -1
  151. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  152. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  153. package/lib/typescript/helpers/getAvatarColor.d.ts +7 -0
  154. package/lib/typescript/helpers/getAvatarColor.d.ts.map +1 -0
  155. package/lib/typescript/helpers/getDateLabelColor.d.ts +8 -0
  156. package/lib/typescript/helpers/getDateLabelColor.d.ts.map +1 -0
  157. package/lib/typescript/helpers/getIconColor.d.ts +8 -0
  158. package/lib/typescript/helpers/getIconColor.d.ts.map +1 -0
  159. package/lib/typescript/helpers/getSenderNameColor.d.ts +8 -0
  160. package/lib/typescript/helpers/getSenderNameColor.d.ts.map +1 -0
  161. package/lib/typescript/helpers/historyPreloadScheduler.d.ts.map +1 -1
  162. package/lib/typescript/hooks/useChatFonts.d.ts +23 -0
  163. package/lib/typescript/hooks/useChatFonts.d.ts.map +1 -0
  164. package/lib/typescript/hooks/useSendMessage.d.ts +1 -1
  165. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  166. package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts +1 -0
  167. package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts.map +1 -1
  168. package/lib/typescript/main.d.ts +2 -1
  169. package/lib/typescript/main.d.ts.map +1 -1
  170. package/lib/typescript/networking/outboundQueue.d.ts +16 -1
  171. package/lib/typescript/networking/outboundQueue.d.ts.map +1 -1
  172. package/lib/typescript/networking/xmppClient.d.ts +3 -0
  173. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  174. package/lib/typescript/roomStore/Middleware/newMessageMidlleware.d.ts.map +1 -1
  175. package/lib/typescript/roomStore/roomsSlice.d.ts +3 -1
  176. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  177. package/lib/typescript/types/models/message.model.d.ts +1 -0
  178. package/lib/typescript/types/models/message.model.d.ts.map +1 -1
  179. package/lib/typescript/types/types.d.ts +53 -0
  180. package/lib/typescript/types/types.d.ts.map +1 -1
  181. package/package.json +5 -1
  182. package/src/assets/EmptyChatIllustration.tsx +49 -0
  183. package/src/assets/icons.tsx +64 -81
  184. package/src/components/DropdownMenu/DropdownMenu.tsx +2 -1
  185. package/src/components/MainComponents/ChatHeader.tsx +2 -1
  186. package/src/components/MainComponents/ChatRoom.tsx +5 -2
  187. package/src/components/MainComponents/ChooseChatMessage.tsx +5 -2
  188. package/src/components/MainComponents/EditWrapper.tsx +9 -6
  189. package/src/components/MainComponents/MessageList.tsx +2 -1
  190. package/src/components/MainComponents/NoMessagesPlaceholder.tsx +4 -1
  191. package/src/components/MainComponents/ProfileImagePlaceholder.tsx +14 -7
  192. package/src/components/MainComponents/ReduxWrapper.tsx +4 -0
  193. package/src/components/MainComponents/RoomList.tsx +2 -1
  194. package/src/components/MessageBubble/Avatar.tsx +18 -9
  195. package/src/components/MessageBubble/Message.tsx +16 -1
  196. package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +6 -0
  197. package/src/components/styled/Button.tsx +5 -1
  198. package/src/components/styled/DateLabel.tsx +10 -7
  199. package/src/components/styled/SendInput.tsx +4 -3
  200. package/src/context/xmppProvider.tsx +11 -1
  201. package/src/helpers/getAvatarColor.ts +31 -0
  202. package/src/helpers/getDateLabelColor.ts +3 -0
  203. package/src/helpers/getIconColor.ts +3 -0
  204. package/src/helpers/getSenderNameColor.ts +3 -0
  205. package/src/helpers/historyPreloadScheduler.ts +7 -1
  206. package/src/hooks/useChatFonts.ts +153 -0
  207. package/src/hooks/useSendMessage.tsx +101 -58
  208. package/src/hooks/useUnreadMessagesCounter.ts +5 -2
  209. package/src/main.ts +4 -0
  210. package/src/networking/outboundQueue.ts +25 -4
  211. package/src/networking/xmppClient.ts +47 -0
  212. package/src/roomStore/Middleware/newMessageMidlleware.tsx +25 -0
  213. package/src/roomStore/roomsSlice.ts +26 -1
  214. package/src/types/models/message.model.ts +3 -0
  215. package/src/types/types.ts +59 -1
@@ -98,132 +98,137 @@ const runHistoryPreloadScheduler = async options => {
98
98
  if (signal?.aborted) {
99
99
  return;
100
100
  }
101
- const state = _roomStore.store.getState();
102
- const rooms = state.rooms.rooms || {};
103
- const defaultSet = new Set(defaultRoomJids);
104
- const sortedQueue = Object.entries(rooms).map(([jid, room]) => ({
105
- jid,
106
- priority: getRoomPriority(jid, room, selectedRoomJid, defaultSet),
107
- activityScore: getRoomLastActivityScore(room),
108
- attempts: 0,
109
- readyAt: Date.now()
110
- })).sort((a, b) => {
111
- if (a.priority !== b.priority) {
112
- return a.priority - b.priority;
113
- }
114
- if (a.activityScore !== b.activityScore) {
115
- return b.activityScore - a.activityScore;
116
- }
117
- return a.jid.localeCompare(b.jid);
118
- });
119
- const queue = roomLimit && roomLimit > 0 ? sortedQueue.slice(0, roomLimit) : sortedQueue;
120
- const inFlightByRoom = new Map();
121
- let consecutiveErrorCount = 0;
122
- while (queue.length > 0) {
123
- if (signal?.aborted) {
124
- return;
125
- }
126
- if (!client.isActiveRoomGateOpen()) {
127
- await sleep(80);
128
- continue;
129
- }
130
- if (shouldPauseForVisibility()) {
131
- await sleep(250);
132
- continue;
133
- }
134
- const now = Date.now();
135
- const readyItems = queue.filter(item => item.readyAt <= now && !inFlightByRoom.has(item.jid));
136
- if (readyItems.length === 0) {
137
- await sleep(60);
138
- continue;
139
- }
140
- const batch = readyItems.slice(0, Math.max(1, concurrency));
141
-
142
- // Snapshot each room's historyPreloadState BEFORE marking the
143
- // batch as 'loading'. Without this snapshot the per-task
144
- // `currentRoom.historyPreloadState === 'done'` skip check below
145
- // is dead — the dispatch immediately overwrites 'done' with
146
- // 'loading', so the task never sees the original value and
147
- // always re-fetches.
148
- const preBatchPreloadStateByJid = new Map(batch.map(item => [item.jid, _roomStore.store.getState().rooms.rooms[item.jid]?.historyPreloadState]));
149
- _roomStore.store.dispatch((0, _roomsSlice.applyRoomsPreloadBatch)({
150
- rooms: batch.map(item => ({
151
- jid: item.jid,
152
- historyPreloadState: 'loading'
153
- }))
154
- }));
155
- await Promise.all(batch.map(async item => {
156
- const queueIndex = queue.findIndex(queued => queued.jid === item.jid);
157
- if (queueIndex !== -1) {
158
- queue.splice(queueIndex, 1);
101
+ _roomStore.store.dispatch((0, _roomsSlice.setUnreadSyncing)(true));
102
+ try {
103
+ const state = _roomStore.store.getState();
104
+ const rooms = state.rooms.rooms || {};
105
+ const defaultSet = new Set(defaultRoomJids);
106
+ const sortedQueue = Object.entries(rooms).map(([jid, room]) => ({
107
+ jid,
108
+ priority: getRoomPriority(jid, room, selectedRoomJid, defaultSet),
109
+ activityScore: getRoomLastActivityScore(room),
110
+ attempts: 0,
111
+ readyAt: Date.now()
112
+ })).sort((a, b) => {
113
+ if (a.priority !== b.priority) {
114
+ return a.priority - b.priority;
115
+ }
116
+ if (a.activityScore !== b.activityScore) {
117
+ return b.activityScore - a.activityScore;
118
+ }
119
+ return a.jid.localeCompare(b.jid);
120
+ });
121
+ const queue = roomLimit && roomLimit > 0 ? sortedQueue.slice(0, roomLimit) : sortedQueue;
122
+ const inFlightByRoom = new Map();
123
+ let consecutiveErrorCount = 0;
124
+ while (queue.length > 0) {
125
+ if (signal?.aborted) {
126
+ return;
127
+ }
128
+ if (!client.isActiveRoomGateOpen()) {
129
+ await sleep(80);
130
+ continue;
131
+ }
132
+ if (shouldPauseForVisibility()) {
133
+ await sleep(250);
134
+ continue;
159
135
  }
160
- const task = (async () => {
161
- const currentRoom = _roomStore.store.getState().rooms.rooms[item.jid];
162
- const preState = preBatchPreloadStateByJid.get(item.jid);
163
- if (!currentRoom || !forceReload && preState === 'done') {
164
- _roomStore.store.dispatch((0, _roomsSlice.applyRoomsPreloadBatch)({
165
- rooms: [{
166
- jid: item.jid,
167
- historyPreloadState: 'done'
168
- }]
169
- }));
170
- return;
136
+ const now = Date.now();
137
+ const readyItems = queue.filter(item => item.readyAt <= now && !inFlightByRoom.has(item.jid));
138
+ if (readyItems.length === 0) {
139
+ await sleep(60);
140
+ continue;
141
+ }
142
+ const batch = readyItems.slice(0, Math.max(1, concurrency));
143
+
144
+ // Snapshot each room's historyPreloadState BEFORE marking the
145
+ // batch as 'loading'. Without this snapshot the per-task
146
+ // `currentRoom.historyPreloadState === 'done'` skip check below
147
+ // is dead — the dispatch immediately overwrites 'done' with
148
+ // 'loading', so the task never sees the original value and
149
+ // always re-fetches.
150
+ const preBatchPreloadStateByJid = new Map(batch.map(item => [item.jid, _roomStore.store.getState().rooms.rooms[item.jid]?.historyPreloadState]));
151
+ _roomStore.store.dispatch((0, _roomsSlice.applyRoomsPreloadBatch)({
152
+ rooms: batch.map(item => ({
153
+ jid: item.jid,
154
+ historyPreloadState: 'loading'
155
+ }))
156
+ }));
157
+ await Promise.all(batch.map(async item => {
158
+ const queueIndex = queue.findIndex(queued => queued.jid === item.jid);
159
+ if (queueIndex !== -1) {
160
+ queue.splice(queueIndex, 1);
171
161
  }
172
- try {
173
- const fetchedMessages = await client.getHistoryStanza(item.jid, pageSize, undefined, undefined, {
174
- coalesceRoom: true,
175
- skipIfPreloaded: !forceReload,
176
- source: 'background'
177
- });
178
- if (signal?.aborted) {
162
+ const task = (async () => {
163
+ const currentRoom = _roomStore.store.getState().rooms.rooms[item.jid];
164
+ const preState = preBatchPreloadStateByJid.get(item.jid);
165
+ if (!currentRoom || !forceReload && preState === 'done') {
166
+ _roomStore.store.dispatch((0, _roomsSlice.applyRoomsPreloadBatch)({
167
+ rooms: [{
168
+ jid: item.jid,
169
+ historyPreloadState: 'done'
170
+ }]
171
+ }));
179
172
  return;
180
173
  }
181
- if (typeof fetchedMessages === 'undefined') {
182
- throw new Error('history_timeout');
183
- }
184
- const nextRoom = _roomStore.store.getState().rooms.rooms[item.jid];
185
- const unreadCapped = computeUnreadCapped(nextRoom, fetchedMessages || [], pageSize);
186
- _roomStore.store.dispatch((0, _roomsSlice.applyRoomsPreloadBatch)({
187
- rooms: [{
188
- jid: item.jid,
189
- messages: fetchedMessages || [],
190
- unreadCapped,
191
- historyPreloadState: 'done'
192
- }]
193
- }));
194
- consecutiveErrorCount = 0;
195
- } catch {
196
- const retries = item.attempts + 1;
197
- const canRetry = retries <= retryLimit;
198
- if (canRetry) {
199
- const jitter = Math.floor(Math.random() * 120);
200
- const backoff = Math.min(1600, 240 * 2 ** item.attempts) + jitter;
201
- queue.push({
202
- ...item,
203
- attempts: retries,
204
- readyAt: Date.now() + backoff
174
+ try {
175
+ const fetchedMessages = await client.getHistoryStanza(item.jid, pageSize, undefined, undefined, {
176
+ coalesceRoom: true,
177
+ skipIfPreloaded: !forceReload,
178
+ source: 'background'
205
179
  });
206
- } else {
180
+ if (signal?.aborted) {
181
+ return;
182
+ }
183
+ if (typeof fetchedMessages === 'undefined') {
184
+ throw new Error('history_timeout');
185
+ }
186
+ const nextRoom = _roomStore.store.getState().rooms.rooms[item.jid];
187
+ const unreadCapped = computeUnreadCapped(nextRoom, fetchedMessages || [], pageSize);
207
188
  _roomStore.store.dispatch((0, _roomsSlice.applyRoomsPreloadBatch)({
208
189
  rooms: [{
209
190
  jid: item.jid,
210
- historyPreloadState: 'error'
191
+ messages: fetchedMessages || [],
192
+ unreadCapped,
193
+ historyPreloadState: 'done'
211
194
  }]
212
195
  }));
213
- }
214
- consecutiveErrorCount += 1;
215
- if (consecutiveErrorCount >= 3) {
216
- await sleep(300);
217
196
  consecutiveErrorCount = 0;
197
+ } catch {
198
+ const retries = item.attempts + 1;
199
+ const canRetry = retries <= retryLimit;
200
+ if (canRetry) {
201
+ const jitter = Math.floor(Math.random() * 120);
202
+ const backoff = Math.min(1600, 240 * 2 ** item.attempts) + jitter;
203
+ queue.push({
204
+ ...item,
205
+ attempts: retries,
206
+ readyAt: Date.now() + backoff
207
+ });
208
+ } else {
209
+ _roomStore.store.dispatch((0, _roomsSlice.applyRoomsPreloadBatch)({
210
+ rooms: [{
211
+ jid: item.jid,
212
+ historyPreloadState: 'error'
213
+ }]
214
+ }));
215
+ }
216
+ consecutiveErrorCount += 1;
217
+ if (consecutiveErrorCount >= 3) {
218
+ await sleep(300);
219
+ consecutiveErrorCount = 0;
220
+ }
218
221
  }
219
- }
220
- })();
221
- inFlightByRoom.set(item.jid, task);
222
- await task.finally(() => inFlightByRoom.delete(item.jid));
223
- }));
222
+ })();
223
+ inFlightByRoom.set(item.jid, task);
224
+ await task.finally(() => inFlightByRoom.delete(item.jid));
225
+ }));
224
226
 
225
- // Yield to JS event loop (no requestIdleCallback in RN).
226
- await new Promise(r => setTimeout(r, 0));
227
+ // Yield to JS event loop (no requestIdleCallback in RN).
228
+ await new Promise(r => setTimeout(r, 0));
229
+ }
230
+ } finally {
231
+ _roomStore.store.dispatch((0, _roomsSlice.setUnreadSyncing)(false));
227
232
  }
228
233
  };
229
234
  exports.runHistoryPreloadScheduler = runHistoryPreloadScheduler;
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_roomStore","_roomsSlice","DEFAULT_CONCURRENCY","DEFAULT_PAGE_SIZE","DEFAULT_RETRY_LIMIT","sleep","ms","Promise","resolve","setTimeout","messageTimestamp","m","t","timestamp","Number","isFinite","id","getRoomLastActivityScore","room","messages","length","reduce","max","Math","computeUnreadCapped","pageSize","historyComplete","countable","filter","msg","pending","lastViewed","lastViewedTimestamp","oldestTs","minTs","ts","min","MAX_SAFE_INTEGER","getRoomPriority","jid","_room","selectedRoomJid","defaultRoomJids","has","shouldPauseForVisibility","AppState","currentState","runHistoryPreloadScheduler","options","client","signal","concurrency","retryLimit","roomLimit","forceReload","aborted","state","store","getState","rooms","defaultSet","Set","sortedQueue","Object","entries","map","priority","activityScore","attempts","readyAt","Date","now","sort","a","b","localeCompare","queue","slice","inFlightByRoom","Map","consecutiveErrorCount","isActiveRoomGateOpen","readyItems","item","batch","preBatchPreloadStateByJid","historyPreloadState","dispatch","applyRoomsPreloadBatch","all","queueIndex","findIndex","queued","splice","task","currentRoom","preState","get","fetchedMessages","getHistoryStanza","undefined","coalesceRoom","skipIfPreloaded","source","Error","nextRoom","unreadCapped","retries","canRetry","jitter","floor","random","backoff","push","set","finally","delete","r","exports","_default","default"],"sourceRoot":"../../../src","sources":["helpers/historyPreloadScheduler.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_roomStore","_roomsSlice","DEFAULT_CONCURRENCY","DEFAULT_PAGE_SIZE","DEFAULT_RETRY_LIMIT","sleep","ms","Promise","resolve","setTimeout","messageTimestamp","m","t","timestamp","Number","isFinite","id","getRoomLastActivityScore","room","messages","length","reduce","max","Math","computeUnreadCapped","pageSize","historyComplete","countable","filter","msg","pending","lastViewed","lastViewedTimestamp","oldestTs","minTs","ts","min","MAX_SAFE_INTEGER","getRoomPriority","jid","_room","selectedRoomJid","defaultRoomJids","has","shouldPauseForVisibility","AppState","currentState","runHistoryPreloadScheduler","options","client","signal","concurrency","retryLimit","roomLimit","forceReload","aborted","store","dispatch","setUnreadSyncing","state","getState","rooms","defaultSet","Set","sortedQueue","Object","entries","map","priority","activityScore","attempts","readyAt","Date","now","sort","a","b","localeCompare","queue","slice","inFlightByRoom","Map","consecutiveErrorCount","isActiveRoomGateOpen","readyItems","item","batch","preBatchPreloadStateByJid","historyPreloadState","applyRoomsPreloadBatch","all","queueIndex","findIndex","queued","splice","task","currentRoom","preState","get","fetchedMessages","getHistoryStanza","undefined","coalesceRoom","skipIfPreloaded","source","Error","nextRoom","unreadCapped","retries","canRetry","jitter","floor","random","backoff","push","set","finally","delete","r","exports","_default","default"],"sourceRoot":"../../../src","sources":["helpers/historyPreloadScheduler.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,IAAAC,UAAA,GAAAD,OAAA;AACA,IAAAE,WAAA,GAAAF,OAAA;AAuBA,MAAMG,mBAAmB,GAAG,CAAC;AAC7B;AACA;AACA;AACA,MAAMC,iBAAiB,GAAG,EAAE;AAC5B,MAAMC,mBAAmB,GAAG,CAAC;AAE7B,MAAMC,KAAK,GAAIC,EAAU,IAAK,IAAIC,OAAO,CAAEC,OAAO,IAAKC,UAAU,CAACD,OAAO,EAAEF,EAAE,CAAC,CAAC;AAE/E,MAAMI,gBAAgB,GAAIC,CAAW,IAAa;EAChD,IAAI,CAACA,CAAC,EAAE;IAAC,OAAO,CAAC;EAAC;EAClB,MAAMC,CAAC,GAAID,CAAC,CAASE,SAAS;EAC9B,IAAIC,MAAM,CAACC,QAAQ,CAACH,CAAC,CAAC,IAAIA,CAAC,GAAG,CAAC,EAAE;IAAC,OAAOE,MAAM,CAACF,CAAC,CAAC;EAAC;EACnD,MAAMI,EAAE,GAAGF,MAAM,CAACH,CAAC,CAACK,EAAE,CAAC;EACvB,IAAIF,MAAM,CAACC,QAAQ,CAACC,EAAE,CAAC,IAAIA,EAAE,GAAG,CAAC,EAAE;IAAC,OAAOA,EAAE;EAAC;EAC9C,OAAO,CAAC;AACV,CAAC;AAED,MAAMC,wBAAwB,GAAIC,IAAW,IAAa;EACxD,IAAI,CAACA,IAAI,EAAEC,QAAQ,EAAEC,MAAM,EAAE;IAAC,OAAO,CAAC;EAAC;EACvC,OAAOF,IAAI,CAACC,QAAQ,CAACE,MAAM,CAAC,CAACC,GAAG,EAAEX,CAAC,KAAKY,IAAI,CAACD,GAAG,CAACA,GAAG,EAAEZ,gBAAgB,CAACC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,MAAMa,mBAAmB,GAAGA,CAC1BN,IAAW,EACXC,QAAoB,EACpBM,QAAgB,KACJ;EACZ,IAAI,CAACP,IAAI,EAAE;IAAC,OAAO,KAAK;EAAC;EACzB,IAAI,CAACC,QAAQ,IAAIA,QAAQ,CAACC,MAAM,GAAGK,QAAQ,EAAE;IAAC,OAAO,KAAK;EAAC;EAC3D,IAAIP,IAAI,CAACQ,eAAe,KAAK,IAAI,EAAE;IAAC,OAAO,KAAK;EAAC;EAEjD,MAAMC,SAAS,GAAGR,QAAQ,CAACS,MAAM,CAC9BC,GAAG,IAAK,CAAC,CAACA,GAAG,IAAIA,GAAG,CAACb,EAAE,KAAK,eAAe,IAAI,CAACa,GAAG,CAACC,OACvD,CAAC;EACD,IAAIH,SAAS,CAACP,MAAM,GAAGK,QAAQ,EAAE;IAAC,OAAO,KAAK;EAAC;EAE/C,MAAMM,UAAU,GAAGjB,MAAM,CAACI,IAAI,CAACc,mBAAmB,CAAC,IAAI,CAAC;EACxD,IAAID,UAAU,IAAI,CAAC,EAAE;IAAC,OAAO,IAAI;EAAC;EAElC,MAAME,QAAQ,GAAGN,SAAS,CAACN,MAAM,CAAS,CAACa,KAAK,EAAEvB,CAAC,KAAK;IACtD,MAAMwB,EAAE,GAAGzB,gBAAgB,CAACC,CAAC,CAAC;IAC9B,IAAI,CAACG,MAAM,CAACC,QAAQ,CAACoB,EAAE,CAAC,IAAIA,EAAE,IAAI,CAAC,EAAE;MAAC,OAAOD,KAAK;IAAC;IACnD,OAAOX,IAAI,CAACa,GAAG,CAACF,KAAK,EAAEC,EAAE,CAAC;EAC5B,CAAC,EAAErB,MAAM,CAACuB,gBAAgB,CAAC;EAC3B,IAAI,CAACvB,MAAM,CAACC,QAAQ,CAACkB,QAAQ,CAAC,IAAIA,QAAQ,KAAKnB,MAAM,CAACuB,gBAAgB,EACpE;IAAC,OAAO,KAAK;EAAC;EAChB,OAAOJ,QAAQ,GAAGF,UAAU;AAC9B,CAAC;AAED,MAAMO,eAAe,GAAGA,CACtBC,GAAW,EACXC,KAAY,EACZC,eAA8B,EAC9BC,eAA4B,KACjB;EACX,IAAID,eAAe,IAAIA,eAAe,KAAKF,GAAG,EAAE;IAAC,OAAO,CAAC;EAAC;EAC1D,IAAIG,eAAe,CAACC,GAAG,CAACJ,GAAG,CAAC,EAAE;IAAC,OAAO,CAAC;EAAC;EACxC,OAAO,CAAC;AACV,CAAC;AAED,MAAMK,wBAAwB,GAAGA,CAAA,KAAe;EAC9C,OAAOC,qBAAQ,CAACC,YAAY,KAAK,QAAQ;AAC3C,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,0BAA0B,GAAG,MACxCC,OAAuC,IACrB;EAClB,MAAM;IACJC,MAAM;IACNC,MAAM;IACNC,WAAW,GAAGjD,mBAAmB;IACjCuB,QAAQ,GAAGtB,iBAAiB;IAC5BiD,UAAU,GAAGhD,mBAAmB;IAChCiD,SAAS;IACTZ,eAAe,GAAG,IAAI;IACtBC,eAAe,GAAG,EAAE;IACpBY,WAAW,GAAG;EAChB,CAAC,GAAGN,OAAO;EAEX,IAAIE,MAAM,EAAEK,OAAO,EAAE;IAAC;EAAO;EAE7BC,gBAAK,CAACC,QAAQ,CAAC,IAAAC,4BAAgB,EAAC,IAAI,CAAC,CAAC;EACtC,IAAI;IAEJ,MAAMC,KAAK,GAAGH,gBAAK,CAACI,QAAQ,CAAC,CAAC;IAC9B,MAAMC,KAAK,GAAIF,KAAK,CAACE,KAAK,CAACA,KAAK,IAAI,CAAC,CAA2B;IAChE,MAAMC,UAAU,GAAG,IAAIC,GAAG,CAACrB,eAAe,CAAC;IAE3C,MAAMsB,WAAwB,GAAGC,MAAM,CAACC,OAAO,CAACL,KAAK,CAAC,CACnDM,GAAG,CAAC,CAAC,CAAC5B,GAAG,EAAErB,IAAI,CAAkB,MAAM;MACtCqB,GAAG;MACH6B,QAAQ,EAAE9B,eAAe,CAACC,GAAG,EAAErB,IAAI,EAAEuB,eAAe,EAAEqB,UAAU,CAAC;MACjEO,aAAa,EAAEpD,wBAAwB,CAACC,IAAI,CAAC;MAC7CoD,QAAQ,EAAE,CAAC;MACXC,OAAO,EAAEC,IAAI,CAACC,GAAG,CAAC;IACpB,CAAC,CAAC,CAAC,CACFC,IAAI,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAK;MACd,IAAID,CAAC,CAACP,QAAQ,KAAKQ,CAAC,CAACR,QAAQ,EAAE;QAAC,OAAOO,CAAC,CAACP,QAAQ,GAAGQ,CAAC,CAACR,QAAQ;MAAC;MAC/D,IAAIO,CAAC,CAACN,aAAa,KAAKO,CAAC,CAACP,aAAa,EAAE;QACvC,OAAOO,CAAC,CAACP,aAAa,GAAGM,CAAC,CAACN,aAAa;MAC1C;MACA,OAAOM,CAAC,CAACpC,GAAG,CAACsC,aAAa,CAACD,CAAC,CAACrC,GAAG,CAAC;IACnC,CAAC,CAAC;IAEJ,MAAMuC,KAAkB,GACtBzB,SAAS,IAAIA,SAAS,GAAG,CAAC,GACtBW,WAAW,CAACe,KAAK,CAAC,CAAC,EAAE1B,SAAS,CAAC,GAC/BW,WAAW;IAEjB,MAAMgB,cAAc,GAAG,IAAIC,GAAG,CAAwB,CAAC;IACvD,IAAIC,qBAAqB,GAAG,CAAC;IAE7B,OAAOJ,KAAK,CAAC1D,MAAM,GAAG,CAAC,EAAE;MACvB,IAAI8B,MAAM,EAAEK,OAAO,EAAE;QAAC;MAAO;MAE7B,IAAI,CAACN,MAAM,CAACkC,oBAAoB,CAAC,CAAC,EAAE;QAClC,MAAM9E,KAAK,CAAC,EAAE,CAAC;QACf;MACF;MACA,IAAIuC,wBAAwB,CAAC,CAAC,EAAE;QAC9B,MAAMvC,KAAK,CAAC,GAAG,CAAC;QAChB;MACF;MAEA,MAAMoE,GAAG,GAAGD,IAAI,CAACC,GAAG,CAAC,CAAC;MACtB,MAAMW,UAAU,GAAGN,KAAK,CAAClD,MAAM,CAC5ByD,IAAI,IAAKA,IAAI,CAACd,OAAO,IAAIE,GAAG,IAAI,CAACO,cAAc,CAACrC,GAAG,CAAC0C,IAAI,CAAC9C,GAAG,CAC/D,CAAC;MACD,IAAI6C,UAAU,CAAChE,MAAM,KAAK,CAAC,EAAE;QAC3B,MAAMf,KAAK,CAAC,EAAE,CAAC;QACf;MACF;MAEA,MAAMiF,KAAK,GAAGF,UAAU,CAACL,KAAK,CAAC,CAAC,EAAExD,IAAI,CAACD,GAAG,CAAC,CAAC,EAAE6B,WAAW,CAAC,CAAC;;MAE3D;MACA;MACA;MACA;MACA;MACA;MACA,MAAMoC,yBAAyB,GAAG,IAAIN,GAAG,CACvCK,KAAK,CAACnB,GAAG,CAAEkB,IAAI,IAAK,CAClBA,IAAI,CAAC9C,GAAG,EACRiB,gBAAK,CAACI,QAAQ,CAAC,CAAC,CAACC,KAAK,CAACA,KAAK,CAACwB,IAAI,CAAC9C,GAAG,CAAC,EAAEiD,mBAAmB,CAC5D,CACH,CAAC;MAEDhC,gBAAK,CAACC,QAAQ,CACZ,IAAAgC,kCAAsB,EAAC;QACrB5B,KAAK,EAAEyB,KAAK,CAACnB,GAAG,CAAEkB,IAAI,KAAM;UAC1B9C,GAAG,EAAE8C,IAAI,CAAC9C,GAAG;UACbiD,mBAAmB,EAAE;QACvB,CAAC,CAAC;MACJ,CAAC,CACH,CAAC;MAED,MAAMjF,OAAO,CAACmF,GAAG,CACfJ,KAAK,CAACnB,GAAG,CAAC,MAAOkB,IAAI,IAAK;QACxB,MAAMM,UAAU,GAAGb,KAAK,CAACc,SAAS,CAAEC,MAAM,IAAKA,MAAM,CAACtD,GAAG,KAAK8C,IAAI,CAAC9C,GAAG,CAAC;QACvE,IAAIoD,UAAU,KAAK,CAAC,CAAC,EAAE;UAACb,KAAK,CAACgB,MAAM,CAACH,UAAU,EAAE,CAAC,CAAC;QAAC;QAEpD,MAAMI,IAAI,GAAG,CAAC,YAAY;UACxB,MAAMC,WAAW,GAAGxC,gBAAK,CAACI,QAAQ,CAAC,CAAC,CAACC,KAAK,CAACA,KAAK,CAACwB,IAAI,CAAC9C,GAAG,CAAC;UAC1D,MAAM0D,QAAQ,GAAGV,yBAAyB,CAACW,GAAG,CAACb,IAAI,CAAC9C,GAAG,CAAC;UACxD,IACE,CAACyD,WAAW,IACX,CAAC1C,WAAW,IAAI2C,QAAQ,KAAK,MAAO,EACrC;YACAzC,gBAAK,CAACC,QAAQ,CACZ,IAAAgC,kCAAsB,EAAC;cACrB5B,KAAK,EAAE,CAAC;gBAAEtB,GAAG,EAAE8C,IAAI,CAAC9C,GAAG;gBAAEiD,mBAAmB,EAAE;cAAO,CAAC;YACxD,CAAC,CACH,CAAC;YACD;UACF;UAEA,IAAI;YACF,MAAMW,eAAe,GAAG,MAAMlD,MAAM,CAACmD,gBAAgB,CACnDf,IAAI,CAAC9C,GAAG,EACRd,QAAQ,EACR4E,SAAS,EACTA,SAAS,EACT;cACEC,YAAY,EAAE,IAAI;cAClBC,eAAe,EAAE,CAACjD,WAAW;cAC7BkD,MAAM,EAAE;YACV,CACF,CAAC;YACD,IAAItD,MAAM,EAAEK,OAAO,EAAE;cAAC;YAAO;YAC7B,IAAI,OAAO4C,eAAe,KAAK,WAAW,EAAE;cAC1C,MAAM,IAAIM,KAAK,CAAC,iBAAiB,CAAC;YACpC;YAEA,MAAMC,QAAQ,GAAGlD,gBAAK,CAACI,QAAQ,CAAC,CAAC,CAACC,KAAK,CAACA,KAAK,CAACwB,IAAI,CAAC9C,GAAG,CAAC;YACvD,MAAMoE,YAAY,GAAGnF,mBAAmB,CACtCkF,QAAQ,EACRP,eAAe,IAAI,EAAE,EACrB1E,QACF,CAAC;YAED+B,gBAAK,CAACC,QAAQ,CACZ,IAAAgC,kCAAsB,EAAC;cACrB5B,KAAK,EAAE,CACL;gBACEtB,GAAG,EAAE8C,IAAI,CAAC9C,GAAG;gBACbpB,QAAQ,EAAEgF,eAAe,IAAI,EAAE;gBAC/BQ,YAAY;gBACZnB,mBAAmB,EAAE;cACvB,CAAC;YAEL,CAAC,CACH,CAAC;YACDN,qBAAqB,GAAG,CAAC;UAC3B,CAAC,CAAC,MAAM;YACN,MAAM0B,OAAO,GAAGvB,IAAI,CAACf,QAAQ,GAAG,CAAC;YACjC,MAAMuC,QAAQ,GAAGD,OAAO,IAAIxD,UAAU;YACtC,IAAIyD,QAAQ,EAAE;cACZ,MAAMC,MAAM,GAAGvF,IAAI,CAACwF,KAAK,CAACxF,IAAI,CAACyF,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC;cAC9C,MAAMC,OAAO,GAAG1F,IAAI,CAACa,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,IAAIiD,IAAI,CAACf,QAAQ,CAAC,GAAGwC,MAAM;cACjEhC,KAAK,CAACoC,IAAI,CAAC;gBACT,GAAG7B,IAAI;gBACPf,QAAQ,EAAEsC,OAAO;gBACjBrC,OAAO,EAAEC,IAAI,CAACC,GAAG,CAAC,CAAC,GAAGwC;cACxB,CAAC,CAAC;YACJ,CAAC,MAAM;cACLzD,gBAAK,CAACC,QAAQ,CACZ,IAAAgC,kCAAsB,EAAC;gBACrB5B,KAAK,EAAE,CAAC;kBAAEtB,GAAG,EAAE8C,IAAI,CAAC9C,GAAG;kBAAEiD,mBAAmB,EAAE;gBAAQ,CAAC;cACzD,CAAC,CACH,CAAC;YACH;YACAN,qBAAqB,IAAI,CAAC;YAC1B,IAAIA,qBAAqB,IAAI,CAAC,EAAE;cAC9B,MAAM7E,KAAK,CAAC,GAAG,CAAC;cAChB6E,qBAAqB,GAAG,CAAC;YAC3B;UACF;QACF,CAAC,EAAE,CAAC;QAEJF,cAAc,CAACmC,GAAG,CAAC9B,IAAI,CAAC9C,GAAG,EAAEwD,IAAI,CAAC;QAClC,MAAMA,IAAI,CAACqB,OAAO,CAAC,MAAMpC,cAAc,CAACqC,MAAM,CAAChC,IAAI,CAAC9C,GAAG,CAAC,CAAC;MAC3D,CAAC,CACH,CAAC;;MAED;MACA,MAAM,IAAIhC,OAAO,CAAE+G,CAAC,IAAK7G,UAAU,CAAC6G,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C;EACA,CAAC,SAAS;IACR9D,gBAAK,CAACC,QAAQ,CAAC,IAAAC,4BAAgB,EAAC,KAAK,CAAC,CAAC;EACzC;AACF,CAAC;AAAC6D,OAAA,CAAAxE,0BAAA,GAAAA,0BAAA;AAAA,IAAAyE,QAAA,GAAAD,OAAA,CAAAE,OAAA,GAEa1E,0BAA0B","ignoreList":[]}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useChatFonts = useChatFonts;
7
+ var _react = require("react");
8
+ var _reactNative = require("react-native");
9
+ 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); }
10
+ /**
11
+ * Loads and applies the host-provided font configuration for the chat UI.
12
+ *
13
+ * React Native has no web-style runtime `@font-face`, so a custom font must be
14
+ * registered with `expo-font` before it can be used. This hook:
15
+ * 1. loads every entry in `typography.fonts` via `expo-font` (remote URL or
16
+ * bundled `require(...)`), then
17
+ * 2. sets the resolved `fontFamily` as the default for all `<Text>` and
18
+ * `<TextInput>` rendered by the chat — mirroring how the web SDK sets a
19
+ * CSS variable. Individual components can still override per-style.
20
+ *
21
+ * `expo-font` is an optional peer dependency: if the host hasn't installed it,
22
+ * the hook degrades gracefully (font simply isn't loaded) instead of throwing.
23
+ *
24
+ * No-op when `typography` is undefined — the system font is kept, so existing
25
+ * integrations are unaffected.
26
+ *
27
+ * @returns `true` once fonts are ready (or when there's nothing to load), so
28
+ * callers can gate first paint to avoid a font "flash" if desired.
29
+ */
30
+ function useChatFonts(typography) {
31
+ const [ready, setReady] = (0, _react.useState)(!typography?.fonts?.length);
32
+ applyDefaultFont(typography);
33
+ (0, _react.useEffect)(() => {
34
+ let cancelled = false;
35
+ async function load() {
36
+ // Apply the default family immediately so already-available fonts
37
+ // (system, or host-loaded) take effect without waiting on a download.
38
+ applyDefaultFont(typography);
39
+ if (!typography?.fonts?.length) {
40
+ setReady(true);
41
+ return;
42
+ }
43
+ try {
44
+ // Optional dependency — resolve lazily so apps that don't use custom
45
+ // fonts don't need expo-font installed.
46
+ const ExpoFont = await Promise.resolve().then(() => _interopRequireWildcard(require('expo-font'))).catch(() => null);
47
+ if (!ExpoFont) {
48
+ if (!cancelled) setReady(true);
49
+ return;
50
+ }
51
+ const map = {};
52
+ for (const f of typography.fonts) map[f.family] = f.source;
53
+ await ExpoFont.loadAsync(map);
54
+ if (!cancelled) {
55
+ applyDefaultFont(typography);
56
+ setReady(true);
57
+ }
58
+ } catch {
59
+ // Loading failed (e.g. bad URL) — keep the fallback font, don't block UI.
60
+ if (!cancelled) setReady(true);
61
+ }
62
+ }
63
+ load();
64
+ return () => {
65
+ cancelled = true;
66
+ };
67
+ // eslint-disable-next-line react-hooks/exhaustive-deps
68
+ }, [typography?.fontFamily, JSON.stringify(typography?.fonts ?? []), JSON.stringify(typography?.weightFamilies ?? {})]);
69
+ return ready;
70
+ }
71
+
72
+ /**
73
+ * The family currently applied as the chat-wide default. Read at render time
74
+ * by the patched components below, so updating it (then triggering a re-render)
75
+ * restyles the whole tree.
76
+ */
77
+ let activeFamily;
78
+ function wrapFactory(orig) {
79
+ if (typeof orig !== 'function') return orig;
80
+ if (orig.__ethoraFontWrapped) return orig;
81
+ const wrapped = function (type, props, ...rest) {
82
+ if (activeFamily && props && (type === _reactNative.Text || type === _reactNative.TextInput)) {
83
+ props = {
84
+ ...props,
85
+ style: [{
86
+ fontFamily: activeFamily
87
+ }, props.style]
88
+ };
89
+ }
90
+ return orig.call(this, type, props, ...rest);
91
+ };
92
+ wrapped.__ethoraFontWrapped = true;
93
+ return wrapped;
94
+ }
95
+ let factoriesPatched = false;
96
+ function ensurePatched() {
97
+ if (factoriesPatched) return;
98
+ let any = false;
99
+ const patchMod = mod => {
100
+ if (!mod) return;
101
+ for (const fn of ['jsx', 'jsxs', 'jsxDEV']) {
102
+ if (typeof mod[fn] === 'function' && !mod[fn].__ethoraFontWrapped) {
103
+ mod[fn] = wrapFactory(mod[fn]);
104
+ any = true;
105
+ }
106
+ }
107
+ };
108
+ try {
109
+ patchMod(require('react/jsx-runtime'));
110
+ } catch {
111
+ /* ignore */
112
+ }
113
+ try {
114
+ patchMod(require('react/jsx-dev-runtime'));
115
+ } catch {
116
+ /* ignore */
117
+ }
118
+ try {
119
+ const React = require('react');
120
+ if (typeof React.createElement === 'function' && !React.createElement.__ethoraFontWrapped) {
121
+ React.createElement = wrapFactory(React.createElement);
122
+ any = true;
123
+ }
124
+ } catch {
125
+ /* ignore */
126
+ }
127
+ if (any) factoriesPatched = true;
128
+ }
129
+
130
+ /**
131
+ * Set (or clear) the chat-wide default font family.
132
+ */
133
+ function applyDefaultFont(typography) {
134
+ activeFamily = typography?.fontFamily;
135
+ if (activeFamily) ensurePatched();
136
+ }
137
+ //# sourceMappingURL=useChatFonts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_react","require","_reactNative","_interopRequireWildcard","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","useChatFonts","typography","ready","setReady","useState","fonts","length","applyDefaultFont","useEffect","cancelled","load","ExpoFont","Promise","resolve","then","catch","map","family","source","loadAsync","fontFamily","JSON","stringify","weightFamilies","activeFamily","wrapFactory","orig","__ethoraFontWrapped","wrapped","type","props","rest","Text","TextInput","style","factoriesPatched","ensurePatched","any","patchMod","mod","fn","React","createElement"],"sourceRoot":"../../../src","sources":["hooks/useChatFonts.ts"],"mappings":"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","ignoreList":[]}
@@ -20,11 +20,25 @@ var _useEventHandlers = require("./useEventHandlers");
20
20
  // long after the optimistic dispatch, mark it failed so the bubble
21
21
  // flips out of the "sending..." state. Covers the silent-failure
22
22
  // case (e.g. device offline before the message ever made it to the
23
- // XMPP socket) — bug #18. Tuned generously so a brief network blip
24
- // followed by reconnect within 30s still resolves naturally via the
25
- // server echo.
23
+ // XMPP socket) — bug #18.
24
+ //
25
+ // 5s window: a brief network blip that reconnects inside this window
26
+ // still resolves on its own — the offline send is buffered in the
27
+ // outbound queue (OUTBOUND_QUEUE_TTL_MS, kept in lockstep) and replayed
28
+ // the moment the stream comes back, so the server echo flips the bubble
29
+ // to delivered. Only a drop that outlasts 5s flips it to "Failed → tap
30
+ // to retry". If a slow send completes just after the window, the
31
+ // delivery clears the failed flag (see newMessageMidlleware) so it
32
+ // doesn't get stuck showing "Failed".
26
33
  const PENDING_WATCHDOG_MS = 30_000;
27
34
 
35
+ // Media gets a longer window than text: the optimistic bubble appears before
36
+ // the file upload even starts, and a large file (up to the 50MB cap) over a
37
+ // slow link can legitimately take far longer than 5s to upload + send. Failing
38
+ // it at 5s mid-upload would flash a wrong "Failed" and let the user kick off a
39
+ // duplicate upload. The text watchdog stays at 5s per product spec.
40
+ const MEDIA_PENDING_WATCHDOG_MS = 30_000;
41
+
28
42
  // Monotonic counter for stanza ids. Bumped on each send within a single
29
43
  // process. Two rapid sends in the same millisecond used to collide on
30
44
  // `send-text-message-${Date.now()}`; that collision made
@@ -63,7 +77,7 @@ const useSendMessage = _configOverride => {
63
77
  handleMessageRetry
64
78
  } = (0, _useEventHandlers.useEventHandlers)(config);
65
79
  const failedMessages = (0, _reactRedux.useSelector)(state => state.roomHeapSlice?.failedMessages || {});
66
- const sendMessage = (0, _react.useCallback)(async (message, activeRoomJID, isReply, isChecked, mainMessage) => {
80
+ const sendMessage = (0, _react.useCallback)(async (message, activeRoomJID, isReply, isChecked, mainMessage, existingId) => {
67
81
  if (editAction?.isEdit) {
68
82
  try {
69
83
  client?.editMessageStanza(editAction.roomJid, editAction.messageId, message);
@@ -97,7 +111,7 @@ const useSendMessage = _configOverride => {
97
111
  // dedupes by id and flips `pending: false` → DoubleTick renders.
98
112
  // Without this, the user taps send and sees nothing for ~200ms
99
113
  // until the echo lands, which feels broken.
100
- const optimisticId = nextStanzaId('send-text-message');
114
+ const optimisticId = existingId || nextStanzaId('send-text-message');
101
115
  const optimisticDate = new Date().toISOString();
102
116
  const selfId = user?.xmppUsername || user?.walletAddress || '';
103
117
  const optimisticMessage = {
@@ -118,7 +132,11 @@ const useSendMessage = _configOverride => {
118
132
  name: `${user?.firstName || ''} ${user?.lastName || ''}`.trim() || selfId
119
133
  }
120
134
  };
121
- if (!config?.disableSentLogic) {
135
+ // On retry (`existingId`) the original optimistic bubble is still in
136
+ // the room (pending:true) — clearMessageFailure just flipped it back out
137
+ // of the "failed" state — so re-adding would duplicate it. Only push a
138
+ // fresh bubble for a brand-new send.
139
+ if (!config?.disableSentLogic && !existingId) {
122
140
  dispatch((0, _roomsSlice.addRoomMessage)({
123
141
  roomJID: activeRoomJID,
124
142
  message: optimisticMessage
@@ -154,26 +172,46 @@ const useSendMessage = _configOverride => {
154
172
  }
155
173
  }, PENDING_WATCHDOG_MS);
156
174
  try {
157
- const effectiveClient = client || [(0, _clientRegistry.getGlobalXmppClient)(), _roomStore.store.getState()?.chatSettingStore?.client].find(c => c && c.status === 'online');
175
+ // The single send closure, used both for the immediate send and for
176
+ // the buffered replay. Passing the optimistic id as the stanza id
177
+ // means the server echoes it back with the same value, so the
178
+ // reducer's dedupe matches and the bubble flips pending → delivered
179
+ // in-place (rather than rendering a second copy).
180
+ const replaySend = c => c.sendMessage(activeRoomJID, user.firstName, user.lastName, '', user.walletAddress, message, '', isReply || false, isChecked || false, mainMessage || '', optimisticId);
181
+
182
+ // Always buffer a copy BEFORE attempting the live send. The WebSocket
183
+ // can still read `status: 'online'` for a beat after the network
184
+ // actually drops (the WS error lands a moment later), so a stanza sent
185
+ // "while online" can vanish into a dying socket and never get echoed.
186
+ // Buffering every send means the onOnline reconnect flush replays
187
+ // anything that wasn't confirmed within the window. The server echo
188
+ // removes the entry (see newMessageMidlleware), so a healthy online
189
+ // send never actually replays — only genuinely-lost ones do.
190
+ (0, _outboundQueue.enqueueOutboundSend)({
191
+ optimisticId,
192
+ roomJID: activeRoomJID,
193
+ enqueuedAt: Date.now(),
194
+ send: replaySend
195
+ });
196
+
197
+ // Only treat a client as usable if its underlying stream is actually
198
+ // `online` — the instance survives a network drop with a stale
199
+ // 'connecting'/'offline' status, and sending through it would just
200
+ // lose the stanza.
201
+ const effectiveClient = [client, (0, _clientRegistry.getGlobalXmppClient)(), _roomStore.store.getState()?.chatSettingStore?.client].find(c => c && c.status === 'online');
158
202
  if (!effectiveClient) {
203
+ // No live stream — kick a reconnect; the buffered copy above is
204
+ // replayed by the onOnline flush once the stream is back.
159
205
  const anyClient = client || (0, _clientRegistry.getGlobalXmppClient)() || _roomStore.store.getState()?.chatSettingStore?.client;
160
206
  try {
161
207
  anyClient?.forceReconnect?.();
162
208
  } catch {}
163
- (0, _outboundQueue.enqueueOutboundSend)({
164
- optimisticId,
165
- roomJID: activeRoomJID,
166
- enqueuedAt: Date.now(),
167
- send: c => c.sendMessage(activeRoomJID, user.firstName, user.lastName, '', user.walletAddress, message, '', isReply || false, isChecked || false, mainMessage || '', optimisticId)
168
- });
169
209
  return;
170
210
  }
171
- // Pass the optimistic id as the stanza id so the server echoes
172
- // it back with the same value — the reducer's dedupe lookup
173
- // matches and the bubble flips from pending → delivered in-place
174
- // (instead of rendering two copies, which is what happens when
175
- // ids don't match).
176
- effectiveClient.sendMessage(activeRoomJID, user.firstName, user.lastName, '', user.walletAddress, message, '', isReply || false, isChecked || false, mainMessage || '', optimisticId);
211
+ replaySend(effectiveClient);
212
+ try {
213
+ effectiveClient.ensureStreamAlive?.();
214
+ } catch {}
177
215
  await handleMessageSent({
178
216
  message,
179
217
  roomJID: activeRoomJID,
@@ -313,7 +351,7 @@ const useSendMessage = _configOverride => {
313
351
  messageType: 'media'
314
352
  });
315
353
  }
316
- }, PENDING_WATCHDOG_MS);
354
+ }, MEDIA_PENDING_WATCHDOG_MS);
317
355
 
318
356
  // Help RN's FormData polyfill build a proper multipart/file part
319
357
  // (instead of serialising the JS object as JSON). On iOS the
@@ -390,11 +428,17 @@ const useSendMessage = _configOverride => {
390
428
  // Stanza id == placeholder id so the MUC echo's outer
391
429
  // <message id="..."> matches xmppId on the placeholder and
392
430
  // insertMessageWithDelimiter merges in place + flips pending.
393
- const effectiveMediaClient = client || [(0, _clientRegistry.getGlobalXmppClient)(), _roomStore.store.getState()?.chatSettingStore?.client].find(c => c && c.status === 'online');
431
+ // Same online-only guard as the text path: a surviving-but-offline
432
+ // client must NOT be used (the stanza would vanish into a dead
433
+ // socket) — fall through to enqueue so the reconnect flush replays.
434
+ const effectiveMediaClient = [client, (0, _clientRegistry.getGlobalXmppClient)(), _roomStore.store.getState()?.chatSettingStore?.client].find(c => c && c.status === 'online');
394
435
  if (effectiveMediaClient) {
395
436
  effectiveMediaClient.setActiveRoomJid?.(activeRoomJID);
396
437
  await Promise.resolve(effectiveMediaClient.prioritizeRoomPresence?.(activeRoomJID)).catch(() => false);
397
438
  effectiveMediaClient.sendMediaMessageStanza(activeRoomJID, messagePayload, id);
439
+ try {
440
+ effectiveMediaClient.ensureStreamAlive?.();
441
+ } catch {}
398
442
  } else {
399
443
  const anyMediaClient = client || (0, _clientRegistry.getGlobalXmppClient)() || _roomStore.store.getState()?.chatSettingStore?.client;
400
444
  try {
@@ -404,6 +448,9 @@ const useSendMessage = _configOverride => {
404
448
  optimisticId: id,
405
449
  roomJID: activeRoomJID,
406
450
  enqueuedAt: Date.now(),
451
+ // Match the media watchdog so a reconnect within the (longer)
452
+ // media window still auto-replays the buffered stanza.
453
+ ttlMs: MEDIA_PENDING_WATCHDOG_MS,
407
454
  send: c => c.sendMediaMessageStanza(activeRoomJID, messagePayload, id)
408
455
  });
409
456
  }
@@ -484,7 +531,10 @@ const useSendMessage = _configOverride => {
484
531
  messageType: payload.kind
485
532
  });
486
533
  if (payload.kind === 'text') {
487
- await sendMessage(payload.body, payload.roomJID, payload.isReply, payload.isChecked, payload.mainMessage);
534
+ await sendMessage(payload.body, payload.roomJID, payload.isReply, payload.isChecked, payload.mainMessage,
535
+ // Re-use the failed message's id so the retry resends in place
536
+ // instead of spawning a duplicate bubble.
537
+ failedId);
488
538
  } else {
489
539
  await sendMedia(payload.data, payload.type, payload.roomJID, payload.isReply, payload.isChecked, payload.mainMessage, failedId);
490
540
  }