diff --git a/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift b/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift index f0e9687..18b4933 100644 --- a/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift +++ b/mobile/plugins/native-call/ios/Sources/NativeCallPlugin/NativeCallPlugin.swift @@ -59,9 +59,11 @@ public class NativeCallPlugin: CAPPlugin, CAPBridgedPlugin, PKPushRegistryDelega private func connectRoom(url: String, token: String) { guard !url.isEmpty, !token.isEmpty else { return } + let old = room let r = Room() room = r Task { [weak self] in + await old?.disconnect() // drop any previous/stale connection so we never leave DUPLICATE participants do { try await r.connect(url: url, token: token) try await r.localParticipant.setMicrophone(enabled: true) diff --git a/server/public/home.html b/server/public/home.html index 03fa9fb..aab4f8c 100644 --- a/server/public/home.html +++ b/server/public/home.html @@ -4411,10 +4411,16 @@ function sfuAttach(pub, track, participant, _try){ if(!pid){ // uid→peerId map (from the mesh join) may lag the LiveKit track — retry a few times… if((_try||0)<6){ setTimeout(()=>sfuAttach(pub,track,participant,(_try||0)+1), 400); return; } // …then fall back: a NATIVE (CallKit + LiveKit) participant joins LiveKit but NOT our WS mesh, so it has - // no mesh peer id. Key its tile + audio by the LiveKit identity so it still shows and is heard. + // no mesh peer id. Key its tile + audio by the LiveKit identity so it still shows and is heard. The + // outgoing "Ringing…" placeholder is cleared here (its mesh 'answered' signal never fires for native), + // and we label the tile from the contact roster so it shows a NAME + DP, not a raw user id. pid='lk:'+participant.identity; - if(!meetNames.get(pid)) meetNames.set(pid, participant.name||'Caller'); - stopRingback(); + removeWaitingTile(); stopRingback(); + if(!meetNames.get(pid)){ + const c=(typeof CONTACTS!=='undefined'?CONTACTS:[]).find(x=>x&&x.id===participant.identity); + meetNames.set(pid, (c&&c.name) || (_dmCallWaiting&&_dmCallWaiting.name) || participant.name || 'Caller'); + if(c&&c.avatar) meetAvatars.set(pid, c.avatar); + } } const p=SFU.peers.get(pid)||{}; SFU.peers.set(pid,p); const mt=track.mediaStreamTrack; if(track.kind==='audio') p.audio=mt;