forked from eatvio/eatvio_app
feat(video_calls): fixed ios and HMS pushes for calls
This commit is contained in:
@@ -14,7 +14,6 @@ import 'package:flutter_callkit_incoming/entities/call_event.dart';
|
||||
import 'package:flutter_callkit_incoming/entities/call_kit_params.dart';
|
||||
import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
|
||||
|
||||
|
||||
class VideoCallCallKitCoordinator {
|
||||
VideoCallCallKitCoordinator({
|
||||
required FirebaseApi firebaseApi,
|
||||
@@ -29,6 +28,7 @@ class VideoCallCallKitCoordinator {
|
||||
final VideoCallSessionCubit? _videoCallSessionCubit;
|
||||
|
||||
StreamSubscription<CallEvent?>? _eventSubscription;
|
||||
AppLifecycleListener? _lifecycleListener;
|
||||
final Map<String, CallKitParams> _callKitParamsById = {};
|
||||
final Set<String> _acceptHandledCallKitIds = {};
|
||||
final Set<String> _suppressedEndCallKitIds = {};
|
||||
@@ -43,13 +43,22 @@ class VideoCallCallKitCoordinator {
|
||||
|
||||
if (Platform.isIOS) {
|
||||
await _firebaseApi.registerPushToken();
|
||||
_lifecycleListener = AppLifecycleListener(
|
||||
onResume: () => unawaited(_openActiveCallKitCallIfNeeded()),
|
||||
);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
unawaited(_openActiveCallKitCallIfNeeded());
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
VideoCallFcmHandler.registerForegroundListener();
|
||||
FlutterCallkitIncoming.acceptCallHandle(_onNativeAcceptCallHandle);
|
||||
await FlutterCallkitIncoming.requestNotificationPermission(<String, dynamic>{
|
||||
await FlutterCallkitIncoming.requestNotificationPermission(<
|
||||
String,
|
||||
dynamic
|
||||
>{
|
||||
'title': 'Уведомления',
|
||||
'rationaleMessagePermission':
|
||||
'Разрешите уведомления, чтобы получать входящие видеозвонки.',
|
||||
@@ -61,13 +70,14 @@ class VideoCallCallKitCoordinator {
|
||||
|
||||
void dispose() {
|
||||
unawaited(_eventSubscription?.cancel());
|
||||
_lifecycleListener?.dispose();
|
||||
_eventSubscription = null;
|
||||
_lifecycleListener = null;
|
||||
_callKitParamsById.clear();
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
VideoCallManager get _manager =>
|
||||
_videoCallManager ?? sl<VideoCallManager>();
|
||||
VideoCallManager get _manager => _videoCallManager ?? sl<VideoCallManager>();
|
||||
|
||||
VideoCallSessionCubit get _cubit =>
|
||||
_videoCallSessionCubit ?? sl<VideoCallSessionCubit>();
|
||||
@@ -102,6 +112,49 @@ class VideoCallCallKitCoordinator {
|
||||
|
||||
CallKitParams? _paramsForCallId(String id) => _callKitParamsById[id];
|
||||
|
||||
Future<void> _openActiveCallKitCallIfNeeded() async {
|
||||
if (!Platform.isIOS) return;
|
||||
if (_cubit.state.connectPhase != VideoCallConnectPhase.idle) return;
|
||||
|
||||
final activeCalls = await FlutterCallkitIncoming.activeCalls();
|
||||
if (activeCalls.isEmpty) return;
|
||||
|
||||
for (final params in activeCalls) {
|
||||
_cacheCallKitParams(params);
|
||||
final extra = params.extra ?? <String, dynamic>{};
|
||||
final conversationUuid = _parseConversationUuid(
|
||||
extra,
|
||||
handle: params.handle,
|
||||
);
|
||||
if (conversationUuid.isEmpty) continue;
|
||||
|
||||
await _deliverIncomingAccept(
|
||||
callKitId: params.id,
|
||||
conversationUuid: conversationUuid,
|
||||
counterpartName:
|
||||
_parseString(extra, const [
|
||||
'counterpartName',
|
||||
'caller_name',
|
||||
'callerName',
|
||||
]) ??
|
||||
params.nameCaller,
|
||||
counterpartAvatarUrl:
|
||||
_parseString(extra, const [
|
||||
'counterpartAvatarUrl',
|
||||
'avatar',
|
||||
'avatarUrl',
|
||||
'caller_avatar',
|
||||
]) ??
|
||||
params.avatar,
|
||||
localParticipantName: _parseString(extra, const [
|
||||
'localParticipantName',
|
||||
'local_participant_name',
|
||||
]),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onNativeAcceptCallHandle(Map<dynamic, dynamic> body) async {
|
||||
final extra = Map<String, dynamic>.from(body);
|
||||
final conversationUuid = _parseConversationUuid(extra);
|
||||
@@ -156,17 +209,21 @@ class VideoCallCallKitCoordinator {
|
||||
await _deliverIncomingAccept(
|
||||
callKitId: callKitId,
|
||||
conversationUuid: conversationUuid,
|
||||
counterpartName: _parseString(extra, const [
|
||||
'counterpartName',
|
||||
'caller_name',
|
||||
'callerName',
|
||||
]) ?? params?.nameCaller,
|
||||
counterpartAvatarUrl: _parseString(extra, const [
|
||||
'counterpartAvatarUrl',
|
||||
'avatar',
|
||||
'avatarUrl',
|
||||
'caller_avatar',
|
||||
]) ?? params?.avatar,
|
||||
counterpartName:
|
||||
_parseString(extra, const [
|
||||
'counterpartName',
|
||||
'caller_name',
|
||||
'callerName',
|
||||
]) ??
|
||||
params?.nameCaller,
|
||||
counterpartAvatarUrl:
|
||||
_parseString(extra, const [
|
||||
'counterpartAvatarUrl',
|
||||
'avatar',
|
||||
'avatarUrl',
|
||||
'caller_avatar',
|
||||
]) ??
|
||||
params?.avatar,
|
||||
localParticipantName: _parseString(extra, const [
|
||||
'localParticipantName',
|
||||
'local_participant_name',
|
||||
@@ -191,12 +248,14 @@ class VideoCallCallKitCoordinator {
|
||||
final binding = WidgetsBinding.instance;
|
||||
final completer = Completer<void>();
|
||||
binding.addPostFrameCallback((_) {
|
||||
unawaited(_openConnectingScreenAfterAccept(
|
||||
conversationUuid: conversationUuid,
|
||||
counterpartName: counterpartName,
|
||||
counterpartAvatarUrl: counterpartAvatarUrl,
|
||||
localParticipantName: localParticipantName,
|
||||
).whenComplete(completer.complete));
|
||||
unawaited(
|
||||
_openConnectingScreenAfterAccept(
|
||||
conversationUuid: conversationUuid,
|
||||
counterpartName: counterpartName,
|
||||
counterpartAvatarUrl: counterpartAvatarUrl,
|
||||
localParticipantName: localParticipantName,
|
||||
).whenComplete(completer.complete),
|
||||
);
|
||||
});
|
||||
await completer.future;
|
||||
} finally {
|
||||
@@ -284,10 +343,7 @@ class VideoCallCallKitCoordinator {
|
||||
return '';
|
||||
}
|
||||
|
||||
static String? _parseString(
|
||||
Map<String, dynamic> map,
|
||||
List<String> keys,
|
||||
) {
|
||||
static String? _parseString(Map<String, dynamic> map, List<String> keys) {
|
||||
for (final key in keys) {
|
||||
final value = map[key];
|
||||
if (value is String && value.trim().isNotEmpty) {
|
||||
|
||||
@@ -47,7 +47,7 @@ class VideoCallNotificationNavigator {
|
||||
String? counterpartAvatarUrl,
|
||||
String? localParticipantName,
|
||||
}) async {
|
||||
for (var attempt = 0; attempt < 40; attempt++) {
|
||||
for (var attempt = 0; attempt < 100; attempt++) {
|
||||
final ctx = AppRouter.navigatorKey.currentContext;
|
||||
if (ctx != null && ctx.mounted) {
|
||||
final router = GoRouter.of(ctx);
|
||||
@@ -68,7 +68,7 @@ class VideoCallNotificationNavigator {
|
||||
}
|
||||
return;
|
||||
}
|
||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||
await Future<void>.delayed(const Duration(milliseconds: 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user