diff --git a/app/components/ReadyBox.js b/app/components/ReadyBox.js
index 4fcb4a8..5020471 100644
--- a/app/components/ReadyBox.js
+++ b/app/components/ReadyBox.js
@@ -1,820 +1,822 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import autoBind from 'auto-bind';
import { FlatList, View, Platform, TouchableHighlight} from 'react-native';
import { IconButton, Title, Button, Colors } from 'react-native-paper';
import ConferenceModal from './ConferenceModal';
import ContactsListBox from './ContactsListBox';
import FooterBox from './FooterBox';
import URIInput from './URIInput';
import config from '../config';
import utils from '../utils';
import styles from '../assets/styles/blink/_ReadyBox.scss';
import {Keyboard} from 'react-native';
class ReadyBox extends Component {
constructor(props) {
super(props);
autoBind(this);
this.state = {
targetUri: '',
contacts: this.props.contacts,
selectedContact: this.props.selectedContact,
showConferenceModal: this.props.showConferenceModal,
sticky: false,
favoriteUris: this.props.favoriteUris,
blockedUris: this.props.blockedUris,
historyCategoryFilter: null,
historyPeriodFilter: null,
missedCalls: this.props.missedCalls,
isLandscape: this.props.isLandscape,
participants: null,
myInvitedParties: this.props.myInvitedParties,
messages: this.props.messages,
myDisplayName: this.props.myDisplayName,
chat: (this.props.selectedContact !== null) && (this.props.call !== null),
call: this.props.call,
inviteContacts: this.props.inviteContacts,
shareToContacts: this.props.shareToContacts,
selectedContacts: this.props.selectedContacts,
pinned: this.props.pinned,
messageZoomFactor: this.props.messageZoomFactor,
isTyping: this.props.isTyping,
navigationItems: this.props.navigationItems,
fontScale: this.props.fontScale
};
this.ended = false;
}
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.ended) {
return;
}
if (this.state.selectedContact && !nextProps.selectedContact) {
this.setState({targetUri: '',
chat: false});
}
if (!this.state.inviteContacts && nextProps.inviteContacts) {
this.handleTargetChange('');
this.setState({chat: false});
}
if (this.state.selectedContact !== nextProps.selectedContact && nextProps.selectedContact) {
this.setState({chat: !this.chatDisabledForUri(nextProps.selectedContact.uri)});
}
if (nextProps.missedCalls.length === 0 && this.state.historyCategoryFilter === 'missed') {
this.setState({'historyCategoryFilter': null});
}
if (nextProps.blockedUris.length === 0 && this.state.historyCategoryFilter === 'blocked') {
this.setState({'historyCategoryFilter': null});
}
if (nextProps.favoriteUris.length === 0 && this.state.historyCategoryFilter === 'favorite') {
this.setState({'historyCategoryFilter': null});
}
this.setState({myInvitedParties: nextProps.myInvitedParties,
messages: nextProps.messages,
myDisplayName: nextProps.myDisplayName,
call: nextProps.call,
showConferenceModal: nextProps.showConferenceModal,
isTyping: nextProps.isTyping,
navigationItems: nextProps.navigationItems,
messageZoomFactor: nextProps.messageZoomFactor,
contacts: nextProps.contacts,
inviteContacts: nextProps.inviteContacts,
shareToContacts: nextProps.shareToContacts,
selectedContacts: nextProps.selectedContacts,
selectedContact: nextProps.selectedContact,
pinned: nextProps.pinned,
favoriteUris: nextProps.favoriteUris,
blockedUris: nextProps.blockedUris,
missedCalls: nextProps.missedCalls,
fontScale: nextProps.fontScale,
isLandscape: nextProps.isLandscape});
}
getTargetUri(uri) {
return utils.normalizeUri(uri, this.props.defaultDomain);
}
async componentDidMount() {
this.ended = false;
}
componentWillUnmount() {
this.ended = true;
}
filterHistory(filter) {
if (this.ended) {
return;
}
if (!filter) {
this.setState({'historyPeriodFilter': null, historyCategoryFilter: null});
} else if (filter === 'today' || filter === 'yesterday') {
filter = this.state.historyPeriodFilter === filter ? null : filter;
this.setState({'historyPeriodFilter': filter});
} else {
this.setState({'historyCategoryFilter': filter});
}
this.handleTargetChange('');
}
chatDisabledForUri(uri) {
if (uri.indexOf('@videoconference') > -1) {
return true;
}
if (uri.indexOf('@guest') > -1) {
return true;
}
if (uri.indexOf('3333@') > -1) {
return true;
}
if (uri.indexOf('4444@') > -1) {
return true;
}
return false;
}
get showSearchBar() {
if (this.state.selectedContact && !this.props.isTablet) {
return false;
}
if (this.props.isTablet || (!this.props.isLandscape && this.state.selectedContact)) {
return true;
}
- if (this.state.call && !this.state.inviteContacts) {
+ if (this.state.call && this.state.call.state !== 'incoming' && !this.state.inviteContacts) {
return false;
}
return true;
}
get showButtonsBar() {
if (this.state.historyCategoryFilter === 'blocked') {
return false;
}
if (this.props.isTablet) {
return true;
}
if (this.state.call) {
return true;
}
if (!this.state.targetUri) {
return true;
}
if (this.state.selectedContact) {
if (this.props.isLandscape && !this.props.isTablet) {
return false;
}
return true;
}
return true;
}
handleTargetChange(new_uri, contact) {
//console.log('---handleTargetChange new_uri =', new_uri);
//console.log('handleTargetChange contact =', contact);
if ((this.state.inviteContacts || this.state.shareToContacts) && contact) {
const uri = contact.uri;
this.props.updateSelection(uri);
return;
}
if (this.state.selectedContact === contact) {
if (this.state.chat) {
this.setState({chat: false});
}
return;
} else {
this.setState({chat: false});
}
let new_value = new_uri;
if (contact) {
if (this.state.targetUri === contact.uri) {
new_value = '';
}
} else {
contact = null;
}
if (this.state.targetUri === new_uri) {
new_value = '';
}
if (new_value === '') {
contact = null;
}
if (new_value.indexOf(' ') === -1) {
new_value = new_value.trim().toLowerCase();
}
//new_value = new_value.replace(' ','');
//console.log('--- Select new contact', contact? contact.uri : null);
//console.log('--- Select new targetUri', new_value);
this.props.selectContact(contact);
this.setState({targetUri: new_value});
}
handleTargetSelect() {
if (this.props.connection === null) {
this.props._notificationCenter.postSystemNotification("Server unreachable");
return;
}
let uri = this.state.targetUri.toLowerCase();
if (uri.endsWith(`@${config.defaultConferenceDomain}`)) {
let participants;
if (this.state.myInvitedParties && this.state.myInvitedParties.hasOwnProperty(uri)) {
participants = this.state.myInvitedParties[uri];
}
this.props.startConference(uri, {audio: true, video: true, participants: this.state.participants});
} else {
this.props.startCall(this.getTargetUri(uri), {audio: true, video: true});
}
}
shareContent() {
this.props.shareContent();
}
showConferenceModal(event) {
event.preventDefault();
this.props.showConferenceModalFunc();
}
handleChat(event) {
event.preventDefault();
let targetUri;
if (!this.state.chat && !this.state.selectedContact) {
targetUri = this.getTargetUri(this.state.targetUri);
this.setState({targetUri: targetUri});
}
let uri = this.state.targetUri.trim().toLowerCase();
if (!this.state.chat && !this.selectedContact && uri) {
if (uri.indexOf('@') === -1) {
uri = uri + '@' + this.props.defaultDomain;
}
let contact = this.props.newContactFunc(uri, null, {src: 'new chat'});
console.log('Create synthetic contact', contact);
this.props.selectContact(contact);
this.setState({targetUri: uri, chat: true});
Keyboard.dismiss();
}
this.setState({chat: !this.state.chat});
}
handleAudioCall(event) {
event.preventDefault();
Keyboard.dismiss();
let uri = this.state.targetUri.trim().toLowerCase();
var uri_parts = uri.split("/");
if (uri_parts.length === 5 && uri_parts[0] === 'https:') {
// https://webrtc.sipthor.net/conference/DaffodilFlyChill0 from external web link
// https://webrtc.sipthor.net/call/alice@example.com from external web link
let event = uri_parts[3];
uri = uri_parts[4];
if (event === 'conference') {
uri = uri.split("@")[0] + '@' + config.defaultConferenceDomain;
}
}
if (uri.endsWith(`@${config.defaultConferenceDomain}`)) {
this.props.startConference(uri, {audio: true, video: false});
} else {
this.props.startCall(this.getTargetUri(uri), {audio: true, video: false});
}
}
handleVideoCall(event) {
event.preventDefault();
Keyboard.dismiss();
let uri = this.state.targetUri.toLowerCase();
var uri_parts = uri.split("/");
if (uri_parts.length === 5 && uri_parts[0] === 'https:') {
// https://webrtc.sipthor.net/conference/DaffodilFlyChill0 from external web link
// https://webrtc.sipthor.net/call/alice@example.com from external web link
let event = uri_parts[3];
uri = uri_parts[4];
if (event === 'conference') {
uri = uri.split("@")[0] + '@' + config.defaultConferenceDomain;
}
}
if (uri.endsWith(`@${config.defaultConferenceDomain}`)) {
this.props.startConference(uri, {audio: true, video: true});
} else {
this.props.startCall(this.getTargetUri(uri), {audio: true, video: true});
}
}
handleConferenceCall(targetUri, options={audio: true, video: true, participants: []}) {
Keyboard.dismiss();
this.props.startConference(targetUri, {audio: options.audio, video: options.video, participants: options.participants});
this.props.hideConferenceModalFunc();
}
get chatButtonDisabled() {
let uri = this.state.targetUri.trim();
if (this.state.selectedContact) {
return true;
}
if (this.state.shareToContacts) {
return true;
}
if (!uri || uri.indexOf(' ') > -1 || uri.indexOf('@guest.') > -1 || uri.indexOf('@videoconference') > -1) {
return true;
}
let username = uri.split('@')[0];
let isPhoneNumber = username.match(/^(\+|0)(\d+)$/);
if (isPhoneNumber) {
return true;
}
if (uri.indexOf('@') > -1) {
let email_reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,})+$/;
let validEmail = email_reg.test(uri);
if (!validEmail) {
return true;
}
}
if (this.chatDisabledForUri(uri)) {
return true;
}
return false;
}
get callButtonDisabled() {
let uri = this.state.targetUri.trim();
if (!uri || uri.indexOf(' ') > -1 || uri.indexOf('@guest.') > -1 || uri.indexOf('@videoconference') > -1) {
return true;
}
if (this.state.shareToContacts) {
return true;
}
if (uri.indexOf('@') > -1) {
let email_reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,})+$/;
let validEmail = email_reg.test(uri);
if (!validEmail) {
return true;
}
}
return false;
}
get videoButtonDisabled() {
let uri = this.state.targetUri.trim();
if (!uri || uri.indexOf(' ') > -1 || uri.indexOf('@guest.') > -1 || uri.indexOf('@videoconference') > -1) {
return true;
}
if (uri.indexOf('4444@') > -1) {
return true;
}
if (this.state.shareToContacts) {
return true;
}
let username = uri.split('@')[0];
let isPhoneNumber = username.match(/^(\+|0)(\d+)$/);
if (isPhoneNumber) {
return true;
}
return this.callButtonDisabled;
}
get conferenceButtonDisabled() {
let uri = this.state.targetUri.trim();
if (uri.indexOf(' ') > -1) {
return true;
}
if (this.state.shareToContacts) {
return true;
}
let username = uri.split('@')[0];
let isPhoneNumber = username.match(/^(\+|0)(\d+)$/);
if (isPhoneNumber) {
return true;
}
if (uri.indexOf('@') > -1 && uri.indexOf(config.defaultConferenceDomain) === -1) {
return true;
}
var uri_parts = uri.split("/");
if (uri_parts.length === 5 && uri_parts[0] === 'https:') {
// https://webrtc.sipthor.net/conference/DaffodilFlyChill0 from external web link
// https://webrtc.sipthor.net/call/alice@example.com from external web link
let event = uri_parts[3];
if (event === 'call') {
return true;
}
}
return false;
}
renderNavigationItem(object) {
if (!object.item.enabled) {
return (null);
}
let title = object.item.title;
let key = object.item.key;
let buttonStyle = object.item.selected ? styles.navigationButtonSelected : styles.navigationButton;
return ();
}
render() {
let uriClass = styles.portraitUriInputBox;
let uriGroupClass = styles.portraitUriButtonGroup;
let titleClass = styles.portraitTitle;
let uri = this.state.targetUri.toLowerCase();
var uri_parts = uri.split("/");
if (uri_parts.length === 5 && uri_parts[0] === 'https:') {
// https://webrtc.sipthor.net/conference/DaffodilFlyChill0 from external web link
// https://webrtc.sipthor.net/call/alice@example.com from external web link
let event = uri_parts[3];
uri = uri_parts[4];
if (event === 'conference') {
uri = uri.split("@")[0] + '@' + config.defaultConferenceDomain;
}
}
/*
console.log('Render -----');
if (this.state.selectedContact) {
console.log('Render selectedContact', this.state.selectedContact.name);
}
if (this.state.callContact) {
console.log('Render callContact', this.state.callContact.uri);
}
if (this.state.targetUri) {
console.log('Render targetUri', this.state.targetUri);
}
console.log('Render chat', this.state.chat);
*/
let buttonClass = (Platform.OS === 'ios') ? styles.iosButton : styles.androidButton;
let disabledButtonClass = styles.disabledButton;
if (this.props.isTablet) {
titleClass = this.props.orientation === 'landscape' ? styles.landscapeTabletTitle : styles.portraitTabletTitle;
} else {
titleClass = this.props.orientation === 'landscape' ? styles.landscapeTitle : styles.portraitTitle;
}
if (this.props.isTablet) {
uriGroupClass = this.props.orientation === 'landscape' ? styles.landscapeTabletUriButtonGroup : styles.portraitTabletUriButtonGroup;
} else {
uriGroupClass = this.props.orientation === 'landscape' ? styles.landscapeUriButtonGroup : styles.portraitUriButtonGroup;
}
if (this.props.isTablet) {
uriClass = this.props.orientation === 'landscape' ? styles.landscapeTabletUriInputBox : styles.portraitTabletUriInputBox;
} else {
uriClass = this.props.orientation === 'landscape' ? styles.landscapeUriInputBox : styles.portraitUriInputBox;
}
const historyContainer = this.props.orientation === 'landscape' ? styles.historyLandscapeContainer : styles.historyPortraitContainer;
const buttonGroupClass = this.props.orientation === 'landscape' ? styles.landscapeButtonGroup : styles.buttonGroup;
const borderClass = this.state.chat ? null : styles.historyBorder;
let backButtonTitle = 'Back to call';
- if (this.state.call) {
+ const showBackToCallButton = this.state.call && this.state.call.state !== 'incoming' ? true : false ;
+
+ if (showBackToCallButton) {
if (this.state.call.hasOwnProperty('_participants')) {
backButtonTitle = this.state.selectedContacts.length > 0 ? 'Invite people' : 'Back to conference';
} else {
backButtonTitle = this.state.selectedContacts.length > 0 ? 'Invite people' : 'Back to call';
}
}
let conferenceEnabled = Object.keys(this.state.myInvitedParties).length > 0 || this.state.navigationItems['conference'];
if (this.state.inviteContacts) {
conferenceEnabled = false;
}
let navigationMenuData = [
{key: null, title: 'All', enabled: true, selected: false},
{key: 'history', title: 'Calls', enabled: true, selected: this.state.historyCategoryFilter === 'history'},
{key: 'chat', title: 'Chat', enabled: true, selected: this.state.historyCategoryFilter === 'chat'},
{key: 'today', title: 'Today', enabled: this.state.navigationItems['today'], selected: this.state.historyPeriodFilter === 'today'},
{key: 'yesterday', title: 'Yesterday', enabled: this.state.navigationItems['yesterday'], selected: this.state.historyPeriodFilter === 'yesterday'},
{key: 'missed', title: 'Missed', enabled: this.state.missedCalls.length > 0, selected: this.state.historyCategoryFilter === 'missed'},
{key: 'favorite', title: 'Favorites', enabled: this.state.favoriteUris.length > 0, selected: this.state.historyCategoryFilter === 'favorite'},
{key: 'blocked', title: 'Blocked', enabled: this.state.blockedUris.length > 0, selected: this.state.historyCategoryFilter === 'blocked'},
{key: 'conference', title: 'Conference', enabled: conferenceEnabled, selected: this.state.historyCategoryFilter === 'conference'},
{key: 'test', title: 'Test', enabled: !this.state.shareToContacts && !this.state.inviteContacts, selected: this.state.historyCategoryFilter === 'test'},
];
return (
{this.showSearchBar && !this.props.isLandscape ?
: null}
{this.showButtonsBar ?
{this.showSearchBar && this.props.isLandscape ?
: null}
- {this.state.call ?
+ {showBackToCallButton ?
:
}
: null}
{ !this.state.selectedContact ?
item.key}
renderItem={this.renderNavigationItem}
/>
: null}
{this.props.isTablet && 0?
: null}
);
}
}
ReadyBox.propTypes = {
account : PropTypes.object,
password : PropTypes.string.isRequired,
config : PropTypes.object.isRequired,
startCall : PropTypes.func.isRequired,
startConference : PropTypes.func.isRequired,
contacts : PropTypes.array,
orientation : PropTypes.string,
isTablet : PropTypes.bool,
isLandscape : PropTypes.bool,
refreshHistory : PropTypes.bool,
refreshFavorites: PropTypes.bool,
saveHistory : PropTypes.func,
localHistory : PropTypes.array,
myDisplayName : PropTypes.string,
myPhoneNumber : PropTypes.string,
toggleFavorite : PropTypes.func,
myInvitedParties: PropTypes.object,
toggleBlocked : PropTypes.func,
favoriteUris : PropTypes.array,
blockedUris : PropTypes.array,
defaultDomain : PropTypes.string,
saveContact : PropTypes.func,
selectContact : PropTypes.func,
lookupContacts : PropTypes.func,
call : PropTypes.object,
goBackFunc : PropTypes.func,
messages : PropTypes.object,
sendMessage : PropTypes.func,
reSendMessage : PropTypes.func,
confirmRead : PropTypes.func,
deleteMessage : PropTypes.func,
expireMessage : PropTypes.func,
getMessages : PropTypes.func,
deleteMessages : PropTypes.func,
pinMessage : PropTypes.func,
unpinMessage : PropTypes.func,
sendPublicKey : PropTypes.func,
inviteContacts : PropTypes.bool,
shareToContacts : PropTypes.bool,
selectedContacts: PropTypes.array,
updateSelection : PropTypes.func,
loadEarlierMessages: PropTypes.func,
newContactFunc : PropTypes.func,
missedCalls : PropTypes.array,
messageZoomFactor: PropTypes.string,
isTyping: PropTypes.bool,
navigationItems: PropTypes.object,
showConferenceModal: PropTypes.bool,
showConferenceModalFunc: PropTypes.func,
hideConferenceModalFunc: PropTypes.func,
shareContent: PropTypes.func,
fetchSharedItems: PropTypes.func,
fontScale: PropTypes.number
};
export default ReadyBox;