@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.
@@ -0,0 +1,57 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { Chart, CategoryScale, LinearScale, LineElement, PointElement } from 'chart.js';
3
+ import { Line } from 'react-chartjs-2';
4
+ import { useMemo } from 'react';
5
+
6
+ // NOTE: this is a side effect by definition, but this component is
7
+ // isolated in a separate chunk, and it won't affect the rest of the app.
8
+ // See CallStats.tsx for more details.
9
+ Chart.register(CategoryScale, LinearScale, LineElement, PointElement);
10
+ const CallStatsLatencyChart = (props) => {
11
+ const { values } = props;
12
+ let max = 0;
13
+ const data = {
14
+ labels: values.map((point) => {
15
+ const date = new Date(point.x * 1000);
16
+ return `${date.getHours()}:${date.getMinutes()}`;
17
+ }),
18
+ datasets: [
19
+ {
20
+ data: values.map((point) => {
21
+ const { y } = point;
22
+ max = Math.max(max, y);
23
+ return point;
24
+ }),
25
+ borderColor: '#00e2a1',
26
+ backgroundColor: '#00e2a1',
27
+ },
28
+ ],
29
+ };
30
+ const options = useMemo(() => getLineOptions(max), [max]);
31
+ return (jsx("div", { className: "str-video__call-stats-line-chart-container", children: jsx(Line, { options: options, data: data, className: "str-video__call-stats__latencychart" }) }));
32
+ };
33
+ const getLineOptions = (max) => ({
34
+ maintainAspectRatio: false,
35
+ animation: { duration: 0 },
36
+ elements: {
37
+ line: { borderWidth: 1 },
38
+ point: { radius: 2 },
39
+ },
40
+ scales: {
41
+ y: {
42
+ position: 'right',
43
+ stacked: true,
44
+ min: 0,
45
+ max: Math.max(180, Math.ceil((max + 10) / 10) * 10),
46
+ grid: { display: true, color: '#979ca0' },
47
+ ticks: { stepSize: 30 },
48
+ },
49
+ x: {
50
+ grid: { display: false },
51
+ ticks: { display: false },
52
+ },
53
+ },
54
+ });
55
+
56
+ export { CallStatsLatencyChart as default };
57
+ //# sourceMappingURL=latency-chart-Bj5OSYzg.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"latency-chart-Bj5OSYzg.es.js","sources":["../../src/components/CallStats/CallStatsLatencyChart.tsx"],"sourcesContent":["import {\n CategoryScale,\n Chart as ChartJS,\n ChartData,\n ChartOptions,\n LinearScale,\n LineElement,\n PointElement,\n} from 'chart.js';\nimport { Line } from 'react-chartjs-2';\nimport { useMemo } from 'react';\n\n// NOTE: this is a side effect by definition, but this component is\n// isolated in a separate chunk, and it won't affect the rest of the app.\n// See CallStats.tsx for more details.\nChartJS.register(CategoryScale, LinearScale, LineElement, PointElement);\n\nconst CallStatsLatencyChart = (props: {\n values: Array<{ x: number; y: number }>;\n}) => {\n const { values } = props;\n let max = 0;\n const data: ChartData<'line'> = {\n labels: values.map((point) => {\n const date = new Date(point.x * 1000);\n return `${date.getHours()}:${date.getMinutes()}`;\n }),\n datasets: [\n {\n data: values.map((point) => {\n const { y } = point;\n max = Math.max(max, y);\n return point;\n }),\n borderColor: '#00e2a1',\n backgroundColor: '#00e2a1',\n },\n ],\n };\n\n const options = useMemo(() => getLineOptions(max), [max]);\n return (\n <div className=\"str-video__call-stats-line-chart-container\">\n <Line\n options={options}\n data={data}\n className=\"str-video__call-stats__latencychart\"\n />\n </div>\n );\n};\n\nexport default CallStatsLatencyChart;\n\nconst getLineOptions = (max: number): ChartOptions<'line'> => ({\n maintainAspectRatio: false,\n animation: { duration: 0 },\n elements: {\n line: { borderWidth: 1 },\n point: { radius: 2 },\n },\n scales: {\n y: {\n position: 'right',\n stacked: true,\n min: 0,\n max: Math.max(180, Math.ceil((max + 10) / 10) * 10),\n grid: { display: true, color: '#979ca0' },\n ticks: { stepSize: 30 },\n },\n x: {\n grid: { display: false },\n ticks: { display: false },\n },\n },\n});\n"],"names":["ChartJS","_jsx"],"mappings":";;;;;AAYA;AACA;AACA;AACAA,KAAO,CAAC,QAAQ,CAAC,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;AAExE,MAAM,qBAAqB,GAAG,CAAC,KAE9B,KAAI;AACH,IAAA,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACzB,IAAI,GAAG,GAAG,CAAC,CAAC;AACZ,IAAA,MAAM,IAAI,GAAsB;QAC9B,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,KAAI;YAC3B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;YACtC,OAAO,CAAA,EAAG,IAAI,CAAC,QAAQ,EAAE,CAAI,CAAA,EAAA,IAAI,CAAC,UAAU,EAAE,CAAA,CAAE,CAAC;AACnD,SAAC,CAAC;AACF,QAAA,QAAQ,EAAE;AACR,YAAA;gBACE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,KAAI;AACzB,oBAAA,MAAM,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;oBACpB,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACvB,oBAAA,OAAO,KAAK,CAAC;AACf,iBAAC,CAAC;AACF,gBAAA,WAAW,EAAE,SAAS;AACtB,gBAAA,eAAe,EAAE,SAAS;AAC3B,aAAA;AACF,SAAA;KACF,CAAC;AAEF,IAAA,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,QACEC,aAAK,SAAS,EAAC,4CAA4C,EACzD,QAAA,EAAAA,GAAA,CAAC,IAAI,EAAA,EACH,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,SAAS,EAAC,qCAAqC,EAAA,CAC/C,EACE,CAAA,EACN;AACJ,EAAE;AAIF,MAAM,cAAc,GAAG,CAAC,GAAW,MAA4B;AAC7D,IAAA,mBAAmB,EAAE,KAAK;AAC1B,IAAA,SAAS,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE;AAC1B,IAAA,QAAQ,EAAE;AACR,QAAA,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE;AACxB,QAAA,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE;AACrB,KAAA;AACD,IAAA,MAAM,EAAE;AACN,QAAA,CAAC,EAAE;AACD,YAAA,QAAQ,EAAE,OAAO;AACjB,YAAA,OAAO,EAAE,IAAI;AACb,YAAA,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC;YACnD,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE;AACzC,YAAA,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;AACxB,SAAA;AACD,QAAA,CAAC,EAAE;AACD,YAAA,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;AACxB,YAAA,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;AAC1B,SAAA;AACF,KAAA;AACF,CAAA,CAAC;;;;"}
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var chart_js = require('chart.js');
5
+ var reactChartjs2 = require('react-chartjs-2');
6
+ var react = require('react');
7
+
8
+ // NOTE: this is a side effect by definition, but this component is
9
+ // isolated in a separate chunk, and it won't affect the rest of the app.
10
+ // See CallStats.tsx for more details.
11
+ chart_js.Chart.register(chart_js.CategoryScale, chart_js.LinearScale, chart_js.LineElement, chart_js.PointElement);
12
+ const CallStatsLatencyChart = (props) => {
13
+ const { values } = props;
14
+ let max = 0;
15
+ const data = {
16
+ labels: values.map((point) => {
17
+ const date = new Date(point.x * 1000);
18
+ return `${date.getHours()}:${date.getMinutes()}`;
19
+ }),
20
+ datasets: [
21
+ {
22
+ data: values.map((point) => {
23
+ const { y } = point;
24
+ max = Math.max(max, y);
25
+ return point;
26
+ }),
27
+ borderColor: '#00e2a1',
28
+ backgroundColor: '#00e2a1',
29
+ },
30
+ ],
31
+ };
32
+ const options = react.useMemo(() => getLineOptions(max), [max]);
33
+ return (jsxRuntime.jsx("div", { className: "str-video__call-stats-line-chart-container", children: jsxRuntime.jsx(reactChartjs2.Line, { options: options, data: data, className: "str-video__call-stats__latencychart" }) }));
34
+ };
35
+ const getLineOptions = (max) => ({
36
+ maintainAspectRatio: false,
37
+ animation: { duration: 0 },
38
+ elements: {
39
+ line: { borderWidth: 1 },
40
+ point: { radius: 2 },
41
+ },
42
+ scales: {
43
+ y: {
44
+ position: 'right',
45
+ stacked: true,
46
+ min: 0,
47
+ max: Math.max(180, Math.ceil((max + 10) / 10) * 10),
48
+ grid: { display: true, color: '#979ca0' },
49
+ ticks: { stepSize: 30 },
50
+ },
51
+ x: {
52
+ grid: { display: false },
53
+ ticks: { display: false },
54
+ },
55
+ },
56
+ });
57
+
58
+ exports.default = CallStatsLatencyChart;
59
+ //# sourceMappingURL=latency-chart-CpL1M_s0.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"latency-chart-CpL1M_s0.cjs.js","sources":["../../src/components/CallStats/CallStatsLatencyChart.tsx"],"sourcesContent":["import {\n CategoryScale,\n Chart as ChartJS,\n ChartData,\n ChartOptions,\n LinearScale,\n LineElement,\n PointElement,\n} from 'chart.js';\nimport { Line } from 'react-chartjs-2';\nimport { useMemo } from 'react';\n\n// NOTE: this is a side effect by definition, but this component is\n// isolated in a separate chunk, and it won't affect the rest of the app.\n// See CallStats.tsx for more details.\nChartJS.register(CategoryScale, LinearScale, LineElement, PointElement);\n\nconst CallStatsLatencyChart = (props: {\n values: Array<{ x: number; y: number }>;\n}) => {\n const { values } = props;\n let max = 0;\n const data: ChartData<'line'> = {\n labels: values.map((point) => {\n const date = new Date(point.x * 1000);\n return `${date.getHours()}:${date.getMinutes()}`;\n }),\n datasets: [\n {\n data: values.map((point) => {\n const { y } = point;\n max = Math.max(max, y);\n return point;\n }),\n borderColor: '#00e2a1',\n backgroundColor: '#00e2a1',\n },\n ],\n };\n\n const options = useMemo(() => getLineOptions(max), [max]);\n return (\n <div className=\"str-video__call-stats-line-chart-container\">\n <Line\n options={options}\n data={data}\n className=\"str-video__call-stats__latencychart\"\n />\n </div>\n );\n};\n\nexport default CallStatsLatencyChart;\n\nconst getLineOptions = (max: number): ChartOptions<'line'> => ({\n maintainAspectRatio: false,\n animation: { duration: 0 },\n elements: {\n line: { borderWidth: 1 },\n point: { radius: 2 },\n },\n scales: {\n y: {\n position: 'right',\n stacked: true,\n min: 0,\n max: Math.max(180, Math.ceil((max + 10) / 10) * 10),\n grid: { display: true, color: '#979ca0' },\n ticks: { stepSize: 30 },\n },\n x: {\n grid: { display: false },\n ticks: { display: false },\n },\n },\n});\n"],"names":["ChartJS","CategoryScale","LinearScale","LineElement","PointElement","useMemo","_jsx","Line"],"mappings":";;;;;;;AAYA;AACA;AACA;AACAA,cAAO,CAAC,QAAQ,CAACC,sBAAa,EAAEC,oBAAW,EAAEC,oBAAW,EAAEC,qBAAY,CAAC,CAAC;AAExE,MAAM,qBAAqB,GAAG,CAAC,KAE9B,KAAI;AACH,IAAA,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACzB,IAAI,GAAG,GAAG,CAAC,CAAC;AACZ,IAAA,MAAM,IAAI,GAAsB;QAC9B,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,KAAI;YAC3B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;YACtC,OAAO,CAAA,EAAG,IAAI,CAAC,QAAQ,EAAE,CAAI,CAAA,EAAA,IAAI,CAAC,UAAU,EAAE,CAAA,CAAE,CAAC;AACnD,SAAC,CAAC;AACF,QAAA,QAAQ,EAAE;AACR,YAAA;gBACE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,KAAI;AACzB,oBAAA,MAAM,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;oBACpB,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACvB,oBAAA,OAAO,KAAK,CAAC;AACf,iBAAC,CAAC;AACF,gBAAA,WAAW,EAAE,SAAS;AACtB,gBAAA,eAAe,EAAE,SAAS;AAC3B,aAAA;AACF,SAAA;KACF,CAAC;AAEF,IAAA,MAAM,OAAO,GAAGC,aAAO,CAAC,MAAM,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,QACEC,wBAAK,SAAS,EAAC,4CAA4C,EACzD,QAAA,EAAAA,cAAA,CAACC,kBAAI,EAAA,EACH,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,SAAS,EAAC,qCAAqC,EAAA,CAC/C,EACE,CAAA,EACN;AACJ,EAAE;AAIF,MAAM,cAAc,GAAG,CAAC,GAAW,MAA4B;AAC7D,IAAA,mBAAmB,EAAE,KAAK;AAC1B,IAAA,SAAS,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE;AAC1B,IAAA,QAAQ,EAAE;AACR,QAAA,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE;AACxB,QAAA,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE;AACrB,KAAA;AACD,IAAA,MAAM,EAAE;AACN,QAAA,CAAC,EAAE;AACD,YAAA,QAAQ,EAAE,OAAO;AACjB,YAAA,OAAO,EAAE,IAAI;AACb,YAAA,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC;YACnD,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE;AACzC,YAAA,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;AACxB,SAAA;AACD,QAAA,CAAC,EAAE;AACD,YAAA,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;AACxB,YAAA,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;AAC1B,SAAA;AACF,KAAA;AACF,CAAA,CAAC;;;;"}
@@ -1,21 +1,11 @@
1
1
  import { ReactNode } from 'react';
