feat(video_calls): ios repeated call fix

This commit is contained in:
misha
2026-10-16 15:41:13 +03:00
parent 86e9d0cc31
commit 5a8f8aee3e
5 changed files with 49 additions and 5 deletions

View File

@@ -686,6 +686,12 @@ import flutter_foreground_task
} else if !nameCaller.isEmpty {
extra["counterpartName"] = nameCaller
}
// Closing this report looks like a user decline. Dart must not tell the
// backend, or the server sends another ended VoIP and the other phone
// shows it as a new incoming call.
if isEndedPush {
extra["endedPush"] = true
}
let data = flutter_callkit_incoming.Data(
id: id,

View File

@@ -363,7 +363,7 @@ class VideoCallCallKitCoordinator {
);
return;
}
await _handleDecline(id);
await _handleDecline(id, eventExtra: _callKitEventParams(event)?.extra);
}
Future<void> _handleEndedEvent(CallEvent event) async {
@@ -855,7 +855,10 @@ class VideoCallCallKitCoordinator {
);
}
Future<void> _handleDecline(String callKitId) async {
Future<void> _handleDecline(
String callKitId, {
Map<String, dynamic>? eventExtra,
}) async {
if (_suppressedEndCallKitIds.contains(callKitId)) {
log(
'VideoCallCallKitCoordinator: ignore spurious end/decline during accept, callKitId=$callKitId',
@@ -865,12 +868,15 @@ class VideoCallCallKitCoordinator {
}
final params = _paramsForCallId(callKitId);
final extra = params?.extra ?? <String, dynamic>{};
final extra = params?.extra ?? eventExtra ?? <String, dynamic>{};
final conversationUuid = _parseConversationUuid(
extra,
handle: params?.handle ?? callKitId,
);
final endedPushDismissal = callKitExtraMarksEndedPush(extra);
final endedPushDismissal = callKitDeclineIsEndedPush(
cachedExtra: params?.extra,
eventExtra: eventExtra,
);
_suppressedEndCallKitIds.add(callKitId);
try {

View File

@@ -71,6 +71,17 @@ bool callKitExtraMarksEndedPush(Map<String, dynamic>? extra) {
return false;
}
/// Either the cached incoming payload or the decline event itself can carry
/// the marker. The decline often arrives with the push payload, while the
/// cache still holds the original ringing call.
bool callKitDeclineIsEndedPush({
Map<String, dynamic>? cachedExtra,
Map<String, dynamic>? eventExtra,
}) {
return callKitExtraMarksEndedPush(cachedExtra) ||
callKitExtraMarksEndedPush(eventExtra);
}
bool shouldForceEndCallAfterRoomDisconnect({
required bool callStageEntered,
required bool sessionConnected,

View File

@@ -1,6 +1,6 @@
name: eatvio_app
description: A new Flutter project.
version: 1.3.54+143
version: 1.3.55+144
publish_to: 'none'
environment:

View File

@@ -158,6 +158,27 @@ void main() {
isTrue,
);
expect(callKitExtraMarksEndedPush(<String, dynamic>{}), isFalse);
expect(
callKitDeclineIsEndedPush(
cachedExtra: <String, dynamic>{},
eventExtra: <String, dynamic>{'endedPush': true},
),
isTrue,
);
expect(
callKitDeclineIsEndedPush(
cachedExtra: <String, dynamic>{'endedPush': true},
eventExtra: <String, dynamic>{},
),
isTrue,
);
expect(
callKitDeclineIsEndedPush(
cachedExtra: <String, dynamic>{},
eventExtra: <String, dynamic>{},
),
isFalse,
);
},
);