@stream-io/video-react-sdk 1.25.1 → 1.26.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 +25 -0
- package/dist/css/styles.css +29 -0
- package/dist/css/styles.css.map +1 -1
- package/dist/index.cjs.js +34 -12
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +35 -14
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/DeviceSettings/AudioVolumeIndicator.d.ts +1 -0
- package/dist/src/components/DeviceSettings/DeviceSelector.d.ts +3 -2
- package/dist/src/components/DeviceSettings/DeviceSelectorAudio.d.ts +2 -1
- package/dist/src/components/DeviceSettings/index.d.ts +1 -0
- package/dist/src/core/components/CallLayout/LivestreamLayout.d.ts +5 -0
- package/package.json +4 -4
- package/src/components/DeviceSettings/AudioVolumeIndicator.tsx +34 -0
- package/src/components/DeviceSettings/DeviceSelector.tsx +30 -18
- package/src/components/DeviceSettings/DeviceSelectorAudio.tsx +11 -1
- package/src/components/DeviceSettings/index.ts +1 -0
- package/src/core/components/CallLayout/LivestreamLayout.tsx +68 -45
package/dist/index.cjs.js
CHANGED
|
@@ -1331,6 +1331,21 @@ const ScreenShareButton = (props) => {
|
|
|
1331
1331
|
: 'screen-share-start-button', disabled: disableScreenShareButton, onClick: handleClick, children: jsxRuntime.jsx(Icon, { icon: isSomeoneScreenSharing ? 'screen-share-on' : 'screen-share-off' }) }) }) }) }));
|
|
1332
1332
|
};
|
|
1333
1333
|
|
|
1334
|
+
const AudioVolumeIndicator = () => {
|
|
1335
|
+
const { useMicrophoneState } = videoReactBindings.useCallStateHooks();
|
|
1336
|
+
const { isEnabled, mediaStream } = useMicrophoneState();
|
|
1337
|
+
const [audioLevel, setAudioLevel] = react.useState(0);
|
|
1338
|
+
react.useEffect(() => {
|
|
1339
|
+
if (!isEnabled || !mediaStream)
|
|
1340
|
+
return;
|
|
1341
|
+
const disposeSoundDetector = videoClient.createSoundDetector(mediaStream, ({ audioLevel: al }) => setAudioLevel(al), { detectionFrequencyInMs: 80, destroyStreamOnStop: false });
|
|
1342
|
+
return () => {
|
|
1343
|
+
disposeSoundDetector().catch(console.error);
|
|
1344
|
+
};
|
|
1345
|
+
}, [isEnabled, mediaStream]);
|
|
1346
|
+
return (jsxRuntime.jsxs("div", { className: "str-video__audio-volume-indicator", children: [jsxRuntime.jsx(Icon, { icon: isEnabled ? 'mic' : 'mic-off' }), jsxRuntime.jsx("div", { className: "str-video__audio-volume-indicator__bar", children: jsxRuntime.jsx("div", { className: "str-video__audio-volume-indicator__bar-value", style: { transform: `scaleX(${audioLevel / 100})` } }) })] }));
|
|
1347
|
+
};
|
|
1348
|
+
|
|
1334
1349
|
const SelectContext = react.createContext({});
|
|
1335
1350
|
const Select = (props) => {
|
|
1336
1351
|
const { children, icon, defaultSelectedLabel, defaultSelectedIndex, handleSelect: handleSelectProp, } = props;
|
|
@@ -1409,7 +1424,7 @@ const DeviceSelectorOption = ({ disabled, id, label, onChange, name, selected, d
|
|
|
1409
1424
|
}), htmlFor: id, children: [jsxRuntime.jsx("input", { type: "radio", name: name, onChange: onChange, value: value, id: id, checked: selected, defaultChecked: defaultChecked, disabled: disabled }), label] }));
|
|
1410
1425
|
};
|
|
1411
1426
|
const DeviceSelectorList = (props) => {
|
|
1412
|
-
const { devices = [], selectedDeviceId, title, type, onChange } = props;
|
|
1427
|
+
const { devices = [], selectedDeviceId, title, type, onChange, children, } = props;
|
|
1413
1428
|
const { close } = useMenuContext();
|
|
1414
1429
|
const { deviceList } = useDeviceList(devices, selectedDeviceId);
|
|
1415
1430
|
return (jsxRuntime.jsxs("div", { className: "str-video__device-settings__device-kind", children: [title && (jsxRuntime.jsx("div", { className: "str-video__device-settings__device-selector-title", children: title })), deviceList.map((device) => {
|
|
@@ -1420,7 +1435,7 @@ const DeviceSelectorList = (props) => {
|
|
|
1420
1435
|
}
|
|
1421
1436
|
close?.();
|
|
1422
1437
|
}, name: type, selected: device.isSelected }, device.deviceId));
|
|
1423
|
-
})] }));
|
|
1438
|
+
}), children] }));
|
|
1424
1439
|
};
|
|
1425
1440
|
const DeviceSelectorDropdown = (props) => {
|
|
1426
1441
|
const { devices = [], selectedDeviceId, title, onChange, icon } = props;
|
|
@@ -1441,12 +1456,12 @@ const DeviceSelector = (props) => {
|
|
|
1441
1456
|
return jsxRuntime.jsx(DeviceSelectorDropdown, { ...rest, icon: icon });
|
|
1442
1457
|
};
|
|
1443
1458
|
|
|
1444
|
-
const DeviceSelectorAudioInput = ({ title, visualType, }) => {
|
|
1459
|
+
const DeviceSelectorAudioInput = ({ title, visualType, volumeIndicatorVisible = true, }) => {
|
|
1445
1460
|
const { useMicrophoneState } = videoReactBindings.useCallStateHooks();
|
|
1446
1461
|
const { microphone, selectedDevice, devices } = useMicrophoneState();
|
|
1447
1462
|
return (jsxRuntime.jsx(DeviceSelector, { devices: devices || [], selectedDeviceId: selectedDevice, type: "audioinput", onChange: async (deviceId) => {
|
|
1448
1463
|
await microphone.select(deviceId);
|
|
1449
|
-
}, title: title, visualType: visualType, icon: "mic" }));
|
|
1464
|
+
}, title: title, visualType: visualType, icon: "mic", children: volumeIndicatorVisible && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("hr", { className: "str-video__device-settings__separator" }), jsxRuntime.jsx(AudioVolumeIndicator, {})] })) }));
|
|
1450
1465
|
};
|
|
1451
1466
|
const DeviceSelectorAudioOutput = ({ title, visualType, }) => {
|
|
1452
1467
|
const { useSpeakerState } = videoReactBindings.useCallStateHooks();
|
|
@@ -2642,13 +2657,14 @@ const LivestreamLayout = (props) => {
|
|
|
2642
2657
|
? participants.find(videoClient.hasScreenShare)
|
|
2643
2658
|
: undefined;
|
|
2644
2659
|
usePaginatedLayoutSortPreset(call);
|
|
2645
|
-
const
|
|
2646
|
-
const {
|
|
2647
|
-
const floatingParticipantOverlay = hasOngoingScreenShare &&
|
|
2648
|
-
|
|
2649
|
-
, {
|
|
2660
|
+
const { floatingParticipantProps, muted, ParticipantViewUI } = props;
|
|
2661
|
+
const overlay = ParticipantViewUI ?? (jsxRuntime.jsx(ParticipantOverlay, { showParticipantCount: props.showParticipantCount, showDuration: props.showDuration, showLiveBadge: props.showLiveBadge, showSpeakerName: props.showSpeakerName, enableFullScreen: props.enableFullScreen }));
|
|
2662
|
+
const floatingParticipantOverlay = hasOngoingScreenShare &&
|
|
2663
|
+
(ParticipantViewUI ?? (jsxRuntime.jsx(ParticipantOverlay
|
|
2650
2664
|
// these elements aren't needed for the video feed
|
|
2651
|
-
|
|
2665
|
+
, {
|
|
2666
|
+
// these elements aren't needed for the video feed
|
|
2667
|
+
showParticipantCount: floatingParticipantProps?.showParticipantCount ?? false, showDuration: floatingParticipantProps?.showDuration ?? false, showLiveBadge: floatingParticipantProps?.showLiveBadge ?? false, showSpeakerName: floatingParticipantProps?.showSpeakerName ?? true, enableFullScreen: floatingParticipantProps?.enableFullScreen ?? true })));
|
|
2652
2668
|
return (jsxRuntime.jsxs("div", { className: "str-video__livestream-layout__wrapper", children: [!muted && jsxRuntime.jsx(ParticipantsAudio, { participants: remoteParticipants }), hasOngoingScreenShare && presenter && (jsxRuntime.jsx(ParticipantView, { className: "str-video__livestream-layout__screen-share", participant: presenter, ParticipantViewUI: overlay, trackType: "screenShareTrack", muteAudio // audio is rendered by ParticipantsAudio
|
|
2653
2669
|
: true })), currentSpeaker && (jsxRuntime.jsx(ParticipantView, { className: clsx(hasOngoingScreenShare &&
|
|
2654
2670
|
clsx('str-video__livestream-layout__floating-participant', `str-video__livestream-layout__floating-participant--${floatingParticipantProps?.position ?? 'top-right'}`)), participant: currentSpeaker, ParticipantViewUI: floatingParticipantOverlay || overlay, mirror: props.mirrorLocalParticipantVideo !== false ? undefined : false, muteAudio // audio is rendered by ParticipantsAudio
|
|
@@ -2670,13 +2686,18 @@ const BackstageLayout = (props) => {
|
|
|
2670
2686
|
BackstageLayout.displayName = 'BackstageLayout';
|
|
2671
2687
|
const ParticipantOverlay = (props) => {
|
|
2672
2688
|
const { enableFullScreen = true, showParticipantCount = true, showDuration = true, showLiveBadge = true, showSpeakerName = false, } = props;
|
|
2689
|
+
const overlayBarVisible = enableFullScreen ||
|
|
2690
|
+
showParticipantCount ||
|
|
2691
|
+
showDuration ||
|
|
2692
|
+
showLiveBadge ||
|
|
2693
|
+
showSpeakerName;
|
|
2673
2694
|
const { participant } = useParticipantViewContext();
|
|
2674
2695
|
const { useParticipantCount } = videoReactBindings.useCallStateHooks();
|
|
2675
2696
|
const participantCount = useParticipantCount();
|
|
2676
2697
|
const duration = useUpdateCallDuration();
|
|
2677
2698
|
const toggleFullScreen = useToggleFullScreen();
|
|
2678
2699
|
const { t } = videoReactBindings.useI18n();
|
|
2679
|
-
return (jsxRuntime.jsx("div", { className: "str-video__livestream-layout__overlay", children: jsxRuntime.jsxs("div", { className: "str-video__livestream-layout__overlay__bar", children: [showLiveBadge && (jsxRuntime.jsx("span", { className: "str-video__livestream-layout__live-badge", children: t('Live') })), showParticipantCount && (jsxRuntime.jsx("span", { className: "str-video__livestream-layout__viewers-count", children: participantCount })), showSpeakerName && (jsxRuntime.jsx("span", { className: "str-video__livestream-layout__speaker-name", title: participant.name || participant.userId || '', children: participant.name || participant.userId || '' })), showDuration && (jsxRuntime.jsx("span", { className: "str-video__livestream-layout__duration", children: formatDuration(duration) })), enableFullScreen && (jsxRuntime.jsx("span", { className: "str-video__livestream-layout__go-fullscreen", onClick: toggleFullScreen }))] }) }));
|
|
2700
|
+
return (jsxRuntime.jsx("div", { className: "str-video__livestream-layout__overlay", children: overlayBarVisible && (jsxRuntime.jsxs("div", { className: "str-video__livestream-layout__overlay__bar", children: [showLiveBadge && (jsxRuntime.jsx("span", { className: "str-video__livestream-layout__live-badge", children: t('Live') })), showParticipantCount && (jsxRuntime.jsx("span", { className: "str-video__livestream-layout__viewers-count", children: participantCount })), showSpeakerName && (jsxRuntime.jsx("span", { className: "str-video__livestream-layout__speaker-name", title: participant.name || participant.userId || '', children: participant.name || participant.userId || '' })), showDuration && (jsxRuntime.jsx("span", { className: "str-video__livestream-layout__duration", children: formatDuration(duration) })), enableFullScreen && (jsxRuntime.jsx("span", { className: "str-video__livestream-layout__go-fullscreen", onClick: toggleFullScreen }))] })) }));
|
|
2680
2701
|
};
|
|
2681
2702
|
const useUpdateCallDuration = () => {
|
|
2682
2703
|
const { useIsCallLive, useCallSession } = videoReactBindings.useCallStateHooks();
|
|
@@ -3005,7 +3026,7 @@ const checkCanJoinEarly = (startsAt, joinAheadTimeSeconds) => {
|
|
|
3005
3026
|
return Date.now() >= +startsAt - (joinAheadTimeSeconds ?? 0) * 1000;
|
|
3006
3027
|
};
|
|
3007
3028
|
|
|
3008
|
-
const [major, minor, patch] = ("1.
|
|
3029
|
+
const [major, minor, patch] = ("1.26.1").split('.');
|
|
3009
3030
|
videoClient.setSdkInfo({
|
|
3010
3031
|
type: videoClient.SfuModels.SdkType.REACT,
|
|
3011
3032
|
major,
|
|
@@ -3015,6 +3036,7 @@ videoClient.setSdkInfo({
|
|
|
3015
3036
|
|
|
3016
3037
|
exports.AcceptCallButton = AcceptCallButton;
|
|
3017
3038
|
exports.Audio = Audio;
|
|
3039
|
+
exports.AudioVolumeIndicator = AudioVolumeIndicator;
|
|
3018
3040
|
exports.Avatar = Avatar;
|
|
3019
3041
|
exports.AvatarFallback = AvatarFallback;
|
|
3020
3042
|
exports.BackgroundFiltersProvider = BackgroundFiltersProvider;
|