66 DailyParticipantsObject ,
77 DailyWaitingParticipant ,
88} from '@daily-co/daily-js' ;
9- import React , { useCallback , useEffect } from 'react' ;
9+ import React , { useCallback , useEffect , useState } from 'react' ;
1010import {
1111 atom ,
1212 atomFamily ,
@@ -47,25 +47,28 @@ export const localIdState = atom<string>({
4747 default : '' ,
4848} ) ;
4949
50- export const participantsState = atom < ExtendedDailyParticipant [ ] > ( {
51- key : RECOIL_PREFIX + 'participants-objects ' ,
50+ export const participantIdsState = atom < string [ ] > ( {
51+ key : RECOIL_PREFIX + 'participant-ids ' ,
5252 default : [ ] ,
5353} ) ;
5454
55- /**
56- * Holds each individual participant's state object.
57- */
58- export const participantState = selectorFamily <
55+ export const participantState = atomFamily <
5956 ExtendedDailyParticipant | null ,
6057 string
6158> ( {
62- key : RECOIL_PREFIX + 'participant' ,
63- get :
64- ( id ) =>
65- ( { get } ) => {
66- const participants = get ( participantsState ) ;
67- return participants . find ( ( p ) => p . session_id === id ) ?? null ;
68- } ,
59+ key : RECOIL_PREFIX + 'participant-state' ,
60+ default : null ,
61+ } ) ;
62+
63+ export const participantsState = selector < ExtendedDailyParticipant [ ] > ( {
64+ key : RECOIL_PREFIX + 'participants' ,
65+ get : ( { get } ) => {
66+ const ids = get ( participantIdsState ) ;
67+ const participants = ids
68+ . map ( ( id ) => get ( participantState ( id ) ) )
69+ . filter ( Boolean ) as ExtendedDailyParticipant [ ] ;
70+ return participants ;
71+ } ,
6972} ) ;
7073
7174/**
@@ -76,8 +79,7 @@ export const participantPropertyState = selectorFamily<any, PropertyType>({
7679 get :
7780 ( { id, properties } ) =>
7881 ( { get } ) => {
79- const participants = get ( participantsState ) ;
80- const participant = participants . find ( ( p ) => p . session_id === id ) ?? null ;
82+ const participant = get ( participantState ( id ) ) ;
8183
8284 return resolveParticipantPaths ( participant , properties ) ;
8385 } ,
@@ -123,13 +125,20 @@ export const DailyParticipants: React.FC<React.PropsWithChildren<{}>> = ({
123125 children,
124126} ) => {
125127 const daily = useDaily ( ) ;
128+ const [ initialized , setInitialized ] = useState ( false ) ;
126129
127130 const initParticipants = useRecoilCallback (
128131 ( { transact_UNSTABLE } ) =>
129132 ( participants : DailyParticipantsObject ) => {
130133 transact_UNSTABLE ( ( { set } ) => {
131134 set ( localIdState , participants . local . session_id ) ;
132- set ( participantsState , Object . values ( participants ) ) ;
135+ const participantsArray = Object . values ( participants ) ;
136+ const ids = participantsArray . map ( ( p ) => p . session_id ) ;
137+ set ( participantIdsState , ids ) ;
138+ participantsArray . forEach ( ( p ) => {
139+ set ( participantState ( p . session_id ) , p ) ;
140+ } ) ;
141+ setInitialized ( true ) ;
133142 } ) ;
134143 } ,
135144 [ ]
@@ -139,7 +148,7 @@ export const DailyParticipants: React.FC<React.PropsWithChildren<{}>> = ({
139148 * Retries every 100ms to initialize the state, until daily is ready.
140149 */
141150 useEffect ( ( ) => {
142- if ( ! daily ) return ;
151+ if ( ! daily || initialized ) return ;
143152 const interval = setInterval ( ( ) => {
144153 const participants = daily . participants ( ) ;
145154 if ( ! ( 'local' in participants ) ) return ;
@@ -149,7 +158,7 @@ export const DailyParticipants: React.FC<React.PropsWithChildren<{}>> = ({
149158 return ( ) => {
150159 clearInterval ( interval ) ;
151160 } ;
152- } , [ daily , initParticipants ] ) ;
161+ } , [ daily , initialized , initParticipants ] ) ;
153162 const handleInitEvent = useCallback ( ( ) => {
154163 if ( ! daily ) return ;
155164 const participants = daily ?. participants ( ) ;
@@ -188,42 +197,37 @@ export const DailyParticipants: React.FC<React.PropsWithChildren<{}>> = ({
188197 | 'left-meeting'
189198 > [ ]
190199 ) => {
191- transact_UNSTABLE ( ( { reset, set } ) => {
200+ transact_UNSTABLE ( ( { get , reset, set } ) => {
192201 evts . forEach ( ( ev ) => {
193202 switch ( ev . action ) {
194203 case 'active-speaker-change' : {
195204 const sessionId = ev . activeSpeaker . peerId ;
196205 set ( activeIdState , sessionId ) ;
197- set ( participantsState , ( prev ) =>
198- [ ...prev ] . map ( ( p ) =>
199- p . session_id === sessionId
200- ? {
201- ...p ,
202- last_active : new Date ( ) ,
203- }
204- : p
205- )
206- ) ;
206+ set ( participantState ( sessionId ) , ( prev ) => {
207+ if ( ! prev ) return null ;
208+ return {
209+ ...prev ,
210+ last_active : new Date ( ) ,
211+ } ;
212+ } ) ;
207213 break ;
208214 }
209215 case 'participant-joined' :
210- set ( participantsState , ( prev ) =>
211- [ ...prev , ev . participant ] . filter (
212- ( participant , idx , arr ) =>
213- arr . findIndex (
214- ( p ) => p . session_id === participant . session_id
215- ) == idx
216- )
216+ set ( participantIdsState , ( prevIds ) =>
217+ prevIds . includes ( ev . participant . session_id )
218+ ? prevIds
219+ : [ ...prevIds , ev . participant . session_id ]
220+ ) ;
221+ set (
222+ participantState ( ev . participant . session_id ) ,
223+ ev . participant
217224 ) ;
218225 break ;
219226 case 'participant-updated' :
220- set ( participantsState , ( prev ) =>
221- [ ...prev ] . map ( ( p ) =>
222- p . session_id === ev . participant . session_id
223- ? { ...ev . participant , last_active : p . last_active }
224- : p
225- )
226- ) ;
227+ set ( participantState ( ev . participant . session_id ) , ( prev ) => ( {
228+ ...prev ,
229+ ...ev . participant ,
230+ } ) ) ;
227231 if ( ev . participant . local ) {
228232 set ( localIdState , ( prevId ) =>
229233 prevId !== ev . participant . session_id
@@ -233,19 +237,27 @@ export const DailyParticipants: React.FC<React.PropsWithChildren<{}>> = ({
233237 }
234238 break ;
235239 case 'participant-left' :
236- set ( participantsState , ( prev ) =>
237- [ ...prev ] . filter (
238- ( p ) => ev . participant . session_id !== p . session_id
239- )
240+ set ( participantIdsState , ( prevIds ) =>
241+ prevIds . includes ( ev . participant . session_id )
242+ ? [
243+ ...prevIds . filter (
244+ ( id ) => id !== ev . participant . session_id
245+ ) ,
246+ ]
247+ : prevIds
240248 ) ;
249+ reset ( participantState ( ev . participant . session_id ) ) ;
241250 break ;
242251 /**
243252 * Reset stored participants, when meeting has ended.
244253 */
245- case 'left-meeting' :
254+ case 'left-meeting' : {
246255 reset ( localIdState ) ;
247- reset ( participantsState ) ;
256+ const ids = get ( participantIdsState ) ;
257+ ids . forEach ( ( id ) => reset ( participantState ( id ) ) ) ;
258+ reset ( participantIdsState ) ;
248259 break ;
260+ }
249261 }
250262 } ) ;
251263 } ) ;
0 commit comments