@stream-io/video-react-sdk 1.39.2 → 1.40.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 +32 -0
- package/dist/css/embedded.css +69 -0
- package/dist/css/embedded.css.map +1 -1
- package/dist/css/styles.css +69 -0
- package/dist/css/styles.css.map +1 -1
- package/dist/embedded.cjs.js +21 -27
- package/dist/embedded.cjs.js.map +1 -1
- package/dist/embedded.es.js +22 -28
- package/dist/embedded.es.js.map +1 -1
- package/dist/index.cjs.js +23 -28
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +24 -30
- package/dist/index.es.js.map +1 -1
- package/dist/src/core/components/CallLayout/hooks.d.ts +0 -1
- package/dist/src/core/components/ParticipantView/DefaultParticipantViewUI.d.ts +14 -1
- package/dist/src/translations/index.d.ts +2 -0
- package/package.json +6 -6
- package/src/core/components/CallLayout/SpeakerLayout.tsx +5 -2
- package/src/core/components/CallLayout/hooks.ts +0 -28
- package/src/core/components/ParticipantView/DefaultParticipantViewUI.tsx +49 -0
- package/src/translations/en.json +3 -0
|
@@ -14,5 +14,4 @@ export declare const useFilteredParticipants: ({ excludeLocalParticipant, filter
|
|
|
14
14
|
}) => StreamVideoParticipant[];
|
|
15
15
|
export declare const applyParticipantsFilter: (participants: StreamVideoParticipant[], filter: ParticipantPredicate | ParticipantFilter) => StreamVideoParticipant[];
|
|
16
16
|
export declare const usePaginatedLayoutSortPreset: (call: Call | undefined) => void;
|
|
17
|
-
export declare const useSpeakerLayoutSortPreset: (call: Call | undefined, isOneOnOneCall: boolean) => void;
|
|
18
17
|
export declare const useRawRemoteParticipants: () => StreamVideoParticipant[];
|
|
@@ -17,8 +17,21 @@ export type DefaultParticipantViewUIProps = {
|
|
|
17
17
|
* Custom component to render the context menu
|
|
18
18
|
*/
|
|
19
19
|
ParticipantActionsContextMenu?: ComponentType;
|
|
20
|
+
/**
|
|
21
|
+
* Rendered over the tile when this participant's audio is blocked by the
|
|
22
|
+
* browser's autoplay policy. Selecting it calls {@link Call.resumeAudio} to
|
|
23
|
+
* unblock audio. Defaults to
|
|
24
|
+
* {@link DefaultAudioBlockedNotification}; pass `null` to disable.
|
|
25
|
+
*/
|
|
26
|
+
AudioBlockedNotification?: ComponentType | null;
|
|
20
27
|
};
|
|
21
28
|
export declare const DefaultScreenShareOverlay: () => import("react/jsx-runtime").JSX.Element;
|
|
22
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Rendered over a remote participant's tile when the browser's autoplay policy
|
|
31
|
+
* has blocked their audio. Selecting it calls `call.resumeAudio()`, unblocking
|
|
32
|
+
* every blocked element at once.
|
|
33
|
+
*/
|
|
34
|
+
export declare const DefaultAudioBlockedNotification: () => import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
export declare const DefaultParticipantViewUI: ({ indicatorsVisible, menuPlacement, showMenuButton, ParticipantActionsContextMenu, AudioBlockedNotification, }: DefaultParticipantViewUIProps) => import("react/jsx-runtime").JSX.Element;
|
|
23
36
|
export declare const ParticipantDetails: ({ indicatorsVisible, }: Pick<DefaultParticipantViewUIProps, "indicatorsVisible">) => import("react/jsx-runtime").JSX.Element;
|
|
24
37
|
export declare const SpeechIndicator: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -51,6 +51,8 @@ export declare const translations: {
|
|
|
51
51
|
"You have no permission to share your audio": string;
|
|
52
52
|
"You are presenting your screen": string;
|
|
53
53
|
"Stop Screen Sharing": string;
|
|
54
|
+
"Audio is blocked by your system": string;
|
|
55
|
+
"Click or tap to play audio": string;
|
|
54
56
|
Allow: string;
|
|
55
57
|
Revoke: string;
|
|
56
58
|
Dismiss: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/video-react-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.40.0",
|
|
4
4
|
"main": "./dist/index.cjs.js",
|
|
5
5
|
"module": "./dist/index.es.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@floating-ui/react": "^0.27.19",
|
|
48
|
-
"@stream-io/video-client": "1.
|
|
49
|
-
"@stream-io/video-filters-web": "0.8.
|
|
50
|
-
"@stream-io/video-react-bindings": "1.
|
|
48
|
+
"@stream-io/video-client": "1.56.0",
|
|
49
|
+
"@stream-io/video-filters-web": "0.8.4",
|
|
50
|
+
"@stream-io/video-react-bindings": "1.19.0",
|
|
51
51
|
"chart.js": "^4.5.1",
|
|
52
52
|
"clsx": "^2.1.1",
|
|
53
53
|
"react-chartjs-2": "^5.3.1"
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
"@rollup/plugin-json": "^6.1.0",
|
|
61
61
|
"@rollup/plugin-replace": "^6.0.3",
|
|
62
62
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
63
|
-
"@stream-io/audio-filters-web": "^0.10.
|
|
63
|
+
"@stream-io/audio-filters-web": "^0.10.2",
|
|
64
64
|
"@stream-io/typescript-config": "^0.0.0",
|
|
65
|
-
"@stream-io/video-styling": "^1.
|
|
65
|
+
"@stream-io/video-styling": "^1.15.0",
|
|
66
66
|
"@types/node": "^25.9.3",
|
|
67
67
|
"@types/react": "~19.2.15",
|
|
68
68
|
"@types/react-dom": "~19.2.3",
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { hasScreenShare } from '@stream-io/video-client';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
useCall,
|
|
6
|
+
useCallStateHooks,
|
|
7
|
+
useSpeakerLayoutSortPreset,
|
|
8
|
+
} from '@stream-io/video-react-bindings';
|
|
5
9
|
|
|
6
10
|
import {
|
|
7
11
|
DefaultParticipantViewUI,
|
|
@@ -19,7 +23,6 @@ import {
|
|
|
19
23
|
ParticipantPredicate,
|
|
20
24
|
useFilteredParticipants,
|
|
21
25
|
useRawRemoteParticipants,
|
|
22
|
-
useSpeakerLayoutSortPreset,
|
|
23
26
|
} from './hooks';
|
|
24
27
|
import { useCalculateHardLimit } from '../../hooks/useCalculateHardLimit';
|
|
25
28
|
import { ParticipantsAudio } from '../Audio';
|
|
@@ -2,16 +2,12 @@ import { useEffect, useMemo } from 'react';
|
|
|
2
2
|
import {
|
|
3
3
|
Call,
|
|
4
4
|
CallTypes,
|
|
5
|
-
combineComparators,
|
|
6
|
-
Comparator,
|
|
7
5
|
defaultSortPreset,
|
|
8
6
|
hasAudio,
|
|
9
7
|
hasScreenShare,
|
|
10
8
|
hasVideo,
|
|
11
9
|
isPinned,
|
|
12
10
|
paginatedLayoutSortPreset,
|
|
13
|
-
screenSharing,
|
|
14
|
-
speakerLayoutSortPreset,
|
|
15
11
|
StreamVideoParticipant,
|
|
16
12
|
} from '@stream-io/video-client';
|
|
17
13
|
import { useCallStateHooks } from '@stream-io/video-react-bindings';
|
|
@@ -94,24 +90,6 @@ export const usePaginatedLayoutSortPreset = (call: Call | undefined) => {
|
|
|
94
90
|
}, [call]);
|
|
95
91
|
};
|
|
96
92
|
|
|
97
|
-
export const useSpeakerLayoutSortPreset = (
|
|
98
|
-
call: Call | undefined,
|
|
99
|
-
isOneOnOneCall: boolean,
|
|
100
|
-
) => {
|
|
101
|
-
useEffect(() => {
|
|
102
|
-
if (!call) return;
|
|
103
|
-
// always show the remote participant in the spotlight
|
|
104
|
-
if (isOneOnOneCall) {
|
|
105
|
-
call.setSortParticipantsBy(combineComparators(screenSharing, loggedIn));
|
|
106
|
-
} else {
|
|
107
|
-
call.setSortParticipantsBy(speakerLayoutSortPreset);
|
|
108
|
-
}
|
|
109
|
-
return () => {
|
|
110
|
-
resetSortPreset(call);
|
|
111
|
-
};
|
|
112
|
-
}, [call, isOneOnOneCall]);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
93
|
export const useRawRemoteParticipants = () => {
|
|
116
94
|
const { useRawParticipants } = useCallStateHooks();
|
|
117
95
|
const rawParticipants = useRawParticipants();
|
|
@@ -128,9 +106,3 @@ const resetSortPreset = (call: Call) => {
|
|
|
128
106
|
callConfig.options.sortParticipantsBy || defaultSortPreset,
|
|
129
107
|
);
|
|
130
108
|
};
|
|
131
|
-
|
|
132
|
-
const loggedIn: Comparator<StreamVideoParticipant> = (a, b) => {
|
|
133
|
-
if (a.isLocalParticipant) return 1;
|
|
134
|
-
if (b.isLocalParticipant) return -1;
|
|
135
|
-
return 0;
|
|
136
|
-
};
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from '@stream-io/video-client';
|
|
10
10
|
import {
|
|
11
11
|
useCall,
|
|
12
|
+
useCallStateHooks,
|
|
12
13
|
useI18n,
|
|
13
14
|
useIsAudioConnecting,
|
|
14
15
|
useIsVideoConnecting,
|
|
@@ -44,6 +45,13 @@ export type DefaultParticipantViewUIProps = {
|
|
|
44
45
|
* Custom component to render the context menu
|
|
45
46
|
*/
|
|
46
47
|
ParticipantActionsContextMenu?: ComponentType;
|
|
48
|
+
/**
|
|
49
|
+
* Rendered over the tile when this participant's audio is blocked by the
|
|
50
|
+
* browser's autoplay policy. Selecting it calls {@link Call.resumeAudio} to
|
|
51
|
+
* unblock audio. Defaults to
|
|
52
|
+
* {@link DefaultAudioBlockedNotification}; pass `null` to disable.
|
|
53
|
+
*/
|
|
54
|
+
AudioBlockedNotification?: ComponentType | null;
|
|
47
55
|
};
|
|
48
56
|
|
|
49
57
|
const ToggleButton = forwardRef<HTMLButtonElement, ToggleMenuButtonProps>(
|
|
@@ -79,14 +87,52 @@ export const DefaultScreenShareOverlay = () => {
|
|
|
79
87
|
);
|
|
80
88
|
};
|
|
81
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Rendered over a remote participant's tile when the browser's autoplay policy
|
|
92
|
+
* has blocked their audio. Selecting it calls `call.resumeAudio()`, unblocking
|
|
93
|
+
* every blocked element at once.
|
|
94
|
+
*/
|
|
95
|
+
export const DefaultAudioBlockedNotification = () => {
|
|
96
|
+
const call = useCall();
|
|
97
|
+
const { t } = useI18n();
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<button
|
|
101
|
+
type="button"
|
|
102
|
+
className="str-video__audio-blocked-notification"
|
|
103
|
+
onClick={call?.resumeAudio}
|
|
104
|
+
aria-live="polite"
|
|
105
|
+
>
|
|
106
|
+
<span className="str-video__audio-blocked-notification__message">
|
|
107
|
+
<Icon icon="speaker" />
|
|
108
|
+
<span className="str-video__audio-blocked-notification__text">
|
|
109
|
+
<span className="str-video__audio-blocked-notification__title">
|
|
110
|
+
{t('Audio is blocked by your system')}
|
|
111
|
+
</span>
|
|
112
|
+
<span className="str-video__audio-blocked-notification__subtitle">
|
|
113
|
+
{t('Click or tap to play audio')}
|
|
114
|
+
</span>
|
|
115
|
+
</span>
|
|
116
|
+
</span>
|
|
117
|
+
</button>
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
|
|
82
121
|
export const DefaultParticipantViewUI = ({
|
|
83
122
|
indicatorsVisible = true,
|
|
84
123
|
menuPlacement = 'bottom-start',
|
|
85
124
|
showMenuButton = true,
|
|
86
125
|
ParticipantActionsContextMenu = DefaultParticipantActionsContextMenu,
|
|
126
|
+
AudioBlockedNotification = DefaultAudioBlockedNotification,
|
|
87
127
|
}: DefaultParticipantViewUIProps) => {
|
|
88
128
|
const { participant, trackType } = useParticipantViewContext();
|
|
129
|
+
const { useAutoplayBlockedSessionIds } = useCallStateHooks();
|
|
130
|
+
const blockedSessionIds = useAutoplayBlockedSessionIds();
|
|
89
131
|
const isScreenSharing = hasScreenShare(participant);
|
|
132
|
+
const shouldShowAudioBlockedNotification =
|
|
133
|
+
!participant.isLocalParticipant &&
|
|
134
|
+
trackType !== 'screenShareTrack' &&
|
|
135
|
+
blockedSessionIds.includes(participant.sessionId);
|
|
90
136
|
|
|
91
137
|
if (
|
|
92
138
|
participant.isLocalParticipant &&
|
|
@@ -114,6 +160,9 @@ export const DefaultParticipantViewUI = ({
|
|
|
114
160
|
)}
|
|
115
161
|
<Reaction participant={participant} />
|
|
116
162
|
<ParticipantDetails indicatorsVisible={indicatorsVisible} />
|
|
163
|
+
{AudioBlockedNotification && shouldShowAudioBlockedNotification && (
|
|
164
|
+
<AudioBlockedNotification />
|
|
165
|
+
)}
|
|
117
166
|
</>
|
|
118
167
|
);
|
|
119
168
|
};
|
package/src/translations/en.json
CHANGED
|
@@ -54,6 +54,9 @@
|
|
|
54
54
|
"You are presenting your screen": "You are presenting your screen",
|
|
55
55
|
"Stop Screen Sharing": "Stop Screen Sharing",
|
|
56
56
|
|
|
57
|
+
"Audio is blocked by your system": "Audio is blocked by your system",
|
|
58
|
+
"Click or tap to play audio": "Click or tap to play audio",
|
|
59
|
+
|
|
57
60
|
"Allow": "Allow",
|
|
58
61
|
"Revoke": "Revoke",
|
|
59
62
|
"Dismiss": "Dismiss",
|