2
- export declare enum Statuses {
3
- GOOD = "Good",
4
- OK = "Ok",
5
- BAD = "Bad"
6
- }
7
- export type Status = Statuses.GOOD | Statuses.OK | Statuses.BAD;
8
- export declare const CallStats: (props: {
2
+ export type CallStatsProps = {
9
3
  latencyLowBound?: number;
10
4
  latencyHighBound?: number;
11
- }) => import("react/jsx-runtime").JSX.Element;
12
- export declare const StatCardExplanation: (props: {
13
- description: string;
14
- }) => import("react/jsx-runtime").JSX.Element;
15
- export declare const StatsTag: ({ children, status, }: {
16
- children: ReactNode;
17
- status: Statuses.GOOD | Statuses.OK | Statuses.BAD;
18
- }) => import("react/jsx-runtime").JSX.Element;
5
+ showCodecInfo?: boolean;
6
+ LatencyChartSuspenseFallback?: ReactNode;
7
+ };
8
+ export declare const CallStats: (props: CallStatsProps) => import("react/jsx-runtime").JSX.Element;
19
9
  export declare const StatCard: (props: {
20
10
  label: string;
21
11
  value: string | ReactNode;
@@ -1,6 +1,7 @@
1
- export declare const CallStatsLatencyChart: (props: {
1
+ declare const CallStatsLatencyChart: (props: {
2
2
  values: Array<{
3
3
  x: number;
4
4
  y: number;
5
5
  }>;
6
6
  }) => import("react/jsx-runtime").JSX.Element;
7
+ export default CallStatsLatencyChart;
@@ -1,2 +1 @@
1
1
  export * from './CallStats';
2
- export * from './CallStatsLatencyChart';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stream-io/video-react-sdk",
3
- "version": "1.3.6",
3
+ "version": "1.4.0",
4
4
  "packageManager": "yarn@3.2.4",
5
5
  "main": "./dist/index.cjs.js",
6
6
  "module": "./dist/index.es.js",
@@ -27,12 +27,15 @@
27
27
  "LICENSE",
28
28
  "CHANGELOG.md"
29
29
  ],
30
+ "sideEffects": [
31
+ "*.css"
32
+ ],
30
33
  "dependencies": {
31
- "@floating-ui/react": "^0.26.5",
32
- "@stream-io/video-client": "1.6.5",
33
- "@stream-io/video-filters-web": "0.1.3",
34
- "@stream-io/video-react-bindings": "1.0.5",
35
- "chart.js": "^4.4.1",
34
+ "@floating-ui/react": "^0.26.24",
35
+ "@stream-io/video-client": "1.7.0",
36
+ "@stream-io/video-filters-web": "0.1.4",
37
+ "@stream-io/video-react-bindings": "1.0.6",
38
+ "chart.js": "^4.4.4",
36
39
  "clsx": "^2.0.0",
37
40
  "react-chartjs-2": "^5.2.0"
38
41
  },
@@ -42,16 +45,16 @@
42
45
  },
43
46
  "devDependencies": {
44
47
  "@rollup/plugin-json": "^6.1.0",
45
- "@rollup/plugin-replace": "^5.0.5",
48
+ "@rollup/plugin-replace": "^5.0.7",
46
49
  "@rollup/plugin-typescript": "^11.1.6",
47
- "@stream-io/audio-filters-web": "^0.2.1",
50
+ "@stream-io/audio-filters-web": "^0.2.2",
48
51
  "@stream-io/video-styling": "^1.0.6",
49
52
  "@types/react": "^18.3.2",
50
53
  "@types/react-dom": "^18.3.0",
51
54
  "react": "^18.3.1",
52
55
  "react-dom": "^18.3.1",
53
56
  "rimraf": "^5.0.7",
54
- "rollup": "^3.29.4",
57
+ "rollup": "^4.22.0",
55
58
  "typescript": "^5.5.2"
56
59
  }
57
60
  }
@@ -1,52 +1,35 @@
1
- import { ReactNode, useEffect, useRef, useState } from 'react';
1
+ import { lazy, ReactNode, Suspense, useEffect, useRef, useState } from 'react';
2
2
  import clsx from 'clsx';
3
3
  import {
4
4
  AggregatedStatsReport,
5
5
  CallStatsReport,
6
6
  } from '@stream-io/video-client';
7
7
  import { useCallStateHooks, useI18n } from '@stream-io/video-react-bindings';
8
-
9
8
  import { useFloating, useHover, useInteractions } from '@floating-ui/react';
10
-
11
- import { CallStatsLatencyChart } from './CallStatsLatencyChart';
12
9
  import { Icon } from '../Icon';
13
10
 
14
- export enum Statuses {
11
+ const CallStatsLatencyChart = lazy(() => import('./CallStatsLatencyChart'));
12
+
13
+ enum Status {
15
14
  GOOD = 'Good',
16
15
  OK = 'Ok',
17
16
  BAD = 'Bad',
18
17
  }
19
- export type Status = Statuses.GOOD | Statuses.OK | Statuses.BAD;
20
-
21
- const statsStatus = ({
22
- value,
23
- lowBound,
24
- highBound,
25
- }: {
26
- value: number;
27
- lowBound: number;
28
- highBound: number;
29
- }): Status => {
30
- if (value <= lowBound) {
31
- return Statuses.GOOD;
32
- }
33
-
34
- if (value >= lowBound && value <= highBound) {
35
- return Statuses.OK;
36
- }
37
-
38
- if (value >= highBound) {
39
- return Statuses.BAD;
40
- }
41
-
42
- return Statuses.GOOD;
43
- };
44
18
 
45
- export const CallStats = (props: {
19
+ export type CallStatsProps = {
46
20
  latencyLowBound?: number;
47
21
  latencyHighBound?: number;
48
- }) => {
49
- const { latencyLowBound = 75, latencyHighBound = 400 } = props;
22
+ showCodecInfo?: boolean;
23
+ LatencyChartSuspenseFallback?: ReactNode;
24
+ };
25
+
26
+ export const CallStats = (props: CallStatsProps) => {
27
+ const {
28
+ latencyLowBound = 75,
29
+ latencyHighBound = 400,
30
+ showCodecInfo = false,
31
+ LatencyChartSuspenseFallback = null,
32
+ } = props;
50
33
  const [latencyBuffer, setLatencyBuffer] = useState<
51
34
  Array<{ x: number; y: number }>
52
35
  >(() => {
@@ -116,7 +99,9 @@ export const CallStats = (props: {
116
99
  </div>
117
100
 
118
101
  <div className="str-video__call-stats__latencychart">
119
- <CallStatsLatencyChart values={latencyBuffer} />
102
+ <Suspense fallback={LatencyChartSuspenseFallback}>
103
+ <CallStatsLatencyChart values={latencyBuffer} />
104
+ </Suspense>
120
105
  </div>
121
106
 
122
107
  <div className="str-video__call-stats__header">
@@ -156,7 +141,7 @@ export const CallStats = (props: {
156
141
  }}
157
142
  />
158
143
  <StatCard
159
- label={t('Publish resolution')}
144
+ label={`${t('Publish resolution')}${showCodecInfo ? formatCodec(callStatsReport) : ''}`}
160
145
  value={toFrameSize(callStatsReport.publisherStats)}
161
146
  />
162
147
  <StatCard
@@ -180,7 +165,7 @@ export const CallStats = (props: {
180
165
  );
181
166
  };
182
167
 
183
- export const StatCardExplanation = (props: { description: string }) => {
168
+ const StatCardExplanation = (props: { description: string }) => {
184
169
  const { description } = props;
185
170
  const [isOpen, setIsOpen] = useState(false);
186
171
 
@@ -216,19 +201,14 @@ export const StatCardExplanation = (props: { description: string }) => {
216
201
  );
217
202
  };
218
203
 
219
- export const StatsTag = ({
220
- children,
221
- status = Statuses.GOOD,
222
- }: {
223
- children: ReactNode;
224
- status: Statuses.GOOD | Statuses.OK | Statuses.BAD;
225
- }) => {
204
+ const StatsTag = (props: { children: ReactNode; status: Status }) => {
205
+ const { children, status } = props;
226
206
  return (
227
207
  <div
228
208
  className={clsx('str-video__call-stats__tag', {
229
- 'str-video__call-stats__tag--good': status === Statuses.GOOD,
230
- 'str-video__call-stats__tag--ok': status === Statuses.OK,
231
- 'str-video__call-stats__tag--bad': status === Statuses.BAD,
209
+ 'str-video__call-stats__tag--good': status === Status.GOOD,
210
+ 'str-video__call-stats__tag--ok': status === Status.OK,
211
+ 'str-video__call-stats__tag--bad': status === Status.BAD,
232
212
  })}
233
213
  >
234
214
  <div className="str-video__call-stats__tag__text">{children}</div>
@@ -245,7 +225,7 @@ export const StatCard = (props: {
245
225
  const { label, value, description, comparison } = props;
246
226
 
247
227
  const { t } = useI18n();
248
- const status = comparison ? statsStatus(comparison) : undefined;
228
+ const status = comparison ? toStatus(comparison) : undefined;
249
229
 
250
230
  return (
251
231
  <div className="str-video__call-stats__card">
@@ -256,11 +236,23 @@ export const StatCard = (props: {
256
236
  </div>
257
237
  <div className="str-video__call-stats__card-value">{value}</div>
258
238
  </div>
259
- {comparison && status && <StatsTag status={status}>{t(status)}</StatsTag>}
239
+ {status && <StatsTag status={status}>{t(status)}</StatsTag>}
260
240
  </div>
261
241
  );
262
242
  };
263
243
 
244
+ const toStatus = (config: {
245
+ value: number;
246
+ lowBound: number;
247
+ highBound: number;
248
+ }): Status => {
249
+ const { value, lowBound, highBound } = config;
250
+ if (value <= lowBound) return Status.GOOD;
251
+ if (value >= lowBound && value <= highBound) return Status.OK;
252
+ if (value >= highBound) return Status.BAD;
253
+ return Status.GOOD;
254
+ };
255
+
264
256
  const toFrameSize = (stats: AggregatedStatsReport) => {
265
257
  const {
266
258
  highestFrameWidth: w,
@@ -277,6 +269,13 @@ const toFrameSize = (stats: AggregatedStatsReport) => {
277
269
  return size;
278
270
  };
279
271
 
272
+ const formatCodec = (callStatsReport: CallStatsReport): string => {
273
+ const { codec } = callStatsReport.publisherStats;
274
+ if (!codec) return '';
275
+ const [, name] = codec.split('/');
276
+ return name ? ` (${name})` : '';
277
+ };
278
+
280
279
  const calculatePublishBitrate = (
281
280
  previousCallStatsReport: CallStatsReport,
282
281
  callStatsReport: CallStatsReport,
@@ -10,9 +10,12 @@ import {
10
10
  import { Line } from 'react-chartjs-2';
11
11
  import { useMemo } from 'react';
12
12
 
13
+ // NOTE: this is a side effect by definition, but this component is
14
+ // isolated in a separate chunk, and it won't affect the rest of the app.
15
+ // See CallStats.tsx for more details.
13
16
  ChartJS.register(CategoryScale, LinearScale, LineElement, PointElement);
14
17
 
15
- export const CallStatsLatencyChart = (props: {
18
+ const CallStatsLatencyChart = (props: {
16
19
  values: Array<{ x: number; y: number }>;
17
20
  }) => {
18
21
  const { values } = props;
@@ -35,46 +38,7 @@ export const CallStatsLatencyChart = (props: {
35
38
  ],
36
39
  };
37
40
 
38
- const options = useMemo<ChartOptions<'line'>>(() => {
39
- return {
40
- maintainAspectRatio: false,
41
- animation: {
42
- duration: 0,
43
- },
44
- elements: {
45
- line: {
46
- borderWidth: 1,
47
- },
48
- point: {
49
- radius: 2,
50
- },
51
- },
52
- scales: {
53
- y: {
54
- position: 'right',
55
- stacked: true,
56
- min: 0,
57
- max: Math.max(180, Math.ceil((max + 10) / 10) * 10),
58
- grid: {
59
- display: true,
60
- color: '#979ca0',
61
- },
62
- ticks: {
63
- stepSize: 30,
64
- },
65
- },
66
- x: {
67
- grid: {
68
- display: false,
69
- },
70
- ticks: {
71
- display: false,
72
- },
73
- },
74
- },
75
- };
76
- }, [max]);
77
-
41
+ const options = useMemo(() => getLineOptions(max), [max]);
78
42
  return (
79
43
  <div className="str-video__call-stats-line-chart-container">
80
44
  <Line
@@ -85,3 +49,28 @@ export const CallStatsLatencyChart = (props: {
85
49
  </div>
86
50
  );
87
51
  };
52
+
53
+ export default CallStatsLatencyChart;
54
+
55
+ const getLineOptions = (max: number): ChartOptions<'line'> => ({
56
+ maintainAspectRatio: false,
57
+ animation: { duration: 0 },
58
+ elements: {
59
+ line: { borderWidth: 1 },
60
+ point: { radius: 2 },
61
+ },
62
+ scales: {
63
+ y: {
64
+ position: 'right',
65
+ stacked: true,
66
+ min: 0,
67
+ max: Math.max(180, Math.ceil((max + 10) / 10) * 10),
68
+ grid: { display: true, color: '#979ca0' },
69
+ ticks: { stepSize: 30 },
70
+ },
71
+ x: {
72
+ grid: { display: false },
73
+ ticks: { display: false },
74
+ },
75
+ },
76
+ });
@@ -1,2 +1 @@
1
1
  export * from './CallStats';
2
- export * from './CallStatsLatencyChart';