Fix private calls
This commit is contained in:
@@ -17,6 +17,56 @@
|
||||
<ng-container *ngComponentOutlet="dmRailComponent()" />
|
||||
}
|
||||
|
||||
@for (call of directCalls.visibleActiveSessions(); track call.callId + ':' + $index) {
|
||||
<div class="group/call relative flex w-full justify-center">
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="pointer-events-none absolute left-0 top-1/2 w-[3px] -translate-y-1/2 rounded-r-full bg-emerald-500 transition-[height,opacity] duration-100"
|
||||
[ngClass]="isSelectedCall($index) ? 'h-5 opacity-100' : 'h-0 opacity-0 group-hover/call:h-2.5 group-hover/call:opacity-100'"
|
||||
></span>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="relative z-10 grid h-10 w-10 place-items-center overflow-hidden rounded-xl transition-colors hover:rounded-lg"
|
||||
[ngClass]="
|
||||
callAvatarUrls(call).length > 0
|
||||
? 'bg-emerald-950 text-white shadow-sm hover:bg-emerald-900'
|
||||
: 'bg-emerald-500/15 text-emerald-600 hover:bg-emerald-500/25'
|
||||
"
|
||||
[attr.data-testid]="'server-rail-call-' + call.callId"
|
||||
title="Open private call"
|
||||
[attr.aria-current]="isSelectedCall($index) ? 'page' : null"
|
||||
(click)="openCall(call.callId)"
|
||||
>
|
||||
@let callAvatars = callAvatarUrls(call);
|
||||
@if (callAvatars.length > 0) {
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="absolute inset-0 bg-emerald-950"
|
||||
></span>
|
||||
|
||||
@for (avatarUrl of callAvatars; track avatarUrl) {
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="absolute inset-0 bg-cover bg-center opacity-65 mix-blend-screen saturate-125"
|
||||
[style.backgroundImage]="'url(' + avatarUrl + ')'"
|
||||
></span>
|
||||
}
|
||||
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="absolute inset-0 bg-gradient-to-br from-black/10 via-emerald-950/20 to-black/45"
|
||||
></span>
|
||||
}
|
||||
|
||||
<ng-icon
|
||||
name="lucidePhone"
|
||||
class="relative z-10 h-5 w-5 drop-shadow"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Saved servers icons -->
|
||||
<div
|
||||
appThemeNode="serversRailList"
|
||||
|
||||
@@ -14,7 +14,7 @@ import { FormsModule } from '@angular/forms';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { NgIcon, provideIcons } from '@ng-icons/core';
|
||||
import { lucidePlus } from '@ng-icons/lucide';
|
||||
import { lucidePhone, lucidePlus } from '@ng-icons/lucide';
|
||||
import {
|
||||
EMPTY,
|
||||
Subject,
|
||||
@@ -35,6 +35,7 @@ import { selectCurrentUser, selectOnlineUsers } from '../../../store/users/users
|
||||
import { RoomsActions } from '../../../store/rooms/rooms.actions';
|
||||
import { DatabaseService } from '../../../infrastructure/persistence';
|
||||
import { NotificationsFacade } from '../../../domains/notifications';
|
||||
import { DirectCallService, DirectCallSession } from '../../../domains/direct-call';
|
||||
import { type ServerInfo, ServerDirectoryFacade } from '../../../domains/server-directory';
|
||||
import { ThemeNodeDirective } from '../../../domains/theme';
|
||||
import { hasRoomBanForUser } from '../../../domains/access-control';
|
||||
@@ -57,7 +58,7 @@ import {
|
||||
ThemeNodeDirective,
|
||||
UserBarComponent
|
||||
],
|
||||
viewProviders: [provideIcons({ lucidePlus })],
|
||||
viewProviders: [provideIcons({ lucidePhone, lucidePlus })],
|
||||
templateUrl: './servers-rail.component.html'
|
||||
})
|
||||
export class ServersRailComponent {
|
||||
@@ -66,6 +67,7 @@ export class ServersRailComponent {
|
||||
private voiceSession = inject(VoiceSessionFacade);
|
||||
private db = inject(DatabaseService);
|
||||
private notifications = inject(NotificationsFacade);
|
||||
readonly directCalls = inject(DirectCallService);
|
||||
private serverDirectory = inject(ServerDirectoryFacade);
|
||||
private destroyRef = inject(DestroyRef);
|
||||
private banLookupRequestVersion = 0;
|
||||
@@ -92,10 +94,44 @@ export class ServersRailComponent {
|
||||
isOnDirectMessage = toSignal(
|
||||
this.router.events.pipe(
|
||||
filter((navigationEvent): navigationEvent is NavigationEnd => navigationEvent instanceof NavigationEnd),
|
||||
map((navigationEvent) => navigationEvent.urlAfterRedirects.startsWith('/dm/'))
|
||||
map((navigationEvent) => navigationEvent.urlAfterRedirects.startsWith('/dm/') || navigationEvent.urlAfterRedirects.startsWith('/pm/'))
|
||||
),
|
||||
{ initialValue: this.router.url.startsWith('/dm/') }
|
||||
{ initialValue: this.router.url.startsWith('/dm/') || this.router.url.startsWith('/pm/') }
|
||||
);
|
||||
isOnCall = toSignal(
|
||||
this.router.events.pipe(
|
||||
filter((navigationEvent): navigationEvent is NavigationEnd => navigationEvent instanceof NavigationEnd),
|
||||
map((navigationEvent) => navigationEvent.urlAfterRedirects.startsWith('/call/'))
|
||||
),
|
||||
{ initialValue: this.router.url.startsWith('/call/') }
|
||||
);
|
||||
currentCallId = toSignal(
|
||||
this.router.events.pipe(
|
||||
filter((navigationEvent): navigationEvent is NavigationEnd => navigationEvent instanceof NavigationEnd),
|
||||
map((navigationEvent) => this.callIdFromUrl(navigationEvent.urlAfterRedirects))
|
||||
),
|
||||
{ initialValue: this.callIdFromUrl(this.router.url) }
|
||||
);
|
||||
selectedCallIndex = computed(() => {
|
||||
const routeCallId = this.currentCallId();
|
||||
const visibleCalls = this.directCalls.visibleActiveSessions();
|
||||
|
||||
if (routeCallId) {
|
||||
const routeMatchIndex = visibleCalls.findIndex((call) => call.callId === routeCallId || call.conversationId === routeCallId);
|
||||
|
||||
if (routeMatchIndex >= 0) {
|
||||
return routeMatchIndex;
|
||||
}
|
||||
}
|
||||
|
||||
const currentSession = this.directCalls.currentSession();
|
||||
|
||||
if (!currentSession) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return visibleCalls.findIndex((call) => call.callId === currentSession.callId);
|
||||
});
|
||||
bannedServerName = signal('');
|
||||
showBannedDialog = signal(false);
|
||||
showPasswordDialog = signal(false);
|
||||
@@ -203,6 +239,26 @@ export class ServersRailComponent {
|
||||
this.savedRoomJoinRequests.next({ room });
|
||||
}
|
||||
|
||||
openCall(callId: string): void {
|
||||
void this.router.navigate(['/call', callId]);
|
||||
}
|
||||
|
||||
isSelectedCall(callIndex: number): boolean {
|
||||
return this.selectedCallIndex() === callIndex;
|
||||
}
|
||||
|
||||
callAvatarUrls(call: DirectCallSession): string[] {
|
||||
if (call.participantIds.length <= 2) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Object.values(call.participants)
|
||||
.filter((participant) => participant.joined)
|
||||
.map((participant) => this.directCalls.userForParticipant(participant.userId)?.avatarUrl || participant.profile.avatarUrl)
|
||||
.filter((avatarUrl): avatarUrl is string => !!avatarUrl)
|
||||
.slice(0, 3);
|
||||
}
|
||||
|
||||
closeBannedDialog(): void {
|
||||
this.showBannedDialog.set(false);
|
||||
this.bannedServerName.set('');
|
||||
@@ -229,6 +285,13 @@ export class ServersRailComponent {
|
||||
return !!this.bannedRoomLookup()[room.id];
|
||||
}
|
||||
|
||||
private callIdFromUrl(url: string): string | null {
|
||||
const path = url.split(/[?#]/, 1)[0];
|
||||
const match = path.match(/^\/call\/([^/]+)/);
|
||||
|
||||
return match?.[1] ? decodeURIComponent(match[1]) : null;
|
||||
}
|
||||
|
||||
openContextMenu(evt: MouseEvent, room: Room): void {
|
||||
evt.preventDefault();
|
||||
this.contextRoom.set(room);
|
||||
@@ -311,7 +374,7 @@ export class ServersRailComponent {
|
||||
}
|
||||
|
||||
isSelectedRoom(room: Room): boolean {
|
||||
if (this.isOnDirectMessage()) {
|
||||
if (this.isOnDirectMessage() || this.isOnCall()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user