|
@@ -6,9 +6,10 @@ import { jitsiLocalStorage } from '@jitsi/js-utils/jitsi-local-storage';
|
6
|
6
|
import React, { useState, useEffect, useCallback, useRef } from 'react';
|
7
|
7
|
import uuid from 'uuid';
|
8
|
8
|
|
9
|
|
-import { Dialog, hideDialog } from '../../base/dialog';
|
|
9
|
+import { Dialog, hideDialog, openDialog } from '../../base/dialog';
|
10
|
10
|
import { translate } from '../../base/i18n';
|
11
|
11
|
import { Icon, IconCloseSmall, IconPlusCircle, IconShareDesktop } from '../../base/icons';
|
|
12
|
+import { browser, JitsiTrackErrors } from '../../base/lib-jitsi-meet';
|
12
|
13
|
import { createLocalTrack } from '../../base/lib-jitsi-meet/functions';
|
13
|
14
|
import { VIDEO_TYPE } from '../../base/media';
|
14
|
15
|
import { connect } from '../../base/redux';
|
|
@@ -92,6 +93,14 @@ type Props = {
|
92
|
93
|
*/
|
93
|
94
|
dispatch: Function,
|
94
|
95
|
|
|
96
|
+ /**
|
|
97
|
+ * The initial options copied in the state for the {@code VirtualBackground} component.
|
|
98
|
+ *
|
|
99
|
+ * NOTE: currently used only for electron in order to open the dialog in the correct state after desktop sharing
|
|
100
|
+ * selection.
|
|
101
|
+ */
|
|
102
|
+ initialOptions: Object,
|
|
103
|
+
|
95
|
104
|
/**
|
96
|
105
|
* Invoked to obtain translated strings.
|
97
|
106
|
*/
|
|
@@ -102,13 +111,39 @@ const onError = event => {
|
102
|
111
|
event.target.style.display = 'none';
|
103
|
112
|
};
|
104
|
113
|
|
|
114
|
+
|
|
115
|
+/**
|
|
116
|
+ * Maps (parts of) the redux state to the associated props for the
|
|
117
|
+ * {@code VirtualBackground} component.
|
|
118
|
+ *
|
|
119
|
+ * @param {Object} state - The Redux state.
|
|
120
|
+ * @private
|
|
121
|
+ * @returns {{Props}}
|
|
122
|
+ */
|
|
123
|
+function _mapStateToProps(state): Object {
|
|
124
|
+ return {
|
|
125
|
+ _virtualBackground: state['features/virtual-background'],
|
|
126
|
+ _selectedThumbnail: state['features/virtual-background'].selectedThumbnail,
|
|
127
|
+ _jitsiTrack: getLocalVideoTrack(state['features/base/tracks'])?.jitsiTrack
|
|
128
|
+ };
|
|
129
|
+}
|
|
130
|
+
|
|
131
|
+const VirtualBackgroundDialog = translate(connect(_mapStateToProps)(VirtualBackground));
|
|
132
|
+
|
105
|
133
|
/**
|
106
|
134
|
* Renders virtual background dialog.
|
107
|
135
|
*
|
108
|
136
|
* @returns {ReactElement}
|
109
|
137
|
*/
|
110
|
|
-function VirtualBackground({ _jitsiTrack, _selectedThumbnail, _virtualBackground, dispatch, t }: Props) {
|
111
|
|
- const [ options, setOptions ] = useState({});
|
|
138
|
+function VirtualBackground({
|
|
139
|
+ _jitsiTrack,
|
|
140
|
+ _selectedThumbnail,
|
|
141
|
+ _virtualBackground,
|
|
142
|
+ dispatch,
|
|
143
|
+ initialOptions,
|
|
144
|
+ t
|
|
145
|
+}: Props) {
|
|
146
|
+ const [ options, setOptions ] = useState({ ...initialOptions });
|
112
|
147
|
const localImages = jitsiLocalStorage.getItem('virtualBackgrounds');
|
113
|
148
|
const [ storedImages, setStoredImages ] = useState<Array<Image>>((localImages && Bourne.parse(localImages)) || []);
|
114
|
149
|
const [ loading, setLoading ] = useState(false);
|
|
@@ -180,23 +215,56 @@ function VirtualBackground({ _jitsiTrack, _selectedThumbnail, _virtualBackground
|
180
|
215
|
|
181
|
216
|
|
182
|
217
|
const shareDesktop = useCallback(async () => {
|
183
|
|
- const url = await createLocalTrack('desktop', '');
|
|
218
|
+ let isCancelled = false, url;
|
|
219
|
+
|
|
220
|
+ try {
|
|
221
|
+ url = await createLocalTrack('desktop', '');
|
|
222
|
+ } catch (e) {
|
|
223
|
+ if (e.name === JitsiTrackErrors.SCREENSHARING_USER_CANCELED) {
|
|
224
|
+ isCancelled = true;
|
|
225
|
+ } else {
|
|
226
|
+ logger.error(e);
|
|
227
|
+ }
|
|
228
|
+ }
|
184
|
229
|
|
185
|
230
|
if (!url) {
|
186
|
|
- dispatch(showErrorNotification({
|
187
|
|
- titleKey: 'virtualBackground.desktopShareError'
|
188
|
|
- }));
|
189
|
|
- logger.error('Could not create desktop share as a virtual background!');
|
|
231
|
+ if (!isCancelled) {
|
|
232
|
+ dispatch(showErrorNotification({
|
|
233
|
+ titleKey: 'virtualBackground.desktopShareError'
|
|
234
|
+ }));
|
|
235
|
+ logger.error('Could not create desktop share as a virtual background!');
|
|
236
|
+ }
|
|
237
|
+
|
|
238
|
+ /**
|
|
239
|
+ * For electron createLocalTrack will open the {@code DesktopPicker} dialog and hide the
|
|
240
|
+ * {@code VirtualBackgroundDialog}. That's why we need to reopen the {@code VirtualBackgroundDialog}
|
|
241
|
+ * and restore the current state through {@code initialOptions} prop.
|
|
242
|
+ */
|
|
243
|
+ if (browser.isElectron()) {
|
|
244
|
+ dispatch(openDialog(VirtualBackgroundDialog, { initialOptions: options }));
|
|
245
|
+ }
|
190
|
246
|
|
191
|
247
|
return;
|
192
|
248
|
}
|
193
|
|
- setOptions({
|
|
249
|
+
|
|
250
|
+ const newOptions = {
|
194
|
251
|
backgroundType: VIRTUAL_BACKGROUND_TYPE.DESKTOP_SHARE,
|
195
|
252
|
enabled: true,
|
196
|
253
|
selectedThumbnail: 'desktop-share',
|
197
|
254
|
url
|
198
|
|
- });
|
199
|
|
- }, []);
|
|
255
|
+ };
|
|
256
|
+
|
|
257
|
+ /**
|
|
258
|
+ * For electron createLocalTrack will open the {@code DesktopPicker} dialog and hide the
|
|
259
|
+ * {@code VirtualBackgroundDialog}. That's why we need to reopen the {@code VirtualBackgroundDialog}
|
|
260
|
+ * and force it to show desktop share virtual background through {@code initialOptions} prop.
|
|
261
|
+ */
|
|
262
|
+ if (browser.isElectron()) {
|
|
263
|
+ dispatch(openDialog(VirtualBackgroundDialog, { initialOptions: newOptions }));
|
|
264
|
+ } else {
|
|
265
|
+ setOptions(newOptions);
|
|
266
|
+ }
|
|
267
|
+ }, [ dispatch, options ]);
|
200
|
268
|
|
201
|
269
|
const shareDesktopKeyPress = useCallback(e => {
|
202
|
270
|
if (e.key === ' ' || e.key === 'Enter') {
|
|
@@ -483,20 +551,4 @@ function VirtualBackground({ _jitsiTrack, _selectedThumbnail, _virtualBackground
|
483
|
551
|
);
|
484
|
552
|
}
|
485
|
553
|
|
486
|
|
-/**
|
487
|
|
- * Maps (parts of) the redux state to the associated props for the
|
488
|
|
- * {@code VirtualBackground} component.
|
489
|
|
- *
|
490
|
|
- * @param {Object} state - The Redux state.
|
491
|
|
- * @private
|
492
|
|
- * @returns {{Props}}
|
493
|
|
- */
|
494
|
|
-function _mapStateToProps(state): Object {
|
495
|
|
- return {
|
496
|
|
- _virtualBackground: state['features/virtual-background'],
|
497
|
|
- _selectedThumbnail: state['features/virtual-background'].selectedThumbnail,
|
498
|
|
- _jitsiTrack: getLocalVideoTrack(state['features/base/tracks'])?.jitsiTrack
|
499
|
|
- };
|
500
|
|
-}
|
501
|
|
-
|
502
|
|
-export default translate(connect(_mapStateToProps)(VirtualBackground));
|
|
554
|
+export default VirtualBackgroundDialog;
|