-
Notifications
You must be signed in to change notification settings - Fork 78
Expand file tree
/
Copy pathRemoteScreenShare.tsx
More file actions
140 lines (133 loc) · 4.85 KB
/
RemoteScreenShare.tsx
File metadata and controls
140 lines (133 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { Spinner, SpinnerSize, Stack } from '@fluentui/react';
import React, { useEffect } from 'react';
import { useLocale } from '../../localization';
import { StreamMedia } from '../StreamMedia';
import { VideoTile } from '../VideoTile';
import { CreateVideoStreamViewResult, VideoStreamOptions } from '../../types';
import { ReactionResources, VideoGalleryLocalParticipant, VideoGalleryRemoteParticipant } from '../../types';
import { loadingStyle } from './styles/RemoteScreenShare.styles';
import { _formatString } from '@internal/acs-ui-common';
import { MeetingReactionOverlay } from '../MeetingReactionOverlay';
/**
* A memoized version of VideoTile for rendering the remote screen share stream. React.memo is used for a performance
* boost by memoizing the same rendered component to avoid rerendering this when the parent component rerenders.
* https://reactjs.org/docs/react-api.html#reactmemo
*/
export const RemoteScreenShare = React.memo(
(props: {
userId: string;
displayName?: string;
onCreateRemoteStreamView?: (
userId: string,
options?: VideoStreamOptions
) => Promise<void | CreateVideoStreamViewResult>;
onDisposeRemoteStreamView?: (userId: string) => Promise<void>;
isAvailable?: boolean;
isReceiving?: boolean;
isMuted?: boolean;
isSpeaking?: boolean;
renderElement?: HTMLElement;
participantVideoScalingMode?: VideoStreamOptions;
reactionResources?: ReactionResources;
localParticipant?: VideoGalleryLocalParticipant;
remoteParticipants?: VideoGalleryRemoteParticipant[];
/* @conditional-compile-remove(ppt-live) */
isPPTLive?: boolean;
}) => {
const {
userId,
displayName,
isMuted,
renderElement,
onCreateRemoteStreamView,
onDisposeRemoteStreamView,
isReceiving,
participantVideoScalingMode,
reactionResources,
localParticipant,
remoteParticipants,
/* @conditional-compile-remove(ppt-live) */
isPPTLive
} = props;
const locale = useLocale();
if (!renderElement) {
/**
* TODO: We need to pass in the scaling mode of the screen share participant to this function because when we
* call this it will recreate both streams (video and screen share) and we need to make sure that the scaling
* mode is the same as before we started the screen share.
*
* We should deprecate the current function and replace it with a
* createRemoteScreenShareStreamView and createRemoteVideoStreamView.
*/
onCreateRemoteStreamView && onCreateRemoteStreamView(userId, participantVideoScalingMode);
}
useEffect(() => {
return () => {
// TODO: Isolate disposing behaviors for screenShare and videoStream
onDisposeRemoteStreamView && onDisposeRemoteStreamView(userId);
};
}, [onDisposeRemoteStreamView, userId]);
const loadingMessage = displayName
? _formatString(locale.strings.videoGallery.screenShareLoadingMessage, {
participant: displayName
})
: '';
/* @conditional-compile-remove(ppt-live) */
if (isPPTLive) {
return (
<VideoTile
renderElement={
renderElement ? (
<StreamMedia
videoStreamElement={renderElement}
loadingState={isReceiving === false ? 'loading' : 'none'}
/>
) : undefined
}
onRenderPlaceholder={() => <LoadingSpinner loadingMessage={loadingMessage} />}
overlay={
reactionResources && (
<MeetingReactionOverlay
reactionResources={reactionResources}
localParticipant={localParticipant}
remoteParticipants={remoteParticipants}
overlayMode="screen-share"
/>
)
}
/>
);
}
return (
<VideoTile
displayName={displayName}
isMuted={isMuted}
renderElement={
renderElement ? (
<StreamMedia videoStreamElement={renderElement} loadingState={isReceiving === false ? 'loading' : 'none'} />
) : undefined
}
onRenderPlaceholder={() => <LoadingSpinner loadingMessage={loadingMessage} />}
overlay={
reactionResources && (
<MeetingReactionOverlay
reactionResources={reactionResources}
localParticipant={localParticipant}
remoteParticipants={remoteParticipants}
overlayMode="screen-share"
/>
)
}
/>
);
}
);
const LoadingSpinner = (props: { loadingMessage: string }): JSX.Element => {
return (
<Stack verticalAlign="center" className={loadingStyle}>
<Spinner label={props.loadingMessage} size={SpinnerSize.xSmall} aria-live={'assertive'} />
</Stack>
);
};