feat: Add pm

This commit is contained in:
2026-04-27 00:45:16 +02:00
parent bc2fa7de22
commit 11c2588e45
65 changed files with 3653 additions and 214 deletions

View File

@@ -23,7 +23,8 @@ import {
lucideLock,
lucideGlobe,
lucidePlus,
lucideSettings
lucideSettings,
lucideChevronDown
} from '@ng-icons/lucide';
import { RoomsActions } from '../../../../store/rooms/rooms.actions';
@@ -39,8 +40,13 @@ import { DatabaseService } from '../../../../infrastructure/persistence';
import { type ServerInfo } from '../../domain/models/server-directory.model';
import { ServerDirectoryFacade } from '../../application/facades/server-directory.facade';
import { selectCurrentUser } from '../../../../store/users/users.selectors';
import { ConfirmDialogComponent } from '../../../../shared';
import {
ConfirmDialogComponent,
LeaveServerDialogComponent,
type LeaveServerDialogResult
} from '../../../../shared';
import { hasRoomBanForUser } from '../../../access-control';
import { UserSearchListComponent } from '../../../direct-message/feature/user-search-list/user-search-list.component';
@Component({
selector: 'app-server-search',
@@ -49,7 +55,9 @@ import { hasRoomBanForUser } from '../../../access-control';
CommonModule,
FormsModule,
NgIcon,
ConfirmDialogComponent
ConfirmDialogComponent,
LeaveServerDialogComponent,
UserSearchListComponent
],
viewProviders: [
provideIcons({
@@ -58,7 +66,8 @@ import { hasRoomBanForUser } from '../../../access-control';
lucideLock,
lucideGlobe,
lucidePlus,
lucideSettings
lucideSettings,
lucideChevronDown
})
],
templateUrl: './server-search.component.html'
@@ -91,6 +100,8 @@ export class ServerSearchComponent implements OnInit {
joinPassword = signal('');
joinPasswordError = signal<string | null>(null);
joinErrorMessage = signal<string | null>(null);
joinedServerMenuId = signal<string | null>(null);
leaveDialogRoom = signal<Room | null>(null);
// Create dialog state
showCreateDialog = signal(false);
@@ -117,7 +128,7 @@ export class ServerSearchComponent implements OnInit {
this.store.dispatch(RoomsActions.loadRooms());
// Setup debounced search
this.searchSubject.pipe(debounceTime(300), distinctUntilChanged()).subscribe((query) => {
this.searchSubject.pipe(debounceTime(120), distinctUntilChanged()).subscribe((query) => {
this.store.dispatch(RoomsActions.searchServers({ query }));
});
}
@@ -190,7 +201,66 @@ export class ServerSearchComponent implements OnInit {
/** Join a previously saved room by converting it to a ServerInfo payload. */
joinSavedRoom(room: Room): void {
void this.joinServer(this.toServerInfo(room));
this.openJoinedRoom(room);
}
openServerCard(server: ServerInfo): void {
const joinedRoom = this.joinedRoomForServer(server);
if (joinedRoom) {
this.openJoinedRoom(joinedRoom);
return;
}
void this.joinServer(server);
}
joinedRoomForServer(server: ServerInfo): Room | null {
return this.savedRooms().find((room) => room.id === server.id) ?? null;
}
isJoinedServer(server: ServerInfo): boolean {
return !!this.joinedRoomForServer(server);
}
toggleJoinedServerMenu(event: Event, server: ServerInfo): void {
event.stopPropagation();
this.joinedServerMenuId.update((currentId) => currentId === server.id ? null : server.id);
}
closeJoinedServerMenu(): void {
this.joinedServerMenuId.set(null);
}
openLeaveDialog(event: Event, server: ServerInfo): void {
event.stopPropagation();
const room = this.joinedRoomForServer(server);
if (!room) {
return;
}
this.joinedServerMenuId.set(null);
this.leaveDialogRoom.set(room);
}
closeLeaveDialog(): void {
this.leaveDialogRoom.set(null);
}
confirmLeaveServer(result: LeaveServerDialogResult): void {
const room = this.leaveDialogRoom();
if (!room) {
return;
}
this.store.dispatch(RoomsActions.forgetRoom({
roomId: room.id,
nextOwnerKey: result.nextOwnerKey
}));
this.leaveDialogRoom.set(null);
}
closeBannedDialog(): void {
@@ -231,6 +301,21 @@ export class ServerSearchComponent implements OnInit {
return server.maxUsers > 0 ? String(server.maxUsers) : '∞';
}
getServerOwnerLabel(server: ServerInfo): string {
const joinedRoom = this.joinedRoomForServer(server);
const ownerKey = server.ownerId || joinedRoom?.hostId || '';
const ownerMember = joinedRoom?.members?.find((member) =>
member.id === ownerKey || member.oderId === ownerKey
);
return server.ownerName || ownerMember?.displayName || server.ownerId || joinedRoom?.hostId || 'Unknown owner';
}
private openJoinedRoom(room: Room): void {
this.joinedServerMenuId.set(null);
this.store.dispatch(RoomsActions.viewServer({ room }));
}
private toServerInfo(room: Room): ServerInfo {
return {
id: room.id,