@ethora/chat-component-rn 26.10.1 → 26.10.3
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.
- package/lib/commonjs/components/MainComponents/ChatHeader.js +11 -10
- package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageContainer.js +10 -2
- package/lib/commonjs/components/MainComponents/MessageContainer.js.map +1 -1
- package/lib/commonjs/components/MainComponents/RoomList.js +8 -18
- package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +17 -14
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +131 -17
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +6 -1
- package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/CallButtons.js +3 -1
- package/lib/commonjs/components/VideoCalls/CallButtons.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js +123 -111
- package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/VideoCallSession.js +207 -346
- package/lib/commonjs/components/VideoCalls/VideoCallSession.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/callActions.js +61 -0
- package/lib/commonjs/components/VideoCalls/callActions.js.map +1 -0
- package/lib/commonjs/components/VideoCalls/callSessionController.js +431 -0
- package/lib/commonjs/components/VideoCalls/callSessionController.js.map +1 -0
- package/lib/commonjs/components/VideoCalls/useDraggable.js +59 -0
- package/lib/commonjs/components/VideoCalls/useDraggable.js.map +1 -0
- package/lib/commonjs/helpers/createRoomFromApi.js +4 -0
- package/lib/commonjs/helpers/createRoomFromApi.js.map +1 -1
- package/lib/commonjs/helpers/incomingCallFromPush.js +1 -1
- package/lib/commonjs/helpers/incomingCallFromPush.js.map +1 -1
- package/lib/commonjs/helpers/roomUserCount.js +7 -1
- package/lib/commonjs/helpers/roomUserCount.js.map +1 -1
- package/lib/commonjs/helpers/uniqueMembers.js +36 -0
- package/lib/commonjs/helpers/uniqueMembers.js.map +1 -0
- package/lib/commonjs/hooks/useLeaveRoom.js +52 -0
- package/lib/commonjs/hooks/useLeaveRoom.js.map +1 -0
- package/lib/commonjs/hooks/useLogout.js +15 -10
- package/lib/commonjs/hooks/useLogout.js.map +1 -1
- package/lib/commonjs/i18n/strings.js +18 -0
- package/lib/commonjs/i18n/strings.js.map +1 -1
- package/lib/commonjs/networking/api-requests/rooms.api.js +36 -1
- package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/commonjs/networking/callTokenStanza.js +47 -3
- package/lib/commonjs/networking/callTokenStanza.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +9 -2
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/module/components/MainComponents/ChatHeader.js +13 -12
- package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/module/components/MainComponents/MessageContainer.js +10 -2
- package/lib/module/components/MainComponents/MessageContainer.js.map +1 -1
- package/lib/module/components/MainComponents/RoomList.js +8 -18
- package/lib/module/components/MainComponents/RoomList.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +18 -15
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +132 -18
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/module/components/RoomComponents/ChatRoomItem.js +6 -1
- package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
- package/lib/module/components/VideoCalls/CallButtons.js +3 -1
- package/lib/module/components/VideoCalls/CallButtons.js.map +1 -1
- package/lib/module/components/VideoCalls/VideoCallOverlay.js +125 -113
- package/lib/module/components/VideoCalls/VideoCallOverlay.js.map +1 -1
- package/lib/module/components/VideoCalls/VideoCallSession.js +208 -348
- package/lib/module/components/VideoCalls/VideoCallSession.js.map +1 -1
- package/lib/module/components/VideoCalls/callActions.js +55 -0
- package/lib/module/components/VideoCalls/callActions.js.map +1 -0
- package/lib/module/components/VideoCalls/callSessionController.js +420 -0
- package/lib/module/components/VideoCalls/callSessionController.js.map +1 -0
- package/lib/module/components/VideoCalls/useDraggable.js +55 -0
- package/lib/module/components/VideoCalls/useDraggable.js.map +1 -0
- package/lib/module/helpers/createRoomFromApi.js +4 -0
- package/lib/module/helpers/createRoomFromApi.js.map +1 -1
- package/lib/module/helpers/incomingCallFromPush.js +1 -1
- package/lib/module/helpers/incomingCallFromPush.js.map +1 -1
- package/lib/module/helpers/roomUserCount.js +7 -1
- package/lib/module/helpers/roomUserCount.js.map +1 -1
- package/lib/module/helpers/uniqueMembers.js +31 -0
- package/lib/module/helpers/uniqueMembers.js.map +1 -0
- package/lib/module/hooks/useLeaveRoom.js +48 -0
- package/lib/module/hooks/useLeaveRoom.js.map +1 -0
- package/lib/module/hooks/useLogout.js +15 -10
- package/lib/module/hooks/useLogout.js.map +1 -1
- package/lib/module/i18n/strings.js +18 -0
- package/lib/module/i18n/strings.js.map +1 -1
- package/lib/module/networking/api-requests/rooms.api.js +35 -1
- package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/module/networking/callTokenStanza.js +47 -3
- package/lib/module/networking/callTokenStanza.js.map +1 -1
- package/lib/module/networking/xmppClient.js +8 -1
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageContainer.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/CallButtons.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/VideoCallOverlay.d.ts +0 -6
- package/lib/typescript/components/VideoCalls/VideoCallOverlay.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts +9 -20
- package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/callActions.d.ts +15 -0
- package/lib/typescript/components/VideoCalls/callActions.d.ts.map +1 -0
- package/lib/typescript/components/VideoCalls/callSessionController.d.ts +61 -0
- package/lib/typescript/components/VideoCalls/callSessionController.d.ts.map +1 -0
- package/lib/typescript/components/VideoCalls/useDraggable.d.ts +19 -0
- package/lib/typescript/components/VideoCalls/useDraggable.d.ts.map +1 -0
- package/lib/typescript/helpers/createRoomFromApi.d.ts.map +1 -1
- package/lib/typescript/helpers/roomUserCount.d.ts +1 -0
- package/lib/typescript/helpers/roomUserCount.d.ts.map +1 -1
- package/lib/typescript/helpers/uniqueMembers.d.ts +11 -0
- package/lib/typescript/helpers/uniqueMembers.d.ts.map +1 -0
- package/lib/typescript/hooks/useLeaveRoom.d.ts +9 -0
- package/lib/typescript/hooks/useLeaveRoom.d.ts.map +1 -0
- package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
- package/lib/typescript/i18n/strings.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/rooms.api.d.ts +8 -0
- package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
- package/lib/typescript/networking/callTokenStanza.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/MainComponents/ChatHeader.tsx +10 -8
- package/src/components/MainComponents/MessageContainer.tsx +14 -1
- package/src/components/MainComponents/RoomList.tsx +8 -14
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +16 -13
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +167 -36
- package/src/components/RoomComponents/ChatRoomItem.tsx +8 -1
- package/src/components/VideoCalls/CallButtons.tsx +5 -1
- package/src/components/VideoCalls/VideoCallOverlay.tsx +156 -163
- package/src/components/VideoCalls/VideoCallSession.tsx +207 -378
- package/src/components/VideoCalls/callActions.ts +63 -0
- package/src/components/VideoCalls/callSessionController.ts +421 -0
- package/src/components/VideoCalls/useDraggable.ts +46 -0
- package/src/helpers/createRoomFromApi.tsx +2 -0
- package/src/helpers/incomingCallFromPush.ts +2 -2
- package/src/helpers/roomUserCount.ts +6 -2
- package/src/helpers/uniqueMembers.ts +26 -0
- package/src/hooks/useLeaveRoom.ts +42 -0
- package/src/hooks/useLogout.tsx +15 -10
- package/src/i18n/strings.ts +18 -0
- package/src/networking/api-requests/rooms.api.ts +28 -1
- package/src/networking/callTokenStanza.ts +46 -6
- package/src/networking/xmppClient.ts +10 -1
- package/src/version.ts +1 -1
package/src/hooks/useLogout.tsx
CHANGED
|
@@ -50,7 +50,18 @@ const logoutService = {
|
|
|
50
50
|
* AFTER all the disk work has actually landed.
|
|
51
51
|
*/
|
|
52
52
|
performLogout: async (): Promise<void> => {
|
|
53
|
-
// 0.
|
|
53
|
+
// 0. Push. Release the device-token registration on the backend
|
|
54
|
+
// FIRST, while the access token is still valid (the token itself
|
|
55
|
+
// is kept so the next login re-registers it). It runs alongside
|
|
56
|
+
// the private-store flush below instead of after it: the flush
|
|
57
|
+
// can take up to 2s, and a host with a logout time budget could
|
|
58
|
+
// cut us off before the release went out, leaving the device
|
|
59
|
+
// receiving pushes for the logged-out user.
|
|
60
|
+
const pushRelease = releasePushRegistration().catch((e) => {
|
|
61
|
+
console.warn('logoutService: push release failed', e);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// 0a. Flush lastViewedTimestamp to the server's private store BEFORE
|
|
54
65
|
// we close XMPP. Only rooms with no outstanding unread (plus the
|
|
55
66
|
// visible room) get their entries updated — rooms with unread
|
|
56
67
|
// keep their old marker so the next login still surfaces those
|
|
@@ -95,15 +106,9 @@ const logoutService = {
|
|
|
95
106
|
/* non-fatal */
|
|
96
107
|
}
|
|
97
108
|
|
|
98
|
-
// 2. Push.
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
// room cache.
|
|
102
|
-
try {
|
|
103
|
-
await releasePushRegistration();
|
|
104
|
-
} catch (e) {
|
|
105
|
-
console.warn('logoutService: push release failed', e);
|
|
106
|
-
}
|
|
109
|
+
// 2. Push. Wait for the release started in step 0, then clear the
|
|
110
|
+
// local MucSub room cache.
|
|
111
|
+
await pushRelease;
|
|
107
112
|
try {
|
|
108
113
|
await pushSubscriptionService.reset();
|
|
109
114
|
} catch (e) {
|
package/src/i18n/strings.ts
CHANGED
|
@@ -128,6 +128,8 @@ const en: UiStringTable = {
|
|
|
128
128
|
'call.error.deviceInUse': 'Your camera or microphone is already in use by another app.',
|
|
129
129
|
'call.error.deviceGeneric': 'Could not access your camera or microphone.',
|
|
130
130
|
'call.error.noAnswerTimeout': 'No answer, the call timed out',
|
|
131
|
+
'call.peerMuted': '{name} is muted',
|
|
132
|
+
'call.selfMuted': 'Your microphone is muted',
|
|
131
133
|
'action.send': 'Send',
|
|
132
134
|
'action.cancel': 'Cancel',
|
|
133
135
|
'action.save': 'Save',
|
|
@@ -138,6 +140,7 @@ const en: UiStringTable = {
|
|
|
138
140
|
'action.mute': 'Mute',
|
|
139
141
|
'action.unmute': 'Unmute',
|
|
140
142
|
'toast.muteFailed': 'Could not update notifications for this chat',
|
|
143
|
+
'toast.leaveFailed': 'Could not leave this chat',
|
|
141
144
|
'action.create': 'Create',
|
|
142
145
|
'action.submit': 'Submit',
|
|
143
146
|
'action.translate': 'Translate',
|
|
@@ -505,6 +508,8 @@ const fr: UiStringTable = {
|
|
|
505
508
|
'call.error.deviceInUse': 'Votre caméra ou microphone est déjà utilisé par une autre application.',
|
|
506
509
|
'call.error.deviceGeneric': 'Impossible d\'accéder à votre caméra ou microphone.',
|
|
507
510
|
'call.error.noAnswerTimeout': 'Pas de réponse, l\'appel a expiré',
|
|
511
|
+
'call.peerMuted': '{name} a coupé son micro',
|
|
512
|
+
'call.selfMuted': 'Votre micro est coupé',
|
|
508
513
|
'action.send': 'Envoyer',
|
|
509
514
|
'action.cancel': 'Annuler',
|
|
510
515
|
'action.save': 'Enregistrer',
|
|
@@ -515,6 +520,7 @@ const fr: UiStringTable = {
|
|
|
515
520
|
'action.mute': 'Muet',
|
|
516
521
|
'action.unmute': 'Réactiver',
|
|
517
522
|
'toast.muteFailed': 'Impossible de modifier les notifications de ce chat',
|
|
523
|
+
'toast.leaveFailed': 'Impossible de quitter ce chat',
|
|
518
524
|
'action.create': 'Créer',
|
|
519
525
|
'action.submit': 'Soumettre',
|
|
520
526
|
'action.translate': 'Traduire',
|
|
@@ -882,6 +888,8 @@ const es: UiStringTable = {
|
|
|
882
888
|
'call.error.deviceInUse': 'Tu cámara o micrófono ya está siendo usado por otra aplicación.',
|
|
883
889
|
'call.error.deviceGeneric': 'No se pudo acceder a tu cámara o micrófono.',
|
|
884
890
|
'call.error.noAnswerTimeout': 'Sin respuesta, la llamada expiró',
|
|
891
|
+
'call.peerMuted': '{name} tiene el micrófono silenciado',
|
|
892
|
+
'call.selfMuted': 'Tu micrófono está silenciado',
|
|
885
893
|
'action.send': 'Enviar',
|
|
886
894
|
'action.cancel': 'Cancelar',
|
|
887
895
|
'action.save': 'Guardar',
|
|
@@ -892,6 +900,7 @@ const es: UiStringTable = {
|
|
|
892
900
|
'action.mute': 'Silenciar',
|
|
893
901
|
'action.unmute': 'Activar',
|
|
894
902
|
'toast.muteFailed': 'No se pudieron cambiar las notificaciones de este chat',
|
|
903
|
+
'toast.leaveFailed': 'No se pudo salir de este chat',
|
|
895
904
|
'action.create': 'Crear',
|
|
896
905
|
'action.submit': 'Enviar',
|
|
897
906
|
'action.translate': 'Traducir',
|
|
@@ -1259,6 +1268,8 @@ const pt: UiStringTable = {
|
|
|
1259
1268
|
'call.error.deviceInUse': 'A sua câmara ou microfone já está a ser utilizado por outra aplicação.',
|
|
1260
1269
|
'call.error.deviceGeneric': 'Não foi possível aceder à câmara ou microfone.',
|
|
1261
1270
|
'call.error.noAnswerTimeout': 'Sem resposta, a chamada expirou',
|
|
1271
|
+
'call.peerMuted': '{name} está com o microfone desativado',
|
|
1272
|
+
'call.selfMuted': 'Seu microfone está desativado',
|
|
1262
1273
|
'action.send': 'Enviar',
|
|
1263
1274
|
'action.cancel': 'Cancelar',
|
|
1264
1275
|
'action.save': 'Guardar',
|
|
@@ -1269,6 +1280,7 @@ const pt: UiStringTable = {
|
|
|
1269
1280
|
'action.mute': 'Silenciar',
|
|
1270
1281
|
'action.unmute': 'Ativar som',
|
|
1271
1282
|
'toast.muteFailed': 'Could not update notifications for this chat',
|
|
1283
|
+
'toast.leaveFailed': 'Não foi possível sair deste chat',
|
|
1272
1284
|
'action.create': 'Criar',
|
|
1273
1285
|
'action.submit': 'Enviar',
|
|
1274
1286
|
'action.translate': 'Traduzir',
|
|
@@ -1636,6 +1648,8 @@ const ht: UiStringTable = {
|
|
|
1636
1648
|
'call.error.deviceInUse': 'Kamera oswa mikwofòn ou deja ap itilize pa yon lòt app.',
|
|
1637
1649
|
'call.error.deviceGeneric': 'Nou pa t kapab jwenn aksè nan kamera oswa mikwofòn ou.',
|
|
1638
1650
|
'call.error.noAnswerTimeout': 'Pa gen repons, apèl la fini',
|
|
1651
|
+
'call.peerMuted': '{name} koupe mikwo li',
|
|
1652
|
+
'call.selfMuted': 'Mikwo ou koupe',
|
|
1639
1653
|
'action.send': 'Voye',
|
|
1640
1654
|
'action.cancel': 'Anile',
|
|
1641
1655
|
'action.save': 'Anrejistre',
|
|
@@ -1646,6 +1660,7 @@ const ht: UiStringTable = {
|
|
|
1646
1660
|
'action.mute': 'Mete an silans',
|
|
1647
1661
|
'action.unmute': 'Retire silans',
|
|
1648
1662
|
'toast.muteFailed': 'Could not update notifications for this chat',
|
|
1663
|
+
'toast.leaveFailed': 'Pa t kapab kite chat sa a',
|
|
1649
1664
|
'action.create': 'Kreye',
|
|
1650
1665
|
'action.submit': 'Soumèt',
|
|
1651
1666
|
'action.translate': 'Tradui',
|
|
@@ -2013,6 +2028,8 @@ const zh: UiStringTable = {
|
|
|
2013
2028
|
'call.error.deviceInUse': '您的摄像头或麦克风正被其他应用占用。',
|
|
2014
2029
|
'call.error.deviceGeneric': '无法访问您的摄像头或麦克风。',
|
|
2015
2030
|
'call.error.noAnswerTimeout': '无人接听,通话已超时',
|
|
2031
|
+
'call.peerMuted': '{name} 已静音',
|
|
2032
|
+
'call.selfMuted': '你的麦克风已静音',
|
|
2016
2033
|
'action.send': '发送',
|
|
2017
2034
|
'action.cancel': '取消',
|
|
2018
2035
|
'action.save': '保存',
|
|
@@ -2023,6 +2040,7 @@ const zh: UiStringTable = {
|
|
|
2023
2040
|
'action.mute': '静音',
|
|
2024
2041
|
'action.unmute': '取消静音',
|
|
2025
2042
|
'toast.muteFailed': 'Could not update notifications for this chat',
|
|
2043
|
+
'toast.leaveFailed': '无法退出此聊天',
|
|
2026
2044
|
'action.create': '创建',
|
|
2027
2045
|
'action.submit': '提交',
|
|
2028
2046
|
'action.translate': '翻译',
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ApiRoom, DeleteRoomMember, PostAddRoomMember, PostReportRoom, PostRoom, RoomMember } from '../../types/models/room.model';
|
|
2
|
+
import { uniqueMembers } from '../../helpers/uniqueMembers';
|
|
2
3
|
import { store } from '../../roomStore';
|
|
3
4
|
import { addRoom, mergeUsersSet, updateRoom } from '../../roomStore/roomsSlice';
|
|
4
5
|
import { IRoom } from '../../types/types';
|
|
@@ -118,7 +119,7 @@ export function ownAppId(): string {
|
|
|
118
119
|
|
|
119
120
|
const toRoomMembers = (members: any[] | undefined): RoomMember[] => {
|
|
120
121
|
const known = (store.getState().rooms?.usersSet || {}) as Record<string, RoomMember>;
|
|
121
|
-
return (members
|
|
122
|
+
return uniqueMembers(members).map((m: any) => ({
|
|
122
123
|
firstName: m.firstName,
|
|
123
124
|
lastName: m.lastName,
|
|
124
125
|
profileImage:
|
|
@@ -495,6 +496,32 @@ export async function deleteRoomMember(data: DeleteRoomMember) {
|
|
|
495
496
|
}
|
|
496
497
|
}
|
|
497
498
|
|
|
499
|
+
/**
|
|
500
|
+
* Take the signed-in user out of a chat on the server (self-removal via the
|
|
501
|
+
* same endpoint that removes other members). The unavailable presence alone
|
|
502
|
+
* only leaves the MUC for this session: the backend keeps the user in
|
|
503
|
+
* `members` and the next /chats/my brings the chat back. A 404 means the
|
|
504
|
+
* server already has us out, which is what we wanted.
|
|
505
|
+
*/
|
|
506
|
+
export async function leaveRoom(chatName: string): Promise<void> {
|
|
507
|
+
const me = (store.getState().chatSettingStore?.user?.xmppUsername || '').split('@')[0];
|
|
508
|
+
if (!chatName || !me) {
|
|
509
|
+
throw new Error('Cannot leave the chat: no chat name or user');
|
|
510
|
+
}
|
|
511
|
+
const token = store.getState().chatSettingStore.user.token || '';
|
|
512
|
+
invalidateRoomsCache();
|
|
513
|
+
try {
|
|
514
|
+
await http.delete('/v1/chats/users-access', {
|
|
515
|
+
headers: { Authorization: token },
|
|
516
|
+
data: { chatName, members: [me] },
|
|
517
|
+
});
|
|
518
|
+
} catch (error: any) {
|
|
519
|
+
if (error?.response?.status !== 404) {throw error;}
|
|
520
|
+
} finally {
|
|
521
|
+
invalidateRoomsCache();
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
498
525
|
export async function deleteRoom(name: string) {
|
|
499
526
|
const token = store.getState().chatSettingStore.user.token || '';
|
|
500
527
|
|
|
@@ -57,6 +57,15 @@ const consumeKindHint = (
|
|
|
57
57
|
|
|
58
58
|
const MAX_CALL_TOKEN_AGE_MS = 5000;
|
|
59
59
|
|
|
60
|
+
// Dev-only trace of call signalling: which `<data type="call-*">` frames
|
|
61
|
+
// arrive and why a call-token was dropped. A dropped token is silent
|
|
62
|
+
// otherwise: the caller sits on "Calling..." and the callee never rings.
|
|
63
|
+
const callTrace = (message: string, extra?: Record<string, unknown>) => {
|
|
64
|
+
if (typeof __DEV__ !== 'undefined' && __DEV__) {
|
|
65
|
+
console.log(`[calls] ${message}`, extra ? JSON.stringify(extra) : '');
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
60
69
|
// Hermes has no global `atob` and RN ships no Buffer polyfill by default,
|
|
61
70
|
// so the JWT payload is decoded here by hand. Only used on the ~500-byte
|
|
62
71
|
// middle segment of a call token, so a table-driven loop is plenty fast
|
|
@@ -215,7 +224,7 @@ const isFreshCallToken = (stanza: Element): boolean => {
|
|
|
215
224
|
const resolveRoomByStanzaRoom = (roomAttr: string) => {
|
|
216
225
|
const rooms = (store.getState().rooms.rooms || {}) as Record<
|
|
217
226
|
string,
|
|
218
|
-
{ jid?: string; name?: string; type?: string; usersCnt?: number }
|
|
227
|
+
{ jid?: string; name?: string; title?: string; type?: string; usersCnt?: number }
|
|
219
228
|
>;
|
|
220
229
|
const roomEntries = Object.values(rooms);
|
|
221
230
|
|
|
@@ -338,6 +347,18 @@ export const onCallTokenMessage = (stanza: Element): boolean => {
|
|
|
338
347
|
const data = findCallData(inner);
|
|
339
348
|
if (data) {
|
|
340
349
|
const dataType = String(data.attrs?.type || '').toLowerCase();
|
|
350
|
+
const traceStanzaId = inner.getChild?.('stanza-id')?.attrs?.id;
|
|
351
|
+
const traceTs = extractNumericTimestamp(traceStanzaId);
|
|
352
|
+
callTrace(`received ${dataType}`, {
|
|
353
|
+
from: stanza.attrs?.from,
|
|
354
|
+
type: stanza.attrs?.type,
|
|
355
|
+
wrapped: inner !== stanza,
|
|
356
|
+
room: data.attrs?.room,
|
|
357
|
+
callId: data.attrs?.callId || data.attrs?.callid,
|
|
358
|
+
hasToken: !!data.attrs?.token,
|
|
359
|
+
stanzaId: traceStanzaId,
|
|
360
|
+
ageMs: traceTs ? Date.now() - traceTs : null,
|
|
361
|
+
});
|
|
341
362
|
|
|
342
363
|
if (dataType === 'call-state') {
|
|
343
364
|
// Surface the raw call-state attrs so we can confirm what the server
|
|
@@ -404,9 +425,11 @@ export const onCallTokenMessage = (stanza: Element): boolean => {
|
|
|
404
425
|
const videoCallsConfig =
|
|
405
426
|
store.getState().chatSettingStore.config?.videoCalls;
|
|
406
427
|
if (videoCallsConfig?.enabled !== true) {
|
|
428
|
+
callTrace('drop call-token: calls disabled');
|
|
407
429
|
return true;
|
|
408
430
|
}
|
|
409
431
|
if (!isFreshCallToken(inner)) {
|
|
432
|
+
callTrace('drop call-token: not fresh');
|
|
410
433
|
return true;
|
|
411
434
|
}
|
|
412
435
|
|
|
@@ -423,6 +446,7 @@ export const onCallTokenMessage = (stanza: Element): boolean => {
|
|
|
423
446
|
const kind: 'audio' | 'video' =
|
|
424
447
|
hintedKind || (stanzaKind === 'audio' ? 'audio' : 'video');
|
|
425
448
|
if (!token || !stanzaRoom) {
|
|
449
|
+
callTrace('drop call-token: no token or room');
|
|
426
450
|
return true;
|
|
427
451
|
}
|
|
428
452
|
|
|
@@ -436,9 +460,11 @@ export const onCallTokenMessage = (stanza: Element): boolean => {
|
|
|
436
460
|
resolvedRoom.type !== 'private' &&
|
|
437
461
|
!isOneToOneLikeRoom
|
|
438
462
|
) {
|
|
463
|
+
callTrace('drop call-token: room type', { type: resolvedRoom.type, usersCnt });
|
|
439
464
|
return true;
|
|
440
465
|
}
|
|
441
466
|
if (resolvedRoom?.type === 'private' && !isPrivateAllowed) {
|
|
467
|
+
callTrace('drop call-token: private not allowed');
|
|
442
468
|
return true;
|
|
443
469
|
}
|
|
444
470
|
if (
|
|
@@ -446,6 +472,7 @@ export const onCallTokenMessage = (stanza: Element): boolean => {
|
|
|
446
472
|
!stanzaRoom.includes('@') &&
|
|
447
473
|
!isOneToOneLikeRoom
|
|
448
474
|
) {
|
|
475
|
+
callTrace('drop call-token: room unknown', { stanzaRoom });
|
|
449
476
|
return true;
|
|
450
477
|
}
|
|
451
478
|
|
|
@@ -457,17 +484,25 @@ export const onCallTokenMessage = (stanza: Element): boolean => {
|
|
|
457
484
|
// title (which for stale / deleted-peer chats reads "deleted").
|
|
458
485
|
const jwtPayload = decodeJwtPayload(token);
|
|
459
486
|
const callerName = extractCallerDisplayName(jwtPayload);
|
|
460
|
-
|
|
487
|
+
// `title` is the display name; on new-arch private rooms `name` is the
|
|
488
|
+
// bare room id ("${appId}_<a>-${appId}_<b>"), never something to show.
|
|
489
|
+
const resolvedTitle = String(
|
|
490
|
+
resolvedRoom?.title || resolvedRoom?.name || ''
|
|
491
|
+
).trim();
|
|
461
492
|
const titleLooksBad =
|
|
462
493
|
!resolvedTitle ||
|
|
494
|
+
resolvedTitle === stanzaRoom ||
|
|
463
495
|
['deleted', 'deleted user', 'unknown', 'null'].includes(
|
|
464
496
|
resolvedTitle.toLowerCase()
|
|
465
497
|
);
|
|
498
|
+
// Never fall back to the room id: an empty name renders as
|
|
499
|
+
// "Unknown caller" on the ring screen.
|
|
466
500
|
const incomingRoomName =
|
|
467
|
-
(
|
|
468
|
-
|
|
469
|
-
stanzaRoom;
|
|
470
|
-
|
|
501
|
+
(titleLooksBad ? callerName : resolvedTitle) || callerName || '';
|
|
502
|
+
if (!roomJid) {
|
|
503
|
+
callTrace('drop call-token: no room jid', { stanzaRoom });
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
471
506
|
|
|
472
507
|
const callId = extractCallId(data, jwtPayload);
|
|
473
508
|
const selfXmpp =
|
|
@@ -481,6 +516,11 @@ export const onCallTokenMessage = (stanza: Element): boolean => {
|
|
|
481
516
|
callState.roomName === incomingRoomName ||
|
|
482
517
|
callState.roomBareName === stanzaRoom);
|
|
483
518
|
|
|
519
|
+
callTrace('accept call-token', {
|
|
520
|
+
outgoing: isOutgoingRoomMatch,
|
|
521
|
+
roomJid,
|
|
522
|
+
callId,
|
|
523
|
+
});
|
|
484
524
|
if (isOutgoingRoomMatch) {
|
|
485
525
|
store.dispatch(
|
|
486
526
|
setOutgoingCallToken({ roomJid, token, callId: callId || null })
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import xmpp, { Client } from '@xmpp/client';
|
|
1
|
+
import xmpp, { Client, xml } from '@xmpp/client';
|
|
2
2
|
import { walletToUsername } from '../helpers/walletUsername';
|
|
3
3
|
import { IMessage, xmppSettingsInterface } from '../types/types';
|
|
4
4
|
|
|
@@ -765,6 +765,15 @@ export class XmppClient {
|
|
|
765
765
|
this.authRecoveryFailures = 0;
|
|
766
766
|
this.authRejectionsSinceOnline = 0;
|
|
767
767
|
this.reconnectAttempts = 0;
|
|
768
|
+
// Initial presence, as the web client sends on 'online'. Without it
|
|
769
|
+
// the session is never "available" to ejabberd, which then holds
|
|
770
|
+
// back every `type="chat"` message addressed to the bare JID: the
|
|
771
|
+
// call-invite and the call-token never arrived, so the phone neither
|
|
772
|
+
// rang nor joined its own outgoing call. Room traffic was unaffected
|
|
773
|
+
// (MUC joins and mucsub don't need it), which hid the problem.
|
|
774
|
+
Promise.resolve()
|
|
775
|
+
.then(() => this.client.send(xml('presence')))
|
|
776
|
+
.catch((err: unknown) => console.warn('initial presence failed', err));
|
|
768
777
|
this.sendAllPresencesAndMarkReady();
|
|
769
778
|
try {
|
|
770
779
|
devPushLog(
|
package/src/version.ts
CHANGED