@runwayml/avatars-react 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +198 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +201 -84
- package/dist/index.js.map +1 -1
- package/dist/styles.css +31 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -124,7 +124,7 @@ declare function AvatarCall({ avatarId, sessionId, sessionKey, credentials: dire
|
|
|
124
124
|
* Establishes a WebRTC connection and provides session state to children.
|
|
125
125
|
* This is a headless component that renders minimal DOM.
|
|
126
126
|
*/
|
|
127
|
-
declare function AvatarSession({ credentials, children, audio, video, onEnd, onError, __unstable_roomOptions, }: AvatarSessionProps): react_jsx_runtime.JSX.Element;
|
|
127
|
+
declare function AvatarSession({ credentials, children, audio: requestAudio, video: requestVideo, onEnd, onError, __unstable_roomOptions, }: AvatarSessionProps): react_jsx_runtime.JSX.Element;
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
130
|
* useAvatarStatus Hook
|
|
@@ -273,6 +273,10 @@ type UseAvatarSessionReturn = {
|
|
|
273
273
|
*/
|
|
274
274
|
declare function useAvatarSession(): UseAvatarSessionReturn;
|
|
275
275
|
|
|
276
|
+
/**
|
|
277
|
+
* Hook for local media controls (mic, camera, screen share).
|
|
278
|
+
* Returns safe defaults when called outside of LiveKitRoom context.
|
|
279
|
+
*/
|
|
276
280
|
declare function useLocalMedia(): UseLocalMediaReturn;
|
|
277
281
|
|
|
278
282
|
export { AvatarCall, type AvatarCallProps, AvatarSession, type AvatarStatus, AvatarVideo, type AvatarVideoStatus, ControlBar, ScreenShareVideo, type SessionCredentials, type SessionState, UserVideo, useAvatar, useAvatarSession, useAvatarStatus, useLocalMedia };
|
package/dist/index.d.ts
CHANGED
|
@@ -124,7 +124,7 @@ declare function AvatarCall({ avatarId, sessionId, sessionKey, credentials: dire
|
|
|
124
124
|
* Establishes a WebRTC connection and provides session state to children.
|
|
125
125
|
* This is a headless component that renders minimal DOM.
|
|
126
126
|
*/
|
|
127
|
-
declare function AvatarSession({ credentials, children, audio, video, onEnd, onError, __unstable_roomOptions, }: AvatarSessionProps): react_jsx_runtime.JSX.Element;
|
|
127
|
+
declare function AvatarSession({ credentials, children, audio: requestAudio, video: requestVideo, onEnd, onError, __unstable_roomOptions, }: AvatarSessionProps): react_jsx_runtime.JSX.Element;
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
130
|
* useAvatarStatus Hook
|
|
@@ -273,6 +273,10 @@ type UseAvatarSessionReturn = {
|
|
|
273
273
|
*/
|
|
274
274
|
declare function useAvatarSession(): UseAvatarSessionReturn;
|
|
275
275
|
|
|
276
|
+
/**
|
|
277
|
+
* Hook for local media controls (mic, camera, screen share).
|
|
278
|
+
* Returns safe defaults when called outside of LiveKitRoom context.
|
|
279
|
+
*/
|
|
276
280
|
declare function useLocalMedia(): UseLocalMediaReturn;
|
|
277
281
|
|
|
278
282
|
export { AvatarCall, type AvatarCallProps, AvatarSession, type AvatarStatus, AvatarVideo, type AvatarVideoStatus, ControlBar, ScreenShareVideo, type SessionCredentials, type SessionState, UserVideo, useAvatar, useAvatarSession, useAvatarStatus, useLocalMedia };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { LiveKitRoom, RoomAudioRenderer, useRoomContext, useConnectionState, useRemoteParticipants, useTracks, isTrackReference, VideoTrack, useLocalParticipant, useMediaDevices, TrackToggle } from '@livekit/components-react';
|
|
1
|
+
import { LiveKitRoom, RoomAudioRenderer, useRoomContext, useConnectionState, useMaybeRoomContext, useRemoteParticipants, useTracks, isTrackReference, VideoTrack, useLocalParticipant, useMediaDevices, TrackToggle } from '@livekit/components-react';
|
|
2
2
|
export { RoomAudioRenderer as AudioRenderer, VideoTrack } from '@livekit/components-react';
|
|
3
|
-
import { createContext, useRef, useCallback,
|
|
3
|
+
import { createContext, useRef, useCallback, useState, useEffect, useContext } from 'react';
|
|
4
4
|
import { Track, ConnectionState } from 'livekit-client';
|
|
5
|
-
import {
|
|
5
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
// src/api/config.ts
|
|
8
8
|
var DEFAULT_BASE_URL = "https://api.dev.runwayml.com";
|
|
@@ -26,44 +26,15 @@ async function consumeSession(options) {
|
|
|
26
26
|
}
|
|
27
27
|
return response.json();
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const suspender = promise.then(
|
|
36
|
-
(value) => {
|
|
37
|
-
status = "fulfilled";
|
|
38
|
-
result = value;
|
|
39
|
-
},
|
|
40
|
-
(err) => {
|
|
41
|
-
status = "rejected";
|
|
42
|
-
error = err;
|
|
43
|
-
}
|
|
44
|
-
);
|
|
45
|
-
return {
|
|
46
|
-
read() {
|
|
47
|
-
switch (status) {
|
|
48
|
-
case "pending":
|
|
49
|
-
throw suspender;
|
|
50
|
-
case "rejected":
|
|
51
|
-
throw error;
|
|
52
|
-
case "fulfilled":
|
|
53
|
-
return result;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
};
|
|
29
|
+
function useLatest(value) {
|
|
30
|
+
const ref = useRef(value);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
ref.current = value;
|
|
33
|
+
}, [value]);
|
|
34
|
+
return ref;
|
|
57
35
|
}
|
|
58
36
|
|
|
59
37
|
// src/hooks/useCredentials.ts
|
|
60
|
-
var resourceCache = /* @__PURE__ */ new Map();
|
|
61
|
-
function computeKey(options) {
|
|
62
|
-
if (options.credentials) return `direct:${options.credentials.sessionId}`;
|
|
63
|
-
if (options.sessionId && options.sessionKey)
|
|
64
|
-
return `session:${options.sessionId}`;
|
|
65
|
-
return `connect:${options.avatarId}:${options.connectUrl ?? "custom"}`;
|
|
66
|
-
}
|
|
67
38
|
async function fetchCredentials(options) {
|
|
68
39
|
const { avatarId, sessionId, sessionKey, connectUrl, connect, baseUrl } = options;
|
|
69
40
|
if (sessionId && sessionKey) {
|
|
@@ -94,28 +65,106 @@ async function fetchCredentials(options) {
|
|
|
94
65
|
);
|
|
95
66
|
}
|
|
96
67
|
function useCredentials(options) {
|
|
97
|
-
const
|
|
68
|
+
const {
|
|
69
|
+
credentials: directCredentials,
|
|
70
|
+
avatarId,
|
|
71
|
+
sessionId,
|
|
72
|
+
sessionKey,
|
|
73
|
+
connectUrl,
|
|
74
|
+
connect,
|
|
75
|
+
baseUrl,
|
|
76
|
+
onError
|
|
77
|
+
} = options;
|
|
78
|
+
const onErrorRef = useLatest(onError);
|
|
79
|
+
const [state, setState] = useState(() => {
|
|
80
|
+
if (directCredentials) {
|
|
81
|
+
return { status: "ready", credentials: directCredentials, error: null };
|
|
82
|
+
}
|
|
83
|
+
return { status: "loading", credentials: null, error: null };
|
|
84
|
+
});
|
|
98
85
|
useEffect(() => {
|
|
86
|
+
if (directCredentials) {
|
|
87
|
+
setState({
|
|
88
|
+
status: "ready",
|
|
89
|
+
credentials: directCredentials,
|
|
90
|
+
error: null
|
|
91
|
+
});
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
let cancelled = false;
|
|
95
|
+
setState({ status: "loading", credentials: null, error: null });
|
|
96
|
+
async function load() {
|
|
97
|
+
try {
|
|
98
|
+
const fetchOptions = {
|
|
99
|
+
avatarId,
|
|
100
|
+
sessionId,
|
|
101
|
+
sessionKey,
|
|
102
|
+
connectUrl,
|
|
103
|
+
connect,
|
|
104
|
+
baseUrl
|
|
105
|
+
};
|
|
106
|
+
const credentials = await fetchCredentials(fetchOptions);
|
|
107
|
+
if (!cancelled) {
|
|
108
|
+
setState({ status: "ready", credentials, error: null });
|
|
109
|
+
}
|
|
110
|
+
} catch (err) {
|
|
111
|
+
if (!cancelled) {
|
|
112
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
113
|
+
setState({ status: "error", credentials: null, error });
|
|
114
|
+
onErrorRef.current?.(error);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
load();
|
|
99
119
|
return () => {
|
|
100
|
-
|
|
120
|
+
cancelled = true;
|
|
101
121
|
};
|
|
102
|
-
}, [
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
122
|
+
}, [
|
|
123
|
+
directCredentials,
|
|
124
|
+
avatarId,
|
|
125
|
+
sessionId,
|
|
126
|
+
sessionKey,
|
|
127
|
+
connectUrl,
|
|
128
|
+
connect,
|
|
129
|
+
baseUrl
|
|
130
|
+
]);
|
|
131
|
+
return state;
|
|
132
|
+
}
|
|
133
|
+
async function hasMediaDevice(kind) {
|
|
134
|
+
try {
|
|
135
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
136
|
+
return devices.some((device) => device.kind === kind);
|
|
137
|
+
} catch {
|
|
138
|
+
return false;
|
|
110
139
|
}
|
|
111
|
-
return resource.read();
|
|
112
140
|
}
|
|
113
|
-
function
|
|
114
|
-
const
|
|
141
|
+
function useDeviceAvailability(requestAudio, requestVideo) {
|
|
142
|
+
const [state, setState] = useState({
|
|
143
|
+
audio: false,
|
|
144
|
+
video: false,
|
|
145
|
+
isChecking: true
|
|
146
|
+
});
|
|
115
147
|
useEffect(() => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
148
|
+
let cancelled = false;
|
|
149
|
+
async function checkDevices() {
|
|
150
|
+
const [hasAudio, hasVideo] = await Promise.all([
|
|
151
|
+
requestAudio ? hasMediaDevice("audioinput") : Promise.resolve(false),
|
|
152
|
+
requestVideo ? hasMediaDevice("videoinput") : Promise.resolve(false)
|
|
153
|
+
]);
|
|
154
|
+
if (!cancelled) {
|
|
155
|
+
setState({
|
|
156
|
+
audio: requestAudio && hasAudio,
|
|
157
|
+
video: requestVideo && hasVideo,
|
|
158
|
+
isChecking: false
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
checkDevices();
|
|
163
|
+
return () => {
|
|
164
|
+
cancelled = true;
|
|
165
|
+
};
|
|
166
|
+
}, [requestAudio, requestVideo]);
|
|
167
|
+
return state;
|
|
119
168
|
}
|
|
120
169
|
var DEFAULT_ROOM_OPTIONS = {
|
|
121
170
|
adaptiveStream: false,
|
|
@@ -141,13 +190,14 @@ var AvatarSessionContext = createContext(
|
|
|
141
190
|
function AvatarSession({
|
|
142
191
|
credentials,
|
|
143
192
|
children,
|
|
144
|
-
audio = true,
|
|
145
|
-
video = true,
|
|
193
|
+
audio: requestAudio = true,
|
|
194
|
+
video: requestVideo = true,
|
|
146
195
|
onEnd,
|
|
147
196
|
onError,
|
|
148
197
|
__unstable_roomOptions
|
|
149
198
|
}) {
|
|
150
199
|
const errorRef = useRef(null);
|
|
200
|
+
const deviceAvailability = useDeviceAvailability(requestAudio, requestVideo);
|
|
151
201
|
const handleError = (error) => {
|
|
152
202
|
errorRef.current = error;
|
|
153
203
|
onError?.(error);
|
|
@@ -156,14 +206,29 @@ function AvatarSession({
|
|
|
156
206
|
...DEFAULT_ROOM_OPTIONS,
|
|
157
207
|
...__unstable_roomOptions
|
|
158
208
|
};
|
|
209
|
+
if (deviceAvailability.isChecking) {
|
|
210
|
+
return /* @__PURE__ */ jsx(
|
|
211
|
+
AvatarSessionContext.Provider,
|
|
212
|
+
{
|
|
213
|
+
value: {
|
|
214
|
+
state: "connecting",
|
|
215
|
+
sessionId: credentials.sessionId,
|
|
216
|
+
error: null,
|
|
217
|
+
end: async () => {
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
children
|
|
221
|
+
}
|
|
222
|
+
);
|
|
223
|
+
}
|
|
159
224
|
return /* @__PURE__ */ jsxs(
|
|
160
225
|
LiveKitRoom,
|
|
161
226
|
{
|
|
162
227
|
serverUrl: credentials.serverUrl,
|
|
163
228
|
token: credentials.token,
|
|
164
229
|
connect: true,
|
|
165
|
-
audio,
|
|
166
|
-
video,
|
|
230
|
+
audio: deviceAvailability.audio,
|
|
231
|
+
video: deviceAvailability.video,
|
|
167
232
|
onDisconnected: () => onEnd?.(),
|
|
168
233
|
onError: handleError,
|
|
169
234
|
options: roomOptions,
|
|
@@ -222,14 +287,34 @@ function useAvatarSessionContext() {
|
|
|
222
287
|
}
|
|
223
288
|
return context;
|
|
224
289
|
}
|
|
290
|
+
function LoadingSessionProvider({
|
|
291
|
+
state,
|
|
292
|
+
error,
|
|
293
|
+
children
|
|
294
|
+
}) {
|
|
295
|
+
const contextValue = {
|
|
296
|
+
state,
|
|
297
|
+
sessionId: "",
|
|
298
|
+
error,
|
|
299
|
+
end: async () => {
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
return /* @__PURE__ */ jsx(AvatarSessionContext.Provider, { value: contextValue, children });
|
|
303
|
+
}
|
|
225
304
|
function useAvatar() {
|
|
226
|
-
const
|
|
305
|
+
const room = useMaybeRoomContext();
|
|
306
|
+
const hasRoomContext = room !== void 0;
|
|
307
|
+
const remoteParticipants = useRemoteParticipants({ room });
|
|
227
308
|
const avatarParticipant = remoteParticipants[0] ?? null;
|
|
228
309
|
const videoTracks = useTracks(
|
|
229
310
|
[{ source: Track.Source.Camera, withPlaceholder: true }],
|
|
230
|
-
{
|
|
311
|
+
{
|
|
312
|
+
onlySubscribed: true,
|
|
313
|
+
updateOnlyOn: [],
|
|
314
|
+
room: hasRoomContext ? room : void 0
|
|
315
|
+
}
|
|
231
316
|
).filter((ref) => !ref.participant.isLocal);
|
|
232
|
-
const videoTrackRef = videoTracks[0] ?? null;
|
|
317
|
+
const videoTrackRef = hasRoomContext ? videoTracks[0] ?? null : null;
|
|
233
318
|
const hasVideo = videoTrackRef !== null && isTrackReference(videoTrackRef);
|
|
234
319
|
return {
|
|
235
320
|
participant: avatarParticipant,
|
|
@@ -282,37 +367,46 @@ function AvatarVideo({ children, ...props }) {
|
|
|
282
367
|
);
|
|
283
368
|
}
|
|
284
369
|
function useLocalMedia() {
|
|
285
|
-
const
|
|
370
|
+
const room = useMaybeRoomContext();
|
|
371
|
+
const hasRoomContext = room !== void 0;
|
|
372
|
+
const { localParticipant } = useLocalParticipant({ room });
|
|
286
373
|
const audioDevices = useMediaDevices({ kind: "audioinput" });
|
|
287
374
|
const videoDevices = useMediaDevices({ kind: "videoinput" });
|
|
288
|
-
const hasMic = audioDevices
|
|
289
|
-
const hasCamera = videoDevices
|
|
375
|
+
const hasMic = audioDevices?.length > 0;
|
|
376
|
+
const hasCamera = videoDevices?.length > 0;
|
|
290
377
|
const isMicEnabled = localParticipant?.isMicrophoneEnabled ?? false;
|
|
291
378
|
const isCameraEnabled = localParticipant?.isCameraEnabled ?? false;
|
|
292
379
|
const isScreenShareEnabled = localParticipant?.isScreenShareEnabled ?? false;
|
|
293
380
|
const isMicEnabledRef = useLatest(isMicEnabled);
|
|
294
381
|
const isCameraEnabledRef = useLatest(isCameraEnabled);
|
|
295
382
|
const isScreenShareEnabledRef = useLatest(isScreenShareEnabled);
|
|
383
|
+
const hasMicRef = useLatest(hasMic);
|
|
384
|
+
const hasCameraRef = useLatest(hasCamera);
|
|
296
385
|
const toggleMic = useCallback(() => {
|
|
297
|
-
|
|
298
|
-
|
|
386
|
+
if (hasMicRef.current || isMicEnabledRef.current) {
|
|
387
|
+
localParticipant?.setMicrophoneEnabled(!isMicEnabledRef.current);
|
|
388
|
+
}
|
|
389
|
+
}, [localParticipant]);
|
|
299
390
|
const toggleCamera = useCallback(() => {
|
|
300
|
-
|
|
301
|
-
|
|
391
|
+
if (hasCameraRef.current || isCameraEnabledRef.current) {
|
|
392
|
+
localParticipant?.setCameraEnabled(!isCameraEnabledRef.current);
|
|
393
|
+
}
|
|
394
|
+
}, [localParticipant]);
|
|
302
395
|
const toggleScreenShare = useCallback(() => {
|
|
303
396
|
localParticipant?.setScreenShareEnabled(!isScreenShareEnabledRef.current);
|
|
304
|
-
}, [localParticipant
|
|
397
|
+
}, [localParticipant]);
|
|
305
398
|
const tracks = useTracks(
|
|
306
399
|
[{ source: Track.Source.Camera, withPlaceholder: true }],
|
|
307
400
|
{
|
|
308
401
|
onlySubscribed: false,
|
|
309
|
-
updateOnlyOn: []
|
|
402
|
+
updateOnlyOn: [],
|
|
403
|
+
room: hasRoomContext ? room : void 0
|
|
310
404
|
}
|
|
311
405
|
);
|
|
312
406
|
const localIdentity = localParticipant?.identity;
|
|
313
|
-
const localVideoTrackRef = tracks.find(
|
|
407
|
+
const localVideoTrackRef = hasRoomContext ? tracks.find(
|
|
314
408
|
(trackRef) => trackRef.participant.identity === localIdentity && trackRef.source === Track.Source.Camera
|
|
315
|
-
) ?? null;
|
|
409
|
+
) ?? null : null;
|
|
316
410
|
return {
|
|
317
411
|
hasMic,
|
|
318
412
|
hasCamera,
|
|
@@ -516,19 +610,44 @@ function AvatarCall({
|
|
|
516
610
|
...props
|
|
517
611
|
}) {
|
|
518
612
|
const onErrorRef = useLatest(onError);
|
|
519
|
-
const
|
|
613
|
+
const credentialsState = useCredentials({
|
|
520
614
|
avatarId,
|
|
521
615
|
sessionId,
|
|
522
616
|
sessionKey,
|
|
523
617
|
credentials: directCredentials,
|
|
524
618
|
connectUrl,
|
|
525
619
|
connect,
|
|
526
|
-
baseUrl
|
|
620
|
+
baseUrl,
|
|
621
|
+
onError: (err) => onErrorRef.current?.(err)
|
|
527
622
|
});
|
|
528
623
|
const handleSessionError = (err) => {
|
|
529
624
|
onErrorRef.current?.(err);
|
|
530
625
|
};
|
|
531
626
|
const backgroundStyle = avatarImageUrl ? { "--avatar-image": `url(${avatarImageUrl})` } : void 0;
|
|
627
|
+
const defaultChildren = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
628
|
+
/* @__PURE__ */ jsx(AvatarVideo, {}),
|
|
629
|
+
/* @__PURE__ */ jsx(UserVideo, {}),
|
|
630
|
+
/* @__PURE__ */ jsx(ControlBar, {})
|
|
631
|
+
] });
|
|
632
|
+
if (credentialsState.status !== "ready") {
|
|
633
|
+
return /* @__PURE__ */ jsx(
|
|
634
|
+
"div",
|
|
635
|
+
{
|
|
636
|
+
...props,
|
|
637
|
+
"data-avatar-call": "",
|
|
638
|
+
"data-avatar-id": avatarId,
|
|
639
|
+
style: { ...props.style, ...backgroundStyle },
|
|
640
|
+
children: /* @__PURE__ */ jsx(
|
|
641
|
+
LoadingSessionProvider,
|
|
642
|
+
{
|
|
643
|
+
state: credentialsState.status === "error" ? "error" : "connecting",
|
|
644
|
+
error: credentialsState.error,
|
|
645
|
+
children: children ?? defaultChildren
|
|
646
|
+
}
|
|
647
|
+
)
|
|
648
|
+
}
|
|
649
|
+
);
|
|
650
|
+
}
|
|
532
651
|
return /* @__PURE__ */ jsx(
|
|
533
652
|
"div",
|
|
534
653
|
{
|
|
@@ -539,15 +658,11 @@ function AvatarCall({
|
|
|
539
658
|
children: /* @__PURE__ */ jsx(
|
|
540
659
|
AvatarSession,
|
|
541
660
|
{
|
|
542
|
-
credentials,
|
|
661
|
+
credentials: credentialsState.credentials,
|
|
543
662
|
onEnd,
|
|
544
663
|
onError: handleSessionError,
|
|
545
664
|
__unstable_roomOptions,
|
|
546
|
-
children: children ??
|
|
547
|
-
/* @__PURE__ */ jsx(AvatarVideo, {}),
|
|
548
|
-
/* @__PURE__ */ jsx(UserVideo, {}),
|
|
549
|
-
/* @__PURE__ */ jsx(ControlBar, {})
|
|
550
|
-
] })
|
|
665
|
+
children: children ?? defaultChildren
|
|
551
666
|
}
|
|
552
667
|
)
|
|
553
668
|
}
|
|
@@ -557,15 +672,17 @@ function ScreenShareVideo({
|
|
|
557
672
|
children,
|
|
558
673
|
...props
|
|
559
674
|
}) {
|
|
560
|
-
const
|
|
675
|
+
const room = useMaybeRoomContext();
|
|
676
|
+
const hasRoomContext = room !== void 0;
|
|
677
|
+
const { localParticipant } = useLocalParticipant({ room });
|
|
561
678
|
const tracks = useTracks(
|
|
562
679
|
[{ source: Track.Source.ScreenShare, withPlaceholder: false }],
|
|
563
|
-
{ onlySubscribed: false }
|
|
680
|
+
{ onlySubscribed: false, room: hasRoomContext ? room : void 0 }
|
|
564
681
|
);
|
|
565
682
|
const localIdentity = localParticipant?.identity;
|
|
566
|
-
const screenShareTrackRef = tracks.find(
|
|
683
|
+
const screenShareTrackRef = hasRoomContext ? tracks.find(
|
|
567
684
|
(trackRef) => trackRef.participant.identity === localIdentity && trackRef.source === Track.Source.ScreenShare
|
|
568
|
-
) ?? null;
|
|
685
|
+
) ?? null : null;
|
|
569
686
|
const isSharing = screenShareTrackRef !== null && isTrackReference(screenShareTrackRef);
|
|
570
687
|
const state = {
|
|
571
688
|
isSharing,
|