Fix private calls
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
<section
|
||||
class="grid h-full min-h-0 bg-background lg:grid-cols-[minmax(0,1fr)_var(--private-call-chat-width)]"
|
||||
[style.--private-call-chat-width]="chatWidthPx() + 'px'"
|
||||
>
|
||||
<main class="flex min-h-0 min-w-0 flex-col overflow-hidden bg-[radial-gradient(circle_at_top,rgba(16,185,129,0.10),transparent_34rem)]">
|
||||
<header class="flex min-h-16 shrink-0 items-center justify-between gap-3 border-b border-border/70 bg-background/80 px-5 backdrop-blur">
|
||||
<div class="flex min-w-0 items-center gap-3">
|
||||
<div class="grid h-10 w-10 shrink-0 place-items-center rounded-2xl bg-emerald-500/10 text-emerald-500">
|
||||
<ng-icon
|
||||
name="lucidePhone"
|
||||
class="h-5 w-5"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="min-w-0">
|
||||
<h1 class="truncate text-base font-semibold text-foreground">Private Call</h1>
|
||||
<p class="truncate text-xs text-muted-foreground">
|
||||
@if (session()) {
|
||||
{{ participantUsers().length }} participants
|
||||
} @else {
|
||||
Call not found
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (session()) {
|
||||
<div class="flex items-center gap-2">
|
||||
<select
|
||||
class="h-9 max-w-44 rounded-md border border-border bg-secondary px-2 text-sm text-foreground"
|
||||
[ngModel]="inviteUserId()"
|
||||
(ngModelChange)="inviteUserId.set($event)"
|
||||
aria-label="Add user to call"
|
||||
>
|
||||
<option value="">Add user</option>
|
||||
@for (user of inviteCandidates(); track userKey(user)) {
|
||||
<option [value]="userKey(user)">{{ user.displayName }}</option>
|
||||
}
|
||||
</select>
|
||||
<button
|
||||
type="button"
|
||||
class="grid h-9 w-9 place-items-center rounded-md bg-secondary text-foreground transition-colors hover:bg-secondary/80 disabled:opacity-50"
|
||||
[disabled]="!inviteUserId()"
|
||||
(click)="inviteSelectedUser()"
|
||||
aria-label="Add user"
|
||||
title="Add user"
|
||||
>
|
||||
<ng-icon
|
||||
name="lucideUserPlus"
|
||||
class="h-4 w-4"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</header>
|
||||
|
||||
@if (session()) {
|
||||
<div class="flex min-h-0 flex-1 flex-col overflow-hidden px-4 py-4 sm:px-5">
|
||||
<div class="relative min-h-0 flex-1 overflow-hidden rounded-2xl border border-border/80 bg-card/45 shadow-sm">
|
||||
@if (activeShares().length > 0) {
|
||||
@if (focusedShare()) {
|
||||
@if (hasMultipleShares()) {
|
||||
<div class="absolute right-3 top-3 z-10 sm:right-4 sm:top-4">
|
||||
<button
|
||||
type="button"
|
||||
data-testid="private-call-show-all-streams"
|
||||
class="inline-flex h-10 items-center gap-2 rounded-full border border-white/10 bg-black/45 px-3 text-xs font-medium text-white/80 backdrop-blur transition hover:bg-black/65 hover:text-white"
|
||||
title="Show all streams"
|
||||
(click)="showAllStreams()"
|
||||
>
|
||||
<ng-icon
|
||||
name="lucideUsers"
|
||||
class="h-3.5 w-3.5"
|
||||
/>
|
||||
All streams
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<app-voice-workspace-stream-tile
|
||||
[item]="focusedShare()!"
|
||||
[featured]="true"
|
||||
[focused]="true"
|
||||
data-testid="private-call-focused-stream"
|
||||
[immersive]="true"
|
||||
(focusRequested)="focusShare($event)"
|
||||
/>
|
||||
} @else if (hasMultipleShares()) {
|
||||
<div
|
||||
class="grid h-full min-h-0 auto-rows-[minmax(12rem,1fr)] grid-cols-1 gap-3 p-3 sm:grid-cols-2 sm:gap-4 sm:p-4"
|
||||
[ngClass]="{ '2xl:grid-cols-3': activeShares().length > 2 }"
|
||||
data-testid="private-call-stream-grid"
|
||||
>
|
||||
@for (share of activeShares(); track share.id) {
|
||||
<div class="min-h-0 overflow-hidden rounded-2xl bg-black">
|
||||
<app-voice-workspace-stream-tile
|
||||
[item]="share"
|
||||
[focused]="false"
|
||||
(focusRequested)="focusShare($event)"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
} @else {
|
||||
<div class="flex h-full min-h-0 items-center justify-center p-4 sm:p-6">
|
||||
<div
|
||||
class="grid w-full max-w-5xl grid-cols-[repeat(auto-fit,minmax(min(10rem,100%),1fr))] items-stretch justify-center gap-3 sm:grid-cols-[repeat(auto-fit,minmax(min(13rem,100%),1fr))] sm:gap-5 lg:gap-7"
|
||||
>
|
||||
<app-private-call-participant-card
|
||||
*ngFor="let user of participantUsers(); trackBy: trackUserKey"
|
||||
[user]="user"
|
||||
[connected]="isParticipantConnected(user)"
|
||||
[speaking]="isSpeaking(user)"
|
||||
[issueLabel]="participantIssueLabel(user)"
|
||||
></app-private-call-participant-card>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (activeShares().length > 0) {
|
||||
<div class="shrink-0 pt-4">
|
||||
<div class="flex w-full items-stretch gap-3 overflow-x-auto pb-1">
|
||||
<app-private-call-participant-card
|
||||
*ngFor="let user of participantUsers(); trackBy: trackUserKey"
|
||||
[user]="user"
|
||||
[connected]="isParticipantConnected(user)"
|
||||
[speaking]="isSpeaking(user)"
|
||||
[issueLabel]="participantIssueLabel(user)"
|
||||
[compact]="true"
|
||||
></app-private-call-participant-card>
|
||||
|
||||
@if (hasMultipleShares()) {
|
||||
@for (share of focusedShare() ? thumbnailShares() : activeShares(); track share.id) {
|
||||
<article
|
||||
class="flex min-h-[8.75rem] w-[11rem] shrink-0 flex-col overflow-hidden rounded-2xl border border-border/80 bg-black shadow-sm sm:w-[12.5rem]"
|
||||
>
|
||||
<div class="min-h-0 flex-1">
|
||||
<app-voice-workspace-stream-tile
|
||||
[item]="share"
|
||||
[mini]="true"
|
||||
[focused]="false"
|
||||
(focusRequested)="focusShare($event)"
|
||||
/>
|
||||
</div>
|
||||
<div class="shrink-0 bg-black/80 px-3 py-2 text-xs font-semibold text-white/75">
|
||||
{{ streamLabel(share) }}
|
||||
</div>
|
||||
</article>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="shrink-0 pt-3">
|
||||
<app-private-call-controls
|
||||
class="mx-auto block w-full max-w-5xl"
|
||||
[connected]="isConnected()"
|
||||
[muted]="isMuted()"
|
||||
[cameraEnabled]="isCameraEnabled()"
|
||||
[screenSharing]="isScreenSharing()"
|
||||
(joinRequested)="join()"
|
||||
(muteToggled)="toggleMute()"
|
||||
(cameraToggled)="toggleCamera()"
|
||||
(screenShareToggled)="toggleScreenShare()"
|
||||
(leaveRequested)="leave()"
|
||||
></app-private-call-controls>
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="flex flex-1 items-center justify-center px-6 text-sm text-muted-foreground">No active call for this route.</div>
|
||||
}
|
||||
</main>
|
||||
|
||||
<aside class="relative hidden min-h-0 border-l border-border bg-card lg:block">
|
||||
<div
|
||||
class="group absolute inset-y-0 left-0 z-10 w-3 -translate-x-1/2 cursor-col-resize bg-transparent"
|
||||
role="separator"
|
||||
aria-orientation="vertical"
|
||||
title="Resize chat"
|
||||
data-testid="private-call-chat-resizer"
|
||||
(mousedown)="startChatResize($event)"
|
||||
>
|
||||
<div class="mx-auto h-full w-px bg-border transition group-hover:bg-primary"></div>
|
||||
</div>
|
||||
<app-dm-chat
|
||||
[conversationId]="session()?.conversationId ?? null"
|
||||
[showCallButton]="false"
|
||||
/>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
@if (showScreenShareQualityDialog()) {
|
||||
<app-screen-share-quality-dialog
|
||||
[selectedQuality]="screenShareQuality()"
|
||||
[includeSystemAudio]="includeSystemAudio()"
|
||||
(cancelled)="onScreenShareQualityCancelled()"
|
||||
(confirmed)="onScreenShareQualityConfirmed($event)"
|
||||
/>
|
||||
}
|
||||
Reference in New Issue
Block a user