diff --git a/app/assets/styles/blink/_Preview.scss b/app/assets/styles/blink/_Preview.scss index 5c3690b..681fe37 100644 --- a/app/assets/styles/blink/_Preview.scss +++ b/app/assets/styles/blink/_Preview.scss @@ -1,28 +1,32 @@ .container { flex: 1; } .videoContainer { width: 100%; height: 100%; } .video { height: 100%; width: 100%; } +.subheader { + font-size: 30px; +} + .buttonContainer { position: absolute; - bottom: 40; + bottom: 20; margin: 0 auto; width: 100%; z-index: 99; justify-content: center; align-items: center; } .button { background-color: rgba(#a94442, .8); } diff --git a/app/components/NavigationBar.js b/app/components/NavigationBar.js index 224c3e7..6d0cfeb 100644 --- a/app/components/NavigationBar.js +++ b/app/components/NavigationBar.js @@ -1,137 +1,138 @@ import React, { Component } from 'react'; import { Linking, Image, View } from 'react-native'; import PropTypes from 'prop-types'; import autoBind from 'auto-bind'; import { Appbar, Menu, Divider, Text } from 'react-native-paper'; import { Icon } from 'material-bread'; import config from '../config'; import AboutModal from './AboutModal'; import CallMeMaybeModal from './CallMeMaybeModal'; import styles from '../assets/styles/blink/_NavigationBar.scss'; const blinkLogo = require('../assets/images/blink-white-big.png'); class NavigationBar extends Component { constructor(props) { super(props); autoBind(this); this.state = { showAboutModal: false, showCallMeMaybeModal: false, mute: false, menuVisible: false } this.menuRef = React.createRef(); } handleMenu(event) { this.callUrl = `${config.publicUrl}/call/${this.props.account.id}`; switch (event) { case 'about': this.toggleAboutModal(); break; case 'callMeMaybe': this.toggleCallMeMaybeModal(); break; case 'logOut': this.props.logout(); break; case 'preview': this.props.preview(); break; case 'settings': Linking.openURL(config.serverSettingsUrl); break; default: break; } this.setState({menuVisible: false}); } toggleMute() { this.setState(prevState => ({mute: !prevState.mute})); this.props.toggleMute(); } toggleAboutModal() { this.setState({showAboutModal: !this.state.showAboutModal}); } toggleCallMeMaybeModal() { this.setState({showCallMeMaybeModal: !this.state.showCallMeMaybeModal}); } render() { const muteIcon = this.state.mute ? 'bell-off' : 'bell'; let statusIcon = null; let account_id = ''; statusIcon = 'check-circle'; if (!this.props.connection || this.props.connection.state !== 'ready') { statusIcon = 'error-outline'; } else if (this.props.registrationState && this.props.registrationState !== 'registered') { statusIcon = 'priority-high'; } // let callUrl = ''; if (this.props.account) { account_id = this.props.account.id; callUrl = config.publicUrl + "/call/" + account_id; } return ( {statusIcon ? : null } this.setState({menuVisible: !this.state.menuVisible})} anchor={ this.setState({menuVisible: !this.state.menuVisible})} /> } > this.handleMenu('about')} icon="information" title="About Sylk" /> + this.handleMenu('preview')} icon="video" title="Video preview" /> this.handleMenu('callMeMaybe')} icon="share" title="Call me, maybe?" /> this.handleMenu('settings')} icon="wrench" title="Server settings" /> this.handleMenu('logOut')} icon="logout" title="Sign Out" /> ); } } NavigationBar.propTypes = { notificationCenter : PropTypes.func.isRequired, account : PropTypes.object.isRequired, logout : PropTypes.func.isRequired, preview : PropTypes.func.isRequired, toggleMute : PropTypes.func.isRequired }; export default NavigationBar; diff --git a/app/components/Preview.js b/app/components/Preview.js index ce0ccff..9b9fe49 100644 --- a/app/components/Preview.js +++ b/app/components/Preview.js @@ -1,190 +1,193 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import debug from 'react-native-debug'; import { View } from 'react-native'; import { Text, IconButton, List, Appbar } from 'react-native-paper'; import autoBind from 'auto-bind'; import { RTCView } from 'react-native-webrtc'; import ConferenceDrawer from './ConferenceDrawer'; import VolumeBar from './VolumeBar'; import styles from '../assets/styles/blink/_Preview.scss'; const DEBUG = debug('blinkrtc:Preview'); debug.enable('*'); class Preview extends Component { constructor(props) { super(props); autoBind(this); - let mic = { label: 'No mic' }; - let camera = { label: 'No Camera' }; + let mic = { label: 'No microphone' }; + let camera = { label: 'No camera' }; if ('camera' in this.props.selectedDevices) { camera = this.props.selectedDevices.camera; } else if (this.props.localMedia.getVideoTracks().length !== 0) { - camera.label = this.props.localMedia.getVideoTracks()[0].label; + camera.label = camera.facing === 'environment' ? 'Back camera': 'Front camera'; } if ('mic' in this.props.selectedDevices) { mic = this.props.selectedDevices.mic; } else if (this.props.localMedia.getAudioTracks().length !== 0) { mic.label = this.props.localMedia.getAudioTracks()[0].label; } this.state = { camera: camera, showDrawer: false, mic: mic, streamURL: null } this.devices = []; this.localVideo = React.createRef(); } componentDidMount() { this.setState({streamURL: this.props.localMedia}); navigator.mediaDevices.enumerateDevices() .then((devices) => { this.devices = devices; - let newState = {}; - if (this.state.camera.label !== 'No Camera') { - if (!devices.find((device) => {return device.kind === 'videoinput'})) { - newState.camera = {label: 'No Camera'}; - } else if (this.props.localMedia.getVideoTracks().length !== 0) { - newState.camera = {label: this.props.localMedia.getVideoTracks()[0].label}; + + newState.camera = {label: 'No camera'}; + + devices.forEach((device) => { + if (device.kind === 'videoinput') { + let label = device.facing === 'environment' ? 'Back camera': 'Front camera'; + newState.camera = {label: label}; } - } + }); - if (this.state.mic.label !== 'No mic') { + if (this.state.mic.label !== 'No microphone') { if (!devices.find((device) => {return device.kind === 'audioinput'})) { - newState.mic = {label: 'No mic'}; + newState.mic = {label: 'No microphone'}; } else if (this.props.localMedia.getAudioTracks().length !== 0) { newState.mic = { label: this.props.localMedia.getAudioTracks()[0].label}; } } if (Object.keys(newState).length != 0) { this.setState(Object.assign({},newState)); } + }) .catch(function(error) { DEBUG('Device enumeration failed: %o', error); }); + } componentWillReceiveProps(nextProps) { if (nextProps.localMedia !== this.props.localMedia) { this.setState({streamURL: nextProps.localMedia}) } - if (nextProps.selectedDevices !== this.props.selectedDevices) { - let camera = {label: 'No Camera'}; - let mic = {label: 'No Mic'}; + let camera = {label: 'No camera'}; + let mic = {label: 'No microphone'}; if ('camera' in nextProps.selectedDevices) { camera = nextProps.selectedDevices.camera; + camera.label = camera.facing === 'environment' ? 'Back camera': 'Front camera'; } if ('mic' in nextProps.selectedDevices) { mic = nextProps.selectedDevices.mic; } this.setState({ camera, mic }); } } setDevice = (device) => (e) => { e.preventDefault(); if (device.label !== this.state.mic.label && device.label !== this.state.camera.label) { this.props.setDevice(device); - this.setState({showDrawer: false}); } + this.setState({showDrawer: false}); } hangupCall(event) { event.preventDefault(); this.props.hangupCall(); } toggleDrawer() { this.setState({showDrawer: !this.state.showDrawer}); } render() { - // let cameras = []; - // let mics = []; - - // this.devices.forEach((device) => { - // if (device.kind === 'videoinput') { - // cameras.push( - // - // ); - // } else if (device.kind === 'audioinput') { - // mics.push( - // - // ); - // } - // }); - + let cameras = []; + let mics = []; + + this.devices.forEach((device) => { + if (device.kind === 'videoinput') { + device.label = device.facing === 'environment' ? 'Back camera': 'Front camera'; + cameras.push( + + ); + } else if (device.kind === 'audioinput') { + mics.push( + + ); + } + }); let header = null; if (this.state.camera !== '') { header = ( { !this.state.showDrawer ? : null } ); } - // let drawercontent = ( - // - // - // Video Camera - // {cameras} - // - // - // Audio Input - // {mics} - // - // - // ); + let drawercontent = ( + + + Video cameras + {cameras} + + + Audio inputs + {mics} + + + ); return ( {header} - {/* + {drawercontent} - */} + ); } } Preview.propTypes = { hangupCall: PropTypes.func, localMedia: PropTypes.object.isRequired, setDevice: PropTypes.func.isRequired, selectedDevices: PropTypes.object.isRequired }; export default Preview;