MM-15282 Fix cutoff placeholder on Android (#2798)
* MM-15282 Fix cutoff placeholder on Android * Feedback review
This commit is contained in:
parent
bbfd6e820f
commit
d0071c21b0
2 changed files with 26 additions and 39 deletions
|
|
@ -14,7 +14,7 @@ import AttachmentButton from 'app/components/attachment_button';
|
|||
import Autocomplete from 'app/components/autocomplete';
|
||||
import Fade from 'app/components/fade';
|
||||
import FileUploadPreview from 'app/components/file_upload_preview';
|
||||
import {INITIAL_HEIGHT, INSERT_TO_COMMENT, INSERT_TO_DRAFT, IS_REACTION_REGEX, MAX_CONTENT_HEIGHT, MAX_FILE_COUNT} from 'app/constants/post_textbox';
|
||||
import {INSERT_TO_COMMENT, INSERT_TO_DRAFT, IS_REACTION_REGEX, MAX_CONTENT_HEIGHT, MAX_FILE_COUNT} from 'app/constants/post_textbox';
|
||||
import {confirmOutOfOfficeDisabled} from 'app/utils/status';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
import {t} from 'app/utils/i18n';
|
||||
|
|
@ -24,6 +24,7 @@ import SendButton from 'app/components/send_button';
|
|||
|
||||
import Typing from './components/typing';
|
||||
|
||||
const PLACEHOLDER_COLOR = changeOpacity('#000', 0.5);
|
||||
const {RNTextInputReset} = NativeModules;
|
||||
|
||||
const AUTOCOMPLETE_MARGIN = 20;
|
||||
|
|
@ -80,8 +81,9 @@ export default class PostTextbox extends PureComponent {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.input = React.createRef();
|
||||
|
||||
this.state = {
|
||||
contentHeight: INITIAL_HEIGHT,
|
||||
cursorPosition: 0,
|
||||
keyboardType: 'default',
|
||||
fileSizeWarning: null,
|
||||
|
|
@ -116,8 +118,8 @@ export default class PostTextbox extends PureComponent {
|
|||
}
|
||||
|
||||
blur = () => {
|
||||
if (this.refs.input) {
|
||||
this.refs.input.blur();
|
||||
if (this.input?.current) {
|
||||
this.input.current.blur();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -188,19 +190,6 @@ export default class PostTextbox extends PureComponent {
|
|||
return false;
|
||||
};
|
||||
|
||||
handleContentSizeChange = (event) => {
|
||||
if (Platform.OS === 'android') {
|
||||
let contentHeight = event.nativeEvent.contentSize.height;
|
||||
if (contentHeight < INITIAL_HEIGHT) {
|
||||
contentHeight = INITIAL_HEIGHT;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
contentHeight,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleEndEditing = (e) => {
|
||||
if (e && e.nativeEvent) {
|
||||
this.changeDraft(e.nativeEvent.text || '');
|
||||
|
|
@ -273,7 +262,7 @@ export default class PostTextbox extends PureComponent {
|
|||
this.setState({
|
||||
value: completed,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleTextChange = (value, autocomplete = false) => {
|
||||
const {
|
||||
|
|
@ -283,8 +272,8 @@ export default class PostTextbox extends PureComponent {
|
|||
} = this.props;
|
||||
|
||||
// Workaround for some Android keyboards that don't play well with cursors (e.g. Samsung keyboards)
|
||||
if (autocomplete && Platform.OS === 'android') {
|
||||
RNTextInputReset.resetKeyboardInput(findNodeHandle(this.refs.input));
|
||||
if (autocomplete && Platform.OS === 'android' & this.input?.current) {
|
||||
RNTextInputReset.resetKeyboardInput(findNodeHandle(this.input.current));
|
||||
}
|
||||
|
||||
this.checkMessageLength(value);
|
||||
|
|
@ -371,14 +360,12 @@ export default class PostTextbox extends PureComponent {
|
|||
|
||||
let callback;
|
||||
if (Platform.OS === 'android') {
|
||||
// Shrink the input textbox since the layout events lag slightly
|
||||
const nextState = {
|
||||
contentHeight: INITIAL_HEIGHT,
|
||||
};
|
||||
|
||||
// Fixes the issue where Android predictive text would prepend suggestions to the post draft when messages
|
||||
// are typed successively without blurring the input
|
||||
nextState.keyboardType = 'email-address';
|
||||
const nextState = {
|
||||
keyboardType: 'email-address',
|
||||
};
|
||||
|
||||
callback = () => this.setState({keyboardType: 'default'});
|
||||
|
||||
this.setState(nextState, callback);
|
||||
|
|
@ -532,7 +519,6 @@ export default class PostTextbox extends PureComponent {
|
|||
}
|
||||
|
||||
const {
|
||||
contentHeight,
|
||||
cursorPosition,
|
||||
fileSizeWarning,
|
||||
showFileMaxWarning,
|
||||
|
|
@ -540,7 +526,6 @@ export default class PostTextbox extends PureComponent {
|
|||
value,
|
||||
} = this.state;
|
||||
|
||||
const textInputHeight = Math.min(contentHeight, MAX_CONTENT_HEIGHT);
|
||||
const textValue = channelIsLoading ? '' : value;
|
||||
|
||||
let placeholder;
|
||||
|
|
@ -572,6 +557,10 @@ export default class PostTextbox extends PureComponent {
|
|||
inputContainerStyle.push(style.inputContainerWithoutFileUpload);
|
||||
}
|
||||
|
||||
if (channelIsReadOnly) {
|
||||
inputContainerStyle.push(style.readonlyContainer);
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Typing/>
|
||||
|
|
@ -595,20 +584,18 @@ export default class PostTextbox extends PureComponent {
|
|||
onLayout={this.handleLayout}
|
||||
>
|
||||
{!channelIsReadOnly && attachmentButton}
|
||||
<View style={[inputContainerStyle, (channelIsReadOnly && {marginLeft: 10})]}>
|
||||
<View style={inputContainerStyle}>
|
||||
<TextInput
|
||||
ref='input'
|
||||
ref={this.input}
|
||||
value={textValue}
|
||||
onChangeText={this.handleTextChange}
|
||||
onSelectionChange={this.handlePostDraftSelectionChanged}
|
||||
placeholder={intl.formatMessage(placeholder, {channelDisplayName})}
|
||||
placeholderTextColor={changeOpacity('#000', 0.5)}
|
||||
placeholderTextColor={PLACEHOLDER_COLOR}
|
||||
multiline={true}
|
||||
numberOfLines={5}
|
||||
blurOnSubmit={false}
|
||||
underlineColorAndroid='transparent'
|
||||
style={[style.input, Platform.OS === 'android' ? {height: textInputHeight} : {maxHeight: MAX_CONTENT_HEIGHT}]}
|
||||
onContentSizeChange={this.handleContentSizeChange}
|
||||
style={style.input}
|
||||
keyboardType={this.state.keyboardType}
|
||||
onEndEditing={this.handleEndEditing}
|
||||
disableFullscreenUI={true}
|
||||
|
|
@ -636,11 +623,11 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
color: '#000',
|
||||
flex: 1,
|
||||
fontSize: 14,
|
||||
maxHeight: MAX_CONTENT_HEIGHT,
|
||||
paddingBottom: 8,
|
||||
paddingLeft: 12,
|
||||
paddingRight: 12,
|
||||
paddingTop: 8,
|
||||
textAlignVertical: 'top',
|
||||
},
|
||||
hidden: {
|
||||
position: 'absolute',
|
||||
|
|
@ -707,5 +694,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
color: 'white',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
readonlyContainer: {
|
||||
marginLeft: 10,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Platform} from 'react-native';
|
||||
|
||||
export const INITIAL_HEIGHT = Platform.OS === 'ios' ? 34 : 36;
|
||||
export const MAX_CONTENT_HEIGHT = 100;
|
||||
export const MAX_FILE_COUNT = 5;
|
||||
export const IS_REACTION_REGEX = /(^\+:([^:\s]*):)$/i;
|
||||
export const INSERT_TO_DRAFT = 'insert_to_draft';
|
||||
export const INSERT_TO_COMMENT = 'insert_to_comment';
|
||||
export const INSERT_TO_COMMENT = 'insert_to_comment';
|
||||
|
|
|
|||
Loading…
Reference in a new issue