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 { } else if !nameCaller.isEmpty {
extra["counterpartName"] = nameCaller 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( let data = flutter_callkit_incoming.Data(
id: id, id: id,

View File

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

View File

@@ -71,6 +71,17 @@ bool callKitExtraMarksEndedPush(Map<String, dynamic>? extra) {
return false; 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({ bool shouldForceEndCallAfterRoomDisconnect({
required bool callStageEntered, required bool callStageEntered,
required bool sessionConnected, required bool sessionConnected,

View File

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

View File

@@ -158,6 +158,27 @@ void main() {
isTrue, isTrue,
); );
expect(callKitExtraMarksEndedPush(<String, dynamic>{}), isFalse); 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,
);
}, },
); );