feat(sounds): broadcast stream_watch from StreamTile click sites
Wire broadcastStreamWatch (LiveKit data-channel ping) to all three explicit user-action sites in StreamTile: "Stop Watching" context-menu item, "Watch Stream" context-menu item, and the handleWatch button callback. Broadcast is intentionally confined to click sites only — not wired in voiceStore actions — to prevent noisy stream_user_left sounds on automatic teardown paths in useLiveKit.ts.
This commit is contained in:
@@ -4,6 +4,7 @@ import { useVoiceStore } from '../../stores/voiceStore';
|
|||||||
import { useContextMenuStore, type ContextMenuItem } from '../../stores/contextMenuStore';
|
import { useContextMenuStore, type ContextMenuItem } from '../../stores/contextMenuStore';
|
||||||
import { getActiveRoom, setStreamSubscription } from '../../hooks/useLiveKit';
|
import { getActiveRoom, setStreamSubscription } from '../../hooks/useLiveKit';
|
||||||
import { stopScreenShare, changeScreenShare } from '../../utils/screenShare';
|
import { stopScreenShare, changeScreenShare } from '../../utils/screenShare';
|
||||||
|
import { encodeStreamWatch } from '../../utils/streamWatchProtocol';
|
||||||
import { ScreenShareSettingsPopover } from './ScreenShareSettingsPopover';
|
import { ScreenShareSettingsPopover } from './ScreenShareSettingsPopover';
|
||||||
import { useVoiceParticipantMeta } from '../../hooks/useVoiceParticipantMeta';
|
import { useVoiceParticipantMeta } from '../../hooks/useVoiceParticipantMeta';
|
||||||
import type { StreamTile as StreamTileType } from '../../hooks/useLiveKit';
|
import type { StreamTile as StreamTileType } from '../../hooks/useLiveKit';
|
||||||
@@ -140,6 +141,14 @@ function StreamAttenuationItem() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function broadcastStreamWatch(streamerUserId: string, watching: boolean): void {
|
||||||
|
const room = getActiveRoom();
|
||||||
|
if (!room) return;
|
||||||
|
const payload = encodeStreamWatch({ type: 'stream_watch', target: streamerUserId, watching });
|
||||||
|
// Reliable delivery; data channels are room-scoped and small (under 1KB).
|
||||||
|
void room.localParticipant.publishData(payload, { reliable: true });
|
||||||
|
}
|
||||||
|
|
||||||
export function StreamTile({ tile, large }: StreamTileProps) {
|
export function StreamTile({ tile, large }: StreamTileProps) {
|
||||||
const videoRef = useRef<HTMLVideoElement>(null);
|
const videoRef = useRef<HTMLVideoElement>(null);
|
||||||
|
|
||||||
@@ -266,6 +275,7 @@ export function StreamTile({ tile, large }: StreamTileProps) {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
useVoiceStore.getState().unwatchStream(userId);
|
useVoiceStore.getState().unwatchStream(userId);
|
||||||
setStreamSubscription(getActiveRoom(), identity, false);
|
setStreamSubscription(getActiveRoom(), identity, false);
|
||||||
|
broadcastStreamWatch(userId, false);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -279,6 +289,7 @@ export function StreamTile({ tile, large }: StreamTileProps) {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
useVoiceStore.getState().watchStream(userId);
|
useVoiceStore.getState().watchStream(userId);
|
||||||
setStreamSubscription(getActiveRoom(), identity, true);
|
setStreamSubscription(getActiveRoom(), identity, true);
|
||||||
|
broadcastStreamWatch(userId, true);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -322,6 +333,7 @@ export function StreamTile({ tile, large }: StreamTileProps) {
|
|||||||
const handleWatch = useCallback(() => {
|
const handleWatch = useCallback(() => {
|
||||||
useVoiceStore.getState().watchStream(userId);
|
useVoiceStore.getState().watchStream(userId);
|
||||||
setStreamSubscription(getActiveRoom(), participant.identity, true);
|
setStreamSubscription(getActiveRoom(), participant.identity, true);
|
||||||
|
broadcastStreamWatch(userId, true);
|
||||||
}, [userId, participant.identity]);
|
}, [userId, participant.identity]);
|
||||||
|
|
||||||
const hasVideo = liveScreenTrack !== null;
|
const hasVideo = liveScreenTrack !== null;
|
||||||
|
|||||||
Reference in New Issue
Block a user