@ethora/chat-component-rn 26.10.10 → 26.10.11

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 (483) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +125 -0
  3. package/lib/commonjs/booking/index.js +44 -0
  4. package/lib/commonjs/booking/index.js.map +1 -0
  5. package/lib/commonjs/booking/pendingScheduledCall.js +275 -0
  6. package/lib/commonjs/booking/pendingScheduledCall.js.map +1 -0
  7. package/lib/commonjs/booking/scheduleForm.js +91 -0
  8. package/lib/commonjs/booking/scheduleForm.js.map +1 -0
  9. package/lib/commonjs/booking/scheduledCall.js +141 -0
  10. package/lib/commonjs/booking/scheduledCall.js.map +1 -0
  11. package/lib/commonjs/booking/scheduledCallActions.js +128 -0
  12. package/lib/commonjs/booking/scheduledCallActions.js.map +1 -0
  13. package/lib/commonjs/booking/scheduledCallLink.js +143 -0
  14. package/lib/commonjs/booking/scheduledCallLink.js.map +1 -0
  15. package/lib/commonjs/booking/scheduledCallStore.js +64 -0
  16. package/lib/commonjs/booking/scheduledCallStore.js.map +1 -0
  17. package/lib/commonjs/booking/startRoomCall.js +84 -0
  18. package/lib/commonjs/booking/startRoomCall.js.map +1 -0
  19. package/lib/commonjs/calls/callBusy.js +18 -0
  20. package/lib/commonjs/calls/callBusy.js.map +1 -0
  21. package/lib/commonjs/calls/callDisplay.js +73 -0
  22. package/lib/commonjs/calls/callDisplay.js.map +1 -0
  23. package/lib/commonjs/calls/callMode.js +175 -0
  24. package/lib/commonjs/calls/callMode.js.map +1 -0
  25. package/lib/commonjs/calls/declineReport.js +20 -0
  26. package/lib/commonjs/calls/declineReport.js.map +1 -0
  27. package/lib/commonjs/calls/p2p/P2PCallController.js +724 -0
  28. package/lib/commonjs/calls/p2p/P2PCallController.js.map +1 -0
  29. package/lib/commonjs/calls/p2p/icePolicy.js +107 -0
  30. package/lib/commonjs/calls/p2p/icePolicy.js.map +1 -0
  31. package/lib/commonjs/calls/p2p/negotiator.js +202 -0
  32. package/lib/commonjs/calls/p2p/negotiator.js.map +1 -0
  33. package/lib/commonjs/calls/p2p/p2pRuntime.js +147 -0
  34. package/lib/commonjs/calls/p2p/p2pRuntime.js.map +1 -0
  35. package/lib/commonjs/calls/p2p/signalInbox.js +98 -0
  36. package/lib/commonjs/calls/p2p/signalInbox.js.map +1 -0
  37. package/lib/commonjs/calls/p2p/signalStanza.js +141 -0
  38. package/lib/commonjs/calls/p2p/signalStanza.js.map +1 -0
  39. package/lib/commonjs/calls/p2p/webrtcRuntime.js +53 -0
  40. package/lib/commonjs/calls/p2p/webrtcRuntime.js.map +1 -0
  41. package/lib/commonjs/calls/senderTrust.js +43 -0
  42. package/lib/commonjs/calls/senderTrust.js.map +1 -0
  43. package/lib/commonjs/calls/startCall.js +51 -0
  44. package/lib/commonjs/calls/startCall.js.map +1 -0
  45. package/lib/commonjs/components/Booking/BookingIcons.js +55 -0
  46. package/lib/commonjs/components/Booking/BookingIcons.js.map +1 -0
  47. package/lib/commonjs/components/Booking/ScheduleCallButton.js +64 -0
  48. package/lib/commonjs/components/Booking/ScheduleCallButton.js.map +1 -0
  49. package/lib/commonjs/components/Booking/ScheduleCallSheet.js +351 -0
  50. package/lib/commonjs/components/Booking/ScheduleCallSheet.js.map +1 -0
  51. package/lib/commonjs/components/Booking/ScheduledCallCard.js +203 -0
  52. package/lib/commonjs/components/Booking/ScheduledCallCard.js.map +1 -0
  53. package/lib/commonjs/components/Booking/ScheduledCallHost.js +23 -0
  54. package/lib/commonjs/components/Booking/ScheduledCallHost.js.map +1 -0
  55. package/lib/commonjs/components/Booking/ScheduledCallMessage.js +55 -0
  56. package/lib/commonjs/components/Booking/ScheduledCallMessage.js.map +1 -0
  57. package/lib/commonjs/components/Booking/ScheduledCallPreJoin.js +235 -0
  58. package/lib/commonjs/components/Booking/ScheduledCallPreJoin.js.map +1 -0
  59. package/lib/commonjs/components/Booking/bookingShared.js +305 -0
  60. package/lib/commonjs/components/Booking/bookingShared.js.map +1 -0
  61. package/lib/commonjs/components/MainComponents/ChatHeader.js +2 -1
  62. package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
  63. package/lib/commonjs/components/MainComponents/LanguageSelectorButton.js +5 -2
  64. package/lib/commonjs/components/MainComponents/LanguageSelectorButton.js.map +1 -1
  65. package/lib/commonjs/components/MainComponents/LanguageSelectorModal.js +6 -3
  66. package/lib/commonjs/components/MainComponents/LanguageSelectorModal.js.map +1 -1
  67. package/lib/commonjs/components/MainComponents/MessageContainer.js +13 -0
  68. package/lib/commonjs/components/MainComponents/MessageContainer.js.map +1 -1
  69. package/lib/commonjs/components/MainComponents/ReduxWrapper.js +10 -0
  70. package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
  71. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js +19 -15
  72. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -1
  73. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +15 -8
  74. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  75. package/lib/commonjs/components/Modals/UserSettingsModal/LanguageCard.js +1 -1
  76. package/lib/commonjs/components/Modals/UserSettingsModal/LanguageCard.js.map +1 -1
  77. package/lib/commonjs/components/VideoCalls/ActiveCallBar.js +3 -2
  78. package/lib/commonjs/components/VideoCalls/ActiveCallBar.js.map +1 -1
  79. package/lib/commonjs/components/VideoCalls/CallButtons.js +19 -11
  80. package/lib/commonjs/components/VideoCalls/CallButtons.js.map +1 -1
  81. package/lib/commonjs/components/VideoCalls/CallControlBar.js +119 -0
  82. package/lib/commonjs/components/VideoCalls/CallControlBar.js.map +1 -0
  83. package/lib/commonjs/components/VideoCalls/CallVideo.js +49 -0
  84. package/lib/commonjs/components/VideoCalls/CallVideo.js.map +1 -0
  85. package/lib/commonjs/components/VideoCalls/GroupCallView.js +281 -0
  86. package/lib/commonjs/components/VideoCalls/GroupCallView.js.map +1 -0
  87. package/lib/commonjs/components/VideoCalls/P2PCallRunner.js +151 -0
  88. package/lib/commonjs/components/VideoCalls/P2PCallRunner.js.map +1 -0
  89. package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js +38 -14
  90. package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js.map +1 -1
  91. package/lib/commonjs/components/VideoCalls/VideoCallSession.js +57 -128
  92. package/lib/commonjs/components/VideoCalls/VideoCallSession.js.map +1 -1
  93. package/lib/commonjs/components/VideoCalls/callActions.js +3 -0
  94. package/lib/commonjs/components/VideoCalls/callActions.js.map +1 -1
  95. package/lib/commonjs/components/VideoCalls/callElapsed.js +38 -0
  96. package/lib/commonjs/components/VideoCalls/callElapsed.js.map +1 -0
  97. package/lib/commonjs/components/VideoCalls/callLive.js +15 -0
  98. package/lib/commonjs/components/VideoCalls/callLive.js.map +1 -0
  99. package/lib/commonjs/components/VideoCalls/callSessionController.js +81 -24
  100. package/lib/commonjs/components/VideoCalls/callSessionController.js.map +1 -1
  101. package/lib/commonjs/components/VideoCalls/callSessionTypes.js +41 -0
  102. package/lib/commonjs/components/VideoCalls/callSessionTypes.js.map +1 -0
  103. package/lib/commonjs/components/VideoCalls/groupLayout.js +43 -0
  104. package/lib/commonjs/components/VideoCalls/groupLayout.js.map +1 -0
  105. package/lib/commonjs/components/VideoCalls/p2pCallSession.js +272 -0
  106. package/lib/commonjs/components/VideoCalls/p2pCallSession.js.map +1 -0
  107. package/lib/commonjs/components/VideoCalls/useCallKeep.js +7 -2
  108. package/lib/commonjs/components/VideoCalls/useCallKeep.js.map +1 -1
  109. package/lib/commonjs/components/VideoCalls/useOngoingCallNotification.js +2 -1
  110. package/lib/commonjs/components/VideoCalls/useOngoingCallNotification.js.map +1 -1
  111. package/lib/commonjs/context/xmppProvider.js +2 -1
  112. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  113. package/lib/commonjs/helpers/callPush.js +3 -1
  114. package/lib/commonjs/helpers/callPush.js.map +1 -1
  115. package/lib/commonjs/helpers/incomingCallFromPush.js +63 -7
  116. package/lib/commonjs/helpers/incomingCallFromPush.js.map +1 -1
  117. package/lib/commonjs/helpers/pushPayload.js +5 -0
  118. package/lib/commonjs/helpers/pushPayload.js.map +1 -1
  119. package/lib/commonjs/helpers/reportRoom.js +76 -0
  120. package/lib/commonjs/helpers/reportRoom.js.map +1 -0
  121. package/lib/commonjs/i18n/strings.js +444 -0
  122. package/lib/commonjs/i18n/strings.js.map +1 -1
  123. package/lib/commonjs/main.js +93 -0
  124. package/lib/commonjs/main.js.map +1 -1
  125. package/lib/commonjs/networking/api-requests/callState.api.js +75 -0
  126. package/lib/commonjs/networking/api-requests/callState.api.js.map +1 -0
  127. package/lib/commonjs/networking/api-requests/push.api.js +29 -6
  128. package/lib/commonjs/networking/api-requests/push.api.js.map +1 -1
  129. package/lib/commonjs/networking/api-requests/rooms.api.js +8 -2
  130. package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
  131. package/lib/commonjs/networking/api-requests/scheduledCalls.api.js +141 -0
  132. package/lib/commonjs/networking/api-requests/scheduledCalls.api.js.map +1 -0
  133. package/lib/commonjs/networking/callTokenStanza.js +210 -50
  134. package/lib/commonjs/networking/callTokenStanza.js.map +1 -1
  135. package/lib/commonjs/roomStore/callSlice.js +59 -4
  136. package/lib/commonjs/roomStore/callSlice.js.map +1 -1
  137. package/lib/commonjs/services/appBadge.js +80 -0
  138. package/lib/commonjs/services/appBadge.js.map +1 -0
  139. package/lib/commonjs/services/languageSettings.js +47 -15
  140. package/lib/commonjs/services/languageSettings.js.map +1 -1
  141. package/lib/commonjs/services/pushRegistration.js +21 -5
  142. package/lib/commonjs/services/pushRegistration.js.map +1 -1
  143. package/lib/commonjs/version.js +1 -1
  144. package/lib/module/booking/index.js +5 -0
  145. package/lib/module/booking/index.js.map +1 -0
  146. package/lib/module/booking/pendingScheduledCall.js +261 -0
  147. package/lib/module/booking/pendingScheduledCall.js.map +1 -0
  148. package/lib/module/booking/scheduleForm.js +79 -0
  149. package/lib/module/booking/scheduleForm.js.map +1 -0
  150. package/lib/module/booking/scheduledCall.js +129 -0
  151. package/lib/module/booking/scheduledCall.js.map +1 -0
  152. package/lib/module/booking/scheduledCallActions.js +118 -0
  153. package/lib/module/booking/scheduledCallActions.js.map +1 -0
  154. package/lib/module/booking/scheduledCallLink.js +136 -0
  155. package/lib/module/booking/scheduledCallLink.js.map +1 -0
  156. package/lib/module/booking/scheduledCallStore.js +60 -0
  157. package/lib/module/booking/scheduledCallStore.js.map +1 -0
  158. package/lib/module/booking/startRoomCall.js +80 -0
  159. package/lib/module/booking/startRoomCall.js.map +1 -0
  160. package/lib/module/calls/callBusy.js +13 -0
  161. package/lib/module/calls/callBusy.js.map +1 -0
  162. package/lib/module/calls/callDisplay.js +65 -0
  163. package/lib/module/calls/callDisplay.js.map +1 -0
  164. package/lib/module/calls/callMode.js +168 -0
  165. package/lib/module/calls/callMode.js.map +1 -0
  166. package/lib/module/calls/declineReport.js +16 -0
  167. package/lib/module/calls/declineReport.js.map +1 -0
  168. package/lib/module/calls/p2p/P2PCallController.js +718 -0
  169. package/lib/module/calls/p2p/P2PCallController.js.map +1 -0
  170. package/lib/module/calls/p2p/icePolicy.js +102 -0
  171. package/lib/module/calls/p2p/icePolicy.js.map +1 -0
  172. package/lib/module/calls/p2p/negotiator.js +197 -0
  173. package/lib/module/calls/p2p/negotiator.js.map +1 -0
  174. package/lib/module/calls/p2p/p2pRuntime.js +137 -0
  175. package/lib/module/calls/p2p/p2pRuntime.js.map +1 -0
  176. package/lib/module/calls/p2p/signalInbox.js +93 -0
  177. package/lib/module/calls/p2p/signalInbox.js.map +1 -0
  178. package/lib/module/calls/p2p/signalStanza.js +135 -0
  179. package/lib/module/calls/p2p/signalStanza.js.map +1 -0
  180. package/lib/module/calls/p2p/webrtcRuntime.js +46 -0
  181. package/lib/module/calls/p2p/webrtcRuntime.js.map +1 -0
  182. package/lib/module/calls/senderTrust.js +38 -0
  183. package/lib/module/calls/senderTrust.js.map +1 -0
  184. package/lib/module/calls/startCall.js +47 -0
  185. package/lib/module/calls/startCall.js.map +1 -0
  186. package/lib/module/components/Booking/BookingIcons.js +48 -0
  187. package/lib/module/components/Booking/BookingIcons.js.map +1 -0
  188. package/lib/module/components/Booking/ScheduleCallButton.js +59 -0
  189. package/lib/module/components/Booking/ScheduleCallButton.js.map +1 -0
  190. package/lib/module/components/Booking/ScheduleCallSheet.js +345 -0
  191. package/lib/module/components/Booking/ScheduleCallSheet.js.map +1 -0
  192. package/lib/module/components/Booking/ScheduledCallCard.js +197 -0
  193. package/lib/module/components/Booking/ScheduledCallCard.js.map +1 -0
  194. package/lib/module/components/Booking/ScheduledCallHost.js +18 -0
  195. package/lib/module/components/Booking/ScheduledCallHost.js.map +1 -0
  196. package/lib/module/components/Booking/ScheduledCallMessage.js +48 -0
  197. package/lib/module/components/Booking/ScheduledCallMessage.js.map +1 -0
  198. package/lib/module/components/Booking/ScheduledCallPreJoin.js +229 -0
  199. package/lib/module/components/Booking/ScheduledCallPreJoin.js.map +1 -0
  200. package/lib/module/components/Booking/bookingShared.js +291 -0
  201. package/lib/module/components/Booking/bookingShared.js.map +1 -0
  202. package/lib/module/components/MainComponents/ChatHeader.js +2 -1
  203. package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
  204. package/lib/module/components/MainComponents/LanguageSelectorButton.js +5 -2
  205. package/lib/module/components/MainComponents/LanguageSelectorButton.js.map +1 -1
  206. package/lib/module/components/MainComponents/LanguageSelectorModal.js +7 -4
  207. package/lib/module/components/MainComponents/LanguageSelectorModal.js.map +1 -1
  208. package/lib/module/components/MainComponents/MessageContainer.js +13 -0
  209. package/lib/module/components/MainComponents/MessageContainer.js.map +1 -1
  210. package/lib/module/components/MainComponents/ReduxWrapper.js +10 -0
  211. package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
  212. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js +21 -15
  213. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -1
  214. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +17 -10
  215. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  216. package/lib/module/components/Modals/UserSettingsModal/LanguageCard.js +1 -1
  217. package/lib/module/components/Modals/UserSettingsModal/LanguageCard.js.map +1 -1
  218. package/lib/module/components/VideoCalls/ActiveCallBar.js +3 -2
  219. package/lib/module/components/VideoCalls/ActiveCallBar.js.map +1 -1
  220. package/lib/module/components/VideoCalls/CallButtons.js +19 -11
  221. package/lib/module/components/VideoCalls/CallButtons.js.map +1 -1
  222. package/lib/module/components/VideoCalls/CallControlBar.js +113 -0
  223. package/lib/module/components/VideoCalls/CallControlBar.js.map +1 -0
  224. package/lib/module/components/VideoCalls/CallVideo.js +43 -0
  225. package/lib/module/components/VideoCalls/CallVideo.js.map +1 -0
  226. package/lib/module/components/VideoCalls/GroupCallView.js +275 -0
  227. package/lib/module/components/VideoCalls/GroupCallView.js.map +1 -0
  228. package/lib/module/components/VideoCalls/P2PCallRunner.js +147 -0
  229. package/lib/module/components/VideoCalls/P2PCallRunner.js.map +1 -0
  230. package/lib/module/components/VideoCalls/VideoCallOverlay.js +38 -14
  231. package/lib/module/components/VideoCalls/VideoCallOverlay.js.map +1 -1
  232. package/lib/module/components/VideoCalls/VideoCallSession.js +46 -127
  233. package/lib/module/components/VideoCalls/VideoCallSession.js.map +1 -1
  234. package/lib/module/components/VideoCalls/callActions.js +3 -0
  235. package/lib/module/components/VideoCalls/callActions.js.map +1 -1
  236. package/lib/module/components/VideoCalls/callElapsed.js +33 -0
  237. package/lib/module/components/VideoCalls/callElapsed.js.map +1 -0
  238. package/lib/module/components/VideoCalls/callLive.js +10 -0
  239. package/lib/module/components/VideoCalls/callLive.js.map +1 -0
  240. package/lib/module/components/VideoCalls/callSessionController.js +80 -24
  241. package/lib/module/components/VideoCalls/callSessionController.js.map +1 -1
  242. package/lib/module/components/VideoCalls/callSessionTypes.js +37 -0
  243. package/lib/module/components/VideoCalls/callSessionTypes.js.map +1 -0
  244. package/lib/module/components/VideoCalls/groupLayout.js +36 -0
  245. package/lib/module/components/VideoCalls/groupLayout.js.map +1 -0
  246. package/lib/module/components/VideoCalls/p2pCallSession.js +256 -0
  247. package/lib/module/components/VideoCalls/p2pCallSession.js.map +1 -0
  248. package/lib/module/components/VideoCalls/useCallKeep.js +8 -2
  249. package/lib/module/components/VideoCalls/useCallKeep.js.map +1 -1
  250. package/lib/module/components/VideoCalls/useOngoingCallNotification.js +2 -1
  251. package/lib/module/components/VideoCalls/useOngoingCallNotification.js.map +1 -1
  252. package/lib/module/context/xmppProvider.js +2 -1
  253. package/lib/module/context/xmppProvider.js.map +1 -1
  254. package/lib/module/helpers/callPush.js +3 -1
  255. package/lib/module/helpers/callPush.js.map +1 -1
  256. package/lib/module/helpers/incomingCallFromPush.js +63 -7
  257. package/lib/module/helpers/incomingCallFromPush.js.map +1 -1
  258. package/lib/module/helpers/pushPayload.js +5 -0
  259. package/lib/module/helpers/pushPayload.js.map +1 -1
  260. package/lib/module/helpers/reportRoom.js +70 -0
  261. package/lib/module/helpers/reportRoom.js.map +1 -0
  262. package/lib/module/i18n/strings.js +444 -0
  263. package/lib/module/i18n/strings.js.map +1 -1
  264. package/lib/module/main.js +5 -0
  265. package/lib/module/main.js.map +1 -1
  266. package/lib/module/networking/api-requests/callState.api.js +66 -0
  267. package/lib/module/networking/api-requests/callState.api.js.map +1 -0
  268. package/lib/module/networking/api-requests/push.api.js +29 -6
  269. package/lib/module/networking/api-requests/push.api.js.map +1 -1
  270. package/lib/module/networking/api-requests/rooms.api.js +8 -2
  271. package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
  272. package/lib/module/networking/api-requests/scheduledCalls.api.js +130 -0
  273. package/lib/module/networking/api-requests/scheduledCalls.api.js.map +1 -0
  274. package/lib/module/networking/callTokenStanza.js +210 -50
  275. package/lib/module/networking/callTokenStanza.js.map +1 -1
  276. package/lib/module/roomStore/callSlice.js +57 -3
  277. package/lib/module/roomStore/callSlice.js.map +1 -1
  278. package/lib/module/services/appBadge.js +74 -0
  279. package/lib/module/services/appBadge.js.map +1 -0
  280. package/lib/module/services/languageSettings.js +44 -13
  281. package/lib/module/services/languageSettings.js.map +1 -1
  282. package/lib/module/services/pushRegistration.js +21 -5
  283. package/lib/module/services/pushRegistration.js.map +1 -1
  284. package/lib/module/version.js +1 -1
  285. package/lib/typescript/booking/index.d.ts +3 -0
  286. package/lib/typescript/booking/index.d.ts.map +1 -0
  287. package/lib/typescript/booking/pendingScheduledCall.d.ts +80 -0
  288. package/lib/typescript/booking/pendingScheduledCall.d.ts.map +1 -0
  289. package/lib/typescript/booking/scheduleForm.d.ts +28 -0
  290. package/lib/typescript/booking/scheduleForm.d.ts.map +1 -0
  291. package/lib/typescript/booking/scheduledCall.d.ts +52 -0
  292. package/lib/typescript/booking/scheduledCall.d.ts.map +1 -0
  293. package/lib/typescript/booking/scheduledCallActions.d.ts +22 -0
  294. package/lib/typescript/booking/scheduledCallActions.d.ts.map +1 -0
  295. package/lib/typescript/booking/scheduledCallLink.d.ts +37 -0
  296. package/lib/typescript/booking/scheduledCallLink.d.ts.map +1 -0
  297. package/lib/typescript/booking/scheduledCallStore.d.ts +47 -0
  298. package/lib/typescript/booking/scheduledCallStore.d.ts.map +1 -0
  299. package/lib/typescript/booking/startRoomCall.d.ts +12 -0
  300. package/lib/typescript/booking/startRoomCall.d.ts.map +1 -0
  301. package/lib/typescript/calls/callBusy.d.ts +9 -0
  302. package/lib/typescript/calls/callBusy.d.ts.map +1 -0
  303. package/lib/typescript/calls/callDisplay.d.ts +23 -0
  304. package/lib/typescript/calls/callDisplay.d.ts.map +1 -0
  305. package/lib/typescript/calls/callMode.d.ts +106 -0
  306. package/lib/typescript/calls/callMode.d.ts.map +1 -0
  307. package/lib/typescript/calls/declineReport.d.ts +11 -0
  308. package/lib/typescript/calls/declineReport.d.ts.map +1 -0
  309. package/lib/typescript/calls/p2p/P2PCallController.d.ts +150 -0
  310. package/lib/typescript/calls/p2p/P2PCallController.d.ts.map +1 -0
  311. package/lib/typescript/calls/p2p/icePolicy.d.ts +37 -0
  312. package/lib/typescript/calls/p2p/icePolicy.d.ts.map +1 -0
  313. package/lib/typescript/calls/p2p/negotiator.d.ts +57 -0
  314. package/lib/typescript/calls/p2p/negotiator.d.ts.map +1 -0
  315. package/lib/typescript/calls/p2p/p2pRuntime.d.ts +41 -0
  316. package/lib/typescript/calls/p2p/p2pRuntime.d.ts.map +1 -0
  317. package/lib/typescript/calls/p2p/signalInbox.d.ts +35 -0
  318. package/lib/typescript/calls/p2p/signalInbox.d.ts.map +1 -0
  319. package/lib/typescript/calls/p2p/signalStanza.d.ts +52 -0
  320. package/lib/typescript/calls/p2p/signalStanza.d.ts.map +1 -0
  321. package/lib/typescript/calls/p2p/webrtcRuntime.d.ts +32 -0
  322. package/lib/typescript/calls/p2p/webrtcRuntime.d.ts.map +1 -0
  323. package/lib/typescript/calls/senderTrust.d.ts +8 -0
  324. package/lib/typescript/calls/senderTrust.d.ts.map +1 -0
  325. package/lib/typescript/calls/startCall.d.ts +17 -0
  326. package/lib/typescript/calls/startCall.d.ts.map +1 -0
  327. package/lib/typescript/components/Booking/BookingIcons.d.ts +9 -0
  328. package/lib/typescript/components/Booking/BookingIcons.d.ts.map +1 -0
  329. package/lib/typescript/components/Booking/ScheduleCallButton.d.ts +11 -0
  330. package/lib/typescript/components/Booking/ScheduleCallButton.d.ts.map +1 -0
  331. package/lib/typescript/components/Booking/ScheduleCallSheet.d.ts +4 -0
  332. package/lib/typescript/components/Booking/ScheduleCallSheet.d.ts.map +1 -0
  333. package/lib/typescript/components/Booking/ScheduledCallCard.d.ts +14 -0
  334. package/lib/typescript/components/Booking/ScheduledCallCard.d.ts.map +1 -0
  335. package/lib/typescript/components/Booking/ScheduledCallHost.d.ts +10 -0
  336. package/lib/typescript/components/Booking/ScheduledCallHost.d.ts.map +1 -0
  337. package/lib/typescript/components/Booking/ScheduledCallMessage.d.ts +20 -0
  338. package/lib/typescript/components/Booking/ScheduledCallMessage.d.ts.map +1 -0
  339. package/lib/typescript/components/Booking/ScheduledCallPreJoin.d.ts +8 -0
  340. package/lib/typescript/components/Booking/ScheduledCallPreJoin.d.ts.map +1 -0
  341. package/lib/typescript/components/Booking/bookingShared.d.ts +199 -0
  342. package/lib/typescript/components/Booking/bookingShared.d.ts.map +1 -0
  343. package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
  344. package/lib/typescript/components/MainComponents/LanguageSelectorButton.d.ts +3 -1
  345. package/lib/typescript/components/MainComponents/LanguageSelectorButton.d.ts.map +1 -1
  346. package/lib/typescript/components/MainComponents/LanguageSelectorModal.d.ts.map +1 -1
  347. package/lib/typescript/components/MainComponents/MessageContainer.d.ts.map +1 -1
  348. package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
  349. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts.map +1 -1
  350. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
  351. package/lib/typescript/components/Modals/UserSettingsModal/LanguageCard.d.ts.map +1 -1
  352. package/lib/typescript/components/VideoCalls/ActiveCallBar.d.ts.map +1 -1
  353. package/lib/typescript/components/VideoCalls/CallButtons.d.ts +2 -1
  354. package/lib/typescript/components/VideoCalls/CallButtons.d.ts.map +1 -1
  355. package/lib/typescript/components/VideoCalls/CallControlBar.d.ts +17 -0
  356. package/lib/typescript/components/VideoCalls/CallControlBar.d.ts.map +1 -0
  357. package/lib/typescript/components/VideoCalls/CallVideo.d.ts +23 -0
  358. package/lib/typescript/components/VideoCalls/CallVideo.d.ts.map +1 -0
  359. package/lib/typescript/components/VideoCalls/GroupCallView.d.ts +22 -0
  360. package/lib/typescript/components/VideoCalls/GroupCallView.d.ts.map +1 -0
  361. package/lib/typescript/components/VideoCalls/P2PCallRunner.d.ts +2 -0
  362. package/lib/typescript/components/VideoCalls/P2PCallRunner.d.ts.map +1 -0
  363. package/lib/typescript/components/VideoCalls/VideoCallOverlay.d.ts.map +1 -1
  364. package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts +10 -12
  365. package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts.map +1 -1
  366. package/lib/typescript/components/VideoCalls/callActions.d.ts.map +1 -1
  367. package/lib/typescript/components/VideoCalls/callElapsed.d.ts +8 -0
  368. package/lib/typescript/components/VideoCalls/callElapsed.d.ts.map +1 -0
  369. package/lib/typescript/components/VideoCalls/callLive.d.ts +9 -0
  370. package/lib/typescript/components/VideoCalls/callLive.d.ts.map +1 -0
  371. package/lib/typescript/components/VideoCalls/callSessionController.d.ts +10 -31
  372. package/lib/typescript/components/VideoCalls/callSessionController.d.ts.map +1 -1
  373. package/lib/typescript/components/VideoCalls/callSessionTypes.d.ts +60 -0
  374. package/lib/typescript/components/VideoCalls/callSessionTypes.d.ts.map +1 -0
  375. package/lib/typescript/components/VideoCalls/groupLayout.d.ts +23 -0
  376. package/lib/typescript/components/VideoCalls/groupLayout.d.ts.map +1 -0
  377. package/lib/typescript/components/VideoCalls/p2pCallSession.d.ts +31 -0
  378. package/lib/typescript/components/VideoCalls/p2pCallSession.d.ts.map +1 -0
  379. package/lib/typescript/components/VideoCalls/useCallKeep.d.ts.map +1 -1
  380. package/lib/typescript/components/VideoCalls/useOngoingCallNotification.d.ts.map +1 -1
  381. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  382. package/lib/typescript/helpers/callPush.d.ts +11 -1
  383. package/lib/typescript/helpers/callPush.d.ts.map +1 -1
  384. package/lib/typescript/helpers/incomingCallFromPush.d.ts.map +1 -1
  385. package/lib/typescript/helpers/pushPayload.d.ts +1 -1
  386. package/lib/typescript/helpers/pushPayload.d.ts.map +1 -1
  387. package/lib/typescript/helpers/reportRoom.d.ts +19 -0
  388. package/lib/typescript/helpers/reportRoom.d.ts.map +1 -0
  389. package/lib/typescript/i18n/strings.d.ts.map +1 -1
  390. package/lib/typescript/main.d.ts +6 -1
  391. package/lib/typescript/main.d.ts.map +1 -1
  392. package/lib/typescript/networking/api-requests/callState.api.d.ts +25 -0
  393. package/lib/typescript/networking/api-requests/callState.api.d.ts.map +1 -0
  394. package/lib/typescript/networking/api-requests/push.api.d.ts +9 -2
  395. package/lib/typescript/networking/api-requests/push.api.d.ts.map +1 -1
  396. package/lib/typescript/networking/api-requests/rooms.api.d.ts +2 -1
  397. package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
  398. package/lib/typescript/networking/api-requests/scheduledCalls.api.d.ts +86 -0
  399. package/lib/typescript/networking/api-requests/scheduledCalls.api.d.ts.map +1 -0
  400. package/lib/typescript/networking/callTokenStanza.d.ts.map +1 -1
  401. package/lib/typescript/roomStore/callSlice.d.ts +23 -1
  402. package/lib/typescript/roomStore/callSlice.d.ts.map +1 -1
  403. package/lib/typescript/services/appBadge.d.ts +3 -0
  404. package/lib/typescript/services/appBadge.d.ts.map +1 -0
  405. package/lib/typescript/services/languageSettings.d.ts +7 -0
  406. package/lib/typescript/services/languageSettings.d.ts.map +1 -1
  407. package/lib/typescript/services/pushRegistration.d.ts.map +1 -1
  408. package/lib/typescript/types/types.d.ts +67 -4
  409. package/lib/typescript/types/types.d.ts.map +1 -1
  410. package/lib/typescript/version.d.ts +1 -1
  411. package/package.json +1 -1
  412. package/src/booking/index.ts +10 -0
  413. package/src/booking/pendingScheduledCall.ts +272 -0
  414. package/src/booking/scheduleForm.ts +84 -0
  415. package/src/booking/scheduledCall.ts +163 -0
  416. package/src/booking/scheduledCallActions.ts +141 -0
  417. package/src/booking/scheduledCallLink.ts +145 -0
  418. package/src/booking/scheduledCallStore.ts +69 -0
  419. package/src/booking/startRoomCall.ts +103 -0
  420. package/src/calls/callBusy.ts +10 -0
  421. package/src/calls/callDisplay.ts +74 -0
  422. package/src/calls/callMode.ts +286 -0
  423. package/src/calls/declineReport.ts +16 -0
  424. package/src/calls/p2p/P2PCallController.ts +813 -0
  425. package/src/calls/p2p/icePolicy.ts +99 -0
  426. package/src/calls/p2p/negotiator.ts +186 -0
  427. package/src/calls/p2p/p2pRuntime.ts +164 -0
  428. package/src/calls/p2p/signalInbox.ts +117 -0
  429. package/src/calls/p2p/signalStanza.ts +205 -0
  430. package/src/calls/p2p/webrtcRuntime.ts +60 -0
  431. package/src/calls/senderTrust.ts +40 -0
  432. package/src/calls/startCall.ts +56 -0
  433. package/src/components/Booking/BookingIcons.tsx +44 -0
  434. package/src/components/Booking/ScheduleCallButton.tsx +66 -0
  435. package/src/components/Booking/ScheduleCallSheet.tsx +380 -0
  436. package/src/components/Booking/ScheduledCallCard.tsx +216 -0
  437. package/src/components/Booking/ScheduledCallHost.tsx +18 -0
  438. package/src/components/Booking/ScheduledCallMessage.tsx +62 -0
  439. package/src/components/Booking/ScheduledCallPreJoin.tsx +230 -0
  440. package/src/components/Booking/bookingShared.tsx +295 -0
  441. package/src/components/MainComponents/ChatHeader.tsx +2 -0
  442. package/src/components/MainComponents/LanguageSelectorButton.tsx +9 -2
  443. package/src/components/MainComponents/LanguageSelectorModal.tsx +10 -6
  444. package/src/components/MainComponents/MessageContainer.tsx +15 -0
  445. package/src/components/MainComponents/ReduxWrapper.tsx +10 -0
  446. package/src/components/Modals/ChatProfileModal/ReportChatModal.tsx +22 -22
  447. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +28 -9
  448. package/src/components/Modals/UserSettingsModal/LanguageCard.tsx +9 -7
  449. package/src/components/VideoCalls/ActiveCallBar.tsx +6 -5
  450. package/src/components/VideoCalls/CallButtons.tsx +23 -12
  451. package/src/components/VideoCalls/CallControlBar.tsx +131 -0
  452. package/src/components/VideoCalls/CallVideo.tsx +59 -0
  453. package/src/components/VideoCalls/GroupCallView.tsx +324 -0
  454. package/src/components/VideoCalls/P2PCallRunner.tsx +192 -0
  455. package/src/components/VideoCalls/VideoCallOverlay.tsx +62 -17
  456. package/src/components/VideoCalls/VideoCallSession.tsx +55 -133
  457. package/src/components/VideoCalls/callActions.ts +3 -0
  458. package/src/components/VideoCalls/callElapsed.ts +27 -0
  459. package/src/components/VideoCalls/callLive.ts +13 -0
  460. package/src/components/VideoCalls/callSessionController.ts +130 -55
  461. package/src/components/VideoCalls/callSessionTypes.ts +80 -0
  462. package/src/components/VideoCalls/groupLayout.ts +48 -0
  463. package/src/components/VideoCalls/p2pCallSession.ts +291 -0
  464. package/src/components/VideoCalls/useCallKeep.ts +9 -2
  465. package/src/components/VideoCalls/useOngoingCallNotification.ts +2 -2
  466. package/src/context/xmppProvider.tsx +3 -0
  467. package/src/helpers/callPush.ts +13 -1
  468. package/src/helpers/incomingCallFromPush.ts +65 -7
  469. package/src/helpers/pushPayload.ts +9 -1
  470. package/src/helpers/reportRoom.ts +93 -0
  471. package/src/i18n/strings.ts +444 -0
  472. package/src/main.ts +33 -0
  473. package/src/networking/api-requests/callState.api.ts +83 -0
  474. package/src/networking/api-requests/push.api.ts +28 -3
  475. package/src/networking/api-requests/rooms.api.ts +12 -3
  476. package/src/networking/api-requests/scheduledCalls.api.ts +232 -0
  477. package/src/networking/callTokenStanza.ts +247 -50
  478. package/src/roomStore/callSlice.ts +86 -2
  479. package/src/services/appBadge.ts +85 -0
  480. package/src/services/languageSettings.ts +43 -8
  481. package/src/services/pushRegistration.ts +34 -3
  482. package/src/types/types.ts +70 -4
  483. package/src/version.ts +1 -1
