Flow, coding style
This commit is contained in:
parent
4c00d39bf2
commit
f53c79ab24
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import JitsiMeetJS, { isAnalyticsEnabled } from '../base/lib-jitsi-meet';
|
import JitsiMeetJS, { isAnalyticsEnabled } from '../base/lib-jitsi-meet';
|
||||||
import { getJitsiMeetGlobalNS, loadScript } from '../base/util';
|
import { getJitsiMeetGlobalNS, loadScript } from '../base/util';
|
||||||
|
|
||||||
|
@ -13,7 +15,7 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||||
* is being dispatched.
|
* is being dispatched.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
export function initAnalytics({ getState }) {
|
export function initAnalytics({ getState }: { getState: Function }) {
|
||||||
getJitsiMeetGlobalNS().analyticsHandlers = [];
|
getJitsiMeetGlobalNS().analyticsHandlers = [];
|
||||||
window.analyticsHandlers = []; // Legacy support.
|
window.analyticsHandlers = []; // Legacy support.
|
||||||
|
|
||||||
|
@ -36,12 +38,12 @@ export function initAnalytics({ getState }) {
|
||||||
|
|
||||||
_loadHandlers(analyticsScriptUrls, handlerConstructorOptions)
|
_loadHandlers(analyticsScriptUrls, handlerConstructorOptions)
|
||||||
.then(handlers => {
|
.then(handlers => {
|
||||||
const permanentProperties = {
|
const state = getState();
|
||||||
roomName: getState()['features/base/conference'].room,
|
const permanentProperties: Object = {
|
||||||
|
roomName: state['features/base/conference'].room,
|
||||||
userAgent: navigator.userAgent
|
userAgent: navigator.userAgent
|
||||||
};
|
};
|
||||||
|
const { group, server } = state['features/jwt'];
|
||||||
const { group, server } = getState()['features/jwt'];
|
|
||||||
|
|
||||||
if (server) {
|
if (server) {
|
||||||
permanentProperties.server = server;
|
permanentProperties.server = server;
|
||||||
|
@ -50,13 +52,14 @@ export function initAnalytics({ getState }) {
|
||||||
permanentProperties.group = group;
|
permanentProperties.group = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optionally include local deployment information based on
|
// Optionally, include local deployment information based on the
|
||||||
// the contents of window.config.deploymentInfo
|
// contents of window.config.deploymentInfo.
|
||||||
if (config.deploymentInfo) {
|
const { deploymentInfo } = config;
|
||||||
for (const key in config.deploymentInfo) {
|
|
||||||
if (config.deploymentInfo.hasOwnProperty(key)) {
|
if (deploymentInfo) {
|
||||||
permanentProperties[key]
|
for (const key in deploymentInfo) {
|
||||||
= config.deploymentInfo[key];
|
if (deploymentInfo.hasOwnProperty(key)) {
|
||||||
|
permanentProperties[key] = deploymentInfo[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,23 +116,22 @@ function _loadHandlers(scriptURLs, handlerConstructorOptions) {
|
||||||
|
|
||||||
if (analyticsHandlers.length === 0) {
|
if (analyticsHandlers.length === 0) {
|
||||||
throw new Error('No analytics handlers available');
|
throw new Error('No analytics handlers available');
|
||||||
} else {
|
|
||||||
const handlers = [];
|
|
||||||
|
|
||||||
for (const Handler of analyticsHandlers) {
|
|
||||||
// catch any error while loading to avoid
|
|
||||||
// skipping analytics in case of multiple scripts
|
|
||||||
try {
|
|
||||||
handlers.push(new Handler(handlerConstructorOptions));
|
|
||||||
} catch (error) {
|
|
||||||
logger.warn(`Error creating analytics handler: ${error}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug(`Loaded ${handlers.length} analytics handlers`);
|
|
||||||
|
|
||||||
return handlers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handlers = [];
|
||||||
|
|
||||||
|
for (const Handler of analyticsHandlers) {
|
||||||
|
// Catch any error while loading to avoid skipping analytics in case
|
||||||
|
// of multiple scripts.
|
||||||
|
try {
|
||||||
|
handlers.push(new Handler(handlerConstructorOptions));
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn(`Error creating analytics handler: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Loaded ${handlers.length} analytics handlers`);
|
||||||
|
|
||||||
|
return handlers;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Text } from 'react-native';
|
import { Text } from 'react-native';
|
||||||
|
@ -79,6 +81,8 @@ class WaitForOwnerDialog extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onCancel: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the cancel button is clicked.
|
* Called when the cancel button is clicked.
|
||||||
*
|
*
|
||||||
|
@ -89,6 +93,8 @@ class WaitForOwnerDialog extends Component {
|
||||||
this.props.dispatch(cancelWaitForOwner());
|
this.props.dispatch(cancelWaitForOwner());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onLogin: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the OK button is clicked.
|
* Called when the OK button is clicked.
|
||||||
*
|
*
|
||||||
|
@ -102,11 +108,11 @@ class WaitForOwnerDialog extends Component {
|
||||||
/**
|
/**
|
||||||
* Renders a specific {@code string} which may contain HTML.
|
* Renders a specific {@code string} which may contain HTML.
|
||||||
*
|
*
|
||||||
* @param {string} html - The {@code string} which may contain HTML to
|
* @param {string|undefined} html - The {@code string} which may
|
||||||
* render.
|
* contain HTML to render.
|
||||||
* @returns {ReactElement[]|string}
|
* @returns {ReactElement[]|string}
|
||||||
*/
|
*/
|
||||||
_renderHTML(html) {
|
_renderHTML(html: ?string) {
|
||||||
if (typeof html === 'string') {
|
if (typeof html === 'string') {
|
||||||
// At the time of this writing, the specified HTML contains a couple
|
// At the time of this writing, the specified HTML contains a couple
|
||||||
// of spaces one after the other. They do not cause a visible
|
// of spaces one after the other. They do not cause a visible
|
||||||
|
@ -164,9 +170,7 @@ class WaitForOwnerDialog extends Component {
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
function _mapStateToProps(state) {
|
function _mapStateToProps(state) {
|
||||||
const {
|
const { authRequired } = state['features/base/conference'];
|
||||||
authRequired
|
|
||||||
} = state['features/base/conference'];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_room: authRequired && authRequired.getName()
|
_room: authRequired && authRequired.getName()
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import { appNavigate } from '../app';
|
import { appNavigate } from '../app';
|
||||||
import {
|
import {
|
||||||
CONFERENCE_FAILED,
|
CONFERENCE_FAILED,
|
||||||
|
@ -134,7 +136,8 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
* @param {Object} store - The redux store.
|
* @param {Object} store - The redux store.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function _clearExistingWaitForOwnerTimeout({ getState }) {
|
function _clearExistingWaitForOwnerTimeout(
|
||||||
|
{ getState }: { getState: Function }) {
|
||||||
const { waitForOwnerTimeoutID } = getState()['features/authentication'];
|
const { waitForOwnerTimeoutID } = getState()['features/authentication'];
|
||||||
|
|
||||||
waitForOwnerTimeoutID && clearTimeout(waitForOwnerTimeoutID);
|
waitForOwnerTimeoutID && clearTimeout(waitForOwnerTimeoutID);
|
||||||
|
@ -146,7 +149,7 @@ function _clearExistingWaitForOwnerTimeout({ getState }) {
|
||||||
* @param {Object} store - The redux store.
|
* @param {Object} store - The redux store.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function _hideLoginDialog({ dispatch }) {
|
function _hideLoginDialog({ dispatch }: { dispatch: Dispatch<*> }) {
|
||||||
dispatch(hideDialog(LoginDialog));
|
dispatch(hideDialog(LoginDialog));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +159,6 @@ function _hideLoginDialog({ dispatch }) {
|
||||||
* @param {Object} store - The redux store.
|
* @param {Object} store - The redux store.
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function _isWaitingForOwner({ getState }) {
|
function _isWaitingForOwner({ getState }: { getState: Function }) {
|
||||||
return Boolean(getState()['features/authentication'].waitForOwnerTimeoutID);
|
return Boolean(getState()['features/authentication'].waitForOwnerTimeoutID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
/* global APP */
|
// @flow
|
||||||
|
|
||||||
import UIEvents from '../../../../service/UI/UIEvents';
|
import UIEvents from '../../../../service/UI/UIEvents';
|
||||||
|
|
||||||
import { CONNECTION_ESTABLISHED } from '../connection';
|
import { CONNECTION_ESTABLISHED } from '../connection';
|
||||||
|
@ -34,6 +35,8 @@ import {
|
||||||
_removeLocalTracksFromConference
|
_removeLocalTracksFromConference
|
||||||
} from './functions';
|
} from './functions';
|
||||||
|
|
||||||
|
declare var APP: Object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the middleware of the feature base/conference.
|
* Implements the middleware of the feature base/conference.
|
||||||
*
|
*
|
||||||
|
@ -299,14 +302,12 @@ function _setLastN(store, next, action) {
|
||||||
* @returns {Object} The new state that is the result of the reduction of the
|
* @returns {Object} The new state that is the result of the reduction of the
|
||||||
* specified action.
|
* specified action.
|
||||||
*/
|
*/
|
||||||
function _setReceiveVideoQuality(store, next, action) {
|
function _setReceiveVideoQuality({ dispatch, getState }, next, action) {
|
||||||
const { audioOnly, conference }
|
const { audioOnly, conference } = getState()['features/base/conference'];
|
||||||
= store.getState()['features/base/conference'];
|
|
||||||
|
|
||||||
conference.setReceiverVideoConstraint(action.receiveVideoQuality);
|
conference.setReceiverVideoConstraint(action.receiveVideoQuality);
|
||||||
|
|
||||||
if (audioOnly) {
|
if (audioOnly) {
|
||||||
store.dispatch(toggleAudioOnly());
|
dispatch(toggleAudioOnly());
|
||||||
}
|
}
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
|
@ -321,9 +322,9 @@ function _setReceiveVideoQuality(store, next, action) {
|
||||||
* @private
|
* @private
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
function _syncConferenceLocalTracksWithState(store, action) {
|
function _syncConferenceLocalTracksWithState({ getState }, action) {
|
||||||
const state = store.getState()['features/base/conference'];
|
const state = getState()['features/base/conference'];
|
||||||
const conference = state.conference;
|
const { conference } = state;
|
||||||
let promise;
|
let promise;
|
||||||
|
|
||||||
// XXX The conference may already be in the process of being left, that's
|
// XXX The conference may already be in the process of being left, that's
|
||||||
|
@ -354,8 +355,8 @@ function _syncConferenceLocalTracksWithState(store, action) {
|
||||||
* @returns {Object} The new state that is the result of the reduction of the
|
* @returns {Object} The new state that is the result of the reduction of the
|
||||||
* specified action.
|
* specified action.
|
||||||
*/
|
*/
|
||||||
function _syncReceiveVideoQuality(store, next, action) {
|
function _syncReceiveVideoQuality({ getState }, next, action) {
|
||||||
const state = store.getState()['features/base/conference'];
|
const state = getState()['features/base/conference'];
|
||||||
|
|
||||||
state.conference.setReceiverVideoConstraint(state.receiveVideoQuality);
|
state.conference.setReceiverVideoConstraint(state.receiveVideoQuality);
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import { CONNECTION_WILL_CONNECT } from '../connection';
|
import { CONNECTION_WILL_CONNECT } from '../connection';
|
||||||
import { JitsiConferenceErrors } from '../lib-jitsi-meet';
|
import { JitsiConferenceErrors } from '../lib-jitsi-meet';
|
||||||
import { assign, ReducerRegistry, set } from '../redux';
|
import { assign, ReducerRegistry, set } from '../redux';
|
||||||
|
@ -351,7 +353,7 @@ function _setReceiveVideoQuality(state, action) {
|
||||||
* reduction of the specified action.
|
* reduction of the specified action.
|
||||||
*/
|
*/
|
||||||
function _setRoom(state, action) {
|
function _setRoom(state, action) {
|
||||||
let room = action.room;
|
let { room } = action;
|
||||||
|
|
||||||
if (!isRoomValid(room)) {
|
if (!isRoomValid(room)) {
|
||||||
// Technically, there are multiple values which don't represent valid
|
// Technically, there are multiple values which don't represent valid
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
|
|
||||||
|
@ -28,18 +30,21 @@ export default class AbstractDialog extends Component {
|
||||||
dispatch: PropTypes.func
|
dispatch: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_mounted: boolean;
|
||||||
|
|
||||||
|
state = {
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new {@code AbstractDialog} instance.
|
* Initializes a new {@code AbstractDialog} instance.
|
||||||
*
|
*
|
||||||
* @param {Object} props - The read-only React {@code Component} props with
|
* @param {Object} props - The read-only React {@code Component} props with
|
||||||
* which the new instance is to be initialized.
|
* which the new instance is to be initialized.
|
||||||
*/
|
*/
|
||||||
constructor(props) {
|
constructor(props: Object) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
// Bind event handlers so they are only bound once per instance.
|
||||||
};
|
|
||||||
|
|
||||||
this._onCancel = this._onCancel.bind(this);
|
this._onCancel = this._onCancel.bind(this);
|
||||||
this._onSubmit = this._onSubmit.bind(this);
|
this._onSubmit = this._onSubmit.bind(this);
|
||||||
this._onSubmitFulfilled = this._onSubmitFulfilled.bind(this);
|
this._onSubmitFulfilled = this._onSubmitFulfilled.bind(this);
|
||||||
|
@ -66,6 +71,8 @@ export default class AbstractDialog extends Component {
|
||||||
this._mounted = false;
|
this._mounted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onCancel: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatches a redux action to hide this dialog when it's canceled.
|
* Dispatches a redux action to hide this dialog when it's canceled.
|
||||||
*
|
*
|
||||||
|
@ -81,19 +88,21 @@ export default class AbstractDialog extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onSubmit: (?string) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submits this dialog. If the React {@code Component} prop
|
* Submits this {@code Dialog}. If the React {@code Component} prop
|
||||||
* {@code onSubmit} is defined, the function that is the value of the prop
|
* {@code onSubmit} is defined, the function that is the value of the prop
|
||||||
* is invoked. If the function returns a {@code thenable}, then the
|
* is invoked. If the function returns a {@code thenable}, then the
|
||||||
* resolution of the {@code thenable} is awaited. If the submission
|
* resolution of the {@code thenable} is awaited. If the submission
|
||||||
* completes successfully, a redux action will be dispatched to hide this
|
* completes successfully, a redux action will be dispatched to hide this
|
||||||
* dialog.
|
* dialog.
|
||||||
*
|
*
|
||||||
* @private
|
* @protected
|
||||||
* @param {string} value - The submitted value if any.
|
* @param {string} [value] - The submitted value if any.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onSubmit(value) {
|
_onSubmit(value: ?string) {
|
||||||
const { okDisabled, onSubmit } = this.props;
|
const { okDisabled, onSubmit } = this.props;
|
||||||
|
|
||||||
if (typeof okDisabled === 'undefined' || !okDisabled) {
|
if (typeof okDisabled === 'undefined' || !okDisabled) {
|
||||||
|
@ -125,6 +134,8 @@ export default class AbstractDialog extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onSubmitFulfilled: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies this {@code AbstractDialog} that it has been submitted
|
* Notifies this {@code AbstractDialog} that it has been submitted
|
||||||
* successfully. Dispatches a redux action to hide this dialog after it has
|
* successfully. Dispatches a redux action to hide this dialog after it has
|
||||||
|
@ -139,6 +150,8 @@ export default class AbstractDialog extends Component {
|
||||||
this.props.dispatch(hideDialog());
|
this.props.dispatch(hideDialog());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onSubmitRejected: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies this {@code AbstractDialog} that its submission has failed.
|
* Notifies this {@code AbstractDialog} that its submission has failed.
|
||||||
*
|
*
|
||||||
|
|
|
@ -108,14 +108,9 @@ class Dialog extends AbstractDialog {
|
||||||
// Secondly, we cannot get Prompt's default behavior anyway
|
// Secondly, we cannot get Prompt's default behavior anyway
|
||||||
// because we've removed Prompt and we're preserving whatever
|
// because we've removed Prompt and we're preserving whatever
|
||||||
// it's rendered only.
|
// it's rendered only.
|
||||||
return (
|
return this._cloneElement(element, /* props */ {
|
||||||
React.cloneElement(
|
onRequestClose: this._onCancel
|
||||||
element,
|
});
|
||||||
/* props */ {
|
|
||||||
onRequestClose: this._onCancel
|
|
||||||
},
|
|
||||||
...React.Children.toArray(element.props.children))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === TextInput) {
|
if (type === TextInput) {
|
||||||
|
@ -146,14 +141,9 @@ class Dialog extends AbstractDialog {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return this._cloneElement(element, /* props */ {
|
||||||
React.cloneElement(
|
style: set(style, _TAG_KEY, undefined)
|
||||||
element,
|
});
|
||||||
/* props */ {
|
|
||||||
style: set(style, _TAG_KEY, undefined)
|
|
||||||
},
|
|
||||||
...React.Children.toArray(element.props.children))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,6 +153,23 @@ class Dialog extends AbstractDialog {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clones a specific {@code ReactElement} and adds/merges specific props
|
||||||
|
* into the clone.
|
||||||
|
*
|
||||||
|
* @param {ReactElement} element - The {@code ReactElement} to clone.
|
||||||
|
* @param {Object} props - The props to add/merge into the clone.
|
||||||
|
* @returns {ReactElement} The close of the specified {@code element} with
|
||||||
|
* the specified {@code props} added/merged.
|
||||||
|
*/
|
||||||
|
_cloneElement(element, props) {
|
||||||
|
return (
|
||||||
|
React.cloneElement(
|
||||||
|
element,
|
||||||
|
props,
|
||||||
|
...React.Children.toArray(element.props.children)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a deep clone of a specific {@code ReactElement} with the results
|
* Creates a deep clone of a specific {@code ReactElement} with the results
|
||||||
* of calling a specific function on every node of a specific
|
* of calling a specific function on every node of a specific
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import { _handleParticipantError } from '../base/conference';
|
import { _handleParticipantError } from '../base/conference';
|
||||||
import { MEDIA_TYPE, VIDEO_TYPE } from '../base/media';
|
import { MEDIA_TYPE, VIDEO_TYPE } from '../base/media';
|
||||||
import {
|
import {
|
||||||
|
@ -16,9 +18,9 @@ import {
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function selectParticipant() {
|
export function selectParticipant() {
|
||||||
return (dispatch, getState) => {
|
return (dispatch: Dispatch<*>, getState: Function) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const conference = state['features/base/conference'].conference;
|
const { conference } = state['features/base/conference'];
|
||||||
|
|
||||||
if (conference) {
|
if (conference) {
|
||||||
const largeVideo = state['features/large-video'];
|
const largeVideo = state['features/large-video'];
|
||||||
|
@ -51,7 +53,7 @@ export function selectParticipant() {
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function selectParticipantInLargeVideo() {
|
export function selectParticipantInLargeVideo() {
|
||||||
return (dispatch, getState) => {
|
return (dispatch: Dispatch<*>, getState: Function) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const participantId = _electParticipantInLargeVideo(state);
|
const participantId = _electParticipantInLargeVideo(state);
|
||||||
const largeVideo = state['features/large-video'];
|
const largeVideo = state['features/large-video'];
|
||||||
|
@ -76,7 +78,7 @@ export function selectParticipantInLargeVideo() {
|
||||||
* resolution: number
|
* resolution: number
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
export function updateKnownLargeVideoResolution(resolution) {
|
export function updateKnownLargeVideoResolution(resolution: number) {
|
||||||
return {
|
return {
|
||||||
type: UPDATE_KNOWN_LARGE_VIDEO_RESOLUTION,
|
type: UPDATE_KNOWN_LARGE_VIDEO_RESOLUTION,
|
||||||
resolution
|
resolution
|
||||||
|
|
|
@ -85,20 +85,21 @@ function _getSymbolDescription(symbol: Symbol) {
|
||||||
* apps may listen to such events via the mechanisms provided by the (native)
|
* apps may listen to such events via the mechanisms provided by the (native)
|
||||||
* mobile Jitsi Meet SDK.
|
* mobile Jitsi Meet SDK.
|
||||||
*
|
*
|
||||||
* @param {Object} store - The redux store associated with the need to send the
|
* @param {Object} store - The redux store.
|
||||||
* specified event.
|
|
||||||
* @param {string} name - The name of the event to send.
|
* @param {string} name - The name of the event to send.
|
||||||
* @param {Object} data - The details/specifics of the event to send determined
|
* @param {Object} data - The details/specifics of the event to send determined
|
||||||
* by/associated with the specified {@code name}.
|
* by/associated with the specified {@code name}.
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function _sendEvent(store: Object, name: string, data: Object) {
|
function _sendEvent(
|
||||||
|
{ getState }: { getState: Function },
|
||||||
|
name: string,
|
||||||
|
data: Object) {
|
||||||
// The JavaScript App needs to provide uniquely identifying information
|
// The JavaScript App needs to provide uniquely identifying information
|
||||||
// to the native ExternalAPI module so that the latter may match the former
|
// to the native ExternalAPI module so that the latter may match the former
|
||||||
// to the native JitsiMeetView which hosts it.
|
// to the native JitsiMeetView which hosts it.
|
||||||
const state = store.getState();
|
const { app } = getState()['features/app'];
|
||||||
const { app } = state['features/app'];
|
|
||||||
|
|
||||||
if (app) {
|
if (app) {
|
||||||
const { externalAPIScope } = app.props;
|
const { externalAPIScope } = app.props;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import { CONFERENCE_FAILED } from '../base/conference';
|
import { CONFERENCE_FAILED } from '../base/conference';
|
||||||
import {
|
import {
|
||||||
CONNECTION_ESTABLISHED,
|
CONNECTION_ESTABLISHED,
|
||||||
|
@ -140,10 +142,12 @@ function _connectionWillConnect(
|
||||||
* @returns {Object} The new state of the feature overlay after the reduction of
|
* @returns {Object} The new state of the feature overlay after the reduction of
|
||||||
* the specified action.
|
* the specified action.
|
||||||
*/
|
*/
|
||||||
function _mediaPermissionPromptVisibilityChanged(state, action) {
|
function _mediaPermissionPromptVisibilityChanged(
|
||||||
|
state,
|
||||||
|
{ browser, isVisible }) {
|
||||||
return assign(state, {
|
return assign(state, {
|
||||||
browser: action.browser,
|
browser,
|
||||||
isMediaPermissionPromptVisible: action.isVisible
|
isMediaPermissionPromptVisible: isVisible
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import { setPassword } from '../base/conference';
|
import { setPassword } from '../base/conference';
|
||||||
import { hideDialog, openDialog } from '../base/dialog';
|
import { hideDialog, openDialog } from '../base/dialog';
|
||||||
import { PasswordRequiredPrompt, RoomLockPrompt } from './components';
|
import { PasswordRequiredPrompt, RoomLockPrompt } from './components';
|
||||||
|
@ -9,15 +11,12 @@ import { PasswordRequiredPrompt, RoomLockPrompt } from './components';
|
||||||
* if specified or undefined if the current JitsiConference is to be locked.
|
* if specified or undefined if the current JitsiConference is to be locked.
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function beginRoomLockRequest(conference) {
|
export function beginRoomLockRequest(conference: ?Object) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch: Function, getState: Function) => {
|
||||||
if (typeof conference === 'undefined') {
|
if (typeof conference === 'undefined') {
|
||||||
const state = getState();
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-param-reassign
|
// eslint-disable-next-line no-param-reassign
|
||||||
conference = state['features/base/conference'].conference;
|
conference = getState()['features/base/conference'].conference;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conference) {
|
if (conference) {
|
||||||
dispatch(openDialog(RoomLockPrompt, { conference }));
|
dispatch(openDialog(RoomLockPrompt, { conference }));
|
||||||
}
|
}
|
||||||
|
@ -33,15 +32,15 @@ export function beginRoomLockRequest(conference) {
|
||||||
* the specified conference.
|
* the specified conference.
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
export function endRoomLockRequest(conference, password) {
|
export function endRoomLockRequest(
|
||||||
return dispatch => {
|
conference: { lock: Function },
|
||||||
|
password: ?string) {
|
||||||
|
return (dispatch: Function) => {
|
||||||
const setPassword_
|
const setPassword_
|
||||||
= password
|
= password
|
||||||
? dispatch(setPassword(conference, conference.lock, password))
|
? dispatch(setPassword(conference, conference.lock, password))
|
||||||
: Promise.resolve();
|
: Promise.resolve();
|
||||||
const endRoomLockRequest_ = () => {
|
const endRoomLockRequest_ = () => dispatch(hideDialog(RoomLockPrompt));
|
||||||
dispatch(hideDialog());
|
|
||||||
};
|
|
||||||
|
|
||||||
setPassword_.then(endRoomLockRequest_, endRoomLockRequest_);
|
setPassword_.then(endRoomLockRequest_, endRoomLockRequest_);
|
||||||
};
|
};
|
||||||
|
@ -59,6 +58,6 @@ export function endRoomLockRequest(conference, password) {
|
||||||
* props: PropTypes
|
* props: PropTypes
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
export function _showPasswordDialog(conference) {
|
export function _openPasswordRequiredPrompt(conference: Object) {
|
||||||
return openDialog(PasswordRequiredPrompt, { conference });
|
return openDialog(PasswordRequiredPrompt, { conference });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -6,35 +8,44 @@ import { setPassword } from '../../base/conference';
|
||||||
import { Dialog } from '../../base/dialog';
|
import { Dialog } from '../../base/dialog';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements a React Component which prompts the user when a password is
|
* {@code PasswordRequiredPrompt}'s React {@code Component} prop types.
|
||||||
* required to join a conference.
|
*/
|
||||||
|
type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code JitsiConference} which requires a password.
|
||||||
|
*
|
||||||
|
* @type {JitsiConference}
|
||||||
|
*/
|
||||||
|
conference: { join: Function },
|
||||||
|
dispatch: Dispatch<*>
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a React {@code Component} which prompts the user when a password
|
||||||
|
* is required to join a conference.
|
||||||
*/
|
*/
|
||||||
class PasswordRequiredPrompt extends Component {
|
class PasswordRequiredPrompt extends Component {
|
||||||
/**
|
/**
|
||||||
* PasswordRequiredPrompt component's property types.
|
* {@code PasswordRequiredPrompt}'s React {@code Component} prop types.
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
/**
|
|
||||||
* The JitsiConference which requires a password.
|
|
||||||
*
|
|
||||||
* @type {JitsiConference}
|
|
||||||
*/
|
|
||||||
conference: PropTypes.object,
|
conference: PropTypes.object,
|
||||||
dispatch: PropTypes.func
|
dispatch: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new PasswordRequiredPrompt instance.
|
* Initializes a new {@code PasswordRequiredPrompt} instance.
|
||||||
*
|
*
|
||||||
* @param {Object} props - The read-only properties with which the new
|
* @param {Props} props - The read-only React {@code Component} props with
|
||||||
* instance is to be initialized.
|
* which the new instance is to be initialized.
|
||||||
*/
|
*/
|
||||||
constructor(props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
// Bind event handlers so they are only bound once for every instance.
|
// Bind event handlers so they are only bound once per instance.
|
||||||
this._onCancel = this._onCancel.bind(this);
|
this._onCancel = this._onCancel.bind(this);
|
||||||
this._onSubmit = this._onSubmit.bind(this);
|
this._onSubmit = this._onSubmit.bind(this);
|
||||||
}
|
}
|
||||||
|
@ -55,11 +66,14 @@ class PasswordRequiredPrompt extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onCancel: () => boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies this prompt that it has been dismissed by cancel.
|
* Notifies this prompt that it has been dismissed by cancel.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @returns {boolean} True to hide this dialog/prompt; otherwise, false.
|
* @returns {boolean} If this prompt is to be closed/hidden, {@code true};
|
||||||
|
* otherwise, {@code false}.
|
||||||
*/
|
*/
|
||||||
_onCancel() {
|
_onCancel() {
|
||||||
// XXX The user has canceled this prompt for a password so we are to
|
// XXX The user has canceled this prompt for a password so we are to
|
||||||
|
@ -69,16 +83,19 @@ class PasswordRequiredPrompt extends Component {
|
||||||
return this._onSubmit(undefined);
|
return this._onSubmit(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onSubmit: (?string) => boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies this prompt that it has been dismissed by submitting a specific
|
* Notifies this prompt that it has been dismissed by submitting a specific
|
||||||
* value.
|
* value.
|
||||||
*
|
*
|
||||||
* @param {string} value - The submitted value.
|
* @param {string|undefined} value - The submitted value.
|
||||||
* @private
|
* @private
|
||||||
* @returns {boolean} True to hide this dialog/prompt; otherwise, false.
|
* @returns {boolean} If this prompt is to be closed/hidden, {@code true};
|
||||||
|
* otherwise, {@code false}.
|
||||||
*/
|
*/
|
||||||
_onSubmit(value) {
|
_onSubmit(value: ?string) {
|
||||||
const conference = this.props.conference;
|
const { conference }: { conference: { join: Function } } = this.props;
|
||||||
|
|
||||||
this.props.dispatch(setPassword(conference, conference.join, value));
|
this.props.dispatch(setPassword(conference, conference.join, value));
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import AKFieldText from '@atlaskit/field-text';
|
import AKFieldText from '@atlaskit/field-text';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
@ -28,6 +30,10 @@ class PasswordRequiredPrompt extends Component {
|
||||||
t: PropTypes.func
|
t: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
password: ''
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new PasswordRequiredPrompt instance.
|
* Initializes a new PasswordRequiredPrompt instance.
|
||||||
*
|
*
|
||||||
|
@ -37,10 +43,7 @@ class PasswordRequiredPrompt extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
// Bind event handlers so they are only bound once per instance.
|
||||||
password: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
this._onPasswordChanged = this._onPasswordChanged.bind(this);
|
this._onPasswordChanged = this._onPasswordChanged.bind(this);
|
||||||
this._onSubmit = this._onSubmit.bind(this);
|
this._onSubmit = this._onSubmit.bind(this);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +62,8 @@ class PasswordRequiredPrompt extends Component {
|
||||||
titleKey = 'dialog.passwordRequired'
|
titleKey = 'dialog.passwordRequired'
|
||||||
width = 'small'>
|
width = 'small'>
|
||||||
{ this._renderBody() }
|
{ this._renderBody() }
|
||||||
</Dialog>);
|
</Dialog>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,6 +88,8 @@ class PasswordRequiredPrompt extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onPasswordChanged: ({ target: { value: * }}) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies this dialog that password has changed.
|
* Notifies this dialog that password has changed.
|
||||||
*
|
*
|
||||||
|
@ -91,17 +97,19 @@ class PasswordRequiredPrompt extends Component {
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onPasswordChanged(event) {
|
_onPasswordChanged({ target: { value } }) {
|
||||||
this.setState({
|
this.setState({
|
||||||
password: event.target.value
|
password: value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onSubmit: () => boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatches action to submit value from thus dialog.
|
* Dispatches action to submit value from this dialog.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
_onSubmit() {
|
_onSubmit() {
|
||||||
const { conference } = this.props;
|
const { conference } = this.props;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -29,13 +31,13 @@ class RoomLockPrompt extends Component {
|
||||||
/**
|
/**
|
||||||
* Initializes a new RoomLockPrompt instance.
|
* Initializes a new RoomLockPrompt instance.
|
||||||
*
|
*
|
||||||
* @param {Object} props - The read-only properties with which the new
|
* @param {Props} props - The read-only properties with which the new
|
||||||
* instance is to be initialized.
|
* instance is to be initialized.
|
||||||
*/
|
*/
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
// Bind event handlers so they are only bound once for every instance.
|
// Bind event handlers so they are only bound once per instance.
|
||||||
this._onCancel = this._onCancel.bind(this);
|
this._onCancel = this._onCancel.bind(this);
|
||||||
this._onSubmit = this._onSubmit.bind(this);
|
this._onSubmit = this._onSubmit.bind(this);
|
||||||
}
|
}
|
||||||
|
@ -56,6 +58,8 @@ class RoomLockPrompt extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onCancel: () => boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies this prompt that it has been dismissed by cancel.
|
* Notifies this prompt that it has been dismissed by cancel.
|
||||||
*
|
*
|
||||||
|
@ -68,17 +72,19 @@ class RoomLockPrompt extends Component {
|
||||||
return this._onSubmit(undefined);
|
return this._onSubmit(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onSubmit: (?string) => boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies this prompt that it has been dismissed by submitting a specific
|
* Notifies this prompt that it has been dismissed by submitting a specific
|
||||||
* value.
|
* value.
|
||||||
*
|
*
|
||||||
* @param {string} value - The submitted value.
|
* @param {string|undefined} value - The submitted value.
|
||||||
* @private
|
* @private
|
||||||
* @returns {boolean} False because we do not want to hide this
|
* @returns {boolean} False because we do not want to hide this
|
||||||
* dialog/prompt as the hiding will be handled inside endRoomLockRequest
|
* dialog/prompt as the hiding will be handled inside endRoomLockRequest
|
||||||
* after setting the password is resolved.
|
* after setting the password is resolved.
|
||||||
*/
|
*/
|
||||||
_onSubmit(value) {
|
_onSubmit(value: ?string) {
|
||||||
this.props.dispatch(endRoomLockRequest(this.props.conference, value));
|
this.props.dispatch(endRoomLockRequest(this.props.conference, value));
|
||||||
|
|
||||||
return false; // Do not hide.
|
return false; // Do not hide.
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
export { default as RoomLockPrompt } from './RoomLockPrompt';
|
|
||||||
export { default as PasswordRequiredPrompt } from './PasswordRequiredPrompt';
|
export { default as PasswordRequiredPrompt } from './PasswordRequiredPrompt';
|
||||||
|
export { default as RoomLockPrompt } from './RoomLockPrompt';
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
/* global APP */
|
// @flow
|
||||||
|
|
||||||
import UIEvents from '../../../service/UI/UIEvents';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CONFERENCE_FAILED,
|
CONFERENCE_FAILED,
|
||||||
|
@ -9,8 +7,11 @@ import {
|
||||||
} from '../base/conference';
|
} from '../base/conference';
|
||||||
import { JitsiConferenceErrors } from '../base/lib-jitsi-meet';
|
import { JitsiConferenceErrors } from '../base/lib-jitsi-meet';
|
||||||
import { MiddlewareRegistry } from '../base/redux';
|
import { MiddlewareRegistry } from '../base/redux';
|
||||||
|
import UIEvents from '../../../service/UI/UIEvents';
|
||||||
|
|
||||||
import { _showPasswordDialog } from './actions';
|
import { _openPasswordRequiredPrompt } from './actions';
|
||||||
|
|
||||||
|
declare var APP: Object;
|
||||||
|
|
||||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
const { conference, error } = action;
|
const { conference, error } = action;
|
||||||
|
|
||||||
if (conference && error === JitsiConferenceErrors.PASSWORD_REQUIRED) {
|
if (conference && error === JitsiConferenceErrors.PASSWORD_REQUIRED) {
|
||||||
store.dispatch(_showPasswordDialog(conference));
|
store.dispatch(_openPasswordRequiredPrompt(conference));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import { appNavigate } from '../app';
|
import { appNavigate } from '../app';
|
||||||
import { SET_WEBRTC_READY } from '../base/lib-jitsi-meet';
|
import { SET_WEBRTC_READY } from '../base/lib-jitsi-meet';
|
||||||
import { MiddlewareRegistry } from '../base/redux';
|
import { MiddlewareRegistry } from '../base/redux';
|
||||||
|
@ -28,26 +30,25 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
* specified action to the specified store.
|
* specified action to the specified store.
|
||||||
* @param {Action} action - The Redux action SET_WEBRTC_READY which is being
|
* @param {Action} action - The Redux action SET_WEBRTC_READY which is being
|
||||||
* dispatched in the specified store.
|
* dispatched in the specified store.
|
||||||
|
* @private
|
||||||
* @returns {Object} The new state that is the result of the reduction of the
|
* @returns {Object} The new state that is the result of the reduction of the
|
||||||
* specified action.
|
* specified action.
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
function _setWebRTCReady(store, next, action) {
|
function _setWebRTCReady({ dispatch, getState }, next, action) {
|
||||||
const nextState = next(action);
|
const result = next(action);
|
||||||
|
|
||||||
// FIXME The feature unsupported-browser needs to notify the app that it may
|
// FIXME The feature unsupported-browser needs to notify the app that it may
|
||||||
// need to render a different Component at its current location because the
|
// need to render a different Component at its current location because the
|
||||||
// execution enviroment has changed. The current location is not necessarily
|
// execution enviroment has changed. The current location is not necessarily
|
||||||
// available through window.location (e.g. on mobile) but the following
|
// available through window.location (e.g. on mobile) but the following
|
||||||
// works at the time of this writing.
|
// works at the time of this writing.
|
||||||
const windowLocation
|
const windowLocation = getState()['features/app'].app.getWindowLocation();
|
||||||
= store.getState()['features/app'].app.getWindowLocation();
|
|
||||||
|
|
||||||
if (windowLocation) {
|
if (windowLocation) {
|
||||||
const href = windowLocation.href;
|
const { href } = windowLocation;
|
||||||
|
|
||||||
href && store.dispatch(appNavigate(href));
|
href && dispatch(appNavigate(href));
|
||||||
}
|
}
|
||||||
|
|
||||||
return nextState;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
|
|
||||||
|
@ -6,6 +8,14 @@ import { isRoomValid } from '../../base/conference';
|
||||||
|
|
||||||
import { generateRoomWithoutSeparator } from '../functions';
|
import { generateRoomWithoutSeparator } from '../functions';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code AbstractWelcomePage}'s React {@code Component} prop types.
|
||||||
|
*/
|
||||||
|
type Props = {
|
||||||
|
_room: string,
|
||||||
|
dispatch: Dispatch<*>
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base (abstract) class for container component rendering the welcome page.
|
* Base (abstract) class for container component rendering the welcome page.
|
||||||
*
|
*
|
||||||
|
@ -22,38 +32,39 @@ export class AbstractWelcomePage extends Component {
|
||||||
dispatch: PropTypes.func
|
dispatch: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_mounted: ?boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save room name into component's local state.
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
* @property {number|null} animateTimeoutId - Identifier of the letter
|
||||||
|
* animation timeout.
|
||||||
|
* @property {string} generatedRoomname - Automatically generated room name.
|
||||||
|
* @property {string} room - Room name.
|
||||||
|
* @property {string} roomPlaceholder - Room placeholder that's used as a
|
||||||
|
* placeholder for input.
|
||||||
|
* @property {nubmer|null} updateTimeoutId - Identifier of the timeout
|
||||||
|
* updating the generated room name.
|
||||||
|
*/
|
||||||
|
state = {
|
||||||
|
animateTimeoutId: undefined,
|
||||||
|
generatedRoomname: '',
|
||||||
|
joining: false,
|
||||||
|
room: '',
|
||||||
|
roomPlaceholder: '',
|
||||||
|
updateTimeoutId: undefined
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a new {@code AbstractWelcomePage} instance.
|
* Initializes a new {@code AbstractWelcomePage} instance.
|
||||||
*
|
*
|
||||||
* @param {Object} props - The React {@code Component} props to initialize
|
* @param {Props} props - The React {@code Component} props to initialize
|
||||||
* the new {@code AbstractWelcomePage} instance with.
|
* the new {@code AbstractWelcomePage} instance with.
|
||||||
*/
|
*/
|
||||||
constructor(props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
/**
|
|
||||||
* Save room name into component's local state.
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
* @property {number|null} animateTimeoutId - Identifier of the letter
|
|
||||||
* animation timeout.
|
|
||||||
* @property {string} generatedRoomname - Automatically generated
|
|
||||||
* room name.
|
|
||||||
* @property {string} room - Room name.
|
|
||||||
* @property {string} roomPlaceholder - Room placeholder
|
|
||||||
* that's used as a placeholder for input.
|
|
||||||
* @property {nubmer|null} updateTimeoutId - Identifier of the timeout
|
|
||||||
* updating the generated room name.
|
|
||||||
*/
|
|
||||||
this.state = {
|
|
||||||
animateTimeoutId: null,
|
|
||||||
generatedRoomname: '',
|
|
||||||
joining: false,
|
|
||||||
room: '',
|
|
||||||
roomPlaceholder: '',
|
|
||||||
updateTimeoutId: null
|
|
||||||
};
|
|
||||||
|
|
||||||
// Bind event handlers so they are only bound once per instance.
|
// Bind event handlers so they are only bound once per instance.
|
||||||
this._animateRoomnameChanging
|
this._animateRoomnameChanging
|
||||||
= this._animateRoomnameChanging.bind(this);
|
= this._animateRoomnameChanging.bind(this);
|
||||||
|
@ -77,9 +88,9 @@ export class AbstractWelcomePage extends Component {
|
||||||
* before this mounted component receives new props.
|
* before this mounted component receives new props.
|
||||||
*
|
*
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
* @param {Object} nextProps - New props component will receive.
|
* @param {Props} nextProps - New props component will receive.
|
||||||
*/
|
*/
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps: Props) {
|
||||||
this.setState({ room: nextProps._room });
|
this.setState({ room: nextProps._room });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +105,8 @@ export class AbstractWelcomePage extends Component {
|
||||||
this._mounted = false;
|
this._mounted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_animateRoomnameChanging: (string) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animates the changing of the room name.
|
* Animates the changing of the room name.
|
||||||
*
|
*
|
||||||
|
@ -102,8 +115,8 @@ export class AbstractWelcomePage extends Component {
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_animateRoomnameChanging(word) {
|
_animateRoomnameChanging(word: string) {
|
||||||
let animateTimeoutId = null;
|
let animateTimeoutId;
|
||||||
const roomPlaceholder = this.state.roomPlaceholder + word.substr(0, 1);
|
const roomPlaceholder = this.state.roomPlaceholder + word.substr(0, 1);
|
||||||
|
|
||||||
if (word.length > 1) {
|
if (word.length > 1) {
|
||||||
|
@ -115,7 +128,6 @@ export class AbstractWelcomePage extends Component {
|
||||||
},
|
},
|
||||||
70);
|
70);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
animateTimeoutId,
|
animateTimeoutId,
|
||||||
roomPlaceholder
|
roomPlaceholder
|
||||||
|
@ -145,6 +157,8 @@ export class AbstractWelcomePage extends Component {
|
||||||
return this.state.joining || !isRoomValid(this.state.room);
|
return this.state.joining || !isRoomValid(this.state.room);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onJoin: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles joining. Either by clicking on 'Join' button
|
* Handles joining. Either by clicking on 'Join' button
|
||||||
* or by pressing 'Enter' in room name input field.
|
* or by pressing 'Enter' in room name input field.
|
||||||
|
@ -160,15 +174,16 @@ export class AbstractWelcomePage extends Component {
|
||||||
|
|
||||||
// By the time the Promise of appNavigate settles, this component
|
// By the time the Promise of appNavigate settles, this component
|
||||||
// may have already been unmounted.
|
// may have already been unmounted.
|
||||||
const onAppNavigateSettled = () => {
|
const onAppNavigateSettled
|
||||||
this._mounted && this.setState({ joining: false });
|
= () => this._mounted && this.setState({ joining: false });
|
||||||
};
|
|
||||||
|
|
||||||
this.props.dispatch(appNavigate(room))
|
this.props.dispatch(appNavigate(room))
|
||||||
.then(onAppNavigateSettled, onAppNavigateSettled);
|
.then(onAppNavigateSettled, onAppNavigateSettled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onRoomChange: (string) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles 'change' event for the room name text input field.
|
* Handles 'change' event for the room name text input field.
|
||||||
*
|
*
|
||||||
|
@ -177,10 +192,12 @@ export class AbstractWelcomePage extends Component {
|
||||||
* @protected
|
* @protected
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onRoomChange(value) {
|
_onRoomChange(value: string) {
|
||||||
this.setState({ room: value });
|
this.setState({ room: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_updateRoomname: () => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers the generation of a new room name and initiates an animation of
|
* Triggers the generation of a new room name and initiates an animation of
|
||||||
* its changing.
|
* its changing.
|
||||||
|
@ -214,7 +231,7 @@ export class AbstractWelcomePage extends Component {
|
||||||
* _room: string
|
* _room: string
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
export function _mapStateToProps(state) {
|
export function _mapStateToProps(state: Object) {
|
||||||
return {
|
return {
|
||||||
_room: state['features/base/conference'].room
|
_room: state['features/base/conference'].room
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue