RN-360 Add support for interactive message buttons (#1131)
This commit is contained in:
parent
a299cdb5c5
commit
d7622eb7a4
7 changed files with 147 additions and 14 deletions
|
|
@ -295,7 +295,7 @@ class Post extends PureComponent {
|
|||
theme
|
||||
} = this.props;
|
||||
|
||||
if (!renderReplies || !post.root_id) {
|
||||
if (!renderReplies || !post.root_id || isPostEphemeral(post)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -253,6 +253,7 @@ class PostBody extends PureComponent {
|
|||
blockStyles={blockStyles}
|
||||
navigator={navigator}
|
||||
message={message}
|
||||
postId={postId}
|
||||
postProps={postProps}
|
||||
textStyles={textStyles}
|
||||
/>
|
||||
|
|
@ -275,6 +276,7 @@ class PostBody extends PureComponent {
|
|||
blockStyles={blockStyles}
|
||||
navigator={navigator}
|
||||
message={message}
|
||||
postId={postId}
|
||||
postProps={postProps}
|
||||
textStyles={textStyles}
|
||||
onLongPress={this.showOptionsContext}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ export default class PostBodyAdditionalContent extends PureComponent {
|
|||
navigator: PropTypes.object.isRequired,
|
||||
onLongPress: PropTypes.func,
|
||||
openGraphData: PropTypes.object,
|
||||
postId: PropTypes.string.isRequired,
|
||||
postProps: PropTypes.object.isRequired,
|
||||
showLinkPreviews: PropTypes.bool.isRequired,
|
||||
textStyles: PropTypes.object,
|
||||
|
|
@ -45,7 +46,7 @@ export default class PostBodyAdditionalContent extends PureComponent {
|
|||
|
||||
static defaultProps = {
|
||||
onLongPress: emptyFunction
|
||||
}
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
@ -152,6 +153,7 @@ export default class PostBodyAdditionalContent extends PureComponent {
|
|||
|
||||
getSlackAttachment = () => {
|
||||
const {
|
||||
postId,
|
||||
postProps,
|
||||
baseTextStyle,
|
||||
blockStyles,
|
||||
|
|
@ -168,6 +170,7 @@ export default class PostBodyAdditionalContent extends PureComponent {
|
|||
baseTextStyle={baseTextStyle}
|
||||
blockStyles={blockStyles}
|
||||
navigator={navigator}
|
||||
postId={postId}
|
||||
textStyles={textStyles}
|
||||
theme={theme}
|
||||
onLongPress={this.props.onLongPress}
|
||||
|
|
|
|||
|
|
@ -14,14 +14,15 @@ export default class SlackAttachments extends PureComponent {
|
|||
attachments: PropTypes.array.isRequired,
|
||||
baseTextStyle: CustomPropTypes.Style,
|
||||
blockStyles: PropTypes.object,
|
||||
textStyles: PropTypes.object,
|
||||
postId: PropTypes.string.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onLongPress: PropTypes.func.isRequired,
|
||||
theme: PropTypes.object,
|
||||
onLongPress: PropTypes.func.isRequired
|
||||
textStyles: PropTypes.object
|
||||
};
|
||||
|
||||
render() {
|
||||
const {attachments, baseTextStyle, blockStyles, navigator, textStyles, theme, onLongPress} = this.props;
|
||||
const {attachments, baseTextStyle, blockStyles, navigator, onLongPress, postId, theme, textStyles} = this.props;
|
||||
const content = [];
|
||||
|
||||
attachments.forEach((attachment, i) => {
|
||||
|
|
@ -31,10 +32,11 @@ export default class SlackAttachments extends PureComponent {
|
|||
baseTextStyle={baseTextStyle}
|
||||
blockStyles={blockStyles}
|
||||
key={'att_' + i}
|
||||
textStyles={textStyles}
|
||||
navigator={navigator}
|
||||
theme={theme}
|
||||
onLongPress={onLongPress}
|
||||
postId={postId}
|
||||
theme={theme}
|
||||
textStyles={textStyles}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
26
app/components/slack_attachments/interactive_action/index.js
Normal file
26
app/components/slack_attachments/interactive_action/index.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {doPostAction} from 'mattermost-redux/actions/posts';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import InteractiveAction from './interactive_action';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
theme: getTheme(state)
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
doPostAction
|
||||
}, dispatch)
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(InteractiveAction);
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
import {Text} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import Button from 'react-native-button';
|
||||
|
||||
import {wrapWithPreventDoubleTap} from 'app/utils/tap';
|
||||
import {makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
export default class InteractiveAction extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
doPostAction: PropTypes.func.isRequired
|
||||
}).isRequired,
|
||||
id: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
postId: PropTypes.string.isRequired,
|
||||
theme: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
handleActionPress = wrapWithPreventDoubleTap(() => {
|
||||
const {actions, id, postId} = this.props;
|
||||
actions.doPostAction(postId, id);
|
||||
});
|
||||
|
||||
render() {
|
||||
const {name, theme} = this.props;
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
return (
|
||||
<Button
|
||||
containerStyle={style.button}
|
||||
onPress={this.handleActionPress}
|
||||
>
|
||||
<Text style={style.text}>{name}</Text>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
button: {
|
||||
borderRadius: 2,
|
||||
backgroundColor: theme.buttonBg,
|
||||
alignItems: 'center',
|
||||
marginBottom: 2,
|
||||
marginRight: 5,
|
||||
marginTop: 10,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 7
|
||||
},
|
||||
text: {
|
||||
color: theme.buttonColor,
|
||||
fontSize: 12,
|
||||
fontWeight: '600'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
@ -10,20 +10,23 @@ import {
|
|||
View
|
||||
} from 'react-native';
|
||||
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import Markdown from 'app/components/markdown';
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import Markdown from 'app/components/markdown';
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
import InteractiveAction from './interactive_action';
|
||||
|
||||
export default class SlackAttachment extends PureComponent {
|
||||
static propTypes = {
|
||||
attachment: PropTypes.object.isRequired,
|
||||
baseTextStyle: CustomPropTypes.Style,
|
||||
blockStyles: PropTypes.object,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
textStyles: PropTypes.object,
|
||||
postId: PropTypes.string.isRequired,
|
||||
onLongPress: PropTypes.func.isRequired,
|
||||
theme: PropTypes.object,
|
||||
onLongPress: PropTypes.func.isRequired
|
||||
textStyles: PropTypes.object
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
|
|
@ -32,6 +35,37 @@ export default class SlackAttachment extends PureComponent {
|
|||
this.state = this.getInitState();
|
||||
}
|
||||
|
||||
getActionView = (style) => {
|
||||
const {attachment, postId} = this.props;
|
||||
const {actions} = attachment;
|
||||
|
||||
if (!actions || !actions.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const buttons = [];
|
||||
|
||||
actions.forEach((action) => {
|
||||
if (!action.id || !action.name) {
|
||||
return;
|
||||
}
|
||||
buttons.push(
|
||||
<InteractiveAction
|
||||
key={action.id}
|
||||
id={action.id}
|
||||
name={action.name}
|
||||
postId={postId}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={style.actionsContainer}>
|
||||
{buttons}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
getCollapsedText = () => {
|
||||
let text = this.props.attachment.text || '';
|
||||
if ((text.match(/\n/g) || []).length >= 5) {
|
||||
|
|
@ -304,6 +338,7 @@ export default class SlackAttachment extends PureComponent {
|
|||
}
|
||||
|
||||
const fields = this.getFieldsTable(style);
|
||||
const actions = this.getActionView(style);
|
||||
|
||||
let image;
|
||||
if (attachment.image_url) {
|
||||
|
|
@ -330,6 +365,7 @@ export default class SlackAttachment extends PureComponent {
|
|||
{thumb}
|
||||
{text}
|
||||
{fields}
|
||||
{actions}
|
||||
{image}
|
||||
</View>
|
||||
</View>
|
||||
|
|
@ -344,8 +380,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
borderWidth: 1,
|
||||
flex: 1,
|
||||
marginTop: 5,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 7
|
||||
padding: 10
|
||||
},
|
||||
border: {
|
||||
borderLeftColor: changeOpacity(theme.linkColor, 0.6),
|
||||
|
|
@ -366,7 +401,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
title: {
|
||||
color: theme.centerChannelColor,
|
||||
fontWeight: '600',
|
||||
marginVertical: 5
|
||||
marginBottom: 5
|
||||
},
|
||||
titleLink: {
|
||||
color: theme.linkColor
|
||||
|
|
@ -409,6 +444,10 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
image: {
|
||||
flex: 1,
|
||||
height: 50
|
||||
},
|
||||
actionsContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue