Files
Toju/toju-app/src/app/domains/server-directory/feature/create-server-dialog/create-server-dialog.component.ts
Myx 31962aeb1a 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>
2026-06-11 12:16:40 +02:00

132 lines
3.9 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 { APP_TRANSLATE_IMPORTS } from '../../../../core/i18n';
import { buildLoginReturnQueryParams } from '../../../authentication/domain/logic/auth-navigation.rules';
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 { AutoFocusDirective, SelectOnFocusDirective } from '../../../../shared/directives';
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,
AutoFocusDirective,
SelectOnFocusDirective,
...APP_TRANSLATE_IMPORTS
],
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'], {
queryParams: buildLoginReturnQueryParams(this.router.url)
});
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);
}
}