@ethora/chat-component-rn 26.5.21 → 26.6.10

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 (352) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +3 -3
  3. package/index.js +1 -1
  4. package/lib/commonjs/components/MainComponents/ChatHeader.js +20 -8
  5. package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
  6. package/lib/commonjs/components/MainComponents/ChatWrapper.js +17 -0
  7. package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
  8. package/lib/commonjs/components/MainComponents/LanguageSelectorButton.js +62 -0
  9. package/lib/commonjs/components/MainComponents/LanguageSelectorButton.js.map +1 -0
  10. package/lib/commonjs/components/MainComponents/LanguageSelectorModal.js +253 -0
  11. package/lib/commonjs/components/MainComponents/LanguageSelectorModal.js.map +1 -0
  12. package/lib/commonjs/components/MainComponents/RoomList.js +23 -9
  13. package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
  14. package/lib/commonjs/components/MessageBubble/Message.js +72 -11
  15. package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
  16. package/lib/commonjs/components/MessageBubble/MessageTranslate.js +160 -0
  17. package/lib/commonjs/components/MessageBubble/MessageTranslate.js.map +1 -0
  18. package/lib/commonjs/components/MessageBubble/TranslatedMessageBody.js +59 -0
  19. package/lib/commonjs/components/MessageBubble/TranslatedMessageBody.js.map +1 -0
  20. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +3 -3
  21. package/lib/commonjs/components/UsersList/UsersList.js +3 -1
  22. package/lib/commonjs/components/UsersList/UsersList.js.map +1 -1
  23. package/lib/commonjs/components/VideoCalls/CallButtons.js +159 -0
  24. package/lib/commonjs/components/VideoCalls/CallButtons.js.map +1 -0
  25. package/lib/commonjs/components/VideoCalls/CallIcons.js +328 -0
  26. package/lib/commonjs/components/VideoCalls/CallIcons.js.map +1 -0
  27. package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js +550 -0
  28. package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js.map +1 -0
  29. package/lib/commonjs/components/VideoCalls/VideoCallSession.js +636 -0
  30. package/lib/commonjs/components/VideoCalls/VideoCallSession.js.map +1 -0
  31. package/lib/commonjs/components/VideoCalls/livekitRuntime.js +91 -0
  32. package/lib/commonjs/components/VideoCalls/livekitRuntime.js.map +1 -0
  33. package/lib/commonjs/components/VideoCalls/useCallKeep.js +215 -0
  34. package/lib/commonjs/components/VideoCalls/useCallKeep.js.map +1 -0
  35. package/lib/commonjs/components/styled/AudioMessage.js +91 -33
  36. package/lib/commonjs/components/styled/AudioMessage.js.map +1 -1
  37. package/lib/commonjs/components/styled/RoomListComponents/index.js +13 -1
  38. package/lib/commonjs/components/styled/RoomListComponents/index.js.map +1 -1
  39. package/lib/commonjs/components/styled/SendInput.js +83 -49
  40. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  41. package/lib/commonjs/components/styled/StyledComponents.js +9 -4
  42. package/lib/commonjs/components/styled/StyledComponents.js.map +1 -1
  43. package/lib/commonjs/components/styled/StyledInputComponents/Composing.js +2 -0
  44. package/lib/commonjs/components/styled/StyledInputComponents/Composing.js.map +1 -1
  45. package/lib/commonjs/context/xmppProvider.js +10 -3
  46. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  47. package/lib/commonjs/helpers/callLogMessage.js +162 -0
  48. package/lib/commonjs/helpers/callLogMessage.js.map +1 -0
  49. package/lib/commonjs/helpers/callPush.js +61 -0
  50. package/lib/commonjs/helpers/callPush.js.map +1 -0
  51. package/lib/commonjs/helpers/constants/LANGUAGE_OPTIONS.js +24 -12
  52. package/lib/commonjs/helpers/constants/LANGUAGE_OPTIONS.js.map +1 -1
  53. package/lib/commonjs/helpers/createUserNameFromSetUser.js +51 -2
  54. package/lib/commonjs/helpers/createUserNameFromSetUser.js.map +1 -1
  55. package/lib/commonjs/helpers/getDataFromXml.js +19 -1
  56. package/lib/commonjs/helpers/getDataFromXml.js.map +1 -1
  57. package/lib/commonjs/helpers/incomingCallFromPush.js +74 -0
  58. package/lib/commonjs/helpers/incomingCallFromPush.js.map +1 -0
  59. package/lib/commonjs/helpers/insertMessageWithDelimiter.js +13 -1
  60. package/lib/commonjs/helpers/insertMessageWithDelimiter.js.map +1 -1
  61. package/lib/commonjs/helpers/isUnresolvedSenderId.js +32 -0
  62. package/lib/commonjs/helpers/isUnresolvedSenderId.js.map +1 -0
  63. package/lib/commonjs/hooks/useChatSettingState.js +2 -0
  64. package/lib/commonjs/hooks/useChatSettingState.js.map +1 -1
  65. package/lib/commonjs/hooks/useMessageTranslation.js +51 -0
  66. package/lib/commonjs/hooks/useMessageTranslation.js.map +1 -0
  67. package/lib/commonjs/hooks/usePushNotifications.js +13 -3
  68. package/lib/commonjs/hooks/usePushNotifications.js.map +1 -1
  69. package/lib/commonjs/hooks/useSendMessage.js +12 -2
  70. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  71. package/lib/commonjs/i18n/strings.js +1308 -0
  72. package/lib/commonjs/i18n/strings.js.map +1 -0
  73. package/lib/commonjs/i18n/useT.js +60 -0
  74. package/lib/commonjs/i18n/useT.js.map +1 -0
  75. package/lib/commonjs/main.js +44 -0
  76. package/lib/commonjs/main.js.map +1 -1
  77. package/lib/commonjs/networking/api-requests/push.api.js +34 -5
  78. package/lib/commonjs/networking/api-requests/push.api.js.map +1 -1
  79. package/lib/commonjs/networking/api-requests/rooms.api.js +108 -0
  80. package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
  81. package/lib/commonjs/networking/callTokenStanza.js +531 -0
  82. package/lib/commonjs/networking/callTokenStanza.js.map +1 -0
  83. package/lib/commonjs/networking/outboundQueue.js.map +1 -1
  84. package/lib/commonjs/networking/stanzaHandlers.js +75 -8
  85. package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
  86. package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js +47 -11
  87. package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
  88. package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js +2 -1
  89. package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
  90. package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +42 -5
  91. package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
  92. package/lib/commonjs/networking/xmppClient.js +78 -16
  93. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  94. package/lib/commonjs/roomStore/callSlice.js +144 -0
  95. package/lib/commonjs/roomStore/callSlice.js.map +1 -0
  96. package/lib/commonjs/roomStore/chatSettingsSlice.js +8 -2
  97. package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
  98. package/lib/commonjs/roomStore/index.js +7 -1
  99. package/lib/commonjs/roomStore/index.js.map +1 -1
  100. package/lib/commonjs/roomStore/persistence.js +69 -5
  101. package/lib/commonjs/roomStore/persistence.js.map +1 -1
  102. package/lib/commonjs/roomStore/roomsSlice.js +136 -6
  103. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  104. package/lib/commonjs/utils/translateModePolicy.js +33 -0
  105. package/lib/commonjs/utils/translateModePolicy.js.map +1 -0
  106. package/lib/module/components/MainComponents/ChatHeader.js +20 -8
  107. package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
  108. package/lib/module/components/MainComponents/ChatWrapper.js +17 -0
  109. package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
  110. package/lib/module/components/MainComponents/LanguageSelectorButton.js +57 -0
  111. package/lib/module/components/MainComponents/LanguageSelectorButton.js.map +1 -0
  112. package/lib/module/components/MainComponents/LanguageSelectorModal.js +246 -0
  113. package/lib/module/components/MainComponents/LanguageSelectorModal.js.map +1 -0
  114. package/lib/module/components/MainComponents/RoomList.js +23 -9
  115. package/lib/module/components/MainComponents/RoomList.js.map +1 -1
  116. package/lib/module/components/MessageBubble/Message.js +73 -12
  117. package/lib/module/components/MessageBubble/Message.js.map +1 -1
  118. package/lib/module/components/MessageBubble/MessageTranslate.js +155 -0
  119. package/lib/module/components/MessageBubble/MessageTranslate.js.map +1 -0
  120. package/lib/module/components/MessageBubble/TranslatedMessageBody.js +53 -0
  121. package/lib/module/components/MessageBubble/TranslatedMessageBody.js.map +1 -0
  122. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +3 -3
  123. package/lib/module/components/UsersList/UsersList.js +3 -1
  124. package/lib/module/components/UsersList/UsersList.js.map +1 -1
  125. package/lib/module/components/VideoCalls/CallButtons.js +154 -0
  126. package/lib/module/components/VideoCalls/CallButtons.js.map +1 -0
  127. package/lib/module/components/VideoCalls/CallIcons.js +309 -0
  128. package/lib/module/components/VideoCalls/CallIcons.js.map +1 -0
  129. package/lib/module/components/VideoCalls/VideoCallOverlay.js +544 -0
  130. package/lib/module/components/VideoCalls/VideoCallOverlay.js.map +1 -0
  131. package/lib/module/components/VideoCalls/VideoCallSession.js +630 -0
  132. package/lib/module/components/VideoCalls/VideoCallSession.js.map +1 -0
  133. package/lib/module/components/VideoCalls/livekitRuntime.js +83 -0
  134. package/lib/module/components/VideoCalls/livekitRuntime.js.map +1 -0
  135. package/lib/module/components/VideoCalls/useCallKeep.js +210 -0
  136. package/lib/module/components/VideoCalls/useCallKeep.js.map +1 -0
  137. package/lib/module/components/styled/AudioMessage.js +91 -33
  138. package/lib/module/components/styled/AudioMessage.js.map +1 -1
  139. package/lib/module/components/styled/RoomListComponents/index.js +13 -1
  140. package/lib/module/components/styled/RoomListComponents/index.js.map +1 -1
  141. package/lib/module/components/styled/SendInput.js +83 -49
  142. package/lib/module/components/styled/SendInput.js.map +1 -1
  143. package/lib/module/components/styled/StyledComponents.js +9 -4
  144. package/lib/module/components/styled/StyledComponents.js.map +1 -1
  145. package/lib/module/components/styled/StyledInputComponents/Composing.js +2 -0
  146. package/lib/module/components/styled/StyledInputComponents/Composing.js.map +1 -1
  147. package/lib/module/context/xmppProvider.js +11 -4
  148. package/lib/module/context/xmppProvider.js.map +1 -1
  149. package/lib/module/helpers/callLogMessage.js +152 -0
  150. package/lib/module/helpers/callLogMessage.js.map +1 -0
  151. package/lib/module/helpers/callPush.js +55 -0
  152. package/lib/module/helpers/callPush.js.map +1 -0
  153. package/lib/module/helpers/constants/LANGUAGE_OPTIONS.js +24 -12
  154. package/lib/module/helpers/constants/LANGUAGE_OPTIONS.js.map +1 -1
  155. package/lib/module/helpers/createUserNameFromSetUser.js +49 -1
  156. package/lib/module/helpers/createUserNameFromSetUser.js.map +1 -1
  157. package/lib/module/helpers/getDataFromXml.js +20 -1
  158. package/lib/module/helpers/getDataFromXml.js.map +1 -1
  159. package/lib/module/helpers/incomingCallFromPush.js +70 -0
  160. package/lib/module/helpers/incomingCallFromPush.js.map +1 -0
  161. package/lib/module/helpers/insertMessageWithDelimiter.js +13 -1
  162. package/lib/module/helpers/insertMessageWithDelimiter.js.map +1 -1
  163. package/lib/module/helpers/isUnresolvedSenderId.js +27 -0
  164. package/lib/module/helpers/isUnresolvedSenderId.js.map +1 -0
  165. package/lib/module/hooks/useChatSettingState.js +2 -0
  166. package/lib/module/hooks/useChatSettingState.js.map +1 -1
  167. package/lib/module/hooks/useMessageTranslation.js +46 -0
  168. package/lib/module/hooks/useMessageTranslation.js.map +1 -0
  169. package/lib/module/hooks/usePushNotifications.js +13 -3
  170. package/lib/module/hooks/usePushNotifications.js.map +1 -1
  171. package/lib/module/hooks/useSendMessage.js +12 -2
  172. package/lib/module/hooks/useSendMessage.js.map +1 -1
  173. package/lib/module/i18n/strings.js +1300 -0
  174. package/lib/module/i18n/strings.js.map +1 -0
  175. package/lib/module/i18n/useT.js +55 -0
  176. package/lib/module/i18n/useT.js.map +1 -0
  177. package/lib/module/main.js +7 -1
  178. package/lib/module/main.js.map +1 -1
  179. package/lib/module/networking/api-requests/push.api.js +35 -5
  180. package/lib/module/networking/api-requests/push.api.js.map +1 -1
  181. package/lib/module/networking/api-requests/rooms.api.js +109 -1
  182. package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
  183. package/lib/module/networking/callTokenStanza.js +526 -0
  184. package/lib/module/networking/callTokenStanza.js.map +1 -0
  185. package/lib/module/networking/outboundQueue.js.map +1 -1
  186. package/lib/module/networking/stanzaHandlers.js +76 -9
  187. package/lib/module/networking/stanzaHandlers.js.map +1 -1
  188. package/lib/module/networking/xmpp/handleStanzas.xmpp.js +48 -11
  189. package/lib/module/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
  190. package/lib/module/networking/xmpp/sendTextMessage.xmpp.js +1 -1
  191. package/lib/module/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
  192. package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +43 -5
  193. package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
  194. package/lib/module/networking/xmppClient.js +78 -16
  195. package/lib/module/networking/xmppClient.js.map +1 -1
  196. package/lib/module/roomStore/callSlice.js +130 -0
  197. package/lib/module/roomStore/callSlice.js.map +1 -0
  198. package/lib/module/roomStore/chatSettingsSlice.js +6 -1
  199. package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
  200. package/lib/module/roomStore/index.js +6 -1
  201. package/lib/module/roomStore/index.js.map +1 -1
  202. package/lib/module/roomStore/persistence.js +69 -5
  203. package/lib/module/roomStore/persistence.js.map +1 -1
  204. package/lib/module/roomStore/roomsSlice.js +134 -5
  205. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  206. package/lib/module/utils/translateModePolicy.js +27 -0
  207. package/lib/module/utils/translateModePolicy.js.map +1 -0
  208. package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
  209. package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
  210. package/lib/typescript/components/MainComponents/LanguageSelectorButton.d.ts +12 -0
  211. package/lib/typescript/components/MainComponents/LanguageSelectorButton.d.ts.map +1 -0
  212. package/lib/typescript/components/MainComponents/LanguageSelectorModal.d.ts +31 -0
  213. package/lib/typescript/components/MainComponents/LanguageSelectorModal.d.ts.map +1 -0
  214. package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
  215. package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
  216. package/lib/typescript/components/MessageBubble/MessageTranslate.d.ts +44 -0
  217. package/lib/typescript/components/MessageBubble/MessageTranslate.d.ts.map +1 -0
  218. package/lib/typescript/components/MessageBubble/TranslatedMessageBody.d.ts +24 -0
  219. package/lib/typescript/components/MessageBubble/TranslatedMessageBody.d.ts.map +1 -0
  220. package/lib/typescript/components/UsersList/UsersList.d.ts.map +1 -1
  221. package/lib/typescript/components/VideoCalls/CallButtons.d.ts +16 -0
  222. package/lib/typescript/components/VideoCalls/CallButtons.d.ts.map +1 -0
  223. package/lib/typescript/components/VideoCalls/CallIcons.d.ts +30 -0
  224. package/lib/typescript/components/VideoCalls/CallIcons.d.ts.map +1 -0
  225. package/lib/typescript/components/VideoCalls/VideoCallOverlay.d.ts +10 -0
  226. package/lib/typescript/components/VideoCalls/VideoCallOverlay.d.ts.map +1 -0
  227. package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts +38 -0
  228. package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts.map +1 -0
  229. package/lib/typescript/components/VideoCalls/livekitRuntime.d.ts +52 -0
  230. package/lib/typescript/components/VideoCalls/livekitRuntime.d.ts.map +1 -0
  231. package/lib/typescript/components/VideoCalls/useCallKeep.d.ts +32 -0
  232. package/lib/typescript/components/VideoCalls/useCallKeep.d.ts.map +1 -0
  233. package/lib/typescript/components/styled/AudioMessage.d.ts.map +1 -1
  234. package/lib/typescript/components/styled/RoomListComponents/index.d.ts.map +1 -1
  235. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  236. package/lib/typescript/components/styled/StyledComponents.d.ts.map +1 -1
  237. package/lib/typescript/components/styled/StyledInputComponents/Composing.d.ts.map +1 -1
  238. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  239. package/lib/typescript/helpers/callLogMessage.d.ts +34 -0
  240. package/lib/typescript/helpers/callLogMessage.d.ts.map +1 -0
  241. package/lib/typescript/helpers/callPush.d.ts +23 -0
  242. package/lib/typescript/helpers/callPush.d.ts.map +1 -0
  243. package/lib/typescript/helpers/constants/LANGUAGE_OPTIONS.d.ts +14 -0
  244. package/lib/typescript/helpers/constants/LANGUAGE_OPTIONS.d.ts.map +1 -1
  245. package/lib/typescript/helpers/createUserNameFromSetUser.d.ts +33 -1
  246. package/lib/typescript/helpers/createUserNameFromSetUser.d.ts.map +1 -1
  247. package/lib/typescript/helpers/getDataFromXml.d.ts.map +1 -1
  248. package/lib/typescript/helpers/incomingCallFromPush.d.ts +14 -0
  249. package/lib/typescript/helpers/incomingCallFromPush.d.ts.map +1 -0
  250. package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts.map +1 -1
  251. package/lib/typescript/helpers/isUnresolvedSenderId.d.ts +2 -0
  252. package/lib/typescript/helpers/isUnresolvedSenderId.d.ts.map +1 -0
  253. package/lib/typescript/hooks/useChatSettingState.d.ts +2 -1
  254. package/lib/typescript/hooks/useChatSettingState.d.ts.map +1 -1
  255. package/lib/typescript/hooks/useMessageTranslation.d.ts +25 -0
  256. package/lib/typescript/hooks/useMessageTranslation.d.ts.map +1 -0
  257. package/lib/typescript/hooks/usePushNotifications.d.ts.map +1 -1
  258. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  259. package/lib/typescript/i18n/strings.d.ts +16 -0
  260. package/lib/typescript/i18n/strings.d.ts.map +1 -0
  261. package/lib/typescript/i18n/useT.d.ts +34 -0
  262. package/lib/typescript/i18n/useT.d.ts.map +1 -0
  263. package/lib/typescript/main.d.ts +6 -1
  264. package/lib/typescript/main.d.ts.map +1 -1
  265. package/lib/typescript/networking/api-requests/push.api.d.ts.map +1 -1
  266. package/lib/typescript/networking/api-requests/rooms.api.d.ts +3 -0
  267. package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
  268. package/lib/typescript/networking/callTokenStanza.d.ts +14 -0
  269. package/lib/typescript/networking/callTokenStanza.d.ts.map +1 -0
  270. package/lib/typescript/networking/outboundQueue.d.ts +1 -0
  271. package/lib/typescript/networking/outboundQueue.d.ts.map +1 -1
  272. package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
  273. package/lib/typescript/networking/xmpp/handleStanzas.xmpp.d.ts.map +1 -1
  274. package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts +10 -0
  275. package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts.map +1 -1
  276. package/lib/typescript/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts +16 -1
  277. package/lib/typescript/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts.map +1 -1
  278. package/lib/typescript/networking/xmppClient.d.ts +1 -1
  279. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  280. package/lib/typescript/roomStore/callSlice.d.ts +39 -0
  281. package/lib/typescript/roomStore/callSlice.d.ts.map +1 -0
  282. package/lib/typescript/roomStore/chatSettingsSlice.d.ts +10 -1
  283. package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
  284. package/lib/typescript/roomStore/index.d.ts +4 -0
  285. package/lib/typescript/roomStore/index.d.ts.map +1 -1
  286. package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
  287. package/lib/typescript/roomStore/roomsSlice.d.ts +6 -1
  288. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  289. package/lib/typescript/types/models/language.model.d.ts +1 -1
  290. package/lib/typescript/types/models/language.model.d.ts.map +1 -1
  291. package/lib/typescript/types/models/message.model.d.ts +7 -0
  292. package/lib/typescript/types/models/message.model.d.ts.map +1 -1
  293. package/lib/typescript/types/types.d.ts +135 -1
  294. package/lib/typescript/types/types.d.ts.map +1 -1
  295. package/lib/typescript/utils/translateModePolicy.d.ts +20 -0
  296. package/lib/typescript/utils/translateModePolicy.d.ts.map +1 -0
  297. package/package.json +20 -4
  298. package/src/components/MainComponents/ChatHeader.tsx +30 -9
  299. package/src/components/MainComponents/ChatWrapper.tsx +15 -0
  300. package/src/components/MainComponents/LanguageSelectorButton.tsx +53 -0
  301. package/src/components/MainComponents/LanguageSelectorModal.tsx +276 -0
  302. package/src/components/MainComponents/RoomList.tsx +27 -9
  303. package/src/components/MessageBubble/Message.tsx +109 -17
  304. package/src/components/MessageBubble/MessageTranslate.tsx +182 -0
  305. package/src/components/MessageBubble/TranslatedMessageBody.tsx +59 -0
  306. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +3 -3
  307. package/src/components/UsersList/UsersList.tsx +3 -1
  308. package/src/components/VideoCalls/CallButtons.tsx +171 -0
  309. package/src/components/VideoCalls/CallIcons.tsx +246 -0
  310. package/src/components/VideoCalls/VideoCallOverlay.tsx +627 -0
  311. package/src/components/VideoCalls/VideoCallSession.tsx +675 -0
  312. package/src/components/VideoCalls/livekitRuntime.ts +100 -0
  313. package/src/components/VideoCalls/useCallKeep.ts +252 -0
  314. package/src/components/styled/AudioMessage.tsx +97 -37
  315. package/src/components/styled/RoomListComponents/index.tsx +15 -3
  316. package/src/components/styled/SendInput.tsx +94 -51
  317. package/src/components/styled/StyledComponents.ts +9 -6
  318. package/src/components/styled/StyledInputComponents/Composing.tsx +7 -1
  319. package/src/context/xmppProvider.tsx +14 -1
  320. package/src/helpers/callLogMessage.ts +174 -0
  321. package/src/helpers/callPush.ts +90 -0
  322. package/src/helpers/constants/LANGUAGE_OPTIONS.ts +20 -5
  323. package/src/helpers/createUserNameFromSetUser.ts +68 -2
  324. package/src/helpers/getDataFromXml.ts +40 -4
  325. package/src/helpers/incomingCallFromPush.ts +83 -0
  326. package/src/helpers/insertMessageWithDelimiter.ts +27 -9
  327. package/src/helpers/isUnresolvedSenderId.ts +25 -0
  328. package/src/hooks/useChatSettingState.tsx +4 -0
  329. package/src/hooks/useMessageTranslation.ts +70 -0
  330. package/src/hooks/usePushNotifications.ts +15 -3
  331. package/src/hooks/useSendMessage.tsx +15 -2
  332. package/src/i18n/strings.ts +1322 -0
  333. package/src/i18n/useT.ts +56 -0
  334. package/src/main.ts +18 -1
  335. package/src/networking/api-requests/push.api.ts +39 -8
  336. package/src/networking/api-requests/rooms.api.ts +109 -1
  337. package/src/networking/callTokenStanza.ts +636 -0
  338. package/src/networking/outboundQueue.ts +1 -0
  339. package/src/networking/stanzaHandlers.ts +74 -15
  340. package/src/networking/xmpp/handleStanzas.xmpp.ts +52 -11
  341. package/src/networking/xmpp/sendTextMessage.xmpp.ts +1 -1
  342. package/src/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.ts +41 -5
  343. package/src/networking/xmppClient.ts +97 -28
  344. package/src/roomStore/callSlice.ts +190 -0
  345. package/src/roomStore/chatSettingsSlice.ts +16 -0
  346. package/src/roomStore/index.ts +5 -0
  347. package/src/roomStore/persistence.ts +103 -3
  348. package/src/roomStore/roomsSlice.ts +149 -4
  349. package/src/types/models/language.model.ts +17 -1
  350. package/src/types/models/message.model.ts +9 -0
  351. package/src/types/types.ts +142 -2
  352. package/src/utils/translateModePolicy.ts +31 -0
