fix: deduplicate VolumeSliderItem and add missing stopPropagation

- Extract VolumeSliderItem to voiceMenuItems.tsx (was duplicated in
  VoiceUser.tsx and VoiceChannel.tsx)
- Add e.stopPropagation() to all imperative context menu handlers
  for consistency with useContextMenu hook behavior
This commit is contained in:
Jannis Braun
2026-03-20 18:55:58 +01:00
parent 443259a527
commit 68378c7d83
4 changed files with 40 additions and 61 deletions
@@ -2,7 +2,7 @@ import React, { useRef, useEffect, useState, useCallback } from 'react';
import { Avatar } from '../ui/Avatar';
import { useVoiceStore } from '../../stores/voiceStore';
import { useContextMenuStore, type ContextMenuItem } from '../../stores/contextMenuStore';
import { buildVoiceModMenuItems } from './voiceMenuItems';
import { buildVoiceModMenuItems, VolumeSliderItem } from './voiceMenuItems';
import { useSpaceStore } from '../../stores/spaceStore';
import { useVoiceParticipantMeta } from '../../hooks/useVoiceParticipantMeta';
import { getActiveRoom, setCameraSubscription } from '../../hooks/useLiveKit';
@@ -13,36 +13,6 @@ interface VoiceUserProps {
large?: boolean;
}
/** Wrapper component for the volume slider so it can use hooks (useState). */
function VolumeSliderItem({ userId }: { userId: string }) {
const volume = useVoiceStore((s) => s.participantVolumes.get(userId) ?? 100);
const setParticipantVolume = useVoiceStore((s) => s.setParticipantVolume);
return (
<div className="p-3">
<div className="text-xs text-txt-tertiary mb-2 font-medium uppercase tracking-wider">
User Volume
</div>
<div className="flex items-center gap-2">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" className="text-txt-tertiary flex-shrink-0">
<path d="M3 9v6h4l5 5V4L7 9H3z" />
</svg>
<input
type="range"
min="0"
max="200"
value={volume}
onChange={(e) => setParticipantVolume(userId, parseInt(e.target.value))}
className="flex-1 accent-accent-primary h-1"
/>
<span className="text-xs text-txt-secondary min-w-[32px] text-right">
{volume}%
</span>
</div>
</div>
);
}
export function VoiceUser({ tile, large }: VoiceUserProps) {
const videoRef = useRef<HTMLVideoElement>(null);
@@ -97,6 +67,7 @@ export function VoiceUser({ tile, large }: VoiceUserProps) {
(e: React.MouseEvent) => {
if (isLocal || !currentVoiceChannelId) return;
e.preventDefault();
e.stopPropagation();
const targetUserId = participant.userId;
const channelId = currentVoiceChannelId;