feat: grey badges for local-only actions and sidebar unwatched camera state

Use neutral bg-white/20 for unwatched camera badge in grid tile instead
of bg-accent-rose/90, matching the local mute badge convention. Show
crossed-out camera icon in channel sidebar when a remote user's camera
is locally unwatched. Add local mute badge to both grid tile and sidebar.
This commit is contained in:
Jannis Braun
2026-03-10 03:19:15 +01:00
parent f9376460d4
commit 3d37c70e50
7 changed files with 359 additions and 276 deletions
@@ -20,6 +20,7 @@ export function VoiceUser({ tile, large }: VoiceUserProps) {
const serverMutedUserIds = useVoiceStore((s) => s.serverMutedUserIds);
const serverDeafenedUserIds = useVoiceStore((s) => s.serverDeafenedUserIds);
const unwatchedCameras = useVoiceStore((s) => s.unwatchedCameras);
const participantMutes = useVoiceStore((s) => s.participantMutes);
const spaceId = useSpaceStore((s) => currentVoiceChannelId ? s.channelToSpaceMap.get(currentVoiceChannelId) : null);
const [, forceUpdate] = useState(0);
@@ -155,7 +156,7 @@ export function VoiceUser({ tile, large }: VoiceUserProps) {
</div>
)}
{!isLocal && participant.isCameraOn && (
<div className={`w-5 h-5 ${unwatchedCameras.has(participant.userId) ? 'bg-accent-rose/90' : 'bg-white/20'} rounded-full flex items-center justify-center`}>
<div className="w-5 h-5 bg-white/20 rounded-full flex items-center justify-center">
<svg width="12" height="12" viewBox="0 0 24 24" fill="white">
<path d="M17 10.5V7c0-.55-.45-1-1-1H2c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h14c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z" />
{unwatchedCameras.has(participant.userId) && (
@@ -164,6 +165,15 @@ export function VoiceUser({ tile, large }: VoiceUserProps) {
</svg>
</div>
)}
{!isLocal && participantMutes.get(participant.userId) && (
<div className="w-5 h-5 bg-white/20 rounded-full flex items-center justify-center" title="Locally Muted">
<svg width="12" height="12" viewBox="0 0 24 24" fill="white">
<path d="M3 9v6h4l5 5V4L7 9H3z" />
<line x1="17" y1="7" x2="23" y2="13" stroke="white" strokeWidth="2" strokeLinecap="round" />
<line x1="23" y1="7" x2="17" y2="13" stroke="white" strokeWidth="2" strokeLinecap="round" />
</svg>
</div>
)}
</>
);
})()}