@stream-io/video-react-sdk 1.34.2 → 1.35.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 +13 -0
- package/dist/css/embedded.css +54 -0
- package/dist/css/embedded.css.map +1 -1
- package/dist/css/styles.css +54 -0
- package/dist/css/styles.css.map +1 -1
- package/dist/embedded.cjs.js +90 -3
- package/dist/embedded.cjs.js.map +1 -1
- package/dist/embedded.es.js +90 -3
- package/dist/embedded.es.js.map +1 -1
- package/dist/index.cjs.js +91 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +91 -4
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/DeviceSettings/DeviceAudioPreviewItem.d.ts +6 -0
- package/dist/src/components/DeviceSettings/DeviceSelector.d.ts +11 -2
- package/dist/src/components/DeviceSettings/DeviceSelectorAudio.d.ts +1 -1
- package/dist/src/components/DeviceSettings/DeviceSelectorVideo.d.ts +1 -1
- package/dist/src/components/DeviceSettings/DeviceVideoPreviewItem.d.ts +6 -0
- package/package.json +5 -5
- package/src/components/DeviceSettings/DeviceAudioPreviewItem.tsx +83 -0
- package/src/components/DeviceSettings/DeviceSelector.tsx +70 -5
- package/src/components/DeviceSettings/DeviceSelectorAudio.tsx +3 -1
- package/src/components/DeviceSettings/DeviceSelectorVideo.tsx +5 -2
- package/src/components/DeviceSettings/DeviceVideoPreviewItem.tsx +73 -0
package/dist/index.es.js
CHANGED
|
@@ -1232,6 +1232,41 @@ const AudioVolumeIndicator = () => {
|
|
|
1232
1232
|
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", style: { transform: `scaleX(${audioLevel / 100})` } }) })] }));
|
|
1233
1233
|
};
|
|
1234
1234
|
|
|
1235
|
+
const LEVEL_BARS = 5;
|
|
1236
|
+
const DeviceLevelIndicator = ({ deviceId }) => {
|
|
1237
|
+
const [audioLevel, setAudioLevel] = useState(0);
|
|
1238
|
+
useEffect(() => {
|
|
1239
|
+
let cancelled = false;
|
|
1240
|
+
let dispose;
|
|
1241
|
+
navigator.mediaDevices
|
|
1242
|
+
.getUserMedia({
|
|
1243
|
+
audio: { deviceId: { exact: deviceId } },
|
|
1244
|
+
video: false,
|
|
1245
|
+
})
|
|
1246
|
+
.then((mediaStream) => {
|
|
1247
|
+
if (cancelled) {
|
|
1248
|
+
mediaStream.getTracks().forEach((t) => t.stop());
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
dispose = createSoundDetector(mediaStream, ({ audioLevel: al }) => setAudioLevel(al), { detectionFrequencyInMs: 80 });
|
|
1252
|
+
})
|
|
1253
|
+
.catch(console.error);
|
|
1254
|
+
return () => {
|
|
1255
|
+
cancelled = true;
|
|
1256
|
+
dispose?.().catch(console.error);
|
|
1257
|
+
};
|
|
1258
|
+
}, [deviceId]);
|
|
1259
|
+
const activeBars = Math.round((audioLevel / 100) * LEVEL_BARS);
|
|
1260
|
+
return (jsx("div", { className: "str-video__device-level-indicator", "aria-label": "Audio level", children: Array.from({ length: LEVEL_BARS }, (_, i) => (jsx("div", { className: clsx('str-video__device-level-indicator__bar', {
|
|
1261
|
+
'str-video__device-level-indicator__bar--active': i < activeBars,
|
|
1262
|
+
}) }, i))) }));
|
|
1263
|
+
};
|
|
1264
|
+
const DeviceAudioPreviewItem = ({ device, onSelect, }) => {
|
|
1265
|
+
if (device.deviceId === 'default')
|
|
1266
|
+
return null;
|
|
1267
|
+
return (jsxs("label", { className: `str-video__device-settings__option${device.isSelected ? ' str-video__device-settings__option--selected' : ''}`, htmlFor: `audioinput--${device.deviceId}`, children: [jsx("input", { type: "radio", name: "audioinput", value: device.deviceId, id: `audioinput--${device.deviceId}`, checked: device.isSelected, onChange: (e) => onSelect(e.target.value) }), device.label, jsx(DeviceLevelIndicator, { deviceId: device.deviceId })] }));
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1235
1270
|
const SelectContext = createContext({});
|
|
1236
1271
|
const Select = (props) => {
|
|
1237
1272
|
const { children, icon, defaultSelectedLabel, defaultSelectedIndex, handleSelect: handleSelectProp, } = props;
|
|
@@ -1323,6 +1358,18 @@ const DeviceSelectorList = (props) => {
|
|
|
1323
1358
|
}, name: type, selected: device.isSelected }, device.deviceId));
|
|
1324
1359
|
}), children] }));
|
|
1325
1360
|
};
|
|
1361
|
+
const DeviceSelectorPreview = (props) => {
|
|
1362
|
+
const { devices = [], selectedDeviceId, title, onChange, children, PreviewItem, } = props;
|
|
1363
|
+
const { close } = useMenuContext();
|
|
1364
|
+
const { deviceList } = useDeviceList(devices, selectedDeviceId);
|
|
1365
|
+
const onSelect = useCallback((deviceId) => {
|
|
1366
|
+
if (deviceId === 'default')
|
|
1367
|
+
return;
|
|
1368
|
+
onChange?.(deviceId);
|
|
1369
|
+
close?.();
|
|
1370
|
+
}, [onChange, close]);
|
|
1371
|
+
return (jsxs("div", { className: "str-video__device-settings__device-kind", children: [title && (jsx("div", { className: "str-video__device-settings__device-selector-title", children: title })), deviceList.map((device) => (jsx(PreviewItem, { device: device, onSelect: onSelect }, device.deviceId))), children] }));
|
|
1372
|
+
};
|
|
1326
1373
|
const DeviceSelectorDropdown = (props) => {
|
|
1327
1374
|
const { devices = [], selectedDeviceId, title, onChange, icon } = props;
|
|
1328
1375
|
const { deviceList, selectedDeviceInfo, selectedIndex } = useDeviceList(devices, selectedDeviceId);
|
|
@@ -1335,6 +1382,10 @@ const DeviceSelectorDropdown = (props) => {
|
|
|
1335
1382
|
return (jsxs("div", { className: "str-video__device-settings__device-kind", children: [jsx("div", { className: "str-video__device-settings__device-selector-title", children: title }), jsx(DropDownSelect, { icon: icon, defaultSelectedIndex: selectedIndex, defaultSelectedLabel: selectedDeviceInfo.label, handleSelect: handleSelect, children: deviceList.map((device) => (jsx(DropDownSelectOption, { icon: icon, label: device.label, selected: device.isSelected }, device.deviceId))) })] }));
|
|
1336
1383
|
};
|
|
1337
1384
|
const DeviceSelector = (props) => {
|
|
1385
|
+
if (props.visualType === 'preview') {
|
|
1386
|
+
const { PreviewItem, ...rest } = props;
|
|
1387
|
+
return jsx(DeviceSelectorPreview, { ...rest, PreviewItem: PreviewItem });
|
|
1388
|
+
}
|
|
1338
1389
|
const { visualType = 'list', icon, ...rest } = props;
|
|
1339
1390
|
if (visualType === 'list') {
|
|
1340
1391
|
return jsx(DeviceSelectorList, { ...rest });
|
|
@@ -1352,7 +1403,7 @@ const SpeakerTest = (props) => {
|
|
|
1352
1403
|
const audioElementRef = useRef(null);
|
|
1353
1404
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
1354
1405
|
const { t } = useI18n();
|
|
1355
|
-
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.
|
|
1406
|
+
const { audioUrl = `https://unpkg.com/${"@stream-io/video-react-sdk"}@${"1.35.0"}/assets/piano.mp3`, } = props;
|
|
1356
1407
|
// Update audio output device when selection changes
|
|
1357
1408
|
useEffect(() => {
|
|
1358
1409
|
const audio = audioElementRef.current;
|
|
@@ -1395,7 +1446,7 @@ const DeviceSelectorAudioInput = ({ title, visualType, volumeIndicatorVisible =
|
|
|
1395
1446
|
const { microphone, selectedDevice, devices } = useMicrophoneState();
|
|
1396
1447
|
return (jsx(DeviceSelector, { devices: devices || [], selectedDeviceId: selectedDevice, type: "audioinput", onChange: async (deviceId) => {
|
|
1397
1448
|
await microphone.select(deviceId);
|
|
1398
|
-
}, title: title, visualType: visualType, icon: "mic", children: volumeIndicatorVisible && (jsxs(Fragment, { children: [jsx("hr", { className: "str-video__device-settings__separator" }), jsx(AudioVolumeIndicator, {})] })) }));
|
|
1449
|
+
}, title: title, visualType: visualType, icon: "mic", PreviewItem: DeviceAudioPreviewItem, children: volumeIndicatorVisible && (jsxs(Fragment, { children: [jsx("hr", { className: "str-video__device-settings__separator" }), jsx(AudioVolumeIndicator, {})] })) }));
|
|
1399
1450
|
};
|
|
1400
1451
|
const DeviceSelectorAudioOutput = ({ title, visualType, speakerTestVisible = true, speakerTestAudioUrl, }) => {
|
|
1401
1452
|
const { useSpeakerState } = useCallStateHooks();
|
|
@@ -1407,12 +1458,48 @@ const DeviceSelectorAudioOutput = ({ title, visualType, speakerTestVisible = tru
|
|
|
1407
1458
|
}, title: title, visualType: visualType, icon: "speaker", children: speakerTestVisible && (jsxs(Fragment, { children: [jsx("hr", { className: "str-video__device-settings__separator" }), jsx(SpeakerTest, { audioUrl: speakerTestAudioUrl })] })) }));
|
|
1408
1459
|
};
|
|
1409
1460
|
|
|
1461
|
+
const DeviceVideoPreview = ({ deviceId }) => {
|
|
1462
|
+
const videoRef = useRef(null);
|
|
1463
|
+
useEffect(() => {
|
|
1464
|
+
let cancelled = false;
|
|
1465
|
+
let stream;
|
|
1466
|
+
navigator.mediaDevices
|
|
1467
|
+
.getUserMedia({
|
|
1468
|
+
video: { deviceId: { exact: deviceId } },
|
|
1469
|
+
audio: false,
|
|
1470
|
+
})
|
|
1471
|
+
.then((mediaStream) => {
|
|
1472
|
+
if (cancelled) {
|
|
1473
|
+
mediaStream.getTracks().forEach((t) => t.stop());
|
|
1474
|
+
return;
|
|
1475
|
+
}
|
|
1476
|
+
stream = mediaStream;
|
|
1477
|
+
if (videoRef.current) {
|
|
1478
|
+
videoRef.current.srcObject = mediaStream;
|
|
1479
|
+
}
|
|
1480
|
+
})
|
|
1481
|
+
.catch(console.error);
|
|
1482
|
+
return () => {
|
|
1483
|
+
cancelled = true;
|
|
1484
|
+
stream?.getTracks().forEach((t) => t.stop());
|
|
1485
|
+
};
|
|
1486
|
+
}, [deviceId]);
|
|
1487
|
+
return (jsx("div", { className: "str-video__device-video-preview", children: jsx("video", { ref: videoRef, autoPlay: true, playsInline: true, muted: true, className: "str-video__device-video-preview__video" }) }));
|
|
1488
|
+
};
|
|
1489
|
+
const DeviceVideoPreviewItem = ({ device, onSelect, }) => {
|
|
1490
|
+
if (device.deviceId === 'default')
|
|
1491
|
+
return null;
|
|
1492
|
+
return (jsxs("button", { type: "button", className: clsx('str-video__device-preview', {
|
|
1493
|
+
'str-video__device-preview--selected': device.isSelected,
|
|
1494
|
+
}), onClick: () => onSelect(device.deviceId), "aria-pressed": device.isSelected, children: [jsx(DeviceVideoPreview, { deviceId: device.deviceId }), jsx("span", { className: "str-video__device-preview__label", children: device.label })] }));
|
|
1495
|
+
};
|
|
1496
|
+
|
|
1410
1497
|
const DeviceSelectorVideo = ({ title, visualType, }) => {
|
|
1411
1498
|
const { useCameraState } = useCallStateHooks();
|
|
1412
1499
|
const { camera, devices, selectedDevice } = useCameraState();
|
|
1413
1500
|
return (jsx(DeviceSelector, { devices: devices || [], type: "videoinput", selectedDeviceId: selectedDevice, onChange: async (deviceId) => {
|
|
1414
1501
|
await camera.select(deviceId);
|
|
1415
|
-
}, title: title, visualType: visualType, icon: "camera" }));
|
|
1502
|
+
}, title: title, visualType: visualType, icon: "camera", PreviewItem: DeviceVideoPreviewItem }));
|
|
1416
1503
|
};
|
|
1417
1504
|
|
|
1418
1505
|
const DeviceSettings = ({ visualType = MenuVisualType.MENU, }) => {
|
|
@@ -3173,7 +3260,7 @@ const checkCanJoinEarly = (startsAt, joinAheadTimeSeconds) => {
|
|
|
3173
3260
|
return Date.now() >= +startsAt - (joinAheadTimeSeconds ?? 0) * 1000;
|
|
3174
3261
|
};
|
|
3175
3262
|
|
|
3176
|
-
const [major, minor, patch] = ("1.
|
|
3263
|
+
const [major, minor, patch] = ("1.35.0").split('.');
|
|
3177
3264
|
setSdkInfo({
|
|
3178
3265
|
type: SfuModels.SdkType.REACT,
|
|
3179
3266
|
major,
|