11import { DailyEventObject , DailyParticipant } from '@daily-co/daily-js' ;
22import { useCallback , useEffect , useState } from 'react' ;
3- import {
4- selectorFamily ,
5- useRecoilCallback ,
6- useRecoilTransactionObserver_UNSTABLE ,
7- useRecoilValue ,
8- } from 'recoil' ;
3+ import { useRecoilCallback , useRecoilValue } from 'recoil' ;
94
105import {
116 ExtendedDailyParticipant ,
@@ -14,6 +9,7 @@ import {
149} from '../DailyParticipants' ;
1510import { RECOIL_PREFIX } from '../lib/constants' ;
1611import { customDeepEqual } from '../lib/customDeepEqual' ;
12+ import { equalSelectorFamily } from '../lib/recoil-custom' ;
1713import { isTrackOff } from '../utils/isTrackOff' ;
1814import {
1915 participantPropertiesState ,
@@ -50,14 +46,15 @@ type SortParticipants = SerializableSortParticipants | SortParticipantsFunction;
5046/**
5147 * Short-cut state selector for useParticipantIds({ filter: 'local' })
5248 */
53- export const participantIdsFilteredAndSortedState = selectorFamily <
49+ export const participantIdsFilteredAndSortedState = equalSelectorFamily <
5450 string [ ] ,
5551 {
5652 filter : SerializableFilterParticipants | null ;
5753 sort : SerializableSortParticipants | null ;
5854 }
5955> ( {
6056 key : RECOIL_PREFIX + 'participant-ids-filtered-sorted' ,
57+ equals : customDeepEqual ,
6158 get :
6259 ( { filter, sort } ) =>
6360 ( { get } ) => {
@@ -153,69 +150,55 @@ export const useParticipantIds = ({
153150 } )
154151 ) ;
155152
156- /**
157- * For custom filter and/or sort, we need to calculate the returned ids manually.
158- */
159- const [ customIds , setCustomIds ] = useState < string [ ] > ( [ ] ) ;
160- /**
161- * Loads participant state from Recoil store and updates custom ids state,
162- * in case resulting set of ids is different.
163- */
164- const maybeUpdateCustomIds = useRecoilCallback (
153+ const getCustomFilteredIds = useRecoilCallback (
165154 ( { snapshot } ) =>
166- async ( ) => {
155+ ( ) => {
167156 if (
168157 // Ignore if both filter and sort are not functions.
169158 typeof filter !== 'function' &&
170159 typeof sort !== 'function'
171160 )
172- return ;
161+ return [ ] ;
173162
174- const participants : ExtendedDailyParticipant [ ] = await Promise . all (
163+ const participants : ExtendedDailyParticipant [ ] =
175164 preFilteredSortedIds . map (
176- async ( id ) =>
177- ( await snapshot . getPromise (
178- participantState ( id )
179- ) ) as ExtendedDailyParticipant
180- )
181- ) ;
182- const newCustomIds = participants
183- // Make sure we don't accidentally try to filter/sort `null` participants
184- // This can happen when a participant's id is already present in store
185- // but the participant object is not stored, yet.
186- . filter ( Boolean )
187- // Run custom filter, if it's a function. Otherwise don't filter any participants.
188- . filter ( typeof filter === 'function' ? filter : ( ) => true )
189- // Run custom sort, if it's a function. Otherwise don't sort.
190- . sort ( typeof sort === 'function' ? sort : ( ) => 0 )
191- // Map back to session_id.
192- . map ( ( p ) => p . session_id )
193- // Filter any potential null/undefined ids.
194- // This shouldn't really happen, but better safe than sorry.
195- . filter ( Boolean ) ;
165+ ( id ) =>
166+ snapshot . getLoadable ( participantState ( id ) )
167+ . contents as ExtendedDailyParticipant
168+ ) ;
196169
197- // Finally compare the new list of ids with the current one.
198- if ( customDeepEqual ( customIds , newCustomIds ) ) return ;
199-
200- setCustomIds ( newCustomIds ) ;
170+ return (
171+ participants
172+ // Make sure we don't accidentally try to filter/sort `null` participants
173+ // This can happen when a participant's id is already present in store
174+ // but the participant object is not stored, yet.
175+ . filter ( Boolean )
176+ // Run custom filter, if it's a function. Otherwise don't filter any participants.
177+ . filter ( typeof filter === 'function' ? filter : ( ) => true )
178+ // Run custom sort, if it's a function. Otherwise don't sort.
179+ . sort ( typeof sort === 'function' ? sort : ( ) => 0 )
180+ // Map back to session_id.
181+ . map ( ( p ) => p . session_id )
182+ // Filter any potential null/undefined ids.
183+ // This shouldn't really happen, but better safe than sorry.
184+ . filter ( Boolean )
185+ ) ;
201186 } ,
202- [ customIds , filter , preFilteredSortedIds , sort ]
187+ [ filter , preFilteredSortedIds , sort ]
203188 ) ;
204189
205- /**
206- * Initialize state.
207- */
190+ const [ customIds , setCustomIds ] = useState < string [ ] > ( [ ] ) ;
191+
192+ const maybeUpdateCustomIds = useCallback ( ( ) => {
193+ const newIds = getCustomFilteredIds ( ) ;
194+ if ( customDeepEqual ( newIds , customIds ) ) return ;
195+ setCustomIds ( newIds ) ;
196+ } , [ customIds , getCustomFilteredIds ] ) ;
197+
208198 useEffect ( ( ) => {
209199 maybeUpdateCustomIds ( ) ;
210200 } , [ maybeUpdateCustomIds ] ) ;
211201
212- /**
213- * Wires up this instance to the Recoil store.
214- */
215- useRecoilTransactionObserver_UNSTABLE ( ( ) => {
216- maybeUpdateCustomIds ( ) ;
217- } ) ;
218-
219202 useThrottledDailyEvent (
220203 [
221204 'participant-joined' ,
@@ -242,8 +225,10 @@ export const useParticipantIds = ({
242225 break ;
243226 }
244227 } ) ;
228+ maybeUpdateCustomIds ( ) ;
245229 } ,
246230 [
231+ maybeUpdateCustomIds ,
247232 onActiveSpeakerChange ,
248233 onParticipantJoined ,
249234 onParticipantLeft ,
0 commit comments