add volume

This commit is contained in:
lukasIO 2026-01-13 16:57:44 +01:00
parent ec28618ded
commit 9a0cb3bbe3
2 changed files with 105 additions and 22 deletions

View File

@ -26,6 +26,7 @@ export interface SecondaryRoomViewProps {
export function SecondaryRoomView({ onToggleEnlarge, isEnlarged, room }: SecondaryRoomViewProps) {
const layoutContext = useCreateLayoutContext();
const [isAudioMuted, setIsAudioMuted] = React.useState(true); // Muted by default
const [volume, setVolume] = React.useState(1); // Volume level (0-1)
const [isCameraEnabled, setIsCameraEnabled] = React.useState(false);
const [isMicEnabled, setIsMicEnabled] = React.useState(false);
const [showControls, setShowControls] = React.useState(false);
@ -56,6 +57,16 @@ export function SecondaryRoomView({ onToggleEnlarge, isEnlarged, room }: Seconda
setIsAudioMuted((prev) => !prev);
}, []);
const handleVolumeChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
const newVolume = parseFloat(e.target.value);
setVolume(newVolume);
if (newVolume === 0) {
setIsAudioMuted(true);
} else if (isAudioMuted) {
setIsAudioMuted(false);
}
}, [isAudioMuted]);
const toggleCamera = React.useCallback(() => {
const newState = !isCameraEnabled;
setIsCameraEnabled(newState);
@ -86,27 +97,46 @@ export function SecondaryRoomView({ onToggleEnlarge, isEnlarged, room }: Seconda
<RoomName />
</div>
<div className={styles.headerControls}>
<button
className={styles.controlButton}
onClick={toggleAudioMute}
title={isAudioMuted ? 'Unmute room audio' : 'Mute room audio'}
>
{isAudioMuted ? (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<path
d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"
fill="currentColor"
/>
</svg>
) : (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<path
d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"
fill="currentColor"
/>
</svg>
)}
</button>
<div className={styles.volumeControl}>
<button
className={styles.controlButton}
onClick={toggleAudioMute}
title={isAudioMuted ? 'Unmute room audio' : 'Mute room audio'}
>
{isAudioMuted || volume === 0 ? (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<path
d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"
fill="currentColor"
/>
</svg>
) : volume < 0.5 ? (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<path
d="M7 9v6h4l5 5V4l-5 5H7z"
fill="currentColor"
/>
</svg>
) : (
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
<path
d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"
fill="currentColor"
/>
</svg>
)}
</button>
<input
type="range"
min="0"
max="1"
step="0.01"
value={volume}
onChange={handleVolumeChange}
className={styles.volumeSlider}
title={`Volume: ${Math.round(volume * 100)}%`}
/>
</div>
<button className={styles.enlargeButton} onClick={onToggleEnlarge} title="Toggle size">
{isEnlarged ? (
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
@ -196,7 +226,7 @@ export function SecondaryRoomView({ onToggleEnlarge, isEnlarged, room }: Seconda
</div>
</div>
<RoomAudioRenderer volume={isAudioMuted ? 0 : 1} />
<RoomAudioRenderer volume={isAudioMuted ? 0 : volume} />
<ConnectionStateToast />
</div>
</LayoutContextProvider>

View File

@ -109,6 +109,59 @@
align-items: center;
}
.volumeControl {
display: flex;
align-items: center;
gap: 0.5rem;
}
.volumeSlider {
width: 80px;
height: 4px;
-webkit-appearance: none;
appearance: none;
background: rgba(255, 255, 255, 0.2);
border-radius: 2px;
outline: none;
cursor: pointer;
transition: background 0.2s ease;
}
.volumeSlider:hover {
background: rgba(255, 255, 255, 0.3);
}
.volumeSlider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 14px;
height: 14px;
background: var(--lk-foreground);
border-radius: 50%;
cursor: pointer;
transition: all 0.2s ease;
}
.volumeSlider::-webkit-slider-thumb:hover {
background: white;
transform: scale(1.2);
}
.volumeSlider::-moz-range-thumb {
width: 14px;
height: 14px;
background: var(--lk-foreground);
border-radius: 50%;
border: none;
cursor: pointer;
transition: all 0.2s ease;
}
.volumeSlider::-moz-range-thumb:hover {
background: white;
transform: scale(1.2);
}
.controlButton,
.enlargeButton {
background: transparent;