210 lines
5.7 KiB
TypeScript
210 lines
5.7 KiB
TypeScript
/* 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<string | null>(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<void> {
|
|
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<void> {
|
|
// Merge into existing voice settings so we don't overwrite device/volume prefs
|
|
let existing: Record<string, unknown> = {};
|
|
|
|
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);
|
|
}
|
|
}
|