handleIncomingPush method

Future<void> handleIncomingPush(
  1. Map<String, dynamic> data, {
  2. bool alreadyRinging = false,
})

Handle an incoming-call push/data message. Call this from your FCM / VoIP push handler with the payload the backend sent ({sessionId, from, ...}). Shows the native incoming UI and arms answer/decline.

Implementation

Future<void> handleIncomingPush(Map<String, dynamic> data, {bool alreadyRinging = false}) async {
  final sessionId = (data['sessionId'] ?? data['session_id']) as String?;
  if (sessionId == null) return;
  // Idempotent: the same call can arrive over BOTH realtime and FCM (foreground),
  // or be re-delivered — don't reset an already-live call or re-ring.
  final existing = current.value;
  if (existing != null && existing.sessionId == sessionId && !existing.state.isTerminal) return;
  final from = (data['from'] ?? data['callerNumber'] ?? '') as String;
  final name = data['callerName'] as String?;
  final avatar = (data['callerAvatar'] ?? data['avatarUrl']) as String?;
  // The backend's callee placeholder leg — lets a decline BEFORE we answer
  // reach the control plane. Replaced by this device's media leg on answer.
  final ringLegId = (data['legId'] ?? data['leg_id']) as String?;
  _set(NexusCall(
    sessionId: sessionId,
    direction: VoiceCallDirection.inbound,
    state: VoiceCallState.ringing,
    remoteAddress: from,
    remoteName: name,
    remoteAvatar: avatar,
    legId: ringLegId,
    startedAt: DateTime.now(),
  ));
  // On iOS the VoIP push already raised the CallKit ring natively before Dart
  // woke up — reporting the same call again would be rejected as a duplicate.
  if (alreadyRinging) return;
  if (_hasNativeCallUi) {
    // Ring in the SYSTEM call UI via our own native stack (ConnectionService on
    // Android, CallKit on iOS) — answered natively, no app launch required.
    // (avatarUrl is honoured on Android's notification + ring screen; iOS
    // CallKit shows name only — the avatar appears in the in-app call UI.)
    await _guard(() => NexusPlatform.instance.voiceReportIncoming(
          callId: sessionId,
          from: from,
          displayName: name,
          avatarUrl: avatar,
        ));
  } else {
    await _guard(() =>
        _callKit.reportIncoming(callId: sessionId, handle: from, displayName: name, avatarUrl: avatar));
  }
}