forked from Ivasoft/mattermost-mobile
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:
5
app/components/conditionalWrapper.js
Normal file
5
app/components/conditionalWrapper.js
Normal 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;
|
||||
@@ -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>
|
||||
`;
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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('');
|
||||
|
||||
|
||||
@@ -121,4 +121,6 @@ export default {
|
||||
NotificationLevels,
|
||||
SidebarSectionTypes,
|
||||
IOS_HORIZONTAL_LANDSCAPE: 44,
|
||||
INPUT_LINE_HEIGHT: 17,
|
||||
INPUT_VERTICAL_PADDING: 16,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user