@stream-io/video-react-sdk 1.33.3 → 1.34.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 +26 -0
- package/dist/css/embedded.css +5 -0
- package/dist/css/embedded.css.map +1 -1
- package/dist/css/styles.css +5 -0
- package/dist/css/styles.css.map +1 -1
- package/dist/embedded.cjs.js +38 -5
- package/dist/embedded.cjs.js.map +1 -1
- package/dist/embedded.es.js +38 -5
- package/dist/embedded.es.js.map +1 -1
- package/dist/index.cjs.js +40 -7
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +40 -7
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/NoiseCancellation/NoiseCancellationProvider.d.ts +4 -0
- package/dist/src/translations/index.d.ts +1 -0
- package/package.json +5 -5
- package/src/components/CallControls/CallControls.tsx +4 -9
- package/src/components/NoiseCancellation/NoiseCancellationProvider.tsx +15 -3
- package/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx +44 -4
- package/src/translations/en.json +1 -0
package/dist/index.cjs.js
CHANGED
|
@@ -1347,7 +1347,7 @@ const SpeakerTest = (props) => {
|
|
|
1347
1347
|
const audioElementRef = react.useRef(null);
|
|
1348
1348
|
const [isPlaying, setIsPlaying] = react.useState(false);
|
|
1349
1349
|
const { t } = videoReactBindings.useI18n();
|
|
1350
|
-
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.
|
|
1350
|
+
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.34.0"}/assets/piano.mp3`, } = props;
|
|
1351
1351
|
// Update audio output device when selection changes
|
|
1352
1352
|
react.useEffect(() => {
|
|
1353
1353
|
const audio = audioElementRef.current;
|
|
@@ -1582,7 +1582,7 @@ const CancelCallButton = ({ disabled, caption, onClick, onLeave, }) => {
|
|
|
1582
1582
|
return (jsxRuntime.jsx(IconButton, { disabled: disabled, icon: "call-end", variant: "danger", title: caption ?? t('Leave call'), "data-testid": "cancel-call-button", onClick: handleClick }));
|
|
1583
1583
|
};
|
|
1584
1584
|
|
|
1585
|
-
const CallControls = ({ onLeave }) => (jsxRuntime.jsxs("div", { className: "str-video__call-controls", children: [jsxRuntime.jsx(videoReactBindings.Restricted, { requiredGrants: [videoClient.OwnCapability.SEND_AUDIO], children: jsxRuntime.jsx(
|
|
1585
|
+
const CallControls = ({ onLeave }) => (jsxRuntime.jsxs("div", { className: "str-video__call-controls", children: [jsxRuntime.jsx(videoReactBindings.Restricted, { requiredGrants: [videoClient.OwnCapability.SEND_AUDIO], children: jsxRuntime.jsx(SpeakingWhileMutedNotification, { children: jsxRuntime.jsx(ToggleAudioPublishingButton, {}) }) }), jsxRuntime.jsx(videoReactBindings.Restricted, { requiredGrants: [videoClient.OwnCapability.SEND_VIDEO], children: jsxRuntime.jsx(ToggleVideoPublishingButton, {}) }), jsxRuntime.jsx(videoReactBindings.Restricted, { requiredGrants: [videoClient.OwnCapability.CREATE_REACTION], children: jsxRuntime.jsx(ReactionsButton, {}) }), jsxRuntime.jsx(videoReactBindings.Restricted, { requiredGrants: [videoClient.OwnCapability.SCREENSHARE], children: jsxRuntime.jsx(ScreenShareButton, {}) }), jsxRuntime.jsx(videoReactBindings.Restricted, { requiredGrants: [
|
|
1586
1586
|
videoClient.OwnCapability.START_RECORD_CALL,
|
|
1587
1587
|
videoClient.OwnCapability.STOP_RECORD_CALL,
|
|
1588
1588
|
], children: jsxRuntime.jsx(RecordCallButton, {}) }), jsxRuntime.jsx(CancelCallButton, { onLeave: onLeave })] }));
|
|
@@ -2024,6 +2024,7 @@ const NoiseCancellationProvider = (props) => {
|
|
|
2024
2024
|
}, [noiseCancellation]);
|
|
2025
2025
|
const isSupported = isSupportedByBrowser && hasCapability && noiseCancellationAllowed;
|
|
2026
2026
|
const [isEnabled, setIsEnabled] = react.useState(false);
|
|
2027
|
+
const [isReady, setIsReady] = react.useState(false);
|
|
2027
2028
|
const deinit = react.useRef(undefined);
|
|
2028
2029
|
react.useEffect(() => {
|
|
2029
2030
|
if (!call || !isSupported)
|
|
@@ -2032,17 +2033,23 @@ const NoiseCancellationProvider = (props) => {
|
|
|
2032
2033
|
const unsubscribe = noiseCancellation.on('change', (v) => setIsEnabled(v));
|
|
2033
2034
|
const init = (deinit.current || Promise.resolve())
|
|
2034
2035
|
.then(() => noiseCancellation.init({ tracer: call.tracer }))
|
|
2035
|
-
.then(() =>
|
|
2036
|
+
.then(() => {
|
|
2037
|
+
setIsReady(true);
|
|
2038
|
+
return call.microphone.enableNoiseCancellation(noiseCancellation);
|
|
2039
|
+
})
|
|
2036
2040
|
.catch((e) => console.error(`Can't initialize noise cancellation`, e));
|
|
2037
2041
|
return () => {
|
|
2038
2042
|
deinit.current = init
|
|
2039
2043
|
.then(() => call.microphone.disableNoiseCancellation())
|
|
2040
2044
|
.then(() => noiseCancellation.dispose())
|
|
2041
|
-
.then(() => unsubscribe())
|
|
2045
|
+
.then(() => unsubscribe())
|
|
2046
|
+
.catch((e) => console.error("Can't clean up noise cancellation", e))
|
|
2047
|
+
.finally(() => setIsReady(false));
|
|
2042
2048
|
};
|
|
2043
2049
|
}, [call, isSupported, noiseCancellation]);
|
|
2044
2050
|
const contextValue = react.useMemo(() => ({
|
|
2045
2051
|
isSupported,
|
|
2052
|
+
isReady,
|
|
2046
2053
|
isEnabled,
|
|
2047
2054
|
setSuppressionLevel: (level) => {
|
|
2048
2055
|
if (!noiseCancellation)
|
|
@@ -2066,7 +2073,7 @@ const NoiseCancellationProvider = (props) => {
|
|
|
2066
2073
|
});
|
|
2067
2074
|
}
|
|
2068
2075
|
},
|
|
2069
|
-
}), [isEnabled, isSupported, noiseCancellation]);
|
|
2076
|
+
}), [isEnabled, isReady, isSupported, noiseCancellation]);
|
|
2070
2077
|
return (jsxRuntime.jsx(NoiseCancellationContext.Provider, { value: contextValue, children: children }));
|
|
2071
2078
|
};
|
|
2072
2079
|
|
|
@@ -2281,7 +2288,9 @@ const ParticipantDetails = ({ indicatorsVisible = true, }) => {
|
|
|
2281
2288
|
const hasVideoTrack = videoClient.hasVideo(participant);
|
|
2282
2289
|
const canUnpin = !!pin && pin.isLocalPin;
|
|
2283
2290
|
const isTrackPaused = trackType !== 'none' ? videoClient.hasPausedTrack(participant, trackType) : false;
|
|
2284
|
-
|
|
2291
|
+
const isAudioTrackUnmuted = useIsTrackUnmuted(participant);
|
|
2292
|
+
const isAudioConnecting = hasAudioTrack && !isAudioTrackUnmuted;
|
|
2293
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "str-video__participant-details", children: jsxRuntime.jsxs("div", { className: "str-video__participant-details__name", children: [name || userId, indicatorsVisible && isAudioConnecting && (jsxRuntime.jsx(LoadingIndicator, { className: "str-video__participant-details__name--audio-connecting", tooltip: t('Audio is connecting...') })), indicatorsVisible && !hasAudioTrack && (jsxRuntime.jsx("span", { className: "str-video__participant-details__name--audio-muted" })), indicatorsVisible && !hasVideoTrack && (jsxRuntime.jsx("span", { className: "str-video__participant-details__name--video-muted" })), indicatorsVisible && isTrackPaused && (jsxRuntime.jsx("span", { title: t('Video paused due to insufficient bandwidth'), className: "str-video__participant-details__name--track-paused" })), indicatorsVisible && canUnpin && (
|
|
2285
2294
|
// TODO: remove this monstrosity once we have a proper design
|
|
2286
2295
|
jsxRuntime.jsx("span", { title: t('Unpin'), onClick: () => call?.unpin(sessionId), className: "str-video__participant-details__name--pinned" })), indicatorsVisible && jsxRuntime.jsx(SpeechIndicator, {})] }) }), indicatorsVisible && (jsxRuntime.jsx(Notification, { isVisible: isLocalParticipant &&
|
|
2287
2296
|
connectionQuality === videoClient.SfuModels.ConnectionQuality.POOR, message: t('Poor connection quality'), children: connectionQualityAsString && (jsxRuntime.jsx("span", { className: clsx('str-video__participant-details__connection-quality', `str-video__participant-details__connection-quality--${connectionQualityAsString}`), title: connectionQualityAsString })) }))] }));
|
|
@@ -2291,6 +2300,29 @@ const SpeechIndicator = () => {
|
|
|
2291
2300
|
const { isSpeaking, isDominantSpeaker } = participant;
|
|
2292
2301
|
return (jsxRuntime.jsxs("span", { className: clsx('str-video__speech-indicator', isSpeaking && 'str-video__speech-indicator--speaking', isDominantSpeaker && 'str-video__speech-indicator--dominant'), children: [jsxRuntime.jsx("span", { className: "str-video__speech-indicator__bar" }), jsxRuntime.jsx("span", { className: "str-video__speech-indicator__bar" }), jsxRuntime.jsx("span", { className: "str-video__speech-indicator__bar" })] }));
|
|
2293
2302
|
};
|
|
2303
|
+
const useIsTrackUnmuted = (participant) => {
|
|
2304
|
+
const audioStream = participant.audioStream;
|
|
2305
|
+
const [unmuted, setUnmuted] = react.useState(() => {
|
|
2306
|
+
const track = audioStream?.getAudioTracks()[0];
|
|
2307
|
+
return !!track && !track.muted;
|
|
2308
|
+
});
|
|
2309
|
+
react.useEffect(() => {
|
|
2310
|
+
const track = audioStream?.getAudioTracks()[0];
|
|
2311
|
+
if (!track)
|
|
2312
|
+
return;
|
|
2313
|
+
setUnmuted(!track.muted);
|
|
2314
|
+
const handler = () => {
|
|
2315
|
+
setUnmuted(!track.muted);
|
|
2316
|
+
};
|
|
2317
|
+
track.addEventListener('mute', handler);
|
|
2318
|
+
track.addEventListener('unmute', handler);
|
|
2319
|
+
return () => {
|
|
2320
|
+
track.removeEventListener('mute', handler);
|
|
2321
|
+
track.removeEventListener('unmute', handler);
|
|
2322
|
+
};
|
|
2323
|
+
}, [audioStream]);
|
|
2324
|
+
return unmuted;
|
|
2325
|
+
};
|
|
2294
2326
|
|
|
2295
2327
|
const ParticipantView = react.forwardRef(function ParticipantView({ participant, trackType = 'videoTrack', mirror, muteAudio, refs: { setVideoElement, setVideoPlaceholderElement } = {}, className, VideoPlaceholder, PictureInPicturePlaceholder, ParticipantViewUI = DefaultParticipantViewUI, }, ref) {
|
|
2296
2328
|
const { isLocalParticipant, isSpeaking, isDominantSpeaker, sessionId } = participant;
|
|
@@ -2461,6 +2493,7 @@ var en = {
|
|
|
2461
2493
|
"Dominant Speaker": "Dominant Speaker",
|
|
2462
2494
|
"Poor connection quality": "Poor connection quality. Please check your internet connection.",
|
|
2463
2495
|
"Video paused due to insufficient bandwidth": "Video paused due to insufficient bandwidth",
|
|
2496
|
+
"Audio is connecting...": "Audio is connecting...",
|
|
2464
2497
|
Participants: Participants,
|
|
2465
2498
|
Anonymous: Anonymous,
|
|
2466
2499
|
"No participants found": "No participants found",
|
|
@@ -3137,7 +3170,7 @@ const checkCanJoinEarly = (startsAt, joinAheadTimeSeconds) => {
|
|
|
3137
3170
|
return Date.now() >= +startsAt - (joinAheadTimeSeconds ?? 0) * 1000;
|
|
3138
3171
|
};
|
|
3139
3172
|
|
|
3140
|
-
const [major, minor, patch] = ("1.
|
|
3173
|
+
const [major, minor, patch] = ("1.34.0").split('.');
|
|
3141
3174
|
videoClient.setSdkInfo({
|
|
3142
3175
|
type: videoClient.SfuModels.SdkType.REACT,
|
|
3143
3176
|
major,
|