feat: Add incoming call modal
This commit is contained in:
@@ -45,6 +45,24 @@ export class DirectCallService {
|
||||
readonly sessions = computed(() => this.sessionsSignal());
|
||||
readonly activeSessions = computed(() => this.sessions().filter((session) => session.status !== 'ended'));
|
||||
readonly visibleActiveSessions = computed(() => this.activeSessions().filter((session) => this.hasOngoingActivity(session)));
|
||||
readonly incomingCall = computed<DirectCallSession | null>(() => {
|
||||
if (this.isDoNotDisturb()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const meId = this.currentUserId();
|
||||
|
||||
if (!meId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [...this.activeSessions()]
|
||||
.sort((left, right) => right.createdAt - left.createdAt)
|
||||
.find((session) => session.status === 'ringing'
|
||||
&& this.currentSession()?.callId !== session.callId
|
||||
&& !session.participants[meId]?.joined
|
||||
&& this.hasConnectedParticipant(session)) ?? null;
|
||||
});
|
||||
readonly currentSession = signal<DirectCallSession | null>(null);
|
||||
readonly hasActiveCall = computed(() => this.visibleActiveSessions().length > 0);
|
||||
|
||||
@@ -66,6 +84,14 @@ export class DirectCallService {
|
||||
|
||||
this.voice.syncOutgoingVoiceRouting(peerIds);
|
||||
});
|
||||
|
||||
effect(() => {
|
||||
if (this.incomingCall() && !this.isDoNotDisturb()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.audio.stop(AppSound.Call);
|
||||
});
|
||||
}
|
||||
|
||||
sessionById(callId: string | null | undefined): DirectCallSession | null {
|
||||
@@ -160,6 +186,50 @@ export class DirectCallService {
|
||||
this.currentSession.set(session);
|
||||
}
|
||||
|
||||
async answerIncomingCall(callId: string): Promise<void> {
|
||||
const session = this.sessionById(callId);
|
||||
|
||||
if (!session || session.status === 'ended') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.audio.stop(AppSound.Call);
|
||||
this.currentSession.set(session);
|
||||
await this.joinCall(callId);
|
||||
await this.router.navigate(['/call', callId]);
|
||||
}
|
||||
|
||||
declineIncomingCall(callId: string): void {
|
||||
const session = this.sessionById(callId);
|
||||
|
||||
if (!session || session.status === 'ended') {
|
||||
return;
|
||||
}
|
||||
|
||||
const meId = this.currentUserId();
|
||||
const nextSession = meId
|
||||
? {
|
||||
...this.markParticipantJoined(session, meId, false, 'ended'),
|
||||
status: 'ended' as const
|
||||
}
|
||||
: {
|
||||
...session,
|
||||
status: 'ended' as const
|
||||
};
|
||||
|
||||
this.audio.stop(AppSound.Call);
|
||||
|
||||
if (meId) {
|
||||
this.broadcastCallEvent('leave', session);
|
||||
}
|
||||
|
||||
this.upsertSession(nextSession);
|
||||
|
||||
if (this.currentSession()?.callId === callId) {
|
||||
this.currentSession.set(null);
|
||||
}
|
||||
}
|
||||
|
||||
async joinCall(callId: string, notifyPeers = true): Promise<void> {
|
||||
const session = this.sessionById(callId);
|
||||
const me = this.requireCurrentUser();
|
||||
@@ -315,13 +385,16 @@ export class DirectCallService {
|
||||
if (payload.action === 'ring') {
|
||||
await this.ensureCallConversation(session);
|
||||
|
||||
if (session.status !== 'connected') {
|
||||
if (this.shouldAlertIncomingCall(session)) {
|
||||
this.audio.playLoop(AppSound.Call);
|
||||
} else {
|
||||
this.audio.stop(AppSound.Call);
|
||||
}
|
||||
|
||||
await this.showIncomingNotification(payload.sender.displayName, payload.callId);
|
||||
if (this.shouldAlertIncomingCall(session)) {
|
||||
await this.showIncomingNotification(payload.sender.displayName, payload.callId);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -745,6 +818,14 @@ export class DirectCallService {
|
||||
}));
|
||||
}
|
||||
|
||||
private shouldAlertIncomingCall(session: DirectCallSession): boolean {
|
||||
return session.status !== 'connected' && !this.isDoNotDisturb();
|
||||
}
|
||||
|
||||
private isDoNotDisturb(): boolean {
|
||||
return this.currentUser()?.status === 'busy';
|
||||
}
|
||||
|
||||
private async showIncomingNotification(displayName: string, callId: string): Promise<void> {
|
||||
if (typeof Notification === 'undefined') {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user