diff --git a/assets/images/avatars/fallback-avatar.svg b/assets/images/avatars/fallback-avatar.svg index f509ba03b1a5..0d71e0fbc210 100644 --- a/assets/images/avatars/fallback-avatar.svg +++ b/assets/images/avatars/fallback-avatar.svg @@ -3,7 +3,7 @@ diff --git a/assets/images/avatars/workspace/default-avatar_0.svg b/assets/images/avatars/workspace/default-avatar_0.svg new file mode 100644 index 000000000000..c942281517f4 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_0.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_1.svg b/assets/images/avatars/workspace/default-avatar_1.svg new file mode 100644 index 000000000000..e6b0c71b53d4 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_1.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_2.svg b/assets/images/avatars/workspace/default-avatar_2.svg new file mode 100644 index 000000000000..c7d469d662ba --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_2.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_3.svg b/assets/images/avatars/workspace/default-avatar_3.svg new file mode 100644 index 000000000000..04c5d6d99372 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_3.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_4.svg b/assets/images/avatars/workspace/default-avatar_4.svg new file mode 100644 index 000000000000..e547481faefd --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_4.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_5.svg b/assets/images/avatars/workspace/default-avatar_5.svg new file mode 100644 index 000000000000..6b8c654ee784 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_5.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_6.svg b/assets/images/avatars/workspace/default-avatar_6.svg new file mode 100644 index 000000000000..c8f155995263 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_6.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_7.svg b/assets/images/avatars/workspace/default-avatar_7.svg new file mode 100644 index 000000000000..714725c62f2f --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_7.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_8.svg b/assets/images/avatars/workspace/default-avatar_8.svg new file mode 100644 index 000000000000..edca9a464610 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_8.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_9.svg b/assets/images/avatars/workspace/default-avatar_9.svg new file mode 100644 index 000000000000..0cc78a5dae7e --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_9.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_a.svg b/assets/images/avatars/workspace/default-avatar_a.svg new file mode 100644 index 000000000000..5ea6d7a1dd0e --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_a.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_b.svg b/assets/images/avatars/workspace/default-avatar_b.svg new file mode 100644 index 000000000000..dfdef9451455 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_b.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_building.svg b/assets/images/avatars/workspace/default-avatar_building.svg new file mode 100644 index 000000000000..69c0f0e73dc4 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_building.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_c.svg b/assets/images/avatars/workspace/default-avatar_c.svg new file mode 100644 index 000000000000..d09cd384d458 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_c.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_d.svg b/assets/images/avatars/workspace/default-avatar_d.svg new file mode 100644 index 000000000000..2d8fb68adf58 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_d.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_e.svg b/assets/images/avatars/workspace/default-avatar_e.svg new file mode 100644 index 000000000000..a21981f244c5 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_e.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_f.svg b/assets/images/avatars/workspace/default-avatar_f.svg new file mode 100644 index 000000000000..2f1323e2c7f9 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_f.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_g.svg b/assets/images/avatars/workspace/default-avatar_g.svg new file mode 100644 index 000000000000..51ff96cdfb7b --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_g.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_h.svg b/assets/images/avatars/workspace/default-avatar_h.svg new file mode 100644 index 000000000000..ddabaa42d06b --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_h.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_i.svg b/assets/images/avatars/workspace/default-avatar_i.svg new file mode 100644 index 000000000000..e9bc60254e2e --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_i.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_j.svg b/assets/images/avatars/workspace/default-avatar_j.svg new file mode 100644 index 000000000000..9daf382ca8ef --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_j.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_k.svg b/assets/images/avatars/workspace/default-avatar_k.svg new file mode 100644 index 000000000000..6018a9912f2c --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_k.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_l.svg b/assets/images/avatars/workspace/default-avatar_l.svg new file mode 100644 index 000000000000..4fd4e62ff93a --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_l.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_m.svg b/assets/images/avatars/workspace/default-avatar_m.svg new file mode 100644 index 000000000000..e2eea24f1af9 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_m.svg @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_n.svg b/assets/images/avatars/workspace/default-avatar_n.svg new file mode 100644 index 000000000000..d1f036614c08 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_n.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_o.svg b/assets/images/avatars/workspace/default-avatar_o.svg new file mode 100644 index 000000000000..5f2c8e89fc89 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_o.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_p.svg b/assets/images/avatars/workspace/default-avatar_p.svg new file mode 100644 index 000000000000..4729bbc0afb9 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_p.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_q.svg b/assets/images/avatars/workspace/default-avatar_q.svg new file mode 100644 index 000000000000..ebdd318460e9 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_q.svg @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_r.svg b/assets/images/avatars/workspace/default-avatar_r.svg new file mode 100644 index 000000000000..015869a190ad --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_r.svg @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_s.svg b/assets/images/avatars/workspace/default-avatar_s.svg new file mode 100644 index 000000000000..334af3a15636 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_s.svg @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_t.svg b/assets/images/avatars/workspace/default-avatar_t.svg new file mode 100644 index 000000000000..9ab5962f9ba1 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_t.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_u.svg b/assets/images/avatars/workspace/default-avatar_u.svg new file mode 100644 index 000000000000..04daa1bd4b04 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_u.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_v.svg b/assets/images/avatars/workspace/default-avatar_v.svg new file mode 100644 index 000000000000..a94242b787e0 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_v.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_w.svg b/assets/images/avatars/workspace/default-avatar_w.svg new file mode 100644 index 000000000000..a0756f443422 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_w.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_x.svg b/assets/images/avatars/workspace/default-avatar_x.svg new file mode 100644 index 000000000000..516da8c1b563 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_x.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_y.svg b/assets/images/avatars/workspace/default-avatar_y.svg new file mode 100644 index 000000000000..435d0d79bc79 --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_y.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/assets/images/avatars/workspace/default-avatar_z.svg b/assets/images/avatars/workspace/default-avatar_z.svg new file mode 100644 index 000000000000..48bb76f4a72a --- /dev/null +++ b/assets/images/avatars/workspace/default-avatar_z.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/src/CONST.js b/src/CONST.js index 30f9e24ae3e7..71a3b4aba7bc 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -764,6 +764,8 @@ const CONST = { ICON_TYPE_ICON: 'icon', ICON_TYPE_AVATAR: 'avatar', + ICON_TYPE_WORKSPACE: 'workspace', + AVATAR_SIZE: { LARGE: 'large', MEDIUM: 'medium', diff --git a/src/components/Avatar.js b/src/components/Avatar.js index 3aaddd895ea8..ed05a78d18c4 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -13,6 +13,7 @@ import Image from './Image'; import {withNetwork} from './OnyxProvider'; import networkPropTypes from './networkPropTypes'; import styles from '../styles/styles'; +import * as ReportUtils from '../libs/ReportUtils'; const propTypes = { /** Source for the avatar. Can be a URL or an icon. */ @@ -28,12 +29,23 @@ const propTypes = { /** Set the size of Avatar */ size: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), - /** The fill color for the icon. Can be hex, rgb, rgba, or valid react-native named color such as 'red' or 'blue' */ + /** + * The fill color for the icon. Can be hex, rgb, rgba, or valid react-native named color such as 'red' or 'blue' + * If the avatar is type === workspace, this fill color will be ignored and decided based on the name prop. + */ fill: PropTypes.string, - /** A fallback avatar icon to display when there is an error on loading avatar from remote URL. */ + /** A fallback avatar icon to display when there is an error on loading avatar from remote URL. + * If the avatar is type === workspace, this fallback icon will be ignored and decided based on the name prop. + */ fallbackIcon: PropTypes.func, + /** 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 */ + name: PropTypes.string, + /** Props to detect online status */ network: networkPropTypes.isRequired, }; @@ -45,6 +57,8 @@ const defaultProps = { size: CONST.AVATAR_SIZE.DEFAULT, fill: themeColors.icon, fallbackIcon: Expensicons.FallbackAvatar, + type: CONST.ICON_TYPE_AVATAR, + name: '', }; class Avatar extends PureComponent { @@ -68,9 +82,13 @@ class Avatar extends PureComponent { return null; } + const isWorkspace = this.props.type === CONST.ICON_TYPE_WORKSPACE; + const iconSize = StyleUtils.getAvatarSize(this.props.size); + const imageStyle = [ StyleUtils.getAvatarStyle(this.props.size), ...this.props.imageStyles, + StyleUtils.getAvatarBorderRadius(this.props.size, this.props.type), ]; const iconStyle = [ @@ -78,7 +96,9 @@ class Avatar extends PureComponent { styles.bgTransparent, ...this.props.imageStyles, ]; - const iconSize = StyleUtils.getAvatarSize(this.props.size); + + const iconFillColor = isWorkspace ? StyleUtils.getDefaultWorspaceAvatarColor(this.props.name).fill : this.props.fill; + const fallbackAvatar = isWorkspace ? ReportUtils.getDefaultWorkspaceAvatar(this.props.name) : this.props.fallbackIcon; return ( @@ -86,11 +106,15 @@ class Avatar extends PureComponent { ? ( ) diff --git a/src/components/AvatarWithImagePicker.js b/src/components/AvatarWithImagePicker.js index a2fa0f41da28..6f33445ba146 100644 --- a/src/components/AvatarWithImagePicker.js +++ b/src/components/AvatarWithImagePicker.js @@ -57,6 +57,9 @@ const propTypes = { /** A fallback avatar icon to display when there is an error on loading avatar from remote URL. */ fallbackIcon: PropTypes.func, + /** Denotes whether it is an avatar or a workspace avatar */ + type: PropTypes.oneOf([CONST.ICON_TYPE_AVATAR, CONST.ICON_TYPE_WORKSPACE]), + ...withLocalizePropTypes, }; @@ -70,6 +73,7 @@ const defaultProps = { isUploading: false, size: CONST.AVATAR_SIZE.DEFAULT, fallbackIcon: Expensicons.FallbackAvatar, + type: CONST.ICON_TYPE_AVATAR, }; class AvatarWithImagePicker extends React.Component { @@ -258,6 +262,7 @@ class AvatarWithImagePicker extends React.Component { source={this.props.source} fallbackIcon={this.props.fallbackIcon} size={this.props.size} + type={this.props.type} /> ) : ( diff --git a/src/components/IOUConfirmationList.js b/src/components/IOUConfirmationList.js index ea012dd32417..b6b834828e67 100755 --- a/src/components/IOUConfirmationList.js +++ b/src/components/IOUConfirmationList.js @@ -16,6 +16,7 @@ import SettlementButton from './SettlementButton'; import ROUTES from '../ROUTES'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from './withCurrentUserPersonalDetails'; import * as IOUUtils from '../libs/IOUUtils'; +import avatarPropTypes from './avatarPropTypes'; const propTypes = { /** Callback to inform parent modal of success */ @@ -44,7 +45,7 @@ const propTypes = { login: PropTypes.string.isRequired, alternateText: PropTypes.string, hasDraftComment: PropTypes.bool, - icons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), + icons: PropTypes.arrayOf(avatarPropTypes), searchText: PropTypes.string, text: PropTypes.string, keyForList: PropTypes.string, diff --git a/src/components/Icon/WorkspaceDefaultAvatars.js b/src/components/Icon/WorkspaceDefaultAvatars.js new file mode 100644 index 000000000000..0f5490b981bd --- /dev/null +++ b/src/components/Icon/WorkspaceDefaultAvatars.js @@ -0,0 +1,77 @@ +import Workspace0 from '../../../assets/images/avatars/workspace/default-avatar_0.svg'; +import Workspace1 from '../../../assets/images/avatars/workspace/default-avatar_1.svg'; +import Workspace2 from '../../../assets/images/avatars/workspace/default-avatar_2.svg'; +import Workspace3 from '../../../assets/images/avatars/workspace/default-avatar_3.svg'; +import Workspace4 from '../../../assets/images/avatars/workspace/default-avatar_4.svg'; +import Workspace5 from '../../../assets/images/avatars/workspace/default-avatar_5.svg'; +import Workspace6 from '../../../assets/images/avatars/workspace/default-avatar_6.svg'; +import Workspace7 from '../../../assets/images/avatars/workspace/default-avatar_7.svg'; +import Workspace8 from '../../../assets/images/avatars/workspace/default-avatar_8.svg'; +import Workspace9 from '../../../assets/images/avatars/workspace/default-avatar_9.svg'; +import WorkspaceA from '../../../assets/images/avatars/workspace/default-avatar_a.svg'; +import WorkspaceB from '../../../assets/images/avatars/workspace/default-avatar_b.svg'; +import WorkspaceC from '../../../assets/images/avatars/workspace/default-avatar_c.svg'; +import WorkspaceD from '../../../assets/images/avatars/workspace/default-avatar_d.svg'; +import WorkspaceE from '../../../assets/images/avatars/workspace/default-avatar_e.svg'; +import WorkspaceF from '../../../assets/images/avatars/workspace/default-avatar_f.svg'; +import WorkspaceG from '../../../assets/images/avatars/workspace/default-avatar_g.svg'; +import WorkspaceH from '../../../assets/images/avatars/workspace/default-avatar_h.svg'; +import WorkspaceI from '../../../assets/images/avatars/workspace/default-avatar_i.svg'; +import WorkspaceJ from '../../../assets/images/avatars/workspace/default-avatar_j.svg'; +import WorkspaceK from '../../../assets/images/avatars/workspace/default-avatar_k.svg'; +import WorkspaceL from '../../../assets/images/avatars/workspace/default-avatar_l.svg'; +import WorkspaceM from '../../../assets/images/avatars/workspace/default-avatar_m.svg'; +import WorkspaceN from '../../../assets/images/avatars/workspace/default-avatar_n.svg'; +import WorkspaceO from '../../../assets/images/avatars/workspace/default-avatar_o.svg'; +import WorkspaceP from '../../../assets/images/avatars/workspace/default-avatar_p.svg'; +import WorkspaceQ from '../../../assets/images/avatars/workspace/default-avatar_q.svg'; +import WorkspaceR from '../../../assets/images/avatars/workspace/default-avatar_r.svg'; +import WorkspaceS from '../../../assets/images/avatars/workspace/default-avatar_s.svg'; +import WorkspaceT from '../../../assets/images/avatars/workspace/default-avatar_t.svg'; +import WorkspaceU from '../../../assets/images/avatars/workspace/default-avatar_u.svg'; +import WorkspaceV from '../../../assets/images/avatars/workspace/default-avatar_v.svg'; +import WorkspaceW from '../../../assets/images/avatars/workspace/default-avatar_w.svg'; +import WorkspaceX from '../../../assets/images/avatars/workspace/default-avatar_x.svg'; +import WorkspaceY from '../../../assets/images/avatars/workspace/default-avatar_y.svg'; +import WorkspaceZ from '../../../assets/images/avatars/workspace/default-avatar_z.svg'; +import WorkspaceBuilding from '../../../assets/images/avatars/workspace/default-avatar_building.svg'; + +export { + Workspace0, + Workspace1, + Workspace2, + Workspace3, + Workspace4, + Workspace5, + Workspace6, + Workspace7, + Workspace8, + Workspace9, + WorkspaceA, + WorkspaceB, + WorkspaceC, + WorkspaceD, + WorkspaceE, + WorkspaceF, + WorkspaceG, + WorkspaceH, + WorkspaceI, + WorkspaceJ, + WorkspaceK, + WorkspaceL, + WorkspaceM, + WorkspaceN, + WorkspaceO, + WorkspaceP, + WorkspaceQ, + WorkspaceR, + WorkspaceS, + WorkspaceT, + WorkspaceU, + WorkspaceV, + WorkspaceW, + WorkspaceX, + WorkspaceY, + WorkspaceZ, + WorkspaceBuilding, +}; diff --git a/src/components/Icon/index.js b/src/components/Icon/index.js index e2017cc5b923..c65030afc407 100644 --- a/src/components/Icon/index.js +++ b/src/components/Icon/index.js @@ -17,7 +17,7 @@ const propTypes = { /** The height of the icon. */ height: PropTypes.number, - /** The fill color for the icon. Can be hex, rgb, rgba, or valid react-native named color such as 'red' or 'blue' */ + /** The fill color for the icon. Can be hex, rgb, rgba, or valid react-native named color such as 'red' or 'blue'. */ fill: PropTypes.string, /** Is small icon */ @@ -26,8 +26,8 @@ const propTypes = { /** Is inline icon */ inline: PropTypes.bool, - /** Is SVG avatar icon */ - isSVGAvatar: PropTypes.bool, + // eslint-disable-next-line react/forbid-prop-types + additionalStyles: PropTypes.arrayOf(PropTypes.object), }; const defaultProps = { @@ -36,7 +36,7 @@ const defaultProps = { fill: themeColors.icon, small: false, inline: false, - isSVGAvatar: false, + additionalStyles: [], }; // We must use a class component to create an animatable component with the Animated API @@ -46,7 +46,8 @@ class Icon extends PureComponent { const width = this.props.small ? variables.iconSizeSmall : this.props.width; const height = this.props.small ? variables.iconSizeSmall : this.props.height; const iconStyles = [StyleUtils.getWidthAndHeightStyle(width, height), IconWrapperStyles, styles.pAbsolute, - StyleUtils.getAvatarSVGBorder(this.props.isSVGAvatar)]; + ...this.props.additionalStyles, + ]; if (this.props.inline) { return ( @@ -66,7 +67,10 @@ class Icon extends PureComponent { } return ( - + {}, interactive: true, fallbackIcon: Expensicons.FallbackAvatar, @@ -88,36 +89,42 @@ const MenuItem = (props) => { {({hovered, pressed}) => ( <> - {(props.icon && props.iconType === CONST.ICON_TYPE_ICON) && ( + {props.icon && ( - - - )} - {(props.icon && props.iconType === CONST.ICON_TYPE_AVATAR) && ( - - + {(props.iconType === CONST.ICON_TYPE_ICON) && ( + + )} + {(props.iconType === CONST.ICON_TYPE_WORKSPACE) && ( + + + )} + {(props.iconType === CONST.ICON_TYPE_AVATAR) && ( + + )} )} @@ -173,7 +180,7 @@ const MenuItem = (props) => { isPressed={pressed} icons={props.floatRightAvatars} size={props.viewMode === CONST.OPTION_MODE.COMPACT ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT} - fallbackIcon={Expensicons.Workspace} + fallbackIcon={defaultWorkspaceAvatars.WorkspaceBuilding} shouldStackHorizontally={props.shouldStackHorizontally} /> diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js index ac8c972fb066..6e30a2579a25 100644 --- a/src/components/MultipleAvatars.js +++ b/src/components/MultipleAvatars.js @@ -10,10 +10,11 @@ import themeColors from '../styles/themes/default'; import * as StyleUtils from '../styles/StyleUtils'; import CONST from '../CONST'; import variables from '../styles/variables'; +import avatarPropTypes from './avatarPropTypes'; const propTypes = { /** Array of avatar URLs or icons */ - icons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), + icons: PropTypes.arrayOf(avatarPropTypes), /** Set the size of avatars */ size: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), @@ -71,9 +72,11 @@ const MultipleAvatars = (props) => { @@ -88,12 +91,15 @@ const MultipleAvatars = (props) => { _.map([...props.icons].splice(0, 4).reverse(), (icon, index) => ( )) @@ -108,6 +114,7 @@ const MultipleAvatars = (props) => { // Set overlay background color with RGBA value so that the text will not inherit opacity StyleUtils.getBackgroundColorWithOpacityStyle(themeColors.overlay, variables.overlayOpacity), styles.horizontalStackedAvatar4Overlay, + StyleUtils.getAvatarBorderRadius(props.size, props.icons[3].type), ]} > @@ -124,11 +131,13 @@ const MultipleAvatars = (props) => { {/* View is necessary for tooltip to show for multiple avatars in LHN */} @@ -139,11 +148,13 @@ const MultipleAvatars = (props) => { diff --git a/src/components/ReportActionItem/IOUPreview.js b/src/components/ReportActionItem/IOUPreview.js index 35105f13a9ad..5bced4225915 100644 --- a/src/components/ReportActionItem/IOUPreview.js +++ b/src/components/ReportActionItem/IOUPreview.js @@ -136,8 +136,16 @@ const IOUPreview = (props) => { const managerName = ReportUtils.getDisplayNameForParticipant(managerEmail, true); const ownerName = ReportUtils.getDisplayNameForParticipant(ownerEmail, true); - const managerAvatar = ReportUtils.getAvatar(lodashGet(props.personalDetails, [managerEmail, 'avatar']), managerEmail); - const ownerAvatar = ReportUtils.getAvatar(lodashGet(props.personalDetails, [ownerEmail, 'avatar']), ownerEmail); + const managerAvatar = { + source: ReportUtils.getAvatar(lodashGet(props.personalDetails, [managerEmail, 'avatar']), managerEmail), + type: CONST.ICON_TYPE_AVATAR, + name: managerEmail, + }; + const ownerAvatar = { + source: ReportUtils.getAvatar(lodashGet(props.personalDetails, [ownerEmail, 'avatar']), ownerEmail), + type: CONST.ICON_TYPE_AVATAR, + name: ownerEmail, + }; const cachedTotal = props.iouReport.total && props.iouReport.currency ? props.numberFormat( Math.abs(props.iouReport.total) / 100, diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index 0c91b421dcaf..eb47af4f6338 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -8,10 +8,10 @@ import CONST from '../CONST'; import Avatar from './Avatar'; import themeColors from '../styles/themes/default'; import * as StyleUtils from '../styles/StyleUtils'; +import avatarPropTypes from './avatarPropTypes'; const propTypes = { - /** Array of avatar URLs or icons */ - icons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), + icons: PropTypes.arrayOf(avatarPropTypes), }; const defaultProps = { @@ -26,10 +26,12 @@ const RoomHeaderAvatars = (props) => { if (props.icons.length === 1) { return ( ); } @@ -45,13 +47,18 @@ const RoomHeaderAvatars = (props) => { return ( - {_.map(iconsToDisplay, (val, index) => ( - + {_.map(iconsToDisplay, (icon, index) => ( + {index === CONST.REPORT.MAX_PREVIEW_AVATARS - 1 && props.icons.length - CONST.REPORT.MAX_PREVIEW_AVATARS !== 0 && ( <> @@ -60,6 +67,7 @@ const RoomHeaderAvatars = (props) => { styles.roomHeaderAvatarSize, styles.roomHeaderAvatar, ...iconStyle, + StyleUtils.getAvatarBorderRadius(CONST.AVATAR_SIZE.LARGE_BORDERED, icon.type), styles.roomHeaderAvatarOverlay, ]} /> diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 4261d9e26678..6da3e918fec4 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -8,13 +8,14 @@ import themeColors from '../styles/themes/default'; import Avatar from './Avatar'; import CONST from '../CONST'; import * as StyleUtils from '../styles/StyleUtils'; +import avatarPropTypes from './avatarPropTypes'; const propTypes = { /** Avatar URL or icon */ - mainAvatar: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, + mainAvatar: avatarPropTypes, /** Subscript avatar URL or icon */ - secondaryAvatar: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, + secondaryAvatar: avatarPropTypes, /** Tooltip for the main avatar */ mainTooltip: PropTypes.string, @@ -34,25 +35,33 @@ const defaultProps = { secondaryTooltip: '', size: CONST.AVATAR_SIZE.DEFAULT, backgroundColor: themeColors.componentBG, + mainAvatar: {}, + secondaryAvatar: {}, }; const SubscriptAvatar = props => ( diff --git a/src/components/avatarPropTypes.js b/src/components/avatarPropTypes.js new file mode 100644 index 000000000000..c068b481c596 --- /dev/null +++ b/src/components/avatarPropTypes.js @@ -0,0 +1,8 @@ +import PropTypes from 'prop-types'; +import CONST from '../CONST'; + +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, +}); diff --git a/src/components/menuItemPropTypes.js b/src/components/menuItemPropTypes.js index 949d1ca26f1a..9f3b40a55b43 100644 --- a/src/components/menuItemPropTypes.js +++ b/src/components/menuItemPropTypes.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import CONST from '../CONST'; import stylePropTypes from '../styles/stylePropTypes'; +import avatarPropTypes from './avatarPropTypes'; const propTypes = { /** Text to be shown as badge near the right end. */ @@ -68,7 +69,7 @@ const propTypes = { subtitle: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), /** Flag to choose between avatar image or an icon */ - iconType: PropTypes.oneOf([CONST.ICON_TYPE_AVATAR, CONST.ICON_TYPE_ICON]), + iconType: PropTypes.oneOf([CONST.ICON_TYPE_AVATAR, CONST.ICON_TYPE_ICON, CONST.ICON_TYPE_WORKSPACE]), /** Whether the menu item should be interactive at all */ interactive: PropTypes.bool, @@ -77,7 +78,7 @@ const propTypes = { fallbackIcon: PropTypes.func, /** Avatars to show on the right of the menu item */ - floatRightAvatars: PropTypes.arrayOf(PropTypes.string), + floatRightAvatars: PropTypes.arrayOf(avatarPropTypes), /** The type of brick road indicator to show. */ brickRoadIndicator: PropTypes.oneOf([CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR, CONST.BRICK_ROAD_INDICATOR_STATUS.INFO, '']), diff --git a/src/components/optionPropTypes.js b/src/components/optionPropTypes.js index b68d6501784d..b5966c13f676 100644 --- a/src/components/optionPropTypes.js +++ b/src/components/optionPropTypes.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import CONST from '../CONST'; import participantPropTypes from './participantPropTypes'; +import avatarPropTypes from './avatarPropTypes'; export default PropTypes.shape({ // Text to display @@ -15,8 +16,8 @@ export default PropTypes.shape({ // Alternate text number of lines alternateTextMaxLines: PropTypes.number, - // Array of URLs or icons - icons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), + // Array of icon information + icons: PropTypes.arrayOf(avatarPropTypes), // Login (only present when there is a single participant) login: PropTypes.string, diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 0f8c3828a543..1f2833357bd9 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -593,7 +593,11 @@ function getOptions(reports, personalDetails, { }); // If user doesn't exist, use a default avatar - userToInvite.icons = [ReportUtils.getAvatar('', login)]; + userToInvite.icons = [{ + source: ReportUtils.getAvatar('', login), + name: login, + type: CONST.ICON_TYPE_AVATAR, + }]; } // If we are prioritizing 1:1 chats in search, do it only once we started searching @@ -663,7 +667,11 @@ function getIOUConfirmationOptionsFromMyPersonalDetail(myPersonalDetail, amountT return { text: myPersonalDetail.displayName, alternateText: myPersonalDetail.login, - icons: [ReportUtils.getAvatar(myPersonalDetail.avatar, myPersonalDetail.login)], + icons: [{ + source: ReportUtils.getAvatar(myPersonalDetail.avatar, myPersonalDetail.login), + name: myPersonalDetail.login, + type: CONST.ICON_TYPE_AVATAR, + }], descriptiveText: amountText, login: myPersonalDetail.login, }; diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js index a911ee26b005..83a84f7be041 100644 --- a/src/libs/ReportUtils.js +++ b/src/libs/ReportUtils.js @@ -21,6 +21,7 @@ import DateUtils from './DateUtils'; import linkingConfig from './Navigation/linkingConfig'; import * as defaultAvatars from '../components/Icon/DefaultAvatars'; import isReportMessageAttachment from './isReportMessageAttachment'; +import * as defaultWorkspaceAvatars from '../components/Icon/WorkspaceDefaultAvatars'; let sessionEmail; Onyx.connect({ @@ -435,13 +436,13 @@ function formatReportLastMessageText(lastMessageText) { } /** - * Hashes provided string and returns a value between [1, range] + * Hashes provided string and returns a value between [0, range) * @param {String} login * @param {Number} range * @returns {Number} */ function hashLogin(login, range) { - return (Math.abs(hashCode(login.toLowerCase())) % range) + 1; + return (Math.abs(hashCode(login.toLowerCase())) % range); } /** @@ -458,12 +459,28 @@ function getDefaultAvatar(login = '') { } // There are 24 possible default avatars, so we choose which one this user has based - // on a simple hash of their login - const loginHashBucket = hashLogin(login, CONST.DEFAULT_AVATAR_COUNT); + // on a simple hash of their login. Note that Avatar count starts at 1. + const loginHashBucket = hashLogin(login, CONST.DEFAULT_AVATAR_COUNT) + 1; return defaultAvatars[`Avatar${loginHashBucket}`]; } +/** + * Helper method to return the default avatar associated with the given login + * @param {String} [workspaceName] + * @returns {String} + */ +function getDefaultWorkspaceAvatar(workspaceName) { + if (!workspaceName) { + return defaultWorkspaceAvatars.WorkspaceBuilding; + } + + // Remove all chars not A-Z or 0-9 including underscore + const alphaNumeric = workspaceName.normalize('NFD').replace(/[^0-9a-z]/gi, '').toUpperCase(); + + return !alphaNumeric ? defaultWorkspaceAvatars.WorkspaceBuilding : defaultWorkspaceAvatars[`Workspace${alphaNumeric[0]}`]; +} + /** * Helper method to return old dot default avatar associated with login * @@ -476,8 +493,8 @@ function getOldDotDefaultAvatar(login = '') { } // There are 8 possible old dot default avatars, so we choose which one this user has based - // on a simple hash of their login - const loginHashBucket = hashLogin(login, CONST.OLD_DEFAULT_AVATAR_COUNT); + // on a simple hash of their login. Note that Avatar count starts at 1. + const loginHashBucket = hashLogin(login, CONST.OLD_DEFAULT_AVATAR_COUNT) + 1; return `${CONST.CLOUDFRONT_URL}/images/avatars/avatar_${loginHashBucket}.png`; } @@ -541,42 +558,74 @@ function getFullSizeAvatar(avatarURL, login) { * @returns {Array<*>} */ function getIcons(report, personalDetails, policies, defaultIcon = null) { + const result = { + source: '', + type: CONST.ICON_TYPE_AVATAR, + name: '', + }; + if (_.isEmpty(report)) { - return [defaultIcon || Expensicons.FallbackAvatar]; + result.source = defaultIcon || Expensicons.FallbackAvatar; + return [result]; } if (isConciergeChatReport(report)) { - return [CONST.CONCIERGE_ICON_URL]; + result.source = CONST.CONCIERGE_ICON_URL; + return [result]; } if (isArchivedRoom(report)) { - return [Expensicons.DeletedRoomAvatar]; + result.source = Expensicons.DeletedRoomAvatar; + return [result]; } if (isDomainRoom(report)) { - return [Expensicons.DomainRoomAvatar]; + result.source = Expensicons.DomainRoomAvatar; + return [result]; } if (isAdminRoom(report)) { - return [Expensicons.AdminRoomAvatar]; + result.source = Expensicons.AdminRoomAvatar; + return [result]; } if (isAnnounceRoom(report)) { - return [Expensicons.AnnounceRoomAvatar]; + result.source = Expensicons.AnnounceRoomAvatar; + return [result]; } if (isChatRoom(report)) { - return [Expensicons.ActiveRoomAvatar]; + result.source = Expensicons.ActiveRoomAvatar; + return [result]; } if (isPolicyExpenseChat(report)) { + const workspaceName = lodashGet(policies, [ + `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'name', + ]); + const policyExpenseChatAvatarSource = lodashGet(policies, [ `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'avatar', - ]) || Expensicons.Workspace; + ]) || getDefaultWorkspaceAvatar(workspaceName); // Return the workspace avatar if the user is the owner of the policy expense chat if (report.isOwnPolicyExpenseChat) { - return [policyExpenseChatAvatarSource]; + result.source = policyExpenseChatAvatarSource; + result.type = CONST.ICON_TYPE_WORKSPACE; + result.name = workspaceName; + return [result]; } + const adminIcon = { + source: getAvatar(lodashGet(personalDetails, [report.ownerEmail, 'avatar']), report.ownerEmail), + name: report.ownerEmail, + type: CONST.ICON_TYPE_AVATAR, + }; + + const workspaceIcon = { + source: policyExpenseChatAvatarSource, + type: CONST.ICON_TYPE_WORKSPACE, + name: workspaceName, + }; + // 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 [ - getAvatar(lodashGet(personalDetails, [report.ownerEmail, 'avatar']), report.ownerEmail), - policyExpenseChatAvatarSource, + adminIcon, + workspaceIcon, ]; } @@ -585,7 +634,6 @@ function getIcons(report, personalDetails, policies, defaultIcon = null) { for (let i = 0; i < participants.length; i++) { const login = participants[i]; - const avatarSource = getAvatar(lodashGet(personalDetails, [login, 'avatar'], ''), login); participantDetails.push([ login, @@ -600,7 +648,12 @@ function getIcons(report, personalDetails, policies, defaultIcon = null) { // Now that things are sorted, gather only the avatars (third element in the array) and return those const avatars = []; for (let i = 0; i < sortedParticipantDetails.length; i++) { - avatars.push(sortedParticipantDetails[i][2]); + const userIcon = { + source: sortedParticipantDetails[i][2], + type: CONST.ICON_TYPE_AVATAR, + name: sortedParticipantDetails[i][0], + }; + avatars.push(userIcon); } return avatars; @@ -1589,6 +1642,8 @@ export { getOldDotDefaultAvatar, getNewMarkerReportActionID, canSeeDefaultRoom, + hashLogin, + getDefaultWorkspaceAvatar, getCommentLength, openReportFromDeepLink, getFullSizeAvatar, diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js index eb682d5026be..fb158c445a24 100755 --- a/src/pages/ReportParticipantsPage.js +++ b/src/pages/ReportParticipantsPage.js @@ -21,6 +21,7 @@ import * as ReportUtils from '../libs/ReportUtils'; import reportPropTypes from './reportPropTypes'; import withReportOrNotFound from './home/report/withReportOrNotFound'; import FullPageNotFoundView from '../components/BlockingViews/FullPageNotFoundView'; +import CONST from '../CONST'; const propTypes = { /* Onyx Props */ @@ -59,7 +60,11 @@ const getAllParticipants = (report, personalDetails) => { return ({ alternateText: userLogin, displayName: userPersonalDetail.displayName, - icons: [ReportUtils.getAvatar(userPersonalDetail.avatar, login)], + icons: [{ + source: ReportUtils.getAvatar(userPersonalDetail.avatar, login), + name: login, + type: CONST.ICON_TYPE_AVATAR, + }], keyForList: userLogin, login, text: userPersonalDetail.displayName, diff --git a/src/pages/home/report/ReportActionItemCreated.js b/src/pages/home/report/ReportActionItemCreated.js index be958eb4bb03..28b0d9cb0a94 100644 --- a/src/pages/home/report/ReportActionItemCreated.js +++ b/src/pages/home/report/ReportActionItemCreated.js @@ -43,7 +43,6 @@ const defaultProps = { const ReportActionItemCreated = (props) => { const icons = ReportUtils.getIcons(props.report, props.personalDetails, props.policies); - return ( PolicyUtils.shouldShowPolicy(policy, this.props.network.isOffline)) .sortBy(policy => policy.name) - .pluck('avatar') + .map(policy => ({ + source: policy.avatar || ReportUtils.getDefaultWorkspaceAvatar(policy.name), + name: policy.name, + type: CONST.ICON_TYPE_WORKSPACE, + })) .value(); + const policyBrickRoadIndicator = _.chain(this.props.policies) .filter(policy => policy && policy.type === CONST.POLICY.TYPE.FREE && policy.role === CONST.POLICY.ROLE.ADMIN) .find(policy => PolicyUtils.hasPolicyError(policy) || PolicyUtils.getPolicyBrickRoadIndicatorStatus(policy, this.props.policyMembers)) diff --git a/src/pages/workspace/WorkspaceInitialPage.js b/src/pages/workspace/WorkspaceInitialPage.js index 0d25f4bffcb3..d2dacbe2f45c 100644 --- a/src/pages/workspace/WorkspaceInitialPage.js +++ b/src/pages/workspace/WorkspaceInitialPage.js @@ -10,12 +10,10 @@ import styles from '../../styles/styles'; import Tooltip from '../../components/Tooltip'; import Text from '../../components/Text'; import ConfirmModal from '../../components/ConfirmModal'; -import Icon from '../../components/Icon'; import * as Expensicons from '../../components/Icon/Expensicons'; import ScreenWrapper from '../../components/ScreenWrapper'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import MenuItem from '../../components/MenuItem'; -import themedefault from '../../styles/themes/default'; import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; import compose from '../../libs/compose'; import Avatar from '../../components/Avatar'; @@ -28,6 +26,7 @@ import CONST from '../../CONST'; import * as ReimbursementAccount from '../../libs/actions/ReimbursementAccount'; import ONYXKEYS from '../../ONYXKEYS'; import OfflineWithFeedback from '../../components/OfflineWithFeedback'; +import * as ReportUtils from '../../libs/ReportUtils'; const propTypes = { ...policyPropTypes, @@ -96,6 +95,7 @@ class WorkspaceInitialPage extends React.Component { render() { const policy = this.props.policy; + const policyName = lodashGet(this.props.policy, 'name', ''); const hasMembersError = PolicyUtils.hasPolicyMemberError(this.props.policyMemberList); const hasGeneralSettingsError = !_.isEmpty(lodashGet(this.props.policy, 'errorFields.generalSettings', {})) || !_.isEmpty(lodashGet(this.props.policy, 'errorFields.avatar', {})); @@ -192,24 +192,15 @@ class WorkspaceInitialPage extends React.Component { style={[styles.pRelative, styles.avatarLarge]} onPress={this.openEditor} > - {this.props.policy.avatar - ? ( - - ) - : ( - - )} + {!_.isEmpty(this.props.policy.name) && ( diff --git a/src/pages/workspace/WorkspaceSettingsPage.js b/src/pages/workspace/WorkspaceSettingsPage.js index de014170abf9..6f0e5c425123 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.js +++ b/src/pages/workspace/WorkspaceSettingsPage.js @@ -9,10 +9,8 @@ import styles from '../../styles/styles'; import Text from '../../components/Text'; import compose from '../../libs/compose'; import * as Policy from '../../libs/actions/Policy'; -import Icon from '../../components/Icon'; import * as Expensicons from '../../components/Icon/Expensicons'; import AvatarWithImagePicker from '../../components/AvatarWithImagePicker'; -import defaultTheme from '../../styles/themes/default'; import CONST from '../../CONST'; import Picker from '../../components/Picker'; import TextInput from '../../components/TextInput'; @@ -21,6 +19,8 @@ import withPolicy, {policyPropTypes, policyDefaultProps} from './withPolicy'; import {withNetwork} from '../../components/OnyxProvider'; import OfflineWithFeedback from '../../components/OfflineWithFeedback'; import Form from '../../components/Form'; +import * as ReportUtils from '../../libs/ReportUtils'; +import Avatar from '../../components/Avatar'; const propTypes = { ...policyPropTypes, @@ -77,6 +77,7 @@ class WorkspaceSettingsPage extends React.Component { } render() { + const policyName = lodashGet(this.props.policy, 'name', ''); return ( ( - )} + type={CONST.ICON_TYPE_WORKSPACE} fallbackIcon={Expensicons.FallbackWorkspaceAvatar} style={[styles.mb3]} anchorPosition={{top: 172, right: 18}} diff --git a/src/pages/workspace/WorkspacesListPage.js b/src/pages/workspace/WorkspacesListPage.js index 5ef22eea7912..cbf604ae10f8 100755 --- a/src/pages/workspace/WorkspacesListPage.js +++ b/src/pages/workspace/WorkspacesListPage.js @@ -24,6 +24,7 @@ import Button from '../../components/Button'; import FixedFooter from '../../components/FixedFooter'; import BlockingView from '../../components/BlockingViews/BlockingView'; import {withNetwork} from '../../components/OnyxProvider'; +import * as ReportUtils from '../../libs/ReportUtils'; const propTypes = { /* Onyx Props */ @@ -119,7 +120,7 @@ class WorkspacesListPage extends Component { .filter(policy => PolicyUtils.shouldShowPolicy(policy, this.props.network.isOffline)) .map(policy => ({ title: policy.name, - icon: policy.avatar ? policy.avatar : Expensicons.Building, + icon: policy.avatar ? policy.avatar : ReportUtils.getDefaultWorkspaceAvatar(policy.name), iconType: policy.avatar ? CONST.ICON_TYPE_AVATAR : CONST.ICON_TYPE_ICON, action: () => Navigation.navigate(ROUTES.getWorkspaceInitialRoute(policy.id)), iconStyles: policy.avatar ? [] : [styles.popoverMenuIconEmphasized], @@ -157,7 +158,7 @@ class WorkspacesListPage extends Component {