Skip to content

Commit

Permalink
New compose box design
Browse files Browse the repository at this point in the history
  • Loading branch information
kunall17 committed May 25, 2017
1 parent ef89570 commit e36cde9
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 25 deletions.
48 changes: 39 additions & 9 deletions src/compose/ComposeBox.js
@@ -1,11 +1,15 @@
/* @flow */
import React from 'react';
// import ComposeOptions from './ComposeOptions';
import { View } from 'react-native';
import { connect } from 'react-redux';

import { getAuth } from '../account/accountSelectors';
import styles from '../styles';
// import ComposeOptions from './ComposeOptions';
import ComposeText from './ComposeText';
import CameraRollView from './CameraRollView';
import ModeView from './ModeView';


type Props = {
onSend: (content: string) => void,
Expand All @@ -19,8 +23,7 @@ const composeComponents = [
View,
];

export default class ComposeBox extends React.Component {

class ComposeBox extends React.Component {
props: Props;

state: {
Expand All @@ -29,23 +32,50 @@ export default class ComposeBox extends React.Component {

constructor(props: Props) {
super(props);
this.state = {
optionSelected: 0,
};
this.state = { optionSelected: 0, operator: '', operand: '' };
}

setOperator = (operator: string) => this.setState({ operator });
setOperand = (operand: string) => this.setState({ operand });

handleOptionSelected = (optionSelected: number) =>
this.setState({ optionSelected });

render() {
const { optionSelected } = this.state;
const { optionSelected, operator, operand } = this.state;
const { auth, narrow, users } = this.props;
const ActiveComposeComponent = composeComponents[optionSelected];

return (
<View style={styles.composeBox}>
<ActiveComposeComponent />
{/* <ComposeOptions selected={optionSelected} onChange={this.handleOptionSelected} /> */}
<View style={styles.wrapper}>
<ModeView
optionSelected={optionSelected}
handleOptionSelected={this.handleOptionSelected}
setOperator={this.setOperator}
setOperand={this.setOperand}
operator={operator}
operand={operand}
users={users}
narrow={narrow}
/>
</View>
<View style={styles.divider} />
<ActiveComposeComponent
auth={auth}
narrow={narrow}
operator={operator}
operand={operand}
/>
</View>
);
}
}

const mapStateToProps = (state) => ({
auth: getAuth(state),
narrow: state.chat.narrow,
users: state.users
});

export default connect(mapStateToProps)(ComposeBox);
28 changes: 12 additions & 16 deletions src/compose/ComposeText.js
@@ -1,14 +1,12 @@
/* @flow */
import React from 'react';
import { StyleSheet, View, ScrollView, TextInput } from 'react-native';
import { connect } from 'react-redux';

import styles from '../styles';
import { MatchResult } from '../types';
import { Input } from '../common';
import { isStreamNarrow, isTopicNarrow, isPrivateOrGroupNarrow } from '../utils/narrow';
import { registerUserInputActivity } from '../utils/activity';
import { getAuth } from '../account/accountSelectors';
import sendMessage from '../api/sendMessage';
import SendButton from './SendButton';
import getAutocompletedText from '../autocomplete/getAutocompletedText';
Expand All @@ -34,7 +32,7 @@ type Props = {
narrow: Object,
};

class ComposeText extends React.Component {
export default class ComposeText extends React.Component {

props: Props;
textInput: TextInput;
Expand All @@ -57,17 +55,23 @@ class ComposeText extends React.Component {
}

handleSend = () => {
const { auth, narrow } = this.props;
const { auth, narrow, operand, operator } = this.props;
const { text } = this.state;

if (isPrivateOrGroupNarrow(narrow)) {
sendMessage(auth, 'private', narrow[0].operand, '', text);
} else if (isStreamNarrow(narrow)) {
sendMessage(auth, 'stream', narrow[0].operand, '(no topic)', text);
} else if (isTopicNarrow(narrow)) {
sendMessage(auth, 'stream', narrow[0].operand, narrow[1].operand, text);
} else if (isTopicNarrow(narrow) || isStreamNarrow(narrow)) {
if (operator !== null) {
sendMessage(auth, 'stream', operand,
(operator === '') ? '(no topic)' : operator, text);
} else if (isTopicNarrow(narrow)) {
sendMessage(auth, 'stream', narrow[0].operand, narrow[1].operand, text);
} else if (isStreamNarrow(narrow)) {
sendMessage(auth, 'stream', narrow[0].operand, '(no topic)', text);
}
}


this.clearInput();
}

Expand Down Expand Up @@ -99,7 +103,6 @@ class ComposeText extends React.Component {
const height = Math.min(Math.max(MIN_HEIGHT, contentHeight), MAX_HEIGHT);
const lastword: MatchResult = text.match(/\b(\w+)$/);
const lastWordPrefix = lastword && lastword.index && text[lastword.index - 1];

return (
<View>
{lastWordPrefix === ':' && lastword &&
Expand Down Expand Up @@ -130,10 +133,3 @@ class ComposeText extends React.Component {
);
}
}

const mapStateToProps = (state) => ({
auth: getAuth(state),
narrow: state.chat.narrow,
});

export default connect(mapStateToProps)(ComposeText);
14 changes: 14 additions & 0 deletions src/compose/ModeSelector.js
@@ -0,0 +1,14 @@
import React from 'react';
import ComposeIcon from './ComposeIcon';

export default (props) => {
switch (props.modeSelected) {
case 0:
return (<ComposeIcon name="ios-chatbubbles" onChange={props.onModeChange} />);
case 1:
return (<ComposeIcon name="ios-add-circle-outline" onChange={props.onModeChange} />);
default:
return (<ComposeIcon name="bullhorn" onChange={props.onModeChange} />);

}
};
75 changes: 75 additions & 0 deletions src/compose/ModeView.js
@@ -0,0 +1,75 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';

import ComposeOptions from './ComposeOptions';
import ModeSelector from './ModeSelector';
import StreamBox from './ModeViews/StreamBox';
import { isTopicNarrow, isStreamNarrow, isPrivateOrGroupNarrow } from '../utils/narrow';

const inlineStyles = StyleSheet.create({
wrapper: {
flexDirection: 'row',
},
divider: {
width: 2,
backgroundColor: '#ecf0f1',
margin: 4
},
});

export default class ModeView extends React.Component {
constructor() {
super();
this.state = {
modeSelected: 0,
};
}

handleModeChanged = () => {
const { setOperator, setOperand, narrow } = this.props;
if (this.state.modeSelected === 0 && (isTopicNarrow(narrow) || isStreamNarrow(narrow))) {
if (narrow.length === 1) {
setOperand(narrow[0].operand);
setOperator('');
} else {
setOperand(narrow[0].operand);
setOperator(narrow[1].operand);
}
} else {
setOperator(null);
setOperand(null);
}
this.setState({
modeSelected: (this.state.modeSelected === 1) ? 0 : this.state.modeSelected + 1
});
};

render() {
const { modeSelected } = this.state;
const { setOperator, setOperand, operator, operand,
optionSelected, handleOptionSelected, narrow } = this.props;

return (
<View style={inlineStyles.wrapper}>
{(isTopicNarrow(narrow) || isStreamNarrow(narrow)) &&
<View style={inlineStyles.wrapper}>
<ModeSelector modeSelected={modeSelected} onModeChange={this.handleModeChanged} />
<View style={inlineStyles.divider} />
</View>
}
{modeSelected === 0 &&
<ComposeOptions selected={optionSelected} onChange={handleOptionSelected} />
}
{modeSelected === 1 &&
<StreamBox
operator={operator}
operand={operand}
setOperator={setOperator}
setOperand={setOperand}
narrow={narrow}
/>
}
</View>
);
}
}
58 changes: 58 additions & 0 deletions src/compose/ModeViews/StreamBox.js
@@ -0,0 +1,58 @@
import React, { Component } from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';


const styles = StyleSheet.create({
streamInputWrapper: {
flexDirection: 'row', alignItems: 'center', flex: 1
},
streamInput: {
flex: 0.2,
margin: 2
},
topicInput: {
flex: 0.8,
margin: 2
}
});

export default class StreamBox extends Component {
componentWillReceiveProps(nextProps) {
if (this.props.narrow !== nextProps.narrow) {
if (nextProps.narrow[0].operator !== 'pm-with') {
const { setOperand, setOperator } = this.props;
setOperand(nextProps.narrow[0].operand);
setOperator(nextProps.narrow[0].operator);
}
}
}

render() {
const { operator, setOperator, operand, setOperand } = this.props;
return (
<View style={styles.streamInputWrapper}>
<TextInput
style={styles.streamInput}
placeholder={'Stream'}
onChange={(event) => {
setOperand(event.nativeEvent.text);
}}
onEndEditing={() => {
this.operandInput.focus();
}}
value={operand}
/>
<Text>{'>'}</Text>
<TextInput
ref={component => { this.operandInput = component; }}
style={styles.topicInput}
placeholder={'Topic'}
onChange={(event) => setOperator(
event.nativeEvent.text
)}
value={operator}
/>
</View>
);
}
}
7 changes: 7 additions & 0 deletions src/styles/theme.js
Expand Up @@ -137,4 +137,11 @@ export default ({ color, backgroundColor, borderColor }) => ({
fontSize: 16,
lineHeight: 16,
},
composeInput: {
padding: 5,
fontSize: 14,
borderWidth: 0.5,
height: CONTROL_SIZE * 3 / 4,
borderColor: BORDER_COLOR,
},
});

0 comments on commit e36cde9

Please sign in to comment.