Files
Toju/toju-app/src/app/domains/server-directory/feature/create-server-dialog/create-server-dialog.component.ts
Myx 9e1d75d038 style: Consistent backdrop and create server in server-rail
wider server rail with larger icons ans slightly animated.
2026-06-05 02:34:02 +02:00

123 lines
3.5 KiB
TypeScript

/* eslint-disable @typescript-eslint/member-ordering */
import {
Component,
HostListener,
inject,
output,
signal
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { Store } from '@ngrx/store';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideChevronDown, lucideChevronUp } from '@ng-icons/lucide';
import { RoomsActions } from '../../../../store/rooms/rooms.actions';
import { ServerDirectoryFacade } from '../../application/facades/server-directory.facade';
import { ThemeNodeDirective } from '../../../theme';
import { ViewportService } from '../../../../core/platform';
import { BottomSheetComponent, ModalBackdropComponent } from '../../../../shared';
import { CATEGORY_PRESETS, ServerCategoryPreset } from '../create-server/create-server.component';
/**
* Modal presentation of the server-creation form. Mirrors the dedicated
* `/create-server` page but is rendered as a Toju modal (desktop) / bottom sheet
* (mobile) so it can be opened straight from the servers rail. Emits `created`
* once a room creation has been dispatched and `cancelled` when dismissed.
*/
@Component({
selector: 'app-create-server-dialog',
standalone: true,
imports: [
CommonModule,
FormsModule,
NgIcon,
ThemeNodeDirective,
BottomSheetComponent,
ModalBackdropComponent
],
viewProviders: [provideIcons({ lucideChevronDown, lucideChevronUp })],
templateUrl: './create-server-dialog.component.html',
host: {
style: 'display: contents;'
}
})
export class CreateServerDialogComponent {
private store = inject(Store);
private router = inject(Router);
private serverDirectory = inject(ServerDirectoryFacade);
readonly isMobile = inject(ViewportService).isMobile;
readonly created = output<undefined>();
readonly cancelled = output<undefined>();
readonly categories = CATEGORY_PRESETS;
activeEndpoints = this.serverDirectory.activeServers;
name = signal('');
description = signal('');
topic = signal('');
selectedCategoryId = signal<string | null>(null);
isPrivate = signal(false);
password = signal('');
sourceId = signal('');
showAdvanced = signal(false);
constructor() {
this.sourceId.set(this.activeEndpoints()[0]?.id ?? '');
}
/** True when the form has enough to create a server. */
get canCreate(): boolean {
return this.name().trim().length > 0 && this.sourceId().length > 0;
}
selectCategory(category: ServerCategoryPreset): void {
if (this.selectedCategoryId() === category.id) {
this.selectedCategoryId.set(null);
this.topic.set('');
return;
}
this.selectedCategoryId.set(category.id);
this.topic.set(category.topic);
}
toggleAdvanced(): void {
this.showAdvanced.update((shown) => !shown);
}
@HostListener('document:keydown.escape')
cancel(): void {
this.cancelled.emit(undefined);
}
create(): void {
if (!this.canCreate) {
return;
}
const currentUserId = localStorage.getItem('metoyou_currentUserId');
if (!currentUserId) {
this.router.navigate(['/login']);
return;
}
this.store.dispatch(
RoomsActions.createRoom({
name: this.name().trim(),
description: this.description().trim() || undefined,
topic: this.topic().trim() || undefined,
isPrivate: this.isPrivate(),
password: this.password().trim() || undefined,
sourceId: this.sourceId() || undefined
})
);
this.created.emit(undefined);
}
}