feat(call): implement CallKeep integration and enhance group call support
Integrate `expo-callkit-telecom` to support native system call handling (answering, ending, and muting via system UI). This includes a new `callKeepService` and a `CallKeepBootstrap` component to manage the lifecycle of system call events. Additionally, improves the calling experience by: - Adding support for group calls with participant tracking and UI indicators. - Enhancing LiveKit integration by replacing polling with event-driven video track synchronization. - Updating `WebSocketService` to prevent disconnection when the app enters the background during an active call. - Adding new WebSocket message types for participant join/leave events and group invites. - Refining call UI components (`CallScreen`, `FloatingCallWindow`, `IncomingCallModal`) for better visual feedback and safe area handling. Refactor LiveKit service to use event-driven updates for local and remote tracks, improving performance and reliability.
This commit is contained in:
@@ -28,6 +28,8 @@ import { useAuthStore } from '../src/stores';
|
||||
import { checkForAPKUpdate } from '@/services/platform';
|
||||
import { CallScreen, IncomingCallModal, FloatingCallWindow } from '../src/components/call';
|
||||
import { jpushService } from '@/services/notification/jpushService';
|
||||
import { callKeepService } from '@/services/callkeep';
|
||||
import { callStore } from '@/stores/call';
|
||||
|
||||
registerNotificationPresentationHandler();
|
||||
|
||||
@@ -237,6 +239,37 @@ function APKUpdateBootstrap() {
|
||||
return null;
|
||||
}
|
||||
|
||||
function CallKeepBootstrap() {
|
||||
useEffect(() => {
|
||||
if (Platform.OS === 'web') return;
|
||||
|
||||
callKeepService.initialize({
|
||||
onSystemAnswered: () => {
|
||||
callStore.getState().handleSystemAnswer();
|
||||
},
|
||||
onSystemEnded: () => {
|
||||
callStore.getState().endCall('ended');
|
||||
},
|
||||
onSystemMuted: (muted: boolean) => {
|
||||
callStore.getState().handleSystemMuted(muted);
|
||||
},
|
||||
onIncomingCallFromPush: (session) => {
|
||||
callStore.getState().handleIncomingFromPush(session);
|
||||
},
|
||||
onOutgoingStarted: () => {
|
||||
// Outgoing call accepted by system — no action needed,
|
||||
// the WS call_invited / call_accepted flow handles everything
|
||||
},
|
||||
});
|
||||
|
||||
return () => {
|
||||
callKeepService.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function ThemedStack() {
|
||||
const router = useRouter();
|
||||
const resolved = useResolvedColorScheme();
|
||||
@@ -249,6 +282,7 @@ function ThemedStack() {
|
||||
<SessionGate>
|
||||
<NotificationBootstrap />
|
||||
<APKUpdateBootstrap />
|
||||
<CallKeepBootstrap />
|
||||
<Stack screenOptions={{ headerShown: false }}>
|
||||
<Stack.Screen name="index" options={{ headerShown: false }} />
|
||||
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
|
||||
|
||||
Reference in New Issue
Block a user