diff --git a/app/screens/channel_info/__snapshots__/channel_info.test.js.snap b/app/screens/channel_info/__snapshots__/channel_info.test.js.snap index 201240039..18e2a2c45 100644 --- a/app/screens/channel_info/__snapshots__/channel_info.test.js.snap +++ b/app/screens/channel_info/__snapshots__/channel_info.test.js.snap @@ -503,7 +503,7 @@ exports[`channelInfo should match snapshot 1`] = ` } } /> - - - Promise<{data?: AppCallResponse, error?: AppCallResponse}>; @@ -28,7 +29,7 @@ type Props = { } } -const Bindings: React.FC = (props: Props) => { +const Bindings: React.FC = injectIntl((props: Props) => { if (!props.appsEnabled) { return null; } @@ -51,7 +52,7 @@ const Bindings: React.FC = (props: Props) => { {options} ); -}; +}); export default Bindings; @@ -67,40 +68,60 @@ type OptionProps = { }, } -const Option = injectIntl((props: OptionProps) => { - const onPress = async () => { +type OptionState = { + submitting: boolean; +} + +class Option extends React.PureComponent { + state = { + submitting: false, + }; + + onPress = async () => { + const {binding, currentChannel, currentTeamId, intl} = this.props; + const {doAppCall, sendEphemeralPost} = this.props.actions; + + if (this.state.submitting) { + return; + } + if (!binding.call) { return; } + const context = createCallContext( binding.app_id, binding.location, - props.currentChannel.id, - props.currentChannel.team_id || props.currentTeamId, + currentChannel.id, + currentChannel.team_id || currentTeamId, ); const call = createCallRequest( binding.call, context, ); - const res = await props.actions.doAppCall(call, AppCallTypes.SUBMIT, props.intl); + this.setState({submitting: true}); + + const res = await doAppCall(call, AppCallTypes.SUBMIT, intl); + + this.setState({submitting: false}); + if (res.error) { const errorResponse = res.error; - const title = props.intl.formatMessage({ + const title = intl.formatMessage({ id: 'mobile.general.error.title', defaultMessage: 'Error', }); - const errorMessage = errorResponse.error || props.intl.formatMessage({ + const errorMessage = errorResponse.error || intl.formatMessage({ id: 'apps.error.unknown', defaultMessage: 'Unknown error occurred.', }); Alert.alert(title, errorMessage); - dismissModal(); return; } const callResp = res.data!; - const ephemeral = (message: string) => props.actions.sendEphemeralPost(message, props.currentChannel.id); + const ephemeral = (message: string) => sendEphemeralPost(message, currentChannel.id); switch (callResp.type) { case AppCallResponseTypes.OK: if (callResp.markdown) { @@ -111,37 +132,40 @@ const Option = injectIntl((props: OptionProps) => { case AppCallResponseTypes.FORM: break; default: { - const title = props.intl.formatMessage({ + const title = intl.formatMessage({ id: 'mobile.general.error.title', defaultMessage: 'Error', }); - const errMessage = props.intl.formatMessage({ + const errMessage = intl.formatMessage({ id: 'apps.error.responses.unknown_type', defaultMessage: 'App response type not supported. Response type: {type}.', }, { type: callResp.type, }); Alert.alert(title, errMessage); + return; } } dismissModal(); }; - const {binding, theme} = props; - if (!binding.label) { - return null; + render() { + const {binding, theme} = this.props; + if (!binding.label) { + return null; + } + return ( + <> + + + + ); } - return ( - <> - - - - ); -}); +} diff --git a/app/screens/post_options/__snapshots__/post_options.test.js.snap b/app/screens/post_options/__snapshots__/post_options.test.js.snap index 76e28657f..643869556 100644 --- a/app/screens/post_options/__snapshots__/post_options.test.js.snap +++ b/app/screens/post_options/__snapshots__/post_options.test.js.snap @@ -192,7 +192,7 @@ exports[`PostOptions should match snapshot, no option for system message to user } } /> - - - void, appsEnabled: boolean, + intl: typeof intlShape, actions: { doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; sendEphemeralPost: (message: any, channelId?: string, parentId?: string) => Promise; } } -const Bindings = (props: Props) => { +const Bindings = injectIntl((props: Props) => { if (!props.appsEnabled) { return null; } @@ -58,7 +59,7 @@ const Bindings = (props: Props) => { {options} ); -}; +}); export default Bindings; @@ -76,9 +77,10 @@ type OptionProps = { }, } -const Option = injectIntl((props: OptionProps) => { - const onPress = async () => { - const {closeWithAnimation, post, teamID} = props; +class Option extends React.PureComponent { + onPress = async () => { + const {closeWithAnimation, post, teamID, binding, intl} = this.props; + const {doAppCall, sendEphemeralPost} = this.props.actions; if (!binding.call) { return; @@ -98,24 +100,25 @@ const Option = injectIntl((props: OptionProps) => { post: AppExpandLevels.ALL, }, ); - const res = await props.actions?.doAppCall(call, AppCallTypes.SUBMIT, props.intl); + + closeWithAnimation(); + const res = await doAppCall(call, AppCallTypes.SUBMIT, intl); if (res.error) { const errorResponse = res.error; - const title = props.intl.formatMessage({ + const title = intl.formatMessage({ id: 'mobile.general.error.title', defaultMessage: 'Error', }); - const errorMessage = errorResponse.error || props.intl.formatMessage({ + const errorMessage = errorResponse.error || intl.formatMessage({ id: 'apps.error.unknown', defaultMessage: 'Unknown error occurred.', }); Alert.alert(title, errorMessage); - closeWithAnimation(); return; } const callResp = (res as {data: AppCallResponse}).data; - const ephemeral = (message: string) => props.actions.sendEphemeralPost(message, props.post.channel_id, props.post.root_id); + const ephemeral = (message: string) => sendEphemeralPost(message, post.channel_id, post.root_id); switch (callResp.type) { case AppCallResponseTypes.OK: if (callResp.markdown) { @@ -126,11 +129,11 @@ const Option = injectIntl((props: OptionProps) => { case AppCallResponseTypes.FORM: break; default: { - const title = props.intl.formatMessage({ + const title = intl.formatMessage({ id: 'mobile.general.error.title', defaultMessage: 'Error', }); - const errMessage = props.intl.formatMessage({ + const errMessage = intl.formatMessage({ id: 'apps.error.responses.unknown_type', defaultMessage: 'App response type not supported. Response type: {type}.', }, { @@ -139,21 +142,21 @@ const Option = injectIntl((props: OptionProps) => { Alert.alert(title, errMessage); } } - - closeWithAnimation(); }; - const {binding, theme} = props; - if (!binding.label) { - return null; - } + render() { + const {binding, theme} = this.props; + if (!binding.label) { + return null; + } - return ( - - ); -}); + return ( + + ); + } +} diff --git a/app/screens/post_options/post_options.test.js b/app/screens/post_options/post_options.test.js index 5ab5e3a92..3b01f47ec 100644 --- a/app/screens/post_options/post_options.test.js +++ b/app/screens/post_options/post_options.test.js @@ -3,14 +3,12 @@ import React from 'react'; import {Alert} from 'react-native'; -import {shallow} from 'enzyme'; +import {shallowWithIntl} from 'test/intl-test-helper'; import Preferences from '@mm-redux/constants/preferences'; import PostOptions from './post_options'; -jest.mock('react-intl'); - describe('PostOptions', () => { const actions = { addReaction: jest.fn(), @@ -55,12 +53,11 @@ describe('PostOptions', () => { }; function getWrapper(props = {}) { - return shallow( + return shallowWithIntl( , - {context: {intl: {formatMessage: ({defaultMessage}) => defaultMessage}}}, ); }