diff --git a/app/components/at_mention/at_mention.js b/app/components/at_mention/at_mention.js index f56242dd7..cbf5744e8 100644 --- a/app/components/at_mention/at_mention.js +++ b/app/components/at_mention/at_mention.js @@ -8,6 +8,8 @@ import {intlShape} from 'react-intl'; import {displayUsername} from 'mattermost-redux/utils/user_utils'; +import {emptyFunction} from 'app/utils/general'; + import CustomPropTypes from 'app/constants/custom_prop_types'; import mattermostManaged from 'app/mattermost_managed'; @@ -25,6 +27,10 @@ export default class AtMention extends React.PureComponent { usersByUsername: PropTypes.object.isRequired, }; + static defaultProps = { + onLongPress: emptyFunction, + }; + static contextTypes = { intl: intlShape, }; diff --git a/app/components/combined_system_message/__snapshots__/combined_system_message.test.js.snap b/app/components/combined_system_message/__snapshots__/combined_system_message.test.js.snap deleted file mode 100644 index aae08f4aa..000000000 --- a/app/components/combined_system_message/__snapshots__/combined_system_message.test.js.snap +++ /dev/null @@ -1,89 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CombinedSystemMessage should match snapshot 1`] = ` - - - - - - - -`; - -exports[`CombinedSystemMessage should match snapshot 2`] = ` - - - - - - . - -`; diff --git a/app/components/combined_system_message/__snapshots__/last_users.test.js.snap b/app/components/combined_system_message/__snapshots__/last_users.test.js.snap deleted file mode 100644 index 74304767d..000000000 --- a/app/components/combined_system_message/__snapshots__/last_users.test.js.snap +++ /dev/null @@ -1,117 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`LastUsers should match snapshot 1`] = ` - - - - - - - -`; - -exports[`LastUsers should match snapshot 2`] = ` - - - - - - - - - - - -`; diff --git a/app/components/combined_system_message/combined_system_message.js b/app/components/combined_system_message/combined_system_message.js index 7bb790121..52ee86612 100644 --- a/app/components/combined_system_message/combined_system_message.js +++ b/app/components/combined_system_message/combined_system_message.js @@ -3,17 +3,13 @@ import PropTypes from 'prop-types'; import React from 'react'; -import {Text} from 'react-native'; import {intlShape} from 'react-intl'; import {Posts} from 'mattermost-redux/constants'; -import {displayUsername} from 'mattermost-redux/utils/user_utils'; - -import CustomPropTypes from 'app/constants/custom_prop_types'; import {makeStyleSheetFromTheme} from 'app/utils/theme'; -import FormattedText from 'app/components/formatted_text'; +import Markdown from 'app/components/markdown'; import LastUsers from './last_users'; @@ -25,130 +21,130 @@ const { const postTypeMessage = { [JOIN_CHANNEL]: { one: { - id: ['mobile.combined_system_message.first_user', 'mobile.combined_system_message.joined_channel'], - defaultMessage: ['{firstUser} ', 'joined the channel'], + id: 'combined_system_message.joined_channel.one', + defaultMessage: '{firstUser} **joined the channel**.', }, two: { - id: ['mobile.combined_system_message.first_user_and_second_user', 'mobile.combined_system_message.joined_channel'], - defaultMessage: ['{firstUser} and {secondUser} ', 'joined the channel'], + id: 'combined_system_message.joined_channel.two', + defaultMessage: '{firstUser} and {secondUser} **joined the channel**.', }, many_expanded: { - id: ['mobile.combined_system_message.users_and_last_user', 'mobile.combined_system_message.joined_channel'], - defaultMessage: ['{users} and {lastUser} ', 'joined the channel'], + id: 'combined_system_message.joined_channel.many_expanded', + defaultMessage: '{users} and {lastUser} **joined the channel**.', }, }, [ADD_TO_CHANNEL]: { one: { - id: ['mobile.combined_system_message.first_user', 'mobile.combined_system_message.added_to_channel', 'mobile.combined_system_message.by_actor'], - defaultMessage: ['{firstUser} ', 'added to the channel', ' by {actor}.'], + id: 'combined_system_message.added_to_channel.one', + defaultMessage: '{firstUser} **added to the channel** by {actor}.', }, one_you: { - id: ['mobile.combined_system_message.you_were', 'mobile.combined_system_message.added_to_channel', 'mobile.combined_system_message.by_actor'], - defaultMessage: ['You were ', 'added to the channel', ' by {actor}.'], + id: 'combined_system_message.added_to_channel.one_you', + defaultMessage: 'You were **added to the channel** by {actor}.', }, two: { - id: ['mobile.combined_system_message.first_user_and_second_user', 'mobile.combined_system_message.added_to_channel', 'mobile.combined_system_message.by_actor'], - defaultMessage: ['{firstUser} and {secondUser} ', 'added to the channel', ' by {actor}.'], + id: 'combined_system_message.added_to_channel.two', + defaultMessage: '{firstUser} and {secondUser} **added to the channel** by {actor}.', }, many_expanded: { - id: ['mobile.combined_system_message.users_and_last_user', 'mobile.combined_system_message.added_to_channel', 'mobile.combined_system_message.by_actor'], - defaultMessage: ['{users} and {lastUser} ', 'added to the channel', ' by {actor}.'], + id: 'combined_system_message.added_to_channel.many_expanded', + defaultMessage: '{users} and {lastUser} were **added to the channel** by {actor}.', }, }, [REMOVE_FROM_CHANNEL]: { one: { - id: ['mobile.combined_system_message.first_user_was', 'mobile.combined_system_message.removed_from_channel'], - defaultMessage: ['{firstUser} was ', 'removed from the channel'], + id: 'combined_system_message.removed_from_channel.one', + defaultMessage: '{firstUser} was **removed from the channel**.', }, one_you: { - id: ['mobile.combined_system_message.you_were', 'mobile.combined_system_message.removed_from_channel'], - defaultMessage: ['You were ', 'removed from the channel'], + id: 'combined_system_message.removed_from_channel.one_you', + defaultMessage: 'You were **removed from the channel**.', }, two: { - id: ['mobile.combined_system_message.first_user_and_second_user_were', 'mobile.combined_system_message.removed_from_channel'], - defaultMessage: ['{firstUser} and {secondUser} were ', 'removed from the channel'], + id: 'combined_system_message.removed_from_channel.two', + defaultMessage: '{firstUser} and {secondUser} were **removed from the channel**.', }, many_expanded: { - id: ['mobile.combined_system_message.users_and_last_user_were', 'mobile.combined_system_message.removed_from_channel'], - defaultMessage: ['{users} and {lastUser} were ', 'removed from the channel'], + id: 'combined_system_message.removed_from_channel.many_expanded', + defaultMessage: '{users} and {lastUser} were **removed from the channel**.', }, }, [LEAVE_CHANNEL]: { one: { - id: ['mobile.combined_system_message.first_user', 'mobile.combined_system_message.left_channel'], - defaultMessage: ['{firstUser} ', 'left the channel'], + id: 'combined_system_message.left_channel.one', + defaultMessage: '{firstUser} **left the channel**.', }, two: { - id: ['mobile.combined_system_message.first_user_and_second_user', 'mobile.combined_system_message.left_channel'], - defaultMessage: ['{firstUser} and {secondUser} ', 'left the channel'], + id: 'combined_system_message.left_channel.two', + defaultMessage: '{firstUser} and {secondUser} **left the channel**.', }, many_expanded: { - id: ['mobile.combined_system_message.users_and_last_user', 'mobile.combined_system_message.left_channel'], - defaultMessage: ['{users} and {lastUser} ', 'left the channel'], + id: 'combined_system_message.left_channel.many_expanded', + defaultMessage: '{users} and {lastUser} **left the channel**.', }, }, [JOIN_TEAM]: { one: { - id: ['mobile.combined_system_message.first_user', 'mobile.combined_system_message.joined_team'], - defaultMessage: ['{firstUser} ', 'joined the team'], + id: 'combined_system_message.joined_team.one', + defaultMessage: '{firstUser} **joined the team**.', }, two: { - id: ['mobile.combined_system_message.first_user_and_second_user', 'mobile.combined_system_message.joined_team'], - defaultMessage: ['{firstUser} and {secondUser} ', 'joined the team'], + id: 'combined_system_message.joined_team.two', + defaultMessage: '{firstUser} and {secondUser} **joined the team**.', }, many_expanded: { - id: ['mobile.combined_system_message.users_and_last_user', 'mobile.combined_system_message.joined_team'], - defaultMessage: ['{users} and {lastUser} ', 'joined the team'], + id: 'combined_system_message.joined_team.many_expanded', + defaultMessage: '{users} and {lastUser} **joined the team**.', }, }, [ADD_TO_TEAM]: { one: { - id: ['mobile.combined_system_message.first_user', 'mobile.combined_system_message.added_to_team', 'mobile.combined_system_message.by_actor'], - defaultMessage: ['{firstUser} ', 'added to the team', ' by {actor}.'], + id: 'combined_system_message.added_to_team.one', + defaultMessage: '{firstUser} **added to the team** by {actor}.', }, one_you: { - id: ['mobile.combined_system_message.you_were', 'mobile.combined_system_message.added_to_team', 'mobile.combined_system_message.by_actor'], - defaultMessage: ['You were ', 'added to the team', ' by {actor}.'], + id: 'combined_system_message.added_to_team.one_you', + defaultMessage: 'You were **added to the team** by {actor}.', }, two: { - id: ['mobile.combined_system_message.first_user_and_second_user', 'mobile.combined_system_message.added_to_team', 'mobile.combined_system_message.by_actor'], - defaultMessage: ['{firstUser} and {secondUser} ', 'added to the team', ' by {actor}.'], + id: 'combined_system_message.added_to_team.two', + defaultMessage: '{firstUser} and {secondUser} **added to the team** by {actor}.', }, many_expanded: { - id: ['mobile.combined_system_message.users_and_last_user', 'mobile.combined_system_message.added_to_team', 'mobile.combined_system_message.by_actor'], - defaultMessage: ['{users} and {lastUser} ', 'added to the team', ' by {actor}.'], + id: 'combined_system_message.added_to_team.many_expanded', + defaultMessage: '{users} and {lastUser} were **added to the team** by {actor}.', }, }, [REMOVE_FROM_TEAM]: { one: { - id: ['mobile.combined_system_message.first_user_was', 'mobile.combined_system_message.removed_from_team'], - defaultMessage: ['{firstUser} was ', 'removed from the team'], + id: 'combined_system_message.removed_from_team.one', + defaultMessage: '{firstUser} was **removed from the team**.', }, one_you: { - id: ['mobile.combined_system_message.you_were', 'mobile.combined_system_message.removed_from_team'], - defaultMessage: ['You were ', 'removed from the team'], + id: 'combined_system_message.removed_from_team.one_you', + defaultMessage: 'You were **removed from the team**.', }, two: { - id: ['mobile.combined_system_message.first_user_and_second_user_were', 'mobile.combined_system_message.removed_from_team'], - defaultMessage: ['{firstUser} and {secondUser} were ', 'removed from the team'], + id: 'combined_system_message.removed_from_team.two', + defaultMessage: '{firstUser} and {secondUser} were **removed from the team**.', }, many_expanded: { - id: ['mobile.combined_system_message.users_and_last_user_were', 'mobile.combined_system_message.removed_from_team'], - defaultMessage: ['{users} and {lastUser} were ', 'removed from the team'], + id: 'combined_system_message.removed_from_team.many_expanded', + defaultMessage: '{users} and {lastUser} were **removed from the team**.', }, }, [LEAVE_TEAM]: { one: { - id: ['mobile.combined_system_message.first_user', 'mobile.combined_system_message.left_team'], - defaultMessage: ['{firstUser} ', 'left the team'], + id: 'combined_system_message.left_team.one', + defaultMessage: '{firstUser} **left the team**.', }, two: { - id: ['mobile.combined_system_message.first_user_and_second_user', 'mobile.combined_system_message.left_team'], - defaultMessage: ['{firstUser} and {secondUser} ', 'left the team'], + id: 'combined_system_message.left_team.two', + defaultMessage: '{firstUser} and {secondUser} **left the team**.', }, many_expanded: { - id: ['mobile.combined_system_message.users_and_last_user', 'mobile.combined_system_message.left_team'], - defaultMessage: ['{users} and {lastUser} ', 'left the team'], + id: 'combined_system_message.left_team.many_expanded', + defaultMessage: '{users} and {lastUser} **left the team**.', }, }, }; @@ -163,10 +159,10 @@ export default class CombinedSystemMessage extends React.PureComponent { allUsernames: PropTypes.array.isRequired, currentUserId: PropTypes.string.isRequired, currentUsername: PropTypes.string.isRequired, - linkStyle: CustomPropTypes.Style, messageData: PropTypes.array.isRequired, + navigator: PropTypes.object.isRequired, showJoinLeave: PropTypes.bool.isRequired, - teammateNameDisplay: PropTypes.string.isRequired, + textStyles: PropTypes.object, theme: PropTypes.object.isRequired, userProfiles: PropTypes.array.isRequired, }; @@ -184,9 +180,10 @@ export default class CombinedSystemMessage extends React.PureComponent { this.loadUserProfiles(this.props.allUserIds, this.props.allUsernames); } - componentWillReceiveProps(nextProps) { - if (this.props.allUserIds !== nextProps.allUserIds || this.props.allUsernames !== nextProps.allUsernames) { - this.loadUserProfiles(nextProps.allUserIds, nextProps.allUsernames); + componentDidUpdate(prevProps) { + const {allUserIds, allUsernames} = this.props; + if (allUserIds !== prevProps.allUserIds || allUsernames !== prevProps.allUsernames) { + this.loadUserProfiles(allUserIds, allUsernames); } } @@ -200,146 +197,115 @@ export default class CombinedSystemMessage extends React.PureComponent { } } - getAllUsersDisplayName = () => { + getAllUsernames = () => { const { allUserIds, allUsernames, currentUserId, currentUsername, - teammateNameDisplay, userProfiles, } = this.props; const {formatMessage} = this.context.intl; - const usersDisplayName = userProfiles.reduce((acc, user) => { - const displayName = displayUsername(user, teammateNameDisplay, true); - acc[user.id] = displayName; - acc[user.username] = displayName; + const usernames = userProfiles.reduce((acc, user) => { + acc[user.id] = user.username; + acc[user.username] = user.username; return acc; }, {}); + const currentUserDisplayName = formatMessage({id: 'combined_system_message.you', defaultMessage: 'You'}); if (allUserIds.includes(currentUserId)) { - usersDisplayName[currentUserId] = formatMessage({id: 'mobile.combined_system_message.you', defaultMessage: 'You'}); + usernames[currentUserId] = currentUserDisplayName; } else if (allUsernames.includes(currentUsername)) { - usersDisplayName[currentUsername] = formatMessage({id: 'mobile.combined_system_message.you', defaultMessage: 'You'}); + usernames[currentUsername] = currentUserDisplayName; } - return usersDisplayName; + return usernames; } - getDisplayNameByIds = (userIds = []) => { + getUsernamesByIds = (userIds = []) => { const {currentUserId, currentUsername} = this.props; - const usersDisplayName = this.getAllUsersDisplayName(); - const displayNames = userIds. + const allUsernames = this.getAllUsernames(); + const usernames = userIds. filter((userId) => { - return ( - usersDisplayName[userId] && - userId !== currentUserId && - userId !== currentUsername - ); + return userId !== currentUserId && userId !== currentUsername; }). map((userId) => { - return usersDisplayName[userId]; - }).filter((displayName) => { - return displayName && displayName !== ''; + return `@${allUsernames[userId]}`; + }).filter((username) => { + return username && username !== ''; }); if (userIds.includes(currentUserId)) { - displayNames.unshift(usersDisplayName[currentUserId]); + usernames.unshift(allUsernames[currentUserId]); } else if (userIds.includes(currentUsername)) { - displayNames.unshift(usersDisplayName[currentUsername]); + usernames.unshift(allUsernames[currentUsername]); } - return displayNames; + return usernames; } - renderSystemMessage(postType, userIds, actorId, style) { - const {currentUserId, currentUsername} = this.props; - const usersDisplayName = this.getDisplayNameByIds(userIds); - let actorDisplayName = actorId ? this.getDisplayNameByIds([actorId])[0] : ''; - if (actorDisplayName && (actorId === currentUserId || actorId === currentUsername)) { - actorDisplayName = actorDisplayName.toLowerCase(); + renderFormattedMessage(postType, userIds, actorId, style) { + const {formatMessage} = this.context.intl; + const { + currentUserId, + currentUsername, + navigator, + textStyles, + theme, + } = this.props; + const usernames = this.getUsernamesByIds(userIds); + let actor = actorId ? this.getUsernamesByIds([actorId])[0] : ''; + if (actor && (actorId === currentUserId || actorId === currentUsername)) { + actor = actor.toLowerCase(); } - const firstUser = usersDisplayName[0]; - const numOthers = usersDisplayName.length - 1; + const firstUser = usernames[0]; + const secondUser = usernames[1]; + const numOthers = usernames.length - 1; - let formattedMessage; - if (numOthers === 0) { - formattedMessage = this.renderFormattedMessage( - postTypeMessage[postType].one, - firstUser, - null, - actorDisplayName, - style, + if (numOthers > 1) { + return ( + ); + } + + let localeHolder; + if (numOthers === 0) { + localeHolder = postTypeMessage[postType].one; if ( (userIds[0] === currentUserId || userIds[0] === currentUsername) && postTypeMessage[postType].one_you ) { - formattedMessage = this.renderFormattedMessage( - postTypeMessage[postType].one_you, - null, - null, - actorDisplayName, - style, - ); + localeHolder = postTypeMessage[postType].one_you; } } else if (numOthers === 1) { - formattedMessage = this.renderFormattedMessage( - postTypeMessage[postType].two, - firstUser, - usersDisplayName[1], - actorDisplayName, - style, - ); - } else if (numOthers > 1) { - formattedMessage = ( - - ); + localeHolder = postTypeMessage[postType].two; } - return formattedMessage; - } + const formattedMessage = formatMessage(localeHolder, {firstUser, secondUser, actor}); - renderFormattedMessage = (localeFormat, firstUser, secondUser, actor, style) => { return ( - - - - - - {localeFormat.id[2] ? ( - - ) : ('.') - } - + ); } render() { const { - linkStyle, messageData, theme, } = this.props; @@ -367,7 +333,7 @@ export default class CombinedSystemMessage extends React.PureComponent { content.push( - {this.renderSystemMessage(postType, userIds, actorId, {activityType: style.activityType, link: linkStyle, text: style.text})} + {this.renderFormattedMessage(postType, userIds, actorId, {baseText: style.baseText, linkText: style.linkText})} ); } @@ -382,14 +348,13 @@ export default class CombinedSystemMessage extends React.PureComponent { const getStyleSheet = makeStyleSheetFromTheme((theme) => { return { - activityType: { - color: theme.centerChannelColor, - fontSize: 14, - fontWeight: 'bold', - }, - text: { + baseText: { color: theme.centerChannelColor, opacity: 0.6, }, + linkText: { + color: theme.linkColor, + opacity: 0.8, + }, }; }); diff --git a/app/components/combined_system_message/combined_system_message.test.js b/app/components/combined_system_message/combined_system_message.test.js deleted file mode 100644 index bfd35346d..000000000 --- a/app/components/combined_system_message/combined_system_message.test.js +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React from 'react'; -import {configure} from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; -configure({adapter: new Adapter()}); - -import {shallowWithIntl} from 'test/intl-test-helper'; -import {emptyFunction} from 'app/utils/general'; - -import {Posts} from 'mattermost-redux/constants'; - -import CombinedSystemMessage from './combined_system_message'; - -/* eslint-disable max-nested-callbacks */ - -describe('CombinedSystemMessage', () => { - const baseProps = { - actions: { - getMissingProfilesByIds: emptyFunction, - getMissingProfilesByUsernames: emptyFunction, - }, - allUserIds: ['user_id_1', 'user_id_2', 'user_id_3'], - currentUserId: 'user_id_3', - currentUsername: 'username_3', - linkStyle: 1, - messageData: [ - {postType: Posts.POST_TYPES.ADD_TO_TEAM, userIds: ['user_id_1'], actorId: 'user_id_2'}, - ], - showJoinLeave: true, - teammateNameDisplay: 'username', - theme: {centerChannelColor: '#aaa'}, - userProfiles: [{id: 'user_id_1', username: 'user1'}, {id: 'user_id_2', username: 'user2'}, {id: 'user_id_3', username: 'user3'}], - }; - - test('should match snapshot', () => { - const props = { - ...baseProps, - actions: { - getMissingProfilesByIds: jest.fn(), - getMissingProfilesByUsernames: emptyFunction, - }, - }; - const wrapper = shallowWithIntl( - - ); - - const {postType, userIds, actorId} = baseProps.messageData[0]; - expect(wrapper.instance().renderSystemMessage(postType, userIds, actorId, {activityType: {fontSize: 14}, text: {opacity: 0.6}}, 1)).toMatchSnapshot(); - - // on componentDidMount - expect(props.actions.getMissingProfilesByIds).toHaveBeenCalledTimes(1); - expect(props.actions.getMissingProfilesByIds).toHaveBeenCalledWith(props.allUserIds); - }); - - test('should match snapshot', () => { - const localeFormat = { - id: ['combined_system_message.first_user_and_second_user_were', 'combined_system_message.removed_from_team'], - defaultMessage: ['{firstUser} and {secondUser} were ', 'removed from the team'], - }; - const wrapper = shallowWithIntl( - - ); - - expect(wrapper.instance().renderFormattedMessage(localeFormat, 'first_user', 'second_user', 'actor', {activityType: {fontSize: 14}, text: {opacity: 0.6}})).toMatchSnapshot(); - }); - - test('should call getMissingProfilesByIds and/or getMissingProfilesByUsernames on loadUserProfiles', () => { - const props = { - ...baseProps, - allUserIds: [], - actions: { - getMissingProfilesByIds: jest.fn(), - getMissingProfilesByUsernames: jest.fn(), - }, - }; - - const wrapper = shallowWithIntl( - - ); - - wrapper.instance().loadUserProfiles([], []); - expect(props.actions.getMissingProfilesByIds).toHaveBeenCalledTimes(0); - expect(props.actions.getMissingProfilesByUsernames).toHaveBeenCalledTimes(0); - - wrapper.instance().loadUserProfiles(['user_id_1'], []); - expect(props.actions.getMissingProfilesByIds).toHaveBeenCalledTimes(1); - expect(props.actions.getMissingProfilesByIds).toHaveBeenCalledWith(['user_id_1']); - expect(props.actions.getMissingProfilesByUsernames).toHaveBeenCalledTimes(0); - - wrapper.instance().loadUserProfiles(['user_id_1', 'user_id_2'], ['user1']); - expect(props.actions.getMissingProfilesByIds).toHaveBeenCalledTimes(2); - expect(props.actions.getMissingProfilesByIds).toHaveBeenCalledWith(['user_id_1', 'user_id_2']); - expect(props.actions.getMissingProfilesByUsernames).toHaveBeenCalledTimes(1); - expect(props.actions.getMissingProfilesByUsernames).toHaveBeenCalledWith(['user1']); - }); -}); diff --git a/app/components/combined_system_message/index.js b/app/components/combined_system_message/index.js index 43e8022dd..7ccee01ea 100644 --- a/app/components/combined_system_message/index.js +++ b/app/components/combined_system_message/index.js @@ -6,7 +6,7 @@ import {bindActionCreators} from 'redux'; import {getMissingProfilesByIds, getMissingProfilesByUsernames} from 'mattermost-redux/actions/users'; import {Preferences} from 'mattermost-redux/constants'; -import {getBool, getTeammateNameDisplaySetting} from 'mattermost-redux/selectors/entities/preferences'; +import {getBool} from 'mattermost-redux/selectors/entities/preferences'; import {getCurrentUser, makeGetProfilesByIdsAndUsernames} from 'mattermost-redux/selectors/entities/users'; import CombinedSystemMessage from './combined_system_message'; @@ -21,7 +21,6 @@ function makeMapStateToProps() { currentUserId: currentUser.id, currentUsername: currentUser.username, showJoinLeave: getBool(state, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE, true), - teammateNameDisplay: getTeammateNameDisplaySetting(state), userProfiles: getProfilesByIdsAndUsernames(state, {allUserIds, allUsernames}), }; }; diff --git a/app/components/combined_system_message/last_users.js b/app/components/combined_system_message/last_users.js index 601a0bccf..2cbc9e341 100644 --- a/app/components/combined_system_message/last_users.js +++ b/app/components/combined_system_message/last_users.js @@ -4,43 +4,46 @@ import PropTypes from 'prop-types'; import React from 'react'; import {Text} from 'react-native'; +import {intlShape} from 'react-intl'; import {Posts} from 'mattermost-redux/constants'; +import FormattedMarkdownText from 'app/components/formatted_markdown_text'; import FormattedText from 'app/components/formatted_text'; +import Markdown from 'app/components/markdown'; const typeMessage = { [Posts.POST_TYPES.ADD_TO_CHANNEL]: { - id: ['mobile.combined_system_message.were', 'mobile.combined_system_message.added_to_channel', 'mobile.combined_system_message.by_actor'], - defaultMessage: ['were ', 'added to the channel', ' by {actor}.'], + id: 'last_users_message.added_to_channel.type', + defaultMessage: 'were **added to the channel** by {actor}.', }, [Posts.POST_TYPES.JOIN_CHANNEL]: { - id: ['', 'mobile.combined_system_message.joined_channel'], - defaultMessage: ['', 'joined the channel'], + id: 'last_users_message.joined_channel.type', + defaultMessage: '**joined the channel**.', }, [Posts.POST_TYPES.LEAVE_CHANNEL]: { - id: ['', 'mobile.combined_system_message.left_channel', ''], - defaultMessage: ['', 'left the channel'], + id: 'last_users_message.left_channel.type', + defaultMessage: '**left the channel**.', }, [Posts.POST_TYPES.REMOVE_FROM_CHANNEL]: { - id: ['mobile.combined_system_message.were', 'mobile.combined_system_message.removed_from_channel'], - defaultMessage: ['were ', 'removed from the channel'], + id: 'last_users_message.removed_from_channel.type', + defaultMessage: 'were **removed from the channel**.', }, [Posts.POST_TYPES.ADD_TO_TEAM]: { - id: ['mobile.combined_system_message.were', 'mobile.combined_system_message.added_to_team', 'mobile.combined_system_message.by_actor'], - defaultMessage: ['were ', 'added to the team', ' by {actor}.'], + id: 'last_users_message.added_to_team.type', + defaultMessage: 'were **added to the team** by {actor}.', }, [Posts.POST_TYPES.JOIN_TEAM]: { - id: ['', 'mobile.combined_system_message.joined_team'], - defaultMessage: ['', 'joined the team'], + id: 'last_users_message.joined_team.type', + defaultMessage: '**joined the team**.', }, [Posts.POST_TYPES.LEAVE_TEAM]: { - id: ['', 'mobile.combined_system_message.left_team'], - defaultMessage: ['', 'left the team'], + id: 'last_users_message.left_team.type', + defaultMessage: '**left the team**.', }, [Posts.POST_TYPES.REMOVE_FROM_TEAM]: { - id: ['', 'mobile.combined_system_message.removed_from_team'], - defaultMessage: ['were ', 'removed from the team'], + id: 'last_users_message.removed_from_team.type', + defaultMessage: 'were **removed from the team**.', }, }; @@ -48,9 +51,12 @@ export default class LastUsers extends React.PureComponent { static propTypes = { actor: PropTypes.string, expandedLocale: PropTypes.object.isRequired, + navigator: PropTypes.object.isRequired, postType: PropTypes.string.isRequired, style: PropTypes.object.isRequired, - userDisplayNames: PropTypes.array.isRequired, + textStyles: PropTypes.object, + theme: PropTypes.object.isRequired, + usernames: PropTypes.array.isRequired, }; constructor(props) { @@ -61,99 +67,102 @@ export default class LastUsers extends React.PureComponent { }; } - handleOnClick = (e) => { + static contextTypes = { + intl: intlShape, + }; + + handleOnPress = (e) => { e.preventDefault(); this.setState({expand: true}); } - renderExpandedView = (expandedLocale, userDisplayNames, actor, lastIndex, style) => { + renderExpandedView = () => { + const {formatMessage} = this.context.intl; + const { + actor, + expandedLocale, + navigator, + style, + textStyles, + usernames, + } = this.props; + + const lastIndex = usernames.length - 1; + const lastUser = usernames[lastIndex]; + + const formattedMessage = formatMessage(expandedLocale, { + users: usernames.slice(0, lastIndex).join(', '), + lastUser, + actor, + }); + return ( - - - - - - {expandedLocale.id[2] ? ( - - ) : ('.') - } - + ); } - renderCollapsedView = (postType, userDisplayNames, actor, lastIndex, style) => { + renderCollapsedView = () => { + const { + actor, + navigator, + postType, + style, + textStyles, + theme, + usernames, + } = this.props; + + const firstUser = usernames[0]; + const numOthers = usernames.length - 1; + return ( - - + + {' '} - {typeMessage[postType].id[0] && - - } - - - - {typeMessage[postType].id[2] ? ( - - ) : ('.') - } ); } render() { - const {expand} = this.state; - const { - actor, - expandedLocale, - postType, - userDisplayNames, - style, - } = this.props; - - const lastIndex = userDisplayNames.length - 1; - - if (expand) { - return this.renderExpandedView(expandedLocale, userDisplayNames, actor, lastIndex, style); + if (this.state.expand) { + return this.renderExpandedView(); } - return this.renderCollapsedView(postType, userDisplayNames, actor, lastIndex, style); + return this.renderCollapsedView(); } } diff --git a/app/components/combined_system_message/last_users.test.js b/app/components/combined_system_message/last_users.test.js deleted file mode 100644 index 469497795..000000000 --- a/app/components/combined_system_message/last_users.test.js +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React from 'react'; -import {configure} from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; -configure({adapter: new Adapter()}); - -import {Posts} from 'mattermost-redux/constants'; - -import {shallowWithIntl} from 'test/intl-test-helper'; - -import LastUsers from './last_users'; - -describe('LastUsers', () => { - const baseProps = { - actor: 'actor', - expandedLocale: {id: 'expanded_locale_id', defaultMessage: 'Expanded Locale'}, - postType: Posts.POST_TYPES.ADD_TO_TEAM, - style: {activityType: {fontSize: 14}, link: 1, text: {opacity: 0.6}}, - userDisplayNames: ['User One', 'User Two'], - }; - - test('should match snapshot', () => { - const wrapper = shallowWithIntl( - - ); - - const expanded = wrapper.instance().renderExpandedView(baseProps.expandedLocale, baseProps.userDisplayNames, baseProps.actor, 1, baseProps.style); - expect(expanded).toMatchSnapshot(); - - const collapsed = wrapper.instance().renderCollapsedView(baseProps.postType, baseProps.userDisplayNames, baseProps.actor, 1, baseProps.style); - expect(collapsed).toMatchSnapshot(); - }); - - test('should match state on handleOnClick', () => { - const wrapper = shallowWithIntl( - - ); - - wrapper.setState({expand: false}); - wrapper.instance().handleOnClick({preventDefault: jest.fn()}); - expect(wrapper.state('expand')).toEqual(true); - }); -}); diff --git a/app/components/formatted_markdown_text.js b/app/components/formatted_markdown_text.js index 1e41b4899..cb11833a2 100644 --- a/app/components/formatted_markdown_text.js +++ b/app/components/formatted_markdown_text.js @@ -7,11 +7,14 @@ import PropTypes from 'prop-types'; import Renderer from 'commonmark-react-renderer'; import {Parser} from 'commonmark'; import {injectIntl, intlShape} from 'react-intl'; -import MarkdownLink from 'app/components/markdown/markdown_link'; + import {concatStyles, changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; import {getMarkdownTextStyles} from 'app/utils/markdown'; import CustomPropTypes from 'app/constants/custom_prop_types'; +import AtMention from 'app/components/at_mention'; +import MarkdownLink from 'app/components/markdown/markdown_link'; + const TARGET_BLANK_URL_PREFIX = '!'; /* @@ -29,12 +32,19 @@ const TARGET_BLANK_URL_PREFIX = '!'; */ class FormattedMarkdownText extends React.PureComponent { static propTypes = { - intl: intlShape.isRequired, - id: PropTypes.string.isRequired, - theme: PropTypes.object.isRequired, + baseTextStyle: CustomPropTypes.Style, defaultMessage: PropTypes.string.isRequired, - values: PropTypes.object, + id: PropTypes.string.isRequired, + navigator: PropTypes.object.isRequired, + onPostPress: PropTypes.func, style: CustomPropTypes.Style, + textStyles: PropTypes.object, + theme: PropTypes.object.isRequired, + values: PropTypes.object, + }; + + static contextTypes = { + intl: intlShape, }; constructor(props) { @@ -63,6 +73,7 @@ class FormattedMarkdownText extends React.PureComponent { del: Renderer.forwardChildren, html_inline: this.renderHTML, html_block: this.renderHTML, + atMention: this.renderAtMention, }, }); } @@ -99,10 +110,24 @@ class FormattedMarkdownText extends React.PureComponent { return this.renderText(props); } + renderAtMention = ({context, mentionName}) => { + return ( + + ); + } + render() { const {id, defaultMessage, values, theme} = this.props; const messageDescriptor = {id, defaultMessage}; - const message = this.props.intl.formatMessage(messageDescriptor, values); + const {formatMessage} = this.context.intl; + const message = formatMessage(messageDescriptor, values); const ast = this.parser.parse(message); this.textStyles = getMarkdownTextStyles(theme); this.baseTextStyle = getStyleSheet(theme).message; diff --git a/app/components/post_body/post_body.js b/app/components/post_body/post_body.js index 3d939bc37..35894f98a 100644 --- a/app/components/post_body/post_body.js +++ b/app/components/post_body/post_body.js @@ -443,17 +443,21 @@ export default class PostBody extends PureComponent { } else if (postType === Posts.POST_TYPES.COMBINED_USER_ACTIVITY) { const {allUserIds, allUsernames, messageData} = postProps.user_activity; messageComponent = ( - - - + + + + + - + ); } else if (message.length) { messageComponent = ( diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index c7a61cb96..02e0812b1 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -2357,26 +2357,6 @@ "mobile.client_upgrade.no_upgrade_subtitle": "You already have the latest version.", "mobile.client_upgrade.no_upgrade_title": "Your App Is Up to Date", "mobile.client_upgrade.upgrade": "Update", - "mobile.combined_system_message.added_to_channel": "added to the channel", - "mobile.combined_system_message.added_to_team": "added to the team", - "mobile.combined_system_message.by_actor": " by {actor}.", - "mobile.combined_system_message.first_user": "{firstUser} ", - "mobile.combined_system_message.first_user_and": "{firstUser} and ", - "mobile.combined_system_message.first_user_and_second_user": "{firstUser} and {secondUser} ", - "mobile.combined_system_message.first_user_and_second_user_were": "{firstUser} and {secondUser} were ", - "mobile.combined_system_message.first_user_was": "{firstUser} was ", - "mobile.combined_system_message.joined_channel": "joined the channel", - "mobile.combined_system_message.joined_team": "joined the team", - "mobile.combined_system_message.left_channel": "left the channel", - "mobile.combined_system_message.left_team": "left the team", - "mobile.combined_system_message.others": "{numOthers} others ", - "mobile.combined_system_message.removed_from_channel": "removed from the channel", - "mobile.combined_system_message.removed_from_team": "removed from the team", - "mobile.combined_system_message.users_and_last_user": "{users} and {lastUser} ", - "mobile.combined_system_message.users_and_last_user_were": "{users} and {lastUser} were ", - "mobile.combined_system_message.were": "were ", - "mobile.combined_system_message.you": "You", - "mobile.combined_system_message.you_were": "You were ", "mobile.commands.error_title": "Error Executing Command", "mobile.components.channels_list_view.yourChannels": "Your channels:", "mobile.components.error_list.dismiss_all": "Dismiss All",