@@ -0,0 +1,80 @@
1
+ /**
2
+ * What the call UI reads from the media session of the current call.
3
+ *
4
+ * Two transports fill the same snapshot: the LiveKit room
5
+ * (callSessionController.ts) and the peer to peer connection
6
+ * (p2pCallSession.ts), so the screen, the minimized strip, CallKit and the
7
+ * ongoing-call notification never need to know which one carries the call.
8
+ */
9
+
10
+ /**
11
+ * One person in a group call grid. `video` is an opaque handle for
12
+ * `<CallVideo source={...} />`, present only while a live, unmuted camera
13
+ * track exists.
14
+ */
15
+ export interface CallParticipantView {
16
+ identity: string;
17
+ name: string;
18
+ isLocal: boolean;
19
+ video: any;
20
+ micMuted: boolean;
21
+ speaking: boolean;
22
+ }
23
+
24
+ export interface CallSessionSnapshot {
25
+ /** A media session (LiveKit room or p2p connection) exists for the current call. */
26
+ active: boolean;
27
+ connected: boolean;
28
+ /** Translated, dismissible camera/mic problem. Never fails the call. */
29
+ deviceError: string | null;
30
+ micOn: boolean;
31
+ cameraOn: boolean;
32
+ speakerOn: boolean;
33
+ /** Which camera the local video comes from; only the front one is mirrored. */
34
+ facingMode: 'user' | 'environment';
35
+ /**
36
+ * Bumped whenever the local camera track is re-acquired, so the self view
37
+ * can remount onto the new stream instead of holding the stopped one.
38
+ */
39
+ localVideoEpoch: number;
40
+ /** Opaque video handle for `<CallVideo />`, live and unmuted only. */
41
+ remoteVideo: any;
42
+ localVideo: any;
43
+ remoteName: string | null;
44
+ remoteJoined: boolean;
45
+ /** Peer joined but has no live microphone. */
46
+ remoteMicMuted: boolean;
47
+ /**
48
+ * When the call truly connected: the later of the two LiveKit `joinedAt`
49
+ * stamps (p2p: when media first flowed). The server sets the LiveKit ones,
50
+ * so both sides count from the same moment (web's useSharedCallElapsed).
51
+ * Null until the peer is in. In a group: when the first two were in.
52
+ */
53
+ anchorAt: number | null;
54
+ /** Group room call: render `participants` as a grid. */
55
+ isGroup: boolean;
56
+ /** Everyone in a group call, local first. Empty for a 1:1 call. */
57
+ participants: CallParticipantView[];
58
+ /** p2p only: media was flowing and the connection is being restored. */
59
+ reconnecting: boolean;
60
+ }
61
+
62
+ export const IDLE_SESSION: CallSessionSnapshot = {
63
+ active: false,
64
+ connected: false,
65
+ deviceError: null,
66
+ micOn: true,
67
+ cameraOn: false,
68
+ speakerOn: false,
69
+ facingMode: 'user',
70
+ localVideoEpoch: 0,
71
+ remoteVideo: null,
72
+ localVideo: null,
73
+ remoteName: null,
74
+ remoteJoined: false,
75
+ remoteMicMuted: false,
76
+ anchorAt: null,
77
+ isGroup: false,
78
+ participants: [],
79
+ reconnecting: false,
80
+ };
@@ -0,0 +1,48 @@
1
+ import type { CallParticipantView } from './callSessionTypes';
2
+
3
+ /**
4
+ * Pure layout decisions of the group call grid, kept apart from the view so
5
+ * they can be tested on their own.
6
+ */
7
+
8
+ /**
9
+ * Most camera surfaces rendered at once. A phone cannot decode and draw 50
10
+ * videos; the rest of the room shows as avatars until they speak. A track
11
+ * with no surface attached is also not requested from the server
12
+ * (adaptiveStream), so this bounds the bandwidth too.
13
+ */
14
+ export const MAX_VIDEO_TILES = 9;
15
+
16
+ /** Columns of the grid for `count` participants. */
17
+ export const gridColumns = (count: number, landscape: boolean): number => {
18
+ if (count <= 1) return 1;
19
+ if (count <= 4) return landscape ? Math.min(count, 4) : 2;
20
+ return landscape ? 4 : 3;
21
+ };
22
+
23
+ /**
24
+ * Which participants get a live video surface. Whoever is speaking comes
25
+ * first, then us, then everyone else in grid order, until the budget is
26
+ * used. Participants without a live camera never take a slot.
27
+ */
28
+ export const pickVideoTiles = (
29
+ participants: CallParticipantView[],
30
+ max: number = MAX_VIDEO_TILES
31
+ ): Set<string> => {
32
+ const withVideo = participants.filter((p) => !!p.video);
33
+ const ranked = [
34
+ ...withVideo.filter((p) => p.speaking),
35
+ ...withVideo.filter((p) => !p.speaking && p.isLocal),
36
+ ...withVideo.filter((p) => !p.speaking && !p.isLocal),
37
+ ];
38
+ return new Set(ranked.slice(0, Math.max(0, max)).map((p) => p.identity));
39
+ };
40
+
41
+ /** Names of the people currently speaking, for the header line. */
42
+ export const speakingNames = (
43
+ participants: CallParticipantView[],
44
+ youLabel: string
45
+ ): string[] =>
46
+ participants
47
+ .filter((p) => p.speaking)
48
+ .map((p) => (p.isLocal ? youLabel : p.name));
@@ -0,0 +1,291 @@
1
+ import { useSyncExternalStore } from 'react';
2
+ import { Platform } from 'react-native';
3
+ import type {
4
+ P2PCallController,
5
+ P2PSnapshot,
6
+ } from '../../calls/p2p/P2PCallController';
7
+ import { loadLiveKit } from './livekitRuntime';
8
+ import { translateCallString } from './callActions';
9
+ import { CallSessionSnapshot, IDLE_SESSION } from './callSessionTypes';
10
+
11
+ /**
12
+ * The peer to peer call, seen through the same snapshot the LiveKit session
13
+ * produces (callSessionController.ts), so the call screen, the minimized
14
+ * strip, CallKit and the ongoing-call notification serve both transports.
15
+ *
16
+ * Like the LiveKit session it is owned outside React: P2PCallRunner binds the
17
+ * controller of the current call here and unbinds it when the call stops.
18
+ * Video is handed to the UI as a `{ streamURL, key }` handle for RTCView;
19
+ * remote audio needs nothing, react-native-webrtc plays it on its own.
20
+ */
21
+
22
+ // The controller words its failures in English (it is shared with the web
23
+ // SDK); the strings the user can see are mapped to the translated tables here.
24
+ const MESSAGE_KEYS: Record<string, string> = {
25
+ 'Camera or microphone permission denied': 'call.error.deviceBlocked',
26
+ 'No camera or microphone found on this device': 'call.error.deviceNotFound',
27
+ 'Your camera or microphone is already in use by another app':
28
+ 'call.error.deviceInUse',
29
+ 'Could not access your camera or microphone': 'call.error.deviceGeneric',
30
+ 'The other person could not access their camera or microphone':
31
+ 'call.error.p2pPeerMedia',
32
+ 'The call could not be connected': 'call.error.p2pConnect',
33
+ 'Could not connect the call': 'call.error.p2pConnect',
34
+ 'Could not start the call': 'call.error.p2pSetup',
35
+ 'Could not set up the call': 'call.error.p2pSetup',
36
+ 'Connection lost': 'call.error.p2pConnectionLost',
37
+ };
38
+
39
+ /** Translated version of a message the p2p controller produced. */
40
+ export const localizeP2PMessage = (message: string): string => {
41
+ const key = MESSAGE_KEYS[message];
42
+ return key ? translateCallString(key) : message;
43
+ };
44
+
45
+ interface Bound {
46
+ controller: P2PCallController;
47
+ kind: 'audio' | 'video';
48
+ unsubscribe: () => void;
49
+ /** First time media flowed; kept across reconnects. */
50
+ connectedAt: number | null;
51
+ }
52
+
53
+ let bound: Bound | null = null;
54
+ let snapshot: CallSessionSnapshot = IDLE_SESSION;
55
+ let speakerOn = false;
56
+ let facingMode: 'user' | 'environment' = 'user';
57
+ let remoteHandle: any = null;
58
+ let localHandle: any = null;
59
+ const listeners = new Set<() => void>();
60
+
61
+ const emit = (next: CallSessionSnapshot) => {
62
+ snapshot = next;
63
+ listeners.forEach((listener) => listener());
64
+ };
65
+
66
+ const subscribe = (listener: () => void) => {
67
+ listeners.add(listener);
68
+ return () => {
69
+ listeners.delete(listener);
70
+ };
71
+ };
72
+
73
+ export const getP2PSessionSnapshot = (): CallSessionSnapshot => snapshot;
74
+
75
+ export const isP2PSessionActive = (): boolean => bound !== null;
76
+
77
+ export const useP2PSession = (): CallSessionSnapshot =>
78
+ useSyncExternalStore(subscribe, getP2PSessionSnapshot, getP2PSessionSnapshot);
79
+
80
+ // A video handle for RTCView. RTCView binds to the stream's video track when
81
+ // the stream URL is set, so the key carries the track ids: a camera that is
82
+ // turned off and on again, or a remote video that arrives late, remounts the
83
+ // view onto the stream as it is now.
84
+ const videoHandle = (
85
+ stream: MediaStream | null,
86
+ previous: any
87
+ ): { handle: any } => {
88
+ const tracks = stream?.getVideoTracks?.() || [];
89
+ if (!stream || tracks.length === 0) return { handle: null };
90
+ const streamURL = String((stream as any).toURL?.() ?? '');
91
+ if (!streamURL) return { handle: null };
92
+ const key = `${streamURL}|${tracks.map((t) => t.id).join(',')}`;
93
+ if (previous && previous.key === key) return { handle: previous };
94
+ return { handle: { streamURL, key } };
95
+ };
96
+
97
+ const connectedStatus = (status: P2PSnapshot['status']): boolean =>
98
+ status === 'waiting' || status === 'connected';
99
+
100
+ const build = (current: Bound, p2p: P2PSnapshot): CallSessionSnapshot => {
101
+ const hasMedia = p2p.status === 'connected' || p2p.status === 'reconnecting';
102
+ if (hasMedia && current.connectedAt === null) {
103
+ current.connectedAt = Date.now();
104
+ }
105
+
106
+ const remote = videoHandle(
107
+ p2p.remoteVideoLive ? p2p.remoteStream : null,
108
+ remoteHandle
109
+ );
110
+ remoteHandle = remote.handle;
111
+ const local = videoHandle(
112
+ current.kind === 'video' && p2p.camEnabled ? p2p.localStream : null,
113
+ localHandle
114
+ );
115
+ localHandle = local.handle;
116
+
117
+ return {
118
+ ...IDLE_SESSION,
119
+ active: true,
120
+ // "Connected" here means the offer is out or media flows, i.e. the
121
+ // screen may say "waiting for the other person" instead of "connecting".
122
+ connected: connectedStatus(p2p.status),
123
+ deviceError: p2p.notice ? localizeP2PMessage(p2p.notice) : null,
124
+ micOn: p2p.micEnabled,
125
+ cameraOn: current.kind === 'video' && p2p.camEnabled,
126
+ speakerOn,
127
+ facingMode,
128
+ remoteVideo: remoteHandle,
129
+ localVideo: localHandle,
130
+ remoteJoined: hasMedia,
131
+ anchorAt: current.connectedAt,
132
+ reconnecting: p2p.status === 'reconnecting',
133
+ };
134
+ };
135
+
136
+ const refresh = () => {
137
+ if (!bound) return;
138
+ emit(build(bound, bound.controller.getSnapshot()));
139
+ };
140
+
141
+ /**
142
+ * Show `controller`'s call through the session snapshot. Returns the unbind
143
+ * function. Only one call is ever bound; binding another replaces it.
144
+ */
145
+ export const bindP2PSession = (
146
+ controller: P2PCallController,
147
+ kind: 'audio' | 'video'
148
+ ): (() => void) => {
149
+ if (bound?.controller === controller) return unbindFor(controller);
150
+ if (bound) unbindP2PSession();
151
+ speakerOn = kind === 'video';
152
+ facingMode = 'user';
153
+ remoteHandle = null;
154
+ localHandle = null;
155
+ const current: Bound = {
156
+ controller,
157
+ kind,
158
+ unsubscribe: controller.subscribe(refresh),
159
+ connectedAt: null,
160
+ };
161
+ bound = current;
162
+ refresh();
163
+ return unbindFor(controller);
164
+ };
165
+
166
+ const unbindFor = (controller: P2PCallController) => () => {
167
+ if (bound?.controller === controller) unbindP2PSession();
168
+ };
169
+
170
+ export const unbindP2PSession = (): void => {
171
+ const current = bound;
172
+ if (!current) return;
173
+ bound = null;
174
+ current.unsubscribe();
175
+ remoteHandle = null;
176
+ localHandle = null;
177
+ try {
178
+ void loadLiveKit()?.AudioSession?.stopAudioSession();
179
+ } catch {
180
+ // Never let teardown throw.
181
+ }
182
+ emit(IDLE_SESSION);
183
+ };
184
+
185
+ /**
186
+ * Claim the native audio session before the connection comes up. Without
187
+ * this the first seconds route to the earpiece on Android even for a video
188
+ * call (the LiveKit session does the same before `room.connect`). Best
189
+ * effort: a call answered from CallKit already owns the iOS session.
190
+ */
191
+ export const prepareP2PAudio = async (
192
+ kind: 'audio' | 'video'
193
+ ): Promise<void> => {
194
+ const audio = loadLiveKit()?.AudioSession;
195
+ if (!audio) return;
196
+ try {
197
+ await audio.startAudioSession();
198
+ } catch {
199
+ // CallKit activates the iOS audio session itself.
200
+ }
201
+ try {
202
+ await audio.setAppleAudioConfiguration?.({
203
+ audioCategory: 'playAndRecord',
204
+ audioCategoryOptions: kind === 'video' ? ['defaultToSpeaker'] : [],
205
+ audioMode: kind === 'video' ? 'videoChat' : 'voiceChat',
206
+ });
207
+ } catch {
208
+ // iOS-only helper.
209
+ }
210
+ };
211
+
212
+ /** Audio session first, then media and the offer / answer. */
213
+ export const startP2PController = async (
214
+ controller: P2PCallController,
215
+ kind: 'audio' | 'video'
216
+ ): Promise<void> => {
217
+ await prepareP2PAudio(kind);
218
+ if (bound?.controller !== controller) {
219
+ // The call was cancelled while the audio session was coming up.
220
+ try {
221
+ void loadLiveKit()?.AudioSession?.stopAudioSession();
222
+ } catch {
223
+ // Never let teardown throw.
224
+ }
225
+ return;
226
+ }
227
+ await controller.start();
228
+ };
229
+
230
+ // ---- controls -----------------------------------------------------------
231
+
232
+ export const setP2PMicEnabled = (next: boolean): void => {
233
+ const current = bound;
234
+ if (!current || current.controller.getSnapshot().micEnabled === next) return;
235
+ current.controller.toggleMic();
236
+ };
237
+
238
+ export const toggleP2PCamera = async (): Promise<void> => {
239
+ const current = bound;
240
+ if (!current) return;
241
+ await current.controller.toggleCamera();
242
+ };
243
+
244
+ /** Front / back camera of the live local video track. */
245
+ export const switchP2PCamera = (): void => {
246
+ const current = bound;
247
+ if (!current) return;
248
+ const track: any = current.controller.getSnapshot().localStream?.getVideoTracks?.()[0];
249
+ if (!track || typeof track._switchCamera !== 'function') return;
250
+ try {
251
+ track._switchCamera();
252
+ facingMode = facingMode === 'user' ? 'environment' : 'user';
253
+ refresh();
254
+ } catch {
255
+ // The camera stays where it was.
256
+ }
257
+ };
258
+
259
+ export const toggleP2PSpeaker = async (): Promise<void> => {
260
+ const current = bound;
261
+ const audio = loadLiveKit()?.AudioSession;
262
+ if (!current || !audio) return;
263
+ const next = !speakerOn;
264
+ speakerOn = next;
265
+ refresh();
266
+ try {
267
+ if (Platform.OS === 'android') {
268
+ await audio.selectAudioOutput(next ? 'speaker' : 'earpiece');
269
+ } else {
270
+ await audio.setAppleAudioConfiguration?.({
271
+ audioCategory: 'playAndRecord',
272
+ audioCategoryOptions: next ? ['defaultToSpeaker'] : [],
273
+ audioMode: next ? 'videoChat' : 'voiceChat',
274
+ });
275
+ }
276
+ } catch {
277
+ speakerOn = !next;
278
+ refresh();
279
+ }
280
+ };
281
+
282
+ export const dismissP2PDeviceError = (): void => {
283
+ bound?.controller.dismissNotice();
284
+ };
285
+
286
+ /** Reset module state. Test seam only. */
287
+ export const __resetP2PCallSessionForTests = (): void => {
288
+ unbindP2PSession();
289
+ speakerOn = false;
290
+ facingMode = 'user';
291
+ };
@@ -6,6 +6,7 @@ import { acceptIncomingCall } from '../../roomStore/callSlice';
6
6
  import { declineActiveCallWhenOnline, terminateActiveCall } from './callActions';
