MM-18603 Fix post header to prevent overlaps (#3332)

* MM-18603 Fix post header to prevent overlaps

* Export BotTag and GuestTag
This commit is contained in:
Elias Nahum
2019-09-28 00:16:36 +03:00
committed by Harrison Healey
parent 51e5fc04d4
commit 3b3a696a55
14 changed files with 354 additions and 368 deletions

View File

@@ -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 = {

View File

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

View File

@@ -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 (
<View style={style.bot}>
<FormattedText
id='post_info.bot'
defaultMessage='BOT'
style={style.botText}
/>
</View>
);
}
}
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',
},
};
});

View File

@@ -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 = {

View File

@@ -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 = {

View File

@@ -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 <Text>{formattedTime}</Text>;
return <Text style={style}>{formattedTime}</Text>;
}
}

View File

@@ -306,51 +306,52 @@ export default class Post extends PureComponent {
const rightColumnStyle = [style.rightColumn, (commentedOnPost && isLastReply && style.rightColumnPadding)];
return (
<TouchableWithFeedback
style={[style.postStyle, highlighted, padding(isLandscape)]}
onPress={this.handlePress}
onLongPress={this.showPostOptions}
delayLongPress={100}
underlayColor={changeOpacity(theme.centerChannelColor, 0.1)}
cancelTouchOnPanning={true}
>
<React.Fragment>
<PostPreHeader
isConsecutive={mergeMessage}
isFlagged={isFlagged}
isPinned={post.is_pinned}
rightColumnStyle={style.rightColumn}
skipFlaggedHeader={skipFlaggedHeader}
skipPinnedHeader={skipPinnedHeader}
theme={theme}
/>
<View style={[style.container, this.props.style, consecutiveStyle]}>
{userProfile}
<View style={rightColumnStyle}>
{postHeader}
<PostBody
ref={this.postBodyRef}
highlight={highlight}
channelIsReadOnly={channelIsReadOnly}
isLastPost={isLastPost}
isSearchResult={isSearchResult}
onFailedPostPress={this.handleFailedPostPress}
onHashtagPress={onHashtagPress}
onPermalinkPress={onPermalinkPress}
onPress={this.handlePress}
post={post}
replyBarStyle={replyBarStyle}
managedConfig={managedConfig}
isFlagged={isFlagged}
isReplyPost={isReplyPost}
showAddReaction={showAddReaction}
showLongPost={showLongPost}
location={location}
/>
<View style={[style.postStyle, highlighted, padding(isLandscape)]}>
<TouchableWithFeedback
onPress={this.handlePress}
onLongPress={this.showPostOptions}
delayLongPress={100}
underlayColor={changeOpacity(theme.centerChannelColor, 0.1)}
cancelTouchOnPanning={true}
>
<React.Fragment>
<PostPreHeader
isConsecutive={mergeMessage}
isFlagged={isFlagged}
isPinned={post.is_pinned}
rightColumnStyle={style.preHeaderRightColumn}
skipFlaggedHeader={skipFlaggedHeader}
skipPinnedHeader={skipPinnedHeader}
theme={theme}
/>
<View style={[style.container, this.props.style, consecutiveStyle]}>
{userProfile}
<View style={rightColumnStyle}>
{postHeader}
<PostBody
ref={this.postBodyRef}
highlight={highlight}
channelIsReadOnly={channelIsReadOnly}
isLastPost={isLastPost}
isSearchResult={isSearchResult}
onFailedPostPress={this.handleFailedPostPress}
onHashtagPress={onHashtagPress}
onPermalinkPress={onPermalinkPress}
onPress={this.handlePress}
post={post}
replyBarStyle={replyBarStyle}
managedConfig={managedConfig}
isFlagged={isFlagged}
isReplyPost={isReplyPost}
showAddReaction={showAddReaction}
showLongPost={showLongPost}
location={location}
/>
</View>
</View>
</View>
</React.Fragment>
</TouchableWithFeedback>
</React.Fragment>
</TouchableWithFeedback>
</View>
);
}
}
@@ -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,

View File

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

View File

@@ -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 (
<View style={style.indicatorContainer}>
<Text style={style.displayName}>
{name}
</Text>
<BotTag
theme={this.props.theme}
/>
</View>
);
} else if (isBot) {
return (
<TouchableWithFeedback
onPress={this.handleUsernamePress}
type={'opacity'}
>
<View style={style.indicatorContainer}>
<Text style={style.displayName}>
{this.props.displayName}
</Text>
<BotTag
theme={this.props.theme}
/>
</View>
</TouchableWithFeedback>
);
} else if (isGuest) {
return (
<TouchableWithFeedback
onPress={this.handleUsernamePress}
type={'opacity'}
>
<View style={style.indicatorContainer}>
<Text style={style.displayName}>
{this.props.displayName}
</Text>
<GuestTag
theme={this.props.theme}
/>
</View>
</TouchableWithFeedback>
);
} else if (fromAutoResponder) {
let name = this.props.displayName;
if (overrideUsername && enablePostUsernameOverride) {
name = overrideUsername;
}
return (
<View style={style.indicatorContainer}>
<Text style={style.displayName}>
{name}
</Text>
<FormattedText
id='post_info.auto_responder'
defaultMessage='AUTOMATIC REPLY'
style={style.bot}
/>
</View>
);
} else if (isSystemMessage) {
return (
<FormattedText
id='post_info.system'
defaultMessage='System'
style={style.displayName}
/>
);
} else if (this.props.displayName) {
return (
<TouchableWithFeedback
onPress={this.handleUsernamePress}
type={'opacity'}
>
<Text style={style.displayName}>
{this.props.displayName}
</Text>
</TouchableWithFeedback>
);
}
return (
<FormattedText
id='channel_loader.someone'
defaultMessage='Someone'
style={style.displayName}
/>
);
};
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 (
<View style={[style.displayNameContainer, {maxWidth: fromAutoResponder ? '30%' : '60%'}]}>
<Text
style={style.displayName}
ellipsizeMode={'tail'}
numberOfLines={1}
>
{name}
</Text>
</View>
);
} else if (isSystemMessage) {
return (
<View style={style.displayNameContainer}>
<FormattedText
id='post_info.system'
defaultMessage='System'
style={[style.displayName]}
/>
</View>
);
} else if (displayName) {
return (
<TouchableWithFeedback
onPress={this.handleUsernamePress}
style={style.displayNameContainer}
type={'opacity'}
>
<Text
style={style.displayName}
ellipsizeMode={'tail'}
numberOfLines={1}
>
{displayName}
</Text>
</TouchableWithFeedback>
);
}
return (
<View style={style.displayNameContainer}>
<FormattedText
id='channel_loader.someone'
defaultMessage='Someone'
style={style.displayName}
/>
</View>
);
};
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 (
<View style={style.replyWrapper}>
<TouchableWithFeedback
onPress={onPress}
style={style.replyIconContainer}
type={'opacity'}
>
<ReplyIcon
height={16}
width={16}
color={theme.linkColor}
/>
{!isSearchResult &&
<Text style={style.replyText}>{commentCount}</Text>
}
</TouchableWithFeedback>
</View>
);
};
renderTag = () => {
const {fromAutoResponder, fromWebHook, isBot, isGuest, theme} = this.props;
const style = getStyleSheet(theme);
if (fromWebHook || isBot) {
return (
<BotTag
style={style.tag}
theme={theme}
/>
);
} else if (isGuest) {
return (
<GuestTag
style={style.tag}
theme={theme}
/>
);
} else if (fromAutoResponder) {
return (
<Tag
id={t('post_info.auto_responder')}
defaultMessage={'AUTOMATIC REPLY'}
style={style.tag}
theme={theme}
/>
);
}
return null;
};
render() {
const {
createAt,
isPendingOrFailedPost,
userTimezone,
militaryTime,
showFullDate,
theme,
} = this.props;
const style = getStyleSheet(theme);
let dateComponent;
if (showFullDate) {
dateComponent = (
<View style={style.datetime}>
<Text style={style.time}>
<FormattedDate
timeZone={userTimezone}
value={createAt}
/>
</Text>
<Text style={style.time}>
<FormattedTime
timeZone={userTimezone}
hour12={!militaryTime}
value={createAt}
/>
</Text>
</View>
<FormattedDate
format={`ddd, MMM DD, YYYY ${militaryTime ? 'HH:mm' : 'hh:mm A'}`}
timeZone={userTimezone}
value={createAt}
style={style.time}
/>
);
} else {
dateComponent = (
<Text style={style.time}>
<FormattedTime
timeZone={userTimezone}
hour12={!militaryTime}
value={createAt}
/>
</Text>
<FormattedTime
timeZone={userTimezone}
hour12={!militaryTime}
value={createAt}
style={style.time}
/>
);
}
return (
<React.Fragment>
<View style={[style.postInfoContainer, (isPendingOrFailedPost && style.pendingPost)]}>
<View style={{flexDirection: 'row', flex: 1}}>
{this.getDisplayName(style)}
<View style={style.timeContainer}>
{dateComponent}
</View>
<View style={[style.container, (isPendingOrFailedPost && style.pendingPost)]}>
<View style={style.wrapper}>
{this.renderDisplayName()}
{this.renderTag()}
{dateComponent}
{this.renderReply()}
</View>
{showReply &&
<TouchableWithFeedback
onPress={onPress}
style={style.replyIconContainer}
type={'opacity'}
>
<ReplyIcon
height={16}
width={16}
color={theme.linkColor}
/>
{!isSearchResult &&
<Text style={style.replyText}>{commentCount}</Text>
}
</TouchableWithFeedback>
}
</View>
{commentedOnDisplayName !== '' &&
<View>
{this.renderCommentedOnMessage(style)}
</View>
}
{this.renderCommentedOnMessage(style)}
</React.Fragment>
);
}
@@ -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,
},
};
});

