Move toju-app into own its folder
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
import {
|
||||
Component,
|
||||
inject,
|
||||
signal,
|
||||
computed,
|
||||
effect,
|
||||
HostListener,
|
||||
viewChild
|
||||
} from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { NgIcon, provideIcons } from '@ng-icons/core';
|
||||
import {
|
||||
lucideX,
|
||||
lucideBug,
|
||||
lucideDownload,
|
||||
lucideGlobe,
|
||||
lucideAudioLines,
|
||||
lucideSettings,
|
||||
lucideUsers,
|
||||
lucideBan,
|
||||
lucideShield
|
||||
} from '@ng-icons/lucide';
|
||||
|
||||
import { SettingsModalService, SettingsPage } from '../../../core/services/settings-modal.service';
|
||||
import { RealtimeSessionFacade } from '../../../core/realtime';
|
||||
import { selectSavedRooms, selectCurrentRoom } from '../../../store/rooms/rooms.selectors';
|
||||
import { selectCurrentUser } from '../../../store/users/users.selectors';
|
||||
import { Room, UserRole } from '../../../shared-kernel';
|
||||
import { findRoomMember } from '../../../store/rooms/room-members.helpers';
|
||||
|
||||
import { GeneralSettingsComponent } from './general-settings/general-settings.component';
|
||||
import { NetworkSettingsComponent } from './network-settings/network-settings.component';
|
||||
import { VoiceSettingsComponent } from './voice-settings/voice-settings.component';
|
||||
import { ServerSettingsComponent } from './server-settings/server-settings.component';
|
||||
import { MembersSettingsComponent } from './members-settings/members-settings.component';
|
||||
import { BansSettingsComponent } from './bans-settings/bans-settings.component';
|
||||
import { PermissionsSettingsComponent } from './permissions-settings/permissions-settings.component';
|
||||
import { DebuggingSettingsComponent } from './debugging-settings/debugging-settings.component';
|
||||
import { UpdatesSettingsComponent } from './updates-settings/updates-settings.component';
|
||||
import { THIRD_PARTY_LICENSES, type ThirdPartyLicense } from './third-party-licenses';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings-modal',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
NgIcon,
|
||||
GeneralSettingsComponent,
|
||||
NetworkSettingsComponent,
|
||||
VoiceSettingsComponent,
|
||||
UpdatesSettingsComponent,
|
||||
DebuggingSettingsComponent,
|
||||
ServerSettingsComponent,
|
||||
MembersSettingsComponent,
|
||||
BansSettingsComponent,
|
||||
PermissionsSettingsComponent
|
||||
],
|
||||
viewProviders: [
|
||||
provideIcons({
|
||||
lucideX,
|
||||
lucideBug,
|
||||
lucideDownload,
|
||||
lucideGlobe,
|
||||
lucideAudioLines,
|
||||
lucideSettings,
|
||||
lucideUsers,
|
||||
lucideBan,
|
||||
lucideShield
|
||||
})
|
||||
],
|
||||
templateUrl: './settings-modal.component.html'
|
||||
})
|
||||
export class SettingsModalComponent {
|
||||
readonly modal = inject(SettingsModalService);
|
||||
private store = inject(Store);
|
||||
private webrtc = inject(RealtimeSessionFacade);
|
||||
readonly thirdPartyLicenses: readonly ThirdPartyLicense[] = THIRD_PARTY_LICENSES;
|
||||
private lastRequestedServerId: string | null = null;
|
||||
|
||||
private permissionsComponent = viewChild<PermissionsSettingsComponent>('permissionsComp');
|
||||
|
||||
savedRooms = this.store.selectSignal(selectSavedRooms);
|
||||
currentRoom = this.store.selectSignal(selectCurrentRoom);
|
||||
currentUser = this.store.selectSignal(selectCurrentUser);
|
||||
|
||||
isOpen = this.modal.isOpen;
|
||||
activePage = this.modal.activePage;
|
||||
|
||||
readonly globalPages: { id: SettingsPage; label: string; icon: string }[] = [
|
||||
{ id: 'general',
|
||||
label: 'General',
|
||||
icon: 'lucideSettings' },
|
||||
{ id: 'network',
|
||||
label: 'Network',
|
||||
icon: 'lucideGlobe' },
|
||||
{ id: 'voice',
|
||||
label: 'Voice & Audio',
|
||||
icon: 'lucideAudioLines' },
|
||||
{ id: 'updates',
|
||||
label: 'Updates',
|
||||
icon: 'lucideDownload' },
|
||||
{ id: 'debugging',
|
||||
label: 'Debugging',
|
||||
icon: 'lucideBug' }
|
||||
];
|
||||
readonly serverPages: { id: SettingsPage; label: string; icon: string }[] = [
|
||||
{ id: 'server',
|
||||
label: 'Server',
|
||||
icon: 'lucideSettings' },
|
||||
{ id: 'members',
|
||||
label: 'Members',
|
||||
icon: 'lucideUsers' },
|
||||
{ id: 'bans',
|
||||
label: 'Bans',
|
||||
icon: 'lucideBan' },
|
||||
{ id: 'permissions',
|
||||
label: 'Permissions',
|
||||
icon: 'lucideShield' }
|
||||
];
|
||||
|
||||
manageableRooms = computed<Room[]>(() => {
|
||||
const user = this.currentUser();
|
||||
|
||||
if (!user)
|
||||
return [];
|
||||
|
||||
return this.savedRooms().filter((room) => {
|
||||
const role = this.getUserRoleForRoom(room, user.id, user.oderId, this.currentRoom()?.id === room.id ? user.role : null);
|
||||
|
||||
return role === 'host' || role === 'admin' || role === 'moderator';
|
||||
});
|
||||
});
|
||||
|
||||
selectedServerId = signal<string | null>(null);
|
||||
selectedServer = computed<Room | null>(() => {
|
||||
const id = this.selectedServerId();
|
||||
|
||||
if (!id)
|
||||
return null;
|
||||
|
||||
return this.manageableRooms().find((room) => room.id === id) ?? null;
|
||||
});
|
||||
|
||||
showServerTabs = computed(() => {
|
||||
return this.manageableRooms().length > 0 && !!this.selectedServerId();
|
||||
});
|
||||
|
||||
selectedServerRole = computed<UserRole | null>(() => {
|
||||
const server = this.selectedServer();
|
||||
const user = this.currentUser();
|
||||
|
||||
if (!server || !user)
|
||||
return null;
|
||||
|
||||
return this.getUserRoleForRoom(
|
||||
server,
|
||||
user.id,
|
||||
user.oderId,
|
||||
this.currentRoom()?.id === server.id ? user.role : null
|
||||
);
|
||||
});
|
||||
|
||||
canAccessSelectedServer = computed(() => {
|
||||
const role = this.selectedServerRole();
|
||||
|
||||
return role === 'host' || role === 'admin' || role === 'moderator';
|
||||
});
|
||||
|
||||
canManageSelectedMembers = computed(() => {
|
||||
const role = this.selectedServerRole();
|
||||
|
||||
return role === 'host' || role === 'admin' || role === 'moderator';
|
||||
});
|
||||
|
||||
canManageSelectedBans = computed(() => {
|
||||
const role = this.selectedServerRole();
|
||||
|
||||
return role === 'host' || role === 'admin';
|
||||
});
|
||||
|
||||
isSelectedServerOwner = computed(() => {
|
||||
return this.selectedServerRole() === 'host';
|
||||
});
|
||||
|
||||
animating = signal(false);
|
||||
showThirdPartyLicenses = signal(false);
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
if (!this.isOpen()) {
|
||||
this.lastRequestedServerId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
const rooms = this.manageableRooms();
|
||||
const targetId = this.modal.targetServerId();
|
||||
const currentRoomId = this.currentRoom()?.id ?? null;
|
||||
const selectedId = this.selectedServerId();
|
||||
const hasSelected = !!selectedId && rooms.some((room) => room.id === selectedId);
|
||||
|
||||
if (!hasSelected) {
|
||||
const fallbackId = [targetId, currentRoomId].find((candidateId) =>
|
||||
!!candidateId && rooms.some((room) => room.id === candidateId)
|
||||
) ?? rooms[0]?.id ?? null;
|
||||
|
||||
this.selectedServerId.set(fallbackId);
|
||||
}
|
||||
|
||||
this.animating.set(true);
|
||||
});
|
||||
|
||||
effect(() => {
|
||||
const server = this.selectedServer();
|
||||
|
||||
if (server) {
|
||||
const permsComp = this.permissionsComponent();
|
||||
|
||||
if (permsComp) {
|
||||
permsComp.loadPermissions(server);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
effect(() => {
|
||||
if (!this.isOpen())
|
||||
return;
|
||||
|
||||
const serverId = this.selectedServerId();
|
||||
|
||||
if (!serverId || this.lastRequestedServerId === serverId)
|
||||
return;
|
||||
|
||||
this.lastRequestedServerId = serverId;
|
||||
|
||||
for (const peerId of this.webrtc.getConnectedPeers()) {
|
||||
try {
|
||||
this.webrtc.sendToPeer(peerId, {
|
||||
type: 'server-state-request',
|
||||
roomId: serverId
|
||||
});
|
||||
} catch {
|
||||
/* peer may have disconnected */
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getUserRoleForRoom(
|
||||
room: Room,
|
||||
userId: string,
|
||||
userOderId: string,
|
||||
currentRole: UserRole | null
|
||||
): UserRole | null {
|
||||
if (room.hostId === userId || room.hostId === userOderId)
|
||||
return 'host';
|
||||
|
||||
if (currentRole)
|
||||
return currentRole;
|
||||
|
||||
return findRoomMember(room.members ?? [], userId)?.role
|
||||
|| findRoomMember(room.members ?? [], userOderId)?.role
|
||||
|| null;
|
||||
}
|
||||
|
||||
@HostListener('document:keydown.escape')
|
||||
onEscapeKey(): void {
|
||||
if (this.showThirdPartyLicenses()) {
|
||||
this.closeThirdPartyLicenses();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isOpen()) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this.showThirdPartyLicenses.set(false);
|
||||
this.animating.set(false);
|
||||
setTimeout(() => this.modal.close(), 200);
|
||||
}
|
||||
|
||||
openThirdPartyLicenses(): void {
|
||||
this.showThirdPartyLicenses.set(true);
|
||||
}
|
||||
|
||||
closeThirdPartyLicenses(): void {
|
||||
this.showThirdPartyLicenses.set(false);
|
||||
}
|
||||
|
||||
navigate(page: SettingsPage): void {
|
||||
this.modal.navigate(page);
|
||||
}
|
||||
|
||||
onBackdropClick(): void {
|
||||
this.close();
|
||||
}
|
||||
|
||||
onServerSelect(event: Event): void {
|
||||
const select = event.target as HTMLSelectElement;
|
||||
|
||||
this.selectedServerId.set(select.value || null);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user