@stream-io/video-react-sdk 1.4.5 → 1.6.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 +19 -0
- package/dist/css/styles.css +5 -5
- package/dist/css/styles.css.map +1 -1
- package/dist/index.cjs.js +441 -432
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +443 -434
- package/dist/index.es.js.map +1 -1
- package/dist/src/components/DropdownSelect/DropdownSelect.d.ts +1 -1
- package/dist/src/core/components/CallLayout/LivestreamLayout.d.ts +5 -0
- package/dist/src/core/components/CallLayout/PaginatedGridLayout.d.ts +5 -0
- package/dist/src/core/components/CallLayout/SpeakerLayout.d.ts +6 -1
- package/dist/src/core/components/ParticipantView/ParticipantView.d.ts +10 -0
- package/dist/src/core/components/Video/Video.d.ts +11 -1
- package/package.json +4 -4
- package/src/components/Button/CompositeButton.tsx +3 -0
- package/src/components/CallParticipantsList/CallParticipantListingItem.tsx +2 -4
- package/src/components/DropdownSelect/DropdownSelect.tsx +2 -2
- package/src/core/components/CallLayout/LivestreamLayout.tsx +9 -0
- package/src/core/components/CallLayout/PaginatedGridLayout.tsx +12 -1
- package/src/core/components/CallLayout/SpeakerLayout.tsx +11 -0
- package/src/core/components/ParticipantView/ParticipantActionsContextMenu.tsx +2 -2
- package/src/core/components/ParticipantView/ParticipantView.tsx +17 -0
- package/src/core/components/Video/Video.tsx +17 -2
|
@@ -2,7 +2,7 @@ import { ReactElement } from 'react';
|
|
|
2
2
|
export type DropDownSelectOptionProps = {
|
|
3
3
|
label: string;
|
|
4
4
|
selected?: boolean;
|
|
5
|
-
icon
|
|
5
|
+
icon?: string;
|
|
6
6
|
};
|
|
7
7
|
export declare const DropDownSelectOption: (props: DropDownSelectOptionProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
8
|
export declare const DropDownSelect: (props: {
|
|
@@ -26,6 +26,11 @@ export type LivestreamLayoutProps = {
|
|
|
26
26
|
* Whether to show the speaker name. Defaults to `false`.
|
|
27
27
|
*/
|
|
28
28
|
showSpeakerName?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* When set to `false` disables mirroring of the local partipant's video.
|
|
31
|
+
* @default true
|
|
32
|
+
*/
|
|
33
|
+
mirrorLocalParticipantVideo?: boolean;
|
|
29
34
|
/**
|
|
30
35
|
* The props to pass to the floating participant element.
|
|
31
36
|
*/
|
|
@@ -9,6 +9,11 @@ export type PaginatedGridLayoutProps = {
|
|
|
9
9
|
* @default false
|
|
10
10
|
*/
|
|
11
11
|
excludeLocalParticipant?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* When set to `false` disables mirroring of the local partipant's video.
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
mirrorLocalParticipantVideo?: boolean;
|
|
12
17
|
/**
|
|
13
18
|
* Turns on/off the pagination arrows.
|
|
14
19
|
* @default true
|
|
@@ -23,6 +23,11 @@ export type SpeakerLayoutProps = {
|
|
|
23
23
|
* @default false
|
|
24
24
|
*/
|
|
25
25
|
excludeLocalParticipant?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* When set to `false` disables mirroring of the local partipant's video.
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
mirrorLocalParticipantVideo?: boolean;
|
|
26
31
|
/**
|
|
27
32
|
* Turns on/off the pagination arrows.
|
|
28
33
|
* @default true
|
|
@@ -30,6 +35,6 @@ export type SpeakerLayoutProps = {
|
|
|
30
35
|
pageArrowsVisible?: boolean;
|
|
31
36
|
} & Pick<ParticipantViewProps, 'VideoPlaceholder'>;
|
|
32
37
|
export declare const SpeakerLayout: {
|
|
33
|
-
({ ParticipantViewUIBar, ParticipantViewUISpotlight, VideoPlaceholder, participantsBarPosition, participantsBarLimit, excludeLocalParticipant, pageArrowsVisible, }: SpeakerLayoutProps): import("react/jsx-runtime").JSX.Element | null;
|
|
38
|
+
({ ParticipantViewUIBar, ParticipantViewUISpotlight, VideoPlaceholder, participantsBarPosition, participantsBarLimit, mirrorLocalParticipantVideo, excludeLocalParticipant, pageArrowsVisible, }: SpeakerLayoutProps): import("react/jsx-runtime").JSX.Element | null;
|
|
34
39
|
displayName: string;
|
|
35
40
|
};
|
|
@@ -18,6 +18,11 @@ export type ParticipantViewProps = {
|
|
|
18
18
|
* You can use `none` if you're building an audio-only call.
|
|
19
19
|
*/
|
|
20
20
|
trackType?: VideoTrackType | 'none';
|
|
21
|
+
/**
|
|
22
|
+
* Forces participant's video to be mirrored or unmirrored. By default, video track
|
|
23
|
+
* from the local participant is mirrored, and all other videos are not mirrored.
|
|
24
|
+
*/
|
|
25
|
+
mirror?: boolean;
|
|
21
26
|
/**
|
|
22
27
|
* This prop is only useful for advanced use-cases (for example, building your own layout).
|
|
23
28
|
* When set to `true` it will mute the give participant's audio stream on the client side.
|
|
@@ -54,6 +59,11 @@ export declare const ParticipantView: import("react").ForwardRefExoticComponent<
|
|
|
54
59
|
* You can use `none` if you're building an audio-only call.
|
|
55
60
|
*/
|
|
56
61
|
trackType?: VideoTrackType | "none";
|
|
62
|
+
/**
|
|
63
|
+
* Forces participant's video to be mirrored or unmirrored. By default, video track
|
|
64
|
+
* from the local participant is mirrored, and all other videos are not mirrored.
|
|
65
|
+
*/
|
|
66
|
+
mirror?: boolean;
|
|
57
67
|
/**
|
|
58
68
|
* This prop is only useful for advanced use-cases (for example, building your own layout).
|
|
59
69
|
* When set to `true` it will mute the give participant's audio stream on the client side.
|
|
@@ -2,6 +2,16 @@ import { ComponentPropsWithoutRef, ComponentType } from 'react';
|
|
|
2
2
|
import { StreamVideoParticipant, VideoTrackType } from '@stream-io/video-client';
|
|
3
3
|
import { VideoPlaceholderProps } from './DefaultVideoPlaceholder';
|
|
4
4
|
export type VideoProps = ComponentPropsWithoutRef<'video'> & {
|
|
5
|
+
/**
|
|
6
|
+
* Pass false to disable rendering video and render fallback
|
|
7
|
+
* even if the participant has published video.
|
|
8
|
+
*/
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Forces the video to be mirrored or unmirrored. By default, video track
|
|
12
|
+
* from the local participant is mirrored, and all other videos are not mirrored.
|
|
13
|
+
*/
|
|
14
|
+
mirror?: boolean;
|
|
5
15
|
/**
|
|
6
16
|
* The track type to display.
|
|
7
17
|
*/
|
|
@@ -35,6 +45,6 @@ export type VideoProps = ComponentPropsWithoutRef<'video'> & {
|
|
|
35
45
|
};
|
|
36
46
|
};
|
|
37
47
|
export declare const Video: {
|
|
38
|
-
({ trackType, participant, className, VideoPlaceholder, refs, ...rest }: VideoProps): import("react/jsx-runtime").JSX.Element | null;
|
|
48
|
+
({ enabled, mirror, trackType, participant, className, VideoPlaceholder, refs, ...rest }: VideoProps): import("react/jsx-runtime").JSX.Element | null;
|
|
39
49
|
displayName: string;
|
|
40
50
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stream-io/video-react-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"packageManager": "yarn@3.2.4",
|
|
5
5
|
"main": "./dist/index.cjs.js",
|
|
6
6
|
"module": "./dist/index.es.js",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@floating-ui/react": "^0.26.24",
|
|
35
|
-
"@stream-io/video-client": "1.
|
|
35
|
+
"@stream-io/video-client": "1.8.0",
|
|
36
36
|
"@stream-io/video-filters-web": "0.1.4",
|
|
37
|
-
"@stream-io/video-react-bindings": "1.0
|
|
37
|
+
"@stream-io/video-react-bindings": "1.1.0",
|
|
38
38
|
"chart.js": "^4.4.4",
|
|
39
39
|
"clsx": "^2.0.0",
|
|
40
40
|
"react-chartjs-2": "^5.2.0"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@rollup/plugin-replace": "^5.0.7",
|
|
49
49
|
"@rollup/plugin-typescript": "^11.1.6",
|
|
50
50
|
"@stream-io/audio-filters-web": "^0.2.2",
|
|
51
|
-
"@stream-io/video-styling": "^1.0
|
|
51
|
+
"@stream-io/video-styling": "^1.1.0",
|
|
52
52
|
"@types/react": "^18.3.2",
|
|
53
53
|
"@types/react-dom": "^18.3.0",
|
|
54
54
|
"react": "^18.3.1",
|
|
@@ -31,6 +31,7 @@ export const CompositeButton = forwardRef<
|
|
|
31
31
|
IconButtonWithMenuProps
|
|
32
32
|
>(function CompositeButton(
|
|
33
33
|
{
|
|
34
|
+
disabled,
|
|
34
35
|
caption,
|
|
35
36
|
children,
|
|
36
37
|
className,
|
|
@@ -63,6 +64,7 @@ export const CompositeButton = forwardRef<
|
|
|
63
64
|
active && variant === 'primary',
|
|
64
65
|
'str-video__composite-button__button-group--active-secondary':
|
|
65
66
|
active && variant === 'secondary',
|
|
67
|
+
'str-video__composite-button__button-group--disabled': disabled,
|
|
66
68
|
})}
|
|
67
69
|
>
|
|
68
70
|
<button
|
|
@@ -72,6 +74,7 @@ export const CompositeButton = forwardRef<
|
|
|
72
74
|
e.preventDefault();
|
|
73
75
|
onClick?.(e);
|
|
74
76
|
}}
|
|
77
|
+
disabled={disabled}
|
|
75
78
|
{...restButtonProps}
|
|
76
79
|
>
|
|
77
80
|
{children}
|
|
@@ -11,10 +11,8 @@ import { IconButton } from '../Button';
|
|
|
11
11
|
import { MenuToggle, ToggleMenuButtonProps } from '../Menu';
|
|
12
12
|
import { WithTooltip } from '../Tooltip';
|
|
13
13
|
import { Avatar } from '../Avatar';
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
ParticipantViewContext,
|
|
17
|
-
} from '../../core/';
|
|
14
|
+
import { ParticipantActionsContextMenu } from '../../core/components/ParticipantView/ParticipantActionsContextMenu';
|
|
15
|
+
import { ParticipantViewContext } from '../../core/components/ParticipantView/ParticipantViewContext';
|
|
18
16
|
|
|
19
17
|
type CallParticipantListingItemProps = {
|
|
20
18
|
/** Participant object be rendered */
|
|
@@ -162,7 +162,7 @@ const Select = (props: {
|
|
|
162
162
|
export type DropDownSelectOptionProps = {
|
|
163
163
|
label: string;
|
|
164
164
|
selected?: boolean;
|
|
165
|
-
icon
|
|
165
|
+
icon?: string;
|
|
166
166
|
};
|
|
167
167
|
|
|
168
168
|
export const DropDownSelectOption = (props: DropDownSelectOptionProps) => {
|
|
@@ -179,7 +179,7 @@ export const DropDownSelectOption = (props: DropDownSelectOptionProps) => {
|
|
|
179
179
|
onClick: () => handleSelect(index),
|
|
180
180
|
})}
|
|
181
181
|
>
|
|
182
|
-
<Icon className="str-video__dropdown-icon" icon={icon} />
|
|
182
|
+
{icon && <Icon className="str-video__dropdown-icon" icon={icon} />}
|
|
183
183
|
<span className="str-video__dropdown-label">{label}</span>
|
|
184
184
|
</div>
|
|
185
185
|
);
|
|
@@ -44,6 +44,12 @@ export type LivestreamLayoutProps = {
|
|
|
44
44
|
*/
|
|
45
45
|
showSpeakerName?: boolean;
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* When set to `false` disables mirroring of the local partipant's video.
|
|
49
|
+
* @default true
|
|
50
|
+
*/
|
|
51
|
+
mirrorLocalParticipantVideo?: boolean;
|
|
52
|
+
|
|
47
53
|
/**
|
|
48
54
|
* The props to pass to the floating participant element.
|
|
49
55
|
*/
|
|
@@ -116,6 +122,9 @@ export const LivestreamLayout = (props: LivestreamLayoutProps) => {
|
|
|
116
122
|
)}
|
|
117
123
|
participant={currentSpeaker}
|
|
118
124
|
ParticipantViewUI={FloatingParticipantOverlay || Overlay}
|
|
125
|
+
mirror={
|
|
126
|
+
props.mirrorLocalParticipantVideo !== false ? undefined : false
|
|
127
|
+
}
|
|
119
128
|
muteAudio // audio is rendered by ParticipantsAudio
|
|
120
129
|
/>
|
|
121
130
|
)}
|
|
@@ -20,11 +20,12 @@ type PaginatedGridLayoutGroupProps = {
|
|
|
20
20
|
* The group of participants to render.
|
|
21
21
|
*/
|
|
22
22
|
group: Array<StreamVideoParticipant>;
|
|
23
|
-
} & Pick<ParticipantViewProps, 'VideoPlaceholder'> &
|
|
23
|
+
} & Pick<ParticipantViewProps, 'VideoPlaceholder' | 'mirror'> &
|
|
24
24
|
Required<Pick<ParticipantViewProps, 'ParticipantViewUI'>>;
|
|
25
25
|
|
|
26
26
|
const PaginatedGridLayoutGroup = ({
|
|
27
27
|
group,
|
|
28
|
+
mirror,
|
|
28
29
|
VideoPlaceholder,
|
|
29
30
|
ParticipantViewUI,
|
|
30
31
|
}: PaginatedGridLayoutGroupProps) => {
|
|
@@ -43,6 +44,7 @@ const PaginatedGridLayoutGroup = ({
|
|
|
43
44
|
key={participant.sessionId}
|
|
44
45
|
participant={participant}
|
|
45
46
|
muteAudio
|
|
47
|
+
mirror={mirror}
|
|
46
48
|
VideoPlaceholder={VideoPlaceholder}
|
|
47
49
|
ParticipantViewUI={ParticipantViewUI}
|
|
48
50
|
/>
|
|
@@ -63,6 +65,12 @@ export type PaginatedGridLayoutProps = {
|
|
|
63
65
|
*/
|
|
64
66
|
excludeLocalParticipant?: boolean;
|
|
65
67
|
|
|
68
|
+
/**
|
|
69
|
+
* When set to `false` disables mirroring of the local partipant's video.
|
|
70
|
+
* @default true
|
|
71
|
+
*/
|
|
72
|
+
mirrorLocalParticipantVideo?: boolean;
|
|
73
|
+
|
|
66
74
|
/**
|
|
67
75
|
* Turns on/off the pagination arrows.
|
|
68
76
|
* @default true
|
|
@@ -76,6 +84,7 @@ export const PaginatedGridLayout = (props: PaginatedGridLayoutProps) => {
|
|
|
76
84
|
? props.groupSize || GROUP_SIZE
|
|
77
85
|
: GROUP_SIZE,
|
|
78
86
|
excludeLocalParticipant = false,
|
|
87
|
+
mirrorLocalParticipantVideo = true,
|
|
79
88
|
pageArrowsVisible = true,
|
|
80
89
|
VideoPlaceholder,
|
|
81
90
|
ParticipantViewUI = DefaultParticipantViewUI,
|
|
@@ -121,6 +130,7 @@ export const PaginatedGridLayout = (props: PaginatedGridLayoutProps) => {
|
|
|
121
130
|
}, [page, pageCount]);
|
|
122
131
|
|
|
123
132
|
const selectedGroup = participantGroups[page];
|
|
133
|
+
const mirror = mirrorLocalParticipantVideo ? undefined : false;
|
|
124
134
|
|
|
125
135
|
if (!call) return null;
|
|
126
136
|
|
|
@@ -143,6 +153,7 @@ export const PaginatedGridLayout = (props: PaginatedGridLayoutProps) => {
|
|
|
143
153
|
{selectedGroup && (
|
|
144
154
|
<PaginatedGridLayoutGroup
|
|
145
155
|
group={selectedGroup}
|
|
156
|
+
mirror={mirror}
|
|
146
157
|
VideoPlaceholder={VideoPlaceholder}
|
|
147
158
|
ParticipantViewUI={ParticipantViewUI}
|
|
148
159
|
/>
|
|
@@ -41,6 +41,11 @@ export type SpeakerLayoutProps = {
|
|
|
41
41
|
* @default false
|
|
42
42
|
*/
|
|
43
43
|
excludeLocalParticipant?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* When set to `false` disables mirroring of the local partipant's video.
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
48
|
+
mirrorLocalParticipantVideo?: boolean;
|
|
44
49
|
/**
|
|
45
50
|
* Turns on/off the pagination arrows.
|
|
46
51
|
* @default true
|
|
@@ -58,6 +63,7 @@ export const SpeakerLayout = ({
|
|
|
58
63
|
VideoPlaceholder,
|
|
59
64
|
participantsBarPosition = 'bottom',
|
|
60
65
|
participantsBarLimit,
|
|
66
|
+
mirrorLocalParticipantVideo = true,
|
|
61
67
|
excludeLocalParticipant = false,
|
|
62
68
|
pageArrowsVisible = true,
|
|
63
69
|
}: SpeakerLayoutProps) => {
|
|
@@ -117,6 +123,8 @@ export const SpeakerLayout = ({
|
|
|
117
123
|
);
|
|
118
124
|
}
|
|
119
125
|
|
|
126
|
+
const mirror = mirrorLocalParticipantVideo ? undefined : false;
|
|
127
|
+
|
|
120
128
|
if (!call) return null;
|
|
121
129
|
|
|
122
130
|
return (
|
|
@@ -134,6 +142,7 @@ export const SpeakerLayout = ({
|
|
|
134
142
|
<ParticipantView
|
|
135
143
|
participant={participantInSpotlight}
|
|
136
144
|
muteAudio={true}
|
|
145
|
+
mirror={mirror}
|
|
137
146
|
trackType={
|
|
138
147
|
isSpeakerScreenSharing ? 'screenShareTrack' : 'videoTrack'
|
|
139
148
|
}
|
|
@@ -164,6 +173,7 @@ export const SpeakerLayout = ({
|
|
|
164
173
|
participant={participantInSpotlight}
|
|
165
174
|
ParticipantViewUI={ParticipantViewUIBar}
|
|
166
175
|
VideoPlaceholder={VideoPlaceholder}
|
|
176
|
+
mirror={mirror}
|
|
167
177
|
muteAudio={true}
|
|
168
178
|
/>
|
|
169
179
|
</div>
|
|
@@ -177,6 +187,7 @@ export const SpeakerLayout = ({
|
|
|
177
187
|
participant={participant}
|
|
178
188
|
ParticipantViewUI={ParticipantViewUIBar}
|
|
179
189
|
VideoPlaceholder={VideoPlaceholder}
|
|
190
|
+
mirror={mirror}
|
|
180
191
|
muteAudio={true}
|
|
181
192
|
/>
|
|
182
193
|
</div>
|
|
@@ -11,9 +11,9 @@ import { useParticipantViewContext } from './ParticipantViewContext';
|
|
|
11
11
|
import {
|
|
12
12
|
GenericMenu,
|
|
13
13
|
GenericMenuButtonItem,
|
|
14
|
-
Icon,
|
|
15
14
|
useMenuContext,
|
|
16
|
-
} from '../../../components';
|
|
15
|
+
} from '../../../components/Menu';
|
|
16
|
+
import { Icon } from '../../../components/Icon';
|
|
17
17
|
|
|
18
18
|
export const ParticipantActionsContextMenu = () => {
|
|
19
19
|
const { participant, participantViewElement, videoElement } =
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
StreamVideoParticipant,
|
|
14
14
|
VideoTrackType,
|
|
15
15
|
} from '@stream-io/video-client';
|
|
16
|
+
import { useCallStateHooks } from '@stream-io/video-react-bindings';
|
|
16
17
|
|
|
17
18
|
import { Audio } from '../Audio';
|
|
18
19
|
import { Video, VideoProps } from '../Video';
|
|
@@ -41,6 +42,12 @@ export type ParticipantViewProps = {
|
|
|
41
42
|
*/
|
|
42
43
|
trackType?: VideoTrackType | 'none';
|
|
43
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Forces participant's video to be mirrored or unmirrored. By default, video track
|
|
47
|
+
* from the local participant is mirrored, and all other videos are not mirrored.
|
|
48
|
+
*/
|
|
49
|
+
mirror?: boolean;
|
|
50
|
+
|
|
44
51
|
/**
|
|
45
52
|
* This prop is only useful for advanced use-cases (for example, building your own layout).
|
|
46
53
|
* When set to `true` it will mute the give participant's audio stream on the client side.
|
|
@@ -68,6 +75,7 @@ export const ParticipantView = forwardRef<HTMLDivElement, ParticipantViewProps>(
|
|
|
68
75
|
{
|
|
69
76
|
participant,
|
|
70
77
|
trackType = 'videoTrack',
|
|
78
|
+
mirror,
|
|
71
79
|
muteAudio,
|
|
72
80
|
refs: { setVideoElement, setVideoPlaceholderElement } = {},
|
|
73
81
|
className,
|
|
@@ -100,6 +108,9 @@ export const ParticipantView = forwardRef<HTMLDivElement, ParticipantViewProps>(
|
|
|
100
108
|
trackType,
|
|
101
109
|
});
|
|
102
110
|
|
|
111
|
+
const { useIncomingVideoSettings } = useCallStateHooks();
|
|
112
|
+
const { isParticipantVideoEnabled } = useIncomingVideoSettings();
|
|
113
|
+
|
|
103
114
|
const participantViewContextValue = useMemo(
|
|
104
115
|
() => ({
|
|
105
116
|
participant,
|
|
@@ -167,6 +178,12 @@ export const ParticipantView = forwardRef<HTMLDivElement, ParticipantViewProps>(
|
|
|
167
178
|
participant={participant}
|
|
168
179
|
trackType={trackType}
|
|
169
180
|
refs={videoRefs}
|
|
181
|
+
enabled={
|
|
182
|
+
isLocalParticipant ||
|
|
183
|
+
trackType !== 'videoTrack' ||
|
|
184
|
+
isParticipantVideoEnabled(participant.sessionId)
|
|
185
|
+
}
|
|
186
|
+
mirror={mirror}
|
|
170
187
|
autoPlay
|
|
171
188
|
/>
|
|
172
189
|
{isComponentType(ParticipantViewUI) ? (
|
|
@@ -20,6 +20,16 @@ import {
|
|
|
20
20
|
import { useCall } from '@stream-io/video-react-bindings';
|
|
21
21
|
|
|
22
22
|
export type VideoProps = ComponentPropsWithoutRef<'video'> & {
|
|
23
|
+
/**
|
|
24
|
+
* Pass false to disable rendering video and render fallback
|
|
25
|
+
* even if the participant has published video.
|
|
26
|
+
*/
|
|
27
|
+
enabled?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Forces the video to be mirrored or unmirrored. By default, video track
|
|
30
|
+
* from the local participant is mirrored, and all other videos are not mirrored.
|
|
31
|
+
*/
|
|
32
|
+
mirror?: boolean;
|
|
23
33
|
/**
|
|
24
34
|
* The track type to display.
|
|
25
35
|
*/
|
|
@@ -54,6 +64,8 @@ export type VideoProps = ComponentPropsWithoutRef<'video'> & {
|
|
|
54
64
|
};
|
|
55
65
|
|
|
56
66
|
export const Video = ({
|
|
67
|
+
enabled,
|
|
68
|
+
mirror,
|
|
57
69
|
trackType,
|
|
58
70
|
participant,
|
|
59
71
|
className,
|
|
@@ -139,8 +151,11 @@ export const Video = ({
|
|
|
139
151
|
trackType === 'none' ||
|
|
140
152
|
viewportVisibilityState?.[trackType] === VisibilityState.INVISIBLE;
|
|
141
153
|
|
|
142
|
-
const hasNoVideoOrInvisible = !isPublishingTrack || isInvisible;
|
|
143
|
-
const mirrorVideo =
|
|
154
|
+
const hasNoVideoOrInvisible = !enabled || !isPublishingTrack || isInvisible;
|
|
155
|
+
const mirrorVideo =
|
|
156
|
+
mirror === undefined
|
|
157
|
+
? isLocalParticipant && trackType === 'videoTrack'
|
|
158
|
+
: mirror;
|
|
144
159
|
const isScreenShareTrack = trackType === 'screenShareTrack';
|
|
145
160
|
return (
|
|
146
161
|
<>
|