7
7
  import { setCallMicEnabled, useCallSession } from './callSessionController';
8
8
  import { loadLiveKit } from './livekitRuntime';
9
+ import { loadWebRTC } from '../../calls/p2p/webrtcRuntime';
9
10
  import { setCallSystemRinging } from './callUiStore';
10
11
  import {
11
12
  callKitUuid,
@@ -42,6 +43,12 @@ import {
42
43
 
43
44
  export { loadCallKeep };
44
45
 
46
+ // WebRTC's view of the iOS audio session. The LiveKit bridge and the p2p one
47
+ // load the same class from the same fork; a p2p-only host may have no
48
+ // LiveKit JS at all.
49
+ const rtcAudioSession = () =>
50
+ loadLiveKit()?.RTCAudioSession ?? loadWebRTC()?.RTCAudioSession ?? null;
51
+
45
52
  const trace = (...args: unknown[]) => {
46
53
  if (__DEV__) {console.log('[calls] CallKit:', ...args);}
47
54
  };
@@ -183,14 +190,14 @@ export const useCallKeep = (): void => {
183
190
  // unit once CallKit has activated the session.
184
191
  const onAudioActivated = () => {
185
192
  try {
186
- loadLiveKit()?.RTCAudioSession?.audioSessionDidActivate?.();
193
+ rtcAudioSession()?.audioSessionDidActivate?.();
187
194
  } catch {
188
195
  // Older webrtc builds manage the session on their own.
189
196
  }
190
197
  };
191
198
  const onAudioDeactivated = () => {
192
199
  try {
193
- loadLiveKit()?.RTCAudioSession?.audioSessionDidDeactivate?.();
200
+ rtcAudioSession()?.audioSessionDidDeactivate?.();
194
201
  } catch {
195
202
  // noop
196
203
  }
@@ -9,6 +9,7 @@ import type {
9
9
  import { terminateActiveCall } from './callActions';
10
10
  import { toggleCallCamera, toggleCallMic, useCallSession } from './callSessionController';
11
11
  import { setCallMinimized } from './callUiStore';
12
+ import { callCanRenderSession } from './callLive';
12
13
 
13
14
  /**
14
15
  * Drives the host's ongoing-call notification (`videoCalls.
@@ -25,8 +26,7 @@ export const useOngoingCallNotification = (
25
26
  const session = useCallSession();
26
27
  const shownRef = useRef(false);
27
28
 
28
- const live =
29
- !!call.token && (call.phase === 'connecting' || call.phase === 'in-call');
29
+ const live = callCanRenderSession(call);
30
30
 
31
31
  useEffect(() => {
32
32
  if (!adapter) {return;}
@@ -11,6 +11,7 @@ import React, {
11
11
  import { AppState, DeviceEventEmitter } from 'react-native';
12
12
  import NetInfo from '@react-native-community/netinfo';
13
13
  import { VideoCallOverlay } from '../components/VideoCalls/VideoCallOverlay';
14
+ import { ScheduledCallHost } from '../components/Booking/ScheduledCallHost';
14
15
  import XmppClient, {
15
16
  XmppCredentialsProvider,
16
17
  } from '../networking/xmppClient';
@@ -976,6 +977,8 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
976
977
  config and call state from Redux itself, so it needs nothing
977
978
  passed in, and renders null whenever no call is in flight. */}
978
979
  <VideoCallOverlay />
980
+ {/* Schedule / edit sheet and the pre-join screen of a scheduled call. */}
981
+ <ScheduledCallHost />
979
982
  </XmppContext.Provider>
980
983
  );
981
984
  };
@@ -9,7 +9,10 @@
9
9
 
10
10
  export interface ParsedCallPush {
11
11
  callId: string | null;
12
- /** LiveKit token, if the push carried one (lets us ring + accept offline). */
12
+ /**
13
+ * LiveKit token, if the push carried one (lets us ring + accept offline).
14
+ * Empty for a peer to peer call: there is no room to join with it.
15
+ */
13
16
  token: string | null;
14
17
  kind: 'audio' | 'video';
15
18
  /** Bare room name (JID localpart) the call belongs to. */
@@ -20,6 +23,13 @@ export interface ParsedCallPush {
20
23
  callerName: string | null;
21
24
  /** Caller's xmpp localpart, when provided. */
22
25
  callerXmppUsername: string | null;
26
+ /**
27
+ * How the call is carried. `p2p` pushes carry an empty token; an older push
28
+ * service sends no `mode`, which means `livekit`.
29
+ */
30
+ mode: 'p2p' | 'livekit';
31
+ /** The call is for a group room (always LiveKit). */
32
+ isGroup: boolean;
23
33
  }
24
34
 
25
35
  const pick = (data: Record<string, any>, keys: string[]): string => {
@@ -86,5 +96,7 @@ export const parseCallPush = (
86
96
  callerXmppUsername:
87
97
  pick(d, ['callerXmppUsername', 'callerUsername', 'userJid', 'senderJid'])
88
98
  .split('@')[0] || null,
99
+ mode: pick(d, ['mode', 'callMode']).toLowerCase() === 'p2p' ? 'p2p' : 'livekit',
100
+ isGroup: ['true', '1'].includes(pick(d, ['group', 'isGroup']).toLowerCase()),
89
101
  };
90
102
  };
@@ -2,6 +2,10 @@ import { store } from '../roomStore';
2
2
  import { acceptIncomingCall, setIncomingCallToken } from '../roomStore/callSlice';
3
3
  import { endSystemIncomingCall } from '../components/VideoCalls/systemCall';
4
4
  import { declineActiveCallWhenOnline } from '../components/VideoCalls/callActions';
5
+ import { reportCallDeclined, reportCallEnded } from '../networking/api-requests/callState.api';
6
+ import { sendCallStateSignal } from '../networking/callTokenStanza';
7
+ import { decideIncomingWhileBusy } from '../calls/callMode';
8
+ import { busySnapshot } from '../calls/callBusy';
5
9
  import { isCallPush, parseCallPush } from './callPush';
6
10
  import { normalizeRoomJid } from './normalizeRoomJid';
7
11
 
@@ -58,11 +62,53 @@ const ringFromPush = (data: Record<string, any>, intent: CallPushIntent): boolea
58
62
  return false;
59
63
  }
60
64
 
65
+ const isP2P = parsed.mode === 'p2p';
66
+
67
+ // A peer to peer call is correlated by its callId alone (there is no room
68
+ // token), and one call at a time: decided the way the call-token stanza
69
+ // decides it. The caller is told when we cannot take it.
70
+ if (isP2P) {
71
+ if (!parsed.callId) {
72
+ trace('p2p call push without a callId, dropping');
73
+ endSystemIncomingCall(parsed.callId);
74
+ return false;
75
+ }
76
+ const decision = decideIncomingWhileBusy(busySnapshot(state.call), {
77
+ mode: 'p2p',
78
+ callId: parsed.callId,
79
+ roomBareName: parsed.roomBareName,
80
+ });
81
+ if (decision === 'duplicate') {
82
+ applyIntent(intent);
83
+ return true;
84
+ }
85
+ if (decision === 'busy' || decision === 'replace') {
86
+ trace('busy, declining p2p call', parsed.callId);
87
+ reportCallDeclined(parsed.callId);
88
+ sendCallStateSignal('declined', {
89
+ peerXmppUsername: parsed.callerXmppUsername,
90
+ callId: parsed.callId,
91
+ roomBareName: parsed.roomBareName,
92
+ });
93
+ endSystemIncomingCall(parsed.callId);
94
+ return false;
95
+ }
96
+ if (decision === 'glare-keep') {
97
+ endSystemIncomingCall(parsed.callId);
98
+ return false;
99
+ }
100
+ if (decision === 'glare-yield') {
101
+ // Both sides dialled at once and theirs has the smaller id: drop ours.
102
+ sendCallStateSignal('cancelled');
103
+ reportCallEnded(state.call.callId);
104
+ }
105
+ }
106
+
61
107
  // Already ringing or in this exact call (the push raced the stanza, or
62
108
  // two pushes arrived). Re-dispatching would reset startedAt and restart
63
109
  // the ring, so leave the existing call alone.
64
110
  const current = state.call;
65
- if (current.phase !== 'idle') {
111
+ if (!isP2P && current.phase !== 'idle') {
66
112
  const sameCall =
67
113
  (!!parsed.callId && parsed.callId === current.callId) ||
68
114
  (!!parsed.roomBareName && parsed.roomBareName === current.roomBareName);
@@ -70,8 +116,9 @@ const ringFromPush = (data: Record<string, any>, intent: CallPushIntent): boolea
70
116
  applyIntent(intent);
71
117
  return true;
72
118
  }
73
- if (current.phase === 'in-call') {
74
- // Busy with another call: no second ring.
119
+ if (current.phase === 'in-call' || current.mode === 'p2p') {
120
+ // Busy with another call: no second ring. (A p2p call is never
121
+ // replaced by a LiveKit one, whatever phase it is in.)
75
122
  endSystemIncomingCall(parsed.callId);
76
123
  return false;
77
124
  }
@@ -81,7 +128,8 @@ const ringFromPush = (data: Record<string, any>, intent: CallPushIntent): boolea
81
128
  // an alert. Ringing anyway would give the user an Accept button that
82
129
  // cannot work, so treat it as handled and let the stanza (once the
83
130
  // socket is back up) open the real ring screen.
84
- if (!parsed.token) {
131
+ // A p2p call carries no token by design: it is answered over XMPP.
132
+ if (!parsed.token && !isP2P) {
85
133
  endSystemIncomingCall(parsed.callId);
86
134
  return false;
87
135
  }
@@ -107,15 +155,25 @@ const ringFromPush = (data: Record<string, any>, intent: CallPushIntent): boolea
107
155
  return false;
108
156
  }
109
157
 
158
+ // In a group the call is the ROOM and the caller is a separate line; a
159
+ // 1:1 call is named after the caller.
160
+ const roomTitle = resolved?.title || resolved?.name || null;
110
161
  store.dispatch(
111
162
  setIncomingCallToken({
112
163
  roomJid,
113
- roomName: parsed.callerName || resolved?.title || resolved?.name || null,
164
+ roomName: parsed.isGroup
165
+ ? roomTitle
166
+ : parsed.callerName || roomTitle,
114
167
  roomBareName: parsed.roomBareName,
115
- token: parsed.token,
168
+ token: parsed.token || '',
116
169
  kind: parsed.kind,
117
170
  callId: parsed.callId,
118
- peerXmppUsername: parsed.callerXmppUsername,
171
+ // A group has no single peer to signal.
172
+ peerXmppUsername: parsed.isGroup ? null : parsed.callerXmppUsername,
173
+ mode: parsed.mode,
174
+ isGroup: parsed.isGroup,
175
+ callerName: parsed.callerName,
176
+ callerXmppUsername: parsed.callerXmppUsername,
119
177
  })
120
178
  );
121
179
  trace('ringing', parsed.callId, intent);
@@ -7,8 +7,14 @@ import {
7
7
  } from '../roomStore/roomsSlice';
8
8
  import { handleCallPush } from './incomingCallFromPush';
9
9
  import { normalizeRoomJid } from './normalizeRoomJid';
10
+ import { handleScheduledCallPush } from '../booking/pendingScheduledCall';
10
11
 
11
- export type PushPayloadOutcome = 'call' | 'room' | 'pending' | 'unknown';
12
+ export type PushPayloadOutcome =
13
+ | 'call'
14
+ | 'scheduledCall'
15
+ | 'room'
16
+ | 'pending'
17
+ | 'unknown';
12
18
 
13
19
  export const PENDING_NOTIFICATION_JID_KEY = 'ethora_pending_notification_jid';
14
20
  export const PENDING_NOTIFICATION_TTL_MS = 5 * 60 * 1000;
@@ -54,6 +60,8 @@ export const handlePushPayload = (
54
60
  ): PushPayloadOutcome => {
55
61
  if (!data) {return 'unknown';}
56
62
  if (handleCallPush(data as Record<string, any>)) {return 'call';}
63
+ // The reminder before a scheduled call opens the same flow as its link.
64
+ if (handleScheduledCallPush(data)) {return 'scheduledCall';}
57
65
  const jid = data.jid ?? data.chatJid ?? data.roomJid ?? data.roomJID;
58
66
  if (typeof jid === 'string' && jid) {
59
67
  return openRoomFromPush(jid);