From e5f0b1c202c021229c808b7ee9d08c2b6c4ec9f8 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Fri, 21 Aug 2026 22:03:03 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(frontend)=20fix=20joined=20notific?= =?UTF-8?q?ation=20tile=20no=20longer=20rendering=20properly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The toast is enqueued on `ParticipantConnected`, which livekit-client fires before the participant's track publications exist. At that point `getTrackPublication(Camera)` is `undefined`, and the track ref used by the toast is frozen that way — the toast never re-subscribes to the participant. Downstream effects: * LiveKit's `useIsMuted` initializes to `false` when there is no publication, so the tile first paints with `data-lk-video-muted="false"`, which the stock CSS maps to placeholder `opacity: 0` — a blank box. * Its effect then subscribes to `mutedObserver`, which defaults to `true` for the same situation, triggering a second render and only then starting the 200 ms fade-in. That render-effect-render transition is the visible lag behind the text. * Because the track ref never updates, no `VideoTrack` ever mounts. When the camera is later subscribed, the placeholder fades out again, leaving the tile empty. Re-derive the track ref inside the toast when the participant's publications become available, so `useIsMuted` sees the real state from the start and the tile renders the video (or a stable placeholder) instead of a blank box. --- CHANGELOG.md | 1 + .../notifications/components/ToastJoined.tsx | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36f336ea..59338f3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to - 🐛(frontend) use state instead of a ref for MoreControls container - 🐛(frontend) stop init_virtual_background from firing on blur updates - 🐛(frontend) hoist mute confirmation dialog to VideoConference level +- 🐛(frontend) fix joined notification tile no longer rendering properly ## [1.27.0] - 2026-08-14 diff --git a/src/frontend/src/features/notifications/components/ToastJoined.tsx b/src/frontend/src/features/notifications/components/ToastJoined.tsx index fd4f9863..336dc9d9 100644 --- a/src/frontend/src/features/notifications/components/ToastJoined.tsx +++ b/src/frontend/src/features/notifications/components/ToastJoined.tsx @@ -1,5 +1,5 @@ import { useToast } from 'react-aria' -import { useRef } from 'react' +import { useMemo, useRef } from 'react' import { Button as RACButton } from 'react-aria-components' import { Track } from 'livekit-client' import Source = Track.Source @@ -11,6 +11,7 @@ import { Div } from '@/primitives' import { useTranslation } from 'react-i18next' import { StyledToastContainer } from './StyledToastContainer' import { setPinnedTrack } from '@/stores/layout' +import { useParticipantTracks } from '@livekit/components-react' const ClickableToast = styled(RACButton, { base: { @@ -30,13 +31,17 @@ export function ToastJoined({ state, ...props }: Readonly) { ) const participant = props.toast.content.participant - if (!participant) return + const [cameraTrack] = useParticipantTracks( + [Source.Camera], + participant?.identity + ) - const trackReference = { - participant, - publication: participant.getTrackPublication(Source.Camera), - source: Source.Camera, - } + const trackReference = useMemo( + () => cameraTrack ?? { participant, source: Source.Camera }, + [cameraTrack, participant] + ) + + if (!participant) return return (