@stream-io/video-react-sdk 1.3.6 → 1.4.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/dist/index.es.js CHANGED
@@ -3,13 +3,11 @@ export * from '@stream-io/video-client';
3
3
  import { useCall, useCallStateHooks, useI18n, Restricted, useConnectedUser, StreamCallProvider, StreamVideoProvider, useStreamVideoClient } from '@stream-io/video-react-bindings';
4
4
  export * from '@stream-io/video-react-bindings';
5
5
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
6
- import { useState, useEffect, Fragment as Fragment$1, createContext, useContext, useCallback, useRef, useMemo, forwardRef, isValidElement, useLayoutEffect } from 'react';
6
+ import { useState, useEffect, Fragment as Fragment$1, createContext, useContext, useCallback, useRef, useMemo, forwardRef, isValidElement, lazy, Suspense, useLayoutEffect } from 'react';
7
7
  import clsx from 'clsx';
8
8
  import { flushSync } from 'react-dom';
9
9
  import { isPlatformSupported, loadTFLite, createRenderer } from '@stream-io/video-filters-web';
10
10
  import { useFloating, offset, shift, flip, size, autoUpdate, FloatingOverlay, FloatingPortal, arrow, FloatingArrow, useListItem, useListNavigation, useTypeahead, useClick, useDismiss, useRole, useInteractions, FloatingFocusManager, FloatingList, useHover } from '@floating-ui/react';
11
- import { Chart, CategoryScale, LinearScale, LineElement, PointElement } from 'chart.js';
12
- import { Line } from 'react-chartjs-2';
13
11
 
