From f1c9b281bc4c14f7e9f4dcddf0e1f1f94c506b34 Mon Sep 17 00:00:00 2001 From: vegard Date: Wed, 18 Mar 2026 04:57:22 +0000 Subject: [PATCH] =?UTF-8?q?Fullf=C3=B8rer=20oppgave=2016.3:=20MixerTrait-k?= =?UTF-8?q?omponent=20med=20kanalstriper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementerer Mixer-UI som trait-komponent for samlingssider: - Kanalstripe per deltaker med volumslider (0–150%), VU-meter (CSS), nød-mute-knapp (rød, tydelig) og navnelabel - Master-seksjon med fader, VU-meter og master-mute - Responsivt design: stacked layout på mobil, horisontal på desktop - Animert VU-meter via requestAnimationFrame og AnalyserNode-data - Integrert i collection-siden som 'mixer'-trait Co-Authored-By: Claude Opus 4.6 (1M context) --- .../lib/components/traits/MixerTrait.svelte | 291 ++++++++++++++++++ .../src/routes/collection/[id]/+page.svelte | 5 +- tasks.md | 3 +- 3 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 frontend/src/lib/components/traits/MixerTrait.svelte diff --git a/frontend/src/lib/components/traits/MixerTrait.svelte b/frontend/src/lib/components/traits/MixerTrait.svelte new file mode 100644 index 0000000..9ecc55f --- /dev/null +++ b/frontend/src/lib/components/traits/MixerTrait.svelte @@ -0,0 +1,291 @@ + + + + {#snippet children()} + {#if getStatus() !== 'connected'} +

Koble til opptak-rommet for å bruke mixeren.

+ {:else if displayChannels.length === 0} +

Ingen lydkanaler aktive.

+ {:else} + +
+ {#each displayChannels as identity (identity)} + {@const state = channelStates.get(identity)} + {@const levels = channelLevels.get(identity)} + {@const isMuted = state?.muted ?? false} + {@const gain = state?.gain ?? 1.0} + +
+ +
+ + + {displayName(identity)} + + + +
+
+
+ + +
+ handleGainChange(identity, parseFloat((e.target as HTMLInputElement).value))} + disabled={isMuted} + class="flex-1 h-2 accent-indigo-600 disabled:opacity-40" + /> + + {gainToPercent(gain)}% + +
+ + + +
+
+ {/each} +
+ + +
+
+ + Master + + + +
+
+
+ + +
+ handleMasterGainChange(parseFloat((e.target as HTMLInputElement).value))} + disabled={masterState.muted} + class="flex-1 h-2 accent-indigo-600 disabled:opacity-40" + /> + + {gainToPercent(masterState.gain)}% + +
+ + + +
+
+ {/if} + {/snippet} +
diff --git a/frontend/src/routes/collection/[id]/+page.svelte b/frontend/src/routes/collection/[id]/+page.svelte index 69fcb75..645baac 100644 --- a/frontend/src/routes/collection/[id]/+page.svelte +++ b/frontend/src/routes/collection/[id]/+page.svelte @@ -14,6 +14,7 @@ import RecordingTrait from '$lib/components/traits/RecordingTrait.svelte'; import TranscriptionTrait from '$lib/components/traits/TranscriptionTrait.svelte'; import StudioTrait from '$lib/components/traits/StudioTrait.svelte'; + import MixerTrait from '$lib/components/traits/MixerTrait.svelte'; import GenericTrait from '$lib/components/traits/GenericTrait.svelte'; import TraitAdmin from '$lib/components/traits/TraitAdmin.svelte'; import NodeUsage from '$lib/components/NodeUsage.svelte'; @@ -49,7 +50,7 @@ /** Traits with dedicated components */ const knownTraits = new Set([ 'editor', 'chat', 'kanban', 'podcast', 'publishing', - 'rss', 'calendar', 'recording', 'transcription', 'studio' + 'rss', 'calendar', 'recording', 'transcription', 'studio', 'mixer' ]); /** Traits that have a dedicated component */ @@ -169,6 +170,8 @@ {:else if trait === 'studio'} + {:else if trait === 'mixer'} + {/if} {/each} diff --git a/tasks.md b/tasks.md index e691ce2..d2b77ae 100644 --- a/tasks.md +++ b/tasks.md @@ -179,8 +179,7 @@ Ref: `docs/features/lydmixer.md` - [x] 16.1 LiveKit-klient i frontend: installer `livekit-client`, koble til rom, vis deltakerliste. Deaktiver LiveKit sin auto-attach av `