View File

@@ -99,7 +99,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
flex: 1,
flexDirection: 'row',
height: 15,
marginLeft: 12,
marginLeft: 10,
marginRight: 10,
marginTop: 10,
},

View File

@@ -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 (
<View>
<View style={style.buffer}>
<AppIcon
color={theme.centerChannelColor}
height={ViewTypes.PROFILE_PICTURE_SIZE}
@@ -61,17 +61,16 @@ export default class PostProfilePicture extends PureComponent {
const frameSize = ViewTypes.PROFILE_PICTURE_SIZE;
const pictureSize = isEmoji ? ViewTypes.PROFILE_PICTURE_EMOJI_SIZE : ViewTypes.PROFILE_PICTURE_SIZE;
const borderRadius = isEmoji ? 0 : ViewTypes.PROFILE_PICTURE_SIZE / 2;
return (
<View
style={{
style={[{
borderRadius,
overflow: 'hidden',
justifyContent: 'center',
alignItems: 'center',
height: frameSize,
width: frameSize,
}}
}, style.buffer]}
>
<Image
source={icon}
@@ -107,3 +106,16 @@ export default class PostProfilePicture extends PureComponent {
return component;
}
}
const style = StyleSheet.create({
buffer: {
...Platform.select({
android: {
marginRight: 2,
},
ios: {
marginRight: 3,
},
}),
},
});

View File

@@ -2,19 +2,51 @@
// See LICENSE.txt for license information.
import React, {PureComponent} from 'react';
import {View, ViewPropTypes} from 'react-native';
import PropTypes from 'prop-types';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import FormattedText from 'app/components/formatted_text';
export default class GuestTag extends PureComponent {
static defaultProps = {
show: true,
import FormattedText from 'app/components/formatted_text';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import {t} from 'app/utils/i18n';
export function BotTag(props) {
const id = t('post_info.bot');
const defaultMessage = 'BOT';
return (
<Tag
id={id}
defaultMessage={defaultMessage}
{...props}
/>
);
}
export function GuestTag(props) {
const id = t('post_info.guest');
const defaultMessage = 'GUEST';
return (
<Tag
id={id}
defaultMessage={defaultMessage}
{...props}
/>
);
}
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 (
<FormattedText
id='post_info.guest'
defaultMessage='GUEST'
style={[style.guest, this.props.inTitle ? style.guestTitle : null]}
/>
<View style={[style.container, this.props.style]}>
<FormattedText
id={this.props.id}
defaultMessage={this.props.defaultMessage}
style={[style.text, this.props.inTitle ? style.title : null]}
/>
</View>
);
}
}
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),
},

View File

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

View File

@@ -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', () => {