@stream-io/video-react-sdk 1.39.3 → 1.40.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.
@@ -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
- export declare const DefaultParticipantViewUI: ({ indicatorsVisible, menuPlacement, showMenuButton, ParticipantActionsContextMenu, }: DefaultParticipantViewUIProps) => import("react/jsx-runtime").JSX.Element;
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.39.3",
3
+ "version": "1.40.1",
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.55.2",
49
- "@stream-io/video-filters-web": "0.8.3",
50
- "@stream-io/video-react-bindings": "1.18.3",
48
+ "@stream-io/video-client": "1.56.0",
49
+ "@stream-io/video-filters-web": "0.8.5",
50
+ "@stream-io/video-react-bindings": "1.19.1",
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.1",
63
+ "@stream-io/audio-filters-web": "^0.10.3",
64
64
  "@stream-io/typescript-config": "^0.0.0",
65
- "@stream-io/video-styling": "^1.14.2",
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",
@@ -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
  };
@@ -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",