MM-15307 Updated to use InteractionManager (#3666)

* MM-15307 Updated to use InteractionManager

Replaced the setTimeout with InteractionManager to resolve the delay set.

* Updated to apply animation to the input height

* Updated to apply animation to the input height

* Fixed eslint issue

* Updates per review

* Updates from feedback
This commit is contained in:
CJ
2020-01-09 05:02:02 -05:00
committed by Saturnino Abril
parent c988a3ea80
commit e08155c81b
5 changed files with 61 additions and 30 deletions

View File

@@ -0,0 +1,5 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
/* eslint-disable no-confusing-arrow */
export const ConditionalWrapper = ({conditional, wrapper, children}) => conditional ? wrapper(children) : children;

View File

@@ -1,12 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PasteableTextInput should render pasteable text input 1`] = `
<TextInput
allowFontScaling={true}
onPaste={[MockFunction]}
rejectResponderTermination={true}
underlineColorAndroid="transparent"
<ConditionalWrapper
conditional={true}
wrapper={[Function]}
>
My Text
</TextInput>
<TextInput
allowFontScaling={true}
onContentSizeChange={[Function]}
onPaste={[MockFunction]}
rejectResponderTermination={true}
underlineColorAndroid="transparent"
>
My Text
</TextInput>
</ConditionalWrapper>
`;

View File

@@ -3,8 +3,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import {TextInput, NativeEventEmitter, NativeModules} from 'react-native';
import {Animated, Easing, NativeEventEmitter, NativeModules, Platform, TextInput} from 'react-native';
import CustomTextInput from './custom_text_input';
import {ConditionalWrapper} from 'app/components/conditionalWrapper';
import {ViewTypes} from 'app/constants';
const {OnPasteEventManager} = NativeModules;
const OnPasteEventEmitter = new NativeEventEmitter(OnPasteEventManager);
@@ -16,6 +18,10 @@ export class PasteableTextInput extends React.Component {
forwardRef: PropTypes.any,
}
state = {
inputHeight: new Animated.Value(33),
};
componentDidMount() {
this.subscription = OnPasteEventEmitter.addListener('onPaste', this.onPaste);
}
@@ -31,14 +37,41 @@ export class PasteableTextInput extends React.Component {
return onPaste?.(null, event);
}
animateHeight = (event) => {
if (Platform.OS === 'ios') {
const {height} = event.nativeEvent.contentSize;
const {style} = this.props;
const {inputHeight} = this.state;
const newHeight = height > style.maxHeight ? inputHeight : height + ViewTypes.INPUT_VERTICAL_PADDING;
const transitionSpeed = height === ViewTypes.INPUT_LINE_HEIGHT ? 500 : 100;
Animated.timing(inputHeight, {
toValue: newHeight,
duration: transitionSpeed,
easing: Easing.inOut(Easing.sin),
}).start();
}
}
wrapperLayout = (children) => {
const {inputHeight} = this.state;
return <Animated.View style={{flex: 1, height: inputHeight}}>{children}</Animated.View>;
}
render() {
const {forwardRef, ...props} = this.props;
return (
<CustomTextInput
{...props}
ref={forwardRef}
/>
<ConditionalWrapper
conditional={Platform.OS === 'ios'}
wrapper={this.wrapperLayout}
>
<CustomTextInput
{...props}
ref={forwardRef}
onContentSizeChange={this.animateHeight}
/>
</ConditionalWrapper>
);
}
}

View File

@@ -8,6 +8,7 @@ import {
AppState,
BackHandler,
findNodeHandle,
InteractionManager,
Keyboard,
NativeModules,
Platform,
@@ -526,26 +527,10 @@ export default class PostTextBoxBase extends PureComponent {
actions.handleClearFiles(channelId, rootId);
}
if (Platform.OS === 'ios') {
// On iOS, if the PostTextbox height increases from its
// initial height (due to a multiline post or a post whose
// message wraps, for example), then when the text is cleared
// the PostTextbox height decrease will be animated. This
// animation in conjunction with the PostList animation as it
// receives the newly created post is causing issues in the iOS
// PostList component as it fails to properly react to its content
// size changes. While a proper fix is determined for the PostList
// component, a small delay in triggering the height decrease
// animation gives the PostList enough time to first handle content
// size changes from the new post.
setTimeout(() => {
this.handleTextChange('');
this.setState({sendingMessage: false});
}, 250);
} else {
InteractionManager.runAfterInteractions(() => {
this.handleTextChange('');
this.setState({sendingMessage: false});
}
});
this.changeDraft('');

View File

@@ -121,4 +121,6 @@ export default {
NotificationLevels,
SidebarSectionTypes,
IOS_HORIZONTAL_LANDSCAPE: 44,
INPUT_LINE_HEIGHT: 17,
INPUT_VERTICAL_PADDING: 16,
};