@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/embedded.cjs.js
CHANGED
|
@@ -1153,7 +1153,7 @@ const SpeakerTest = (props) => {
|
|
|
1153
1153
|
const audioElementRef = react.useRef(null);
|
|
1154
1154
|
const [isPlaying, setIsPlaying] = react.useState(false);
|
|
1155
1155
|
const { t } = videoReactBindings.useI18n();
|
|
1156
|
-
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.
|
|
1156
|
+
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.34.0"}/assets/piano.mp3`, } = props;
|
|
1157
1157
|
// Update audio output device when selection changes
|
|
1158
1158
|
react.useEffect(() => {
|
|
1159
1159
|
const audio = audioElementRef.current;
|
|
@@ -1572,6 +1572,7 @@ const NoiseCancellationProvider = (props) => {
|
|
|
1572
1572
|
}, [noiseCancellation]);
|
|
1573
1573
|
const isSupported = isSupportedByBrowser && hasCapability && noiseCancellationAllowed;
|
|
1574
1574
|
const [isEnabled, setIsEnabled] = react.useState(false);
|
|
1575
|
+
const [isReady, setIsReady] = react.useState(false);
|
|
1575
1576
|
const deinit = react.useRef(undefined);
|
|
1576
1577
|
react.useEffect(() => {
|
|
1577
1578
|
if (!call || !isSupported)
|
|
@@ -1580,17 +1581,23 @@ const NoiseCancellationProvider = (props) => {
|
|
|
1580
1581
|
const unsubscribe = noiseCancellation.on('change', (v) => setIsEnabled(v));
|
|
1581
1582
|
const init = (deinit.current || Promise.resolve())
|
|
1582
1583
|
.then(() => noiseCancellation.init({ tracer: call.tracer }))
|
|
1583
|
-
.then(() =>
|
|
1584
|
+
.then(() => {
|
|
1585
|
+
setIsReady(true);
|
|
1586
|
+
return call.microphone.enableNoiseCancellation(noiseCancellation);
|
|
1587
|
+
})
|
|
1584
1588
|
.catch((e) => console.error(`Can't initialize noise cancellation`, e));
|
|
1585
1589
|
return () => {
|
|
1586
1590
|
deinit.current = init
|
|
1587
1591
|
.then(() => call.microphone.disableNoiseCancellation())
|
|
1588
1592
|
.then(() => noiseCancellation.dispose())
|
|
1589
|
-
.then(() => unsubscribe())
|
|
1593
|
+
.then(() => unsubscribe())
|
|
1594
|
+
.catch((e) => console.error("Can't clean up noise cancellation", e))
|
|
1595
|
+
.finally(() => setIsReady(false));
|
|
1590
1596
|
};
|
|
1591
1597
|
}, [call, isSupported, noiseCancellation]);
|
|
1592
1598
|
const contextValue = react.useMemo(() => ({
|
|
1593
1599
|
isSupported,
|
|
1600
|
+
isReady,
|
|
1594
1601
|
isEnabled,
|
|
1595
1602
|
setSuppressionLevel: (level) => {
|
|
1596
1603
|
if (!noiseCancellation)
|
|
@@ -1614,7 +1621,7 @@ const NoiseCancellationProvider = (props) => {
|
|
|
1614
1621
|
});
|
|
1615
1622
|
}
|
|
1616
1623
|
},
|
|
1617
|
-
}), [isEnabled, isSupported, noiseCancellation]);
|
|
1624
|
+
}), [isEnabled, isReady, isSupported, noiseCancellation]);
|
|
1618
1625
|
return (jsxRuntime.jsx(NoiseCancellationContext.Provider, { value: contextValue, children: children }));
|
|
1619
1626
|
};
|
|
1620
1627
|
|
|
@@ -1787,7 +1794,9 @@ const ParticipantDetails = ({ indicatorsVisible = true, }) => {
|
|
|
1787
1794
|
const hasVideoTrack = videoClient.hasVideo(participant);
|
|
1788
1795
|
const canUnpin = !!pin && pin.isLocalPin;
|
|
1789
1796
|
const isTrackPaused = trackType !== 'none' ? videoClient.hasPausedTrack(participant, trackType) : false;
|
|
1790
|
-
|
|
1797
|
+
const isAudioTrackUnmuted = useIsTrackUnmuted(participant);
|
|
1798
|
+
const isAudioConnecting = hasAudioTrack && !isAudioTrackUnmuted;
|
|
1799
|
+
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 && (
|
|
1791
1800
|
// TODO: remove this monstrosity once we have a proper design
|
|
1792
1801
|
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 &&
|
|
1793
1802
|
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 })) }))] }));
|
|
@@ -1797,6 +1806,29 @@ const SpeechIndicator = () => {
|
|
|
1797
1806
|
const { isSpeaking, isDominantSpeaker } = participant;
|
|
1798
1807
|
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" })] }));
|
|
1799
1808
|
};
|
|
1809
|
+
const useIsTrackUnmuted = (participant) => {
|
|
1810
|
+
const audioStream = participant.audioStream;
|
|
1811
|
+
const [unmuted, setUnmuted] = react.useState(() => {
|
|
1812
|
+
const track = audioStream?.getAudioTracks()[0];
|
|
1813
|
+
return !!track && !track.muted;
|
|
1814
|
+
});
|
|
1815
|
+
react.useEffect(() => {
|
|
1816
|
+
const track = audioStream?.getAudioTracks()[0];
|
|
1817
|
+
if (!track)
|
|
1818
|
+
return;
|
|
1819
|
+
setUnmuted(!track.muted);
|
|
1820
|
+
const handler = () => {
|
|
1821
|
+
setUnmuted(!track.muted);
|
|
1822
|
+
};
|
|
1823
|
+
track.addEventListener('mute', handler);
|
|
1824
|
+
track.addEventListener('unmute', handler);
|
|
1825
|
+
return () => {
|
|
1826
|
+
track.removeEventListener('mute', handler);
|
|
1827
|
+
track.removeEventListener('unmute', handler);
|
|
1828
|
+
};
|
|
1829
|
+
}, [audioStream]);
|
|
1830
|
+
return unmuted;
|
|
1831
|
+
};
|
|
1800
1832
|
|
|
1801
1833
|
const ParticipantView = react.forwardRef(function ParticipantView({ participant, trackType = 'videoTrack', mirror, muteAudio, refs: { setVideoElement, setVideoPlaceholderElement } = {}, className, VideoPlaceholder, PictureInPicturePlaceholder, ParticipantViewUI = DefaultParticipantViewUI, }, ref) {
|
|
1802
1834
|
const { isLocalParticipant, isSpeaking, isDominantSpeaker, sessionId } = participant;
|
|
@@ -1967,6 +1999,7 @@ var en = {
|
|
|
1967
1999
|
"Dominant Speaker": "Dominant Speaker",
|
|
1968
2000
|
"Poor connection quality": "Poor connection quality. Please check your internet connection.",
|
|
1969
2001
|
"Video paused due to insufficient bandwidth": "Video paused due to insufficient bandwidth",
|
|
2002
|
+
"Audio is connecting...": "Audio is connecting...",
|
|
1970
2003
|
Participants: Participants,
|
|
1971
2004
|
Anonymous: Anonymous,
|
|
1972
2005
|
"No participants found": "No participants found",
|