From a5297c328c5bd79bc4c490060e2e12d0ef536a93 Mon Sep 17 00:00:00 2001 From: Mattermost Build Date: Thu, 29 Apr 2021 17:26:51 +0200 Subject: [PATCH] [MM-34746] Fix ephemeral error message response (#5304) (#5360) * fix ephemeral error message response * extract helpers for posting call responses (cherry picked from commit 3eaa5387070ad7a513108a0c7d99e9bdbe30a96a) Co-authored-by: Michael Kochell <6913320+mickmister@users.noreply.github.com> --- app/actions/apps.ts | 53 ++++++++++++++++++- app/actions/views/command.ts | 8 +-- .../app_command_parser_dependencies.ts | 1 - .../button_binding/button_binding.tsx | 15 +++--- .../embedded_bindings/button_binding/index.ts | 12 ++--- .../embedded_bindings/menu_binding/index.ts | 12 ++--- .../menu_binding/menu_binding.tsx | 18 +++---- app/screens/apps_form/apps_form_component.tsx | 9 ++-- app/screens/apps_form/apps_form_container.tsx | 14 ++--- app/screens/apps_form/index.ts | 12 ++--- .../channel_info/bindings/bindings.tsx | 17 +++--- app/screens/channel_info/bindings/index.ts | 12 ++--- .../post_options/bindings/bindings.tsx | 17 +++--- app/screens/post_options/bindings/index.ts | 12 ++--- types/actions/apps.d.ts | 26 +++++++++ 15 files changed, 149 insertions(+), 89 deletions(-) create mode 100644 types/actions/apps.d.ts diff --git a/app/actions/apps.ts b/app/actions/apps.ts index 6f8281f7d..ff2a86037 100644 --- a/app/actions/apps.ts +++ b/app/actions/apps.ts @@ -2,8 +2,11 @@ // See LICENSE.txt for license information. import {Client4} from '@client/rest'; -import {ActionFunc} from '@mm-redux/types/actions'; -import {AppCallResponse, AppForm, AppCallRequest, AppCallType} from '@mm-redux/types/apps'; + +import {ActionFunc, DispatchFunc} from '@mm-redux/types/actions'; +import {AppCallResponse, AppForm, AppCallRequest, AppCallType, AppContext} from '@mm-redux/types/apps'; +import {Post} from '@mm-redux/types/posts'; + import {AppCallTypes, AppCallResponseTypes} from '@mm-redux/constants/apps'; import {handleGotoLocation} from '@mm-redux/actions/integrations'; import {showModal} from './navigation'; @@ -12,6 +15,8 @@ import CompassIcon from '@components/compass_icon'; import {getTheme} from '@mm-redux/selectors/entities/preferences'; import EphemeralStore from '@store/ephemeral_store'; import {makeCallErrorResponse} from '@utils/apps'; +import {sendEphemeralPost} from '@actions/views/post'; +import {CommandArgs} from '@mm-redux/types/integrations'; export function doAppCall(call: AppCallRequest, type: AppCallType, intl: any): ActionFunc { return async (dispatch, getState) => { @@ -114,3 +119,47 @@ const showAppForm = async (form: AppForm, call: AppCallRequest, theme: Theme) => const passProps = {form, call}; showModal('AppForm', form.title, passProps, options); }; + +export function postEphemeralCallResponseForPost(response: AppCallResponse, message: string, post: Post): ActionFunc { + return (dispatch: DispatchFunc) => { + return dispatch(sendEphemeralPost( + message, + post.channel_id, + post.root_id || post.id, + response.app_metadata?.bot_user_id, + )); + }; +} + +export function postEphemeralCallResponseForChannel(response: AppCallResponse, message: string, channelID: string): ActionFunc { + return (dispatch: DispatchFunc) => { + return dispatch(sendEphemeralPost( + message, + channelID, + '', + response.app_metadata?.bot_user_id, + )); + }; +} + +export function postEphemeralCallResponseForContext(response: AppCallResponse, message: string, context: AppContext): ActionFunc { + return (dispatch: DispatchFunc) => { + return dispatch(sendEphemeralPost( + message, + context.channel_id, + context.root_id || context.post_id, + response.app_metadata?.bot_user_id, + )); + }; +} + +export function postEphemeralCallResponseForCommandArgs(response: AppCallResponse, message: string, args: CommandArgs): ActionFunc { + return (dispatch: DispatchFunc) => { + return dispatch(sendEphemeralPost( + message, + args.channel_id, + args.root_id, + response.app_metadata?.bot_user_id, + )); + }; +} diff --git a/app/actions/views/command.ts b/app/actions/views/command.ts index 96b380076..2448eddc1 100644 --- a/app/actions/views/command.ts +++ b/app/actions/views/command.ts @@ -8,13 +8,13 @@ import {executeCommand as executeCommandService} from '@mm-redux/actions/integra import {getCurrentTeamId} from '@mm-redux/selectors/entities/teams'; import {AppCallResponseTypes, AppCallTypes} from '@mm-redux/constants/apps'; import {DispatchFunc, GetStateFunc, ActionFunc} from '@mm-redux/types/actions'; +import {CommandArgs} from '@mm-redux/types/integrations'; import {AppCommandParser} from '@components/autocomplete/slash_suggestion/app_command_parser/app_command_parser'; -import {doAppCall} from '@actions/apps'; +import {doAppCall, postEphemeralCallResponseForCommandArgs} from '@actions/apps'; import {appsEnabled} from '@utils/apps'; import {AppCallResponse} from '@mm-redux/types/apps'; -import {sendEphemeralPost} from './post'; export function executeCommand(message: string, channelId: string, rootId: string, intl: typeof intlShape): ActionFunc { return async (dispatch: DispatchFunc, getState: GetStateFunc) => { @@ -22,7 +22,7 @@ export function executeCommand(message: string, channelId: string, rootId: strin const teamId = getCurrentTeamId(state); - const args = { + const args: CommandArgs = { channel_id: channelId, team_id: teamId, root_id: rootId, @@ -65,7 +65,7 @@ export function executeCommand(message: string, channelId: string, rootId: strin switch (callResp.type) { case AppCallResponseTypes.OK: if (callResp.markdown) { - dispatch(sendEphemeralPost(callResp.markdown, args.channel_id, args.parent_id, callResp.app_metadata?.bot_user_id)); + dispatch(postEphemeralCallResponseForCommandArgs(callResp, callResp.markdown, args)); } return {data: {}}; case AppCallResponseTypes.FORM: diff --git a/app/components/autocomplete/slash_suggestion/app_command_parser/app_command_parser_dependencies.ts b/app/components/autocomplete/slash_suggestion/app_command_parser/app_command_parser_dependencies.ts index 7179cb77c..992fb4e79 100644 --- a/app/components/autocomplete/slash_suggestion/app_command_parser/app_command_parser_dependencies.ts +++ b/app/components/autocomplete/slash_suggestion/app_command_parser/app_command_parser_dependencies.ts @@ -49,7 +49,6 @@ export {getUserByUsername as selectUserByUsername} from '@mm-redux/selectors/ent export {getUserByUsername} from '@mm-redux/actions/users'; export {getChannelByNameAndTeamName} from '@mm-redux/actions/channels'; -export {sendEphemeralPost} from '@actions/views/post'; export {doAppCall} from '@actions/apps'; export {createCallRequest} from '@utils/apps'; diff --git a/app/components/embedded_bindings/button_binding/button_binding.tsx b/app/components/embedded_bindings/button_binding/button_binding.tsx index 0ffa97c83..273a1edd5 100644 --- a/app/components/embedded_bindings/button_binding/button_binding.tsx +++ b/app/components/embedded_bindings/button_binding/button_binding.tsx @@ -11,18 +11,18 @@ import {getStatusColors} from '@utils/message_attachment_colors'; import ButtonBindingText from './button_binding_text'; import {Theme} from '@mm-redux/types/preferences'; import {ActionResult} from '@mm-redux/types/actions'; -import {AppBinding, AppCallRequest, AppCallResponse, AppCallType} from '@mm-redux/types/apps'; +import {AppBinding} from '@mm-redux/types/apps'; import {Post} from '@mm-redux/types/posts'; +import {DoAppCall, PostEphemeralCallResponseForPost} from 'types/actions/apps'; import {AppExpandLevels, AppBindingLocations, AppCallTypes, AppCallResponseTypes} from '@mm-redux/constants/apps'; import {createCallContext, createCallRequest} from '@utils/apps'; import {Channel} from '@mm-redux/types/channels'; -import {SendEphemeralPost} from 'types/actions/posts'; type Props = { actions: { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; + doAppCall: DoAppCall; getChannel: (channelId: string) => Promise; - sendEphemeralPost: SendEphemeralPost; + postEphemeralCallResponseForPost: PostEphemeralCallResponseForPost; }; post: Post; binding: AppBinding; @@ -72,14 +72,13 @@ export default class ButtonBinding extends PureComponent { this.setState({executing: false}); } - const ephemeral = (message: string) => this.props.actions.sendEphemeralPost(message, this.props.post.channel_id, this.props.post.root_id, res.data?.app_metadata?.bot_user_id); if (res.error) { const errorResponse = res.error; const errorMessage = errorResponse.error || intl.formatMessage( {id: 'apps.error.unknown', defaultMessage: 'Unknown error occurred.', }); - ephemeral(errorMessage); + this.props.actions.postEphemeralCallResponseForPost(errorResponse, errorMessage, post); return; } @@ -88,7 +87,7 @@ export default class ButtonBinding extends PureComponent { switch (callResp.type) { case AppCallResponseTypes.OK: if (callResp.markdown) { - ephemeral(callResp.markdown); + this.props.actions.postEphemeralCallResponseForPost(callResp, callResp.markdown, post); } return; case AppCallResponseTypes.NAVIGATE: @@ -104,7 +103,7 @@ export default class ButtonBinding extends PureComponent { type: callResp.type, }, ); - ephemeral(errorMessage); + this.props.actions.postEphemeralCallResponseForPost(callResp, errorMessage, post); } } }, 4000); diff --git a/app/components/embedded_bindings/button_binding/index.ts b/app/components/embedded_bindings/button_binding/index.ts index 456ea20fa..0843bd0ec 100644 --- a/app/components/embedded_bindings/button_binding/index.ts +++ b/app/components/embedded_bindings/button_binding/index.ts @@ -8,15 +8,13 @@ import {getTheme} from '@mm-redux/selectors/entities/preferences'; import {GlobalState} from '@mm-redux/types/store'; import {ActionFunc, ActionResult, GenericAction} from '@mm-redux/types/actions'; -import {AppCallRequest, AppCallResponse, AppCallType} from '@mm-redux/types/apps'; -import {doAppCall} from '@actions/apps'; +import {DoAppCall, PostEphemeralCallResponseForPost} from 'types/actions/apps'; +import {doAppCall, postEphemeralCallResponseForPost} from '@actions/apps'; import {getPost} from '@mm-redux/selectors/entities/posts'; import ButtonBinding from './button_binding'; import {getChannel} from '@mm-redux/actions/channels'; -import {sendEphemeralPost} from '@actions/views/post'; import {getCurrentTeamId} from '@mm-redux/selectors/entities/teams'; -import {SendEphemeralPost} from 'types/actions/posts'; type OwnProps = { postId: string; @@ -31,9 +29,9 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) { } type Actions = { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; + doAppCall: DoAppCall; getChannel: (channelId: string) => Promise; - sendEphemeralPost: SendEphemeralPost; + postEphemeralCallResponseForPost: PostEphemeralCallResponseForPost; } function mapDispatchToProps(dispatch: Dispatch) { @@ -41,7 +39,7 @@ function mapDispatchToProps(dispatch: Dispatch) { actions: bindActionCreators, Actions>({ doAppCall, getChannel, - sendEphemeralPost, + postEphemeralCallResponseForPost, }, dispatch), }; } diff --git a/app/components/embedded_bindings/menu_binding/index.ts b/app/components/embedded_bindings/menu_binding/index.ts index 25e0dddb7..8f7ebaffe 100644 --- a/app/components/embedded_bindings/menu_binding/index.ts +++ b/app/components/embedded_bindings/menu_binding/index.ts @@ -5,16 +5,14 @@ import {ActionCreatorsMapObject, bindActionCreators, Dispatch} from 'redux'; import {connect} from 'react-redux'; import {GlobalState} from '@mm-redux/types/store'; -import {doAppCall} from '@actions/apps'; import {ActionFunc, ActionResult, GenericAction} from '@mm-redux/types/actions'; -import {AppCallRequest, AppCallResponse, AppCallType} from '@mm-redux/types/apps'; -import {SendEphemeralPost} from 'types/actions/posts'; +import {DoAppCall, PostEphemeralCallResponseForPost} from 'types/actions/apps'; import {getPost} from '@mm-redux/selectors/entities/posts'; import MenuBinding from './menu_binding'; import {getChannel} from '@mm-redux/actions/channels'; -import {sendEphemeralPost} from '@actions/views/post'; import {getCurrentTeamId} from '@mm-redux/selectors/entities/teams'; +import {doAppCall, postEphemeralCallResponseForPost} from '@actions/apps'; type OwnProps = { postId: string; @@ -28,9 +26,9 @@ function mapStateToProps(state: GlobalState, ownProps: OwnProps) { } type Actions = { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; + doAppCall: DoAppCall; getChannel: (channelId: string) => Promise; - sendEphemeralPost: SendEphemeralPost; + postEphemeralCallResponseForPost: PostEphemeralCallResponseForPost; } function mapDispatchToProps(dispatch: Dispatch) { @@ -38,7 +36,7 @@ function mapDispatchToProps(dispatch: Dispatch) { actions: bindActionCreators, Actions>({ doAppCall, getChannel, - sendEphemeralPost, + postEphemeralCallResponseForPost, }, dispatch), }; } diff --git a/app/components/embedded_bindings/menu_binding/menu_binding.tsx b/app/components/embedded_bindings/menu_binding/menu_binding.tsx index e5830446b..995328be8 100644 --- a/app/components/embedded_bindings/menu_binding/menu_binding.tsx +++ b/app/components/embedded_bindings/menu_binding/menu_binding.tsx @@ -7,18 +7,18 @@ import AutocompleteSelector from 'app/components/autocomplete_selector'; import {intlShape} from 'react-intl'; import {PostActionOption} from '@mm-redux/types/integration_actions'; import {Post} from '@mm-redux/types/posts'; -import {AppBinding, AppCallRequest, AppCallResponse, AppCallType} from '@mm-redux/types/apps'; +import {AppBinding} from '@mm-redux/types/apps'; import {ActionResult} from '@mm-redux/types/actions'; +import {DoAppCall, PostEphemeralCallResponseForPost} from 'types/actions/apps'; import {AppExpandLevels, AppBindingLocations, AppCallTypes, AppCallResponseTypes} from '@mm-redux/constants/apps'; import {Channel} from '@mm-redux/types/channels'; import {createCallContext, createCallRequest} from '@utils/apps'; -import {SendEphemeralPost} from 'types/actions/posts'; type Props = { actions: { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; + doAppCall: DoAppCall; getChannel: (channelId: string) => Promise; - sendEphemeralPost: SendEphemeralPost; + postEphemeralCallResponseForPost: PostEphemeralCallResponseForPost; }; binding?: AppBinding; post: Post; @@ -82,16 +82,14 @@ export default class MenuBinding extends PureComponent { {post: AppExpandLevels.EXPAND_ALL}, ); - const res = await actions.doAppCall(call, AppCallTypes.SUBMIT, this.context.intl); - - const ephemeral = (message: string) => this.props.actions.sendEphemeralPost(message, this.props.post.channel_id, this.props.post.root_id, res.data?.app_metadata?.bot_user_id); + const res = await actions.doAppCall(call, AppCallTypes.SUBMIT, intl); if (res.error) { const errorResponse = res.error; const errorMessage = errorResponse.error || intl.formatMessage({ id: 'apps.error.unknown', defaultMessage: 'Unknown error occurred.', }); - ephemeral(errorMessage); + this.props.actions.postEphemeralCallResponseForPost(res.error, errorMessage, post); return; } @@ -99,7 +97,7 @@ export default class MenuBinding extends PureComponent { switch (callResp.type) { case AppCallResponseTypes.OK: if (callResp.markdown) { - ephemeral(callResp.markdown); + this.props.actions.postEphemeralCallResponseForPost(callResp, callResp.markdown, post); } return; case AppCallResponseTypes.NAVIGATE: @@ -112,7 +110,7 @@ export default class MenuBinding extends PureComponent { }, { type: callResp.type, }); - ephemeral(errorMessage); + this.props.actions.postEphemeralCallResponseForPost(callResp, errorMessage, post); } } }; diff --git a/app/screens/apps_form/apps_form_component.tsx b/app/screens/apps_form/apps_form_component.tsx index 591f30972..ca0c101df 100644 --- a/app/screens/apps_form/apps_form_component.tsx +++ b/app/screens/apps_form/apps_form_component.tsx @@ -18,11 +18,12 @@ import {dismissModal} from 'app/actions/navigation'; import DialogIntroductionText from './dialog_introduction_text'; import {Theme} from '@mm-redux/types/preferences'; -import {AppCallRequest, AppCallResponse, AppField, AppForm, AppFormValue, AppFormValues, AppLookupResponse, AppSelectOption, FormResponseData} from '@mm-redux/types/apps'; +import {AppCallRequest, AppField, AppForm, AppFormValue, AppFormValues, AppLookupResponse, AppSelectOption, FormResponseData} from '@mm-redux/types/apps'; import {DialogElement} from '@mm-redux/types/integrations'; import {AppCallResponseTypes} from '@mm-redux/constants/apps'; import AppsFormField from './apps_form_field'; import {preventDoubleTap} from '@utils/tap'; +import {DoAppCallResult} from 'types/actions/apps'; export type Props = { call: AppCallRequest; @@ -32,9 +33,9 @@ export type Props = { values: { [name: string]: string; }; - }) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; - performLookupCall: (field: AppField, values: AppFormValues, userInput: string) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; - refreshOnSelect: (field: AppField, values: AppFormValues, value: AppFormValue) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; + }) => Promise>; + performLookupCall: (field: AppField, values: AppFormValues, userInput: string) => Promise>; + refreshOnSelect: (field: AppField, values: AppFormValues, value: AppFormValue) => Promise>; }; theme: Theme; componentId: string; diff --git a/app/screens/apps_form/apps_form_container.tsx b/app/screens/apps_form/apps_form_container.tsx index 50970f1f5..e85fec0df 100644 --- a/app/screens/apps_form/apps_form_container.tsx +++ b/app/screens/apps_form/apps_form_container.tsx @@ -5,18 +5,18 @@ import React, {PureComponent} from 'react'; import {intlShape} from 'react-intl'; import {Theme} from '@mm-redux/types/preferences'; -import {AppCallResponse, AppCallRequest, AppField, AppForm, AppFormValues, FormResponseData, AppCallType, AppLookupResponse} from '@mm-redux/types/apps'; +import {AppCallResponse, AppCallRequest, AppField, AppForm, AppFormValues, FormResponseData, AppLookupResponse} from '@mm-redux/types/apps'; import {AppCallResponseTypes, AppCallTypes} from '@mm-redux/constants/apps'; import AppsFormComponent from './apps_form_component'; import {makeCallErrorResponse} from '@utils/apps'; -import {SendEphemeralPost} from 'types/actions/posts'; +import {DoAppCall, DoAppCallResult, PostEphemeralCallResponseForContext} from 'types/actions/apps'; export type Props = { form?: AppForm; call?: AppCallRequest; actions: { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; - sendEphemeralPost: SendEphemeralPost; + doAppCall: DoAppCall; + postEphemeralCallResponseForContext: PostEphemeralCallResponseForContext; }; theme: Theme; componentId: string; @@ -81,7 +81,7 @@ export default class AppsFormContainer extends PureComponent { switch (callResp.type) { case AppCallResponseTypes.OK: if (callResp.markdown) { - this.props.actions.sendEphemeralPost(callResp.markdown, call.context.channel_id, call.context.root_id || call.context.post_id, callResp.app_metadata?.bot_user_id); + this.props.actions.postEphemeralCallResponseForContext(callResp, callResp.markdown, call.context); } break; case AppCallResponseTypes.FORM: @@ -102,7 +102,7 @@ export default class AppsFormContainer extends PureComponent { return res; } - refreshOnSelect = async (field: AppField, values: AppFormValues): Promise<{data?: AppCallResponse, error?: AppCallResponse}> => { + refreshOnSelect = async (field: AppField, values: AppFormValues): Promise> => { const intl = this.context.intl; const makeErrorMsg = (message: string) => intl.formatMessage( { @@ -171,7 +171,7 @@ export default class AppsFormContainer extends PureComponent { return res; }; - performLookupCall = async (field: AppField, values: AppFormValues, userInput: string): Promise<{data?: AppCallResponse, error?: AppCallResponse}> => { + performLookupCall = async (field: AppField, values: AppFormValues, userInput: string): Promise> => { const intl = this.context.intl; const makeErrorMsg = (message: string) => intl.formatMessage( { diff --git a/app/screens/apps_form/index.ts b/app/screens/apps_form/index.ts index 0e2685cee..84ae177cf 100644 --- a/app/screens/apps_form/index.ts +++ b/app/screens/apps_form/index.ts @@ -5,19 +5,17 @@ import {ActionCreatorsMapObject, bindActionCreators, Dispatch} from 'redux'; import {connect} from 'react-redux'; import {getTheme} from '@mm-redux/selectors/entities/preferences'; -import {doAppCall} from '@actions/apps'; +import {doAppCall, postEphemeralCallResponseForContext} from '@actions/apps'; -import {AppCallResponse, AppCallRequest, AppCallType} from '@mm-redux/types/apps'; import {GlobalState} from '@mm-redux/types/store'; import {ActionFunc, GenericAction} from '@mm-redux/types/actions'; -import {SendEphemeralPost} from 'types/actions/posts'; import AppsFormContainer from './apps_form_container'; -import {sendEphemeralPost} from '@actions/views/post'; +import {DoAppCall, PostEphemeralCallResponseForContext} from 'types/actions/apps'; type Actions = { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; - sendEphemeralPost: SendEphemeralPost; + doAppCall: DoAppCall; + postEphemeralCallResponseForContext: PostEphemeralCallResponseForContext; }; function mapStateToProps(state: GlobalState) { @@ -30,7 +28,7 @@ function mapDispatchToProps(dispatch: Dispatch) { return { actions: bindActionCreators, Actions>({ doAppCall, - sendEphemeralPost, + postEphemeralCallResponseForContext, }, dispatch), }; } diff --git a/app/screens/channel_info/bindings/bindings.tsx b/app/screens/channel_info/bindings/bindings.tsx index f77c97b6b..6d30f464c 100644 --- a/app/screens/channel_info/bindings/bindings.tsx +++ b/app/screens/channel_info/bindings/bindings.tsx @@ -8,13 +8,13 @@ import {intlShape, injectIntl} from 'react-intl'; import Separator from '@screens/channel_info/separator'; import ChannelInfoRow from '../channel_info_row'; -import {AppBinding, AppCallRequest, AppCallResponse, AppCallType} from '@mm-redux/types/apps'; +import {AppBinding} from '@mm-redux/types/apps'; import {Theme} from '@mm-redux/types/preferences'; import {Channel} from '@mm-redux/types/channels'; import {AppCallResponseTypes, AppCallTypes} from '@mm-redux/constants/apps'; import {dismissModal} from '@actions/navigation'; import {createCallContext, createCallRequest} from '@utils/apps'; -import {SendEphemeralPost} from 'types/actions/posts'; +import {DoAppCall, PostEphemeralCallResponseForChannel} from 'types/actions/apps'; type Props = { bindings: AppBinding[]; @@ -24,8 +24,8 @@ type Props = { intl: typeof intlShape; currentTeamId: string; actions: { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; - sendEphemeralPost: SendEphemeralPost; + doAppCall: DoAppCall; + postEphemeralCallResponseForChannel: PostEphemeralCallResponseForChannel; } } @@ -63,8 +63,8 @@ type OptionProps = { intl: typeof intlShape; currentTeamId: string; actions: { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; - sendEphemeralPost: SendEphemeralPost; + doAppCall: DoAppCall; + postEphemeralCallResponseForChannel: PostEphemeralCallResponseForChannel; }, } @@ -79,7 +79,7 @@ class Option extends React.PureComponent { onPress = async () => { const {binding, currentChannel, currentTeamId, intl} = this.props; - const {doAppCall, sendEphemeralPost} = this.props.actions; + const {doAppCall, postEphemeralCallResponseForChannel} = this.props.actions; if (this.state.submitting) { return; @@ -121,11 +121,10 @@ class Option extends React.PureComponent { } const callResp = res.data!; - const ephemeral = (message: string) => sendEphemeralPost(message, currentChannel.id, '', callResp.app_metadata?.bot_user_id); switch (callResp.type) { case AppCallResponseTypes.OK: if (callResp.markdown) { - ephemeral(callResp.markdown); + postEphemeralCallResponseForChannel(callResp, callResp.markdown, currentChannel.id); } break; case AppCallResponseTypes.NAVIGATE: diff --git a/app/screens/channel_info/bindings/index.ts b/app/screens/channel_info/bindings/index.ts index c34ecaf74..546f6c041 100644 --- a/app/screens/channel_info/bindings/index.ts +++ b/app/screens/channel_info/bindings/index.ts @@ -9,15 +9,13 @@ import {AppBindingLocations} from '@mm-redux/constants/apps'; import {getCurrentChannel} from '@mm-redux/selectors/entities/channels'; import {GlobalState} from '@mm-redux/types/store'; import {GenericAction, ActionFunc} from '@mm-redux/types/actions'; -import {AppCallRequest, AppCallResponse, AppCallType} from '@mm-redux/types/apps'; +import {DoAppCall, PostEphemeralCallResponseForChannel} from 'types/actions/apps'; import {appsEnabled} from '@utils/apps'; -import {doAppCall} from '@actions/apps'; +import {doAppCall, postEphemeralCallResponseForChannel} from '@actions/apps'; import Bindings from './bindings'; -import {sendEphemeralPost} from '@actions/views/post'; import {getCurrentTeamId} from '@mm-redux/selectors/entities/teams'; -import {SendEphemeralPost} from 'types/actions/posts'; function mapStateToProps(state: GlobalState) { const apps = appsEnabled(state); @@ -33,15 +31,15 @@ function mapStateToProps(state: GlobalState) { } type Actions = { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; - sendEphemeralPost: SendEphemeralPost; + doAppCall: DoAppCall; + postEphemeralCallResponseForChannel: PostEphemeralCallResponseForChannel; } function mapDispatchToProps(dispatch: Dispatch) { return { actions: bindActionCreators, Actions>({ doAppCall, - sendEphemeralPost, + postEphemeralCallResponseForChannel, }, dispatch), }; } diff --git a/app/screens/post_options/bindings/bindings.tsx b/app/screens/post_options/bindings/bindings.tsx index 4e94832f2..800cc36f8 100644 --- a/app/screens/post_options/bindings/bindings.tsx +++ b/app/screens/post_options/bindings/bindings.tsx @@ -8,13 +8,13 @@ import {intlShape, injectIntl} from 'react-intl'; import {isSystemMessage} from '@mm-redux/utils/post_utils'; import PostOption from '../post_option'; -import {AppBinding, AppCallRequest, AppCallResponse, AppCallType} from '@mm-redux/types/apps'; +import {AppBinding, AppCallResponse} from '@mm-redux/types/apps'; import {Theme} from '@mm-redux/types/preferences'; import {Post} from '@mm-redux/types/posts'; import {UserProfile} from '@mm-redux/types/users'; import {AppCallResponseTypes, AppCallTypes, AppExpandLevels} from '@mm-redux/constants/apps'; import {createCallContext, createCallRequest} from '@utils/apps'; -import {SendEphemeralPost} from 'types/actions/posts'; +import {DoAppCall, PostEphemeralCallResponseForPost} from 'types/actions/apps'; type Props = { bindings: AppBinding[], @@ -26,8 +26,8 @@ type Props = { appsEnabled: boolean, intl: typeof intlShape, actions: { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; - sendEphemeralPost: SendEphemeralPost; + doAppCall: DoAppCall; + postEphemeralCallResponseForPost: PostEphemeralCallResponseForPost; } } @@ -72,15 +72,15 @@ type OptionProps = { closeWithAnimation: () => void, intl: typeof intlShape, actions: { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; - sendEphemeralPost: SendEphemeralPost; + doAppCall: DoAppCall; + postEphemeralCallResponseForPost: PostEphemeralCallResponseForPost; }, } class Option extends React.PureComponent { onPress = async () => { const {closeWithAnimation, post, teamID, binding, intl} = this.props; - const {doAppCall, sendEphemeralPost} = this.props.actions; + const {doAppCall, postEphemeralCallResponseForPost} = this.props.actions; if (!binding.call) { return; @@ -118,11 +118,10 @@ class Option extends React.PureComponent { } const callResp = (res as {data: AppCallResponse}).data; - const ephemeral = (message: string) => sendEphemeralPost(message, post.channel_id, post.root_id || post.id, callResp.app_metadata?.bot_user_id); switch (callResp.type) { case AppCallResponseTypes.OK: if (callResp.markdown) { - ephemeral(callResp.markdown); + postEphemeralCallResponseForPost(callResp, callResp.markdown, post); } break; case AppCallResponseTypes.NAVIGATE: diff --git a/app/screens/post_options/bindings/index.ts b/app/screens/post_options/bindings/index.ts index 0a91bd3af..a86d4ded8 100644 --- a/app/screens/post_options/bindings/index.ts +++ b/app/screens/post_options/bindings/index.ts @@ -7,21 +7,19 @@ import {bindActionCreators, Dispatch, ActionCreatorsMapObject} from 'redux'; import {getTheme} from '@mm-redux/selectors/entities/preferences'; import {GlobalState} from '@mm-redux/types/store'; -import {AppCallRequest, AppCallResponse, AppCallType} from '@mm-redux/types/apps'; import {GenericAction, ActionFunc} from '@mm-redux/types/actions'; import {getAppsBindings} from '@mm-redux/selectors/entities/apps'; import {AppBindingLocations} from '@mm-redux/constants/apps'; import {getCurrentUser} from '@mm-redux/selectors/entities/users'; -import {doAppCall} from '@actions/apps'; +import {doAppCall, postEphemeralCallResponseForPost} from '@actions/apps'; import {appsEnabled} from '@utils/apps'; import Bindings from './bindings'; import {getCurrentTeamId} from '@mm-redux/selectors/entities/teams'; -import {sendEphemeralPost} from '@actions/views/post'; import {Post} from '@mm-redux/types/posts'; import {getChannel} from '@mm-redux/selectors/entities/channels'; -import {SendEphemeralPost} from 'types/actions/posts'; +import {DoAppCall, PostEphemeralCallResponseForPost} from 'types/actions/apps'; type OwnProps = { post: Post; @@ -43,15 +41,15 @@ function mapStateToProps(state: GlobalState, props: OwnProps) { } type Actions = { - doAppCall: (call: AppCallRequest, type: AppCallType, intl: any) => Promise<{data?: AppCallResponse, error?: AppCallResponse}>; - sendEphemeralPost: SendEphemeralPost; + doAppCall: DoAppCall; + postEphemeralCallResponseForPost: PostEphemeralCallResponseForPost; } function mapDispatchToProps(dispatch: Dispatch) { return { actions: bindActionCreators, Actions>({ doAppCall, - sendEphemeralPost, + postEphemeralCallResponseForPost, }, dispatch), }; } diff --git a/types/actions/apps.d.ts b/types/actions/apps.d.ts new file mode 100644 index 000000000..97b5c8f19 --- /dev/null +++ b/types/actions/apps.d.ts @@ -0,0 +1,26 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {AppCallRequest, AppCallResponse, AppCallType, AppContext} from '@mm-redux/types/apps'; +import {Post} from '@mm-redux/types/posts'; + +export type DoAppCallResult = { + data?: AppCallResponse; + error?: AppCallResponse; +} + +export interface DoAppCall { + (call: AppCallRequest, type: AppCallType, intl: any): Promise>; +} + +export interface PostEphemeralCallResponseForPost { + (response: AppCallResponse, message: string, post: Post): void; +} + +export interface PostEphemeralCallResponseForChannel { + (response: AppCallResponse, message: string, channelID: string): void; +} + +export interface PostEphemeralCallResponseForContext { + (response: AppCallResponse, message: string, context: AppContext): void; +}