feat(video_calls): fixed ios push UI

This commit is contained in:
misha
2026-06-16 18:30:16 +03:00
parent 705538ac85
commit e0d697e8d0
3 changed files with 78 additions and 15 deletions

View File

@@ -60,6 +60,34 @@ import flutter_foreground_task
) )
} }
private func conversationUuid(fromActionUrl actionUrl: String?) -> String? {
guard
let actionUrl = actionUrl,
let components = URLComponents(string: actionUrl)
else {
return nil
}
let queryItems = components.queryItems ?? []
for key in ["uuid", "conversationUuid", "conversation_uuid"] {
if let value = queryItems.first(where: { $0.name == key })?.value,
!value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
{
return value.trimmingCharacters(in: .whitespacesAndNewlines)
}
}
let segments = components.path.split(separator: "/").map(String.init)
for index in segments.indices where segments[index] == "video-call" {
let nextIndex = segments.index(after: index)
if segments.indices.contains(nextIndex), !segments[nextIndex].isEmpty {
return segments[nextIndex]
}
}
return nil
}
func pushRegistry( func pushRegistry(
_ registry: PKPushRegistry, _ registry: PKPushRegistry,
@@ -86,32 +114,42 @@ import flutter_foreground_task
} }
let dict = payload.dictionaryPayload let dict = payload.dictionaryPayload
if let pushType = ( let pushMarkers = [
dict["type"] as? String dict["type"] as? String,
?? dict["notification_type"] as? String dict["notification_type"] as? String,
?? dict["event"] as? String dict["event"] as? String,
?? dict["action"] as? String dict["action"] as? String,
)?.lowercased().replacingOccurrences(of: "-", with: "_"), dict["push_type"] as? String,
pushType.contains("video_call"), dict["call_type"] as? String,
pushType.contains("end") || pushType.contains("cancel") ]
{ .compactMap { $0?.lowercased().replacingOccurrences(of: "-", with: "_") }
if pushMarkers.contains(where: { $0.contains("video_call") })
&& pushMarkers.contains(where: { $0.contains("end") || $0.contains("cancel") }) {
SwiftFlutterCallkitIncomingPlugin.sharedInstance?.endAllCalls() SwiftFlutterCallkitIncomingPlugin.sharedInstance?.endAllCalls()
completion() completion()
return return
} }
let nameCaller = (dict["nameCaller"] as? String) let nameCaller = (dict["nameCaller"] as? String)
?? (dict["counterpartName"] as? String)
?? (dict["counterpart_name"] as? String)
?? (dict["caller_name"] as? String) ?? (dict["caller_name"] as? String)
?? (dict["callerName"] as? String) ?? (dict["callerName"] as? String)
?? (dict["caller"] as? String)
?? "" ?? ""
let conversationUuid = (dict["conversation_uuid"] as? String) let conversationUuid = (dict["conversation_uuid"] as? String)
?? (dict["conversationUuid"] as? String) ?? (dict["conversationUuid"] as? String)
?? (dict["conversation_id"] as? String)
?? (dict["chat_uuid"] as? String)
?? (dict["uuid"] as? String)
?? conversationUuid(fromActionUrl: dict["action_url"] as? String)
?? (dict["handle"] as? String) ?? (dict["handle"] as? String)
?? "" ?? ""
let id = [ let id = [
dict["id"] as? String,
dict["call_id"] as? String,
conversationUuid, conversationUuid,
dict["call_id"] as? String,
dict["id"] as? String,
dict["message_id"] as? String, dict["message_id"] as? String,
] ]
.compactMap { $0?.trimmingCharacters(in: .whitespacesAndNewlines) } .compactMap { $0?.trimmingCharacters(in: .whitespacesAndNewlines) }
@@ -127,6 +165,9 @@ import flutter_foreground_task
} }
if let avatar = dict["caller_avatar"] as? String ?? dict["avatar"] as? String if let avatar = dict["caller_avatar"] as? String ?? dict["avatar"] as? String
?? dict["avatarUrl"] as? String ?? dict["avatarUrl"] as? String
?? dict["avatar_url"] as? String
?? dict["counterpartAvatarUrl"] as? String
?? dict["counterpart_avatar_url"] as? String
{ {
extra["counterpartAvatarUrl"] = avatar extra["counterpartAvatarUrl"] = avatar
} }
@@ -143,6 +184,8 @@ import flutter_foreground_task
} }
if let counterpartName = dict["counterpartName"] as? String { if let counterpartName = dict["counterpartName"] as? String {
extra["counterpartName"] = counterpartName extra["counterpartName"] = counterpartName
} else if let counterpartName = dict["counterpart_name"] as? String {
extra["counterpartName"] = counterpartName
} else if !nameCaller.isEmpty { } else if !nameCaller.isEmpty {
extra["counterpartName"] = nameCaller extra["counterpartName"] = nameCaller
} }
@@ -151,8 +194,15 @@ import flutter_foreground_task
id: id, id: id,
nameCaller: nameCaller, nameCaller: nameCaller,
handle: conversationUuid.isEmpty ? nameCaller : conversationUuid, handle: conversationUuid.isEmpty ? nameCaller : conversationUuid,
type: isVideo ? 1 : 0 type: 0
) )
data.appName = "Итвио"
data.duration = 45000
data.handleType = "generic"
data.supportsVideo = isVideo
data.ringtonePath = "system_ringtone_default"
data.configureAudioSession = false
data.includesCallsInRecents = false
data.extra = extra as NSDictionary data.extra = extra as NSDictionary
SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming( SwiftFlutterCallkitIncomingPlugin.sharedInstance?.showCallkitIncoming(

View File

@@ -112,6 +112,18 @@ class VideoCallCallKitCoordinator {
CallKitParams? _paramsForCallId(String id) => _callKitParamsById[id]; CallKitParams? _paramsForCallId(String id) => _callKitParamsById[id];
Future<CallKitParams?> _paramsForCallIdOrActiveCall(String id) async {
final cached = _paramsForCallId(id);
if (cached != null || !Platform.isIOS) return cached;
final activeCalls = await FlutterCallkitIncoming.activeCalls();
for (final params in activeCalls) {
_cacheCallKitParams(params);
}
return _paramsForCallId(id);
}
Future<void> _openActiveCallKitCallIfNeeded() async { Future<void> _openActiveCallKitCallIfNeeded() async {
if (!Platform.isIOS) return; if (!Platform.isIOS) return;
if (_cubit.state.connectPhase != VideoCallConnectPhase.idle) return; if (_cubit.state.connectPhase != VideoCallConnectPhase.idle) return;
@@ -121,6 +133,7 @@ class VideoCallCallKitCoordinator {
for (final params in activeCalls) { for (final params in activeCalls) {
_cacheCallKitParams(params); _cacheCallKitParams(params);
if (!params.isAccepted) continue;
final extra = params.extra ?? <String, dynamic>{}; final extra = params.extra ?? <String, dynamic>{};
final conversationUuid = _parseConversationUuid( final conversationUuid = _parseConversationUuid(
extra, extra,
@@ -191,12 +204,12 @@ class VideoCallCallKitCoordinator {
if (_acceptHandledCallKitIds.contains(callKitId)) return; if (_acceptHandledCallKitIds.contains(callKitId)) return;
_activeCallKitId = callKitId; _activeCallKitId = callKitId;
final params = _paramsForCallId(callKitId); final params = await _paramsForCallIdOrActiveCall(callKitId);
final extra = params?.extra ?? <String, dynamic>{}; final extra = params?.extra ?? <String, dynamic>{};
final conversationUuid = _parseConversationUuid( final conversationUuid = _parseConversationUuid(
extra, extra,
handle: params?.handle, handle: params?.handle ?? callKitId,
); );
if (conversationUuid.isEmpty) { if (conversationUuid.isEmpty) {
log( log(

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.27+109 version: 1.3.27+110
publish_to: 'none' publish_to: 'none'
environment: environment: