diff --git a/app/components/autocomplete/at_mention_item/at_mention_item.js b/app/components/autocomplete/at_mention_item/at_mention_item.js
index 9592d3093..a91cc399c 100644
--- a/app/components/autocomplete/at_mention_item/at_mention_item.js
+++ b/app/components/autocomplete/at_mention_item/at_mention_item.js
@@ -9,11 +9,10 @@ import {
} from 'react-native';
import ProfilePicture from 'app/components/profile_picture';
-import BotTag from 'app/components/bot_tag';
-import GuestTag from 'app/components/guest_tag';
+import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
+import {BotTag, GuestTag} from 'app/components/tag';
import TouchableWithFeedback from 'app/components/touchable_with_feedback';
import {makeStyleSheetFromTheme} from 'app/utils/theme';
-import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
export default class AtMentionItem extends PureComponent {
static propTypes = {
diff --git a/app/components/autocomplete/channel_mention_item/channel_mention_item.js b/app/components/autocomplete/channel_mention_item/channel_mention_item.js
index b110f26cf..226af6fe9 100644
--- a/app/components/autocomplete/channel_mention_item/channel_mention_item.js
+++ b/app/components/autocomplete/channel_mention_item/channel_mention_item.js
@@ -8,8 +8,7 @@ import {
} from 'react-native';
import {General} from 'mattermost-redux/constants';
-import BotTag from 'app/components/bot_tag';
-import GuestTag from 'app/components/guest_tag';
+import {BotTag, GuestTag} from 'app/components/tag';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
import TouchableWithFeedback from 'app/components/touchable_with_feedback';
import {makeStyleSheetFromTheme} from 'app/utils/theme';
diff --git a/app/components/bot_tag.js b/app/components/bot_tag.js
deleted file mode 100644
index e18201091..000000000
--- a/app/components/bot_tag.js
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
-// See LICENSE.txt for license information.
-
-import React, {PureComponent} from 'react';
-import PropTypes from 'prop-types';
-import {Platform, View} from 'react-native';
-import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
-import FormattedText from 'app/components/formatted_text';
-
-export default class BotTag extends PureComponent {
- static defaultProps = {
- show: true,
- };
-
- static propTypes = {
- show: PropTypes.bool,
- theme: PropTypes.object.isRequired,
- };
-
- render() {
- if (!this.props.show) {
- return null;
- }
- const style = createStyleSheet(this.props.theme);
-
- return (
-
-
-
- );
- }
-}
-
-const createStyleSheet = makeStyleSheetFromTheme((theme) => {
- return {
- bot: {
- alignSelf: 'center',
- backgroundColor: changeOpacity(theme.centerChannelColor, 0.15),
- borderRadius: 2,
- marginRight: 2,
- marginBottom: 1,
- ...Platform.select({
- android: {
- marginBottom: 0,
- },
- }),
- marginLeft: 2,
- paddingVertical: 2,
- paddingHorizontal: 4,
- },
- botText: {
- color: theme.centerChannelColor,
- fontSize: 10,
- fontWeight: '600',
- },
- };
-});
diff --git a/app/components/channel_intro/channel_intro.js b/app/components/channel_intro/channel_intro.js
index a2ae4392f..0e7c1e17a 100644
--- a/app/components/channel_intro/channel_intro.js
+++ b/app/components/channel_intro/channel_intro.js
@@ -12,16 +12,15 @@ import {injectIntl, intlShape} from 'react-intl';
import {getFullName} from 'mattermost-redux/utils/user_utils';
import {General} from 'mattermost-redux/constants';
-import BotTag from 'app/components/bot_tag';
-import GuestTag from 'app/components/guest_tag';
+import {goToScreen} from 'app/actions/navigation';
import ProfilePicture from 'app/components/profile_picture';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
+import {BotTag, GuestTag} from 'app/components/tag';
import TouchableWithFeedback from 'app/components/touchable_with_feedback';
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import {t} from 'app/utils/i18n';
import {isGuest} from 'app/utils/users';
-import {goToScreen} from 'app/actions/navigation';
class ChannelIntro extends PureComponent {
static propTypes = {
diff --git a/app/components/custom_list/user_list_row/user_list_row.js b/app/components/custom_list/user_list_row/user_list_row.js
index 10309de12..4e8ebf708 100644
--- a/app/components/custom_list/user_list_row/user_list_row.js
+++ b/app/components/custom_list/user_list_row/user_list_row.js
@@ -10,12 +10,12 @@ import {
} from 'react-native';
import {displayUsername} from 'mattermost-redux/utils/user_utils';
+
+import CustomListRow from 'app/components/custom_list/custom_list_row';
import ProfilePicture from 'app/components/profile_picture';
-import BotTag from 'app/components/bot_tag';
-import GuestTag from 'app/components/guest_tag';
+import {BotTag, GuestTag} from 'app/components/tag';
import {makeStyleSheetFromTheme, changeOpacity} from 'app/utils/theme';
import {isGuest} from 'app/utils/users';
-import CustomListRow from 'app/components/custom_list/custom_list_row';
export default class UserListRow extends React.PureComponent {
static propTypes = {
diff --git a/app/components/formatted_time.js b/app/components/formatted_time.js
index 64cc06569..88c903882 100644
--- a/app/components/formatted_time.js
+++ b/app/components/formatted_time.js
@@ -6,12 +6,15 @@ import PropTypes from 'prop-types';
import {Text} from 'react-native';
import moment from 'moment-timezone';
+import CustomPropTypes from 'app/constants/custom_prop_types';
+
export default class FormattedTime extends React.PureComponent {
static propTypes = {
value: PropTypes.any.isRequired,
timeZone: PropTypes.string,
children: PropTypes.func,
hour12: PropTypes.bool,
+ style: CustomPropTypes.Style,
};
getFormattedTime = () => {
@@ -30,13 +33,13 @@ export default class FormattedTime extends React.PureComponent {
};
render() {
- const {children} = this.props;
+ const {children, style} = this.props;
const formattedTime = this.getFormattedTime();
if (typeof children === 'function') {
return children(formattedTime);
}
- return {formattedTime};
+ return {formattedTime};
}
}
diff --git a/app/components/post/post.js b/app/components/post/post.js
index 2ba71ef42..a1a555fb5 100644
--- a/app/components/post/post.js
+++ b/app/components/post/post.js
@@ -306,51 +306,52 @@ export default class Post extends PureComponent {
const rightColumnStyle = [style.rightColumn, (commentedOnPost && isLastReply && style.rightColumnPadding)];
return (
-
-
-
-
- {userProfile}
-
- {postHeader}
-
+
+
+
+
+
+ {userProfile}
+
+ {postHeader}
+
+
-
-
-
+
+
+
);
}
}
@@ -359,6 +360,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
postStyle: {
overflow: 'hidden',
+ flex: 1,
},
container: {
flexDirection: 'row',
@@ -366,6 +368,11 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
pendingPost: {
opacity: 0.5,
},
+ preHeaderRightColumn: {
+ flex: 1,
+ flexDirection: 'column',
+ marginLeft: 2,
+ },
rightColumn: {
flex: 1,
flexDirection: 'column',
@@ -398,6 +405,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
replyBar: {
backgroundColor: theme.centerChannelColor,
opacity: 0.1,
+ marginLeft: 1,
marginRight: 7,
width: 3,
flexBasis: 3,
diff --git a/app/components/post_header/__snapshots__/post_pre_header.test.js.snap b/app/components/post_header/__snapshots__/post_pre_header.test.js.snap
index 24150d3ad..79cce8349 100644
--- a/app/components/post_header/__snapshots__/post_pre_header.test.js.snap
+++ b/app/components/post_header/__snapshots__/post_pre_header.test.js.snap
@@ -8,7 +8,7 @@ exports[`PostPreHeader should match snapshot when flagged and not pinned 1`] = `
"flex": 1,
"flexDirection": "row",
"height": 15,
- "marginLeft": 12,
+ "marginLeft": 10,
"marginRight": 10,
"marginTop": 10,
},
@@ -77,7 +77,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged 1`] = `
"flex": 1,
"flexDirection": "row",
"height": 15,
- "marginLeft": 12,
+ "marginLeft": 10,
"marginRight": 10,
"marginTop": 10,
},
@@ -166,7 +166,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged but skippin
"flex": 1,
"flexDirection": "row",
"height": 15,
- "marginLeft": 12,
+ "marginLeft": 10,
"marginRight": 10,
"marginTop": 10,
},
@@ -231,7 +231,7 @@ exports[`PostPreHeader should match snapshot when pinned and flagged but skippin
"flex": 1,
"flexDirection": "row",
"height": 15,
- "marginLeft": 12,
+ "marginLeft": 10,
"marginRight": 10,
"marginTop": 10,
},
@@ -296,7 +296,7 @@ exports[`PostPreHeader should match snapshot when pinned and not flagged 1`] = `
"flex": 1,
"flexDirection": "row",
"height": 15,
- "marginLeft": 12,
+ "marginLeft": 10,
"marginRight": 10,
"marginTop": 10,
},
diff --git a/app/components/post_header/post_header.js b/app/components/post_header/post_header.js
index b2dd60d4f..591aecebc 100644
--- a/app/components/post_header/post_header.js
+++ b/app/components/post_header/post_header.js
@@ -4,7 +4,6 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {
- Platform,
Text,
View,
} from 'react-native';
@@ -13,10 +12,10 @@ import FormattedText from 'app/components/formatted_text';
import FormattedTime from 'app/components/formatted_time';
import FormattedDate from 'app/components/formatted_date';
import ReplyIcon from 'app/components/reply_icon';
-import BotTag from 'app/components/bot_tag';
-import GuestTag from 'app/components/guest_tag';
+import Tag, {BotTag, GuestTag} from 'app/components/tag';
import TouchableWithFeedback from 'app/components/touchable_with_feedback';
import {emptyFunction} from 'app/utils/general';
+import {t} from 'app/utils/i18n';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
export default class PostHeader extends PureComponent {
@@ -56,121 +55,16 @@ export default class PostHeader extends PureComponent {
if (this.props.username) {
this.props.onUsernamePress(this.props.username);
}
- }
-
- getDisplayName = (style) => {
- const {
- enablePostUsernameOverride,
- fromWebHook,
- isSystemMessage,
- fromAutoResponder,
- overrideUsername,
- isBot,
- isGuest,
- } = this.props;
-
- if (fromWebHook) {
- let name = this.props.displayName;
- if (overrideUsername && enablePostUsernameOverride) {
- name = overrideUsername;
- }
-
- return (
-
-
- {name}
-
-
-
- );
- } else if (isBot) {
- return (
-
-
-
- {this.props.displayName}
-
-
-
-
- );
- } else if (isGuest) {
- return (
-
-
-
- {this.props.displayName}
-
-
-
-
- );
- } else if (fromAutoResponder) {
- let name = this.props.displayName;
- if (overrideUsername && enablePostUsernameOverride) {
- name = overrideUsername;
- }
-
- return (
-
-
- {name}
-
-
-
- );
- } else if (isSystemMessage) {
- return (
-
- );
- } else if (this.props.displayName) {
- return (
-
-
- {this.props.displayName}
-
-
- );
- }
-
- return (
-
- );
};
- renderCommentedOnMessage = (style) => {
+ renderCommentedOnMessage = () => {
if (!this.props.renderReplies || !this.props.commentedOnDisplayName) {
return null;
}
- const displayName = this.props.commentedOnDisplayName;
+ const {commentedOnDisplayName, theme} = this.props;
+ const style = getStyleSheet(theme);
+ const displayName = commentedOnDisplayName;
let name;
if (displayName) {
@@ -204,86 +98,187 @@ export default class PostHeader extends PureComponent {
);
};
- render() {
+ renderDisplayName = () => {
+ const {
+ displayName,
+ enablePostUsernameOverride,
+ fromWebHook,
+ isSystemMessage,
+ fromAutoResponder,
+ overrideUsername,
+ theme,
+ } = this.props;
+
+ const style = getStyleSheet(theme);
+
+ if (fromAutoResponder || fromWebHook) {
+ let name = displayName;
+ if (overrideUsername && enablePostUsernameOverride) {
+ name = overrideUsername;
+ }
+
+ return (
+
+
+ {name}
+
+
+ );
+ } else if (isSystemMessage) {
+ return (
+
+
+
+ );
+ } else if (displayName) {
+ return (
+
+
+ {displayName}
+
+
+ );
+ }
+
+ return (
+
+
+
+ );
+ };
+
+ renderReply = () => {
const {
- commentedOnDisplayName,
commentCount,
- createAt,
- isPendingOrFailedPost,
+ commentedOnDisplayName,
isSearchResult,
- userTimezone,
- militaryTime,
onPress,
renderReplies,
shouldRenderReplyButton,
- showFullDate,
theme,
} = this.props;
const style = getStyleSheet(theme);
const showReply = shouldRenderReplyButton || (!commentedOnDisplayName && commentCount > 0 && renderReplies);
+ if (!showReply) {
+ return null;
+ }
+
+ return (
+
+
+
+ {!isSearchResult &&
+ {commentCount}
+ }
+
+
+ );
+ };
+
+ renderTag = () => {
+ const {fromAutoResponder, fromWebHook, isBot, isGuest, theme} = this.props;
+ const style = getStyleSheet(theme);
+
+ if (fromWebHook || isBot) {
+ return (
+
+ );
+ } else if (isGuest) {
+ return (
+
+ );
+ } else if (fromAutoResponder) {
+ return (
+
+ );
+ }
+
+ return null;
+ };
+
+ render() {
+ const {
+ createAt,
+ isPendingOrFailedPost,
+ userTimezone,
+ militaryTime,
+ showFullDate,
+ theme,
+ } = this.props;
+ const style = getStyleSheet(theme);
+
let dateComponent;
if (showFullDate) {
dateComponent = (
-
-
-
-
-
-
-
-
+
);
} else {
dateComponent = (
-
-
-
+
);
}
return (
-
-
- {this.getDisplayName(style)}
-
- {dateComponent}
-
+
+
+ {this.renderDisplayName()}
+ {this.renderTag()}
+ {dateComponent}
+ {this.renderReply()}
- {showReply &&
-
-
- {!isSearchResult &&
- {commentCount}
- }
-
- }
- {commentedOnDisplayName !== '' &&
-
- {this.renderCommentedOnMessage(style)}
-
- }
+ {this.renderCommentedOnMessage(style)}
);
}
@@ -291,67 +286,64 @@ export default class PostHeader extends PureComponent {
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
- commentedOn: {
- color: changeOpacity(theme.centerChannelColor, 0.65),
- marginBottom: 3,
- lineHeight: 21,
- },
- postInfoContainer: {
- alignItems: 'center',
- flexDirection: 'row',
+ container: {
+ flex: 1,
marginTop: 10,
},
pendingPost: {
opacity: 0.5,
},
- timeContainer: {
- justifyContent: 'center',
+ tag: {
+ marginLeft: 0,
+ marginRight: 5,
+ marginBottom: 5,
},
- datetime: {
+ wrapper: {
flex: 1,
flexDirection: 'row',
},
- time: {
- color: theme.centerChannelColor,
- fontSize: 13,
- marginLeft: 5,
- marginBottom: 1,
- opacity: 0.5,
- },
- replyIconContainer: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'center',
- marginVertical: -10,
- minWidth: 40,
- paddingVertical: 10,
- },
- replyText: {
- fontSize: 15,
- marginLeft: 3,
- color: theme.linkColor,
- },
- indicatorContainer: {
- flexDirection: 'row',
+ displayNameContainer: {
+ maxWidth: '60%',
+ marginRight: 5,
+ marginBottom: 3,
},
displayName: {
color: theme.centerChannelColor,
fontSize: 15,
fontWeight: '600',
- marginRight: 5,
- marginBottom: 3,
+ flexGrow: 1,
+ paddingVertical: 2,
},
- flagContainer: {
- marginLeft: 10,
- alignSelf: 'center',
- ...Platform.select({
- ios: {
- marginBottom: 2,
- },
- android: {
- marginBottom: 1,
- },
- }),
+ time: {
+ color: theme.centerChannelColor,
+ fontSize: 12,
+ marginTop: 5,
+ opacity: 0.5,
+ flex: 1,
+ },
+ replyWrapper: {
+ flex: 1,
+ justifyContent: 'flex-end',
+ },
+ replyIconContainer: {
+ flexDirection: 'row',
+ alignItems: 'flex-start',
+ justifyContent: 'flex-end',
+ minWidth: 40,
+ paddingTop: 2,
+ paddingBottom: 10,
+ flex: 1,
+ },
+ replyText: {
+ fontSize: 12,
+ marginLeft: 2,
+ marginTop: 2,
+ color: theme.linkColor,
+ },
+ commentedOn: {
+ color: changeOpacity(theme.centerChannelColor, 0.65),
+ marginBottom: 3,
+ lineHeight: 21,
},
};
});
diff --git a/app/components/post_header/post_pre_header.js b/app/components/post_header/post_pre_header.js
index 982ae93a3..1b9edcf5a 100644
--- a/app/components/post_header/post_pre_header.js
+++ b/app/components/post_header/post_pre_header.js
@@ -99,7 +99,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
flex: 1,
flexDirection: 'row',
height: 15,
- marginLeft: 12,
+ marginLeft: 10,
marginRight: 10,
marginTop: 10,
},
diff --git a/app/components/post_profile_picture/post_profile_picture.js b/app/components/post_profile_picture/post_profile_picture.js
index ec2ec981a..699979dac 100644
--- a/app/components/post_profile_picture/post_profile_picture.js
+++ b/app/components/post_profile_picture/post_profile_picture.js
@@ -3,7 +3,7 @@
import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
-import {Image, View} from 'react-native';
+import {Image, Platform, StyleSheet, View} from 'react-native';
import AppIcon from 'app/components/app_icon';
import ProfilePicture from 'app/components/profile_picture';
@@ -46,7 +46,7 @@ export default class PostProfilePicture extends PureComponent {
if (isSystemMessage && !fromAutoResponder && !isBot) {
return (
-
+
+ );
+}
+
+export function GuestTag(props) {
+ const id = t('post_info.guest');
+ const defaultMessage = 'GUEST';
+
+ return (
+
+ );
+}
+
+export default class Tag extends PureComponent {
+ static propTypes = {
+ id: PropTypes.string.isRequired,
+ defaultMessage: PropTypes.string.isRequired,
+ inTitle: PropTypes.bool,
+ show: PropTypes.bool,
+ style: ViewPropTypes.style,
+ theme: PropTypes.object.isRequired,
};
- static propTypes = {
- show: PropTypes.bool,
- theme: PropTypes.object.isRequired,
- inTitle: PropTypes.bool,
+ static defaultProps = {
+ show: true,
};
render() {
@@ -24,30 +56,35 @@ export default class GuestTag extends PureComponent {
const style = createStyleSheet(this.props.theme);
return (
-
+
+
+
);
}
}
const createStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
- guest: {
+ container: {
alignSelf: 'center',
backgroundColor: changeOpacity(theme.centerChannelColor, 0.15),
borderRadius: 2,
- color: theme.centerChannelColor,
- fontSize: 10,
- fontWeight: '600',
- marginRight: 5,
- marginLeft: 5,
+ marginRight: 2,
+ marginBottom: 1,
+ marginLeft: 2,
paddingVertical: 2,
paddingHorizontal: 4,
},
- guestTitle: {
+ text: {
+ color: theme.centerChannelColor,
+ fontSize: 10,
+ fontWeight: '600',
+ },
+ title: {
backgroundColor: changeOpacity(theme.sidebarHeaderTextColor, 0.15),
color: changeOpacity(theme.sidebarHeaderTextColor, 0.6),
},
diff --git a/app/screens/user_profile/user_profile.js b/app/screens/user_profile/user_profile.js
index e7675eaf0..215c1e005 100644
--- a/app/screens/user_profile/user_profile.js
+++ b/app/screens/user_profile/user_profile.js
@@ -20,8 +20,7 @@ import ProfilePicture from 'app/components/profile_picture';
import FormattedText from 'app/components/formatted_text';
import FormattedTime from 'app/components/formatted_time';
import StatusBar from 'app/components/status_bar';
-import BotTag from 'app/components/bot_tag';
-import GuestTag from 'app/components/guest_tag';
+import {BotTag, GuestTag} from 'app/components/tag';
import {alertErrorWithFallback} from 'app/utils/general';
import {changeOpacity, makeStyleSheetFromTheme, setNavigatorStyles} from 'app/utils/theme';
diff --git a/app/screens/user_profile/user_profile.test.js b/app/screens/user_profile/user_profile.test.js
index 79d36b16c..8cc4296b7 100644
--- a/app/screens/user_profile/user_profile.test.js
+++ b/app/screens/user_profile/user_profile.test.js
@@ -8,8 +8,7 @@ import Preferences from 'mattermost-redux/constants/preferences';
import * as NavigationActions from 'app/actions/navigation';
import UserProfile from './user_profile.js';
-import BotTag from 'app/components/bot_tag';
-import GuestTag from 'app/components/guest_tag';
+import {BotTag, GuestTag} from 'app/components/tag';
jest.mock('react-intl');
jest.mock('app/utils/theme', () => {