RN-360 Add support for interactive message buttons (#1131)

This commit is contained in:
enahum 2017-11-13 13:52:43 -03:00 committed by Jarred Witt
parent a299cdb5c5
commit d7622eb7a4
7 changed files with 147 additions and 14 deletions

View file

@ -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;
}

View file

@ -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}

View file

@ -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}

View file

@ -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}
/>
);
});

View 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);

View file

@ -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'
}
};
});

View file

@ -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'
}
};
});