@stream-io/video-react-sdk 1.37.7 → 1.39.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/CHANGELOG.md +4409 -0
- package/dist/css/embedded.css +1 -0
- package/dist/css/embedded.css.map +1 -1
- package/dist/css/styles.css +1 -0
- package/dist/css/styles.css.map +1 -1
- package/dist/embedded.cjs.js +60 -39
- package/dist/embedded.cjs.js.map +1 -1
- package/dist/embedded.es.js +62 -41
- package/dist/embedded.es.js.map +1 -1
- package/dist/index.cjs.js +60 -40
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +62 -42
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/CallParticipantsList/CallParticipantListingItem.d.ts +1 -1
- package/dist/src/core/components/Audio/Audio.d.ts +1 -4
- package/dist/src/core/components/ParticipantView/ParticipantView.d.ts +1 -1
- package/dist/src/translations/index.d.ts +1 -0
- package/package.json +9 -7
- package/src/components/CallParticipantsList/CallParticipantListingItem.tsx +50 -46
- package/src/components/CallParticipantsList/CallParticipantsList.tsx +17 -6
- package/src/components/DeviceSettings/AudioVolumeIndicator.tsx +8 -4
- package/src/components/Search/SearchInput.tsx +4 -2
- package/src/core/components/Audio/Audio.tsx +4 -4
- package/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx +8 -0
- package/src/core/components/ParticipantView/ParticipantView.tsx +4 -3
- package/src/core/components/Video/BaseVideo.tsx +3 -1
- package/src/core/components/Video/Video.tsx +5 -2
- package/src/embedded/hooks/useWakeLock.ts +1 -0
- package/src/embedded/livestream/viewer/ViewerLobby.tsx +5 -6
- package/src/hooks/useDragToScroll.ts +9 -4
- package/src/hooks/useScrollPosition.ts +2 -2
- package/src/translations/en.json +1 -0
- package/src/wrappers/LivestreamPlayer/LivestreamPlayer.tsx +5 -6
package/dist/embedded.es.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { useState, useEffect, Fragment as Fragment$1, createContext, useContext, useCallback, useMemo, useRef, isValidElement, forwardRef, useLayoutEffect, lazy, Suspense } from 'react';
|
|
3
|
-
import { useCall, useCallStateHooks, useI18n, Restricted, useToggleCallRecording, useConnectedUser, useIsAudioConnecting, StreamCallProvider, StreamVideoProvider
|
|
2
|
+
import { memo, useState, useEffect, Fragment as Fragment$1, createContext, useContext, useCallback, useMemo, useRef, isValidElement, forwardRef, useLayoutEffect, lazy, Suspense } from 'react';
|
|
3
|
+
import { useCall, useCallStateHooks, useI18n, Restricted, useToggleCallRecording, useConnectedUser, useEffectEvent, useIsAudioConnecting, useIsVideoConnecting, StreamCallProvider, StreamVideoProvider } from '@stream-io/video-react-bindings';
|
|
4
4
|
import { hasAudio, hasScreenShareAudio, hasVideo, hasScreenShare, OwnCapability, Browsers, VisibilityState, hasPausedTrack, createSoundDetector, SfuModels, isPinned, name, NoiseCancellationSettingsModeEnum, CallingState, combineComparators, screenSharing, speakerLayoutSortPreset, paginatedLayoutSortPreset, CallTypes, defaultSortPreset, humanize, StreamVideoClient } from '@stream-io/video-client';
|
|
5
5
|
import { useFloating, offset, shift, flip, size, autoUpdate, FloatingOverlay, FloatingPortal, arrow, FloatingArrow, useListItem, useListNavigation, useTypeahead, useClick, useDismiss, useRole, useInteractions, FloatingFocusManager, FloatingList } from '@floating-ui/react';
|
|
6
6
|
import clsx from 'clsx';
|
|
7
7
|
|
|
8
|
-
const Audio = ({ participant, trackType = 'audioTrack', ...rest })
|
|
8
|
+
const Audio = memo(function Audio({ participant, trackType = 'audioTrack', ...rest }) {
|
|
9
9
|
const call = useCall();
|
|
10
10
|
const [audioElement, setAudioElement] = useState(null);
|
|
11
11
|
const { userId, sessionId } = participant;
|
|
@@ -18,7 +18,7 @@ const Audio = ({ participant, trackType = 'audioTrack', ...rest }) => {
|
|
|
18
18
|
};
|
|
19
19
|
}, [call, sessionId, audioElement, trackType]);
|
|
20
20
|
return (jsx("audio", { autoPlay: true, ...rest, ref: setAudioElement, "data-user-id": userId, "data-session-id": sessionId, "data-track-type": trackType }));
|
|
21
|
-
};
|
|
21
|
+
});
|
|
22
22
|
Audio.displayName = 'Audio';
|
|
23
23
|
|
|
24
24
|
const ParticipantsAudio = (props) => {
|
|
@@ -94,7 +94,7 @@ const useVerticalScrollPosition = (scrollElement, threshold = SCROLL_THRESHOLD)
|
|
|
94
94
|
};
|
|
95
95
|
const resizeObserver = new ResizeObserver(scrollHandler);
|
|
96
96
|
resizeObserver.observe(scrollElement);
|
|
97
|
-
scrollElement.addEventListener('scroll', scrollHandler);
|
|
97
|
+
scrollElement.addEventListener('scroll', scrollHandler, { passive: true });
|
|
98
98
|
return () => {
|
|
99
99
|
scrollElement.removeEventListener('scroll', scrollHandler);
|
|
100
100
|
resizeObserver.disconnect();
|
|
@@ -122,7 +122,7 @@ const useHorizontalScrollPosition = (scrollElement, threshold = SCROLL_THRESHOLD
|
|
|
122
122
|
};
|
|
123
123
|
const resizeObserver = new ResizeObserver(scrollHandler);
|
|
124
124
|
resizeObserver.observe(scrollElement);
|
|
125
|
-
scrollElement.addEventListener('scroll', scrollHandler);
|
|
125
|
+
scrollElement.addEventListener('scroll', scrollHandler, { passive: true });
|
|
126
126
|
return () => {
|
|
127
127
|
scrollElement.removeEventListener('scroll', scrollHandler);
|
|
128
128
|
resizeObserver.disconnect();
|
|
@@ -213,6 +213,7 @@ function useDeviceList(devices, selectedDeviceId) {
|
|
|
213
213
|
* @param options - Options for customizing the drag-to-scroll behavior.
|
|
214
214
|
*/
|
|
215
215
|
function useDragToScroll(element, options = {}) {
|
|
216
|
+
const { enabled, decay = 0.95, minVelocity = 0.5, dragThreshold = 5, } = options;
|
|
216
217
|
const stateRef = useRef({
|
|
217
218
|
isDragging: false,
|
|
218
219
|
isPointerActive: false,
|
|
@@ -225,9 +226,8 @@ function useDragToScroll(element, options = {}) {
|
|
|
225
226
|
startY: 0,
|
|
226
227
|
});
|
|
227
228
|
useEffect(() => {
|
|
228
|
-
if (!element || !
|
|
229
|
+
if (!element || !enabled)
|
|
229
230
|
return;
|
|
230
|
-
const { decay = 0.95, minVelocity = 0.5, dragThreshold = 5 } = options;
|
|
231
231
|
const state = stateRef.current;
|
|
232
232
|
const stopMomentum = () => {
|
|
233
233
|
if (state.rafId) {
|
|
@@ -311,7 +311,7 @@ function useDragToScroll(element, options = {}) {
|
|
|
311
311
|
window.removeEventListener('pointercancel', onPointerUpOrCancel);
|
|
312
312
|
stopMomentum();
|
|
313
313
|
};
|
|
314
|
-
}, [element,
|
|
314
|
+
}, [element, enabled, decay, minVelocity, dragThreshold]);
|
|
315
315
|
}
|
|
316
316
|
|
|
317
317
|
var MenuVisualType;
|
|
@@ -541,9 +541,10 @@ const BaseVideo = forwardRef(function BaseVideo({ stream, ...rest }, ref) {
|
|
|
541
541
|
if (stream === videoElement.srcObject)
|
|
542
542
|
return;
|
|
543
543
|
videoElement.srcObject = stream;
|
|
544
|
+
let timeoutId;
|
|
544
545
|
if (Browsers.isSafari() || Browsers.isFirefox()) {
|
|
545
546
|
// Firefox and Safari have some timing issue
|
|
546
|
-
setTimeout(() => {
|
|
547
|
+
timeoutId = setTimeout(() => {
|
|
547
548
|
videoElement.srcObject = stream;
|
|
548
549
|
videoElement.play().catch((e) => {
|
|
549
550
|
console.error(`Failed to play stream`, e);
|
|
@@ -551,6 +552,7 @@ const BaseVideo = forwardRef(function BaseVideo({ stream, ...rest }, ref) {
|
|
|
551
552
|
}, 0);
|
|
552
553
|
}
|
|
553
554
|
return () => {
|
|
555
|
+
clearTimeout(timeoutId);
|
|
554
556
|
videoElement.pause();
|
|
555
557
|
videoElement.srcObject = null;
|
|
556
558
|
};
|
|
@@ -587,6 +589,7 @@ const DefaultPictureInPicturePlaceholder = forwardRef(function DefaultPictureInP
|
|
|
587
589
|
return (jsx(BaseVideoPlaceholder, { ref: ref, ...props, children: t('Video is playing in a popup') }));
|
|
588
590
|
});
|
|
589
591
|
|
|
592
|
+
const ABSOLUTE_POSITION_STYLE = { position: 'absolute' };
|
|
590
593
|
const Video$1 = ({ enabled = true, mirror, trackType, participant, className, VideoPlaceholder = DefaultVideoPlaceholder, PictureInPicturePlaceholder = DefaultPictureInPicturePlaceholder, refs, ...rest }) => {
|
|
591
594
|
const { sessionId, videoStream, screenShareStream, viewportVisibilityState, isLocalParticipant, userId, } = participant;
|
|
592
595
|
const call = useCall();
|
|
@@ -659,7 +662,7 @@ const Video$1 = ({ enabled = true, mirror, trackType, participant, className, Vi
|
|
|
659
662
|
}), "data-user-id": userId, "data-session-id": sessionId, ref: (element) => {
|
|
660
663
|
setVideoElement(element);
|
|
661
664
|
refs?.setVideoElement?.(element);
|
|
662
|
-
} })), isPiP && PictureInPicturePlaceholder && (jsx(PictureInPicturePlaceholder, { style:
|
|
665
|
+
} })), isPiP && PictureInPicturePlaceholder && (jsx(PictureInPicturePlaceholder, { style: ABSOLUTE_POSITION_STYLE, participant: participant })), (hasNoVideoOrInvisible || isVideoPaused) && VideoPlaceholder && (jsx(VideoPlaceholder, { style: ABSOLUTE_POSITION_STYLE, participant: participant, ref: refs?.setVideoPlaceholderElement }))] }));
|
|
663
666
|
};
|
|
664
667
|
Video$1.displayName = 'Video';
|
|
665
668
|
|
|
@@ -1018,16 +1021,20 @@ const ScreenShareButton = (props) => {
|
|
|
1018
1021
|
const AudioVolumeIndicator = () => {
|
|
1019
1022
|
const { useMicrophoneState } = useCallStateHooks();
|
|
1020
1023
|
const { isEnabled, mediaStream } = useMicrophoneState();
|
|
1021
|
-
const
|
|
1024
|
+
const barRef = useRef(null);
|
|
1022
1025
|
useEffect(() => {
|
|
1023
1026
|
if (!isEnabled || !mediaStream)
|
|
1024
1027
|
return;
|
|
1025
|
-
const disposeSoundDetector = createSoundDetector(mediaStream, ({ audioLevel: al }) =>
|
|
1028
|
+
const disposeSoundDetector = createSoundDetector(mediaStream, ({ audioLevel: al }) => {
|
|
1029
|
+
if (barRef.current) {
|
|
1030
|
+
barRef.current.style.transform = `scaleX(${al / 100})`;
|
|
1031
|
+
}
|
|
1032
|
+
}, { detectionFrequencyInMs: 80, destroyStreamOnStop: false });
|
|
1026
1033
|
return () => {
|
|
1027
1034
|
disposeSoundDetector().catch(console.error);
|
|
1028
1035
|
};
|
|
1029
1036
|
}, [isEnabled, mediaStream]);
|
|
1030
|
-
return (jsxs("div", { className: "str-video__audio-volume-indicator", children: [jsx(Icon, { icon: isEnabled ? 'mic' : 'mic-off' }), jsx("div", { className: "str-video__audio-volume-indicator__bar", children: jsx("div", { className: "str-video__audio-volume-indicator__bar-value"
|
|
1037
|
+
return (jsxs("div", { className: "str-video__audio-volume-indicator", children: [jsx(Icon, { icon: isEnabled ? 'mic' : 'mic-off' }), jsx("div", { className: "str-video__audio-volume-indicator__bar", children: jsx("div", { ref: barRef, className: "str-video__audio-volume-indicator__bar-value" }) })] }));
|
|
1031
1038
|
};
|
|
1032
1039
|
|
|
1033
1040
|
const LEVEL_BARS = 5;
|
|
@@ -1201,7 +1208,7 @@ const SpeakerTest = (props) => {
|
|
|
1201
1208
|
const audioElementRef = useRef(null);
|
|
1202
1209
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
1203
1210
|
const { t } = useI18n();
|
|
1204
|
-
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.
|
|
1211
|
+
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.39.0"}/assets/piano.mp3`, } = props;
|
|
1205
1212
|
// Update audio output device when selection changes
|
|
1206
1213
|
useEffect(() => {
|
|
1207
1214
|
const audio = audioElementRef.current;
|
|
@@ -1500,13 +1507,14 @@ const CallParticipantListHeader = ({ onClose, }) => {
|
|
|
1500
1507
|
return (jsxs("div", { className: "str-video__participant-list-header", children: [jsxs("div", { className: "str-video__participant-list-header__title", children: [t('Participants'), ' ', jsxs("span", { className: "str-video__participant-list-header__title-count", children: ["[", participants.length, "]"] }), anonymousParticipantCount > 0 && (jsx("span", { className: "str-video__participant-list-header__title-anonymous", children: t('Anonymous', { count: anonymousParticipantCount }) }))] }), jsx(IconButton, { onClick: onClose, className: "str-video__participant-list-header__close-button", icon: "close" })] }));
|
|
1501
1508
|
};
|
|
1502
1509
|
|
|
1503
|
-
const CallParticipantListingItem = ({ participant, DisplayName = DefaultDisplayName, })
|
|
1510
|
+
const CallParticipantListingItem = memo(function CallParticipantListingItem({ participant, DisplayName = DefaultDisplayName, }) {
|
|
1504
1511
|
const isAudioOn = hasAudio(participant);
|
|
1505
1512
|
const isVideoOn = hasVideo(participant);
|
|
1506
1513
|
const isPinnedOn = isPinned(participant);
|
|
1507
1514
|
const { t } = useI18n();
|
|
1508
1515
|
return (jsxs("div", { className: "str-video__participant-listing-item", children: [jsx(Avatar, { name: participant.name, imageSrc: participant.image }), jsx(DisplayName, { participant: participant }), jsxs("div", { className: "str-video__participant-listing-item__media-indicator-group", children: [jsx(MediaIndicator, { title: isAudioOn ? t('Microphone on') : t('Microphone off'), className: clsx('str-video__participant-listing-item__icon', `str-video__participant-listing-item__icon-${isAudioOn ? 'mic' : 'mic-off'}`) }), jsx(MediaIndicator, { title: isVideoOn ? t('Camera on') : t('Camera off'), className: clsx('str-video__participant-listing-item__icon', `str-video__participant-listing-item__icon-${isVideoOn ? 'camera' : 'camera-off'}`) }), isPinnedOn && (jsx(MediaIndicator, { title: t('Pinned'), className: clsx('str-video__participant-listing-item__icon', 'str-video__participant-listing-item__icon-pinned') })), jsx(MenuToggle, { placement: "bottom-end", ToggleButton: ToggleButton$2, children: jsx(ParticipantViewContext.Provider, { value: { participant, trackType: 'none' }, children: jsx(ParticipantActionsContextMenu, {}) }) })] })] }));
|
|
1509
|
-
};
|
|
1516
|
+
});
|
|
1517
|
+
CallParticipantListingItem.displayName = 'CallParticipantListingItem';
|
|
1510
1518
|
const MediaIndicator = (props) => (jsx(WithTooltip, { ...props }));
|
|
1511
1519
|
const DefaultDisplayName = ({ participant }) => {
|
|
1512
1520
|
const connectedUser = useConnectedUser();
|
|
@@ -1538,18 +1546,19 @@ const EmptyParticipantSearchList = () => {
|
|
|
1538
1546
|
|
|
1539
1547
|
const SearchInput = ({ exitSearch, isActive, ...rest }) => {
|
|
1540
1548
|
const [inputElement, setInputElement] = useState(null);
|
|
1549
|
+
const onExitSearch = useEffectEvent(exitSearch);
|
|
1541
1550
|
useEffect(() => {
|
|
1542
1551
|
if (!inputElement)
|
|
1543
1552
|
return;
|
|
1544
1553
|
const handleKeyDown = (e) => {
|
|
1545
1554
|
if (e.key.toLowerCase() === 'escape')
|
|
1546
|
-
|
|
1555
|
+
onExitSearch();
|
|
1547
1556
|
};
|
|
1548
1557
|
inputElement.addEventListener('keydown', handleKeyDown);
|
|
1549
1558
|
return () => {
|
|
1550
1559
|
inputElement.removeEventListener('keydown', handleKeyDown);
|
|
1551
1560
|
};
|
|
1552
|
-
}, [
|
|
1561
|
+
}, [inputElement]);
|
|
1553
1562
|
return (jsxs("div", { className: clsx('str-video__search-input__container', {
|
|
1554
1563
|
'str-video__search-input__container--active': isActive,
|
|
1555
1564
|
}), children: [jsx("input", { placeholder: "Search", ...rest, ref: setInputElement }), isActive ? (jsx("button", { className: "str-video__search-input__clear-btn", onClick: exitSearch, children: jsx("span", { className: "str-video__search-input__icon--active" }) })) : (jsx("span", { className: "str-video__search-input__icon" }))] }));
|
|
@@ -1620,10 +1629,19 @@ const CallParticipantListContentHeader = ({ userListType, setUserListType, }) =>
|
|
|
1620
1629
|
const ActiveUsersSearchResults = ({ searchQuery, activeUsersSearchFn: activeUsersSearchFnFromProps, debounceSearchInterval, }) => {
|
|
1621
1630
|
const { useParticipants } = useCallStateHooks();
|
|
1622
1631
|
const participants = useParticipants({ sortBy: name });
|
|
1632
|
+
// cache: each distinct name is normalized once
|
|
1633
|
+
const normalizedNameCache = useRef(null);
|
|
1623
1634
|
const activeUsersSearchFn = useCallback(async (queryString) => {
|
|
1624
1635
|
const normalizedQuery = normalizeString(queryString);
|
|
1625
|
-
const
|
|
1626
|
-
return participants.filter((p) =>
|
|
1636
|
+
const cache = (normalizedNameCache.current ??= new Map());
|
|
1637
|
+
return participants.filter((p) => {
|
|
1638
|
+
let normalizedName = cache.get(p.name);
|
|
1639
|
+
if (normalizedName === undefined) {
|
|
1640
|
+
normalizedName = normalizeString(p.name);
|
|
1641
|
+
cache.set(p.name, normalizedName);
|
|
1642
|
+
}
|
|
1643
|
+
return normalizedName.includes(normalizedQuery);
|
|
1644
|
+
});
|
|
1627
1645
|
}, [participants]);
|
|
1628
1646
|
const { searchQueryInProgress, searchResults } = useSearch({
|
|
1629
1647
|
searchFn: activeUsersSearchFnFromProps ?? activeUsersSearchFn,
|
|
@@ -1636,8 +1654,8 @@ const BlockedUsersSearchResults = ({ blockedUsersSearchFn: blockedUsersSearchFnF
|
|
|
1636
1654
|
const { useCallBlockedUserIds } = useCallStateHooks();
|
|
1637
1655
|
const blockedUsers = useCallBlockedUserIds();
|
|
1638
1656
|
const blockedUsersSearchFn = useCallback(async (queryString) => {
|
|
1639
|
-
const
|
|
1640
|
-
return blockedUsers.filter((userId) => userId.
|
|
1657
|
+
const normalizedQuery = queryString.toLowerCase();
|
|
1658
|
+
return blockedUsers.filter((userId) => userId.toLowerCase().includes(normalizedQuery));
|
|
1641
1659
|
}, [blockedUsers]);
|
|
1642
1660
|
const { searchQueryInProgress, searchResults } = useSearch({
|
|
1643
1661
|
searchFn: blockedUsersSearchFnFromProps ?? blockedUsersSearchFn,
|
|
@@ -1898,7 +1916,8 @@ const ParticipantDetails = ({ indicatorsVisible = true, }) => {
|
|
|
1898
1916
|
const canUnpin = !!pin && pin.isLocalPin;
|
|
1899
1917
|
const isTrackPaused = trackType !== 'none' ? hasPausedTrack(participant, trackType) : false;
|
|
1900
1918
|
const isAudioConnecting = useIsAudioConnecting(participant);
|
|
1901
|
-
|
|
1919
|
+
const isVideoConnecting = useIsVideoConnecting(participant);
|
|
1920
|
+
return (jsxs(Fragment, { children: [jsx("div", { className: "str-video__participant-details", children: jsxs("div", { className: "str-video__participant-details__name", children: [name || userId, indicatorsVisible && isAudioConnecting && (jsx(LoadingIndicator, { className: "str-video__participant-details__name--audio-connecting", tooltip: t('Audio is connecting...') })), indicatorsVisible && !hasAudioTrack && (jsx("span", { className: "str-video__participant-details__name--audio-muted" })), indicatorsVisible && isVideoConnecting && (jsx(LoadingIndicator, { className: "str-video__participant-details__name--video-connecting", tooltip: t('Video is connecting...') })), indicatorsVisible && !hasVideoTrack && (jsx("span", { className: "str-video__participant-details__name--video-muted" })), indicatorsVisible && isTrackPaused && (jsx("span", { title: t('Video paused due to insufficient bandwidth'), className: "str-video__participant-details__name--track-paused" })), indicatorsVisible && pin && (jsx("span", { title: canUnpin ? t('Unpin') : t('Pinned'), onClick: canUnpin ? () => call?.unpin(sessionId) : undefined, className: "str-video__participant-details__name--pinned" })), indicatorsVisible && jsx(SpeechIndicator, {})] }) }), indicatorsVisible && (jsx(Notification, { isVisible: isLocalParticipant &&
|
|
1902
1921
|
connectionQuality === SfuModels.ConnectionQuality.POOR, message: t('Poor connection quality'), children: connectionQualityAsString && (jsx("span", { className: clsx('str-video__participant-details__connection-quality', `str-video__participant-details__connection-quality--${connectionQualityAsString}`), title: connectionQualityAsString })) }))] }));
|
|
1903
1922
|
};
|
|
1904
1923
|
const SpeechIndicator = () => {
|
|
@@ -1907,7 +1926,7 @@ const SpeechIndicator = () => {
|
|
|
1907
1926
|
return (jsxs("span", { className: clsx('str-video__speech-indicator', isSpeaking && 'str-video__speech-indicator--speaking', isDominantSpeaker && 'str-video__speech-indicator--dominant'), children: [jsx("span", { className: "str-video__speech-indicator__bar" }), jsx("span", { className: "str-video__speech-indicator__bar" }), jsx("span", { className: "str-video__speech-indicator__bar" })] }));
|
|
1908
1927
|
};
|
|
1909
1928
|
|
|
1910
|
-
const ParticipantView = forwardRef(function ParticipantView({ participant, trackType = 'videoTrack', mirror, muteAudio, refs: { setVideoElement, setVideoPlaceholderElement } = {}, className, VideoPlaceholder, PictureInPicturePlaceholder, ParticipantViewUI = DefaultParticipantViewUI, }, ref) {
|
|
1929
|
+
const ParticipantView = memo(forwardRef(function ParticipantView({ participant, trackType = 'videoTrack', mirror, muteAudio, refs: { setVideoElement, setVideoPlaceholderElement } = {}, className, VideoPlaceholder, PictureInPicturePlaceholder, ParticipantViewUI = DefaultParticipantViewUI, }, ref) {
|
|
1911
1930
|
const { isLocalParticipant, isSpeaking, isDominantSpeaker, sessionId } = participant;
|
|
1912
1931
|
const hasAudioTrack = hasAudio(participant);
|
|
1913
1932
|
const hasVideoTrack = hasVideo(participant);
|
|
@@ -1951,7 +1970,7 @@ const ParticipantView = forwardRef(function ParticipantView({ participant, track
|
|
|
1951
1970
|
}, className: clsx('str-video__participant-view', isDominantSpeaker && 'str-video__participant-view--dominant-speaker', isSpeaking && 'str-video__participant-view--speaking', !hasVideoTrack && 'str-video__participant-view--no-video', !hasAudioTrack && 'str-video__participant-view--no-audio', className), children: jsxs(ParticipantViewContext.Provider, { value: participantViewContextValue, children: [!isLocalParticipant && !muteAudio && (jsxs(Fragment, { children: [hasAudioTrack && (jsx(Audio, { participant: participant, trackType: "audioTrack" })), hasScreenShareAudioTrack && (jsx(Audio, { participant: participant, trackType: "screenShareAudioTrack" }))] })), jsx(Video$1, { VideoPlaceholder: VideoPlaceholder, PictureInPicturePlaceholder: PictureInPicturePlaceholder, participant: participant, trackType: trackType, refs: videoRefs, enabled: isLocalParticipant ||
|
|
1952
1971
|
trackType !== 'videoTrack' ||
|
|
1953
1972
|
isParticipantVideoEnabled(participant.sessionId), mirror: mirror, autoPlay: true }), isComponentType(ParticipantViewUI) ? (jsx(ParticipantViewUI, {})) : (ParticipantViewUI)] }) }));
|
|
1954
|
-
});
|
|
1973
|
+
}));
|
|
1955
1974
|
ParticipantView.displayName = 'ParticipantView';
|
|
1956
1975
|
|
|
1957
1976
|
// re-exporting the StreamCallProvider as StreamCall
|
|
@@ -2078,6 +2097,7 @@ var en = {
|
|
|
2078
2097
|
"Poor connection quality": "Poor connection quality. Please check your internet connection.",
|
|
2079
2098
|
"Video paused due to insufficient bandwidth": "Video paused due to insufficient bandwidth",
|
|
2080
2099
|
"Audio is connecting...": "Audio is connecting...",
|
|
2100
|
+
"Video is connecting...": "Video is connecting...",
|
|
2081
2101
|
Participants: Participants,
|
|
2082
2102
|
Anonymous: Anonymous,
|
|
2083
2103
|
"No participants found": "No participants found",
|
|
@@ -2168,20 +2188,20 @@ function checkConditions(obj, conditions) {
|
|
|
2168
2188
|
const eqOperatorValue = isDateString(eqOperator.$eq)
|
|
2169
2189
|
? new Date(eqOperator.$eq).getTime()
|
|
2170
2190
|
: eqOperator.$eq;
|
|
2171
|
-
match
|
|
2191
|
+
match &&= eqOperatorValue === value;
|
|
2172
2192
|
}
|
|
2173
2193
|
else if (maybeOperator && '$neq' in operator) {
|
|
2174
2194
|
const neqOperator = operator;
|
|
2175
|
-
match
|
|
2195
|
+
match &&= neqOperator.$neq !== value;
|
|
2176
2196
|
}
|
|
2177
2197
|
else if (maybeOperator && '$in' in operator) {
|
|
2178
2198
|
const inOperator = operator;
|
|
2179
|
-
match
|
|
2199
|
+
match &&= inOperator.$in.includes(value);
|
|
2180
2200
|
}
|
|
2181
2201
|
else if (maybeOperator && '$contains' in operator) {
|
|
2182
2202
|
if (Array.isArray(value)) {
|
|
2183
2203
|
const containsOperator = operator;
|
|
2184
|
-
match
|
|
2204
|
+
match &&= value.includes(containsOperator.$contains);
|
|
2185
2205
|
}
|
|
2186
2206
|
else {
|
|
2187
2207
|
match = false;
|
|
@@ -2192,35 +2212,35 @@ function checkConditions(obj, conditions) {
|
|
|
2192
2212
|
const gtOperatorValue = isDateString(gtOperator.$gt)
|
|
2193
2213
|
? new Date(gtOperator.$gt).getTime()
|
|
2194
2214
|
: gtOperator.$gt;
|
|
2195
|
-
match
|
|
2215
|
+
match &&= value > gtOperatorValue;
|
|
2196
2216
|
}
|
|
2197
2217
|
else if (maybeOperator && '$gte' in operator) {
|
|
2198
2218
|
const gteOperator = operator;
|
|
2199
2219
|
const gteOperatorValue = isDateString(gteOperator.$gte)
|
|
2200
2220
|
? new Date(gteOperator.$gte).getTime()
|
|
2201
2221
|
: gteOperator.$gte;
|
|
2202
|
-
match
|
|
2222
|
+
match &&= value >= gteOperatorValue;
|
|
2203
2223
|
}
|
|
2204
2224
|
else if (maybeOperator && '$lt' in operator) {
|
|
2205
2225
|
const ltOperator = operator;
|
|
2206
2226
|
const ltOperatorValue = isDateString(ltOperator.$lt)
|
|
2207
2227
|
? new Date(ltOperator.$lt).getTime()
|
|
2208
2228
|
: ltOperator.$lt;
|
|
2209
|
-
match
|
|
2229
|
+
match &&= value < ltOperatorValue;
|
|
2210
2230
|
}
|
|
2211
2231
|
else if (maybeOperator && '$lte' in operator) {
|
|
2212
2232
|
const lteOperator = operator;
|
|
2213
2233
|
const lteOperatorValue = isDateString(lteOperator.$lte)
|
|
2214
2234
|
? new Date(lteOperator.$lte).getTime()
|
|
2215
2235
|
: lteOperator.$lte;
|
|
2216
|
-
match
|
|
2236
|
+
match &&= value <= lteOperatorValue;
|
|
2217
2237
|
// } else if (maybeOperator && '$autocomplete' in operator) {
|
|
2218
2238
|
// TODO: regexp solution maybe?
|
|
2219
2239
|
// match &&= false;
|
|
2220
2240
|
}
|
|
2221
2241
|
else {
|
|
2222
2242
|
const eqValue = operator;
|
|
2223
|
-
match
|
|
2243
|
+
match &&= eqValue === value;
|
|
2224
2244
|
}
|
|
2225
2245
|
if (!match) {
|
|
2226
2246
|
return false;
|
|
@@ -3059,6 +3079,7 @@ const useWakeLock = () => {
|
|
|
3059
3079
|
if (interrupted)
|
|
3060
3080
|
return wls.release();
|
|
3061
3081
|
wakeLockSentinel = wls;
|
|
3082
|
+
return undefined;
|
|
3062
3083
|
})
|
|
3063
3084
|
.catch((error) => console.debug(`Couldn't setup WakeLock due to: ${error}`));
|
|
3064
3085
|
return () => {
|
|
@@ -3393,12 +3414,12 @@ const ViewerLobby = ({ onJoin }) => {
|
|
|
3393
3414
|
}
|
|
3394
3415
|
}, [canJoin, autoJoin, onJoin]);
|
|
3395
3416
|
useEffect(() => {
|
|
3396
|
-
if (
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3417
|
+
if (canJoinEarly)
|
|
3418
|
+
return;
|
|
3419
|
+
const handle = setInterval(() => {
|
|
3420
|
+
setCanJoinEarly(checkCanJoinEarly(startsAt, joinAheadTimeSeconds));
|
|
3421
|
+
}, 1000);
|
|
3422
|
+
return () => clearInterval(handle);
|
|
3402
3423
|
}, [canJoinEarly, startsAt, joinAheadTimeSeconds]);
|
|
3403
3424
|
useEffect(() => {
|
|
3404
3425
|
if (!startsAt || startsAtPassed)
|