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
@@ -23,6 +23,8 @@ export function VoiceChannel({ channelId, channelName, onClick, locked }: VoiceC
const voiceUserStates = useVoiceStore((s) => s.voiceUserStates);
const serverMutedUserIds = useVoiceStore((s) => s.serverMutedUserIds);
const serverDeafenedUserIds = useVoiceStore((s) => s.serverDeafenedUserIds);
const participantMutes = useVoiceStore((s) => s.participantMutes);
const unwatchedCameras = useVoiceStore((s) => s.unwatchedCameras);
const currentUserId = useVoiceStore((s) => {
const local = s.participants.find(p => p.isLocal);
return local?.userId ?? null;
@@ -146,11 +148,23 @@ export function VoiceChannel({ channelId, channelName, onClick, locked }: VoiceC
{hasCamera && (
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" className="text-txt-tertiary">
<path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z" />
{userId !== myUser?.id && unwatchedCameras.has(userId) && (
<line x1="1" y1="1" x2="23" y2="23" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" />
)}
</svg>
)}
{isScreenSharing && (
<span className="bg-accent-rose text-white text-[9px] font-bold px-1 rounded leading-[14px]">LIVE</span>
)}
{userId !== myUser?.id && participantMutes.get(userId) && (
<span title="Locally Muted">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" className="text-txt-tertiary">
<path d="M3 9v6h4l5 5V4L7 9H3z" />
<line x1="17" y1="7" x2="23" y2="13" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" />
<line x1="23" y1="7" x2="17" y2="13" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" />
</svg>
</span>
)}
</div>
</div>
);