Skip to content

Commit 59a2088

Browse files
author
Daily Autobot
committed
Merge branch 'main' into daily-js-releases
2 parents 1375949 + 9354a10 commit 59a2088

32 files changed

+860
-468
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "0.12.0",
2+
"version": "0.14.0",
33
"license": "BSD-2-Clause",
44
"keywords": [
55
"daily",

src/DailyMeeting.tsx

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import {
2+
DailyEventObjectFatalError,
3+
DailyEventObjectNonFatalError,
24
DailyMeetingSessionState,
35
DailyMeetingState,
46
} from '@daily-co/daily-js';
@@ -14,6 +16,16 @@ export const meetingStateState = atom<DailyMeetingState>({
1416
default: 'new',
1517
});
1618

19+
export const meetingErrorState = atom<DailyEventObjectFatalError | null>({
20+
key: RECOIL_PREFIX + 'meeting-error',
21+
default: null,
22+
});
23+
24+
export const nonFatalErrorState = atom<DailyEventObjectNonFatalError | null>({
25+
key: RECOIL_PREFIX + 'non-fatal-error',
26+
default: null,
27+
});
28+
1729
export const meetingSessionDataState = atom<DailyMeetingSessionState>({
1830
key: 'meeting-session-data',
1931
default: {
@@ -46,7 +58,27 @@ export const DailyMeeting: React.FC<React.PropsWithChildren<{}>> = ({
4658
useDailyEvent('joining-meeting', updateMeetingState);
4759
useDailyEvent('joined-meeting', updateMeetingState);
4860
useDailyEvent('left-meeting', updateMeetingState);
49-
useDailyEvent('error', updateMeetingState);
61+
useDailyEvent(
62+
'error',
63+
useRecoilCallback(
64+
({ set }) =>
65+
(ev) => {
66+
set(meetingErrorState, ev);
67+
updateMeetingState();
68+
},
69+
[updateMeetingState]
70+
)
71+
);
72+
useDailyEvent(
73+
'nonfatal-error',
74+
useRecoilCallback(
75+
({ set }) =>
76+
(ev) => {
77+
set(nonFatalErrorState, ev);
78+
},
79+
[]
80+
)
81+
);
5082

5183
/**
5284
* Updates meeting session state.
@@ -99,9 +131,14 @@ export const DailyMeeting: React.FC<React.PropsWithChildren<{}>> = ({
99131
useDailyEvent(
100132
'call-instance-destroyed',
101133
useRecoilCallback(
102-
({ reset }) =>
134+
({ transact_UNSTABLE }) =>
103135
() => {
104-
reset(meetingStateState);
136+
transact_UNSTABLE(({ reset }) => {
137+
reset(meetingStateState);
138+
reset(meetingErrorState);
139+
reset(nonFatalErrorState);
140+
reset(meetingSessionDataState);
141+
});
105142
},
106143
[]
107144
)

src/DailyNetwork.tsx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { DailyNetworkStats, DailyNetworkTopology } from '@daily-co/daily-js';
2+
import React, { useEffect } from 'react';
3+
import { atom, useRecoilCallback, useRecoilValue } from 'recoil';
4+
5+
import { useDaily } from './hooks/useDaily';
6+
import { useDailyEvent } from './hooks/useDailyEvent';
7+
import { RECOIL_PREFIX } from './lib/constants';
8+
9+
export const topologyState = atom<DailyNetworkTopology | 'none'>({
10+
key: RECOIL_PREFIX + 'topology',
11+
default: 'none',
12+
});
13+
export const networkQualityState = atom<DailyNetworkStats['quality']>({
14+
key: RECOIL_PREFIX + 'networkQuality',
15+
default: 100,
16+
});
17+
export const networkThresholdState = atom<DailyNetworkStats['threshold']>({
18+
key: RECOIL_PREFIX + 'networkThreshold',
19+
default: 'good',
20+
});
21+
22+
export const DailyNetwork: React.FC<React.PropsWithChildren<{}>> = ({
23+
children,
24+
}) => {
25+
const daily = useDaily();
26+
27+
const topology = useRecoilValue(topologyState);
28+
29+
const initTopology = useRecoilCallback(
30+
({ set }) =>
31+
async () => {
32+
if (!daily) return;
33+
const topology = await daily.getNetworkTopology();
34+
if (!topology || topology?.topology === 'none') return;
35+
set(topologyState, topology.topology);
36+
},
37+
[daily]
38+
);
39+
40+
useDailyEvent('joined-meeting', initTopology);
41+
useDailyEvent(
42+
'network-connection',
43+
useRecoilCallback(
44+
({ set }) =>
45+
(ev) => {
46+
switch (ev.event) {
47+
case 'connected':
48+
if (ev.type === 'peer-to-peer') set(topologyState, 'peer');
49+
if (ev.type === 'sfu') set(topologyState, 'sfu');
50+
break;
51+
}
52+
},
53+
[]
54+
)
55+
);
56+
useDailyEvent(
57+
'network-quality-change',
58+
useRecoilCallback(
59+
({ transact_UNSTABLE }) =>
60+
(ev) => {
61+
transact_UNSTABLE(({ set }) => {
62+
set(networkQualityState, (prevQuality) =>
63+
prevQuality !== ev.quality ? ev.quality : prevQuality
64+
);
65+
set(networkThresholdState, (prevThreshold) =>
66+
prevThreshold !== ev.threshold ? ev.threshold : prevThreshold
67+
);
68+
});
69+
},
70+
[]
71+
)
72+
);
73+
74+
useDailyEvent(
75+
'left-meeting',
76+
useRecoilCallback(
77+
({ transact_UNSTABLE }) =>
78+
() => {
79+
transact_UNSTABLE(({ reset }) => {
80+
reset(topologyState);
81+
reset(networkQualityState);
82+
reset(networkThresholdState);
83+
});
84+
},
85+
[]
86+
)
87+
);
88+
89+
useEffect(() => {
90+
if (!daily || topology !== 'none') return;
91+
initTopology();
92+
}, [daily, initTopology, topology]);
93+
94+
return <>{children}</>;
95+
};

src/DailyParticipants.tsx

Lines changed: 111 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import {
2-
DailyEventObject,
3-
DailyEventObjectWaitingParticipant,
42
DailyParticipant,
53
DailyParticipantsObject,
64
DailyWaitingParticipant,
@@ -10,8 +8,15 @@ import { atom, atomFamily, selector, useRecoilCallback } from 'recoil';
108

119
import { useDaily } from './hooks/useDaily';
1210
import { useDailyEvent } from './hooks/useDailyEvent';
11+
import {
12+
participantPropertyPathsState,
13+
participantPropertyState,
14+
} from './hooks/useParticipantProperty';
1315
import { useThrottledDailyEvent } from './hooks/useThrottledDailyEvent';
1416
import { RECOIL_PREFIX } from './lib/constants';
17+
import { customDeepEqual } from './lib/customDeepEqual';
18+
import { getParticipantPaths } from './utils/getParticipantPaths';
19+
import { resolveParticipantPaths } from './utils/resolveParticipantPaths';
1520

1621
/**
1722
* Extends DailyParticipant with convenient additional properties.
@@ -116,6 +121,23 @@ export const DailyParticipants: React.FC<React.PropsWithChildren<{}>> = ({
116121
set(participantIdsState, ids);
117122
participantsArray.forEach((p) => {
118123
set(participantState(p.session_id), p);
124+
const paths = getParticipantPaths(p);
125+
// Set list of property paths
126+
set(participantPropertyPathsState(p.session_id), paths);
127+
// Set all property path values
128+
paths.forEach((property) => {
129+
const [value] = resolveParticipantPaths(
130+
p as ExtendedDailyParticipant,
131+
[property]
132+
);
133+
set(
134+
participantPropertyState({
135+
id: p.session_id,
136+
property,
137+
}),
138+
value
139+
);
140+
});
119141
});
120142
setInitialized(true);
121143
});
@@ -178,16 +200,7 @@ export const DailyParticipants: React.FC<React.PropsWithChildren<{}>> = ({
178200
],
179201
useRecoilCallback(
180202
({ transact_UNSTABLE }) =>
181-
(
182-
evts: DailyEventObject<
183-
| 'active-speaker-change'
184-
| 'participant-joined'
185-
| 'participant-updated'
186-
| 'participant-left'
187-
| 'left-meeting'
188-
| 'call-instance-destroyed'
189-
>[]
190-
) => {
203+
(evts) => {
191204
transact_UNSTABLE(({ get, reset, set }) => {
192205
evts.forEach((ev) => {
193206
switch (ev.action) {
@@ -203,31 +216,94 @@ export const DailyParticipants: React.FC<React.PropsWithChildren<{}>> = ({
203216
});
204217
break;
205218
}
206-
case 'participant-joined':
219+
case 'participant-joined': {
220+
// Update list of ids
207221
set(participantIdsState, (prevIds) =>
208222
prevIds.includes(ev.participant.session_id)
209223
? prevIds
210224
: [...prevIds, ev.participant.session_id]
211225
);
226+
// Store entire object
212227
set(
213228
participantState(ev.participant.session_id),
214229
ev.participant
215230
);
231+
232+
const paths = getParticipantPaths(ev.participant);
233+
// Set list of property paths
234+
set(
235+
participantPropertyPathsState(ev.participant.session_id),
236+
paths
237+
);
238+
// Set all property path values
239+
paths.forEach((property) => {
240+
const [value] = resolveParticipantPaths(
241+
ev.participant as ExtendedDailyParticipant,
242+
[property]
243+
);
244+
set(
245+
participantPropertyState({
246+
id: ev.participant.session_id,
247+
property,
248+
}),
249+
value
250+
);
251+
});
216252
break;
217-
case 'participant-updated':
253+
}
254+
case 'participant-updated': {
255+
// Update entire object
218256
set(participantState(ev.participant.session_id), (prev) => ({
219257
...prev,
220258
...ev.participant,
221259
}));
260+
// Update local session_id
222261
if (ev.participant.local) {
223262
set(localIdState, (prevId) =>
224263
prevId !== ev.participant.session_id
225264
? ev.participant.session_id
226265
: prevId
227266
);
228267
}
268+
269+
const paths = getParticipantPaths(ev.participant);
270+
const oldPaths = get(
271+
participantPropertyPathsState(ev.participant.session_id)
272+
);
273+
// Set list of property paths
274+
set(
275+
participantPropertyPathsState(ev.participant.session_id),
276+
(prev) => (customDeepEqual(prev, paths) ? prev : paths)
277+
);
278+
// Reset old path values
279+
oldPaths
280+
.filter((p) => !paths.includes(p))
281+
.forEach((property) => {
282+
reset(
283+
participantPropertyState({
284+
id: ev.participant.session_id,
285+
property,
286+
})
287+
);
288+
});
289+
// Set all property path values
290+
paths.forEach((property) => {
291+
const [value] = resolveParticipantPaths(
292+
ev.participant as ExtendedDailyParticipant,
293+
[property]
294+
);
295+
set(
296+
participantPropertyState({
297+
id: ev.participant.session_id,
298+
property,
299+
}),
300+
(prev) => (customDeepEqual(prev, value) ? prev : value)
301+
);
302+
});
229303
break;
230-
case 'participant-left':
304+
}
305+
case 'participant-left': {
306+
// Remove from list of ids
231307
set(participantIdsState, (prevIds) =>
232308
prevIds.includes(ev.participant.session_id)
233309
? [
@@ -237,8 +313,27 @@ export const DailyParticipants: React.FC<React.PropsWithChildren<{}>> = ({
237313
]
238314
: prevIds
239315
);
316+
// Remove entire object
240317
reset(participantState(ev.participant.session_id));
318+
319+
const oldPaths = get(
320+
participantPropertyPathsState(ev.participant.session_id)
321+
);
322+
// Remove property path values
323+
oldPaths.forEach((property) => {
324+
reset(
325+
participantPropertyState({
326+
id: ev.participant.session_id,
327+
property,
328+
})
329+
);
330+
});
331+
// Remove all property paths
332+
reset(
333+
participantPropertyPathsState(ev.participant.session_id)
334+
);
241335
break;
336+
}
242337
/**
243338
* Reset stored participants, when meeting has ended.
244339
*/
@@ -266,7 +361,7 @@ export const DailyParticipants: React.FC<React.PropsWithChildren<{}>> = ({
266361
],
267362
useRecoilCallback(
268363
({ transact_UNSTABLE }) =>
269-
(evts: DailyEventObjectWaitingParticipant[]) => {
364+
(evts) => {
270365
transact_UNSTABLE(({ reset, set }) => {
271366
evts.forEach((ev) => {
272367
switch (ev.action) {

0 commit comments

Comments
 (0)