import React from 'react'; import { Animated, Keyboard, SafeAreaView, TextInput, TouchableHighlight, TouchableOpacity, View } from 'react-native'; import Permissions from 'react-native-permissions'; import { connect } from 'react-redux'; import { translate } from '../../base/i18n'; import { Icon } from '../../base/font-icons'; import { MEDIA_TYPE } from '../../base/media'; import { Header, LoadingIndicator, Text } from '../../base/react'; import { ColorPalette } from '../../base/styles'; import { createDesiredLocalTracks, destroyLocalTracks } from '../../base/tracks'; import { SettingsView } from '../../settings'; import { AbstractWelcomePage, _mapStateToProps } from './AbstractWelcomePage'; import { setSideBarVisible } from '../actions'; import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay'; import styles, { PLACEHOLDER_TEXT_COLOR } from './styles'; import VideoSwitch from './VideoSwitch'; import WelcomePageLists from './WelcomePageLists'; import WelcomePageSideBar from './WelcomePageSideBar'; /** * The native container rendering the welcome page. * * @extends AbstractWelcomePage */ class WelcomePage extends AbstractWelcomePage { /** * Constructor of the Component. * * @inheritdoc */ constructor(props) { super(props); this.state._fieldFocused = false; this.state.hintBoxAnimation = new Animated.Value(0); // Bind event handlers so they are only bound once per instance. this._onFieldFocusChange = this._onFieldFocusChange.bind(this); this._onShowSideBar = this._onShowSideBar.bind(this); this._renderHintBox = this._renderHintBox.bind(this); // Specially bind functions to avoid function definition on render. this._onFieldBlur = this._onFieldFocusChange.bind(this, false); this._onFieldFocus = this._onFieldFocusChange.bind(this, true); } /** * Implements React's {@link Component#componentWillMount()}. Invoked * immediately before mounting occurs. Creates a local video track if none * is available and the camera permission was already granted. * * @inheritdoc * @returns {void} */ componentWillMount() { super.componentWillMount(); const { dispatch } = this.props; if (this.props._settings.startAudioOnly) { dispatch(destroyLocalTracks()); } else { // Make sure we don't request the permission for the camera from // the start. We will, however, create a video track iff the user // already granted the permission. Permissions.check('camera').then(response => { response === 'authorized' && dispatch(createDesiredLocalTracks(MEDIA_TYPE.VIDEO)); }); } } /** * Implements React's {@link Component#render()}. Renders a prompt for * entering a room name. * * @inheritdoc * @returns {ReactElement} */ render() { const { buttonStyle, pageStyle } = Header; const roomnameAccLabel = 'welcomepage.accessibilityLabel.roomname'; const { t } = this.props; return (
{ this._renderHintBox() }
); } /** * Constructs a style array to handle the hint box animation. * * @private * @returns {Array} */ _getHintBoxStyle() { return [ styles.hintContainer, { opacity: this.state.hintBoxAnimation } ]; } /** * Callback for when the room field's focus changes so the hint box * must be rendered or removed. * * @private * @param {boolean} focused - The focused state of the field. * @returns {void} */ _onFieldFocusChange(focused) { focused && this.setState({ _fieldFocused: true }); Animated.timing( this.state.hintBoxAnimation, { duration: 300, toValue: focused ? 1 : 0 }) .start(animationState => animationState.finished && !focused && this.setState({ _fieldFocused: false })); } /** * Toggles the side bar. * * @private * @returns {void} */ _onShowSideBar() { Keyboard.dismiss(); this.props.dispatch(setSideBarVisible(true)); } /** * Renders the hint box if necessary. * * @private * @returns {React$Node} */ _renderHintBox() { if (this.state._fieldFocused) { const { t } = this.props; return ( { t('welcomepage.roomnameHint') } { this._renderJoinButton() } ); } return null; } /** * Renders the join button. * * @private * @returns {ReactElement} */ _renderJoinButton() { const { t } = this.props; let children; if (this.state.joining) { // TouchableHighlight is picky about what its children can be, so // wrap it in a native component, i.e. View to avoid having to // modify non-native children. children = ( ); } else { children = ( { this.props.t('welcomepage.join') } ); } const buttonDisabled = this._isJoinDisabled(); return ( { children } ); } } export default translate(connect(_mapStateToProps)(WelcomePage));