feat: Add incoming call modal
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import {
|
||||
Component,
|
||||
HostListener,
|
||||
computed,
|
||||
inject,
|
||||
signal
|
||||
} from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { NgIcon, provideIcons } from '@ng-icons/core';
|
||||
import { lucidePhone, lucidePhoneOff } from '@ng-icons/lucide';
|
||||
import { UserAvatarComponent } from '../../../../shared';
|
||||
import { selectCurrentUser } from '../../../../store/users/users.selectors';
|
||||
import { User } from '../../../../shared-kernel';
|
||||
import { DirectCallService } from '../../application/services/direct-call.service';
|
||||
import { DirectCallSession, participantToUser } from '../../domain/models/direct-call.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-incoming-call-modal',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
NgIcon,
|
||||
UserAvatarComponent
|
||||
],
|
||||
viewProviders: [
|
||||
provideIcons({
|
||||
lucidePhone,
|
||||
lucidePhoneOff
|
||||
})
|
||||
],
|
||||
templateUrl: './incoming-call-modal.component.html'
|
||||
})
|
||||
export class IncomingCallModalComponent {
|
||||
readonly calls = inject(DirectCallService);
|
||||
readonly currentUser = inject(Store).selectSignal(selectCurrentUser);
|
||||
readonly session = this.calls.incomingCall;
|
||||
readonly answering = signal(false);
|
||||
readonly caller = computed(() => {
|
||||
const session = this.session();
|
||||
|
||||
if (!session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const callerId = this.callerIdFor(session);
|
||||
const participant = callerId ? session.participants[callerId]?.profile : null;
|
||||
|
||||
return (callerId ? this.calls.userForParticipant(callerId) : null)
|
||||
?? (participant ? participantToUser(participant) : null);
|
||||
});
|
||||
readonly callerName = computed(() => this.caller()?.displayName || 'Someone');
|
||||
readonly callKindLabel = computed(() => {
|
||||
const participantCount = this.session()?.participantIds.length ?? 0;
|
||||
|
||||
return participantCount > 2 ? `${participantCount} person call` : 'Direct call';
|
||||
});
|
||||
|
||||
@HostListener('document:keydown.escape')
|
||||
onEscape(): void {
|
||||
this.decline();
|
||||
}
|
||||
|
||||
async answer(): Promise<void> {
|
||||
const session = this.session();
|
||||
|
||||
if (!session || this.answering()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.answering.set(true);
|
||||
|
||||
try {
|
||||
await this.calls.answerIncomingCall(session.callId);
|
||||
} finally {
|
||||
this.answering.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
decline(): void {
|
||||
const session = this.session();
|
||||
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.calls.declineIncomingCall(session.callId);
|
||||
}
|
||||
|
||||
private callerIdFor(session: DirectCallSession): string | null {
|
||||
const currentUserId = this.currentUserKey();
|
||||
|
||||
if (session.initiatorId && session.initiatorId !== currentUserId) {
|
||||
return session.initiatorId;
|
||||
}
|
||||
|
||||
return session.participantIds.find((participantId) => participantId !== currentUserId) ?? null;
|
||||
}
|
||||
|
||||
private currentUserKey(): string | null {
|
||||
const user = this.currentUser();
|
||||
|
||||
return user ? this.userKey(user) : null;
|
||||
}
|
||||
|
||||
private userKey(user: User): string {
|
||||
return user.oderId || user.id;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user