14
12
  const Audio = ({ participant, trackType = 'audioTrack', ...rest }) => {
15
13
  const call = useCall();
@@ -1202,89 +1200,15 @@ const CancelCallButton = ({ disabled, caption, onClick, onLeave, }) => {
1202
1200
 
1203
1201
  const CallControls = ({ onLeave }) => (jsxs("div", { className: "str-video__call-controls", children: [jsx(SpeakingWhileMutedNotification, { children: jsx(ToggleAudioPublishingButton, {}) }), jsx(ToggleVideoPublishingButton, {}), jsx(ReactionsButton, {}), jsx(ScreenShareButton, {}), jsx(RecordCallButton, {}), jsx(CancelCallButton, { onLeave: onLeave })] }));
1204
1202
 
1205
- Chart.register(CategoryScale, LinearScale, LineElement, PointElement);
1206
- const CallStatsLatencyChart = (props) => {
1207
- const { values } = props;
1208
- let max = 0;
1209
- const data = {
1210
- labels: values.map((point) => {
1211
- const date = new Date(point.x * 1000);
1212
- return `${date.getHours()}:${date.getMinutes()}`;
1213
- }),
1214
- datasets: [
1215
- {
1216
- data: values.map((point) => {
1217
- const { y } = point;
1218
- max = Math.max(max, y);
1219
- return point;
1220
- }),
1221
- borderColor: '#00e2a1',
1222
- backgroundColor: '#00e2a1',
1223
- },
1224
- ],
1225
- };
1226
- const options = useMemo(() => {
1227
- return {
1228
- maintainAspectRatio: false,
1229
- animation: {
1230
- duration: 0,
1231
- },
1232
- elements: {
1233
- line: {
1234
- borderWidth: 1,
1235
- },
1236
- point: {
1237
- radius: 2,
1238
- },
1239
- },
1240
- scales: {
1241
- y: {
1242
- position: 'right',
1243
- stacked: true,
1244
- min: 0,
1245
- max: Math.max(180, Math.ceil((max + 10) / 10) * 10),
1246
- grid: {
1247
- display: true,
1248
- color: '#979ca0',
1249
- },
1250
- ticks: {
1251
- stepSize: 30,
1252
- },
1253
- },
1254
- x: {
1255
- grid: {
1256
- display: false,
1257
- },
1258
- ticks: {
1259
- display: false,
1260
- },
1261
- },
1262
- },
1263
- };
1264
- }, [max]);
1265
- return (jsx("div", { className: "str-video__call-stats-line-chart-container", children: jsx(Line, { options: options, data: data, className: "str-video__call-stats__latencychart" }) }));
1266
- };
1267
-
1268
- var Statuses;
1269
- (function (Statuses) {
1270
- Statuses["GOOD"] = "Good";
1271
- Statuses["OK"] = "Ok";
1272
- Statuses["BAD"] = "Bad";
1273
- })(Statuses || (Statuses = {}));
1274
- const statsStatus = ({ value, lowBound, highBound, }) => {
1275
- if (value <= lowBound) {
1276
- return Statuses.GOOD;
1277
- }
1278
- if (value >= lowBound && value <= highBound) {
1279
- return Statuses.OK;
1280
- }
1281
- if (value >= highBound) {
1282
- return Statuses.BAD;
1283
- }
1284
- return Statuses.GOOD;
1285
- };
1203
+ const CallStatsLatencyChart = lazy(() => import('./latency-chart-Bj5OSYzg.es.js'));
1204
+ var Status;
1205
+ (function (Status) {
1206
+ Status["GOOD"] = "Good";
1207
+ Status["OK"] = "Ok";
1208
+ Status["BAD"] = "Bad";
1209
+ })(Status || (Status = {}));
1286
1210
  const CallStats = (props) => {
1287
- const { latencyLowBound = 75, latencyHighBound = 400 } = props;
1211
+ const { latencyLowBound = 75, latencyHighBound = 400, showCodecInfo = false, LatencyChartSuspenseFallback = null, } = props;
1288
1212
  const [latencyBuffer, setLatencyBuffer] = useState(() => {
1289
1213
  const now = Date.now();
1290
1214
  return Array.from({ length: 20 }, (_, i) => ({ x: now + i, y: 0 }));
@@ -1324,13 +1248,13 @@ const CallStats = (props) => {
1324
1248
  highBound: latencyHighBound,
1325
1249
  value: callStatsReport?.publisherStats.averageRoundTripTimeInMs || 0,
1326
1250
  };
1327
- return (jsx("div", { className: "str-video__call-stats", children: callStatsReport && (jsxs(Fragment, { children: [jsxs("div", { className: "str-video__call-stats__header", children: [jsxs("h3", { className: "str-video__call-stats__heading", children: [jsx(Icon, { className: "str-video__call-stats__icon", icon: "call-latency" }), t('Call Latency')] }), jsx("p", { className: "str-video__call-stats__description", children: t('Very high latency values may reduce call quality, cause lag, and make the call less enjoyable.') })] }), jsx("div", { className: "str-video__call-stats__latencychart", children: jsx(CallStatsLatencyChart, { values: latencyBuffer }) }), jsxs("div", { className: "str-video__call-stats__header", children: [jsxs("h3", { className: "str-video__call-stats__heading", children: [jsx(Icon, { className: "str-video__call-stats__icon", icon: "network-quality" }), t('Call performance')] }), jsx("p", { className: "str-video__call-stats__description", children: t('Review the key data points below to assess call performance') })] }), jsxs("div", { className: "str-video__call-stats__card-container", children: [jsx(StatCard, { label: t('Region'), value: callStatsReport.datacenter }), jsx(StatCard, { label: t('Latency'), value: `${callStatsReport.publisherStats.averageRoundTripTimeInMs} ms.`, comparison: latencyComparison }), jsx(StatCard, { label: t('Receive jitter'), value: `${callStatsReport.subscriberStats.averageJitterInMs} ms.`, comparison: {
1251
+ return (jsx("div", { className: "str-video__call-stats", children: callStatsReport && (jsxs(Fragment, { children: [jsxs("div", { className: "str-video__call-stats__header", children: [jsxs("h3", { className: "str-video__call-stats__heading", children: [jsx(Icon, { className: "str-video__call-stats__icon", icon: "call-latency" }), t('Call Latency')] }), jsx("p", { className: "str-video__call-stats__description", children: t('Very high latency values may reduce call quality, cause lag, and make the call less enjoyable.') })] }), jsx("div", { className: "str-video__call-stats__latencychart", children: jsx(Suspense, { fallback: LatencyChartSuspenseFallback, children: jsx(CallStatsLatencyChart, { values: latencyBuffer }) }) }), jsxs("div", { className: "str-video__call-stats__header", children: [jsxs("h3", { className: "str-video__call-stats__heading", children: [jsx(Icon, { className: "str-video__call-stats__icon", icon: "network-quality" }), t('Call performance')] }), jsx("p", { className: "str-video__call-stats__description", children: t('Review the key data points below to assess call performance') })] }), jsxs("div", { className: "str-video__call-stats__card-container", children: [jsx(StatCard, { label: t('Region'), value: callStatsReport.datacenter }), jsx(StatCard, { label: t('Latency'), value: `${callStatsReport.publisherStats.averageRoundTripTimeInMs} ms.`, comparison: latencyComparison }), jsx(StatCard, { label: t('Receive jitter'), value: `${callStatsReport.subscriberStats.averageJitterInMs} ms.`, comparison: {
1328
1252
  ...latencyComparison,
1329
1253
  value: callStatsReport.subscriberStats.averageJitterInMs,
1330
1254
  } }), jsx(StatCard, { label: t('Publish jitter'), value: `${callStatsReport.publisherStats.averageJitterInMs} ms.`, comparison: {
1331
1255
  ...latencyComparison,
1332
1256
  value: callStatsReport.publisherStats.averageJitterInMs,
1333
- } }), jsx(StatCard, { label: t('Publish resolution'), value: toFrameSize(callStatsReport.publisherStats) }), jsx(StatCard, { label: t('Publish quality drop reason'), value: callStatsReport.publisherStats.qualityLimitationReasons }), jsx(StatCard, { label: t('Receiving resolution'), value: toFrameSize(callStatsReport.subscriberStats) }), jsx(StatCard, { label: t('Receive quality drop reason'), value: callStatsReport.subscriberStats.qualityLimitationReasons }), jsx(StatCard, { label: t('Publish bitrate'), value: publishBitrate }), jsx(StatCard, { label: t('Receiving bitrate'), value: subscribeBitrate })] })] })) }));
1257
+ } }), jsx(StatCard, { label: `${t('Publish resolution')}${showCodecInfo ? formatCodec(callStatsReport) : ''}`, value: toFrameSize(callStatsReport.publisherStats) }), jsx(StatCard, { label: t('Publish quality drop reason'), value: callStatsReport.publisherStats.qualityLimitationReasons }), jsx(StatCard, { label: t('Receiving resolution'), value: toFrameSize(callStatsReport.subscriberStats) }), jsx(StatCard, { label: t('Receive quality drop reason'), value: callStatsReport.subscriberStats.qualityLimitationReasons }), jsx(StatCard, { label: t('Publish bitrate'), value: publishBitrate }), jsx(StatCard, { label: t('Receiving bitrate'), value: subscribeBitrate })] })] })) }));
1334
1258
  };
1335
1259
  const StatCardExplanation = (props) => {
1336
1260
  const { description } = props;
@@ -1343,18 +1267,29 @@ const StatCardExplanation = (props) => {
1343
1267
  const { getReferenceProps, getFloatingProps } = useInteractions([hover]);
1344
1268
  return (jsxs(Fragment, { children: [jsx("div", { className: "str-video__call-explanation", ref: refs.setReference, ...getReferenceProps(), children: jsx(Icon, { className: "str-video__call-explanation__icon", icon: "info" }) }), isOpen && (jsx("div", { className: "str-video__call-explanation__description", ref: refs.setFloating, style: floatingStyles, ...getFloatingProps(), children: description }))] }));
1345
1269
  };
1346
- const StatsTag = ({ children, status = Statuses.GOOD, }) => {
1270
+ const StatsTag = (props) => {
1271
+ const { children, status } = props;
1347
1272
  return (jsx("div", { className: clsx('str-video__call-stats__tag', {
1348
- 'str-video__call-stats__tag--good': status === Statuses.GOOD,
1349
- 'str-video__call-stats__tag--ok': status === Statuses.OK,
1350
- 'str-video__call-stats__tag--bad': status === Statuses.BAD,
1273
+ 'str-video__call-stats__tag--good': status === Status.GOOD,
1274
+ 'str-video__call-stats__tag--ok': status === Status.OK,
1275
+ 'str-video__call-stats__tag--bad': status === Status.BAD,
1351
1276
  }), children: jsx("div", { className: "str-video__call-stats__tag__text", children: children }) }));
1352
1277
  };
1353
1278
  const StatCard = (props) => {
1354
1279
  const { label, value, description, comparison } = props;
1355
1280
  const { t } = useI18n();
1356
- const status = comparison ? statsStatus(comparison) : undefined;
1357
- return (jsxs("div", { className: "str-video__call-stats__card", children: [jsxs("div", { className: "str-video__call-stats__card-content", children: [jsxs("div", { className: "str-video__call-stats__card-label", children: [label, description && jsx(StatCardExplanation, { description: description })] }), jsx("div", { className: "str-video__call-stats__card-value", children: value })] }), comparison && status && jsx(StatsTag, { status: status, children: t(status) })] }));
1281
+ const status = comparison ? toStatus(comparison) : undefined;
1282
+ return (jsxs("div", { className: "str-video__call-stats__card", children: [jsxs("div", { className: "str-video__call-stats__card-content", children: [jsxs("div", { className: "str-video__call-stats__card-label", children: [label, description && jsx(StatCardExplanation, { description: description })] }), jsx("div", { className: "str-video__call-stats__card-value", children: value })] }), status && jsx(StatsTag, { status: status, children: t(status) })] }));
1283
+ };
1284
+ const toStatus = (config) => {
1285
+ const { value, lowBound, highBound } = config;
1286
+ if (value <= lowBound)
1287
+ return Status.GOOD;
1288
+ if (value >= lowBound && value <= highBound)
1289
+ return Status.OK;
1290
+ if (value >= highBound)
1291
+ return Status.BAD;
1292
+ return Status.GOOD;
1358
1293
  };
1359
1294
  const toFrameSize = (stats) => {
1360
1295
  const { highestFrameWidth: w, highestFrameHeight: h, highestFramesPerSecond: fps, } = stats;
@@ -1367,6 +1302,13 @@ const toFrameSize = (stats) => {
1367
1302
  }
1368
1303
  return size;
1369
1304
  };
1305
+ const formatCodec = (callStatsReport) => {
1306
+ const { codec } = callStatsReport.publisherStats;
1307
+ if (!codec)
1308
+ return '';
1309
+ const [, name] = codec.split('/');
1310
+ return name ? ` (${name})` : '';
1311
+ };
1370
1312
  const calculatePublishBitrate = (previousCallStatsReport, callStatsReport) => {
1371
1313
  const { publisherStats: { totalBytesSent: previousTotalBytesSent, timestamp: previousTimestamp, }, } = previousCallStatsReport;
1372
1314
  const { publisherStats: { totalBytesSent, timestamp }, } = callStatsReport;
@@ -2605,7 +2547,7 @@ const LivestreamPlayer = (props) => {
2605
2547
  return (jsx(StreamCall, { call: call, children: jsx(LivestreamLayout, { ...layoutProps }) }));
2606
2548
  };
2607
2549
 
2608
- const [major, minor, patch] = ("1.3.6" ).split('.');
2550
+ const [major, minor, patch] = ("1.4.0").split('.');
2609
2551
  setSdkInfo({
2610
2552
  type: SfuModels.SdkType.REACT,
2611
2553
  major,
@@ -2613,5 +2555,5 @@ setSdkInfo({
2613
2555
  patch,
2614
2556
  });
2615
2557
 
2616
- export { AcceptCallButton, Audio, Avatar, AvatarFallback, BackgroundFiltersProvider, BaseVideo, CallControls, CallParticipantListing, CallParticipantListingItem, CallParticipantsList, CallPreview, CallRecordingList, CallRecordingListHeader, CallRecordingListItem, CallStats, CallStatsButton, CallStatsLatencyChart, CancelCallButton, CancelCallConfirmButton, CompositeButton, DefaultParticipantViewUI, DefaultReactionsMenu, DefaultScreenShareOverlay, DefaultVideoPlaceholder, DeviceSelector, DeviceSelectorAudioInput, DeviceSelectorAudioOutput, DeviceSelectorVideo, DeviceSettings, DropDownSelect, DropDownSelectOption, EmptyCallRecordingListing, GenericMenu, GenericMenuButtonItem, Icon, IconButton, LivestreamLayout, LivestreamPlayer, LoadingCallRecordingListing, LoadingIndicator, MenuToggle, MenuVisualType, NoiseCancellationProvider, Notification, PaginatedGridLayout, ParticipantActionsContextMenu, ParticipantDetails, ParticipantView, ParticipantViewContext, ParticipantsAudio, PermissionNotification, PermissionRequestList, PermissionRequests, ReactionsButton, RecordCallButton, RecordCallConfirmationButton, RecordingInProgressNotification, RingingCall, RingingCallControls, ScreenShareButton, SearchInput, SearchResults, SpeakerLayout, SpeakingWhileMutedNotification, SpeechIndicator, StatCard, StatCardExplanation, StatsTag, Statuses, StreamCall, StreamTheme, StreamVideo, TextButton, ToggleAudioOutputButton, ToggleAudioPreviewButton, ToggleAudioPublishingButton, ToggleVideoPreviewButton, ToggleVideoPublishingButton, Tooltip, Video$1 as Video, VideoPreview, WithTooltip, defaultReactions, translations, useBackgroundFilters, useHorizontalScrollPosition, useMenuContext, useNoiseCancellation, useParticipantViewContext, usePersistedDevicePreferences, useRequestPermission, useTrackElementVisibility, useVerticalScrollPosition };
2558
+ export { AcceptCallButton, Audio, Avatar, AvatarFallback, BackgroundFiltersProvider, BaseVideo, CallControls, CallParticipantListing, CallParticipantListingItem, CallParticipantsList, CallPreview, CallRecordingList, CallRecordingListHeader, CallRecordingListItem, CallStats, CallStatsButton, CancelCallButton, CancelCallConfirmButton, CompositeButton, DefaultParticipantViewUI, DefaultReactionsMenu, DefaultScreenShareOverlay, DefaultVideoPlaceholder, DeviceSelector, DeviceSelectorAudioInput, DeviceSelectorAudioOutput, DeviceSelectorVideo, DeviceSettings, DropDownSelect, DropDownSelectOption, EmptyCallRecordingListing, GenericMenu, GenericMenuButtonItem, Icon, IconButton, LivestreamLayout, LivestreamPlayer, LoadingCallRecordingListing, LoadingIndicator, MenuToggle, MenuVisualType, NoiseCancellationProvider, Notification, PaginatedGridLayout, ParticipantActionsContextMenu, ParticipantDetails, ParticipantView, ParticipantViewContext, ParticipantsAudio, PermissionNotification, PermissionRequestList, PermissionRequests, ReactionsButton, RecordCallButton, RecordCallConfirmationButton, RecordingInProgressNotification, RingingCall, RingingCallControls, ScreenShareButton, SearchInput, SearchResults, SpeakerLayout, SpeakingWhileMutedNotification, SpeechIndicator, StatCard, StreamCall, StreamTheme, StreamVideo, TextButton, ToggleAudioOutputButton, ToggleAudioPreviewButton, ToggleAudioPublishingButton, ToggleVideoPreviewButton, ToggleVideoPublishingButton, Tooltip, Video$1 as Video, VideoPreview, WithTooltip, defaultReactions, translations, useBackgroundFilters, useHorizontalScrollPosition, useMenuContext, useNoiseCancellation, useParticipantViewContext, usePersistedDevicePreferences, useRequestPermission, useTrackElementVisibility, useVerticalScrollPosition };
2617
2559
  //# sourceMappingURL=index.es.js.map