Flow, coding style

This commit is contained in:
Lyubo Marinov 2017-10-06 15:15:51 -05:00
parent d4d2cb4aad
commit 2eb36c4053
8 changed files with 179 additions and 165 deletions

View File

@ -8,16 +8,6 @@
*/
export const CANCEL_LOGIN = Symbol('CANCEL_LOGIN');
/**
* The type of (redux) action which signals that the {@link WaitForOwnerDialog}
* has been canceled.
*
* {
* type: CANCEL_WAIT_FOR_OWNER
* }
*/
export const CANCEL_WAIT_FOR_OWNER = Symbol('CANCEL_WAIT_FOR_OWNER');
/**
* The type of (redux) action which signals that the cyclic operation of waiting
* for conference owner has been aborted.

View File

@ -1,11 +1,11 @@
/* @flow */
// @flow
import { appNavigate } from '../app';
import { checkIfCanJoin } from '../base/conference';
import { openDialog } from '../base/dialog';
import {
CANCEL_LOGIN,
CANCEL_WAIT_FOR_OWNER,
STOP_WAIT_FOR_OWNER,
UPGRADE_ROLE_FINISHED,
UPGRADE_ROLE_STARTED,
@ -25,7 +25,7 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
* @param {string} password - The XMPP user's password.
* @param {JitsiConference} conference - The conference for which the local
* participant's role will be upgraded.
* @returns {function({ dispatch: Dispatch, getState: Function })}
* @returns {Function}
*/
export function authenticateAndUpgradeRole(
id: string,
@ -79,13 +79,12 @@ export function cancelLogin() {
/**
* Cancels {@link WaitForOwnerDialog}. Will navigate back to the welcome page.
*
* @returns {{
* type: CANCEL_WAIT_FOR_OWNER
* }}
* @returns {Function}
*/
export function cancelWaitForOwner() {
return {
type: CANCEL_WAIT_FOR_OWNER
return (dispatch: Dispatch<*>) => {
dispatch(stopWaitForOwner());
dispatch(appNavigate(undefined));
};
}
@ -197,7 +196,7 @@ function _upgradeRoleStarted(thenableWithCancel) {
* start the process of "waiting for the owner" by periodically trying to join
* the room every five seconds.
*
* @returns {function({ dispatch: Dispatch })}
* @returns {Function}
*/
export function waitForOwner() {
return (dispatch: Dispatch) =>

View File

@ -22,7 +22,6 @@ import {
} from './actions';
import {
CANCEL_LOGIN,
CANCEL_WAIT_FOR_OWNER,
STOP_WAIT_FOR_OWNER,
WAIT_FOR_OWNER
} from './actionTypes';
@ -40,8 +39,8 @@ import { LoginDialog, WaitForOwnerDialog } from './components';
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case CANCEL_LOGIN: {
const { thenableWithCancel }
= store.getState()['features/authentication'];
const { dispatch, getState } = store;
const { thenableWithCancel } = getState()['features/authentication'];
thenableWithCancel && thenableWithCancel.cancel();
@ -53,27 +52,18 @@ MiddlewareRegistry.register(store => next => action => {
// Instead of hiding show the new one.
const result = next(action);
store.dispatch(_openWaitForOwnerDialog());
dispatch(_openWaitForOwnerDialog());
return result;
}
// Go back to the app's entry point.
_hideLoginDialog(store);
store.dispatch(appNavigate(undefined));
dispatch(appNavigate(undefined));
}
break;
}
case CANCEL_WAIT_FOR_OWNER: {
const result = next(action);
store.dispatch(stopWaitForOwner());
store.dispatch(appNavigate(undefined));
return result;
}
case CONFERENCE_FAILED:
if (action.error.name
=== JitsiConferenceErrors.AUTHENTICATION_REQUIRED) {

View File

@ -71,6 +71,15 @@ export default class AbstractDialog extends Component {
this._mounted = false;
}
/**
* Dispatches a redux action to hide this dialog.
*
* @returns {*} The return value of {@link hideDialog}.
*/
_hide() {
return this.props.dispatch(hideDialog());
}
_onCancel: () => void;
/**
@ -84,7 +93,7 @@ export default class AbstractDialog extends Component {
if ((typeof cancelDisabled === 'undefined' || !cancelDisabled)
&& (!onCancel || onCancel())) {
this.props.dispatch(hideDialog());
this._hide();
}
}
@ -147,7 +156,7 @@ export default class AbstractDialog extends Component {
_onSubmitFulfilled() {
this._mounted && this.setState({ submitting: false });
this.props.dispatch(hideDialog());
this._hide();
}
_onSubmitRejected: () => void;

View File

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

View File

@ -1,3 +1,5 @@
// @flow
import Tabs from '@atlaskit/tabs';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
@ -15,7 +17,12 @@ const THUMBNAIL_SIZE = {
};
const UPDATE_INTERVAL = 1000;
const TAB_CONFIGURATIONS = [
type TabConfiguration = {
defaultSelected?: boolean,
label: string,
type: string
};
const TAB_CONFIGURATIONS: Array<TabConfiguration> = [
{
/**
* The indicator which determines whether this tab configuration is
@ -83,6 +90,14 @@ class DesktopPicker extends Component {
t: PropTypes.func
};
_poller = null;
state = {
selectedSource: {},
tabsToPopulate: [],
typesToFetch: []
};
/**
* Initializes a new DesktopPicker instance.
*
@ -92,13 +107,7 @@ class DesktopPicker extends Component {
constructor(props) {
super(props);
this.state = {
selectedSource: {},
tabsToPopulate: [],
typesToFetch: []
};
this._poller = null;
// Bind event handlers so they are only bound once per instance.
this._onCloseModal = this._onCloseModal.bind(this);
this._onPreviewClick = this._onPreviewClick.bind(this);
this._onSubmit = this._onSubmit.bind(this);
@ -175,12 +184,14 @@ class DesktopPicker extends Component {
);
}
_onCloseModal: (?string, string) => void;
/**
* Dispatches an action to hide the DesktopPicker and invokes the passed in
* callback with a selectedSource, if any.
*
* @param {string} id - The id of the DesktopCapturerSource to pass into the
* onSourceChoose callback.
* @param {string} [id] - The id of the DesktopCapturerSource to pass into
* the onSourceChoose callback.
* @param {string} type - The type of the DesktopCapturerSource to pass into
* the onSourceChoose callback.
* @returns {void}
@ -190,6 +201,8 @@ class DesktopPicker extends Component {
this.props.dispatch(hideDialog());
}
_onPreviewClick: (string, string) => void;
/**
* Sets the currently selected DesktopCapturerSource.
*
@ -206,6 +219,27 @@ class DesktopPicker extends Component {
});
}
/**
* Handles changing of allowed desktop sharing source types.
*
* @param {Array<string>} desktopSharingSourceTypes - The types that will be
* fetched and displayed.
* @returns {void}
*/
_onSourceTypesConfigChanged(desktopSharingSourceTypes = []) {
const tabsToPopulate
= TAB_CONFIGURATIONS.filter(({ type }) =>
desktopSharingSourceTypes.includes(type)
&& VALID_TYPES.includes(type));
this.setState({
tabsToPopulate,
typesToFetch: tabsToPopulate.map(c => c.type)
});
}
_onSubmit: () => void;
/**
* Request to close the modal and execute callbacks with the selected source
* id.
@ -268,24 +302,7 @@ class DesktopPicker extends Component {
this._poller = null;
}
/**
* Handles changing of allowed desktop sharing source types.
*
* @param {Array<string>} desktopSharingSourceTypes - The types that will be
* fetched and displayed.
* @returns {void}
*/
_onSourceTypesConfigChanged(desktopSharingSourceTypes = []) {
const tabsToPopulate = TAB_CONFIGURATIONS.filter(
c => desktopSharingSourceTypes.includes(c.type)
&& VALID_TYPES.includes(c.type)
);
this.setState({
tabsToPopulate,
typesToFetch: tabsToPopulate.map(c => c.type)
});
}
_updateSources: () => void;
/**
* Dispatches an action to get currently available DesktopCapturerSources.

View File

@ -1,3 +1,5 @@
// @flow
import Avatar from '@atlaskit/avatar';
import InlineMessage from '@atlaskit/inline-message';
import { Immutable } from 'nuclear-js';
@ -8,8 +10,7 @@ import { connect } from 'react-redux';
import { getInviteURL } from '../../base/connection';
import { Dialog, hideDialog } from '../../base/dialog';
import { translate } from '../../base/i18n';
import MultiSelectAutocomplete
from '../../base/react/components/web/MultiSelectAutocomplete';
import { MultiSelectAutocomplete } from '../../base/react';
import { invitePeople, inviteRooms, searchPeople } from '../functions';
@ -67,6 +68,54 @@ class AddPeopleDialog extends Component {
t: PropTypes.func
};
_multiselect = null;
_resourceClient = {
makeQuery: text => {
const {
_jwt,
_peopleSearchQueryTypes,
_peopleSearchUrl
} = this.props; // eslint-disable-line no-invalid-this
return (
searchPeople(
_peopleSearchUrl,
_jwt,
text,
_peopleSearchQueryTypes));
},
parseResults: response => response.map(user => {
return {
content: user.name,
elemBefore: <Avatar
size = 'medium'
src = { user.avatar } />,
item: user,
value: user.id
};
})
};
state = {
/**
* Indicating that an error occurred when adding people to the call.
*/
addToCallError: false,
/**
* Indicating that we're currently adding the new people to the
* call.
*/
addToCallInProgress: false,
/**
* The list of invite items.
*/
inviteItems: new Immutable.List()
};
/**
* Initializes a new {@code AddPeopleDialog} instance.
*
@ -76,56 +125,7 @@ class AddPeopleDialog extends Component {
constructor(props) {
super(props);
this.state = {
/**
* Indicating that an error occurred when adding people to the call.
*/
addToCallError: false,
/**
* Indicating that we're currently adding the new people to the
* call.
*/
addToCallInProgress: false,
/**
* The list of invite items.
*/
inviteItems: new Immutable.List()
};
this._multiselect = null;
this._resourceClient = {
makeQuery: text => {
const {
_jwt,
_peopleSearchQueryTypes,
_peopleSearchUrl
} = this.props;
return searchPeople(
_peopleSearchUrl,
_jwt,
text,
_peopleSearchQueryTypes
);
},
parseResults: response => response.map(user => {
const avatar = ( // eslint-disable-line no-extra-parens
<Avatar
size = 'medium'
src = { user.avatar } />
);
return {
content: user.name,
value: user.id,
elemBefore: avatar,
item: user
};
})
};
// Bind event handlers so they are only bound once per instance.
this._isAddDisabled = this._isAddDisabled.bind(this);
this._onSelectionChange = this._onSelectionChange.bind(this);
this._onSubmit = this._onSubmit.bind(this);
@ -144,9 +144,9 @@ class AddPeopleDialog extends Component {
* invite.
*/
if (prevState.addToCallError
&& !this.state.addToCallInProgress
&& !this.state.addToCallError
&& this._multiselect) {
&& !this.state.addToCallInProgress
&& !this.state.addToCallError
&& this._multiselect) {
this._multiselect.clear();
}
}
@ -169,44 +169,22 @@ class AddPeopleDialog extends Component {
);
}
/**
* Renders the input form.
*
* @returns {ReactElement}
* @private
*/
_renderUserInputForm() {
const { t } = this.props;
return (
<div className = 'add-people-form-wrap'>
{ this._renderErrorMessage() }
<MultiSelectAutocomplete
isDisabled
= { this.state.addToCallInProgress || false }
noMatchesFound = { t('addPeople.noResults') }
onSelectionChange = { this._onSelectionChange }
placeholder = { t('addPeople.searchPlaceholder') }
ref = { this._setMultiSelectElement }
resourceClient = { this._resourceClient }
shouldFitContainer = { true }
shouldFocus = { true } />
</div>
);
}
_isAddDisabled: () => boolean;
/**
* Indicates if the Add button should be disabled.
*
* @private
* @returns {boolean} - True to indicate that the Add button should
* be disabled, false otherwise.
* @private
*/
_isAddDisabled() {
return !this.state.inviteItems.length
|| this.state.addToCallInProgress;
}
_onSelectionChange: (Map<*, *>) => void;
/**
* Handles a selection change.
*
@ -222,6 +200,8 @@ class AddPeopleDialog extends Component {
});
}
_onSubmit: () => void;
/**
* Handles the submit button action.
*
@ -245,27 +225,28 @@ class AddPeopleDialog extends Component {
this.props._inviteUrl,
this.props._jwt,
this.state.inviteItems.filter(i => i.type === 'user'))
.then(() => {
this.setState({
addToCallInProgress: false
});
.then(
/* onFulfilled */ () => {
this.setState({
addToCallInProgress: false
});
this.props.hideDialog();
})
.catch(() => {
this.setState({
addToCallInProgress: false,
addToCallError: true
this.props.hideDialog();
},
/* onRejected */ () => {
this.setState({
addToCallInProgress: false,
addToCallError: true
});
});
});
}
}
/**
* Renders the error message if the add doesn't succeed.
*
* @returns {ReactElement|null}
* @private
* @returns {ReactElement|null}
*/
_renderErrorMessage() {
if (!this.state.addToCallError) {
@ -304,6 +285,34 @@ class AddPeopleDialog extends Component {
);
}
/**
* Renders the input form.
*
* @private
* @returns {ReactElement}
*/
_renderUserInputForm() {
const { t } = this.props;
return (
<div className = 'add-people-form-wrap'>
{ this._renderErrorMessage() }
<MultiSelectAutocomplete
isDisabled
= { this.state.addToCallInProgress || false }
noMatchesFound = { t('addPeople.noResults') }
onSelectionChange = { this._onSelectionChange }
placeholder = { t('addPeople.searchPlaceholder') }
ref = { this._setMultiSelectElement }
resourceClient = { this._resourceClient }
shouldFitContainer = { true }
shouldFocus = { true } />
</div>
);
}
_setMultiSelectElement: (Object) => void;
/**
* Sets the instance variable for the multi select component
* element so it can be accessed directly.
@ -338,13 +347,13 @@ function _mapStateToProps(state) {
return {
_conference: conference,
_jwt: state['features/jwt'].jwt,
_inviteUrl: getInviteURL(state),
_inviteServiceUrl: inviteServiceUrl,
_inviteUrl: getInviteURL(state),
_jwt: state['features/jwt'].jwt,
_peopleSearchQueryTypes: peopleSearchQueryTypes,
_peopleSearchUrl: peopleSearchUrl
};
}
export default translate(
connect(_mapStateToProps, { hideDialog })(AddPeopleDialog));
export default translate(connect(_mapStateToProps, { hideDialog })(
AddPeopleDialog));

View File

@ -1,4 +1,4 @@
/* @flow */
// @flow
import { NativeModules } from 'react-native';
import uuid from 'uuid';
@ -238,9 +238,9 @@ function _onPerformEndCallAction({ callUUID }) {
const conference = getCurrentConference(getState);
if (conference && conference.callUUID === callUUID) {
// We arrive here when a call is ended by the system, for
// example when another incoming call is received and the user
// selects "End & Accept".
// We arrive here when a call is ended by the system, for example, when
// another incoming call is received and the user selects "End &
// Accept".
delete conference.callUUID;
dispatch(appNavigate(undefined));
}