@ethora/chat-component-rn 26.7.7 → 26.7.9

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 (170) hide show
  1. package/lib/commonjs/components/MainComponents/ChatRoom.js +17 -8
  2. package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
  3. package/lib/commonjs/components/MainComponents/MediaMessage.js +8 -5
  4. package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
  5. package/lib/commonjs/components/MainComponents/MessageContainer.js +5 -1
  6. package/lib/commonjs/components/MainComponents/MessageContainer.js.map +1 -1
  7. package/lib/commonjs/components/MainComponents/MessageList.js +2 -1
  8. package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
  9. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +51 -12
  10. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  11. package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js +12 -1
  12. package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
  13. package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js +13 -2
  14. package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
  15. package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js +13 -2
  16. package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
  17. package/lib/commonjs/components/styled/MessageImage.js +3 -1
  18. package/lib/commonjs/components/styled/MessageImage.js.map +1 -1
  19. package/lib/commonjs/components/styled/UnsupportedType.js +14 -4
  20. package/lib/commonjs/components/styled/UnsupportedType.js.map +1 -1
  21. package/lib/commonjs/components/styled/VideoMessage.js +3 -1
  22. package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
  23. package/lib/commonjs/context/xmppProvider.js +46 -31
  24. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  25. package/lib/commonjs/helpers/createMessageFromXml.js +19 -1
  26. package/lib/commonjs/helpers/createMessageFromXml.js.map +1 -1
  27. package/lib/commonjs/helpers/getDisplayFileName.js +79 -0
  28. package/lib/commonjs/helpers/getDisplayFileName.js.map +1 -0
  29. package/lib/commonjs/helpers/getServerReadTimestamp.js +125 -0
  30. package/lib/commonjs/helpers/getServerReadTimestamp.js.map +1 -0
  31. package/lib/commonjs/helpers/initXmppRooms.js +9 -7
  32. package/lib/commonjs/helpers/initXmppRooms.js.map +1 -1
  33. package/lib/commonjs/helpers/isOwnMessage.js +75 -0
  34. package/lib/commonjs/helpers/isOwnMessage.js.map +1 -0
  35. package/lib/commonjs/helpers/mimeToExtension.js +6 -14
  36. package/lib/commonjs/helpers/mimeToExtension.js.map +1 -1
  37. package/lib/commonjs/hooks/useChatRoomFocus.js +17 -8
  38. package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -1
  39. package/lib/commonjs/hooks/useChatWrapperInit.js +12 -7
  40. package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
  41. package/lib/commonjs/networking/stanzaHandlers.js +20 -2
  42. package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
  43. package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js +45 -11
  44. package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
  45. package/lib/commonjs/networking/xmppClient.js +36 -2
  46. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  47. package/lib/commonjs/roomStore/index.js +35 -2
  48. package/lib/commonjs/roomStore/index.js.map +1 -1
  49. package/lib/commonjs/roomStore/persistence.js +200 -11
  50. package/lib/commonjs/roomStore/persistence.js.map +1 -1
  51. package/lib/commonjs/roomStore/roomsSlice.js +83 -6
  52. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  53. package/lib/module/components/MainComponents/ChatRoom.js +17 -8
  54. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  55. package/lib/module/components/MainComponents/MediaMessage.js +9 -6
  56. package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
  57. package/lib/module/components/MainComponents/MessageContainer.js +5 -1
  58. package/lib/module/components/MainComponents/MessageContainer.js.map +1 -1
  59. package/lib/module/components/MainComponents/MessageList.js +2 -1
  60. package/lib/module/components/MainComponents/MessageList.js.map +1 -1
  61. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +52 -13
  62. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  63. package/lib/module/components/RoomComponents/styled/LastMessageFile.js +12 -1
  64. package/lib/module/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
  65. package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js +13 -2
  66. package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
  67. package/lib/module/components/RoomComponents/styled/LastMessageVideo.js +13 -2
  68. package/lib/module/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
  69. package/lib/module/components/styled/MessageImage.js +3 -1
  70. package/lib/module/components/styled/MessageImage.js.map +1 -1
  71. package/lib/module/components/styled/UnsupportedType.js +14 -4
  72. package/lib/module/components/styled/UnsupportedType.js.map +1 -1
  73. package/lib/module/components/styled/VideoMessage.js +3 -1
  74. package/lib/module/components/styled/VideoMessage.js.map +1 -1
  75. package/lib/module/context/xmppProvider.js +47 -32
  76. package/lib/module/context/xmppProvider.js.map +1 -1
  77. package/lib/module/helpers/createMessageFromXml.js +19 -1
  78. package/lib/module/helpers/createMessageFromXml.js.map +1 -1
  79. package/lib/module/helpers/getDisplayFileName.js +73 -0
  80. package/lib/module/helpers/getDisplayFileName.js.map +1 -0
  81. package/lib/module/helpers/getServerReadTimestamp.js +120 -0
  82. package/lib/module/helpers/getServerReadTimestamp.js.map +1 -0
  83. package/lib/module/helpers/initXmppRooms.js +9 -7
  84. package/lib/module/helpers/initXmppRooms.js.map +1 -1
  85. package/lib/module/helpers/isOwnMessage.js +70 -0
  86. package/lib/module/helpers/isOwnMessage.js.map +1 -0
  87. package/lib/module/helpers/mimeToExtension.js +6 -13
  88. package/lib/module/helpers/mimeToExtension.js.map +1 -1
  89. package/lib/module/hooks/useChatRoomFocus.js +17 -8
  90. package/lib/module/hooks/useChatRoomFocus.js.map +1 -1
  91. package/lib/module/hooks/useChatWrapperInit.js +12 -7
  92. package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
  93. package/lib/module/networking/stanzaHandlers.js +20 -2
  94. package/lib/module/networking/stanzaHandlers.js.map +1 -1
  95. package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js +45 -11
  96. package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
  97. package/lib/module/networking/xmppClient.js +36 -2
  98. package/lib/module/networking/xmppClient.js.map +1 -1
  99. package/lib/module/roomStore/index.js +37 -4
  100. package/lib/module/roomStore/index.js.map +1 -1
  101. package/lib/module/roomStore/persistence.js +197 -11
  102. package/lib/module/roomStore/persistence.js.map +1 -1
  103. package/lib/module/roomStore/roomsSlice.js +83 -6
  104. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  105. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  106. package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
  107. package/lib/typescript/components/MainComponents/MessageContainer.d.ts.map +1 -1
  108. package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
  109. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
  110. package/lib/typescript/components/RoomComponents/styled/LastMessageFile.d.ts +1 -1
  111. package/lib/typescript/components/RoomComponents/styled/LastMessageFile.d.ts.map +1 -1
  112. package/lib/typescript/components/RoomComponents/styled/LastMessagePhoto.d.ts +1 -1
  113. package/lib/typescript/components/RoomComponents/styled/LastMessagePhoto.d.ts.map +1 -1
  114. package/lib/typescript/components/RoomComponents/styled/LastMessageVideo.d.ts +1 -1
  115. package/lib/typescript/components/RoomComponents/styled/LastMessageVideo.d.ts.map +1 -1
  116. package/lib/typescript/components/styled/MessageImage.d.ts +6 -0
  117. package/lib/typescript/components/styled/MessageImage.d.ts.map +1 -1
  118. package/lib/typescript/components/styled/UnsupportedType.d.ts.map +1 -1
  119. package/lib/typescript/components/styled/VideoMessage.d.ts +6 -0
  120. package/lib/typescript/components/styled/VideoMessage.d.ts.map +1 -1
  121. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  122. package/lib/typescript/helpers/createMessageFromXml.d.ts.map +1 -1
  123. package/lib/typescript/helpers/getDisplayFileName.d.ts +49 -0
  124. package/lib/typescript/helpers/getDisplayFileName.d.ts.map +1 -0
  125. package/lib/typescript/helpers/getServerReadTimestamp.d.ts +69 -0
  126. package/lib/typescript/helpers/getServerReadTimestamp.d.ts.map +1 -0
  127. package/lib/typescript/helpers/initXmppRooms.d.ts.map +1 -1
  128. package/lib/typescript/helpers/isOwnMessage.d.ts +36 -0
  129. package/lib/typescript/helpers/isOwnMessage.d.ts.map +1 -0
  130. package/lib/typescript/helpers/mimeToExtension.d.ts +0 -15
  131. package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -1
  132. package/lib/typescript/hooks/useChatRoomFocus.d.ts +4 -1
  133. package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -1
  134. package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
  135. package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
  136. package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts +9 -2
  137. package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts.map +1 -1
  138. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  139. package/lib/typescript/roomStore/index.d.ts.map +1 -1
  140. package/lib/typescript/roomStore/persistence.d.ts +18 -1
  141. package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
  142. package/lib/typescript/roomStore/roomsSlice.d.ts +13 -1
  143. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  144. package/package.json +1 -1
  145. package/src/components/MainComponents/ChatRoom.tsx +21 -10
  146. package/src/components/MainComponents/MediaMessage.tsx +8 -5
  147. package/src/components/MainComponents/MessageContainer.tsx +5 -1
  148. package/src/components/MainComponents/MessageList.tsx +2 -1
  149. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +63 -26
  150. package/src/components/RoomComponents/styled/LastMessageFile.tsx +14 -2
  151. package/src/components/RoomComponents/styled/LastMessagePhoto.tsx +14 -2
  152. package/src/components/RoomComponents/styled/LastMessageVideo.tsx +14 -2
  153. package/src/components/styled/MessageImage.tsx +8 -1
  154. package/src/components/styled/UnsupportedType.tsx +14 -4
  155. package/src/components/styled/VideoMessage.tsx +8 -1
  156. package/src/context/xmppProvider.tsx +47 -24
  157. package/src/helpers/createMessageFromXml.ts +20 -1
  158. package/src/helpers/getDisplayFileName.ts +87 -0
  159. package/src/helpers/getServerReadTimestamp.ts +120 -0
  160. package/src/helpers/initXmppRooms.tsx +9 -9
  161. package/src/helpers/isOwnMessage.ts +90 -0
  162. package/src/helpers/mimeToExtension.ts +6 -22
  163. package/src/hooks/useChatRoomFocus.ts +14 -5
  164. package/src/hooks/useChatWrapperInit.ts +12 -7
  165. package/src/networking/stanzaHandlers.ts +20 -6
  166. package/src/networking/xmpp/flushLastViewedToPrivateStore.ts +65 -18
  167. package/src/networking/xmppClient.ts +41 -2
  168. package/src/roomStore/index.ts +40 -4
  169. package/src/roomStore/persistence.ts +197 -7
  170. package/src/roomStore/roomsSlice.ts +84 -6
@@ -21,7 +21,10 @@ interface UseChatRoomFocusOptions {
21
21
  * Without this hook, `useUnread()` will always return 0 for the chat
22
22
  * room because the SDK assumes "mounted == active". With this hook,
23
23
  * focus marks the room visible (clearing the badge) and blur stamps
24
- * `lastViewedTimestamp = Date.now()` so future messages count as unread.
24
+ * `lastViewedTimestamp` to the newest SERVER-acknowledged message so
25
+ * future messages count as unread. Deliberately not `Date.now()`: a
26
+ * device clock running ahead would write a future marker that the
27
+ * forward-only private-store merge could never correct again (bug #38).
25
28
  *
26
29
  * Usage with React Navigation:
27
30
  *
@@ -1 +1 @@
1
- {"version":3,"file":"useChatRoomFocus.d.ts","sourceRoot":"","sources":["../../../src/hooks/useChatRoomFocus.ts"],"names":[],"mappings":"AAUA,UAAU,uBAAuB;IAC/B,wEAAwE;IACxE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC;;;;;;;OAOG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,gBAAgB,GAAI,yBAG9B,uBAAuB,SAuCzB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"useChatRoomFocus.d.ts","sourceRoot":"","sources":["../../../src/hooks/useChatRoomFocus.ts"],"names":[],"mappings":"AAWA,UAAU,uBAAuB;IAC/B,wEAAwE;IACxE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC;;;;;;;OAOG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,gBAAgB,GAAI,yBAG9B,uBAAuB,SA4CzB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useChatWrapperInit.d.ts","sourceRoot":"","sources":["../../../src/hooks/useChatWrapperInit.ts"],"names":[],"mappings":"AAAA,cAAc;AAId,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAiBlD,UAAU,uBAAuB;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,UAAU,wBAAwB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACzD,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC;IACnE,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,QAAA,MAAM,kBAAkB,GAAI,uCAIzB,uBAAuB,KAAG,wBA+O5B,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"useChatWrapperInit.d.ts","sourceRoot":"","sources":["../../../src/hooks/useChatWrapperInit.ts"],"names":[],"mappings":"AAAA,cAAc;AAId,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAgBlD,UAAU,uBAAuB;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,UAAU,wBAAwB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACzD,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC;IACnE,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,QAAA,MAAM,kBAAkB,GAAI,uCAIzB,uBAAuB,KAAG,wBAqP5B,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"stanzaHandlers.d.ts","sourceRoot":"","sources":["../../../src/networking/stanzaHandlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AA6B9B,QAAA,MAAM,iBAAiB,GAAU,QAAQ,OAAO,oDAgH/C,CAAC;AAEF,QAAA,MAAM,eAAe,GAAU,QAAQ,OAAO,kBAiB7C,CAAC;AAEF,QAAA,MAAM,aAAa,GAAU,QAAQ,OAAO,kBAiB3C,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAU,QAAQ,GAAG,kBAoF1C,CAAC;AAEF,QAAA,MAAM,eAAe,GAAU,QAAQ,OAAO,EAAE,aAAa,MAAM,kBA8ClE,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,QAAQ,OAAO,GAAG,GAAG,SAU9C,CAAC;AAEF,QAAA,MAAM,YAAY,GAAU,QAAQ,OAAO,EAAE,QAAQ,GAAG,kBAoBvD,CAAC;AAEF,QAAA,MAAM,YAAY,GAAI,QAAQ,OAAO,SAgEpC,CAAC;AAEF,QAAA,MAAM,aAAa,GAAI,QAAQ,OAAO,SAGrC,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAAI,QAAQ,OAAO,EAAE,OAAO,GAAG,SAG3D,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,QAAQ,OAAO,EAAE,MAAM,GAAG,SAGnD,CAAC;AAEF,QAAA,MAAM,cAAc,GAAI,QAAQ,OAAO,EAAE,MAAM,GAAG,SAsDjD,CAAC;AAKF,QAAA,MAAM,cAAc,GAAI,SAAS,OAAO,EAAE,QAAQ,GAAG,SAAO,CAAC;AAC7D,QAAA,MAAM,iBAAiB,GAAI,SAAS,OAAO,SAAO,CAAC;AACnD,QAAA,MAAM,iBAAiB,GAAI,SAAS,OAAO,SAAO,CAAC;AACnD,QAAA,MAAM,YAAY,GAAI,SAAS,OAAO,SAAO,CAAC;AAE9C,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,aAAa,EACb,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,GACb,CAAC"}
1
+ {"version":3,"file":"stanzaHandlers.d.ts","sourceRoot":"","sources":["../../../src/networking/stanzaHandlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AA6B9B,QAAA,MAAM,iBAAiB,GAAU,QAAQ,OAAO,oDAgH/C,CAAC;AAEF,QAAA,MAAM,eAAe,GAAU,QAAQ,OAAO,kBAiB7C,CAAC;AAEF,QAAA,MAAM,aAAa,GAAU,QAAQ,OAAO,kBAiB3C,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAU,QAAQ,GAAG,kBAkG1C,CAAC;AAEF,QAAA,MAAM,eAAe,GAAU,QAAQ,OAAO,EAAE,aAAa,MAAM,kBA8ClE,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,QAAQ,OAAO,GAAG,GAAG,SAU9C,CAAC;AAEF,QAAA,MAAM,YAAY,GAAU,QAAQ,OAAO,EAAE,QAAQ,GAAG,kBAoBvD,CAAC;AAEF,QAAA,MAAM,YAAY,GAAI,QAAQ,OAAO,SAgEpC,CAAC;AAEF,QAAA,MAAM,aAAa,GAAI,QAAQ,OAAO,SAGrC,CAAC;AAEF,QAAA,MAAM,uBAAuB,GAAI,QAAQ,OAAO,EAAE,OAAO,GAAG,SAG3D,CAAC;AAEF,QAAA,MAAM,gBAAgB,GAAI,QAAQ,OAAO,EAAE,MAAM,GAAG,SAGnD,CAAC;AAEF,QAAA,MAAM,cAAc,GAAI,QAAQ,OAAO,EAAE,MAAM,GAAG,SAsDjD,CAAC;AAKF,QAAA,MAAM,cAAc,GAAI,SAAS,OAAO,EAAE,QAAQ,GAAG,SAAO,CAAC;AAC7D,QAAA,MAAM,iBAAiB,GAAI,SAAS,OAAO,SAAO,CAAC;AACnD,QAAA,MAAM,iBAAiB,GAAI,SAAS,OAAO,SAAO,CAAC;AACnD,QAAA,MAAM,YAAY,GAAI,SAAS,OAAO,SAAO,CAAC;AAE9C,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,aAAa,EACb,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,GACb,CAAC"}
@@ -1,12 +1,16 @@
1
+ import { type ReadTimestampHeapState } from '../../helpers/getServerReadTimestamp';
2
+ import type { IMessage } from '../../types/types';
1
3
  interface RoomLike {
2
4
  jid: string;
3
5
  lastViewedTimestamp?: number;
4
6
  unreadMessages?: number;
7
+ messages?: IMessage[];
5
8
  }
6
9
  interface FlushOpts {
7
10
  visibleRoomJID?: string | null;
8
11
  visibleRoomTs?: number | null;
9
12
  onlyIfNoUnread?: boolean;
13
+ heapState?: ReadTimestampHeapState;
10
14
  }
11
15
  /**
12
16
  * Merge in-memory lastViewedTimestamp values into the server-side
@@ -15,8 +19,11 @@ interface FlushOpts {
15
19
  * each other's entries.
16
20
  *
17
21
  * Called on: tab change away from chat, AppState background/inactive,
18
- * and (with onlyIfNoUnread=true) logout. ChatRoom's own unmount path
19
- * still uses actionSetTimestampToPrivateStore for the single-room case.
22
+ * and (with onlyIfNoUnread=true) logout. ChatRoom's own unmount path also
23
+ * goes through this (via flushLastViewedToPrivateStoreStanza) for the
24
+ * single-room case - actionSetTimestampToPrivateStore is a separate,
25
+ * unconditional low-level write primitive kept for direct/external use
26
+ * and is not part of this merge path.
20
27
  */
21
28
  export declare function flushLastViewedToPrivateStore(client: any, rooms: Record<string, RoomLike> | null | undefined, opts?: FlushOpts): Promise<boolean>;
22
29
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"flushLastViewedToPrivateStore.d.ts","sourceRoot":"","sources":["../../../../src/networking/xmpp/flushLastViewedToPrivateStore.ts"],"names":[],"mappings":"AAGA,UAAU,QAAQ;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,SAAS;IAIjB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAQ/B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAI9B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,GAAG,EACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,GAAG,SAAS,EAClD,IAAI,GAAE,SAAc,GACnB,OAAO,CAAC,OAAO,CAAC,CAuDlB"}
1
+ {"version":3,"file":"flushLastViewedToPrivateStore.d.ts","sourceRoot":"","sources":["../../../../src/networking/xmpp/flushLastViewedToPrivateStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,UAAU,QAAQ;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IAGxB,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED,UAAU,SAAS;IAKjB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAQ/B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAI9B,cAAc,CAAC,EAAE,OAAO,CAAC;IAMzB,SAAS,CAAC,EAAE,sBAAsB,CAAC;CACpC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,GAAG,EACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,GAAG,SAAS,EAClD,IAAI,GAAE,SAAc,GACnB,OAAO,CAAC,OAAO,CAAC,CAmFlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"xmppClient.d.ts","sourceRoot":"","sources":["../../../src/networking/xmppClient.ts"],"names":[],"mappings":"AAAA,OAAa,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAgFvD,KAAK,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,CAAC;AAEtE,UAAU,cAAc;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAeD,MAAM,MAAM,uBAAuB,GAAG,MAAM,OAAO,CAAC;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,qBAAa,UAAU;IACrB,MAAM,EAAG,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,qBAAqB,CAAC;IACrC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAM;IAClB,OAAO,EAAE,MAAM,CAAM;IACrB,UAAU,EAAE,MAAM,CAAM;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,QAAQ,GAAG,OAAO,CAAa;IAElE,QAAQ,SAAM;IACd,iBAAiB,SAAK;IACtB,oBAAoB,SAAK;IACzB,cAAc,SAAQ;IAItB,iBAAiB,SAAS;IAI1B,OAAO,CAAC,eAAe,CAAK;IAC5B,iBAAiB,UAAS;IAI1B,OAAO,CAAC,cAAc,CAA8C;IAMpE,OAAO,CAAC,YAAY,CAAS;IAK7B,aAAa,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAC9C;;;;OAIG;IACH,OAAO,CAAC,sBAAsB,CAAK;IACnC,OAAO,CAAC,mBAAmB,CAAwC;IACnE,OAAO,CAAC,0BAA0B,CAA8B;IAGhE,OAAO,CAAC,gBAAgB,CAA6B;IAGrD,cAAc,UAAS;IACvB,eAAe,UAAS;IACxB,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,iBAAiB,CAA4C;IACrE,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,oBAAoB,CAAO;IACnC,OAAO,CAAC,oBAAoB,CAAQ;IACpC,OAAO,CAAC,0BAA0B,CAAQ;IAI1C,WAAW;IAIX;;;;;;OAMG;IACH,sBAAsB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,IAAI;IAI/D;yDACqD;IACrD,WAAW,CAAC,EAAE,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI;IAInC,2DAA2D;IAC3D,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;gBAMlD,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,qBAAqB,GAAG,MAAM;IAgC/C,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKvC,kBAAkB,CAAC,QAAQ,EAAE,MAAM;IAInC;;;OAGG;IACH,oBAAoB,IAAI,OAAO;IAM/B,uEAAuE;IACvE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAKnD;;;;OAIG;IACG,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS/D;;;;OAIG;IACG,kBAAkB,CAAC,MAAM,EAAE;QAC/B,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,aAAa,CAAC;KACxB,GAAG,OAAO,CAAC,GAAG,CAAC;IA8ChB,OAAO,CAAC,UAAU;IAalB,gBAAgB;IAqHhB,OAAO,CAAC,YAAY,CAAC,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,CAAa;IAC9B,OAAO,CAAC,OAAO,CAAC,CAAuB;IACvC,OAAO,CAAC,QAAQ,CAAC,CAAwB;IAEzC,oBAAoB;IAkGpB,oBAAoB;IAepB;;;OAGG;IACH,aAAa,CAAC,SAAS,GAAE,MAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBvD,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,iBAAiB;IA4BjB;;;;;OAKG;IACH,cAAc;IAkBd,OAAO,CAAC,gBAAgB,CAAiC;IAEzD,iBAAiB,CAAC,SAAS,GAAE,MAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAgCvD,iBAAiB,CAAC,SAAS,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1D,SAAS;IA8Ef;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IA0B9B,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,oBAAoB,CAAS;YAEvB,iBAAiB;IAuBzB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAY9B,4EAA4E;IAC5E,MAAM,IAAI,IAAI;IAOd,IAAI,WAAW,IAAI,OAAO,CAEzB;IAEK,UAAU,CAAC,OAAO,CAAC,EAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAKpE,KAAK;IAgCX,cAAc,sBAEZ;IAII,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM;IAIhE,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAIzD,kBAAkB,GAAI,SAAS,MAAM,UAEnC;IAEF,oBAAoB,GAAI,SAAS,MAAM,UAErC;IAEF,gBAAgB,GACd,SAAS,MAAM,EACf,KAAK,MAAM,EACX,SAAS,MAAM,EACf,KAAK,MAAM,EACX,UAAU,cAAc,kBAYxB;IAEF,2BAA2B,CAAC,OAAO,EAAE,MAAM;IAI3C,kBAAkB,GAChB,SAAS,MAAM,EACf,eAAe,MAAM,EACrB,MAAM,MAAM,EACZ,iBAAiB,MAAM,UAGvB;IAEF,iBAAiB,GAAI,SAAS,MAAM,UAElC;IAEF,oBAAoB,GAAI,SAAS,MAAM,UAErC;IAEF;;;;;OAKG;IACH,OAAO,CAAC,aAAa;IAIrB,wEAAwE;IACxE,iBAAiB;IAKjB,WAAW,GACT,SAAS,MAAM,EACf,WAAW,MAAM,EACjB,UAAU,MAAM,EAChB,OAAO,MAAM,EACb,eAAe,MAAM,EACrB,aAAa,MAAM,EACnB,oBAAoB,MAAM,EAC1B,UAAU,OAAO,EACjB,gBAAgB,OAAO,EACvB,cAAc,MAAM,EACpB,WAAW,MAAM,KAChB,OAAO,CA0CR;IAEF,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAI/C,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAI3D,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;IAIxE,iCAAiC,yBA6B/B;IAEI,sCAAsC,CAC1C,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,MAAM,EAAE;IAgBZ,mCAAmC,CACvC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,SAAS,EAC7C,IAAI,GAAE;QACJ,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC/B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;KACrB;IAUR,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM;IA8BpE,cAAc,CAAC,aAAa,EAAE,MAAM;IAI9B,uBAAuB,CAC3B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,MAAM,CAAC;IAMlB,yBAAyB,CACvB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EAAE,EACxB,eAAe,CAAC,EAAE,MAAM;IAY1B,qCAAqC,CACnC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,iBAAiB,CAAC,EAAE,MAAM,EAC1B,OAAO,CAAC,EAAE,OAAO,EACjB,aAAa,CAAC,EAAE,OAAO,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO;CA4CX;AAED,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"xmppClient.d.ts","sourceRoot":"","sources":["../../../src/networking/xmppClient.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/roomStore/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAOvC,QAAA,MAAM,WAAW;;;;;;;;;;GAQf,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAmCvD,eAAO,MAAM,KAAK;;;;;;;;;;;;oCAEgC,CAAC;AAEnD,MAAM,MAAM,WAAW,GAAG,OAAO,KAAK,CAAC,QAAQ,CAAC;AAEhD,eAAO,MAAM,aAAa,GAAI,OAAO,SAAS,KAAG,KAAK,GAAG,IAKxD,CAAC;AAGF,eAAO,MAAM,cAAc,eAapB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/roomStore/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAWvC,QAAA,MAAM,WAAW;;;;;;;;;;GAQf,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAmCvD,eAAO,MAAM,KAAK;;;;;;;;;;;;oCAEgC,CAAC;AAEnD,MAAM,MAAM,WAAW,GAAG,OAAO,KAAK,CAAC,QAAQ,CAAC;AAEhD,eAAO,MAAM,aAAa,GAAI,OAAO,SAAS,KAAG,KAAK,GAAG,IAKxD,CAAC;AAIF,eAAO,MAAM,cAAc,eA4CpB,CAAC"}
@@ -1,12 +1,27 @@
1
1
  import { Middleware } from '@reduxjs/toolkit';
2
- import { IRoom, User } from '../types/types';
2
+ import { IMessage, IRoom, User } from '../types/types';
3
+ import type { FailedMessagePayload } from './roomHeapSlice';
3
4
  export declare const MESSAGE_LIMIT = 100;
5
+ export declare const MAX_PERSISTED_FAILED_MESSAGES = 200;
4
6
  interface PersistedChatState {
5
7
  user: User;
6
8
  }
7
9
  interface PersistedRoomsState {
8
10
  rooms: Record<string, IRoom>;
9
11
  }
12
+ interface PersistedHeapState {
13
+ failedMessages: Record<string, FailedMessagePayload>;
14
+ }
15
+ export declare function reconstructFailedMessagePayload(message: IMessage, roomJID: string): FailedMessagePayload | null;
16
+ /**
17
+ * Scan every persisted room for messages still `pending: true` that
18
+ * DON'T already have a restored failure entry (those are handled by the
19
+ * caller separately, from the persisted `failedMessages` map), and
20
+ * synthesize a retry-able FailedMessagePayload for each. Pure function:
21
+ * the caller (roomStore/index.ts) is responsible for dispatching
22
+ * `markMessageFailed` for the results.
23
+ */
24
+ export declare function computeBootTimeFailures(rooms: Record<string, IRoom> | null | undefined, alreadyFailed: Record<string, FailedMessagePayload> | null | undefined): FailedMessagePayload[];
10
25
  /**
11
26
  * Middleware that debounces writes of the persisted slices to AsyncStorage.
12
27
  * Only triggers on actions that actually mutate persisted state.
@@ -20,11 +35,13 @@ export declare const persistenceMiddleware: Middleware;
20
35
  export declare function readPersistedState(): Promise<{
21
36
  chat: PersistedChatState | null;
22
37
  rooms: PersistedRoomsState | null;
38
+ heap: PersistedHeapState | null;
23
39
  }>;
24
40
  export declare function clearPersistedState(): Promise<void>;
25
41
  export declare const PERSIST_KEYS: {
26
42
  KEY_CHAT: string;
27
43
  KEY_ROOMS: string;
44
+ KEY_HEAP: string;
28
45
  };
29
46
  export {};
30
47
  //# sourceMappingURL=persistence.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../src/roomStore/persistence.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAY,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAyBvD,eAAO,MAAM,aAAa,MAAM,CAAC;AAEjC,UAAU,kBAAkB;IAC1B,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,UAAU,mBAAmB;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAE9B;AAoJD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,UA0CnC,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAClD,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACnC,CAAC,CAwBD;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMzD;AAED,eAAO,MAAM,YAAY;;;CAA0B,CAAC"}
1
+ {"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../../src/roomStore/persistence.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AA8B5D,eAAO,MAAM,aAAa,MAAM,CAAC;AAMjC,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD,UAAU,kBAAkB;IAC1B,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,UAAU,mBAAmB;IAC3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAE9B;AAED,UAAU,kBAAkB;IAC1B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CAKtD;AA4OD,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,QAAQ,EACjB,OAAO,EAAE,MAAM,GACd,oBAAoB,GAAG,IAAI,CAkC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,IAAI,GAAG,SAAS,EAC/C,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,IAAI,GAAG,SAAS,GACrE,oBAAoB,EAAE,CAaxB;AAID;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,UAkDnC,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC;IAClD,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACjC,CAAC,CA6BD;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMzD;AAED,eAAO,MAAM,YAAY;;;;CAAoC,CAAC"}
@@ -87,7 +87,19 @@ declare const reducers: {
87
87
  *
88
88
  * Monotonic: a marker only ever moves a baseline FORWARD, so a stale
89
89
  * server value can't resurrect already-read messages and a more-recent
90
- * local read (tab blur stamping Date.now()) always wins.
90
+ * local read (tab blur stamping the server read timestamp) always wins.
91
+ *
92
+ * Bug #38 self-heal: forward-only is correct for a SANE existing
93
+ * value, but a device whose clock was ahead may have already stamped
94
+ * a marker in the future (either persisted locally from a previous
95
+ * session, or fetched from the server before this fix existed). To
96
+ * "only ever move forward" from a corrupt future value is to never
97
+ * move at all - the room would stay stuck at `unreadMessages: 0`
98
+ * forever. When the room is loaded, detect a marker that sits well
99
+ * past the newest message we actually know it has and waive the
100
+ * forward-only check for that one comparison, so the incoming
101
+ * (already-clamped, see xmppClient.getChatsPrivateStoreRequestStanza)
102
+ * value can correct it even though it's numerically smaller.
91
103
  */
92
104
  applyPrivateStoreMarkers: (state: WritableDraft<RoomMessagesState>, action: PayloadAction<Record<string, number>>) => void;
93
105
  setRoomRole: (state: WritableDraft<RoomMessagesState>, action: PayloadAction<{
@@ -1 +1 @@
1
- {"version":3,"file":"roomsSlice.d.ts","sourceRoot":"","sources":["../../../src/roomStore/roomsSlice.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"roomsSlice.d.ts","sourceRoot":"","sources":["../../../src/roomStore/roomsSlice.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ethora/chat-component-rn",
3
- "version": "26.7.7",
3
+ "version": "26.7.9",
4
4
  "description": "Drop-in XMPP chat component for React Native / Expo. <Chat config={...}/> and you're done.",
5
5
  "main": "index.js",
6
6
  "module": "lib/module/main.js",
@@ -28,6 +28,7 @@ import { IConfig } from '../../types/models/config.model';
28
28
  import { useRoomInitialization } from '../../hooks/useRoomInitialization';
29
29
  import { useRoomState } from '../../hooks/useRoomState';
30
30
  import { useChatSettingState } from '../../hooks/useChatSettingState';
31
+ import { isOwnMessage } from '../../helpers/isOwnMessage';
31
32
  import CustomTypingIndicator from '../styled/StyledInputComponents/CustomTypingIndicator';
32
33
  // import {PanGestureHandler} from 'react-native-gesture-handler';
33
34
  import { FlatList } from 'react-native';
@@ -46,6 +47,7 @@ import {
46
47
  } from 'react-native-keyboard-controller';
47
48
  import useComposing from '../../hooks/useComposing';
48
49
  import { store } from '../../roomStore';
50
+ import { getServerReadTimestamp } from '../../helpers/getServerReadTimestamp';
49
51
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
50
52
  import {
51
53
  getInputDockPaddingBottom,
@@ -234,21 +236,30 @@ const ChatRoom: React.FC<ChatRoomProps> = React.memo(
234
236
  dispatch(setVisibleRoom({ roomJID: activeRoomJID }));
235
237
  setIsLoadingMore(false);
236
238
  return () => {
237
- const timestamp = readBoundaryRef.current ?? new Date().getTime();
238
- dispatch(
239
- setLastViewedTimestamp({
240
- chatJID: activeRoomJID,
241
- timestamp,
242
- }),
243
- );
239
+ const rooms = store.getState().rooms?.rooms;
240
+ const heapState = store.getState().roomHeapSlice;
241
+ // Fall back to the newest server-acked message, never the device
242
+ // clock: a fast device clock would write a future marker that the
243
+ // forward-only private-store merge could never correct (bug #38).
244
+ const timestamp =
245
+ readBoundaryRef.current ??
246
+ getServerReadTimestamp(rooms?.[activeRoomJID], heapState);
247
+ if (timestamp > 0) {
248
+ dispatch(
249
+ setLastViewedTimestamp({
250
+ chatJID: activeRoomJID,
251
+ timestamp,
252
+ }),
253
+ );
254
+ }
244
255
  dispatch(clearVisibleRoom());
245
256
  const liveClient = clientRef.current;
246
257
  if (liveClient) {
247
258
  liveClient
248
- .flushLastViewedToPrivateStoreStanza(store.getState().rooms?.rooms, {
259
+ .flushLastViewedToPrivateStoreStanza(rooms, {
249
260
  visibleRoomJID: activeRoomJID,
250
261
  // Carry the same boundary to the SERVER marker. Without
251
- // this the flush defaults to Date.now() for the visible
262
+ // this the flush defaults to "everything" for the visible
252
263
  // room, so messages the user never scrolled down to come
253
264
  // back as read on the next login — the local count was
254
265
  // right but the server overrode it.
@@ -440,7 +451,7 @@ const ChatRoom: React.FC<ChatRoomProps> = React.memo(
440
451
  CustomMessageComponent ? (
441
452
  <CustomMessageComponent
442
453
  message={decorated.message}
443
- isUser={decorated.message.user.id === user.xmppUsername}
454
+ isUser={isOwnMessage(decorated.message, user)}
444
455
  isReply={false}
445
456
  />
446
457
  ) : null
@@ -11,7 +11,8 @@ import {
11
11
  Text,
12
12
  View,
13
13
  } from 'react-native';
14
- import { deriveDisplayFilename, isLikelyAudio } from '../../helpers/mimeToExtension';
14
+ import { isLikelyAudio } from '../../helpers/mimeToExtension';
15
+ import { getDisplayFileName } from '../../helpers/getDisplayFileName';
15
16
  import { FileIcon, PlayIcon } from '../../assets/icons';
16
17
  import { defaultMediaDims } from '../../helpers/mediaDimensions';
17
18
  import { useChatSettingState } from '../../hooks/useChatSettingState';
@@ -148,11 +149,11 @@ const MediaMessage: React.FC<MediaMessageProps> = ({
148
149
  const messageText = appendFileToken(rawMessageText, fileToken);
149
150
 
150
151
  if (mimeType) {
151
- const displayName = deriveDisplayFilename({
152
- fileName: message?.fileName,
152
+ const displayName = getDisplayFileName({
153
153
  originalName: (message as any)?.originalName,
154
- url: rawLocation || rawMessageText,
155
- mime: mimeType,
154
+ fileName: message?.fileName,
155
+ location: rawLocation || rawMessageText,
156
+ mimetype: mimeType,
156
157
  });
157
158
  const isAudioPayload = isLikelyAudio(
158
159
  mimeType,
@@ -180,6 +181,7 @@ const MediaMessage: React.FC<MediaMessageProps> = ({
180
181
  return (
181
182
  <CustomMessageImage
182
183
  fileName={displayName}
184
+ originalName={(message as any)?.originalName}
183
185
  // Full-size original: opened by the preview modal.
184
186
  fileURL={location || messageText || ''}
185
187
  // ...and the thumbnail the bubble actually renders, which is
@@ -192,6 +194,7 @@ const MediaMessage: React.FC<MediaMessageProps> = ({
192
194
  return (
193
195
  <CustomMessageVideo
194
196
  fileName={displayName}
197
+ originalName={(message as any)?.originalName}
195
198
  fileURL={location || ''}
196
199
  // `messageText` is the message's locationPreview — the poster
197
200
  // frame the backend generated for this video. Handing it over
@@ -1,5 +1,6 @@
1
1
  import React, { FC, Fragment, useMemo } from 'react';
2
2
  import { IConfig, IMessage } from '../../types/types';
3
+ import { isOwnMessage } from '../../helpers/isOwnMessage';
3
4
  import DateLabel from '../styled/DateLabel';
4
5
  import SystemMessage from './SystemMessage';
5
6
  import NewMessageLabel from '../styled/NewMessageLabel';
@@ -46,7 +47,10 @@ export const MessageContainer: FC<MessageContainerProps> = ({
46
47
  isReply,
47
48
  className,
48
49
  }) => {
49
- const isUser = message.user.id === walletAddress;
50
+ // Bug #41: `message.user.id === walletAddress` used to treat two
51
+ // empty/undefined ids as a match, briefly rendering catch-up messages
52
+ // from other users as our own. isOwnMessage() never does that.
53
+ const isUser = isOwnMessage(message, walletAddress);
50
54
 
51
55
  const messageDate = new Date(message.date);
52
56
 
@@ -29,6 +29,7 @@ import { ArowDownIcon } from '../../assets/icons';
29
29
  import CustomTypingIndicator from '../styled/StyledInputComponents/CustomTypingIndicator';
30
30
  import { getIconColor } from '../../helpers/getIconColor';
31
31
  import { getChatBackgroundColor } from '../../helpers/getChatBackground';
32
+ import { isOwnMessage } from '../../helpers/isOwnMessage';
32
33
 
33
34
  interface MessageListProps<TMessage extends IMessage> {
34
35
  CustomMessage?: React.ComponentType<{
@@ -438,7 +439,7 @@ const MessageList = <TMessage extends IMessage>({
438
439
  {CustomMessage && (
439
440
  <CustomMessage
440
441
  message={activeMessage}
441
- isUser={activeMessage.user.id === user.walletAddress}
442
+ isUser={isOwnMessage(activeMessage, user)}
442
443
  isReply={isReply}
443
444
  />
444
445
  )}
@@ -31,7 +31,12 @@ import { useToast } from '../../../context/ToastContext';
31
31
  import PdfViewer from './PdfView';
32
32
  import DocumentViewer from './DocumentViewer';
33
33
  import AudioMessage from '../../styled/AudioMessage';
34
- import { ensureFilenameHasExtension, isLikelyAudio } from '../../../helpers/mimeToExtension';
34
+ import { isLikelyAudio } from '../../../helpers/mimeToExtension';
35
+ import {
36
+ getDisplayFileName,
37
+ getUniqueFileName,
38
+ sanitizeFileNameForPath,
39
+ } from '../../../helpers/getDisplayFileName';
35
40
 
36
41
  // MIME types Google's gview embed renders reliably. Everything else
37
42
  // falls through to the info-card so the user can still download.
@@ -128,6 +133,19 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
128
133
 
129
134
  if (!activeFile) {return null;}
130
135
 
136
+ // Bug #40: prefer the sender's original name over the server's stored
137
+ // hash name everywhere this modal shows or saves/shares the file.
138
+ // Sanitized so it's safe to use as an actual path segment (strips path
139
+ // separators/control chars) when writing to disk below.
140
+ const displayFileName = sanitizeFileNameForPath(
141
+ getDisplayFileName({
142
+ originalName: activeFile.originalName,
143
+ fileName: activeFile.fileName,
144
+ location: activeFile.fileURL,
145
+ mimetype: activeFile.mimetype,
146
+ })
147
+ );
148
+
131
149
  const requestStoragePermission = async () => {
132
150
  const MediaLibrary = getMediaLibrary();
133
151
  if (!MediaLibrary?.requestPermissionsAsync) {return false;}
@@ -151,12 +169,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
151
169
  }
152
170
 
153
171
  try {
154
- const fileName = ensureFilenameHasExtension(
155
- activeFile.fileName,
156
- activeFile.mimetype
157
- );
158
-
159
- const filePath = FileSystem.cacheDirectory + fileName;
172
+ const filePath = FileSystem.cacheDirectory + displayFileName;
160
173
  const download = await FileSystem.downloadAsync(withFileToken(activeFile.fileURL), filePath);
161
174
 
162
175
  if (download.status === 200) {
@@ -171,17 +184,39 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
171
184
  Alert.alert('Error', 'Failed to save the file.');
172
185
  }
173
186
  } catch (err) {
174
- Alert.alert('Error', `Failed to save the file: ${activeFile.fileName}`);
187
+ Alert.alert('Error', `Failed to save the file: ${displayFileName}`);
188
+ }
189
+ };
190
+
191
+ // Best-effort existing-name lookup for the Android SAF branch below: SAF
192
+ // hands back content URIs, not plain names, so this decodes each one and
193
+ // takes its last path segment. If the provider's URI shape doesn't match
194
+ // what we expect, we fail open (empty set) rather than block the save -
195
+ // worst case we skip de-duplication, we never crash the save flow.
196
+ const listSafDirectoryNames = async (
197
+ saf: any,
198
+ dirUri: string
199
+ ): Promise<Set<string>> => {
200
+ try {
201
+ const uris: string[] = await saf.readDirectoryAsync(dirUri);
202
+ const names = uris.map((uri) => {
203
+ try {
204
+ const decoded = decodeURIComponent(uri);
205
+ const last = decoded.split('/').pop() || '';
206
+ return last.includes(':') ? last.split(':').pop() || '' : last;
207
+ } catch {
208
+ return '';
209
+ }
210
+ });
211
+ return new Set(names.filter(Boolean));
212
+ } catch {
213
+ return new Set<string>();
175
214
  }
176
215
  };
177
216
 
178
217
  const saveFileToDownloads = async () => {
179
218
  try {
180
- const fileName = ensureFilenameHasExtension(
181
- activeFile.fileName,
182
- activeFile.mimetype
183
- );
184
- const filePath = FileSystem.cacheDirectory + fileName;
219
+ const filePath = FileSystem.cacheDirectory + displayFileName;
185
220
  const download = await FileSystem.downloadAsync(withFileToken(activeFile.fileURL), filePath);
186
221
 
187
222
  if (download.status !== 200) {
@@ -205,7 +240,16 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
205
240
  safDirUriRef.current = dirUri;
206
241
  }
207
242
 
208
- const baseName = fileName.replace(/\.[^/.]+$/, '');
243
+ // Avoid silently overwriting a different attachment that happens
244
+ // to share the same display name (common now that we prefer the
245
+ // human-picked name over the unique server hash - bug #40) by
246
+ // suffixing " (1)", " (2)", ... on a collision.
247
+ const existingNames = await listSafDirectoryNames(saf, dirUri as string);
248
+ const uniqueName = await getUniqueFileName(
249
+ displayFileName,
250
+ async (candidate) => existingNames.has(candidate)
251
+ );
252
+ const baseName = uniqueName.replace(/\.[^/.]+$/, '');
209
253
  const mime = activeFile.mimetype || 'application/octet-stream';
210
254
  const base64 = await FileSystem.readAsStringAsync(download.uri, {
211
255
  encoding: FileSystem.EncodingType.Base64,
@@ -232,7 +276,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
232
276
  // user may cancel), so we don't show a "Save successful" toast here.
233
277
  await Share.share({
234
278
  url: download.uri,
235
- title: fileName,
279
+ title: displayFileName,
236
280
  });
237
281
  } catch (err) {
238
282
  console.error('Error saving file:', err);
@@ -279,7 +323,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
279
323
  'https://as2.ftcdn.net/v2/jpg/02/51/95/53/1000_F_251955356_FAQH0U1y1TZw3ZcdPGybwUkH90a3VAhb.jpg',
280
324
  }}
281
325
  resizeMode="contain"
282
- accessibilityLabel={activeFile.fileName}
326
+ accessibilityLabel={displayFileName}
283
327
  />
284
328
  );
285
329
  case activeFile.mimetype.startsWith('video/'):
@@ -333,10 +377,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
333
377
  }}
334
378
  >
335
379
  <Text style={{ fontSize: 16, fontWeight: '600' }}>
336
- {ensureFilenameHasExtension(
337
- activeFile.originalName || activeFile.fileName,
338
- activeFile.mimetype
339
- )}
380
+ {displayFileName}
340
381
  </Text>
341
382
  <AudioMessage
342
383
  src={withFileToken(activeFile.fileURL)}
@@ -351,10 +392,6 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
351
392
  case activeFile.mimetype === 'application/pdf':
352
393
  return <PdfViewer pdfUrl={withFileToken(activeFile.fileURL)} />;
353
394
  default: {
354
- const displayName = ensureFilenameHasExtension(
355
- activeFile.fileName,
356
- activeFile.mimetype
357
- );
358
395
  // Office docs (.docx / .xlsx / .pptx / .doc / .xls / .ppt /
359
396
  // .txt / .csv / .rtf) → render inline via Google's gview embed
360
397
  // — fixes the "blank preview" complaint for docs (bug #9).
@@ -362,7 +399,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
362
399
  return (
363
400
  <DocumentViewer
364
401
  url={activeFile.fileURL}
365
- fileName={displayName}
402
+ fileName={displayFileName}
366
403
  />
367
404
  );
368
405
  }
@@ -379,7 +416,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
379
416
  }}
380
417
  >
381
418
  <Text style={{ fontSize: 16, fontWeight: '600' }}>
382
- {displayName}
419
+ {displayFileName}
383
420
  </Text>
384
421
  <Text style={{ color: '#666' }}>
385
422
  {activeFile.mimetype || 'unknown type'}
@@ -14,9 +14,13 @@ import {
14
14
  isSecureFileUrl,
15
15
  requestFileTokenRecovery,
16
16
  } from '../../../helpers/secureFileUrl';
17
+ import { getDisplayFileName } from '../../../helpers/getDisplayFileName';
17
18
 
18
19
  interface LastMessageFileProps
19
- extends Pick<LastMessage, 'user' | 'originalName' | 'locationPreview'> {}
20
+ extends Pick<
21
+ LastMessage,
22
+ 'user' | 'originalName' | 'fileName' | 'mimetype' | 'locationPreview'
23
+ > {}
20
24
 
21
25
  const fallbackImage =
22
26
  'https://as2.ftcdn.net/v2/jpg/02/51/95/53/1000_F_251955356_FAQH0U1y1TZw3ZcdPGybwUkH90a3VAhb.jpg';
@@ -24,10 +28,18 @@ const fallbackImage =
24
28
  const LastMessageFile: FC<LastMessageFileProps> = ({
25
29
  user,
26
30
  originalName,
31
+ fileName,
32
+ mimetype,
27
33
  locationPreview,
28
34
  }) => {
29
35
  const [imgSrc, setImgSrc] = useState(locationPreview);
30
36
  const fileToken = useFileToken();
37
+ // Bug #40: prefer the sender's original name over the stored hash
38
+ // name; only fall back to the generic "file" label when neither is
39
+ // present at all (avoids a synthetic "media_<timestamp>.bin" here).
40
+ const displayName = originalName || fileName
41
+ ? getDisplayFileName({ originalName, fileName, mimetype })
42
+ : 'file';
31
43
 
32
44
  return (
33
45
  <LastRoomMessageContainer>
@@ -57,7 +69,7 @@ const LastMessageFile: FC<LastMessageFileProps> = ({
57
69
  ) : (
58
70
  <FileIcon style={{ width: '20px', height: '20px' }} />
59
71
  )}
60
- <LastRoomMessageText>{originalName || 'file'}</LastRoomMessageText>
72
+ <LastRoomMessageText>{displayName}</LastRoomMessageText>
61
73
  </View>
62
74
  </LastRoomMessageContainer>
63
75
  );
@@ -11,6 +11,7 @@ import {
11
11
  ShadeWrapper,
12
12
  } from './StyledRoomComponents';
13
13
  import { View } from 'react-native';
14
+ import { getDisplayFileName } from '../../../helpers/getDisplayFileName';
14
15
 
15
16
  const PhotoContainer = styled.View`
16
17
  position: relative;
@@ -25,14 +26,25 @@ const PhotoContainer = styled.View`
25
26
  `;
26
27
 
27
28
  interface LastMessagePhotoProps
28
- extends Pick<LastMessage, 'user' | 'originalName' | 'locationPreview'> {}
29
+ extends Pick<
30
+ LastMessage,
31
+ 'user' | 'originalName' | 'fileName' | 'mimetype' | 'locationPreview'
32
+ > {}
29
33
 
30
34
  const LastMessagePhoto: FC<LastMessagePhotoProps> = ({
31
35
  user,
32
36
  locationPreview,
33
37
  originalName,
38
+ fileName,
39
+ mimetype,
34
40
  }) => {
35
41
  const fileToken = useFileToken();
42
+ // Bug #40: prefer the sender's original name over the stored hash
43
+ // name; only fall back to the generic "file" label when neither is
44
+ // present at all (avoids a synthetic "media_<timestamp>.bin" here).
45
+ const displayName = originalName || fileName
46
+ ? getDisplayFileName({ originalName, fileName, mimetype })
47
+ : 'file';
36
48
  return (
37
49
  <LastRoomMessageContainer>
38
50
  <LastRoomMessageName>{user?.name || ''}:</LastRoomMessageName>
@@ -48,7 +60,7 @@ const LastMessagePhoto: FC<LastMessagePhotoProps> = ({
48
60
  <LastMessageImg src={appendFileToken(locationPreview, fileToken)} />
49
61
  </ShadeWrapper>
50
62
  </PhotoContainer>
51
- <LastRoomMessageText>{originalName || 'file'}</LastRoomMessageText>
63
+ <LastRoomMessageText>{displayName}</LastRoomMessageText>
52
64
  </View>
53
65
  </LastRoomMessageContainer>
54
66
  );