fix: restore build and stabilize E2E cross-signal behavior

Revert the automated member-ordering pass that broke Angular field init
(TS2729) and disable that rule until a safe reorder strategy exists.
Fix modal/confirm dialog i18n defaults via template fallbacks, search all
active endpoints (including offline), register foreign rooms with actor
owner IDs, sync profile display names from avatar summaries, and guard
dm-chat when a private call converts to a group conversation.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-11 12:16:40 +02:00
parent 79c6f91cd6
commit 31962aeb1a
131 changed files with 2483 additions and 3896 deletions

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/member-ordering */
import {
CUSTOM_ELEMENTS_SCHEMA,
Component,
@@ -81,29 +82,34 @@ import { PrivateCallParticipantCardComponent } from './private-call-participant-
templateUrl: './private-call.component.html'
})
export class PrivateCallComponent {
private readonly route = inject(ActivatedRoute);
private readonly router = inject(Router);
private readonly destroyRef = inject(DestroyRef);
private readonly store = inject(Store);
private readonly calls = inject(DirectCallService);
private readonly realtime = inject(RealtimeSessionFacade);
private readonly voice = inject(VoiceConnectionFacade);
private readonly voiceActivity = inject(VoiceActivityService);
private readonly playback = inject(VoicePlaybackService);
private readonly screenShare = inject(ScreenShareFacade);
private readonly viewport = inject(ViewportService);
private readonly mobilePlatform = inject(MobilePlatformService);
private readonly mobileMedia = inject(MobileMediaService);
private chatResizing = false;
private readonly i18n = inject(AppI18nService);
readonly allUsers = this.store.selectSignal(selectAllUsers);
readonly currentUser = this.store.selectSignal(selectCurrentUser);
readonly isMobile = this.viewport.isMobile;
readonly showSpeakerphoneButton = computed(() => this.mobilePlatform.isNativeMobile());
readonly speakerphoneEnabled = signal(true);
readonly callIdInput = input<string | null>(null);
readonly overlayMode = input(false);
readonly routeCallId = toSignal(this.route.paramMap.pipe(map((params) => params.get('callId'))), {
initialValue: this.route.snapshot.paramMap.get('callId')
});
readonly callId = computed(() => this.callIdInput() ?? this.routeCallId());
readonly session = computed(() => this.calls.sessionById(this.callId()));
readonly participantUsers = computed(() => {
const session = this.session();
@@ -115,40 +121,25 @@ export class PrivateCallComponent {
.map((participantId) => this.userForSessionParticipant(session, participantId))
.filter((user): user is User => !!user);
});
readonly isConnected = computed(() => {
const session = this.session();
const currentUserId = this.currentUserKey();
return !!session && !!currentUserId && !!session.participants[currentUserId]?.joined;
});
readonly isMuted = this.voice.isMuted;
readonly isDeafened = this.voice.isDeafened;
readonly isCameraEnabled = this.voice.isCameraEnabled;
readonly isScreenSharing = this.screenShare.isScreenSharing;
readonly remoteStreamRevision = signal(0);
readonly includeSystemAudio = signal(false);
readonly screenShareQuality = signal<ScreenShareQuality>('balanced');
readonly askScreenShareQuality = signal(true);
readonly showScreenShareQualityDialog = signal(false);
readonly inviteUserId = signal('');
readonly focusedStreamId = signal<string | null>(null);
readonly showAllStreamsMode = signal(false);
readonly chatWidthPx = signal(384);
readonly inviteCandidates = computed(() => {
const participantIds = new Set(this.session()?.participantIds ?? []);
const currentUserId = this.currentUserKey();
@@ -159,7 +150,6 @@ export class PrivateCallComponent {
return userId !== currentUserId && !participantIds.has(userId);
});
});
readonly activeShares = computed<VoiceWorkspaceStreamItem[]>(() => {
this.remoteStreamRevision();
@@ -203,11 +193,8 @@ export class PrivateCallComponent {
return shares;
});
readonly featuredShare = computed(() => this.activeShares()[0] ?? null);
readonly hasMultipleShares = computed(() => this.activeShares().length > 1);
readonly focusedShareId = computed(() => {
const requested = this.focusedStreamId();
const activeShares = this.activeShares();
@@ -226,9 +213,7 @@ export class PrivateCallComponent {
return null;
});
readonly focusedShare = computed(() => this.activeShares().find((share) => share.id === this.focusedShareId()) ?? null);
readonly thumbnailShares = computed(() => {
const focusedShareId = this.focusedShareId();
@@ -238,37 +223,6 @@ export class PrivateCallComponent {
return this.activeShares().filter((share) => share.id !== focusedShareId);
});
private readonly route = inject(ActivatedRoute);
private readonly router = inject(Router);
private readonly destroyRef = inject(DestroyRef);
private readonly store = inject(Store);
private readonly calls = inject(DirectCallService);
private readonly realtime = inject(RealtimeSessionFacade);
private readonly voice = inject(VoiceConnectionFacade);
private readonly voiceActivity = inject(VoiceActivityService);
private readonly playback = inject(VoicePlaybackService);
private readonly screenShare = inject(ScreenShareFacade);
private readonly viewport = inject(ViewportService);
private readonly mobilePlatform = inject(MobilePlatformService);
private readonly mobileMedia = inject(MobileMediaService);
private chatResizing = false;
private readonly i18n = inject(AppI18nService);
constructor() {
effect(() => {
const callId = this.callId();
@@ -346,8 +300,6 @@ export class PrivateCallComponent {
this.chatResizing = false;
}
readonly trackUserKey = (index: number, user: User): string => this.userKey(user);
async join(): Promise<void> {
const session = this.session();
@@ -556,6 +508,8 @@ export class PrivateCallComponent {
return user.oderId || user.id;
}
readonly trackUserKey = (index: number, user: User): string => this.userKey(user);
private currentUserKey(): string {
const user = this.currentUser();
@@ -705,5 +659,4 @@ export class PrivateCallComponent {
private bumpRemoteStreamRevision(): void {
this.remoteStreamRevision.update((value) => value + 1);
}
}