From d6a02a7c296de715899efeed391ef98bdb4c2283 Mon Sep 17 00:00:00 2001 From: Miguel Alatzar Date: Mon, 27 Jul 2020 16:38:31 -0700 Subject: [PATCH] Define registerTypingAnimation in Thread screen (#4617) --- .../channel_post_list/channel_post_list.js | 3 +-- .../__snapshots__/thread.ios.test.js.snap | 16 +----------- app/screens/thread/thread.android.js | 3 +-- app/screens/thread/thread.ios.js | 3 +-- app/screens/thread/thread.ios.test.js | 21 +++++++++++----- app/screens/thread/thread_base.js | 25 ++++++++++++++++--- 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/app/screens/channel/channel_post_list/channel_post_list.js b/app/screens/channel/channel_post_list/channel_post_list.js index 2e6782ee0..e994ebe73 100644 --- a/app/screens/channel/channel_post_list/channel_post_list.js +++ b/app/screens/channel/channel_post_list/channel_post_list.js @@ -102,7 +102,7 @@ export default class ChannelPostList extends PureComponent { goToThread = (post) => { telemetry.start(['post_list:thread']); - const {actions, channelId, registerTypingAnimation} = this.props; + const {actions, channelId} = this.props; const rootId = (post.root_id || post.id); Keyboard.dismiss(); @@ -114,7 +114,6 @@ export default class ChannelPostList extends PureComponent { const passProps = { channelId, rootId, - registerTypingAnimation, }; requestAnimationFrame(() => { diff --git a/app/screens/thread/__snapshots__/thread.ios.test.js.snap b/app/screens/thread/__snapshots__/thread.ios.test.js.snap index 12b2c1689..50f24a68e 100644 --- a/app/screens/thread/__snapshots__/thread.ios.test.js.snap +++ b/app/screens/thread/__snapshots__/thread.ios.test.js.snap @@ -70,21 +70,7 @@ exports[`thread should match snapshot, has root post 1`] = ` channelId="channel_id" channelIsArchived={false} cursorPositionEvent="onThreadTextBoxCursorChange" - registerTypingAnimation={ - [MockFunction] { - "calls": Array [ - Array [ - [Function], - ], - ], - "results": Array [ - Object { - "type": "return", - "value": [MockFunction], - }, - ], - } - } + registerTypingAnimation={[Function]} rootId="root_id" valueEvent="onThreadTextBoxValueChange" /> diff --git a/app/screens/thread/thread.android.js b/app/screens/thread/thread.android.js index fbea95765..cf208b667 100644 --- a/app/screens/thread/thread.android.js +++ b/app/screens/thread/thread.android.js @@ -24,7 +24,6 @@ export default class ThreadAndroid extends ThreadBase { rootId, channelIsArchived, theme, - registerTypingAnimation, } = this.props; let content; @@ -49,7 +48,7 @@ export default class ThreadAndroid extends ThreadBase { channelIsArchived={channelIsArchived} rootId={rootId} screenId={this.props.componentId} - registerTypingAnimation={registerTypingAnimation} + registerTypingAnimation={this.registerTypingAnimation} /> ); diff --git a/app/screens/thread/thread.ios.js b/app/screens/thread/thread.ios.js index e3f6d818b..2d8dbf708 100644 --- a/app/screens/thread/thread.ios.js +++ b/app/screens/thread/thread.ios.js @@ -37,7 +37,6 @@ export default class ThreadIOS extends ThreadBase { rootId, channelIsArchived, theme, - registerTypingAnimation, } = this.props; let content; @@ -84,7 +83,7 @@ export default class ThreadIOS extends ThreadBase { rootId={rootId} screenId={this.props.componentId} valueEvent={THREAD_POST_TEXTBOX_VALUE_CHANGE} - registerTypingAnimation={registerTypingAnimation} + registerTypingAnimation={this.registerTypingAnimation} /> ); diff --git a/app/screens/thread/thread.ios.test.js b/app/screens/thread/thread.ios.test.js index 5ca2440bd..595cc8d57 100644 --- a/app/screens/thread/thread.ios.test.js +++ b/app/screens/thread/thread.ios.test.js @@ -6,8 +6,10 @@ import {shallow} from 'enzyme'; import Preferences from '@mm-redux/constants/preferences'; import {General, RequestStatus} from '@mm-redux/constants'; +import EventEmitter from '@mm-redux/utils/event_emitter'; import PostList from 'app/components/post_list'; +import {TYPING_VISIBLE} from '@constants/post_draft'; import ThreadIOS from './thread.ios'; @@ -30,9 +32,6 @@ describe('thread', () => { postIds: ['root_id', 'post_id_1', 'post_id_2'], channelIsArchived: false, threadLoadingStatus: {status: RequestStatus.STARTED}, - registerTypingAnimation: jest.fn(() => { - return jest.fn(); - }), }; test('should match snapshot, has root post', () => { @@ -80,11 +79,21 @@ describe('thread', () => { {context: {intl: {formatMessage: jest.fn()}}}, ); const instance = wrapper.instance(); + instance.registerTypingAnimation = jest.fn(() => { + return jest.fn(); + }); + instance.bottomPaddingAnimation = jest.fn(); + instance.runTypingAnimations = jest.fn(); + EventEmitter.on = jest.fn(); + EventEmitter.off = jest.fn(); - expect(baseProps.registerTypingAnimation).toHaveBeenCalledTimes(1); + instance.componentDidMount(); + expect(instance.registerTypingAnimation).toHaveBeenCalledWith(instance.bottomPaddingAnimation); expect(instance.removeTypingAnimation).not.toHaveBeenCalled(); + expect(EventEmitter.on).toHaveBeenCalledWith(TYPING_VISIBLE, instance.runTypingAnimations); - wrapper.unmount(); - expect(instance.removeTypingAnimation).toHaveBeenCalledTimes(1); + instance.componentWillUnmount(); + expect(instance.removeTypingAnimation).toHaveBeenCalled(); + expect(EventEmitter.off).toHaveBeenCalledWith(TYPING_VISIBLE, instance.runTypingAnimations); }); }); diff --git a/app/screens/thread/thread_base.js b/app/screens/thread/thread_base.js index c79b48c17..de0cd274f 100644 --- a/app/screens/thread/thread_base.js +++ b/app/screens/thread/thread_base.js @@ -7,11 +7,12 @@ import {Animated, Keyboard} from 'react-native'; import {intlShape} from 'react-intl'; import {General, RequestStatus} from '@mm-redux/constants'; +import EventEmitter from '@mm-redux/utils/event_emitter'; import Loading from 'app/components/loading'; import DeletedPost from 'app/components/deleted_post'; import {popTopScreen, mergeNavigationOptions} from 'app/actions/navigation'; -import {TYPING_HEIGHT} from '@constants/post_draft'; +import {TYPING_HEIGHT, TYPING_VISIBLE} from '@constants/post_draft'; export default class ThreadBase extends PureComponent { static propTypes = { @@ -26,7 +27,6 @@ export default class ThreadBase extends PureComponent { rootId: PropTypes.string.isRequired, theme: PropTypes.object.isRequired, postIds: PropTypes.array.isRequired, - registerTypingAnimation: PropTypes.func.isRequired, channelIsArchived: PropTypes.bool, threadLoadingStatus: PropTypes.object, }; @@ -68,10 +68,12 @@ export default class ThreadBase extends PureComponent { }; this.bottomPadding = new Animated.Value(0); + this.typingAnimations = []; } componentDidMount() { - this.removeTypingAnimation = this.props.registerTypingAnimation(this.bottomPaddingAnimation); + this.removeTypingAnimation = this.registerTypingAnimation(this.bottomPaddingAnimation); + EventEmitter.on(TYPING_VISIBLE, this.runTypingAnimations); } componentWillReceiveProps(nextProps) { @@ -88,6 +90,7 @@ export default class ThreadBase extends PureComponent { componentWillUnmount() { this.props.actions.selectPost(''); this.removeTypingAnimation(); + EventEmitter.off(TYPING_VISIBLE, this.runTypingAnimations); } close = () => { @@ -119,6 +122,22 @@ export default class ThreadBase extends PureComponent { return null; }; + registerTypingAnimation = (animation) => { + const length = this.typingAnimations.push(animation); + const removeAnimation = () => { + const animationIndex = length - 1; + this.typingAnimations = this.typingAnimations.filter((a, index) => index !== animationIndex); + }; + + return removeAnimation; + } + + runTypingAnimations = (typingVisible) => { + Animated.parallel( + this.typingAnimations.map((animation) => animation(typingVisible)), + ).start(); + } + bottomPaddingAnimation = (visible) => { const [padding, duration] = visible ? [TYPING_HEIGHT, 200] :