/* eslint-disable @typescript-eslint/member-ordering */ import { Component, inject, signal, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { Router } from '@angular/router'; import { NgIcon, provideIcons } from '@ng-icons/core'; import { lucideServer, lucidePlus, lucideTrash2, lucideCheck, lucideX, lucideSettings, lucideRefreshCw, lucideGlobe, lucideArrowLeft, lucideAudioLines } from '@ng-icons/lucide'; import { ServerDirectoryService } from '../../core/services/server-directory.service'; import { WebRTCService } from '../../core/services/webrtc.service'; import { NotificationAudioService, AppSound } from '../../core/services/notification-audio.service'; import { STORAGE_KEY_CONNECTION_SETTINGS, STORAGE_KEY_VOICE_SETTINGS } from '../../core/constants'; @Component({ selector: 'app-settings', standalone: true, imports: [ CommonModule, FormsModule, NgIcon ], viewProviders: [ provideIcons({ lucideServer, lucidePlus, lucideTrash2, lucideCheck, lucideX, lucideSettings, lucideRefreshCw, lucideGlobe, lucideArrowLeft, lucideAudioLines }) ], templateUrl: './settings.component.html' }) /** * Settings page for managing signaling servers and connection preferences. */ export class SettingsComponent implements OnInit { private serverDirectory = inject(ServerDirectoryService); private webrtcService = inject(WebRTCService); private router = inject(Router); audioService = inject(NotificationAudioService); servers = this.serverDirectory.servers; isTesting = signal(false); addError = signal(null); newServerName = ''; newServerUrl = ''; autoReconnect = true; searchAllServers = true; noiseReduction = true; /** Load persisted connection settings on component init. */ ngOnInit(): void { this.loadConnectionSettings(); this.loadVoiceSettings(); } /** Add a new signaling server after URL validation and duplicate checking. */ addServer(): void { this.addError.set(null); // Validate URL try { new URL(this.newServerUrl); } catch { this.addError.set('Please enter a valid URL'); return; } // Check for duplicates if (this.servers().some((server) => server.url === this.newServerUrl)) { this.addError.set('This server URL already exists'); return; } this.serverDirectory.addServer({ name: this.newServerName.trim(), url: this.newServerUrl.trim().replace(/\/$/, '') // Remove trailing slash }); // Clear form this.newServerName = ''; this.newServerUrl = ''; // Test the new server const servers = this.servers(); const newServer = servers[servers.length - 1]; if (newServer) { this.serverDirectory.testServer(newServer.id); } } /** Remove a signaling server by its ID. */ removeServer(id: string): void { this.serverDirectory.removeServer(id); } /** Set the active signaling server used for connections. */ setActiveServer(id: string): void { this.serverDirectory.setActiveServer(id); } /** Test connectivity to all configured servers. */ async testAllServers(): Promise { this.isTesting.set(true); await this.serverDirectory.testAllServers(); this.isTesting.set(false); } /** Load connection settings (auto-reconnect, search scope) from localStorage. */ loadConnectionSettings(): void { const settings = localStorage.getItem(STORAGE_KEY_CONNECTION_SETTINGS); if (settings) { const parsed = JSON.parse(settings); this.autoReconnect = parsed.autoReconnect ?? true; this.searchAllServers = parsed.searchAllServers ?? true; this.serverDirectory.setSearchAllServers(this.searchAllServers); } } /** Persist current connection settings to localStorage. */ saveConnectionSettings(): void { localStorage.setItem( STORAGE_KEY_CONNECTION_SETTINGS, JSON.stringify({ autoReconnect: this.autoReconnect, searchAllServers: this.searchAllServers }) ); this.serverDirectory.setSearchAllServers(this.searchAllServers); } /** Navigate back to the main page. */ goBack(): void { this.router.navigate(['/']); } /** Load voice settings (noise reduction) from localStorage. */ loadVoiceSettings(): void { const settings = localStorage.getItem(STORAGE_KEY_VOICE_SETTINGS); if (settings) { const parsed = JSON.parse(settings); this.noiseReduction = parsed.noiseReduction ?? false; } // Sync the live WebRTC state with the persisted preference if (this.noiseReduction !== this.webrtcService.isNoiseReductionEnabled()) { this.webrtcService.toggleNoiseReduction(this.noiseReduction); } } /** Called when the notification volume slider changes. */ onNotificationVolumeChange(value: number): void { this.audioService.setNotificationVolume(value); } /** Play a preview of the notification sound at the current volume. */ previewNotificationSound(): void { this.audioService.play(AppSound.Notification); } /** Persist noise reduction preference (merged into existing voice settings) and apply immediately. */ async saveVoiceSettings(): Promise { // Merge into existing voice settings so we don't overwrite device/volume prefs let existing: Record = {}; try { const raw = localStorage.getItem(STORAGE_KEY_VOICE_SETTINGS); if (raw) existing = JSON.parse(raw); } catch {} localStorage.setItem( STORAGE_KEY_VOICE_SETTINGS, JSON.stringify({ ...existing, noiseReduction: this.noiseReduction }) ); await this.webrtcService.toggleNoiseReduction(this.noiseReduction); } }