Improve performance on post textbox (#1138)
This commit is contained in:
parent
20168d90ca
commit
aa5f0c9557
10 changed files with 219 additions and 245 deletions
|
|
@ -27,16 +27,16 @@ export default class AtMention extends PureComponent {
|
|||
matchTerm: PropTypes.string,
|
||||
onChangeText: PropTypes.func.isRequired,
|
||||
outChannel: PropTypes.array,
|
||||
postDraft: PropTypes.string,
|
||||
requestStatus: PropTypes.string.isRequired,
|
||||
teamMembers: PropTypes.array,
|
||||
theme: PropTypes.object.isRequired
|
||||
theme: PropTypes.object.isRequired,
|
||||
value: PropTypes.string
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
defaultChannel: {},
|
||||
postDraft: '',
|
||||
isSearch: false
|
||||
isSearch: false,
|
||||
value: ''
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -144,8 +144,8 @@ export default class AtMention extends PureComponent {
|
|||
};
|
||||
|
||||
completeMention = (mention) => {
|
||||
const {cursorPosition, isSearch, onChangeText, postDraft} = this.props;
|
||||
const mentionPart = postDraft.substring(0, cursorPosition);
|
||||
const {cursorPosition, isSearch, onChangeText, value} = this.props;
|
||||
const mentionPart = value.substring(0, cursorPosition);
|
||||
|
||||
let completedDraft;
|
||||
if (isSearch) {
|
||||
|
|
@ -154,8 +154,8 @@ export default class AtMention extends PureComponent {
|
|||
completedDraft = mentionPart.replace(AT_MENTION_REGEX, `@${mention} `);
|
||||
}
|
||||
|
||||
if (postDraft.length > cursorPosition) {
|
||||
completedDraft += postDraft.substring(cursorPosition);
|
||||
if (value.length > cursorPosition) {
|
||||
completedDraft += value.substring(cursorPosition);
|
||||
}
|
||||
|
||||
onChangeText(completedDraft, true);
|
||||
|
|
|
|||
|
|
@ -19,25 +19,10 @@ import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
|||
import AtMention from './at_mention';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
const {cursorPosition, isSearch, rootId} = ownProps;
|
||||
const {cursorPosition, isSearch} = ownProps;
|
||||
const currentChannelId = getCurrentChannelId(state);
|
||||
|
||||
let postDraft = '';
|
||||
if (isSearch) {
|
||||
postDraft = state.views.search;
|
||||
} else if (ownProps.rootId) {
|
||||
const threadDraft = state.views.thread.drafts[rootId];
|
||||
if (threadDraft) {
|
||||
postDraft = threadDraft.draft;
|
||||
}
|
||||
} else if (currentChannelId) {
|
||||
const channelDraft = state.views.channel.drafts[currentChannelId];
|
||||
if (channelDraft) {
|
||||
postDraft = channelDraft.draft;
|
||||
}
|
||||
}
|
||||
|
||||
const value = postDraft.substring(0, cursorPosition);
|
||||
const value = ownProps.value.substring(0, cursorPosition);
|
||||
const matchTerm = getMatchTermForAtMention(value, isSearch);
|
||||
|
||||
let teamMembers;
|
||||
|
|
@ -54,14 +39,12 @@ function mapStateToProps(state, ownProps) {
|
|||
currentChannelId,
|
||||
currentTeamId: getCurrentTeamId(state),
|
||||
defaultChannel: getDefaultChannel(state),
|
||||
postDraft,
|
||||
matchTerm,
|
||||
teamMembers,
|
||||
inChannel,
|
||||
outChannel,
|
||||
requestStatus: state.requests.users.autocompleteUsers.status,
|
||||
theme: getTheme(state),
|
||||
...ownProps
|
||||
theme: getTheme(state)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,16 +24,16 @@ export default class ChannelMention extends PureComponent {
|
|||
myChannels: PropTypes.array,
|
||||
otherChannels: PropTypes.array,
|
||||
onChangeText: PropTypes.func.isRequired,
|
||||
postDraft: PropTypes.string,
|
||||
privateChannels: PropTypes.array,
|
||||
publicChannels: PropTypes.array,
|
||||
requestStatus: PropTypes.string.isRequired,
|
||||
theme: PropTypes.object.isRequired
|
||||
theme: PropTypes.object.isRequired,
|
||||
value: PropTypes.string
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
postDraft: '',
|
||||
isSearch: false
|
||||
isSearch: false,
|
||||
value: ''
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -116,8 +116,8 @@ export default class ChannelMention extends PureComponent {
|
|||
}
|
||||
|
||||
completeMention = (mention) => {
|
||||
const {cursorPosition, isSearch, onChangeText, postDraft} = this.props;
|
||||
const mentionPart = postDraft.substring(0, cursorPosition);
|
||||
const {cursorPosition, isSearch, onChangeText, value} = this.props;
|
||||
const mentionPart = value.substring(0, cursorPosition);
|
||||
|
||||
let completedDraft;
|
||||
if (isSearch) {
|
||||
|
|
@ -127,8 +127,8 @@ export default class ChannelMention extends PureComponent {
|
|||
completedDraft = mentionPart.replace(CHANNEL_MENTION_REGEX, `~${mention} `);
|
||||
}
|
||||
|
||||
if (postDraft.length > cursorPosition) {
|
||||
completedDraft += postDraft.substring(cursorPosition);
|
||||
if (value.length > cursorPosition) {
|
||||
completedDraft += value.substring(cursorPosition);
|
||||
}
|
||||
|
||||
onChangeText(completedDraft, true);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {bindActionCreators} from 'redux';
|
|||
import {connect} from 'react-redux';
|
||||
|
||||
import {searchChannels} from 'mattermost-redux/actions/channels';
|
||||
import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||
|
||||
import {
|
||||
|
|
@ -20,25 +19,9 @@ import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
|||
import ChannelMention from './channel_mention';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
const {cursorPosition, isSearch, rootId} = ownProps;
|
||||
const currentChannelId = getCurrentChannelId(state);
|
||||
const {cursorPosition, isSearch} = ownProps;
|
||||
|
||||
let postDraft = '';
|
||||
if (isSearch) {
|
||||
postDraft = state.views.search;
|
||||
} else if (rootId) {
|
||||
const threadDraft = state.views.thread.drafts[rootId];
|
||||
if (threadDraft) {
|
||||
postDraft = threadDraft.draft;
|
||||
}
|
||||
} else if (currentChannelId) {
|
||||
const channelDraft = state.views.channel.drafts[currentChannelId];
|
||||
if (channelDraft) {
|
||||
postDraft = channelDraft.draft;
|
||||
}
|
||||
}
|
||||
|
||||
const value = postDraft.substring(0, cursorPosition);
|
||||
const value = ownProps.value.substring(0, cursorPosition);
|
||||
const matchTerm = getMatchTermForChannelMention(value, isSearch);
|
||||
|
||||
let myChannels;
|
||||
|
|
@ -61,7 +44,6 @@ function mapStateToProps(state, ownProps) {
|
|||
privateChannels,
|
||||
currentTeamId: getCurrentTeamId(state),
|
||||
matchTerm,
|
||||
postDraft,
|
||||
requestStatus: state.requests.channels.getChannels.status,
|
||||
theme: getTheme(state)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,25 +22,25 @@ export default class EmojiSuggestion extends Component {
|
|||
}).isRequired,
|
||||
cursorPosition: PropTypes.number,
|
||||
emojis: PropTypes.array.isRequired,
|
||||
postDraft: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
onChangeText: PropTypes.func.isRequired,
|
||||
rootId: PropTypes.string
|
||||
rootId: PropTypes.string,
|
||||
value: PropTypes.string
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
defaultChannel: {},
|
||||
postDraft: ''
|
||||
value: ''
|
||||
};
|
||||
|
||||
state = {
|
||||
active: false,
|
||||
dataSource: []
|
||||
}
|
||||
};
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const regex = EMOJI_REGEX;
|
||||
const match = nextProps.postDraft.substring(0, nextProps.cursorPosition).match(regex);
|
||||
const match = nextProps.value.substring(0, nextProps.cursorPosition).match(regex);
|
||||
|
||||
if (!match || this.state.emojiComplete) {
|
||||
this.setState({
|
||||
|
|
@ -74,8 +74,8 @@ export default class EmojiSuggestion extends Component {
|
|||
}
|
||||
|
||||
completeSuggestion = (emoji) => {
|
||||
const {actions, cursorPosition, onChangeText, postDraft, rootId} = this.props;
|
||||
const emojiPart = postDraft.substring(0, cursorPosition);
|
||||
const {actions, cursorPosition, onChangeText, value, rootId} = this.props;
|
||||
const emojiPart = value.substring(0, cursorPosition);
|
||||
|
||||
if (emojiPart.startsWith('+:')) {
|
||||
actions.addReactionToLatestPost(emoji, rootId);
|
||||
|
|
@ -83,8 +83,8 @@ export default class EmojiSuggestion extends Component {
|
|||
} else {
|
||||
let completedDraft = emojiPart.replace(EMOJI_REGEX, `:${emoji}: `);
|
||||
|
||||
if (postDraft.length > cursorPosition) {
|
||||
completedDraft += postDraft.substring(cursorPosition);
|
||||
if (value.length > cursorPosition) {
|
||||
completedDraft += value.substring(cursorPosition);
|
||||
}
|
||||
|
||||
onChangeText(completedDraft);
|
||||
|
|
|
|||
|
|
@ -25,26 +25,11 @@ const getEmojisByName = createSelector(
|
|||
}
|
||||
);
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
const {currentChannelId} = state.entities.channels;
|
||||
function mapStateToProps(state) {
|
||||
const emojis = getEmojisByName(state);
|
||||
|
||||
let postDraft;
|
||||
if (ownProps.rootId) {
|
||||
const threadDraft = state.views.thread.drafts[ownProps.rootId];
|
||||
if (threadDraft) {
|
||||
postDraft = threadDraft.draft;
|
||||
}
|
||||
} else if (currentChannelId) {
|
||||
const channelDraft = state.views.channel.drafts[currentChannelId];
|
||||
if (channelDraft) {
|
||||
postDraft = channelDraft.draft;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
emojis,
|
||||
postDraft,
|
||||
theme: getTheme(state)
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ export default class Autocomplete extends PureComponent {
|
|||
static propTypes = {
|
||||
onChangeText: PropTypes.func.isRequired,
|
||||
rootId: PropTypes.string,
|
||||
isSearch: PropTypes.bool
|
||||
isSearch: PropTypes.bool,
|
||||
value: PropTypes.string
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export default class PaperClipIcon extends Component {
|
|||
if (this.root) {
|
||||
this.root.setNativeProps(nativeProps);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,16 +3,7 @@
|
|||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Alert,
|
||||
BackHandler,
|
||||
Keyboard,
|
||||
Platform,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
View
|
||||
} from 'react-native';
|
||||
import {Alert, BackHandler, Keyboard, Platform, Text, TextInput, TouchableOpacity, View} from 'react-native';
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
import {RequestStatus} from 'mattermost-redux/constants';
|
||||
|
||||
|
|
@ -62,11 +53,16 @@ class PostTextbox extends PureComponent {
|
|||
value: ''
|
||||
};
|
||||
|
||||
state = {
|
||||
contentHeight: INITIAL_HEIGHT,
|
||||
inputWidth: null,
|
||||
keyboardType: 'default'
|
||||
};
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
contentHeight: INITIAL_HEIGHT,
|
||||
inputWidth: null,
|
||||
keyboardType: 'default',
|
||||
value: props.value
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (Platform.OS === 'android') {
|
||||
|
|
@ -76,8 +72,54 @@ class PostTextbox extends PureComponent {
|
|||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.channelId !== this.props.channelId || nextProps.rootId !== this.props.rootId) {
|
||||
this.setState({value: nextProps.value});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (Platform.OS === 'android') {
|
||||
Keyboard.removeListener('keyboardDidHide', this.handleAndroidKeyboard);
|
||||
BackHandler.removeEventListener('hardwareBackPress', this.handleAndroidBack);
|
||||
}
|
||||
}
|
||||
|
||||
attachAutocomplete = (c) => {
|
||||
this.autocomplete = c;
|
||||
};
|
||||
|
||||
blur = () => {
|
||||
this.refs.input.blur();
|
||||
};
|
||||
|
||||
canSend = () => {
|
||||
const {files, uploadFileRequestStatus} = this.props;
|
||||
const {value} = this.state;
|
||||
const valueLength = value.trim().length;
|
||||
|
||||
if (files.length) {
|
||||
return valueLength <= MAX_MESSAGE_LENGTH && uploadFileRequestStatus !== RequestStatus.STARTED && files.filter((f) => !f.failed).length > 0;
|
||||
}
|
||||
|
||||
return valueLength > 0 && valueLength <= MAX_MESSAGE_LENGTH;
|
||||
};
|
||||
|
||||
changeDraft = (text) => {
|
||||
const {
|
||||
actions,
|
||||
channelId,
|
||||
rootId
|
||||
} = this.props;
|
||||
|
||||
if (rootId) {
|
||||
actions.handleCommentDraftChanged(rootId, text);
|
||||
} else {
|
||||
actions.handlePostDraftChanged(channelId, text);
|
||||
}
|
||||
};
|
||||
|
||||
checkMessageLength = (value) => {
|
||||
const {intl} = this.props;
|
||||
const {value} = nextProps;
|
||||
const valueLength = value.trim().length;
|
||||
|
||||
if (valueLength > MAX_MESSAGE_LENGTH) {
|
||||
|
|
@ -95,28 +137,6 @@ class PostTextbox extends PureComponent {
|
|||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (Platform.OS === 'android') {
|
||||
Keyboard.removeListener('keyboardDidHide', this.handleAndroidKeyboard);
|
||||
BackHandler.removeEventListener('hardwareBackPress', this.handleAndroidBack);
|
||||
}
|
||||
}
|
||||
|
||||
blur = () => {
|
||||
this.refs.input.blur();
|
||||
};
|
||||
|
||||
canSend = () => {
|
||||
const {files, uploadFileRequestStatus, value} = this.props;
|
||||
const valueLength = value.trim().length;
|
||||
|
||||
if (files.length) {
|
||||
return valueLength <= MAX_MESSAGE_LENGTH && uploadFileRequestStatus !== RequestStatus.STARTED && files.filter((f) => !f.failed).length > 0;
|
||||
}
|
||||
|
||||
return valueLength > 0 && valueLength <= MAX_MESSAGE_LENGTH;
|
||||
};
|
||||
|
||||
handleAndroidKeyboard = () => {
|
||||
|
|
@ -132,12 +152,47 @@ class PostTextbox extends PureComponent {
|
|||
return false;
|
||||
};
|
||||
|
||||
handleContentSizeChange = (event) => {
|
||||
let contentHeight = event.nativeEvent.layout.height;
|
||||
if (contentHeight < INITIAL_HEIGHT) {
|
||||
contentHeight = INITIAL_HEIGHT;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
contentHeight
|
||||
});
|
||||
};
|
||||
|
||||
handleEndEditing = (e) => {
|
||||
if (e && e.nativeEvent) {
|
||||
this.changeDraft(e.nativeEvent.text || '');
|
||||
}
|
||||
};
|
||||
|
||||
handleInputSizeChange = (event) => {
|
||||
this.setState({
|
||||
inputWidth: event.nativeEvent.layout.width
|
||||
});
|
||||
};
|
||||
|
||||
handlePostDraftSelectionChanged = (event) => {
|
||||
const cursorPosition = event.nativeEvent.selection.end;
|
||||
if (this.props.rootId) {
|
||||
this.props.actions.handleCommentDraftSelectionChanged(this.props.rootId, cursorPosition);
|
||||
} else {
|
||||
this.props.actions.handlePostDraftSelectionChanged(this.props.channelId, cursorPosition);
|
||||
}
|
||||
|
||||
this.autocomplete.handleSelectionChange(event);
|
||||
};
|
||||
|
||||
handleSendMessage = () => {
|
||||
if (!this.canSend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {files, value} = this.props;
|
||||
const {files} = this.props;
|
||||
const {value} = this.state;
|
||||
|
||||
const isReactionMatch = value.match(IS_REACTION_REGEX);
|
||||
if (isReactionMatch) {
|
||||
|
|
@ -171,8 +226,85 @@ class PostTextbox extends PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
handleSubmit = () => {
|
||||
// Workaround for android as the multiline is not working
|
||||
if (Platform.OS === 'android') {
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
this.timeout = setTimeout(() => {
|
||||
let {value: msg} = this.props;
|
||||
msg += '\n';
|
||||
this.handleTextChange(msg);
|
||||
}, 10);
|
||||
}
|
||||
};
|
||||
|
||||
handleTextChange = (value) => {
|
||||
const {
|
||||
actions,
|
||||
channelId,
|
||||
rootId
|
||||
} = this.props;
|
||||
|
||||
this.checkMessageLength(value);
|
||||
this.setState({value});
|
||||
|
||||
if (value) {
|
||||
actions.userTyping(channelId, rootId);
|
||||
}
|
||||
};
|
||||
|
||||
handleUploadFiles = (images) => {
|
||||
this.props.actions.handleUploadFiles(images, this.props.rootId);
|
||||
};
|
||||
|
||||
renderDisabledSendButton = () => {
|
||||
const {theme} = this.props;
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
return (
|
||||
<View style={style.sendButtonContainer}>
|
||||
<View style={[style.sendButton, style.disableButton]}>
|
||||
<PaperPlane
|
||||
height={13}
|
||||
width={15}
|
||||
color={theme.buttonColor}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
renderSendButton = () => {
|
||||
const {theme, uploadFileRequestStatus} = this.props;
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
if (uploadFileRequestStatus === RequestStatus.STARTED) {
|
||||
return this.renderDisabledSendButton();
|
||||
} else if (this.canSend()) {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={this.handleSendMessage}
|
||||
style={style.sendButtonContainer}
|
||||
>
|
||||
<View style={style.sendButton}>
|
||||
<PaperPlane
|
||||
height={13}
|
||||
width={15}
|
||||
color={theme.buttonColor}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
sendMessage = () => {
|
||||
const {actions, currentUserId, channelId, files, rootId, value} = this.props;
|
||||
const {actions, currentUserId, channelId, files, rootId} = this.props;
|
||||
const {value} = this.state;
|
||||
|
||||
const postFiles = files.filter((f) => !f.failed);
|
||||
const post = {
|
||||
|
|
@ -185,6 +317,7 @@ class PostTextbox extends PureComponent {
|
|||
|
||||
actions.createPost(post, postFiles);
|
||||
this.handleTextChange('');
|
||||
this.changeDraft('');
|
||||
if (postFiles.length) {
|
||||
actions.handleClearFiles(channelId, rootId);
|
||||
}
|
||||
|
|
@ -205,139 +338,25 @@ class PostTextbox extends PureComponent {
|
|||
this.setState(nextState, callback);
|
||||
};
|
||||
|
||||
handleUploadFiles = (images) => {
|
||||
this.props.actions.handleUploadFiles(images, this.props.rootId);
|
||||
};
|
||||
|
||||
changeDraft = (text) => {
|
||||
const {
|
||||
actions,
|
||||
channelId,
|
||||
rootId
|
||||
} = this.props;
|
||||
|
||||
if (rootId) {
|
||||
actions.handleCommentDraftChanged(rootId, text);
|
||||
} else {
|
||||
actions.handlePostDraftChanged(channelId, text);
|
||||
}
|
||||
}
|
||||
|
||||
sendReaction = (emoji) => {
|
||||
const {actions, rootId} = this.props;
|
||||
actions.addReactionToLatestPost(emoji, rootId);
|
||||
this.handleTextChange('');
|
||||
}
|
||||
|
||||
handleTextChange = (text) => {
|
||||
const {
|
||||
actions,
|
||||
channelId,
|
||||
rootId
|
||||
} = this.props;
|
||||
|
||||
this.changeDraft(text);
|
||||
actions.userTyping(channelId, rootId);
|
||||
this.changeDraft('');
|
||||
};
|
||||
|
||||
handleContentSizeChange = (event) => {
|
||||
let contentHeight = event.nativeEvent.layout.height;
|
||||
if (contentHeight < INITIAL_HEIGHT) {
|
||||
contentHeight = INITIAL_HEIGHT;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
contentHeight
|
||||
});
|
||||
};
|
||||
|
||||
handleInputSizeChange = (event) => {
|
||||
this.setState({
|
||||
inputWidth: event.nativeEvent.layout.width
|
||||
});
|
||||
};
|
||||
|
||||
handleSubmit = () => {
|
||||
// Workaround for android as the multiline is not working
|
||||
if (Platform.OS === 'android') {
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
this.timeout = setTimeout(() => {
|
||||
let {value: msg} = this.props;
|
||||
msg += '\n';
|
||||
this.handleTextChange(msg);
|
||||
}, 10);
|
||||
}
|
||||
};
|
||||
|
||||
attachAutocomplete = (c) => {
|
||||
this.autocomplete = c;
|
||||
};
|
||||
|
||||
renderDisabledSendButton = () => {
|
||||
const {theme} = this.props;
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
return (
|
||||
<View style={[style.sendButton, style.disableButton]}>
|
||||
<PaperPlane
|
||||
height={13}
|
||||
width={15}
|
||||
color={theme.buttonColor}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
renderSendButton = () => {
|
||||
const {theme, uploadFileRequestStatus} = this.props;
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
if (uploadFileRequestStatus === RequestStatus.STARTED) {
|
||||
return this.renderDisabledSendButton();
|
||||
} else if (this.canSend()) {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={this.handleSendMessage}
|
||||
style={style.sendButton}
|
||||
>
|
||||
<PaperPlane
|
||||
height={13}
|
||||
width={15}
|
||||
color={theme.buttonColor}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
handlePostDraftSelectionChanged = (event) => {
|
||||
const cursorPosition = event.nativeEvent.selection.end;
|
||||
if (this.props.rootId) {
|
||||
this.props.actions.handleCommentDraftSelectionChanged(this.props.rootId, cursorPosition);
|
||||
} else {
|
||||
this.props.actions.handlePostDraftSelectionChanged(this.props.channelId, cursorPosition);
|
||||
}
|
||||
|
||||
this.autocomplete.handleSelectionChange(event);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
canUploadFiles,
|
||||
channelIsLoading,
|
||||
intl,
|
||||
theme,
|
||||
value
|
||||
theme
|
||||
} = this.props;
|
||||
|
||||
const style = getStyleSheet(theme);
|
||||
const textInputHeight = Math.min(this.state.contentHeight, MAX_CONTENT_HEIGHT);
|
||||
|
||||
const textValue = channelIsLoading ? '' : value;
|
||||
const textValue = channelIsLoading ? '' : this.state.value;
|
||||
|
||||
let placeholder;
|
||||
if (this.props.rootId) {
|
||||
|
|
@ -378,8 +397,8 @@ class PostTextbox extends PureComponent {
|
|||
/>
|
||||
<Autocomplete
|
||||
ref={this.attachAutocomplete}
|
||||
onChangeText={this.changeDraft}
|
||||
rootId={this.props.rootId}
|
||||
onChangeText={this.handleTextChange}
|
||||
value={this.state.value}
|
||||
/>
|
||||
<View style={style.inputWrapper}>
|
||||
{attachmentButton}
|
||||
|
|
@ -392,13 +411,14 @@ class PostTextbox extends PureComponent {
|
|||
placeholder={intl.formatMessage(placeholder)}
|
||||
placeholderTextColor={changeOpacity('#000', 0.5)}
|
||||
multiline={true}
|
||||
numberOfLines={10}
|
||||
numberOfLines={5}
|
||||
blurOnSubmit={false}
|
||||
underlineColorAndroid='transparent'
|
||||
style={[style.input, {height: textInputHeight}]}
|
||||
onSubmitEditing={this.handleSubmit}
|
||||
onLayout={this.handleInputSizeChange}
|
||||
keyboardType={this.state.keyboardType}
|
||||
onEndEditing={this.handleEndEditing}
|
||||
/>
|
||||
{this.renderSendButton()}
|
||||
</View>
|
||||
|
|
@ -435,8 +455,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
backgroundColor: '#fff',
|
||||
alignItems: 'flex-end',
|
||||
marginRight: 10
|
||||
alignItems: 'flex-end'
|
||||
},
|
||||
inputContainerWithoutFileUpload: {
|
||||
marginLeft: 10
|
||||
|
|
@ -449,6 +468,9 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
borderTopWidth: 1,
|
||||
borderTopColor: changeOpacity(theme.centerChannelColor, 0.20)
|
||||
},
|
||||
sendButtonContainer: {
|
||||
paddingRight: 10
|
||||
},
|
||||
sendButton: {
|
||||
backgroundColor: theme.buttonBg,
|
||||
borderRadius: 18,
|
||||
|
|
|
|||
|
|
@ -603,6 +603,7 @@ class Search extends PureComponent {
|
|||
ref={this.attachAutocomplete}
|
||||
onChangeText={this.handleTextChanged}
|
||||
isSearch={true}
|
||||
value={value}
|
||||
/>
|
||||
{previewComponent}
|
||||
</View>
|
||||
|
|
|
|||
Loading…
Reference in a new issue