Преглед на файлове

fix(virtual-background) upload bkg image on poor connection

master
Tudor D. Pop преди 4 години
родител
ревизия
eb4aefbca1
No account linked to committer's email address

+ 2
- 1
lang/main.json Целия файл

@@ -386,7 +386,8 @@
386 386
         "image7" : "Sunrise",
387 387
         "desktopShareError": "Could not create desktop share",
388 388
         "desktopShare":"Desktop share",
389
-        "webAssemblyWarning": "WebAssembly not supported"
389
+        "webAssemblyWarning": "WebAssembly not supported",
390
+        "backgroundEffectError": "Failed to apply background effect."
390 391
     },
391 392
     "feedback": {
392 393
         "average": "Average",

+ 17
- 7
react/features/stream-effects/virtual-background/index.js Целия файл

@@ -1,6 +1,7 @@
1 1
 // @flow
2 2
 
3 3
 import { showWarningNotification } from '../../notifications/actions';
4
+import { timeout } from '../../virtual-background/functions';
4 5
 import logger from '../../virtual-background/logger';
5 6
 
6 7
 import JitsiStreamBackgroundEffect from './JitsiStreamBackgroundEffect';
@@ -44,17 +45,26 @@ export async function createVirtualBackgroundEffect(virtualBackground: Object, d
44 45
 
45 46
     try {
46 47
         wasmCheck = require('wasm-check');
48
+        const tfliteTimeout = 10000;
49
+
47 50
         if (wasmCheck?.feature?.simd) {
48
-            tflite = await createTFLiteSIMDModule();
51
+            tflite = await timeout(tfliteTimeout, createTFLiteSIMDModule());
49 52
         } else {
50
-            tflite = await createTFLiteModule();
53
+            tflite = await timeout(tfliteTimeout, createTFLiteModule());
51 54
         }
52 55
     } catch (err) {
53
-        logger.error('Looks like WebAssembly is disabled or not supported on this browser');
54
-        dispatch(showWarningNotification({
55
-            titleKey: 'virtualBackground.webAssemblyWarning',
56
-            description: 'WebAssembly disabled or not supported by this browser'
57
-        }));
56
+        if (err?.message === '408') {
57
+            logger.error('Failed to download tflite model!');
58
+            dispatch(showWarningNotification({
59
+                titleKey: 'virtualBackground.backgroundEffectError'
60
+            }));
61
+        } else {
62
+            logger.error('Looks like WebAssembly is disabled or not supported on this browser');
63
+            dispatch(showWarningNotification({
64
+                titleKey: 'virtualBackground.webAssemblyWarning',
65
+                description: 'WebAssembly disabled or not supported by this browser'
66
+            }));
67
+        }
58 68
 
59 69
         return;
60 70
 

+ 11
- 5
react/features/virtual-background/components/VirtualBackgroundDialog.js Целия файл

@@ -153,6 +153,7 @@ function VirtualBackground({
153 153
     initialOptions,
154 154
     t
155 155
 }: Props) {
156
+    const [ previewIsLoaded, setPreviewIsLoaded ] = useState(false);
156 157
     const [ options, setOptions ] = useState({ ...initialOptions });
157 158
     const localImages = jitsiLocalStorage.getItem('virtualBackgrounds');
158 159
     const [ storedImages, setStoredImages ] = useState<Array<Image>>((localImages && Bourne.parse(localImages)) || []);
@@ -190,7 +191,6 @@ function VirtualBackground({
190 191
         }
191 192
     }, [ storedImages ]);
192 193
 
193
-
194 194
     const enableBlur = useCallback(async () => {
195 195
         setOptions({
196 196
             backgroundType: VIRTUAL_BACKGROUND_TYPE.BLUR,
@@ -425,15 +425,21 @@ function VirtualBackground({
425 425
         dispatch(hideDialog());
426 426
     });
427 427
 
428
+    const loadedPreviewState = useCallback(async loaded => {
429
+        await setPreviewIsLoaded(loaded);
430
+    });
431
+
428 432
     return (
429 433
         <Dialog
430 434
             hideCancelButton = { false }
431 435
             okKey = { 'virtualBackground.apply' }
432 436
             onCancel = { cancelVirtualBackground }
433 437
             onSubmit = { applyVirtualBackground }
434
-            submitDisabled = { !options || loading }
438
+            submitDisabled = { !options || loading || !previewIsLoaded }
435 439
             titleKey = { 'virtualBackground.title' } >
436
-            <VirtualBackgroundPreview options = { options } />
440
+            <VirtualBackgroundPreview
441
+                loadedPreview = { loadedPreviewState }
442
+                options = { options } />
437 443
             {loading ? (
438 444
                 <div className = 'virtual-background-loading'>
439 445
                     <Spinner
@@ -442,7 +448,7 @@ function VirtualBackground({
442 448
                 </div>
443 449
             ) : (
444 450
                 <div>
445
-                    <label
451
+                    {previewIsLoaded && <label
446 452
                         aria-label = { t('virtualBackground.uploadImage') }
447 453
                         className = 'file-upload-label'
448 454
                         htmlFor = 'file-upload'
@@ -453,7 +459,7 @@ function VirtualBackground({
453 459
                             size = { 20 }
454 460
                             src = { IconPlusCircle } />
455 461
                         {t('virtualBackground.addBackground')}
456
-                    </label>
462
+                    </label> }
457 463
                     <input
458 464
                         accept = 'image/*'
459 465
                         className = 'file-upload-btn'

+ 47
- 13
react/features/virtual-background/components/VirtualBackgroundPreview.js Целия файл

@@ -3,15 +3,18 @@
3 3
 import Spinner from '@atlaskit/spinner';
4 4
 import React, { PureComponent } from 'react';
5 5
 
6
+import { hideDialog } from '../../base/dialog';
6 7
 import { translate } from '../../base/i18n';
7 8
 import { VIDEO_TYPE } from '../../base/media';
8 9
 import Video from '../../base/media/components/Video';
9 10
 import { connect, equals } from '../../base/redux';
10 11
 import { getCurrentCameraDeviceId } from '../../base/settings';
11 12
 import { createLocalTracksF } from '../../base/tracks/functions';
13
+import { showWarningNotification } from '../../notifications/actions';
12 14
 import { toggleBackgroundEffect } from '../actions';
13 15
 import { VIRTUAL_BACKGROUND_TYPE } from '../constants';
14 16
 import { localTrackStopped } from '../functions';
17
+import logger from '../logger';
15 18
 
16 19
 const videoClassName = 'video-preview-video';
17 20
 
@@ -30,6 +33,11 @@ export type Props = {
30 33
      */
31 34
     dispatch: Function,
32 35
 
36
+    /**
37
+     * Dialog callback that indicates if the background preview was loaded.
38
+     */
39
+    loadedPreview: Function,
40
+
33 41
     /**
34 42
      * Represents the virtual background setted options.
35 43
      */
@@ -51,6 +59,11 @@ type State = {
51 59
      */
52 60
     loading: boolean,
53 61
 
62
+    /**
63
+     * Flag that indicates if the local track was loaded.
64
+     */
65
+    localTrackLoaded: boolean,
66
+
54 67
     /**
55 68
      * Activate the selected device camera only.
56 69
      */
@@ -77,6 +90,7 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
77 90
 
78 91
         this.state = {
79 92
             loading: false,
93
+            localTrackLoaded: false,
80 94
             jitsiTrack: null
81 95
         };
82 96
     }
@@ -99,24 +113,42 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
99 113
      * @returns {void}
100 114
      */
101 115
     async _setTracks() {
102
-        const [ jitsiTrack ] = await createLocalTracksF({
103
-            cameraDeviceId: this.props._currentCameraDeviceId,
104
-            devices: [ 'video' ]
105
-        });
116
+        try {
117
+            this.setState({ loading: true });
118
+            const [ jitsiTrack ] = await createLocalTracksF({
119
+                cameraDeviceId: this.props._currentCameraDeviceId,
120
+                devices: [ 'video' ]
121
+            });
122
+
123
+            this.setState({ localTrackLoaded: true });
106 124
 
125
+            // In case the component gets unmounted before the tracks are created
126
+            // avoid a leak by not setting the state
127
+            if (this._componentWasUnmounted) {
128
+                this._stopStream(jitsiTrack);
107 129
 
108
-        // In case the component gets unmounted before the tracks are created
109
-        // avoid a leak by not setting the state
110
-        if (this._componentWasUnmounted) {
111
-            this._stopStream(jitsiTrack);
130
+                return;
131
+            }
132
+            this.setState({
133
+                jitsiTrack,
134
+                loading: false
135
+            });
136
+            this.props.loadedPreview(true);
137
+        } catch (error) {
138
+            this.props.dispatch(hideDialog());
139
+            this.props.dispatch(
140
+                showWarningNotification({
141
+                    titleKey: 'virtualBackground.backgroundEffectError',
142
+                    description: 'Failed to access camera device.'
143
+                })
144
+            );
145
+            logger.error('Failed to access camera device. Error on apply background effect.');
112 146
 
113 147
             return;
114 148
         }
115
-        this.setState({
116
-            jitsiTrack
117
-        });
118 149
 
119
-        if (this.props.options.backgroundType === VIRTUAL_BACKGROUND_TYPE.DESKTOP_SHARE) {
150
+        if (this.props.options.backgroundType === VIRTUAL_BACKGROUND_TYPE.DESKTOP_SHARE
151
+                && this.state.localTrackLoaded) {
120 152
             this._applyBackgroundEffect();
121 153
         }
122 154
     }
@@ -128,7 +160,9 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
128 160
      */
129 161
     async _applyBackgroundEffect() {
130 162
         this.setState({ loading: true });
163
+        this.props.loadedPreview(false);
131 164
         await this.props.dispatch(toggleBackgroundEffect(this.props.options, this.state.jitsiTrack));
165
+        this.props.loadedPreview(true);
132 166
         this.setState({ loading: false });
133 167
     }
134 168
 
@@ -212,7 +246,7 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
212 246
         if (!equals(this.props._currentCameraDeviceId, prevProps._currentCameraDeviceId)) {
213 247
             this._setTracks();
214 248
         }
215
-        if (!equals(this.props.options, prevProps.options)) {
249
+        if (!equals(this.props.options, prevProps.options) && this.state.localTrackLoaded) {
216 250
             if (prevProps.options.backgroundType === VIRTUAL_BACKGROUND_TYPE.DESKTOP_SHARE) {
217 251
                 prevProps.options.url.dispose();
218 252
             }

+ 22
- 0
react/features/virtual-background/functions.js Целия файл

@@ -118,3 +118,25 @@ export function localTrackStopped(dispatch: Function, desktopTrack: Object, curr
118 118
         }));
119 119
     });
120 120
 }
121
+
122
+/**
123
+ * Creating a wrapper for promises on a specific time interval.
124
+ *
125
+ * @param {number} milliseconds - The number of milliseconds to wait the specified
126
+ * {@code promise} to settle before automatically rejecting the returned
127
+ * {@code Promise}.
128
+ * @param {Promise} promise - The {@code Promise} for which automatic rejecting
129
+ * after the specified timeout is to be implemented.
130
+ * @returns {Promise}
131
+ */
132
+export function timeout(milliseconds: number, promise: Promise<*>): Promise<Object> {
133
+    return new Promise((resolve, reject) => {
134
+        setTimeout(() => {
135
+            reject(new Error('408'));
136
+
137
+            return;
138
+        }, milliseconds);
139
+
140
+        promise.then(resolve, reject);
141
+    });
142
+}

Loading…
Отказ
Запис