diff --git a/app/assets/styles/blink/_HistoryCard.scss b/app/assets/styles/blink/_HistoryCard.scss index ca6c91c..2db3bbe 100644 --- a/app/assets/styles/blink/_HistoryCard.scss +++ b/app/assets/styles/blink/_HistoryCard.scss @@ -1,23 +1,27 @@ .content { flex: 1; flex-direction: row; } .mainContent { - width: 80%; -} - -.userIcon { + width: 100%; } .userAvatarContent { margin-top: 7px; margin-left: auto; } -.container { +.landscapeContainer { + width: 42%; + margin-left: 5%; + margin-top: 10px; + border-radius: 5px; +} + +.portraitContainer { width: 90%; margin: 0 auto; margin-top: 10px; border-radius: 5px; } diff --git a/app/assets/styles/blink/_HistoryTileBox.scss b/app/assets/styles/blink/_HistoryTileBox.scss index 6e1738f..22b1e30 100644 --- a/app/assets/styles/blink/_HistoryTileBox.scss +++ b/app/assets/styles/blink/_HistoryTileBox.scss @@ -1,4 +1,6 @@ .container { - margin-top: 20px; + margin-top: 10px; margin-bottom: 0px; + flex: 1; + flex-direction: column; } diff --git a/app/assets/styles/blink/_ReadyBox.scss b/app/assets/styles/blink/_ReadyBox.scss index a7b1e5f..e518792 100644 --- a/app/assets/styles/blink/_ReadyBox.scss +++ b/app/assets/styles/blink/_ReadyBox.scss @@ -1,100 +1,101 @@ @import './variables'; .wholeContainer { flex: 1; flex-direction: column; justify-content: center; } .container { margin: 0 auto; width: 90%; - padding-top: 20px; + padding-top: 10px; } .landscapeTitle { color: white; font-size: 20px; height: 0%; } .portraitTitle { color: white; font-size: 20px; } .footer { flex: 1; justify-content: flex-end; padding-bottom: 15px; } .button { background-color: rgba(#6DAA63, .9); margin: 10px; padding-top: 2px; padding-left: 1px; } .iosButton { background-color: rgba(#6DAA63, .9); margin: 10px; padding-top: 4px; padding-left: 1px; } .androidButton { background-color: rgba(#6DAA63, .9); margin: 10px; padding-top: 1px; padding-left: 1px; } .conferenceButton { background-color: rgba(#4572a6, 1); margin: 10px; } .landscapeUriButtonGroup { flex-direction: row; justify-content: space-between; + width: 90%; } .portraitUriButtonGroup { flex-direction: column; } .buttonGroup { flex-direction: row; - padding-top: 10px; + padding-top: 5px; justify-content: center; } .uriInputBox { align: left; padding-top: 10px; width: 100%; } .landscapeUriInputBox { align: left; padding-top: 10px; - width: 350px; + width: 52%; } .portraitUriInputBox { align: left; padding-top: 10px; width: 100%; } .landscapeHistory { width: 100%; flex: 9; } .portraitHistory { width: 100%; flex: 9; } diff --git a/app/components/HistoryCard.js b/app/components/HistoryCard.js index 954d358..cab8fa9 100644 --- a/app/components/HistoryCard.js +++ b/app/components/HistoryCard.js @@ -1,106 +1,111 @@ -import React from 'react'; +import React from 'react'; import { View } from 'react-native'; import PropTypes from 'prop-types'; import moment from 'moment'; import momentFormat from 'moment-duration-format'; import { Card, IconButton, Caption, Title, Subheading } from 'react-native-paper'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import styles from '../assets/styles/blink/_HistoryCard.scss'; import UserIcon from './UserIcon'; const HistoryCard = (props) => { const identity = { displayName: props.historyItem.displayName, uri: props.historyItem.remoteParty || props.historyItem } + console.log(identity); + const startVideoCall = (e) => { e.stopPropagation(); props.setTargetUri(identity.uri); // We need to wait for targetURI setImmediate(() => { props.startVideoCall(e); }); } const startAudioCall = (e) => { e.stopPropagation(); props.setTargetUri(identity.uri); // We need to wait for targetURI setImmediate(() => { props.startAudioCall(e); }); } let duration = moment.duration(props.historyItem.duration, 'seconds').format('hh:mm:ss', {trim: false}); + let containerClass = (props.orientation === 'landscape') ? styles.landscapeContainer : styles.portraitContainer; + let color = {}; if (props.historyItem.direction === 'received' && props.historyItem.duration === 0) { color.color = '#a94442'; duration = 'missed'; } else if (props.historyItem.direction === 'placed' && props.historyItem.duration === 0) { // color.color = 'blue'; duration = 'cancelled'; } const name = identity.displayName || identity.uri; let title = identity.displayName || identity.uri; let subtitle = identity.uri; if (duration) { let subtitle = identity.uri + ' (' + duration + ')'; } if (!identity.displayName) { title = identity.uri; if (duration === 'missed') { subtitle = 'Last call missed'; } else if (duration === 'cancelled') { subtitle = 'Last call cancelled'; } else { subtitle = 'Last call duration ' + duration ; } } return ( {props.setTargetUri(identity.uri)}} onLongPress={startVideoCall} - style={styles.container} + style={containerClass} > {title} {subtitle} {props.historyItem.startTime} ); /* */ } HistoryCard.propTypes = { historyItem : PropTypes.object, - startAudioCall : PropTypes.func.isRequired, - startVideoCall : PropTypes.func.isRequired, - setTargetUri : PropTypes.func.isRequired + startAudioCall : PropTypes.func, + startVideoCall : PropTypes.func, + setTargetUri : PropTypes.func, + orientation : PropTypes.string }; export default HistoryCard; diff --git a/app/components/HistoryTileBox.js b/app/components/HistoryTileBox.js index e4f32cb..1239e4d 100644 --- a/app/components/HistoryTileBox.js +++ b/app/components/HistoryTileBox.js @@ -1,20 +1,45 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { ScrollView } from 'react-native'; +import { SafeAreaView, ScrollView, View, FlatList, Text } from 'react-native'; +import HistoryCard from './HistoryCard'; import styles from '../assets/styles/blink/_HistoryTileBox.scss'; const HistoryTileBox = (props) => { - return ( - - {props.children} - - ); + + const renderItem = ({ item }) => ( + + ); + + let columns = props.orientation === 'landscape' ? 2 : 1; + + return ( + + item.sessionId} + key={props.orientation} + /> + + ); + } HistoryTileBox.propTypes = { - children : PropTypes.node + items : PropTypes.array, + orientation : PropTypes.string, + startAudioCall : PropTypes.func, + startVideoCall : PropTypes.func, + setTargetUri : PropTypes.func }; export default HistoryTileBox; diff --git a/app/components/ReadyBox.js b/app/components/ReadyBox.js index 854da3d..55ccbba 100644 --- a/app/components/ReadyBox.js +++ b/app/components/ReadyBox.js @@ -1,215 +1,211 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; // import VizSensor = require('react-visibility-sensor').default; import autoBind from 'auto-bind'; import { View, Platform} from 'react-native'; import { IconButton, Title } from 'react-native-paper'; import ConferenceModal from './ConferenceModal'; -import HistoryCard from './HistoryCard'; import HistoryTileBox from './HistoryTileBox'; import FooterBox from './FooterBox'; import URIInput from './URIInput'; import config from '../config'; import utils from '../utils'; import styles from '../assets/styles/blink/_ReadyBox.scss'; class ReadyBox extends Component { constructor(props) { super(props); autoBind(this); this.state = { targetUri: this.props.missedTargetUri, showConferenceModal: false, sticky: false, }; } getTargetUri() { const defaultDomain = this.props.account.id.substring(this.props.account.id.indexOf('@') + 1); return utils.normalizeUri(this.state.targetUri, defaultDomain); } async componentDidMount() { console.log('Ready now'); if (this.state.targetUri) { console.log('We must call', this.state.targetUri); } } handleTargetChange(value) { if (this.state.targetUri) { let currentUri = this.getTargetUri(); if (currentUri.trim() === value.trim()) { this.setState({targetUri: ''}); } else { this.setState({targetUri: value}); } } else { this.setState({targetUri: value}); } this.forceUpdate(); } handleTargetSelect() { if (this.props.connection === null) { this.props._notificationCenter.postSystemNotification("Server unreachable", {timeout: 2}); return; } // the user pressed enter, start a video call by default if (this.state.targetUri.endsWith(`@${config.defaultConferenceDomain}`)) { this.props.startConference(this.state.targetUri, {audio: true, video: true}); } else { this.props.startCall(this.getTargetUri(), {audio: true, video: true}); } } showConferenceModal(event) { event.preventDefault(); if (this.state.targetUri.length !== 0) { const uri = `${this.state.targetUri.split('@')[0].replace(/[\s()-]/g, '')}@${config.defaultConferenceDomain}`; this.handleConferenceCall(uri.toLowerCase()); } else { this.setState({showConferenceModal: true}); } } handleAudioCall(event) { if (this.props.connection === null) { this.props._notificationCenter.postSystemNotification("Server unreachable", {timeout: 2}); return; } event.preventDefault(); if (this.state.targetUri.endsWith(`@${config.defaultConferenceDomain}`)) { this.props.startConference(this.state.targetUri, {audio: true, video: false}); } else { this.props.startCall(this.getTargetUri(), {audio: true, video: false}); } } handleVideoCall(event) { if (this.props.connection === null) { this.props._notificationCenter.postSystemNotification("Server unreachable", {timeout: 2}); return; } event.preventDefault(); if (this.state.targetUri.endsWith(`@${config.defaultConferenceDomain}`)) { this.props.startConference(this.state.targetUri, {audio: true, video: false}); } else { this.props.startCall(this.getTargetUri(), {audio: true, video: true}); } } handleConferenceCall(targetUri, options={audio: true, video: true}) { if (targetUri) { if (!options.video) { console.log('ReadyBox: Handle audio only conference call to',targetUri); } else { console.log('ReadyBox: Handle video conference call to',targetUri); } this.props.startConference(targetUri, options); } this.setState({showConferenceModal: false}); } render() { const defaultDomain = `${config.defaultDomain}`; const buttonClass = (Platform.OS === 'ios') ? styles.iosButton : styles.androidButton; const uriGroupClass = this.props.orientation === 'landscape' ? styles.landscapeUriButtonGroup : styles.portraitUriButtonGroup; const uriClass = this.props.orientation === 'landscape' ? styles.landscapeUriInputBox : styles.portraitUriInputBox; const titleClass = this.props.orientation === 'landscape' ? styles.landscapeTitle : styles.portraitTitle; const historyClass = this.props.orientation === 'landscape' ? styles.landscapeHistory : styles.portraitHistory; // Join URIs from local and server history for input let history = this.props.history.concat( this.props.serverHistory.map(e => e.remoteParty) ); history = [...new Set(history)]; //console.log('history from server is', this.props.serverHistory); const placehoder = 'Enter a SIP address like alice@' + defaultDomain; return ( Enter address or phone number - - {this.props.serverHistory.filter(historyItem => historyItem.remoteParty.startsWith(this.state.targetUri)).map((historyItem, idx) => - () - )} - + historyItem.remoteParty.startsWith(this.state.targetUri))} + orientation={this.props.orientation} + setTargetUri={this.handleTargetChange} + startVideoCall={this.handleVideoCall} + startAudioCall={this.handleAudioCall} + /> ); } } + ReadyBox.propTypes = { account : PropTypes.object.isRequired, startCall : PropTypes.func.isRequired, startConference : PropTypes.func.isRequired, missedTargetUri : PropTypes.string, history : PropTypes.array, serverHistory : PropTypes.array, orientation : PropTypes.string }; export default ReadyBox;