Add new settngs modal

This commit is contained in:
2026-03-03 02:55:08 +01:00
parent d684fc5632
commit cf91d77502
24 changed files with 1781 additions and 316 deletions

View File

@@ -0,0 +1,154 @@
import { Component, inject, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideMic, lucideHeadphones, lucideAudioLines } from '@ng-icons/lucide';
import { WebRTCService } from '../../../../core/services/webrtc.service';
import { STORAGE_KEY_VOICE_SETTINGS } from '../../../../core/constants';
interface AudioDevice {
deviceId: string;
label: string;
}
@Component({
selector: 'app-voice-settings',
standalone: true,
imports: [CommonModule, FormsModule, NgIcon],
viewProviders: [
provideIcons({
lucideMic,
lucideHeadphones,
lucideAudioLines,
}),
],
templateUrl: './voice-settings.component.html',
})
export class VoiceSettingsComponent {
private webrtcService = inject(WebRTCService);
inputDevices = signal<AudioDevice[]>([]);
outputDevices = signal<AudioDevice[]>([]);
selectedInputDevice = signal<string>('');
selectedOutputDevice = signal<string>('');
inputVolume = signal(100);
outputVolume = signal(100);
audioBitrate = signal(96);
latencyProfile = signal<'low' | 'balanced' | 'high'>('balanced');
includeSystemAudio = signal(false);
noiseReduction = signal(false);
constructor() {
this.loadVoiceSettings();
this.loadAudioDevices();
}
async loadAudioDevices(): Promise<void> {
try {
if (!navigator.mediaDevices?.enumerateDevices) return;
const devices = await navigator.mediaDevices.enumerateDevices();
this.inputDevices.set(
devices
.filter((d) => d.kind === 'audioinput')
.map((d) => ({ deviceId: d.deviceId, label: d.label })),
);
this.outputDevices.set(
devices
.filter((d) => d.kind === 'audiooutput')
.map((d) => ({ deviceId: d.deviceId, label: d.label })),
);
} catch {}
}
loadVoiceSettings(): void {
try {
const raw = localStorage.getItem(STORAGE_KEY_VOICE_SETTINGS);
if (!raw) return;
const s = JSON.parse(raw);
if (s.inputDevice) this.selectedInputDevice.set(s.inputDevice);
if (s.outputDevice) this.selectedOutputDevice.set(s.outputDevice);
if (typeof s.inputVolume === 'number') this.inputVolume.set(s.inputVolume);
if (typeof s.outputVolume === 'number') this.outputVolume.set(s.outputVolume);
if (typeof s.audioBitrate === 'number') this.audioBitrate.set(s.audioBitrate);
if (s.latencyProfile) this.latencyProfile.set(s.latencyProfile);
if (typeof s.includeSystemAudio === 'boolean')
this.includeSystemAudio.set(s.includeSystemAudio);
if (typeof s.noiseReduction === 'boolean') this.noiseReduction.set(s.noiseReduction);
} catch {}
if (this.noiseReduction() !== this.webrtcService.isNoiseReductionEnabled()) {
this.webrtcService.toggleNoiseReduction(this.noiseReduction());
}
}
saveVoiceSettings(): void {
try {
localStorage.setItem(
STORAGE_KEY_VOICE_SETTINGS,
JSON.stringify({
inputDevice: this.selectedInputDevice(),
outputDevice: this.selectedOutputDevice(),
inputVolume: this.inputVolume(),
outputVolume: this.outputVolume(),
audioBitrate: this.audioBitrate(),
latencyProfile: this.latencyProfile(),
includeSystemAudio: this.includeSystemAudio(),
noiseReduction: this.noiseReduction(),
}),
);
} catch {}
}
onInputDeviceChange(event: Event): void {
const select = event.target as HTMLSelectElement;
this.selectedInputDevice.set(select.value);
this.saveVoiceSettings();
}
onOutputDeviceChange(event: Event): void {
const select = event.target as HTMLSelectElement;
this.selectedOutputDevice.set(select.value);
this.webrtcService.setOutputVolume(this.outputVolume() / 100);
this.saveVoiceSettings();
}
onInputVolumeChange(event: Event): void {
const input = event.target as HTMLInputElement;
this.inputVolume.set(parseInt(input.value, 10));
this.saveVoiceSettings();
}
onOutputVolumeChange(event: Event): void {
const input = event.target as HTMLInputElement;
this.outputVolume.set(parseInt(input.value, 10));
this.webrtcService.setOutputVolume(this.outputVolume() / 100);
this.saveVoiceSettings();
}
onLatencyProfileChange(event: Event): void {
const select = event.target as HTMLSelectElement;
const profile = select.value as 'low' | 'balanced' | 'high';
this.latencyProfile.set(profile);
this.webrtcService.setLatencyProfile(profile);
this.saveVoiceSettings();
}
onAudioBitrateChange(event: Event): void {
const input = event.target as HTMLInputElement;
this.audioBitrate.set(parseInt(input.value, 10));
this.webrtcService.setAudioBitrate(this.audioBitrate());
this.saveVoiceSettings();
}
onIncludeSystemAudioChange(event: Event): void {
const input = event.target as HTMLInputElement;
this.includeSystemAudio.set(!!input.checked);
this.saveVoiceSettings();
}
async onNoiseReductionChange(): Promise<void> {
this.noiseReduction.update((v) => !v);
await this.webrtcService.toggleNoiseReduction(this.noiseReduction());
this.saveVoiceSettings();
}
}