Call push: ring ALL of a user's devices, not just the first
sendCallNotification returned after the iOS VoIP branch, so a user signed in on both an iPhone (ios-voip token) and an Android phone only got the call on iOS — the Android invite was never sent, so a swiped-away Android phone never rang (confirmed on-device: only type=cancel reached Android, never type=invite, since sendCallCancel does fan out to all platforms). Now send to iOS VoIP AND Android FCM, and only fall back to the banner when no native device was waked. Server-only; no app rebuild. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
cab0c79f57
commit
da5b44c0a5
1 file changed
+13
-7
+13
-7
@@ -157,8 +157,13 @@ async function sendCallNotification(userId, data) {
|
||||
// data: { callUUID, room, kind, callerId, callerName, groupId, groupName, title, body, hasVideo }
|
||||
let toks = [];
|
||||
try { toks = await R.deviceTokens.byUser(userId); } catch (_) { toks = []; }
|
||||
// Ring EVERY native device the user has — not just the first. (A user signed in on both an iPhone and an
|
||||
// Android phone must ring on both; the old early-return after the iOS branch meant the Android invite was
|
||||
// never sent, so a swiped-away Android phone never rang while the iPhone did.)
|
||||
let handledNative = false;
|
||||
// iOS CallKit via VoIP push.
|
||||
const voip = toks.filter((t) => t.platform === 'ios-voip');
|
||||
if (voip.length && apnsCfg && process.env.CALLKIT_ENABLED === '1') { // kill-switch: off → fall through to a banner
|
||||
if (voip.length && apnsCfg && process.env.CALLKIT_ENABLED === '1') {
|
||||
const payload = {
|
||||
type: 'invite',
|
||||
callUUID: data.callUUID, room: data.room, kind: data.kind,
|
||||
@@ -171,12 +176,10 @@ async function sendCallNotification(userId, data) {
|
||||
for (const t of voip) {
|
||||
try { const r = await sendApnsVoip(t.token, payload); if (r && r.dead) { try { await R.deviceTokens.removeByToken(t.token); } catch (_) {} } } catch (_) {}
|
||||
}
|
||||
return 'voip';
|
||||
handledNative = true;
|
||||
}
|
||||
// Android native ring: send a high-priority DATA message to the user's 'android' tokens so the native-call
|
||||
// plugin rings even when the app is closed (BzCallMessagingService → full-screen incoming UI). Gated on
|
||||
// ANDROID_CALLS so the app can ship with the plugin dormant and be switched on server-side, like CALLKIT_ENABLED
|
||||
// for iOS. Returns early (no banner) so the same token isn't ALSO buzzed by the fallback push below.
|
||||
// Android native ring: a high-priority DATA message to the user's 'android' tokens so the native-call plugin
|
||||
// rings even when the app is closed (BzCallMessagingService → full-screen incoming UI). Gated on ANDROID_CALLS.
|
||||
const android = toks.filter((t) => t.platform === 'android');
|
||||
if (android.length && fcmSA && process.env.ANDROID_CALLS === '1') {
|
||||
const cd = {
|
||||
@@ -188,8 +191,11 @@ async function sendCallNotification(userId, data) {
|
||||
for (const t of android) {
|
||||
try { const r = await sendFcmData(t.token, cd); if (r && r.dead) { try { await R.deviceTokens.removeByToken(t.token); } catch (_) {} } } catch (_) {}
|
||||
}
|
||||
return 'fcm-call';
|
||||
handledNative = true;
|
||||
}
|
||||
// Native devices got the call-wake above; the banner is only a fallback for web push + non-native devices
|
||||
// (sending it too would double-notify the native devices).
|
||||
if (handledNative) return 'native';
|
||||
await sendToUser(userId, {
|
||||
title: data.title, body: data.body, kind: data.kind, id: data.callerId || data.groupId,
|
||||
room: data.room, tag: 'call:' + data.room, data: { kind: data.kind, id: data.callerId || data.groupId, room: data.room, call: 1 },
|
||||
|
||||
Reference in new issue
Block a user