Skip to content

Commit

Permalink
New compose box design for stream messages
Browse files Browse the repository at this point in the history
  • Loading branch information
kunall17 authored and borisyankov committed Jun 9, 2017
1 parent e8e6c02 commit 3603254
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 27 deletions.
50 changes: 43 additions & 7 deletions src/compose/ComposeBox.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
/* @flow */
import React from 'react';
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';
import { getLastTopicInActiveNarrow } from '../chat/chatSelectors';
import { Auth, Narrow } from '../types';

type Props = {
onSend: (content: string) => void,
auth: Auth,
narrow: Narrow,
lastTopic: string,
users: Object[]
};

const composeComponents = [
Expand All @@ -19,33 +27,61 @@ const composeComponents = [
View,
];

export default class ComposeBox extends React.Component {

class ComposeBox extends React.Component {
props: Props;

state: {
optionSelected: number
optionSelected: number,
operator: string | null,
};

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

setTopic = (operator: string | null) => this.setState({ operator });

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

render() {
const { optionSelected } = this.state;
const { optionSelected, operator } = this.state;
const { auth, narrow, users, lastTopic } = 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}
setTopic={this.setTopic}
operator={operator}
users={users}
narrow={narrow}
lastTopic={lastTopic}
/>
</View>
<View style={styles.divider} />
<ActiveComposeComponent
auth={auth}
narrow={narrow}
operator={operator}
/>
</View>
);
}
}

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

export default connect(mapStateToProps)(ComposeBox);
35 changes: 15 additions & 20 deletions src/compose/ComposeText.js
Original file line number Diff line number Diff line change
@@ -1,15 +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 { getLastTopicInActiveNarrow } from '../chat/chatSelectors';
import sendMessage from '../api/sendMessage';
import SendButton from './SendButton';
import getAutocompletedText from '../autocomplete/getAutocompletedText';
Expand All @@ -23,7 +20,7 @@ const MAX_HEIGHT = 200;
const componentStyles = StyleSheet.create({
wrapper: {
flexDirection: 'row',
alignItems: 'center',
alignItems: 'center'
},
messageBox: {
flex: 1,
Expand All @@ -33,9 +30,10 @@ const componentStyles = StyleSheet.create({
type Props = {
auth: Object,
narrow: Object,
operator: string | null
};

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

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

handleSend = () => {
const { auth, narrow } = this.props;
const { auth, narrow, 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', narrow[0].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 All @@ -80,7 +84,7 @@ class ComposeText extends React.Component {
});
}

handleOnChange = (event) =>
handleOnChange = (event: Object) =>
this.setState({ contentHeight: event.nativeEvent.contentSize.height });

handleChangeText = (text: string) => {
Expand All @@ -100,7 +104,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 @@ -131,11 +134,3 @@ class ComposeText extends React.Component {
);
}
}

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

export default connect(mapStateToProps)(ComposeText);
70 changes: 70 additions & 0 deletions src/compose/ModeView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';

import ComposeOptions from './ComposeOptions';
import StreamBox from './ModeViews/StreamBox';
import ComposeIcon from './ComposeIcon';
import { isTopicNarrow, isStreamNarrow } 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 = {
showOptions: true,
};
}

handleModeChanged = () => {
const { setTopic, narrow, lastTopic } = this.props;
if (this.state.showOptions && (isTopicNarrow(narrow) || isStreamNarrow(narrow))) {
if (narrow.length === 1) {
setTopic(lastTopic);
} else {
setTopic(narrow[1].operand);
}
} else {
setTopic(null);
}
this.setState({
showOptions: !this.state.showOptions
});
};

render() {
const { showOptions } = this.state;
const { setTopic, operator, optionSelected,
handleOptionSelected, narrow, lastTopic } = this.props;

return (
<View style={inlineStyles.wrapper}>
{(isTopicNarrow(narrow) || isStreamNarrow(narrow)) &&
<View style={inlineStyles.wrapper}>
<ComposeIcon name="ios-chatbubbles" onChange={this.handleModeChanged} />
<View style={inlineStyles.divider} />
</View>
}
{showOptions ?
<ComposeOptions selected={optionSelected} onChange={handleOptionSelected} />
:
<StreamBox
operator={operator}
setTopic={setTopic}
narrow={narrow}
lastTopic={lastTopic}
/>
}
</View>
);
}
}
46 changes: 46 additions & 0 deletions src/compose/ModeViews/StreamBox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { Component } from 'react';
import { View, TextInput, StyleSheet } from 'react-native';

import { isTopicNarrow } from '../../utils/narrow';

const styles = StyleSheet.create({
streamInputWrapper: {
flexDirection: 'row', alignItems: 'center', flex: 1
},
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 { setTopic } = this.props;
if (isTopicNarrow(nextProps.narrow)) {
setTopic(nextProps.narrow[1].operand);
} else {
setTopic(nextProps.lastTopic);
}
}
}
}

render() {
const { operator, setTopic } = this.props;
return (
<View style={styles.streamInputWrapper}>
<TextInput
ref={component => { this.operandInput = component; }}
style={styles.topicInput}
placeholder={'Topic'}
onChange={(event) => setTopic(
event.nativeEvent.text
)}
value={operator}
/>
</View>
);
}
}
7 changes: 7 additions & 0 deletions src/styles/theme.js
Original file line number Diff line number Diff line change
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 3603254

Please sign in to comment.