@@ -9,12 +9,14 @@ import {
9
9
  setCurrentRoom,
10
10
  setRoomRole,
11
11
  updateRoom,
12
+ mergeUsersSet,
12
13
  } from '../roomStore/roomsSlice';
13
14
  import { IRoom, RoomMember } from '../types/types';
14
15
  import { createMessageFromXml } from '../helpers/createMessageFromXml';
15
16
  import { getDataFromXml } from '../helpers/getDataFromXml';
16
17
  import { setDeleteModal } from '../roomStore/chatSettingsSlice';
17
18
  import { messageNotificationManager } from '../utils/messageNotificationManager';
19
+ import { transformCallLogMessage } from '../helpers/callLogMessage';
18
20
 
19
21
  // TO DO: we are thinking to refactor this code in the following way:
20
22
  // each stanza will be parsed for 'type'
@@ -51,10 +53,21 @@ const onRealtimeMessage = async (stanza: Element) => {
51
53
  return;
52
54
  }
53
55
 
54
- if (!data.attrs.senderJID) {
56
+ // Not every sender stamps `senderJID` onto `<data>` — the web SDK's
57
+ // translate-tagged send path in particular builds `<data>` from a
58
+ // differently-named attr bag (roomJID/firstName/userMessage/…) that
59
+ // has no senderJID at all. This used to hard-drop the message here —
60
+ // live AND, via the identical check in onMessageHistory, in the MAM
61
+ // backfill too — so anything sent through that path just never
62
+ // appeared, on this device or after a restart. The stanza's own
63
+ // `from` is always the full MUC occupant jid (`room@conference/nick`,
64
+ // exactly what senderJID would have held), so fall back to it instead
65
+ // of dropping the message. Web's own onRealtimeMessage only requires
66
+ // `<data>` to exist at all — no senderJID check — so this brings RN
67
+ // to the same tolerance.
68
+ const senderJID = data.attrs.senderJID || stanza.attrs.from;
69
+ if (!senderJID) {
55
70
  console.log(stanza.toString());
56
- console.log(data.attrs.senderJID);
57
-
58
71
  console.log('Missing sender information in real-time message.');
59
72
  return;
60
73
  }
@@ -66,17 +79,29 @@ const onRealtimeMessage = async (stanza: Element) => {
66
79
  const parsed = await getDataFromXml(stanza);
67
80
  const { data: pData, id: pId, body: pBody, ...pRest } =
68
81
  parsed ?? ({} as Partial<NonNullable<typeof parsed>>);
82
+ const mergedData: Record<string, unknown> = { ...(pData || data.attrs) };
83
+ if (!mergedData.senderJID) {mergedData.senderJID = senderJID;}
69
84
  // Cast at the call site: createMessageFromXml accepts the merged
70
85
  // wrapped/positional shape; IUser type drift between models prevents
71
86
  // a narrower type here without a wider refactor.
72
- const message = await createMessageFromXml({
73
- data: pData || data.attrs,
87
+ const rawMessage = await createMessageFromXml({
88
+ data: mergedData,
74
89
  id: pId || id,
75
90
  body: pBody ?? '',
76
91
  ...pRest,
77
92
  isDeleted: !!deleted || !!pRest?.deleted,
78
93
  } as Parameters<typeof createMessageFromXml>[0]);
79
94
 
95
+ // Turn server call-state stanzas into a friendly call-log entry
96
+ // ("Outgoing call · 12 sec" / "Missed call"). Non-call messages pass
97
+ // through unchanged. Without this the raw message keeps body
98
+ // "call-state" and gets dropped by the call-signal filter in
99
+ // roomsSlice, so call history silently disappears.
100
+ const message = transformCallLogMessage(
101
+ rawMessage,
102
+ store.getState().chatSettingStore.user?.xmppUsername || ''
103
+ );
104
+
80
105
  const roomJID = stanza.attrs.from.split('/')[0];
81
106
  store.dispatch(
82
107
  addRoomMessage({
@@ -90,8 +115,8 @@ const onRealtimeMessage = async (stanza: Element) => {
90
115
  try {
91
116
  const state = store.getState();
92
117
  const currentUserWallet = (state.chatSettingStore.user?.walletAddress || '').toLowerCase();
93
- const senderJID = String(data.attrs.senderJID || '').toLowerCase();
94
- if (currentUserWallet && senderJID.includes(currentUserWallet)) {
118
+ const senderJIDLower = String(senderJID || '').toLowerCase();
119
+ if (currentUserWallet && senderJIDLower.includes(currentUserWallet)) {
95
120
  return message; // own message, skip toast
96
121
  }
97
122
  const room = state.rooms.rooms[roomJID];
@@ -193,25 +218,44 @@ const onMessageHistory = async (stanza: any) => {
193
218
  }
194
219
  // console.log(stanza.attrs.from);
195
220
 
196
- if (
197
- !data?.attrs ||
198
- !data.attrs.senderFirstName ||
199
- !data.attrs.senderLastName ||
200
- !data.attrs.senderJID
201
- ) {
221
+ // Mirror the realtime path's tolerance: don't hard-require
222
+ // senderFirstName/senderLastName/senderJID on <data> — the web SDK's
223
+ // translate-tagged send path doesn't stamp any of them, and this used
224
+ // to drop those messages out of MAM backfill entirely (so they never
225
+ // appeared even after a restart). The inner forwarded <message>'s own
226
+ // `from` is the full MUC occupant jid (room@conference/nick), exactly
227
+ // what senderJID would have held — fall back to it. createMessageFromXml
228
+ // already derives a display name from the jid when senderFirstName/
229
+ // senderLastName are absent.
230
+ const innerFrom =
231
+ stanza
232
+ .getChild('result')
233
+ ?.getChild('forwarded')
234
+ ?.getChild('message')?.attrs?.from || stanza.attrs.from;
235
+ const senderJID = data?.attrs?.senderJID || innerFrom;
236
+ if (!data?.attrs || !senderJID) {
202
237
  // console.log(
203
238
  // "Missing sender information in message history.",
204
239
  // stanza.toString()
205
240
  // );
206
241
  return;
207
242
  }
208
- const message = await createMessageFromXml(
209
- data.attrs,
243
+ const mergedAttrs = { ...data.attrs };
244
+ if (!mergedAttrs.senderJID) {mergedAttrs.senderJID = senderJID;}
245
+ const rawMessage = await createMessageFromXml(
246
+ mergedAttrs,
210
247
  body,
211
248
  id,
212
249
  stanza.attrs.from,
213
250
  !!deleted
214
251
  );
252
+
253
+ // Same call-log transform as the realtime path, applied to archived
254
+ // history so calls received while offline still render as log entries.
255
+ const message = transformCallLogMessage(
256
+ rawMessage,
257
+ store.getState().chatSettingStore.user?.xmppUsername || ''
258
+ );
215
259
  store.dispatch(
216
260
  addRoomMessage({
217
261
  roomJID: stanza.attrs.from,
@@ -349,6 +393,21 @@ const onGetMembers = (stanza: Element) => {
349
393
  });
350
394
 
351
395
  store.dispatch(updateRoom({ jid, updates: { roomMembers } }));
396
+
397
+ // Also feed the identity cache Message.tsx reads sender names from
398
+ // (state.rooms.usersSet). Keyed by both the bare local part and the
399
+ // full jid since a message's `user.id` can be either depending on
400
+ // how it was parsed (see createUserNameFromSetUser).
401
+ const usersSetUpdates: Record<string, RoomMember> = {};
402
+ for (const member of roomMembers) {
403
+ if (!member.jid) {continue;}
404
+ const local = member.jid.split('@')[0];
405
+ usersSetUpdates[local] = member;
406
+ usersSetUpdates[member.jid] = member;
407
+ }
408
+ if (Object.keys(usersSetUpdates).length > 0) {
409
+ store.dispatch(mergeUsersSet({ members: usersSetUpdates }));
410
+ }
352
411
  } catch (err) {
353
412
  console.warn('onGetMembers parse failed', err);
354
413
  }
@@ -18,22 +18,63 @@ import {
18
18
  onMessageError,
19
19
  } from '../stanzaHandlers';
20
20
  import XmppClient from '../xmppClient';
21
+ import { onCallTokenMessage } from '../callTokenStanza';
22
+
23
+ /**
24
+ * Unwrap a mucsub event wrapper so the chat handlers see the real inner
25
+ * `<message>` (the one carrying `<data senderJID=…>` and `<body>`).
26
+ *
27
+ * We subscribe every room to `urn:xmpp:mucsub:nodes:messages` (see
28
+ * subscribeToRoomMessages / pushSubscriptionService), so ejabberd pushes
29
+ * room traffic as:
30
+ *
31
+ * <message from="room@conference/…">
32
+ * <event xmlns="http://jabber.org/protocol/pubsub#event">
33
+ * <items node="urn:xmpp:mucsub:nodes:messages">
34
+ * <item><message …><data senderJID=…/><body>…</body></message></item>
35
+ *
36
+ * Without unwrapping, onRealtimeMessage reads `<data>` off the OUTER
37
+ * wrapper, finds nothing, logs "Missing data elements in real-time
38
+ * message" and drops the stanza — so live messages never render and only
39
+ * surface later through the MAM history fetch (i.e. after an app restart
40
+ * or re-opening the room). Mirrors the web SDK's handleStanza.
41
+ */
42
+ const unwrapMucsubMessage = (stanza: Element): Element => {
43
+ const inner = (stanza as any)
44
+ ?.getChild?.('event', 'http://jabber.org/protocol/pubsub#event')
45
+ ?.getChild?.('items')
46
+ ?.getChild?.('item')
47
+ ?.getChild?.('message');
48
+ return (inner as Element) || stanza;
49
+ };
21
50
 
22
51
  export function handleStanza(stanza: Element, xmppWs: XmppClient) {
23
52
  if (stanza?.attrs?.type === 'headline') {return;}
53
+
54
+ // Call signaling is swallowed before any chat handler sees it. A
55
+ // `<data type="call-*">` frame is not user-visible content, and letting
56
+ // it through renders bubbles reading "Deleted User: call-state" and
57
+ // fires new-message notifications for a call that never happened.
58
+ // Returns false for server call-LOGS, which do belong in the chat.
59
+ if (stanza?.name === 'message' && onCallTokenMessage(stanza)) {
60
+ return;
61
+ }
62
+
24
63
  switch (stanza.name) {
25
- case 'message':
26
- onMessageError(stanza, xmppWs);
27
- onReactionMessage(stanza);
28
- onReactionHistory(stanza);
29
- onDeleteMessage(stanza);
30
- onEditMessage(stanza);
31
- onChatInvite(stanza, xmppWs);
32
- onRealtimeMessage(stanza);
33
- onMessageHistory(stanza);
34
- handleComposing(stanza, xmppWs.username);
35
- onPresenceInRoom(stanza);
64
+ case 'message': {
65
+ const unwrapped = unwrapMucsubMessage(stanza);
66
+ onMessageError(unwrapped, xmppWs);
67
+ onReactionMessage(unwrapped);
68
+ onReactionHistory(unwrapped);
69
+ onDeleteMessage(unwrapped);
70
+ onEditMessage(unwrapped);
71
+ onChatInvite(unwrapped, xmppWs);
72
+ onRealtimeMessage(unwrapped);
73
+ onMessageHistory(unwrapped);
74
+ handleComposing(unwrapped, xmppWs.username);
75
+ onPresenceInRoom(unwrapped);
36
76
  break;
77
+ }
37
78
  case 'presence':
38
79
  onRoomKicked(stanza);
39
80
  onPresenceInRoom(stanza);
@@ -12,7 +12,7 @@ let _sendTextSeq = 0;
12
12
  *
13
13
  * Mirrors web's `SERVICE` derivation (utils/runtimeHostConfig.ts).
14
14
  */
15
- const toServiceXmlns = (devServer: string | undefined, client: Client): string => {
15
+ export const toServiceXmlns = (devServer: string | undefined, client: Client): string => {
16
16
  // Prefer the URL the client is actually connected to — guaranteed to
17
17
  // be the one the server expects.
18
18
  const clientService = (client as any)?.options?.service as string | undefined;
@@ -1,6 +1,22 @@
1
1
  import { Client, xml } from '@xmpp/client';
2
2
  import { Iso639_1Codes } from '../../types/types';
3
+ import { toServiceXmlns } from './sendTextMessage.xmpp';
3
4
 
5
+ /**
6
+ * Same wire message as `sendTextMessage`, plus a `<translate source="xx"/>`
7
+ * child that DECLARES the message's source language so the backend can
8
+ * translate it for readers in other languages. No pre-translation happens
9
+ * client-side.
10
+ *
11
+ * The `<data>` element MUST be built identically to `sendTextMessage`
12
+ * (correct `xmlns` = the `wss://<host>/ws` service URL, and the
13
+ * `senderFirstName` / `senderLastName` / `senderJID` / `roomJid` attr
14
+ * names the server + parser expect). An earlier version spread a loose
15
+ * `stanzaMessage` bag into `<data>` with no xmlns and mismatched attr
16
+ * names — the server silently dropped those stanzas, so no echo came back
17
+ * and every sent message stayed stuck in the "pending" state. Keep this in
18
+ * lockstep with sendTextMessage.xmpp.ts.
19
+ */
4
20
  export const sendTextMessageWithTranslateTag = (
5
21
  client: Client,
6
22
  stanzaMessage: {
@@ -18,27 +34,47 @@ export const sendTextMessageWithTranslateTag = (
18
34
  },
19
35
  source: Iso639_1Codes,
20
36
  customId?: string
21
- ) => {
22
- const id = customId || `get-translate-messsage:${Date.now().toString()}`;
37
+ ): boolean => {
38
+ const id = customId || `send-text-message-${Date.now()}`;
23
39
 
24
40
  try {
41
+ const dataXmlns = toServiceXmlns(stanzaMessage.devServer, client);
25
42
  const message = xml(
26
43
  'message',
27
44
  {
28
45
  to: stanzaMessage.roomJID,
29
46
  type: 'groupchat',
30
- id: id,
47
+ id,
31
48
  },
32
49
  xml('data', {
33
- ...stanzaMessage,
50
+ xmlns: dataXmlns,
51
+ senderFirstName: stanzaMessage.firstName,
52
+ senderLastName: stanzaMessage.lastName,
53
+ fullName: `${stanzaMessage.firstName} ${stanzaMessage.lastName}`,
54
+ photoURL: stanzaMessage.photo,
55
+ senderJID: client.jid?.toString(),
56
+ senderWalletAddress: stanzaMessage.walletAddress,
57
+ roomJid: stanzaMessage.roomJID,
58
+ isSystemMessage: false,
59
+ tokenAmount: 0,
60
+ quickReplies: '',
61
+ notDisplayedValue: '',
62
+ showInChannel: stanzaMessage.showInChannel || false,
63
+ isReply: stanzaMessage.isReply || false,
64
+ mainMessage: stanzaMessage.mainMessage || '',
34
65
  push: 'true',
35
66
  }),
36
67
  xml('body', {}, stanzaMessage.userMessage),
37
- xml('translate', { source: source })
68
+ // `<translate source>` only DECLARES the language this text is in; it
69
+ // costs nothing to send and is what lets each reader translate the
70
+ // message into their own language on their side.
71
+ xml('translate', { source })
38
72
  );
39
73
 
40
74
  client.send(message);
75
+ return true;
41
76
  } catch (error) {
42
77
  console.error('An error occurred while sending message:', error);
78
+ return false;
43
79
  }
44
80
  };
@@ -10,6 +10,7 @@ import { sendTypingRequest } from './xmpp/sendTypingRequest.xmpp';
10
10
  import { sendPing } from './xmpp/sendPing.xmpp';
11
11
  import { getHistory } from './xmpp/getHistory.xmpp';
12
12
  import { sendTextMessage } from './xmpp/sendTextMessage.xmpp';
13
+ import { sendTextMessageWithTranslateTag } from './xmpp/sendTextMessageWithTranslateTag.xmpp';
13
14
  import { deleteMessage } from './xmpp/deleteMessage.xmpp';
14
15
  import { presenceInRoom } from './xmpp/presenceInRoom.xmpp';
15
16
  import { getLastMessage } from './xmpp/getLastMessageArchive.xmpp';
@@ -35,6 +36,31 @@ import {
35
36
  // Canonical production XMPP WSS endpoint (standard wss/443, no port suffix).
36
37
  const DEFAULT_DEV_SERVER = 'xmpp.chat.ethora.com';
37
38
 
39
+ // How long to wait for the old client's stop() during a reconnect before
40
+ // giving up on it. Short on purpose: we are already tearing this client
41
+ // down, and a socket that hasn't closed in 3s is exactly the dead one we
42
+ // must not block on. See the call site in reconnect().
43
+ const STOP_TIMEOUT_MS = 3000;
44
+
45
+ /**
46
+ * Resolve when `promise` settles or when `ms` elapses, whichever is first.
47
+ * Never rejects: a teardown that fails or hangs must not break the caller's
48
+ * control flow (that is the whole point of using it around stop()).
49
+ */
50
+ function withTimeout(promise: Promise<unknown>, ms: number): Promise<void> {
51
+ return new Promise<void>((resolve) => {
52
+ let settled = false;
53
+ const done = () => {
54
+ if (settled) {return;}
55
+ settled = true;
56
+ clearTimeout(timer);
57
+ resolve();
58
+ };
59
+ const timer = setTimeout(done, ms);
60
+ Promise.resolve(promise).then(done, done);
61
+ });
62
+ }
63
+
38
64
  // @xmpp/client surfaces SASL/stream errors in a few shapes depending on
39
65
  // where it fails — XMPPError on stream:error, SASLError on SASL bind, or
40
66
  // a generic Error whose message contains "not-authorized". Match all of
@@ -697,9 +723,17 @@ export class XmppClient {
697
723
  const old = this.client;
698
724
  if (old) {
699
725
  this.detachEventListeners();
700
- try {
701
- await old.stop();
702
- } catch {}
726
+ // NEVER await a bare stop(): on a half-dead socket (the exact case
727
+ // we're reconnecting for) @xmpp/client's stop() can hang forever
728
+ // waiting on a close handshake that never lands. That leaves this
729
+ // function parked before `finally`, so `reconnecting` stays true and
730
+ // EVERY later reconnect — watchdog, NetInfo, AppState — silently
731
+ // returns at the single-flight guard. The client then never comes
732
+ // back until the app is killed, which reads as "new messages just
733
+ // stop arriving". Cap the teardown and move on: initializeClient()
734
+ // replaces `this.client` anyway, and the old one's listeners are
735
+ // already detached above, so a late-settling stop() is harmless.
736
+ await withTimeout(old.stop(), STOP_TIMEOUT_MS);
703
737
  }
704
738
  this.initializeClient();
705
739
  } finally {
@@ -755,12 +789,17 @@ export class XmppClient {
755
789
  // handshake can't re-enter handleStanza and dispatch into a store
756
790
  // that's being wiped (or, on re-login, the new session's store).
757
791
  this.detachEventListeners();
758
- try {
759
- await this.client.stop();
760
- console.log('XMPP client connection closed.');
761
- } catch (error) {
762
- console.error('Error closing the xmpp client:', error);
763
- }
792
+ // Bounded like the reconnect teardown: a stop() that never settles on
793
+ // a dead socket would otherwise hang logout (the LOGOUT_EVENT handler
794
+ // awaits this) and leave the app wedged on the sign-out screen. The
795
+ // rejection is still logged — only the *waiting* is capped.
796
+ await withTimeout(
797
+ Promise.resolve(this.client.stop()).catch((error: unknown) => {
798
+ console.error('Error closing the xmpp client:', error);
799
+ }),
800
+ STOP_TIMEOUT_MS
801
+ );
802
+ console.log('XMPP client connection closed.');
764
803
  }
765
804
  this.status = 'offline';
766
805
  this.presencesReady = false;
@@ -1031,6 +1070,13 @@ export class XmppClient {
1031
1070
  console.warn('sendMessageReactionStanza: not implemented in RN xmpp client');
1032
1071
  }
1033
1072
 
1073
+ // Sends a groupchat message carrying a `<translate source="xx"/>` tag so
1074
+ // the backend knows the message's source language and can translate it
1075
+ // for each reader (mirrors the web SDK's send path). `langSource` is the
1076
+ // sender's own language; it only DECLARES the source, no pre-translation
1077
+ // happens client-side. Structure mirrors `sendMessage`: buffer + replay
1078
+ // when the stream isn't ready so a reconnect flush re-sends it, and
1079
+ // forward `customId` so the optimistic bubble reconciles with the echo.
1034
1080
  sendTextMessageWithTranslateTagStanza(
1035
1081
  roomJID: string,
1036
1082
  firstName: string,
@@ -1042,26 +1088,49 @@ export class XmppClient {
1042
1088
  isReply?: boolean,
1043
1089
  showInChannel?: boolean,
1044
1090
  mainMessage?: string,
1045
- _langSource?: string,
1091
+ langSource?: string,
1046
1092
  customId?: string
1047
- ) {
1048
- // No translate tag support yet — fall back to a regular text send.
1049
- // Forward the caller's customId so the optimistic message (heap/redux)
1050
- // reconciles with the server echo. Without it, translated sends went
1051
- // out with no client id → the echo carried a server-assigned id and
1052
- // surfaced as a stuck-pending message PLUS a duplicate (affected both
1053
- // the live translated-send path and resend).
1054
- this.sendMessage(
1055
- roomJID,
1056
- firstName,
1057
- lastName,
1058
- photo,
1059
- walletAddress,
1060
- userMessage,
1061
- notDisplayedValue,
1062
- isReply,
1063
- showInChannel,
1064
- mainMessage,
1093
+ ): boolean {
1094
+ const source = (langSource || 'en') as any;
1095
+ if (!this.isStreamReady()) {
1096
+ enqueueOutboundSend({
1097
+ optimisticId: customId || `send-text-message-${Date.now()}`,
1098
+ roomJID,
1099
+ enqueuedAt: Date.now(),
1100
+ send: (c) =>
1101
+ c.sendTextMessageWithTranslateTagStanza(
1102
+ roomJID,
1103
+ firstName,
1104
+ lastName,
1105
+ photo,
1106
+ walletAddress,
1107
+ userMessage,
1108
+ notDisplayedValue,
1109
+ isReply,
1110
+ showInChannel,
1111
+ mainMessage,
1112
+ langSource,
1113
+ customId
1114
+ ),
1115
+ });
1116
+ return false;
1117
+ }
1118
+ return sendTextMessageWithTranslateTag(
1119
+ this.client,
1120
+ {
1121
+ roomJID,
1122
+ firstName,
1123
+ lastName,
1124
+ photo,
1125
+ walletAddress,
1126
+ userMessage,
1127
+ notDisplayedValue,
1128
+ isReply,
1129
+ showInChannel,
1130
+ mainMessage,
1131
+ devServer: this.devServer || DEFAULT_DEV_SERVER,
1132
+ },
1133
+ source,
1065
1134
  customId
1066
1135
  );
1067
1136
  }
@@ -0,0 +1,190 @@
1
+ import { PayloadAction, createSlice } from '@reduxjs/toolkit';
2
+
3
+ export type CallPhase =
4
+ | 'idle'
5
+ | 'requesting'
6
+ | 'ringing-incoming'
7
+ | 'connecting'
8
+ | 'in-call'
9
+ | 'error';
10
+
11
+ export type CallDirection = 'outgoing' | 'incoming' | null;
12
+ export type CallKind = 'audio' | 'video';
13
+
14
+ export interface CallState {
15
+ phase: CallPhase;
16
+ direction: CallDirection;
17
+ kind: CallKind;
18
+ roomJid: string | null;
19
+ roomName: string | null;
20
+ // Bare room name (JID localpart). Server's call-state stanzas reference
21
+ // calls by this value, and we echo it back on hangup signaling.
22
+ roomBareName: string | null;
23
+ // Stable callId from the call-token data attr (or JWT metadata). Used
24
+ // when emitting our own call-state hangup so the peer can correlate.
25
+ callId: string | null;
26
+ // Peer's XMPP localpart (bare username, no @host). For outgoing we
27
+ // resolve it from members[]; for incoming we derive it from the room
28
+ // name format "<userA>-<userB>" minus our own username.
29
+ peerXmppUsername: string | null;
30
+ token: string | null;
31
+ error: string | null;
32
+ startedAt: number | null;
33
+ // When the call actually connected (phase -> 'in-call'). Null until then.
34
+ // Used to compute a duration for the local "call ended" log fallback.
35
+ connectedAt: number | null;
36
+ }
37
+
38
+ const initialState: CallState = {
39
+ phase: 'idle',
40
+ direction: null,
41
+ kind: 'video',
42
+ roomJid: null,
43
+ roomName: null,
44
+ roomBareName: null,
45
+ callId: null,
46
+ peerXmppUsername: null,
47
+ token: null,
48
+ error: null,
49
+ startedAt: null,
50
+ connectedAt: null,
51
+ };
52
+
53
+ const resetState = (): CallState => ({ ...initialState });
54
+
55
+ const callSlice = createSlice({
56
+ name: 'call',
57
+ initialState,
58
+ reducers: {
59
+ startOutgoingCall(
60
+ state,
61
+ action: PayloadAction<{
62
+ roomJid: string;
63
+ roomName?: string | null;
64
+ roomBareName?: string | null;
65
+ kind?: CallKind;
66
+ peerXmppUsername?: string | null;
67
+ }>
68
+ ) {
69
+ state.phase = 'requesting';
70
+ state.direction = 'outgoing';
71
+ state.kind = action.payload.kind || 'video';
72
+ state.roomJid = action.payload.roomJid;
73
+ state.roomName = action.payload.roomName || null;
74
+ state.roomBareName =
75
+ action.payload.roomBareName ||
76
+ (action.payload.roomJid || '').split('@')[0] ||
77
+ null;
78
+ state.peerXmppUsername = action.payload.peerXmppUsername || null;
79
+ state.callId = null;
80
+ state.token = null;
81
+ state.error = null;
82
+ state.startedAt = Date.now();
83
+ state.connectedAt = null;
84
+ },
85
+ setIncomingCallToken(
86
+ state,
87
+ action: PayloadAction<{
88
+ roomJid: string;
89
+ roomName?: string | null;
90
+ roomBareName?: string | null;
91
+ token: string;
92
+ kind?: CallKind;
93
+ callId?: string | null;
94
+ peerXmppUsername?: string | null;
95
+ }>
96
+ ) {
97
+ state.phase = 'ringing-incoming';
98
+ state.direction = 'incoming';
99
+ state.kind = action.payload.kind || 'video';
100
+ state.roomJid = action.payload.roomJid;
101
+ state.roomName = action.payload.roomName || null;
102
+ state.roomBareName =
103
+ action.payload.roomBareName ||
104
+ (action.payload.roomJid || '').split('@')[0] ||
105
+ null;
106
+ state.callId = action.payload.callId || null;
107
+ state.peerXmppUsername = action.payload.peerXmppUsername || null;
108
+ state.token = action.payload.token;
109
+ state.error = null;
110
+ state.startedAt = Date.now();
111
+ state.connectedAt = null;
112
+ },
113
+ setOutgoingCallToken(
114
+ state,
115
+ action: PayloadAction<{
116
+ roomJid: string;
117
+ token: string;
118
+ callId?: string | null;
119
+ }>
120
+ ) {
121
+ if (state.direction !== 'outgoing') {return;}
122
+
123
+ const currentRoom = state.roomJid || '';
124
+ if (currentRoom && currentRoom !== action.payload.roomJid) {return;}
125
+
126
+ state.phase = 'connecting';
127
+ state.roomJid = action.payload.roomJid;
128
+ state.token = action.payload.token;
129
+ if (action.payload.callId) {state.callId = action.payload.callId;}
130
+ state.error = null;
131
+ state.startedAt = state.startedAt || Date.now();
132
+ },
133
+ acceptIncomingCall(state) {
134
+ if (state.direction !== 'incoming') {return;}
135
+ state.phase = 'connecting';
136
+ state.error = null;
137
+ state.startedAt = state.startedAt || Date.now();
138
+ },
139
+ declineIncomingCall() {
140
+ return resetState();
141
+ },
142
+ endCall() {
143
+ return resetState();
144
+ },
145
+ setCallError(state, action: PayloadAction<string>) {
146
+ state.phase = 'error';
147
+ state.error = action.payload;
148
+ state.startedAt = state.startedAt || Date.now();
149
+ },
150
+ setCallPhase(state, action: PayloadAction<CallPhase>) {
151
+ state.phase = action.payload;
152
+ if (action.payload === 'in-call') {
153
+ state.error = null;
154
+ // Anchor the connect moment once, so a mid-call reconnect blip
155
+ // doesn't reset the duration used by the local call-end log.
156
+ state.connectedAt = state.connectedAt || Date.now();
157
+ }
158
+ },
159
+ // Patch the call kind in-place. Used when the server's call-token
160
+ // stanza doesn't carry a `kind` attribute and we receive the
161
+ // client-side `call-invite` hint AFTER the call-token has already
162
+ // landed (race window: token relays through server, invite is direct
163
+ // chat, normally invite wins but not always).
164
+ setCallKind(state, action: PayloadAction<CallKind>) {
165
+ if (state.phase === 'idle') {return;}
166
+ state.kind = action.payload;
167
+ },
168
+ resetCall() {
169
+ return resetState();
170
+ },
171
+ },
172
+ extraReducers: (builder) => {
173
+ builder.addCase('chatSettingStore/logout' as any, () => resetState());
174
+ },
175
+ });
176
+
177
+ export const {
178
+ startOutgoingCall,
179
+ setIncomingCallToken,
180
+ setOutgoingCallToken,
181
+ acceptIncomingCall,
182
+ declineIncomingCall,
183
+ endCall,
184
+ setCallError,
185
+ setCallPhase,
186
+ setCallKind,
187
+ resetCall,
188
+ } = callSlice.actions;
189
+
190
+ export default callSlice.reducer;