feat(sanity): axe IE and Temasys plugin support 🔥🔥🔥

This commit is contained in:
Saúl Ibarra Corretgé 2018-06-27 11:43:13 +02:00 committed by Saúl Ibarra Corretgé
parent 7164cd49e4
commit 87fa8de815
20 changed files with 43 additions and 251 deletions

View File

@ -152,10 +152,7 @@
}
}
/* With the TemasysWebRTC plugin <object/> element is used
instead of <video/> */
& > video,
& > object {
& > video {
cursor: hand;
border-radius: $borderRadius;
object-fit: cover;

View File

@ -1,4 +1,4 @@
/* global $, APP, JitsiMeetJS */
/* global $, APP */
/* eslint-disable no-unused-vars */
import React from 'react';
import ReactDOM from 'react-dom';
@ -29,14 +29,6 @@ import AudioLevels from '../audio_levels/AudioLevels';
const DESKTOP_CONTAINER_TYPE = 'desktop';
/**
* The time interval in milliseconds to check the video resolution of the video
* being displayed.
*
* @type {number}
*/
const VIDEO_RESOLUTION_POLL_INTERVAL = 2000;
/**
* Manager for all Large containers.
*/
@ -103,30 +95,15 @@ export default class LargeVideoManager {
= this._onVideoResolutionUpdate.bind(this);
this.videoContainer.addResizeListener(this._onVideoResolutionUpdate);
if (!JitsiMeetJS.util.RTCUIHelper.isResizeEventSupported()) {
/**
* An interval for polling if the displayed video resolution is or
* is not high-definition. For browsers that do not support video
* resize events, polling is the fallback.
*
* @private
* @type {timeoutId}
*/
this._updateVideoResolutionInterval = window.setInterval(
this._onVideoResolutionUpdate,
VIDEO_RESOLUTION_POLL_INTERVAL);
}
}
/**
* Stops any polling intervals on the instance and removes any
* listeners registered on child components, including React Components.
* Removes any listeners registered on child components, including
* React Components.
*
* @returns {void}
*/
destroy() {
window.clearInterval(this._updateVideoResolutionInterval);
this.videoContainer.removeResizeListener(
this._onVideoResolutionUpdate);

View File

@ -258,11 +258,8 @@ LocalVideo.prototype._onContainerClick = function(event) {
= $source.parents('.displayNameContainer').length > 0;
const clickedOnPopover = $source.parents('.popover').length > 0
|| classList.contains('popover');
const ignoreClick = clickedOnDisplayName || clickedOnPopover;
// FIXME: with Temasys plugin event arg is not an event, but the clicked
// object itself, so we have to skip this call
if (event.stopPropagation && !ignoreClick) {
event.stopPropagation();
}

View File

@ -158,14 +158,9 @@ RemoteVideo.prototype._generatePopupContent = function() {
}
}
let initialVolumeValue, onVolumeChange;
// Feature check for volume setting as temasys objects cannot adjust volume.
if (this._canSetAudioVolume()) {
initialVolumeValue = this._getAudioElement().volume;
onVolumeChange = this._setAudioVolume;
}
const initialVolumeValue
= this._audioStreamElement && this._audioStreamElement.volume;
const onVolumeChange = this._setAudioVolume;
const { isModerator } = APP.conference;
const participantID = this.id;
@ -267,35 +262,14 @@ RemoteVideo.prototype._stopRemoteControl = function() {
this.updateRemoteVideoMenu();
};
/**
* Get the remote participant's audio element.
*
* @returns {Element} audio element
*/
RemoteVideo.prototype._getAudioElement = function() {
return this._audioStreamElement;
};
/**
* Check if the remote participant's audio can have its volume adjusted.
*
* @returns {boolean} true if the volume can be adjusted.
*/
RemoteVideo.prototype._canSetAudioVolume = function() {
const audioElement = this._getAudioElement();
return audioElement && audioElement.volume !== undefined;
};
/**
* Change the remote participant's volume level.
*
* @param {int} newVal - The value to set the slider to.
*/
RemoteVideo.prototype._setAudioVolume = function(newVal) {
if (this._canSetAudioVolume()) {
this._getAudioElement().volume = newVal;
if (this._audioStreamElement) {
this._audioStreamElement.volume = newVal;
}
};
@ -526,23 +500,18 @@ RemoteVideo.prototype.addRemoteStreamElement = function(stream) {
return;
}
let streamElement = SmallVideo.createStreamElement(stream);
const streamElement = SmallVideo.createStreamElement(stream);
// Put new stream element always in front
UIUtils.prependChild(this.container, streamElement);
// If we hide element when Temasys plugin is used then
// we'll never receive 'onplay' event and other logic won't work as expected
// NOTE: hiding will not have effect when Temasys plugin is in use, as
// calling attach will show it back
$(streamElement).hide();
// If the container is currently visible
// we attach the stream to the element.
if (!isVideo || (this.container.offsetParent !== null && isVideo)) {
this.waitForPlayback(streamElement, stream);
streamElement = stream.attach(streamElement);
stream.attach(streamElement);
}
if (!isVideo) {

View File

@ -1,4 +1,4 @@
/* global $, APP, JitsiMeetJS, interfaceConfig */
/* global $, APP, interfaceConfig */
/* eslint-disable no-unused-vars */
import React from 'react';
@ -34,8 +34,6 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
import UIUtil from '../util/UIUtil';
import UIEvents from '../../../service/UI/UIEvents';
const RTCUIHelper = JitsiMeetJS.util.RTCUIHelper;
/**
* Display mode constant used when video is being displayed on the small video.
* @type {number}
@ -240,8 +238,7 @@ SmallVideo.createStreamElement = function(stream) {
element.setAttribute('muted', 'true');
}
RTCUIHelper.setAutoPlay(element, true);
element.autoplay = true;
element.id = SmallVideo.getStreamElementID(stream);
return element;
@ -438,7 +435,7 @@ SmallVideo.prototype.removeModeratorIndicator = function() {
* array (after checking its length of course!).
*/
SmallVideo.prototype.selectVideoElement = function() {
return $(RTCUIHelper.findVideoElement(this.container));
return $($(this.container).find('video')[0]);
};
/**

View File

@ -186,7 +186,6 @@ function getDesktopVideoPosition(videoWidth, videoHeight, videoSpaceWidth) {
* Container for user video.
*/
export class VideoContainer extends LargeContainer {
// FIXME: With Temasys we have to re-select everytime
/**
*
*/
@ -277,10 +276,6 @@ export class VideoContainer extends LargeContainer {
this.wasVideoRendered = true;
}.bind(this);
// This does not work with Temasys plugin - has to be a property to be
// copied between new <object> elements
// this.$video.on('play', onPlay);
this.$video[0].onplaying = onPlayingCallback;
/**
@ -290,7 +285,6 @@ export class VideoContainer extends LargeContainer {
*/
this._resizeListeners = new Set();
// As of May 16, 2017, temasys does not support resize events.
this.$video[0].onresize = this._onResize.bind(this);
}
@ -605,6 +599,8 @@ export class VideoContainer extends LargeContainer {
* <video> elements with plugin <object> tag. In Safari jQuery is
* unable to store values on this plugin object which breaks all
* animation effects performed on it directly.
*
* TODO: refactor this since Temasys is no longer supported.
*/
show() {
// its already visible
@ -692,8 +688,7 @@ export class VideoContainer extends LargeContainer {
// explicitly disabled.
if (interfaceConfig.DISABLE_VIDEO_BACKGROUND
|| browser.isFirefox()
|| browser.isSafariWithWebrtc()
|| browser.isTemasysPluginUsed()) {
|| browser.isSafariWithWebrtc()) {
return;
}

View File

@ -2,11 +2,7 @@
import type { Dispatch } from 'redux';
import {
libInitError,
WEBRTC_NOT_READY,
WEBRTC_NOT_SUPPORTED
} from '../lib-jitsi-meet';
import { libInitError, WEBRTC_NOT_SUPPORTED } from '../lib-jitsi-meet';
declare var APP: Object;
declare var config: Object;
@ -45,7 +41,6 @@ export function connect() {
// features/base/lib-jitsi-meet but we are not there yet on the
// Web at the time of this writing.
switch (error.name) {
case WEBRTC_NOT_READY:
case WEBRTC_NOT_SUPPORTED:
dispatch(libInitError(error));
}

View File

@ -91,18 +91,13 @@ export function libInitError(error: Error) {
}
/**
* Sets the indicator which determines whether WebRTC is ready. In execution
* environments in which WebRTC is supported via a known plugin such
* as Temasys WebRTC may start not ready and then become ready. Of course, there
* are execution enviroments such as old Mozilla Firefox versions or
* certains Microsoft Edge versions in which WebRTC is not supported at all.
* Sets the indicator which determines whether WebRTC is ready.
*
* @param {boolean|Promise} webRTCReady - The indicator which determines
* whether WebRTC is ready. If a Promise is specified, its resolution will be
* awaited.
* @param {boolean} webRTCReady - The indicator which determines
* whether WebRTC is ready.
* @returns {Function}
*/
export function setWebRTCReady(webRTCReady: boolean | Promise<*>) {
export function setWebRTCReady(webRTCReady: boolean) {
return (dispatch: Function, getState: Function) => {
if (getState()['features/base/lib-jitsi-meet'].webRTCReady
!== webRTCReady) {
@ -110,33 +105,6 @@ export function setWebRTCReady(webRTCReady: boolean | Promise<*>) {
type: SET_WEBRTC_READY,
webRTCReady
});
// If the specified webRTCReady is a thenable (i.e. a Promise), then
// await its resolution.
switch (typeof webRTCReady) {
case 'function':
case 'object': {
const { then } = webRTCReady;
if (typeof then === 'function') {
const onFulfilled = value => {
// Is the app still interested in the specified
// webRTCReady?
if (getState()['features/base/lib-jitsi-meet']
.webRTCReady
=== webRTCReady) {
dispatch(setWebRTCReady(value));
}
};
then.call(
webRTCReady,
/* onFulfilled */ () => onFulfilled(true),
/* onRejected*/ () => onFulfilled(false));
}
break;
}
}
}
};
}

View File

@ -1,13 +1,5 @@
/**
* The name of the Error thrown by {@link JitsiMeetJS.init()} which indicates
* that WebRTC is not ready and its readiness may be tracked via the
* webRTCReadyPromise property value of the Error.
*/
export const WEBRTC_NOT_READY = 'WEBRTC_NOT_READY';
/**
* The name of the Error thrown by {@link JitsiMeetJS.init()} which indicates
* that WebRTC is not supported by the execution environment either natively or
* via a known plugin such as Temasys.
* that WebRTC is not supported by the execution environment.
*/
export const WEBRTC_NOT_SUPPORTED = 'WEBRTC_NOT_SUPPORTED';

View File

@ -8,7 +8,7 @@ import { MiddlewareRegistry } from '../redux';
import JitsiMeetJS from './_';
import { disposeLib, initLib, setWebRTCReady } from './actions';
import { LIB_DID_INIT, LIB_INIT_ERROR, LIB_WILL_INIT } from './actionTypes';
import { WEBRTC_NOT_READY, WEBRTC_NOT_SUPPORTED } from './constants';
import { WEBRTC_NOT_SUPPORTED } from './constants';
declare var APP: Object;
@ -74,20 +74,8 @@ function _libInitError(store, next, action) {
const { error } = action;
if (error) {
let webRTCReady;
switch (error.name) {
case WEBRTC_NOT_READY:
webRTCReady = error.webRTCReadyPromise;
break;
case WEBRTC_NOT_SUPPORTED:
webRTCReady = false;
break;
}
typeof webRTCReady === 'undefined'
|| store.dispatch(setWebRTCReady(webRTCReady));
if (error && error.name === WEBRTC_NOT_SUPPORTED) {
store.dispatch(setWebRTCReady(false));
}
return nextState;

View File

@ -30,8 +30,8 @@ const SOCK_STREAM = 1; /* stream socket */
* The RTCPeerConnection provided by react-native-webrtc fires onaddstream
* before it remembers remotedescription (and thus makes it available to API
* clients). Because that appears to be a problem for lib-jitsi-meet which has
* been successfully running on Chrome, Firefox, Temasys, etc. for a very long
* time, attempt to meets its expectations (by extending RTCPPeerConnection).
* been successfully running on Chrome, Firefox, etc. for a very long
* time, attempt to meet its expectations (by extending RTCPPeerConnection).
*
* @class
*/

View File

@ -57,11 +57,10 @@ class Video extends Component {
/**
* The internal reference to the DOM/HTML element intended for
* displaying a video. This element may be an HTML video element or a
* temasys video object.
* displaying a video.
*
* @private
* @type {HTMLVideoElement|Object}
* @type {HTMLVideoElement}
*/
this._videoElement = null;
@ -79,8 +78,6 @@ class Video extends Component {
* @returns {void}
*/
componentDidMount() {
// Add these attributes directly onto the video element so temasys can
// use them when converting the video to an object.
this._videoElement.volume = 0;
this._videoElement.onplaying = this._onVideoPlaying;
@ -101,9 +98,7 @@ class Video extends Component {
/**
* Updates the video display only if a new track is added. This component's
* updating is blackboxed from React to prevent re-rendering of video
* element, as the lib uses track.attach(videoElement) instead. Also,
* re-rendering cannot be used with temasys, which replaces video elements
* with an object.
* element, as the lib uses track.attach(videoElement) instead.
*
* @inheritdoc
* @returns {boolean} - False is always returned to blackbox this component.
@ -130,17 +125,12 @@ class Video extends Component {
* @returns {ReactElement}
*/
render() {
// The wrapping div is necessary because temasys will replace the video
// with an object but react will keep expecting the video element. The
// div gives a constant element for react to keep track of.
return (
<div>
<video
autoPlay = { true }
className = { this.props.className }
id = { this.props.id }
ref = { this._setVideoElement } />
</div>
<video
autoPlay = { true }
className = { this.props.className }
id = { this.props.id }
ref = { this._setVideoElement } />
);
}
@ -158,19 +148,13 @@ class Video extends Component {
return;
}
const updatedVideoElement
= videoTrack.jitsiTrack.attach(this._videoElement);
// Sets the instance variable for the video element again as the element
// maybe have been replaced with a new object by temasys.
this._setVideoElement(updatedVideoElement);
videoTrack.jitsiTrack.attach(this._videoElement);
}
/**
* Removes the association to the component's video element from the passed
* in redux representation of jitsi video track to stop the track from
* rendering. With temasys, the video element must still be visible for
* detaching to complete.
* rendering.
*
* @param {Object} videoTrack - The redux representation of the
* {@code JitsiLocalTrack}.
@ -178,15 +162,7 @@ class Video extends Component {
* @returns {void}
*/
_detachTrack(videoTrack) {
// Detach the video element from the track only if it has already
// been attached. This accounts for a special case with temasys
// where if detach is being called before attach, the video
// element is converted to Object without updating this
// component's reference to the video element.
if (this._videoElement
&& videoTrack
&& videoTrack.jitsiTrack
&& videoTrack.jitsiTrack.containers.includes(this._videoElement)) {
if (this._videoElement && videoTrack && videoTrack.jitsiTrack) {
videoTrack.jitsiTrack.detach(this._videoElement);
}
}

View File

@ -1,39 +0,0 @@
/* @flow */
import React, { Component } from 'react';
/**
* React component that represents HTML style element with CSS specific to
* unsupported mobile browser components.
*
* @private
* @returns {ReactElement}
*/
export default class HideNotificationBarStyles extends Component<*> {
/**
* Implements React's {@link Component#render()}.
*
* @inheritdoc
* @returns {ReactElement}
*/
render() {
// Temasys provide lib-jitsi-meet/modules/RTC/adapter.screenshare.js
// which detects whether the browser supports WebRTC. If the browser
// does not support WebRTC, it displays an alert in the form of a yellow
// bar at the top of the page. The alert notifies the user that the
// browser does not support WebRTC and, if Temasys provide a plugin for
// the browser, the alert contains a button to initiate installing the
// browser. When Temasys do not provide a plugin for the browser, we do
// not want the alert on the unsupported-browser page because the
// notification about the lack of WebRTC support is the whole point of
// the unsupported-browser page.
return (
<style type = 'text/css'>
{
'iframe[name="adapterjs-alert"] { display: none; }'
}
</style>
);
}
}

View File

@ -1,6 +1,4 @@
export { default as Container } from './Container';
export { default as HideNotificationBarStyle }
from './HideNotificationBarStyle';
export { default as MultiSelectAutocomplete } from './MultiSelectAutocomplete';
export { default as Text } from './Text';
export { default as Watermarks } from './Watermarks';

View File

@ -8,7 +8,6 @@ import { connect, disconnect } from '../../base/connection';
import { DialogContainer } from '../../base/dialog';
import { translate } from '../../base/i18n';
import { CalleeInfoContainer } from '../../base/jwt';
import { HideNotificationBarStyle } from '../../base/react';
import { Filmstrip } from '../../filmstrip';
import { LargeVideo } from '../../large-video';
import { NotificationsContainer } from '../../notifications';
@ -162,15 +161,6 @@ class Conference extends Component<Props> {
<NotificationsContainer />
<CalleeInfoContainer />
{/*
* Temasys automatically injects a notification bar, if
* necessary, displayed at the top of the page notifying that
* WebRTC is not installed or supported. We do not need/want
* the notification bar in question because we have whole pages
* dedicated to the respective scenarios.
*/}
<HideNotificationBarStyle />
</div>
);
}

View File

@ -6,7 +6,7 @@ import { connect } from 'react-redux';
import { createDeepLinkingPageEvent, sendAnalytics } from '../../analytics';
import { translate, translateToHTML } from '../../base/i18n';
import { HideNotificationBarStyle, Platform } from '../../base/react';
import { Platform } from '../../base/react';
import { DialInSummary } from '../../invite';
import { _TNS } from '../constants';
@ -154,7 +154,6 @@ class DeepLinkingMobilePage extends Component<*, *> {
clickableNumbers = { true }
room = { _room } />
</div>
<HideNotificationBarStyle />
</div>
);
}

View File

@ -3,7 +3,6 @@
import React, { Component } from 'react';
import { createDeepLinkingPageEvent, sendAnalytics } from '../../analytics';
import { HideNotificationBarStyle } from '../../base/react';
declare var interfaceConfig: Object;
@ -41,8 +40,6 @@ export default class NoMobileApp extends Component<*> {
Please use { interfaceConfig.NATIVE_APP_NAME } on desktop to
join calls.
</p>
<HideNotificationBarStyle />
</div>
);
}

View File

@ -60,8 +60,7 @@ export type Props = {
/**
* Whether or not the audio output source selector should display. If
* true, the audio output selector and test audio link will not be
* rendered. This is specifically used for hiding audio output on
* temasys browsers which do not support such change.
* rendered.
*/
hideAudioOutputSelect: boolean,

View File

@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { translate } from '../../base/i18n';
import { HideNotificationBarStyle, Platform } from '../../base/react';
import { Platform } from '../../base/react';
import { CHROME, FIREFOX, IE, SAFARI } from './browserLinks';
@ -60,8 +60,6 @@ class UnsupportedDesktopBrowser extends Component<*> {
this._renderOSSpecificBrowserDownloadLink()
}
</p>
<HideNotificationBarStyle />
</div>
);
}

View File

@ -7,7 +7,7 @@ import React from 'react';
import { connect } from 'react-redux';
import { translate } from '../../base/i18n';
import { HideNotificationBarStyle, Watermarks } from '../../base/react';
import { Watermarks } from '../../base/react';
import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage';
@ -151,7 +151,6 @@ class WelcomePage extends AbstractWelcomePage {
ref = { this._setAdditionalContentRef } />
: null }
</div>
<HideNotificationBarStyle />
</AtlasKitThemeProvider>
);
}