fix(virtual-background) upload bkg image on poor connection
This commit is contained in:
parent
6c40329f6a
commit
eb4aefbca1
|
@ -386,7 +386,8 @@
|
|||
"image7" : "Sunrise",
|
||||
"desktopShareError": "Could not create desktop share",
|
||||
"desktopShare":"Desktop share",
|
||||
"webAssemblyWarning": "WebAssembly not supported"
|
||||
"webAssemblyWarning": "WebAssembly not supported",
|
||||
"backgroundEffectError": "Failed to apply background effect."
|
||||
},
|
||||
"feedback": {
|
||||
"average": "Average",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import { showWarningNotification } from '../../notifications/actions';
|
||||
import { timeout } from '../../virtual-background/functions';
|
||||
import logger from '../../virtual-background/logger';
|
||||
|
||||
import JitsiStreamBackgroundEffect from './JitsiStreamBackgroundEffect';
|
||||
|
@ -44,17 +45,26 @@ export async function createVirtualBackgroundEffect(virtualBackground: Object, d
|
|||
|
||||
try {
|
||||
wasmCheck = require('wasm-check');
|
||||
const tfliteTimeout = 10000;
|
||||
|
||||
if (wasmCheck?.feature?.simd) {
|
||||
tflite = await createTFLiteSIMDModule();
|
||||
tflite = await timeout(tfliteTimeout, createTFLiteSIMDModule());
|
||||
} else {
|
||||
tflite = await createTFLiteModule();
|
||||
tflite = await timeout(tfliteTimeout, createTFLiteModule());
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Looks like WebAssembly is disabled or not supported on this browser');
|
||||
dispatch(showWarningNotification({
|
||||
titleKey: 'virtualBackground.webAssemblyWarning',
|
||||
description: 'WebAssembly disabled or not supported by this browser'
|
||||
}));
|
||||
if (err?.message === '408') {
|
||||
logger.error('Failed to download tflite model!');
|
||||
dispatch(showWarningNotification({
|
||||
titleKey: 'virtualBackground.backgroundEffectError'
|
||||
}));
|
||||
} else {
|
||||
logger.error('Looks like WebAssembly is disabled or not supported on this browser');
|
||||
dispatch(showWarningNotification({
|
||||
titleKey: 'virtualBackground.webAssemblyWarning',
|
||||
description: 'WebAssembly disabled or not supported by this browser'
|
||||
}));
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ function VirtualBackground({
|
|||
initialOptions,
|
||||
t
|
||||
}: Props) {
|
||||
const [ previewIsLoaded, setPreviewIsLoaded ] = useState(false);
|
||||
const [ options, setOptions ] = useState({ ...initialOptions });
|
||||
const localImages = jitsiLocalStorage.getItem('virtualBackgrounds');
|
||||
const [ storedImages, setStoredImages ] = useState<Array<Image>>((localImages && Bourne.parse(localImages)) || []);
|
||||
|
@ -190,7 +191,6 @@ function VirtualBackground({
|
|||
}
|
||||
}, [ storedImages ]);
|
||||
|
||||
|
||||
const enableBlur = useCallback(async () => {
|
||||
setOptions({
|
||||
backgroundType: VIRTUAL_BACKGROUND_TYPE.BLUR,
|
||||
|
@ -425,15 +425,21 @@ function VirtualBackground({
|
|||
dispatch(hideDialog());
|
||||
});
|
||||
|
||||
const loadedPreviewState = useCallback(async loaded => {
|
||||
await setPreviewIsLoaded(loaded);
|
||||
});
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
hideCancelButton = { false }
|
||||
okKey = { 'virtualBackground.apply' }
|
||||
onCancel = { cancelVirtualBackground }
|
||||
onSubmit = { applyVirtualBackground }
|
||||
submitDisabled = { !options || loading }
|
||||
submitDisabled = { !options || loading || !previewIsLoaded }
|
||||
titleKey = { 'virtualBackground.title' } >
|
||||
<VirtualBackgroundPreview options = { options } />
|
||||
<VirtualBackgroundPreview
|
||||
loadedPreview = { loadedPreviewState }
|
||||
options = { options } />
|
||||
{loading ? (
|
||||
<div className = 'virtual-background-loading'>
|
||||
<Spinner
|
||||
|
@ -442,7 +448,7 @@ function VirtualBackground({
|
|||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<label
|
||||
{previewIsLoaded && <label
|
||||
aria-label = { t('virtualBackground.uploadImage') }
|
||||
className = 'file-upload-label'
|
||||
htmlFor = 'file-upload'
|
||||
|
@ -453,7 +459,7 @@ function VirtualBackground({
|
|||
size = { 20 }
|
||||
src = { IconPlusCircle } />
|
||||
{t('virtualBackground.addBackground')}
|
||||
</label>
|
||||
</label> }
|
||||
<input
|
||||
accept = 'image/*'
|
||||
className = 'file-upload-btn'
|
||||
|
|
|
@ -3,15 +3,18 @@
|
|||
import Spinner from '@atlaskit/spinner';
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import { hideDialog } from '../../base/dialog';
|
||||
import { translate } from '../../base/i18n';
|
||||
import { VIDEO_TYPE } from '../../base/media';
|
||||
import Video from '../../base/media/components/Video';
|
||||
import { connect, equals } from '../../base/redux';
|
||||
import { getCurrentCameraDeviceId } from '../../base/settings';
|
||||
import { createLocalTracksF } from '../../base/tracks/functions';
|
||||
import { showWarningNotification } from '../../notifications/actions';
|
||||
import { toggleBackgroundEffect } from '../actions';
|
||||
import { VIRTUAL_BACKGROUND_TYPE } from '../constants';
|
||||
import { localTrackStopped } from '../functions';
|
||||
import logger from '../logger';
|
||||
|
||||
const videoClassName = 'video-preview-video';
|
||||
|
||||
|
@ -30,6 +33,11 @@ export type Props = {
|
|||
*/
|
||||
dispatch: Function,
|
||||
|
||||
/**
|
||||
* Dialog callback that indicates if the background preview was loaded.
|
||||
*/
|
||||
loadedPreview: Function,
|
||||
|
||||
/**
|
||||
* Represents the virtual background setted options.
|
||||
*/
|
||||
|
@ -51,6 +59,11 @@ type State = {
|
|||
*/
|
||||
loading: boolean,
|
||||
|
||||
/**
|
||||
* Flag that indicates if the local track was loaded.
|
||||
*/
|
||||
localTrackLoaded: boolean,
|
||||
|
||||
/**
|
||||
* Activate the selected device camera only.
|
||||
*/
|
||||
|
@ -77,6 +90,7 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
|
||||
this.state = {
|
||||
loading: false,
|
||||
localTrackLoaded: false,
|
||||
jitsiTrack: null
|
||||
};
|
||||
}
|
||||
|
@ -99,24 +113,42 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
* @returns {void}
|
||||
*/
|
||||
async _setTracks() {
|
||||
const [ jitsiTrack ] = await createLocalTracksF({
|
||||
cameraDeviceId: this.props._currentCameraDeviceId,
|
||||
devices: [ 'video' ]
|
||||
});
|
||||
try {
|
||||
this.setState({ loading: true });
|
||||
const [ jitsiTrack ] = await createLocalTracksF({
|
||||
cameraDeviceId: this.props._currentCameraDeviceId,
|
||||
devices: [ 'video' ]
|
||||
});
|
||||
|
||||
this.setState({ localTrackLoaded: true });
|
||||
|
||||
// In case the component gets unmounted before the tracks are created
|
||||
// avoid a leak by not setting the state
|
||||
if (this._componentWasUnmounted) {
|
||||
this._stopStream(jitsiTrack);
|
||||
// In case the component gets unmounted before the tracks are created
|
||||
// avoid a leak by not setting the state
|
||||
if (this._componentWasUnmounted) {
|
||||
this._stopStream(jitsiTrack);
|
||||
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
jitsiTrack,
|
||||
loading: false
|
||||
});
|
||||
this.props.loadedPreview(true);
|
||||
} catch (error) {
|
||||
this.props.dispatch(hideDialog());
|
||||
this.props.dispatch(
|
||||
showWarningNotification({
|
||||
titleKey: 'virtualBackground.backgroundEffectError',
|
||||
description: 'Failed to access camera device.'
|
||||
})
|
||||
);
|
||||
logger.error('Failed to access camera device. Error on apply background effect.');
|
||||
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
jitsiTrack
|
||||
});
|
||||
|
||||
if (this.props.options.backgroundType === VIRTUAL_BACKGROUND_TYPE.DESKTOP_SHARE) {
|
||||
if (this.props.options.backgroundType === VIRTUAL_BACKGROUND_TYPE.DESKTOP_SHARE
|
||||
&& this.state.localTrackLoaded) {
|
||||
this._applyBackgroundEffect();
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +160,9 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
*/
|
||||
async _applyBackgroundEffect() {
|
||||
this.setState({ loading: true });
|
||||
this.props.loadedPreview(false);
|
||||
await this.props.dispatch(toggleBackgroundEffect(this.props.options, this.state.jitsiTrack));
|
||||
this.props.loadedPreview(true);
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
|
||||
|
@ -212,7 +246,7 @@ class VirtualBackgroundPreview extends PureComponent<Props, State> {
|
|||
if (!equals(this.props._currentCameraDeviceId, prevProps._currentCameraDeviceId)) {
|
||||
this._setTracks();
|
||||
}
|
||||
if (!equals(this.props.options, prevProps.options)) {
|
||||
if (!equals(this.props.options, prevProps.options) && this.state.localTrackLoaded) {
|
||||
if (prevProps.options.backgroundType === VIRTUAL_BACKGROUND_TYPE.DESKTOP_SHARE) {
|
||||
prevProps.options.url.dispose();
|
||||
}
|
||||
|
|
|
@ -118,3 +118,25 @@ export function localTrackStopped(dispatch: Function, desktopTrack: Object, curr
|
|||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creating a wrapper for promises on a specific time interval.
|
||||
*
|
||||
* @param {number} milliseconds - The number of milliseconds to wait the specified
|
||||
* {@code promise} to settle before automatically rejecting the returned
|
||||
* {@code Promise}.
|
||||
* @param {Promise} promise - The {@code Promise} for which automatic rejecting
|
||||
* after the specified timeout is to be implemented.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function timeout(milliseconds: number, promise: Promise<*>): Promise<Object> {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(new Error('408'));
|
||||
|
||||
return;
|
||||
}, milliseconds);
|
||||
|
||||
promise.then(resolve, reject);
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue