110 lines
2.9 KiB
TypeScript
110 lines
2.9 KiB
TypeScript
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;
|
|
}
|
|
}
|