@stream-io/video-react-sdk 1.33.4 → 1.34.1
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 +29 -0
- package/dist/{background-filters-Zu84SkRR.cjs.js → background-filters-DdQqSx4T.cjs.js} +7 -3
- package/dist/background-filters-DdQqSx4T.cjs.js.map +1 -0
- package/dist/{background-filters-RdXfNf6_.es.js → background-filters-g6ozIvlN.es.js} +7 -3
- package/dist/background-filters-g6ozIvlN.es.js.map +1 -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-BackgroundFilters-Zu84SkRR.cjs.js → embedded-BackgroundFilters-DdQqSx4T.cjs.js} +7 -3
- package/dist/embedded-BackgroundFilters-DdQqSx4T.cjs.js.map +1 -0
- package/dist/{embedded-BackgroundFilters-RdXfNf6_.es.js → embedded-BackgroundFilters-g6ozIvlN.es.js} +7 -3
- package/dist/embedded-BackgroundFilters-g6ozIvlN.es.js.map +1 -0
- package/dist/embedded.cjs.js +64 -35
- package/dist/embedded.cjs.js.map +1 -1
- package/dist/embedded.es.js +64 -35
- package/dist/embedded.es.js.map +1 -1
- package/dist/index.cjs.js +70 -39
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +70 -39
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/BackgroundFilters/types.d.ts +6 -1
- package/dist/src/components/CallControls/RecordCallButton.d.ts +6 -5
- package/dist/src/translations/index.d.ts +1 -0
- package/package.json +5 -5
- package/src/components/BackgroundFilters/BackgroundFilters.tsx +6 -0
- package/src/components/BackgroundFilters/types.ts +7 -0
- package/src/components/CallControls/CallControls.tsx +4 -9
- package/src/components/CallControls/RecordCallButton.tsx +26 -13
- package/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx +44 -4
- package/src/translations/en.json +1 -0
- package/dist/background-filters-RdXfNf6_.es.js.map +0 -1
- package/dist/background-filters-Zu84SkRR.cjs.js.map +0 -1
- package/dist/embedded-BackgroundFilters-RdXfNf6_.es.js.map +0 -1
- package/dist/embedded-BackgroundFilters-Zu84SkRR.cjs.js.map +0 -1
package/dist/embedded.es.js
CHANGED
|
@@ -684,7 +684,7 @@ const AvatarFallback = ({ className, names, style, }) => {
|
|
|
684
684
|
return (jsx("div", { className: clsx('str-video__avatar--initials-fallback', className), style: style, children: jsxs("div", { children: [names[0][0], names[1]?.[0]] }) }));
|
|
685
685
|
};
|
|
686
686
|
|
|
687
|
-
const BackgroundFiltersProviderImpl = lazy(() => import('./embedded-BackgroundFilters-
|
|
687
|
+
const BackgroundFiltersProviderImpl = lazy(() => import('./embedded-BackgroundFilters-g6ozIvlN.es.js').then((m) => ({
|
|
688
688
|
default: m.BackgroundFiltersProvider,
|
|
689
689
|
})));
|
|
690
690
|
/**
|
|
@@ -862,23 +862,53 @@ const WithTooltip = ({ title, tooltipClassName, tooltipPlacement, tooltipDisable
|
|
|
862
862
|
return (jsxs(Fragment, { children: [jsx(Tooltip, { referenceElement: tooltipAnchor, visible: tooltipActuallyVisible, tooltipClassName: tooltipClassName, tooltipPlacement: tooltipPlacement, children: title || '' }), jsx("div", { ref: setTooltipAnchor, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, ...props })] }));
|
|
863
863
|
};
|
|
864
864
|
|
|
865
|
-
|
|
865
|
+
/**
|
|
866
|
+
* Wraps an event handler, silencing and logging exceptions (excluding the NotAllowedError
|
|
867
|
+
* DOMException, which is a normal situation handled by the SDK)
|
|
868
|
+
*
|
|
869
|
+
* @param props component props, including the onError callback
|
|
870
|
+
* @param handler event handler to wrap
|
|
871
|
+
*/
|
|
872
|
+
const createCallControlHandler = (props, handler) => {
|
|
873
|
+
return async () => {
|
|
874
|
+
try {
|
|
875
|
+
await handler();
|
|
876
|
+
}
|
|
877
|
+
catch (error) {
|
|
878
|
+
if (props.onError) {
|
|
879
|
+
props.onError(error);
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
if (!isNotAllowedError(error)) {
|
|
883
|
+
console.error('Call control handler failed', error);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
};
|
|
888
|
+
function isNotAllowedError(error) {
|
|
889
|
+
return error instanceof DOMException && error.name === 'NotAllowedError';
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
const RecordEndConfirmation = (props) => {
|
|
866
893
|
const { t } = useI18n();
|
|
867
894
|
const { toggleCallRecording, isAwaitingResponse } = useToggleCallRecording();
|
|
868
895
|
const { close } = useMenuContext();
|
|
869
|
-
|
|
896
|
+
const handleClick = createCallControlHandler(props, toggleCallRecording);
|
|
897
|
+
return (jsxs("div", { className: "str-video__end-recording__confirmation", children: [jsxs("div", { className: "str-video__end-recording__header", children: [jsx(Icon, { icon: "recording-on" }), jsx("h2", { className: "str-video__end-recording__heading", children: t('End recording') })] }), jsx("p", { className: "str-video__end-recording__description", children: t('Are you sure you want end the recording?') }), jsxs("div", { className: "str-video__end-recording__actions", children: [jsx(CompositeButton, { variant: "secondary", onClick: close, children: t('Cancel') }), jsx(CompositeButton, { variant: "primary", onClick: isAwaitingResponse ? undefined : handleClick, children: isAwaitingResponse ? jsx(LoadingIndicator, {}) : t('End recording') })] })] }));
|
|
870
898
|
};
|
|
871
899
|
const ToggleEndRecordingMenuButton = forwardRef(function ToggleEndRecordingMenuButton(props, ref) {
|
|
872
900
|
return (jsx(CompositeButton, { ref: ref, active: true, variant: "secondary", "data-testid": "recording-stop-button", children: jsx(Icon, { icon: "recording-off" }) }));
|
|
873
901
|
});
|
|
874
|
-
const RecordCallConfirmationButton = (
|
|
902
|
+
const RecordCallConfirmationButton = (props) => {
|
|
903
|
+
const { caption } = props;
|
|
875
904
|
const { t } = useI18n();
|
|
876
905
|
const { toggleCallRecording, isAwaitingResponse, isCallRecordingInProgress } = useToggleCallRecording();
|
|
906
|
+
const handleClick = createCallControlHandler(props, toggleCallRecording);
|
|
877
907
|
if (isCallRecordingInProgress) {
|
|
878
908
|
return (jsx(Restricted, { requiredGrants: [
|
|
879
909
|
OwnCapability.START_RECORD_CALL,
|
|
880
910
|
OwnCapability.STOP_RECORD_CALL,
|
|
881
|
-
], children: jsx(MenuToggle, { ToggleButton: ToggleEndRecordingMenuButton, visualType: MenuVisualType.PORTAL, children: jsx(RecordEndConfirmation, {}) }) }));
|
|
911
|
+
], children: jsx(MenuToggle, { ToggleButton: ToggleEndRecordingMenuButton, visualType: MenuVisualType.PORTAL, children: jsx(RecordEndConfirmation, { onError: props.onError }) }) }));
|
|
882
912
|
}
|
|
883
913
|
const title = isAwaitingResponse
|
|
884
914
|
? t('Waiting for recording to start...')
|
|
@@ -886,7 +916,7 @@ const RecordCallConfirmationButton = ({ caption, }) => {
|
|
|
886
916
|
return (jsx(Restricted, { requiredGrants: [
|
|
887
917
|
OwnCapability.START_RECORD_CALL,
|
|
888
918
|
OwnCapability.STOP_RECORD_CALL,
|
|
889
|
-
], children: jsx(WithTooltip, { title: title, children: jsx(CompositeButton, { active: isCallRecordingInProgress, caption: caption, variant: "secondary", "data-testid": "recording-start-button", onClick: isAwaitingResponse ? undefined :
|
|
919
|
+
], children: jsx(WithTooltip, { title: title, children: jsx(CompositeButton, { active: isCallRecordingInProgress, caption: caption, variant: "secondary", "data-testid": "recording-start-button", onClick: isAwaitingResponse ? undefined : handleClick, children: isAwaitingResponse ? (jsx(LoadingIndicator, {})) : (jsx(Icon, { icon: "recording-off" })) }) }) }));
|
|
890
920
|
};
|
|
891
921
|
|
|
892
922
|
const defaultEmojiReactionMap = {
|
|
@@ -961,33 +991,6 @@ const DefaultReactionsMenu = ({ reactions, layout = 'horizontal', }) => {
|
|
|
961
991
|
}, children: reaction.emoji_code && defaultEmojiReactionMap[reaction.emoji_code] }, reaction.emoji_code))) }));
|
|
962
992
|
};
|
|
963
993
|
|
|
964
|
-
/**
|
|
965
|
-
* Wraps an event handler, silencing and logging exceptions (excluding the NotAllowedError
|
|
966
|
-
* DOMException, which is a normal situation handled by the SDK)
|
|
967
|
-
*
|
|
968
|
-
* @param props component props, including the onError callback
|
|
969
|
-
* @param handler event handler to wrap
|
|
970
|
-
*/
|
|
971
|
-
const createCallControlHandler = (props, handler) => {
|
|
972
|
-
return async () => {
|
|
973
|
-
try {
|
|
974
|
-
await handler();
|
|
975
|
-
}
|
|
976
|
-
catch (error) {
|
|
977
|
-
if (props.onError) {
|
|
978
|
-
props.onError(error);
|
|
979
|
-
return;
|
|
980
|
-
}
|
|
981
|
-
if (!isNotAllowedError(error)) {
|
|
982
|
-
console.error('Call control handler failed', error);
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
};
|
|
986
|
-
};
|
|
987
|
-
function isNotAllowedError(error) {
|
|
988
|
-
return error instanceof DOMException && error.name === 'NotAllowedError';
|
|
989
|
-
}
|
|
990
|
-
|
|
991
994
|
const ScreenShareButton = (props) => {
|
|
992
995
|
const { t } = useI18n();
|
|
993
996
|
const { caption, optimisticUpdates } = props;
|
|
@@ -1151,7 +1154,7 @@ const SpeakerTest = (props) => {
|
|
|
1151
1154
|
const audioElementRef = useRef(null);
|
|
1152
1155
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
1153
1156
|
const { t } = useI18n();
|
|
1154
|
-
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.
|
|
1157
|
+
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.34.1"}/assets/piano.mp3`, } = props;
|
|
1155
1158
|
// Update audio output device when selection changes
|
|
1156
1159
|
useEffect(() => {
|
|
1157
1160
|
const audio = audioElementRef.current;
|
|
@@ -1792,7 +1795,9 @@ const ParticipantDetails = ({ indicatorsVisible = true, }) => {
|
|
|
1792
1795
|
const hasVideoTrack = hasVideo(participant);
|
|
1793
1796
|
const canUnpin = !!pin && pin.isLocalPin;
|
|
1794
1797
|
const isTrackPaused = trackType !== 'none' ? hasPausedTrack(participant, trackType) : false;
|
|
1795
|
-
|
|
1798
|
+
const isAudioTrackUnmuted = useIsTrackUnmuted(participant);
|
|
1799
|
+
const isAudioConnecting = hasAudioTrack && !isAudioTrackUnmuted;
|
|
1800
|
+
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 && !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 && canUnpin && (
|
|
1796
1801
|
// TODO: remove this monstrosity once we have a proper design
|
|
1797
1802
|
jsx("span", { title: t('Unpin'), onClick: () => call?.unpin(sessionId), className: "str-video__participant-details__name--pinned" })), indicatorsVisible && jsx(SpeechIndicator, {})] }) }), indicatorsVisible && (jsx(Notification, { isVisible: isLocalParticipant &&
|
|
1798
1803
|
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 })) }))] }));
|
|
@@ -1802,6 +1807,29 @@ const SpeechIndicator = () => {
|
|
|
1802
1807
|
const { isSpeaking, isDominantSpeaker } = participant;
|
|
1803
1808
|
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" })] }));
|
|
1804
1809
|
};
|
|
1810
|
+
const useIsTrackUnmuted = (participant) => {
|
|
1811
|
+
const audioStream = participant.audioStream;
|
|
1812
|
+
const [unmuted, setUnmuted] = useState(() => {
|
|
1813
|
+
const track = audioStream?.getAudioTracks()[0];
|
|
1814
|
+
return !!track && !track.muted;
|
|
1815
|
+
});
|
|
1816
|
+
useEffect(() => {
|
|
1817
|
+
const track = audioStream?.getAudioTracks()[0];
|
|
1818
|
+
if (!track)
|
|
1819
|
+
return;
|
|
1820
|
+
setUnmuted(!track.muted);
|
|
1821
|
+
const handler = () => {
|
|
1822
|
+
setUnmuted(!track.muted);
|
|
1823
|
+
};
|
|
1824
|
+
track.addEventListener('mute', handler);
|
|
1825
|
+
track.addEventListener('unmute', handler);
|
|
1826
|
+
return () => {
|
|
1827
|
+
track.removeEventListener('mute', handler);
|
|
1828
|
+
track.removeEventListener('unmute', handler);
|
|
1829
|
+
};
|
|
1830
|
+
}, [audioStream]);
|
|
1831
|
+
return unmuted;
|
|
1832
|
+
};
|
|
1805
1833
|
|
|
1806
1834
|
const ParticipantView = forwardRef(function ParticipantView({ participant, trackType = 'videoTrack', mirror, muteAudio, refs: { setVideoElement, setVideoPlaceholderElement } = {}, className, VideoPlaceholder, PictureInPicturePlaceholder, ParticipantViewUI = DefaultParticipantViewUI, }, ref) {
|
|
1807
1835
|
const { isLocalParticipant, isSpeaking, isDominantSpeaker, sessionId } = participant;
|
|
@@ -1972,6 +2000,7 @@ var en = {
|
|
|
1972
2000
|
"Dominant Speaker": "Dominant Speaker",
|
|
1973
2001
|
"Poor connection quality": "Poor connection quality. Please check your internet connection.",
|
|
1974
2002
|
"Video paused due to insufficient bandwidth": "Video paused due to insufficient bandwidth",
|
|
2003
|
+
"Audio is connecting...": "Audio is connecting...",
|
|
1975
2004
|
Participants: Participants,
|
|
1976
2005
|
Anonymous: Anonymous,
|
|
1977
2006
|
"No participants found": "No participants found",
|