ddd test 2

This commit is contained in:
2026-03-23 00:23:56 +01:00
parent fe9c1dd1c0
commit 971a5afb8b
130 changed files with 2493 additions and 822 deletions

View File

@@ -0,0 +1,111 @@
# Voice Session Domain
Tracks voice session metadata across client-side navigation and manages the voice workspace UI state (expanded, minimized, hidden). This domain does not touch WebRTC directly; actual connections live in `voice-connection` and `infrastructure/realtime`.
## Module map
```
voice-session/
├── application/
│ ├── voice-session.facade.ts Tracks active voice session, drives floating controls
│ └── voice-workspace.service.ts Workspace mode (hidden/expanded/minimized), focused stream, mini-window position
├── domain/
│ ├── voice-session.logic.ts isViewingVoiceSessionServer, buildVoiceSessionRoom
│ └── voice-session.models.ts VoiceSessionInfo interface
├── infrastructure/
│ └── voice-settings.storage.ts Persists audio device IDs, volumes, bitrate, latency, noise reduction to localStorage
├── feature/
│ ├── voice-controls/ Full voice control panel (mic, deafen, devices, screen share, settings)
│ └── floating-voice-controls/ Minimal overlay when user navigates away from the voice server
└── index.ts Barrel exports
```
## How the pieces connect
The facade manages session bookkeeping. The workspace service owns view state. Settings storage provides persistence for user preferences. Neither service opens any WebRTC connections.
```mermaid
graph TD
VSF[VoiceSessionFacade]
VWS[VoiceWorkspaceService]
VSS[voiceSettingsStorage]
Logic[voice-session.logic]
VC[VoiceControlsComponent]
FC[FloatingVoiceControlsComponent]
Store[NgRx Store]
VC --> VSF
VC --> VWS
VC --> VSS
FC --> VSF
FC --> VWS
VSF --> Logic
VSF --> Store
VWS --> VSF
click VSF "application/voice-session.facade.ts" "Tracks active voice session"
click VWS "application/voice-workspace.service.ts" "Workspace mode and focused stream"
click VSS "infrastructure/voice-settings.storage.ts" "localStorage persistence for audio settings"
click Logic "domain/voice-session.logic.ts" "Pure helper functions"
click VC "feature/voice-controls/" "Full voice control panel"
click FC "feature/floating-voice-controls/" "Minimal floating overlay"
```
## Session lifecycle
```mermaid
stateDiagram-v2
[*] --> NoSession
NoSession --> Active: startSession(info)
Active --> Active: checkCurrentRoute(serverId)
Active --> NoSession: endSession()
state Active {
[*] --> ViewingServer
ViewingServer --> AwayFromServer: navigated to different server
AwayFromServer --> ViewingServer: navigated back / navigateToVoiceServer()
}
```
When a voice session is active and the user navigates away from the voice-connected server, `showFloatingControls` becomes `true` and the floating overlay appears. Clicking the overlay dispatches `RoomsActions.viewServer` to navigate back.
## Workspace modes
`VoiceWorkspaceService` controls the voice workspace panel state. The workspace is only visible when the user is viewing the voice-connected server.
```mermaid
stateDiagram-v2
[*] --> Hidden
Hidden --> Expanded: open()
Expanded --> Minimized: minimize()
Expanded --> Hidden: close() / showChat()
Minimized --> Expanded: restore()
Minimized --> Hidden: close()
Expanded --> Hidden: voice session ends
Minimized --> Hidden: voice session ends
```
The minimized mode renders a draggable mini-window. Its position is tracked in `miniWindowPosition` and clamped to viewport bounds on resize. `focusedStreamId` controls which screen-share stream gets the widescreen treatment in expanded mode.
## Voice settings
Settings are stored in localStorage under a single JSON key. All values are validated and clamped on load to defend against corrupt storage.
| Setting | Default | Range |
|---|---|---|
| inputDevice | `""` | device ID string |
| outputDevice | `""` | device ID string |
| inputVolume | 100 | 0 -- 100 |
| outputVolume | 100 | 0 -- 100 |
| audioBitrate | 96 kbps | 32 -- 256 |
| latencyProfile | `"balanced"` | low / balanced / high |
| noiseReduction | `true` | boolean |
| screenShareQuality | `"balanced"` | low / balanced / high |
| askScreenShareQuality | `true` | boolean |
| includeSystemAudio | `false` | boolean |
`loadVoiceSettingsFromStorage()` and `saveVoiceSettingsToStorage(patch)` are the only entry points. The save function merges the patch with the current stored value so callers only need to pass changed fields.