Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F7232225
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
24 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/app/components/ReadyBox.js b/app/components/ReadyBox.js
index c2e9f5d..00f18c5 100644
--- a/app/components/ReadyBox.js
+++ b/app/components/ReadyBox.js
@@ -1,599 +1,599 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import autoBind from 'auto-bind';
import { FlatList, View, Platform} from 'react-native';
import { IconButton, Title, Button } 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';
class ReadyBox extends Component {
constructor(props) {
super(props);
autoBind(this);
this.state = {
targetUri: '',
contacts: this.props.contacts,
selectedContact: this.props.selectedContact,
showConferenceModal: false,
sticky: false,
favoriteUris: this.props.favoriteUris,
blockedUris: this.props.blockedUris,
historyFilter: 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,
selectedContacts: this.props.selectedContacts,
pinned: this.props.pinned
};
this.ended = false;
}
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.ended) {
return;
}
if (this.state.selectedContact && nextProps.selectedContact === null) {
this.setState({targetUri: '',
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.historyFilter === 'missed') {
this.setState({'historyFilter': null});
}
if (nextProps.blockedUris.length === 0 && this.state.historyFilter === 'blocked') {
this.setState({'historyFilter': null});
}
if (nextProps.favoriteUris.length === 0 && this.state.historyFilter === 'favorite') {
this.setState({'historyFilter': null});
}
this.setState({myInvitedParties: nextProps.myInvitedParties,
messages: nextProps.messages,
myDisplayName: nextProps.myDisplayName,
call: nextProps.call,
contacts: nextProps.contacts,
inviteContacts: nextProps.inviteContacts,
selectedContacts: nextProps.selectedContacts,
selectedContact: nextProps.selectedContact,
pinned: nextProps.pinned,
favoriteUris: nextProps.favoriteUris,
blockedUris: nextProps.blockedUris,
missedCalls: nextProps.missedCalls,
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;
}
this.setState({'historyFilter': 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;
}
return false;
}
get showSearchBar() {
if (this.props.isTablet || this.props.isLandscape) {
return true;
}
if (this.state.call) {
return false;
}
return (this.state.selectedContact === null);
}
get showButtonsBar() {
if (this.props.isTablet) {
return true;
}
if (this.state.call) {
return true;
}
if (this.state.chat && this.state.selectedContact) {
return false;
}
return true;
}
handleTargetChange(value, contact) {
//console.log('handleTargetChange', value, contact);
if (this.state.inviteContacts && 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 = value;
if (contact) {
if (this.state.targetUri === contact.uri) {
new_value = '';
}
} else {
contact = null;
}
if (this.state.targetUri === value) {
new_value = '';
}
if (new_value === '') {
contact = null;
}
//new_value = new_value.replace(' ','');
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});
}
}
showConferenceModal(event) {
event.preventDefault();
this.setState({showConferenceModal: true});
return;
}
handleChat(event) {
event.preventDefault();
let targetUri;
if (!this.state.chat && !this.state.selectedContact && this.state.targetUri.toLowerCase().indexOf('@') === -1) {
targetUri = this.getTargetUri(this.state.targetUri);
this.setState({targetUri: targetUri});
}
let chat = !this.state.chat;
let uri = this.state.targetUri.toLowerCase();
if (chat && !this.selectedContact && targetUri) {
let contact = this.props.newContactFunc(targetUri, null, {src: 'new chat'});
this.handleTargetChange(targetUri, contact);
}
this.setState({chat: !this.state.chat});
}
handleAudioCall(event) {
event.preventDefault();
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: false});
} else {
this.props.startCall(this.getTargetUri(uri), {audio: true, video: false});
}
}
handleVideoCall(event) {
event.preventDefault();
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: []}) {
this.props.startConference(targetUri, {audio: options.audio, video: options.video, participants: options.participants});
this.setState({showConferenceModal: false});
}
conferenceButtonActive() {
if (this.state.targetUri.indexOf('@guest.') > -1) {
return false;
}
if (this.state.targetUri.indexOf('@') > -1 &&
this.state.targetUri.indexOf(config.defaultConferenceDomain) === -1) {
return false;
}
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];
if (event === 'call') {
return false;
}
}
if (this.state.targetUri.match(/^(\+)(\d+)$/)) {
return false;
}
return true;
}
get chatButtonDisabled() {
let uri = this.state.targetUri.trim();
if (this.chatDisabledForUri(uri)) {
return true;
}
return this.callButtonDisabled;
}
get callButtonDisabled() {
let uri = this.state.targetUri.trim();
if (uri.indexOf(' ') > -1) {
return true;
}
if (uri.length === 0 ||
uri.indexOf('@videoconference') > -1 ||
uri.indexOf('@guest') > -1
) {
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 (<Button style={buttonStyle} onPress={() => {this.filterHistory(key)}}>{title}</Button>);
}
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 missed calls', this.state.missedCalls);
const buttonClass = (Platform.OS === 'ios') ? styles.iosButton : styles.androidButton;
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 callType = 'Back to call';
if (this.state.call && this.state.call.hasOwnProperty('_participants')) {
callType = this.state.selectedContacts.length > 0 ? 'Invite people' : 'Back to conference';
}
let navigationMenuData = [
{key: null, title: 'All', enabled: true, selected: false},
{key: 'history', title: 'Calls', enabled: true, selected: this.state.historyFilter === 'history'},
{key: 'chat', title: 'Chat', enabled: true, selected: this.state.historyFilter === 'chat'},
{key: 'missed', title: 'Missed', enabled: this.state.missedCalls.length > 0, selected: this.state.historyFilter === 'missed'},
{key: 'favorite', title: 'Favorites', enabled: this.state.favoriteUris.length > 0, selected: this.state.historyFilter === 'favorite'},
{key: 'blocked', title: 'Blocked', enabled: this.state.blockedUris.length > 0, selected: this.state.historyFilter === 'blocked'},
- {key: 'conference', title: 'Conference', enabled: true, selected: this.state.historyFilter === 'conference'},
+ {key: 'conference', title: 'Conference', enabled: Object.keys(this.state.myInvitedParties).length >0 , selected: this.state.historyFilter === 'conference'},
{key: 'test', title: 'Test', enabled: true, selected: this.state.historyFilter === 'test'},
];
return (
<Fragment>
<View style={styles.container}>
<View >
{this.showButtonsBar ?
<View style={uriGroupClass}>
{this.showSearchBar ?
<View style={uriClass}>
<URIInput
defaultValue={this.state.targetUri}
onChange={this.handleTargetChange}
onSelect={this.handleTargetSelect}
autoFocus={false}
/>
</View>
: null}
{( this.state.call && this.state.call.state == 'established') ?
<View style={buttonGroupClass}>
<Button
mode="contained"
style={styles.backButton}
onPress={this.props.goBackFunc}
accessibilityLabel={callType}
>{callType}
</Button>
</View>
:
<View style={buttonGroupClass}>
<IconButton
style={buttonClass}
size={32}
disabled={this.chatButtonDisabled}
onPress={this.handleChat}
icon="chat"
/>
<IconButton
style={buttonClass}
size={32}
disabled={this.callButtonDisabled}
onPress={this.handleAudioCall}
icon="phone"
/>
<IconButton
style={buttonClass}
size={32}
disabled={this.callButtonDisabled}
onPress={this.handleVideoCall}
icon="video"
/>
<IconButton
style={styles.conferenceButton}
disabled={!this.conferenceButtonActive()}
size={32}
onPress={this.showConferenceModal}
icon="account-group"
/>
</View>
}
</View>
: null}
</View>
<View style={[historyContainer, borderClass]}>
<ContactsListBox
contacts={this.state.contacts}
targetUri={this.state.targetUri}
orientation={this.props.orientation}
setTargetUri={this.handleTargetChange}
selectedContact={this.state.selectedContact}
isTablet={this.props.isTablet}
chat={this.state.chat}
isLandscape={this.state.isLandscape}
account={this.props.account}
password={this.props.password}
config={this.props.config}
refreshHistory={this.props.refreshHistory}
refreshFavorites={this.props.refreshFavorites}
localHistory={this.props.localHistory}
saveHistory={this.props.saveHistory}
myDisplayName={this.state.myDisplayName}
myPhoneNumber={this.props.myPhoneNumber}
saveInvitedParties={this.props.saveInvitedParties}
myInvitedParties = {this.state.myInvitedParties}
favoriteUris={this.props.favoriteUris}
blockedUris={this.props.blockedUris}
filter={this.state.historyFilter}
defaultDomain={this.props.defaultDomain}
saveContact={this.props.saveContact}
myContacts = {this.props.myContacts}
messages = {this.state.messages}
sendMessage = {this.props.sendMessage}
reSendMessage = {this.props.reSendMessage}
deleteMessages = {this.props.deleteMessages}
expireMessage = {this.props.expireMessage}
deleteMessage = {this.props.deleteMessage}
getMessages = {this.props.getMessages}
pinMessage = {this.props.pinMessage}
unpinMessage = {this.props.unpinMessage}
confirmRead = {this.props.confirmRead}
sendPublicKey = {this.props.sendPublicKey}
inviteContacts = {this.state.inviteContacts}
selectedContacts = {this.state.selectedContacts}
toggleFavorite={this.props.toggleFavorite}
toggleBlocked={this.props.toggleBlocked}
togglePinned = {this.props.togglePinned}
pinned = {this.state.pinned}
loadEarlierMessages = {this.props.loadEarlierMessages}
newContactFunc = {this.props.newContactFunc}
/>
</View>
{ !this.state.selectedContact ?
<View style={styles.navigationContainer}>
<FlatList contentContainerStyle={styles.navigationButtonGroup}
horizontal={true}
data={navigationMenuData}
extraData={this.state}
keyExtractor={(item, index) => item.key}
renderItem={this.renderNavigationItem}
/>
</View>
: null}
{this.props.isTablet && 0?
<View style={styles.footer}>
<FooterBox />
</View>
: null}
</View>
<ConferenceModal
show={this.state.showConferenceModal}
targetUri={uri}
myInvitedParties={this.state.myInvitedParties}
selectedContact={this.state.selectedContact}
handleConferenceCall={this.handleConferenceCall}
defaultDomain={this.props.defaultDomain}
accountId={this.props.account ? this.props.account.id: null}
lookupContacts={this.props.lookupContacts}
/>
</Fragment>
);
}
}
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,
selectedContacts: PropTypes.array,
updateSelection : PropTypes.func,
loadEarlierMessages: PropTypes.func,
newContactFunc : PropTypes.func,
missedCalls : PropTypes.array
};
export default ReadyBox;
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Dec 28, 8:26 PM (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3454355
Default Alt Text
(24 KB)
Attached To
Mode
rSYLKWRTCM Sylk WebRTC mobile
Attached
Detach File
Event Timeline
Log In to Comment