[MM-13381] Added reply to post options (#2665)
* [MM-13381] Added reply to post options * [MM-13381] Fixes for adding reply to post options * [MM-13381] Fixed logic for adding reply to post options * [MM-13381] Fixed canReply logic for post options
This commit is contained in:
parent
cd875ac3a8
commit
c3a1e3561e
12 changed files with 237 additions and 88 deletions
|
|
@ -63,6 +63,7 @@ export default class Post extends PureComponent {
|
|||
skipFlaggedHeader: PropTypes.bool,
|
||||
skipPinnedHeader: PropTypes.bool,
|
||||
isCommentMention: PropTypes.bool,
|
||||
location: PropTypes.string,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
|
@ -255,6 +256,7 @@ export default class Post extends PureComponent {
|
|||
highlightPinnedOrFlagged,
|
||||
skipFlaggedHeader,
|
||||
skipPinnedHeader,
|
||||
location,
|
||||
} = this.props;
|
||||
|
||||
if (!post) {
|
||||
|
|
@ -348,6 +350,7 @@ export default class Post extends PureComponent {
|
|||
isReplyPost={isReplyPost}
|
||||
showAddReaction={showAddReaction}
|
||||
showLongPost={showLongPost}
|
||||
location={location}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ export default class PostBody extends PureComponent {
|
|||
isEmojiOnly: PropTypes.bool.isRequired,
|
||||
shouldRenderJumboEmoji: PropTypes.bool.isRequired,
|
||||
theme: PropTypes.object,
|
||||
location: PropTypes.string,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
|
@ -149,6 +150,7 @@ export default class PostBody extends PureComponent {
|
|||
navigator,
|
||||
postId,
|
||||
showAddReaction,
|
||||
location,
|
||||
} = this.props;
|
||||
|
||||
if (isSystemMessage && (!canDelete || hasBeenDeleted)) {
|
||||
|
|
@ -178,6 +180,7 @@ export default class PostBody extends PureComponent {
|
|||
postId,
|
||||
managedConfig,
|
||||
showAddReaction,
|
||||
location,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ export default class PostListBase extends PureComponent {
|
|||
onPostPress,
|
||||
renderReplies,
|
||||
shouldRenderReplyButton,
|
||||
location,
|
||||
} = this.props;
|
||||
const {managedConfig} = this.state;
|
||||
|
||||
|
|
@ -190,6 +191,7 @@ export default class PostListBase extends PureComponent {
|
|||
onPress={onPostPress}
|
||||
navigator={navigator}
|
||||
managedConfig={managedConfig}
|
||||
location={location}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,42 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`PostOptions should match snapshot, no option for system message to user who doesn't have the permission to delete 1`] = `null`;
|
||||
exports[`PostOptions should match snapshot, no option for system message to user who doesn't have the permission to delete 1`] = `
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<Connect(SlideUpPanel)
|
||||
allowStayMiddle={false}
|
||||
initialPosition={274}
|
||||
marginFromTop={326}
|
||||
onRequestClose={[Function]}
|
||||
>
|
||||
<PostOption
|
||||
icon="edit"
|
||||
onPress={[Function]}
|
||||
text="Edit"
|
||||
/>
|
||||
<PostOption
|
||||
icon="reply"
|
||||
onPress={[Function]}
|
||||
text="Reply"
|
||||
/>
|
||||
<PostOption
|
||||
icon="pin"
|
||||
onPress={[Function]}
|
||||
text="Pin to Channel"
|
||||
/>
|
||||
<PostOption
|
||||
icon="emoji"
|
||||
onPress={[Function]}
|
||||
text="Add Reaction"
|
||||
/>
|
||||
</Connect(SlideUpPanel)>
|
||||
</View>
|
||||
`;
|
||||
|
||||
exports[`PostOptions should match snapshot, showing Delete option only for system message to user who has permission to delete 1`] = `
|
||||
<View
|
||||
|
|
@ -12,10 +48,30 @@ exports[`PostOptions should match snapshot, showing Delete option only for syste
|
|||
>
|
||||
<Connect(SlideUpPanel)
|
||||
allowStayMiddle={false}
|
||||
initialPosition={124}
|
||||
marginFromTop={476}
|
||||
initialPosition={324}
|
||||
marginFromTop={276}
|
||||
onRequestClose={[Function]}
|
||||
>
|
||||
<PostOption
|
||||
icon="edit"
|
||||
onPress={[Function]}
|
||||
text="Edit"
|
||||
/>
|
||||
<PostOption
|
||||
icon="reply"
|
||||
onPress={[Function]}
|
||||
text="Reply"
|
||||
/>
|
||||
<PostOption
|
||||
icon="pin"
|
||||
onPress={[Function]}
|
||||
text="Pin to Channel"
|
||||
/>
|
||||
<PostOption
|
||||
icon="emoji"
|
||||
onPress={[Function]}
|
||||
text="Add Reaction"
|
||||
/>
|
||||
<PostOption
|
||||
destructive={true}
|
||||
icon="trash"
|
||||
|
|
@ -36,8 +92,8 @@ exports[`PostOptions should match snapshot, showing all possible options 1`] = `
|
|||
>
|
||||
<Connect(SlideUpPanel)
|
||||
allowStayMiddle={false}
|
||||
initialPosition={424}
|
||||
marginFromTop={176}
|
||||
initialPosition={324}
|
||||
marginFromTop={276}
|
||||
onRequestClose={[Function]}
|
||||
>
|
||||
<PostOption
|
||||
|
|
@ -46,9 +102,9 @@ exports[`PostOptions should match snapshot, showing all possible options 1`] = `
|
|||
text="Edit"
|
||||
/>
|
||||
<PostOption
|
||||
icon="flag"
|
||||
icon="reply"
|
||||
onPress={[Function]}
|
||||
text="Flag"
|
||||
text="Reply"
|
||||
/>
|
||||
<PostOption
|
||||
icon="pin"
|
||||
|
|
@ -60,16 +116,6 @@ exports[`PostOptions should match snapshot, showing all possible options 1`] = `
|
|||
onPress={[Function]}
|
||||
text="Add Reaction"
|
||||
/>
|
||||
<PostOption
|
||||
icon="link"
|
||||
onPress={[Function]}
|
||||
text="Copy Permalink"
|
||||
/>
|
||||
<PostOption
|
||||
icon="copy"
|
||||
onPress={[Function]}
|
||||
text="Copy Text"
|
||||
/>
|
||||
<PostOption
|
||||
destructive={true}
|
||||
icon="trash"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
unflagPost,
|
||||
unpinPost,
|
||||
removePost,
|
||||
selectPost,
|
||||
} from 'mattermost-redux/actions/posts';
|
||||
import {General, Permissions} from 'mattermost-redux/constants';
|
||||
import {getChannel, getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
||||
|
|
@ -22,6 +23,8 @@ import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles'
|
|||
import {getCurrentTeamId, getCurrentTeamUrl} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {canEditPost} from 'mattermost-redux/utils/post_utils';
|
||||
|
||||
import {loadThreadIfNecessary} from 'app/actions/views/channel';
|
||||
import {THREAD} from 'app/constants/screen';
|
||||
import {addReaction} from 'app/actions/views/emoji';
|
||||
import {getDimensions} from 'app/selectors/device';
|
||||
|
||||
|
|
@ -39,9 +42,13 @@ function mapStateToProps(state, ownProps) {
|
|||
const channelIsArchived = channel.delete_at !== 0;
|
||||
|
||||
let canAddReaction = true;
|
||||
let canReply = true;
|
||||
let canCopyPermalink = true;
|
||||
let canCopyText = false;
|
||||
let canEdit = false;
|
||||
let canEditUntil = -1;
|
||||
let {canDelete} = ownProps;
|
||||
let canFlag = true;
|
||||
let canPin = true;
|
||||
|
||||
if (hasNewPermissions(state)) {
|
||||
|
|
@ -52,8 +59,13 @@ function mapStateToProps(state, ownProps) {
|
|||
});
|
||||
}
|
||||
|
||||
if (channelIsArchived) {
|
||||
if (ownProps.location === THREAD) {
|
||||
canReply = false;
|
||||
}
|
||||
|
||||
if (channelIsArchived || ownProps.channelIsReadOnly) {
|
||||
canAddReaction = false;
|
||||
canReply = false;
|
||||
canDelete = false;
|
||||
canPin = false;
|
||||
} else {
|
||||
|
|
@ -65,12 +77,39 @@ function mapStateToProps(state, ownProps) {
|
|||
}
|
||||
}
|
||||
|
||||
if (ownProps.channelIsReadOnly) {
|
||||
canFlag = false;
|
||||
}
|
||||
|
||||
if (ownProps.isSystemMessage) {
|
||||
canAddReaction = false;
|
||||
canReply = false;
|
||||
canCopyPermalink = false;
|
||||
canEdit = false;
|
||||
canPin = false;
|
||||
}
|
||||
if (ownProps.hasBeenDeleted) {
|
||||
canDelete = false;
|
||||
}
|
||||
|
||||
if (!ownProps.showAddReaction) {
|
||||
canAddReaction = false;
|
||||
}
|
||||
|
||||
if (!ownProps.isSystemMessage && ownProps.managedConfig.copyAndPasteProtection !== 'true' && post.message) {
|
||||
canCopyText = true;
|
||||
}
|
||||
|
||||
return {
|
||||
...getDimensions(state),
|
||||
canAddReaction,
|
||||
canReply,
|
||||
canCopyPermalink,
|
||||
canCopyText,
|
||||
canEdit,
|
||||
canEditUntil,
|
||||
canDelete,
|
||||
canFlag,
|
||||
canPin,
|
||||
currentTeamUrl: getCurrentTeamUrl(state),
|
||||
isMyPost: currentUserId === post.user_id,
|
||||
|
|
@ -89,6 +128,8 @@ function mapDispatchToProps(dispatch) {
|
|||
removePost,
|
||||
unflagPost,
|
||||
unpinPost,
|
||||
selectPost,
|
||||
loadThreadIfNecessary,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import flag from 'assets/images/post_menu/flag.png';
|
|||
import link from 'assets/images/post_menu/link.png';
|
||||
import pin from 'assets/images/post_menu/pin.png';
|
||||
import trash from 'assets/images/post_menu/trash.png';
|
||||
import reply from 'assets/images/post_menu/reply.png';
|
||||
|
||||
const icons = {
|
||||
copy,
|
||||
|
|
@ -29,6 +30,7 @@ const icons = {
|
|||
link,
|
||||
pin,
|
||||
trash,
|
||||
reply,
|
||||
};
|
||||
|
||||
export default class PostOption extends PureComponent {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Alert, Clipboard, StyleSheet, View} from 'react-native';
|
||||
import {Alert, Clipboard, Platform, StyleSheet, View} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
|
|
@ -23,23 +23,24 @@ export default class PostOptions extends PureComponent {
|
|||
removePost: PropTypes.func.isRequired,
|
||||
unflagPost: PropTypes.func.isRequired,
|
||||
unpinPost: PropTypes.func.isRequired,
|
||||
selectPost: PropTypes.func.isRequired,
|
||||
loadThreadIfNecessary: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
canAddReaction: PropTypes.bool,
|
||||
canReply: PropTypes.bool,
|
||||
canCopyPermalink: PropTypes.bool,
|
||||
canCopyText: PropTypes.bool,
|
||||
canDelete: PropTypes.bool,
|
||||
canFlag: PropTypes.bool,
|
||||
canPin: PropTypes.bool,
|
||||
canEdit: PropTypes.bool,
|
||||
canEditUntil: PropTypes.number.isRequired,
|
||||
channelIsReadOnly: PropTypes.bool,
|
||||
currentTeamUrl: PropTypes.string.isRequired,
|
||||
deviceHeight: PropTypes.number.isRequired,
|
||||
hasBeenDeleted: PropTypes.bool,
|
||||
isFlagged: PropTypes.bool,
|
||||
isMyPost: PropTypes.bool,
|
||||
isSystemMessage: PropTypes.bool,
|
||||
managedConfig: PropTypes.object.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
post: PropTypes.object.isRequired,
|
||||
showAddReaction: PropTypes.bool,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
|
|
@ -63,9 +64,9 @@ export default class PostOptions extends PureComponent {
|
|||
|
||||
getAddReactionOption = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {canAddReaction, channelIsReadOnly, isSystemMessage, showAddReaction} = this.props;
|
||||
const {canAddReaction} = this.props;
|
||||
|
||||
if (!isSystemMessage && showAddReaction && canAddReaction && !channelIsReadOnly) {
|
||||
if (canAddReaction) {
|
||||
return (
|
||||
<PostOption
|
||||
key='reaction'
|
||||
|
|
@ -79,28 +80,47 @@ export default class PostOptions extends PureComponent {
|
|||
return null;
|
||||
};
|
||||
|
||||
getCopyPermalink = () => {
|
||||
if (this.props.isSystemMessage) {
|
||||
return null;
|
||||
getReplyOption = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {canReply} = this.props;
|
||||
|
||||
if (canReply) {
|
||||
return (
|
||||
<PostOption
|
||||
key='reply'
|
||||
icon='reply'
|
||||
text={formatMessage({id: 'mobile.post_info.reply', defaultMessage: 'Reply'})}
|
||||
onPress={this.handleReply}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const {formatMessage} = this.context.intl;
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<PostOption
|
||||
key='permalink'
|
||||
icon='link'
|
||||
text={formatMessage({id: 'get_post_link_modal.title', defaultMessage: 'Copy Permalink'})}
|
||||
onPress={this.handleCopyPermalink}
|
||||
/>
|
||||
);
|
||||
getCopyPermalink = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {canCopyPermalink} = this.props;
|
||||
|
||||
if (canCopyPermalink) {
|
||||
return (
|
||||
<PostOption
|
||||
key='permalink'
|
||||
icon='link'
|
||||
text={formatMessage({id: 'get_post_link_modal.title', defaultMessage: 'Copy Permalink'})}
|
||||
onPress={this.handleCopyPermalink}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
getCopyText = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {isSystemMessage, managedConfig, post} = this.props;
|
||||
const {canCopyText} = this.props;
|
||||
|
||||
if (!isSystemMessage && managedConfig.copyAndPasteProtection !== 'true' && post.message) {
|
||||
if (canCopyText) {
|
||||
return (
|
||||
<PostOption
|
||||
key='copy'
|
||||
|
|
@ -116,9 +136,9 @@ export default class PostOptions extends PureComponent {
|
|||
|
||||
getDeleteOption = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {canDelete, hasBeenDeleted} = this.props;
|
||||
const {canDelete} = this.props;
|
||||
|
||||
if (canDelete && !hasBeenDeleted) {
|
||||
if (canDelete) {
|
||||
return (
|
||||
<PostOption
|
||||
destructive={true}
|
||||
|
|
@ -135,9 +155,9 @@ export default class PostOptions extends PureComponent {
|
|||
|
||||
getEditOption = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {canEdit, canEditUntil, isSystemMessage} = this.props;
|
||||
const {canEdit, canEditUntil} = this.props;
|
||||
|
||||
if (!isSystemMessage && canEdit && (canEditUntil === -1 || canEditUntil > Date.now())) {
|
||||
if (canEdit && (canEditUntil === -1 || canEditUntil > Date.now())) {
|
||||
return (
|
||||
<PostOption
|
||||
key='edit'
|
||||
|
|
@ -153,9 +173,9 @@ export default class PostOptions extends PureComponent {
|
|||
|
||||
getFlagOption = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {channelIsReadOnly, isFlagged, isSystemMessage} = this.props;
|
||||
const {canFlag, isFlagged} = this.props;
|
||||
|
||||
if (isSystemMessage || channelIsReadOnly) {
|
||||
if (!canFlag) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -182,9 +202,9 @@ export default class PostOptions extends PureComponent {
|
|||
|
||||
getPinOption = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {channelIsReadOnly, isSystemMessage, post} = this.props;
|
||||
const {canPin, post} = this.props;
|
||||
|
||||
if (isSystemMessage || channelIsReadOnly) {
|
||||
if (!canPin) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -212,51 +232,37 @@ export default class PostOptions extends PureComponent {
|
|||
getMyPostOptions = () => {
|
||||
const actions = [
|
||||
this.getEditOption(),
|
||||
this.getReplyOption(),
|
||||
this.getFlagOption(),
|
||||
this.getPinOption(),
|
||||
this.getAddReactionOption(),
|
||||
this.getCopyPermalink(),
|
||||
this.getCopyText(),
|
||||
this.getDeleteOption(),
|
||||
];
|
||||
|
||||
const {canDelete, canPin} = this.props;
|
||||
if (canPin) {
|
||||
actions.splice(2, 0, this.getPinOption());
|
||||
}
|
||||
if (canDelete) {
|
||||
actions.push(this.getDeleteOption());
|
||||
}
|
||||
|
||||
return actions.filter((a) => a !== null);
|
||||
};
|
||||
|
||||
getOthersPostOptions = () => {
|
||||
const actions = [
|
||||
this.getReplyOption(),
|
||||
this.getFlagOption(),
|
||||
this.getAddReactionOption(),
|
||||
this.getPinOption(),
|
||||
this.getCopyPermalink(),
|
||||
this.getCopyText(),
|
||||
this.getEditOption(),
|
||||
this.getDeleteOption(),
|
||||
];
|
||||
|
||||
const {canDelete, canPin} = this.props;
|
||||
if (canPin) {
|
||||
actions.splice(2, 0, this.getPinOption());
|
||||
}
|
||||
if (canDelete) {
|
||||
actions.push(this.getDeleteOption());
|
||||
}
|
||||
|
||||
return actions.filter((a) => a !== null);
|
||||
};
|
||||
|
||||
getPostOptions = () => {
|
||||
const {isMyPost} = this.props;
|
||||
|
||||
if (isMyPost) {
|
||||
return this.getMyPostOptions();
|
||||
}
|
||||
|
||||
return this.getOthersPostOptions();
|
||||
return isMyPost ? this.getMyPostOptions() : this.getOthersPostOptions();
|
||||
};
|
||||
|
||||
handleAddReaction = () => {
|
||||
|
|
@ -285,6 +291,37 @@ export default class PostOptions extends PureComponent {
|
|||
});
|
||||
};
|
||||
|
||||
handleReply = () => {
|
||||
const {actions, post, navigator, theme} = this.props;
|
||||
const rootId = (post.root_id || post.id);
|
||||
const channelId = post.channel_id;
|
||||
|
||||
actions.loadThreadIfNecessary(rootId, channelId);
|
||||
actions.selectPost(rootId);
|
||||
|
||||
const options = {
|
||||
screen: 'Thread',
|
||||
animated: true,
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
channelId,
|
||||
rootId,
|
||||
},
|
||||
};
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
navigator.showModal(options);
|
||||
} else {
|
||||
navigator.push(options);
|
||||
}
|
||||
}
|
||||
|
||||
handleAddReactionToPost = (emoji) => {
|
||||
const {actions, post} = this.props;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ describe('PostOptions', () => {
|
|||
const navigator = {
|
||||
showModal: jest.fn(),
|
||||
dismissModal: jest.fn(),
|
||||
push: jest.fn(),
|
||||
};
|
||||
|
||||
const actions = {
|
||||
|
|
@ -24,16 +25,22 @@ describe('PostOptions', () => {
|
|||
removePost: jest.fn(),
|
||||
unflagPost: jest.fn(),
|
||||
unpinPost: jest.fn(),
|
||||
selectPost: jest.fn(),
|
||||
loadThreadIfNecessary: jest.fn(),
|
||||
};
|
||||
|
||||
const post = {
|
||||
root_id: 'root_id',
|
||||
id: 'post_id',
|
||||
message: 'message',
|
||||
is_pinned: false,
|
||||
channel_id: 'channel_id',
|
||||
};
|
||||
|
||||
const baseProps = {
|
||||
actions,
|
||||
canAddReaction: true,
|
||||
canReply: true,
|
||||
canDelete: true,
|
||||
canPin: true,
|
||||
canEdit: true,
|
||||
|
|
@ -52,37 +59,44 @@ describe('PostOptions', () => {
|
|||
theme: Preferences.THEMES.default,
|
||||
};
|
||||
|
||||
test('should match snapshot, showing all possible options', () => {
|
||||
const wrapper = shallow(
|
||||
<PostOptions {...baseProps}/>,
|
||||
{context: {intl: {formatMessage: jest.fn((format) => format.defaultMessage)}}},
|
||||
function getWrapper(props = {}) {
|
||||
return shallow(
|
||||
<PostOptions
|
||||
{...baseProps}
|
||||
{...props}
|
||||
/>,
|
||||
{context: {intl: {formatMessage: ({defaultMessage}) => defaultMessage}}}
|
||||
);
|
||||
}
|
||||
|
||||
test('should match snapshot, showing all possible options', () => {
|
||||
const wrapper = getWrapper();
|
||||
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match snapshot, showing Delete option only for system message to user who has permission to delete', () => {
|
||||
const wrapper = shallow(
|
||||
<PostOptions
|
||||
{...baseProps}
|
||||
isSystemMessage={true}
|
||||
/>,
|
||||
{context: {intl: {formatMessage: jest.fn((format) => format.defaultMessage)}}},
|
||||
);
|
||||
const wrapper = getWrapper({isSystemMessage: true});
|
||||
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should match snapshot, no option for system message to user who doesn\'t have the permission to delete', () => {
|
||||
const wrapper = shallow(
|
||||
<PostOptions
|
||||
{...baseProps}
|
||||
isSystemMessage={true}
|
||||
canDelete={false}
|
||||
/>,
|
||||
{context: {intl: {formatMessage: jest.fn((format) => format.defaultMessage)}}},
|
||||
);
|
||||
const wrapper = getWrapper({isSystemMessage: true, canDelete: false});
|
||||
|
||||
expect(wrapper.getElement()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should load thread', () => {
|
||||
const wrapper = getWrapper();
|
||||
|
||||
wrapper.findWhere((node) => node.key() === 'reply').simulate('press');
|
||||
expect(actions.loadThreadIfNecessary).toBeCalled();
|
||||
});
|
||||
|
||||
test('should not show reply option', () => {
|
||||
const wrapper = getWrapper({canReply: false});
|
||||
|
||||
expect(wrapper.findWhere((node) => node.key() === 'reply')).toMatchObject({});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -339,6 +339,7 @@
|
|||
"mobile.post_info.flag": "Flag",
|
||||
"mobile.post_info.unflag": "Unflag",
|
||||
"mobile.post_info.pin": "Pin to Channel",
|
||||
"mobile.post_info.reply": "Reply",
|
||||
"mobile.post_info.unpin": "Unpin from Channel",
|
||||
"mobile.post_pre_header.flagged": "Flagged",
|
||||
"mobile.post_pre_header.pinned_flagged": "Pinned and Flagged",
|
||||
|
|
|
|||
BIN
assets/base/images/post_menu/reply.png
Normal file
BIN
assets/base/images/post_menu/reply.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 380 B |
BIN
assets/base/images/post_menu/reply@2x.png
Normal file
BIN
assets/base/images/post_menu/reply@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 737 B |
BIN
assets/base/images/post_menu/reply@3x.png
Normal file
BIN
assets/base/images/post_menu/reply@3x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1 KiB |
Loading…
Reference in a new issue