diff --git a/src/CONST.js b/src/CONST.js index 68e309e589bf..76910d5d8737 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -1109,6 +1109,7 @@ const CONST = { LARGE_BORDERED: 'large-bordered', HEADER: 'header', MENTION_ICON: 'mention-icon', + SMALL_NORMAL: 'small-normal', }, AVATAR_ROW_SIZE: { DEFAULT: 4, diff --git a/src/components/Avatar.js b/src/components/Avatar.js index b59a8902eb13..51e791251f2c 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -45,7 +45,7 @@ const propTypes = { /** Denotes whether it is an avatar or a workspace avatar */ type: PropTypes.oneOf([CONST.ICON_TYPE_AVATAR, CONST.ICON_TYPE_WORKSPACE]), - /** Owner of the avatar, typically a login email or workspace name */ + /** Owner of the avatar. If user, displayName. If workspace, policy name */ name: PropTypes.string, }; @@ -76,7 +76,7 @@ function Avatar(props) { const imageStyle = props.imageStyles && props.imageStyles.length ? [StyleUtils.getAvatarStyle(props.size), ...props.imageStyles, StyleUtils.getAvatarBorderRadius(props.size, props.type)] - : [StyleUtils.getAvatarStyle(props.size), styles.noBorderRadius]; + : [StyleUtils.getAvatarStyle(props.size), StyleUtils.getAvatarBorderStyle(props.size, props.type)]; const iconStyle = props.imageStyles && props.imageStyles.length ? [StyleUtils.getAvatarStyle(props.size), styles.bgTransparent, ...props.imageStyles] : undefined; diff --git a/src/components/AvatarWithDisplayName.js b/src/components/AvatarWithDisplayName.js index a5a12e6de980..f63b51cacf99 100644 --- a/src/components/AvatarWithDisplayName.js +++ b/src/components/AvatarWithDisplayName.js @@ -70,8 +70,6 @@ function AvatarWithDisplayName(props) { backgroundColor={themeColors.highlightBG} mainAvatar={icons[0]} secondaryAvatar={icons[1]} - mainTooltip={props.report.ownerEmail} - secondaryTooltip={subtitle} size={props.size} /> ) : ( diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index ca812a408474..0aa21115d5f8 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -19,7 +19,6 @@ import SubscriptAvatar from '../SubscriptAvatar'; import CONST from '../../CONST'; import themeColors from '../../styles/themes/default'; import SidebarUtils from '../../libs/SidebarUtils'; -import TextPill from '../TextPill'; import OfflineWithFeedback from '../OfflineWithFeedback'; import PressableWithSecondaryInteraction from '../PressableWithSecondaryInteraction'; import * as ReportActionContextMenu from '../../pages/home/report/ContextMenu/ReportActionContextMenu'; @@ -83,7 +82,6 @@ function OptionRowLHN(props) { const textStyle = props.isFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText; const textUnreadStyle = optionItem.isUnread ? [textStyle, styles.sidebarLinkTextBold] : [textStyle]; const displayNameStyle = StyleUtils.combineStyles([styles.optionDisplayName, styles.optionDisplayNameCompact, styles.pre, ...textUnreadStyle], props.style); - const textPillStyle = props.isFocused ? [styles.ml1, StyleUtils.getBackgroundColorWithOpacityStyle(themeColors.icon, 0.5)] : [styles.ml1]; const alternateTextStyle = StyleUtils.combineStyles( props.viewMode === CONST.OPTION_MODE.COMPACT ? [textStyle, styles.optionAlternateText, styles.pre, styles.textLabelSupporting, styles.optionAlternateTextCompact, styles.ml2] @@ -101,6 +99,7 @@ function OptionRowLHN(props) { const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor; const hasBrickError = optionItem.brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR; + const defaultSubscriptSize = optionItem.isExpenseRequest ? CONST.AVATAR_SIZE.SMALL_NORMAL : CONST.AVATAR_SIZE.DEFAULT; const shouldShowGreenDotIndicator = !hasBrickError && (optionItem.isUnreadWithMention || @@ -172,9 +171,7 @@ function OptionRowLHN(props) { backgroundColor={props.isFocused ? themeColors.activeComponentBG : themeColors.sidebar} mainAvatar={optionItem.icons[0]} secondaryAvatar={optionItem.icons[1]} - mainTooltip={optionItem.ownerEmail} - secondaryTooltip={optionItem.subtitle} - size={props.viewMode === CONST.OPTION_MODE.COMPACT ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT} + size={props.viewMode === CONST.OPTION_MODE.COMPACT ? CONST.AVATAR_SIZE.SMALL : defaultSubscriptSize} /> ) : ( - {optionItem.isChatRoom && !optionItem.isThread && ( - - )} {optionItem.alternateText ? ( - - + + {/* View is necessary for tooltip to show for multiple avatars in LHN */} - + {props.icons.length === 2 ? ( - + @@ -257,7 +258,7 @@ function MultipleAvatars(props) { ) : ( - + 1; + const defaultSubscriptSize = this.props.option.isExpenseRequest ? CONST.AVATAR_SIZE.SMALL_NORMAL : CONST.AVATAR_SIZE.DEFAULT; // We only create tooltips for the first 10 users or so since some reports have hundreds of users, causing performance to degrade. const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips( @@ -193,9 +194,8 @@ class OptionRow extends Component { ) : ( - + - - - + + + - + ); } diff --git a/src/components/UserDetailsTooltip/index.js b/src/components/UserDetailsTooltip/index.js index a13728fb1074..116e5f34abfe 100644 --- a/src/components/UserDetailsTooltip/index.js +++ b/src/components/UserDetailsTooltip/index.js @@ -12,6 +12,7 @@ import ONYXKEYS from '../../ONYXKEYS'; import withLocalize from '../withLocalize'; import compose from '../../libs/compose'; import * as UserUtils from '../../libs/UserUtils'; +import CONST from '../../CONST'; import * as LocalePhoneNumber from '../../libs/LocalePhoneNumber'; function UserDetailsTooltip(props) { @@ -32,27 +33,30 @@ function UserDetailsTooltip(props) { userAccountID = props.delegateAccountID; } + let title = String(userDisplayName).trim() ? userDisplayName : ''; + const subtitle = (userLogin || '').trim() && !_.isEqual(LocalePhoneNumber.formatPhoneNumber(userLogin || ''), userDisplayName) ? Str.removeSMSDomain(userLogin) : ''; + if (props.icon && props.icon.type === CONST.ICON_TYPE_WORKSPACE) { + title = props.icon.name; + } const renderTooltipContent = useCallback( () => ( - - {userDisplayName} - - - {(userLogin || '').trim() && !_.isEqual(LocalePhoneNumber.formatPhoneNumber(userLogin || ''), userDisplayName) ? Str.removeSMSDomain(userLogin) : ''} - + {title} + {subtitle} ), - [userAvatar, userDisplayName, userLogin, userAccountID], + [props.icon, userAvatar, userAccountID, userLogin, title, subtitle], ); - if (!userDisplayName && !userLogin) { + if (!props.icon && !userDisplayName && !userLogin) { return props.children; } diff --git a/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js b/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js index 0bf0f5f9b7cb..271e74aaf06c 100644 --- a/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js +++ b/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import personalDetailsPropType from '../../pages/personalDetailsPropType'; +import avatarPropTypes from '../avatarPropTypes'; import {withLocalizePropTypes} from '../withLocalize'; const propTypes = { @@ -13,7 +14,11 @@ const propTypes = { displayName: PropTypes.string, /** Login */ login: PropTypes.string, + /** Whether this is a Workspace Avatar or User Avatar */ + type: PropTypes.string, }), + /** Optionally, pass in the icon instead of calculating it. If defined, will take precedence. */ + icon: avatarPropTypes, /** Component that displays the tooltip */ children: PropTypes.node.isRequired, /** List of personalDetails (keyed by accountID) */ @@ -28,9 +33,10 @@ const propTypes = { const defaultProps = { accountID: '', - fallbackUserDetails: {displayName: '', login: '', avatar: ''}, + fallbackUserDetails: {displayName: '', login: '', avatar: '', type: ''}, personalDetailsList: {}, delegateAccountID: 0, + icon: undefined, }; export {propTypes, defaultProps}; diff --git a/src/components/avatarPropTypes.js b/src/components/avatarPropTypes.js index c068b481c596..7e978fc74963 100644 --- a/src/components/avatarPropTypes.js +++ b/src/components/avatarPropTypes.js @@ -5,4 +5,5 @@ export default PropTypes.shape({ source: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), type: PropTypes.oneOf([CONST.ICON_TYPE_AVATAR, CONST.ICON_TYPE_WORKSPACE]), name: PropTypes.string, + id: PropTypes.number, }); diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index d19ecb79a67a..558d2f9bb7ba 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -444,6 +444,7 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, { isArchivedRoom: false, shouldShowSubscript: false, isPolicyExpenseChat: false, + isExpenseReport: false, }; const personalDetailMap = getPersonalDetailsForAccountIDs(accountIDs, personalDetails); @@ -460,6 +461,7 @@ function createOption(accountIDs, personalDetails, report, reportActions = {}, { result.isDefaultRoom = ReportUtils.isDefaultRoom(report); result.isArchivedRoom = ReportUtils.isArchivedRoom(report); result.isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); + result.isExpenseReport = ReportUtils.isExpenseReport(report); result.isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report); result.isThread = ReportUtils.isChatThread(report); result.isTaskReport = ReportUtils.isTaskReport(report); diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index 72f642d3e844..e481f83c707c 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -356,6 +356,20 @@ function getBankAccountRoute(report) { return isPolicyExpenseChat(report) ? ROUTES.getBankAccountRoute('', report.policyID) : ROUTES.SETTINGS_ADD_BANK_ACCOUNT; } +/** + * Checks if a report is a task report from a policy expense chat. + * + * @param {Object} report + * @returns {Boolean} + */ +function isWorkspaceTaskReport(report) { + if (!isTaskReport(report)) { + return false; + } + const parentReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`]; + return isPolicyExpenseChat(parentReport); +} + /** * Returns true if report has a parent * @@ -531,6 +545,26 @@ function isPolicyExpenseChatAdmin(report, policies) { return policyRole === CONST.POLICY.ROLE.ADMIN; } +/** + * Returns true if report is a DM/Group DM chat. + * + * @param {Object} report + * @returns {Boolean} + */ +function isDM(report) { + return !getChatType(report); +} + +/** + * If the report is a thread and has a chat type set, it is a workspace chat. + * + * @param {Object} report + * @returns {Boolean} + */ +function isWorkspaceThread(report) { + return Boolean(isThread(report) && !isDM(report)); +} + /** * Returns true if reportAction has a child. * @@ -552,6 +586,22 @@ function isThreadFirstChat(reportAction, reportID) { return !_.isUndefined(reportAction.childReportID) && reportAction.childReportID.toString() === reportID; } +/** + * An Expense Request is a thread where the parent report is an Expense Report and + * the parentReportAction is a transaction. + * + * @param {Object} report + * @returns {Boolean} + */ +function isExpenseRequest(report) { + if (isThread(report)) { + const parentReportAction = ReportActionsUtils.getParentReportAction(report); + const parentReport = lodashGet(allReports, [`${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`]); + return isExpenseReport(parentReport) && ReportActionsUtils.isTransactionThread(parentReportAction); + } + return false; +} + /** * Get welcome message based on room type * @param {Object} report @@ -700,6 +750,24 @@ function getIconsForParticipants(participants, personalDetails) { return avatars; } +/** + * Given a report, return the associated workspace icon. + * + * @param {Object} report + * @returns {Object} + */ +function getWorkspaceIcon(report) { + const workspaceName = getPolicyName(report); + const policyExpenseChatAvatarSource = lodashGet(allPolicies, [`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'avatar']) || getDefaultWorkspaceAvatar(workspaceName); + const workspaceIcon = { + source: policyExpenseChatAvatarSource, + type: CONST.ICON_TYPE_WORKSPACE, + name: workspaceName, + id: -1, + }; + return workspaceIcon; +} + /** * Returns the appropriate icons for the given chat report using the stored personalDetails. * The Avatar sources can be URLs or Icon components according to the chat type. @@ -712,27 +780,32 @@ function getIconsForParticipants(participants, personalDetails) { * @param {Number} [defaultAccountID] * @returns {Array<*>} */ -function getIcons(report, personalDetails, defaultIcon = null, isPayer = false, defaultName = '', defaultAccountID = undefined) { - const result = { - source: '', - type: CONST.ICON_TYPE_AVATAR, - name: '', - }; - +function getIcons(report, personalDetails, defaultIcon = null, isPayer = false) { if (_.isEmpty(report)) { - result.source = defaultIcon || Expensicons.FallbackAvatar; - result.name = defaultName || ''; - result.id = defaultAccountID; - return [result]; + const fallbackIcon = { + source: defaultIcon || Expensicons.FallbackAvatar, + type: CONST.ICON_TYPE_AVATAR, + name: '', + id: -1, + }; + return [fallbackIcon]; } - if (isArchivedRoom(report)) { - result.source = Expensicons.DeletedRoomAvatar; - return [result]; + if (isExpenseRequest(report)) { + const parentReportAction = ReportActionsUtils.getParentReportAction(report); + const workspaceIcon = getWorkspaceIcon(report); + const memberIcon = { + source: UserUtils.getAvatar(lodashGet(personalDetails, [parentReportAction.actorAccountID, 'avatar']), parentReportAction.actorAccountID), + id: parentReportAction.actorAccountID, + type: CONST.ICON_TYPE_AVATAR, + name: lodashGet(personalDetails, [parentReportAction.actorAccountID, 'displayName'], ''), + }; + + return [memberIcon, workspaceIcon]; } if (isChatThread(report)) { const parentReportAction = ReportActionsUtils.getParentReportAction(report); - const actorAccountID = lodashGet(parentReportAction, 'actorAccountID', 0); + const actorAccountID = lodashGet(parentReportAction, 'actorAccountID', -1); const actorDisplayName = lodashGet(allPersonalDetails, [actorAccountID, 'displayName'], ''); const actorIcon = { id: actorAccountID, @@ -741,78 +814,70 @@ function getIcons(report, personalDetails, defaultIcon = null, isPayer = false, type: CONST.ICON_TYPE_AVATAR, }; + if (isWorkspaceThread(report)) { + const workspaceIcon = getWorkspaceIcon(report); + return [actorIcon, workspaceIcon]; + } return [actorIcon]; } if (isTaskReport(report)) { - const ownerEmail = report.ownerEmail || ''; const ownerIcon = { id: report.ownerAccountID, source: UserUtils.getAvatar(lodashGet(personalDetails, [report.ownerAccountID, 'avatar']), report.ownerAccountID), - name: ownerEmail, type: CONST.ICON_TYPE_AVATAR, + name: lodashGet(personalDetails, [report.ownerAccountID, 'displayName'], ''), }; + if (isWorkspaceTaskReport(report)) { + const workspaceIcon = getWorkspaceIcon(report); + return [ownerIcon, workspaceIcon]; + } + return [ownerIcon]; } if (isDomainRoom(report)) { - result.source = Expensicons.DomainRoomAvatar; - return [result]; - } - if (isAdminRoom(report)) { - result.source = Expensicons.AdminRoomAvatar; - return [result]; - } - if (isAnnounceRoom(report)) { - result.source = Expensicons.AnnounceRoomAvatar; - return [result]; + // Get domain name after the #. Domain Rooms use our default workspace avatar pattern. + const domainName = report.reportName.substring(1); + const policyExpenseChatAvatarSource = getDefaultWorkspaceAvatar(domainName); + const domainIcon = { + source: policyExpenseChatAvatarSource, + type: CONST.ICON_TYPE_WORKSPACE, + name: domainName, + id: -1, + }; + return [domainIcon]; } - if (isChatRoom(report)) { - result.source = Expensicons.ActiveRoomAvatar; - return [result]; + if (isAdminRoom(report) || isAnnounceRoom(report) || isChatRoom(report) || isArchivedRoom(report)) { + const workspaceIcon = getWorkspaceIcon(report); + return [workspaceIcon]; } if (isPolicyExpenseChat(report) || isExpenseReport(report)) { - const workspaceName = getPolicyName(report); - - const policyExpenseChatAvatarSource = getWorkspaceAvatar(report); - - // Return the workspace avatar if the user is the owner of the policy expense chat - if (report.isOwnPolicyExpenseChat && !isExpenseReport(report)) { - result.source = policyExpenseChatAvatarSource; - result.type = CONST.ICON_TYPE_WORKSPACE; - result.name = workspaceName; - return [result]; - } - - const adminIcon = { - id: report.ownerAccountID, + const workspaceIcon = getWorkspaceIcon(report); + const memberIcon = { source: UserUtils.getAvatar(lodashGet(personalDetails, [report.ownerAccountID, 'avatar']), report.ownerAccountID), - name: report.ownerEmail, + id: report.ownerAccountID, + type: CONST.ICON_TYPE_AVATAR, + name: lodashGet(personalDetails, [report.ownerAccountID, 'displayName'], ''), + }; + return isExpenseReport(report) ? [memberIcon, workspaceIcon] : [workspaceIcon, memberIcon]; + } + if (isIOUReport(report)) { + const managerIcon = { + source: UserUtils.getAvatar(lodashGet(personalDetails, [report.managerID, 'avatar']), report.managerID), + id: report.managerID, type: CONST.ICON_TYPE_AVATAR, + name: lodashGet(personalDetails, [report.managerID, 'displayName'], ''), }; - const workspaceIcon = { - source: policyExpenseChatAvatarSource, - type: CONST.ICON_TYPE_WORKSPACE, - name: workspaceName, + const ownerIcon = { + id: report.ownerAccountID, + source: UserUtils.getAvatar(lodashGet(personalDetails, [report.ownerAccountID, 'avatar']), report.ownerAccountID), + type: CONST.ICON_TYPE_AVATAR, + name: lodashGet(personalDetails, [report.ownerAccountID, 'displayName'], ''), }; - // If the user is an admin, return avatar source of the other participant of the report - // (their workspace chat) and the avatar source of the workspace - return [adminIcon, workspaceIcon]; - } - if (isIOUReport(report)) { - const email = isPayer ? report.managerEmail : report.ownerEmail; - const accountID = isPayer ? report.managerID : report.ownerAccountID; - return [ - { - id: accountID, - source: UserUtils.getAvatar(lodashGet(personalDetails, [accountID, 'avatar']), accountID), - name: email, - type: CONST.ICON_TYPE_AVATAR, - }, - ]; + return isPayer ? [managerIcon, ownerIcon] : [ownerIcon, managerIcon]; } - return getIconsForParticipants(report.participantAccountIDs, personalDetails); } @@ -2324,7 +2389,7 @@ function getWhisperDisplayNames(participantAccountIDs) { } /** - * Show subscript on IOU or expense report + * Show subscript on workspace chats / threads and expense requests * @param {Object} report * @returns {Boolean} */ @@ -2337,7 +2402,23 @@ function shouldReportShowSubscript(report) { return true; } - return isExpenseReport(report); + if (isPolicyExpenseChat(report) && !isThread(report) && !isTaskReport(report)) { + return true; + } + + if (isExpenseRequest(report)) { + return true; + } + + if (isWorkspaceTaskReport(report)) { + return true; + } + + if (isWorkspaceThread(report)) { + return true; + } + + return false; } /** @@ -2451,6 +2532,7 @@ export { getDisplayNameForParticipant, isChatReport, isExpenseReport, + isExpenseRequest, isIOUReport, isTaskReport, isTaskCompleted, diff --git a/src/libs/SidebarUtils.js b/src/libs/SidebarUtils.js index f51623e6fa0a..1e7a9131df2f 100644 --- a/src/libs/SidebarUtils.js +++ b/src/libs/SidebarUtils.js @@ -258,6 +258,7 @@ function getOptionData(reportID) { shouldShowSubscript: false, isPolicyExpenseChat: false, isMoneyRequestReport: false, + isExpenseRequest: false, }; const participantPersonalDetailList = _.values(OptionsListUtils.getPersonalDetailsForAccountIDs(report.participantAccountIDs, personalDetails)); @@ -272,6 +273,7 @@ function getOptionData(reportID) { } result.isArchivedRoom = ReportUtils.isArchivedRoom(report); result.isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); + result.isExpenseRequest = ReportUtils.isExpenseRequest(report); result.isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report); result.shouldShowSubscript = ReportUtils.shouldReportShowSubscript(report); result.pendingAction = report.pendingFields ? report.pendingFields.addWorkspaceRoom || report.pendingFields.createChat : null; diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 955b5e5c2936..e0c338657ba6 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -130,6 +130,7 @@ function HeaderView(props) { const shouldShowThreeDotsButton = !!threeDotMenuItems.length; const shouldShowSubscript = ReportUtils.shouldReportShowSubscript(props.report); + const defaultSubscriptSize = ReportUtils.isExpenseRequest(props.report) ? CONST.AVATAR_SIZE.SMALL_NORMAL : CONST.AVATAR_SIZE.DEFAULT; const icons = ReportUtils.getIcons(reportHeaderData, props.personalDetails); const brickRoadIndicator = ReportUtils.hasReportNameError(props.report) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''; return ( @@ -169,8 +170,7 @@ function HeaderView(props) { ) : ( 0; const shouldDisplayThreadReplies = hasReplies && props.action.childCommenterCount && !ReportUtils.isThreadFirstChat(props.action, props.report.reportID); - const oldestFourAccountIDs = lodashGet(props.action, 'childOldestFourAccountIDs', '').split(','); + const oldestFourAccountIDs = _.map(lodashGet(props.action, 'childOldestFourAccountIDs', '').split(','), (accountID) => Number(accountID)); const draftMessageRightAlign = props.draftMessage ? styles.chatItemReactionsDraftRight : {}; return ( diff --git a/src/pages/home/report/ReportActionItemSingle.js b/src/pages/home/report/ReportActionItemSingle.js index 3011dff69bf1..30a02336aa42 100644 --- a/src/pages/home/report/ReportActionItemSingle.js +++ b/src/pages/home/report/ReportActionItemSingle.js @@ -91,6 +91,7 @@ function ReportActionItemSingle(props) { displayName = actorHint; avatarSource = UserUtils.getAvatar(delegateDetails.avatar, props.action.delegateAccountID); } + const icon = {source: avatarSource, type: isWorkspaceActor ? CONST.ICON_TYPE_WORKSPACE : CONST.ICON_TYPE_AVATAR, name: displayName, id: actorAccountID}; // Since the display name for a report action message is delivered with the report history as an array of fragments // we'll need to take the displayName from personal details and have it be in the same format for now. Eventually, @@ -125,7 +126,7 @@ function ReportActionItemSingle(props) { {props.shouldShowSubscriptAvatar ? ( diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js index 59a5938ef923..1fbc14795997 100644 --- a/src/styles/StyleUtils.js +++ b/src/styles/StyleUtils.js @@ -43,6 +43,7 @@ const avatarBorderSizes = { [CONST.AVATAR_SIZE.MEDIUM]: variables.componentBorderRadiusLarge, [CONST.AVATAR_SIZE.LARGE]: variables.componentBorderRadiusLarge, [CONST.AVATAR_SIZE.LARGE_BORDERED]: variables.componentBorderRadiusRounded, + [CONST.AVATAR_SIZE.SMALL_NORMAL]: variables.componentBorderRadiusMedium, }; const avatarSizes = { @@ -57,6 +58,7 @@ const avatarSizes = { [CONST.AVATAR_SIZE.LARGE_BORDERED]: variables.avatarSizeLargeBordered, [CONST.AVATAR_SIZE.HEADER]: variables.avatarSizeHeader, [CONST.AVATAR_SIZE.MENTION_ICON]: variables.avatarSizeMentionIcon, + [CONST.AVATAR_SIZE.SMALL_NORMAL]: variables.avatarSizeSmallNormal, }; const emptyAvatarStyles = { diff --git a/src/styles/styles.js b/src/styles/styles.js index dbea05a367c0..e60a7ee78fb5 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1840,6 +1840,12 @@ const styles = { right: -1, }, + secondAvatarSubscriptSmallNormal: { + position: 'absolute', + bottom: 0, + right: 0, + }, + leftSideLargeAvatar: { left: 15, }, @@ -1913,6 +1919,11 @@ const styles = { width: variables.avatarSizeNormal, }, + emptyAvatarSmallNormal: { + height: variables.avatarSizeSmallNormal, + width: variables.avatarSizeSmallNormal, + }, + emptyAvatarSmall: { height: variables.avatarSizeSmall, width: variables.avatarSizeSmall, @@ -3137,18 +3148,6 @@ const styles = { zIndex: 2, }, - textPill: { - backgroundColor: themeColors.border, - borderRadius: 10, - overflow: 'hidden', - paddingVertical: 2, - flexShrink: 0, - maxWidth: variables.badgeMaxWidth, - fontSize: variables.fontSizeSmall, - ...whiteSpace.pre, - ...spacing.ph2, - }, - dropZoneTopInvisibleOverlay: { position: 'absolute', width: '100%', diff --git a/src/styles/variables.js b/src/styles/variables.js index 5313abc72fe4..a771aa95906e 100644 --- a/src/styles/variables.js +++ b/src/styles/variables.js @@ -29,15 +29,16 @@ export default { componentBorderRadiusCard: 12, componentBorderRadiusRounded: 24, buttonBorderRadius: 100, - avatarSizeLarge: 80, - avatarSizeHeader: 40, avatarSizeLargeBordered: 88, + avatarSizeLarge: 80, avatarSizeMedium: 52, + avatarSizeHeader: 40, avatarSizeNormal: 40, + avatarSizeSmallNormal: 32, avatarSizeSmall: 28, avatarSizeSmaller: 24, - avatarSizeMidSubscript: 18, avatarSizeSubscript: 20, + avatarSizeMidSubscript: 18, avatarSizeMentionIcon: 16, avatarSizeSmallSubscript: 14, defaultAvatarPreviewSize: 360,