diff --git a/README.md b/README.md
index c31a423233e..c3080f22b77 100644
--- a/README.md
+++ b/README.md
@@ -117,7 +117,7 @@ This is a persistent storage solution wrapped in a Pub/Sub library. In general t
- Onyx stores and retrieves data from persistent storage
- Data is stored as key/value pairs, where the value can be anything from a single piece of data to a complex object
-- Collections of data are usually not stored as a single key (eg. an array with multiple objects), but as individual keys+ID (eg. `report_1234`, `report_4567`, etc.). Store collections as individual keys when a component will bind directly to one of those keys. For example: reports are stored as individual keys because `SidebarLink.js` binds to the individual report keys for each link. However, report actions are stored as an array of objects because nothing binds directly to a single report action.
+- Collections of data are usually not stored as a single key (eg. an array with multiple objects), but as individual keys+ID (eg. `report_1234`, `report_4567`, etc.). Store collections as individual keys when a component will bind directly to one of those keys. For example: reports are stored as individual keys because `ChatLinkRow.js` binds to the individual report keys for each link. However, report actions are stored as an array of objects because nothing binds directly to a single report action.
- Onyx allows other code to subscribe to changes in data, and then publishes change events whenever data is changed
- Anything needing to read Onyx data needs to:
1. Know what key the data is stored in (for web, you can find this by looking in the JS console > Application > local storage)
diff --git a/src/pages/home/sidebar/ChatLinkRow.js b/src/pages/home/sidebar/ChatLinkRow.js
new file mode 100644
index 00000000000..b1384fd76fa
--- /dev/null
+++ b/src/pages/home/sidebar/ChatLinkRow.js
@@ -0,0 +1,131 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {
+ Image,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+import styles from '../../../styles/StyleSheet';
+import ChatSwitcherOptionPropTypes from './ChatSwitcherOptionPropTypes';
+import ROUTES from '../../../ROUTES';
+import PressableLink from '../../../components/PressableLink';
+
+const propTypes = {
+ // Option to allow the user to choose from can be type 'report' or 'user'
+ option: ChatSwitcherOptionPropTypes.isRequired,
+
+ // Whether this option is currently in focus so we can modify its style
+ optionIsFocused: PropTypes.bool.isRequired,
+
+ // A function that is called when an option is selected. Selected option is passed as a param
+ onSelectRow: PropTypes.func.isRequired,
+
+ // Callback that adds a user to the pending list of Group DM users
+ onAddToGroup: PropTypes.func,
+
+ // A flag to indicate whether this comes from the Chat Switcher so we can display the group button
+ isChatSwitcher: PropTypes.bool,
+};
+
+const defaultProps = {
+ onAddToGroup: () => {},
+ isChatSwitcher: false,
+};
+
+const ChatLinkRow = ({
+ option,
+ optionIsFocused,
+ onSelectRow,
+ onAddToGroup,
+ isChatSwitcher,
+}) => {
+ const isUserRow = option.type === 'user';
+ const textStyle = optionIsFocused
+ ? styles.sidebarLinkActiveText
+ : styles.sidebarLinkText;
+ const textUnreadStyle = option.isUnread
+ ? [textStyle, styles.sidebarLinkTextUnread] : [textStyle];
+ return (
+
+ onSelectRow(option)}
+ to={ROUTES.getReportRoute(option.reportID)}
+ style={styles.textDecorationNoLine}
+ >
+ onSelectRow(option)}
+ style={[
+ styles.flexGrow1,
+ styles.chatSwitcherItemAvatarNameWrapper,
+ ]}
+ >
+
+ {
+ option.icon
+ && (
+
+
+
+ )
+ }
+
+ {option.text === option.alternateText ? (
+
+ {option.alternateText}
+
+ ) : (
+ <>
+
+ {option.text}
+
+
+ {option.alternateText}
+
+ >
+ )}
+
+
+
+
+ {isUserRow && isChatSwitcher && (
+
+ onAddToGroup(option)}
+ >
+
+ Add
+
+
+
+ )}
+
+ );
+};
+
+ChatLinkRow.propTypes = propTypes;
+ChatLinkRow.defaultProps = defaultProps;
+ChatLinkRow.displayName = 'ChatLinkRow';
+
+export default ChatLinkRow;
diff --git a/src/pages/home/sidebar/ChatSwitcherList.js b/src/pages/home/sidebar/ChatSwitcherList.js
index ed9319f0439..004597a2a42 100644
--- a/src/pages/home/sidebar/ChatSwitcherList.js
+++ b/src/pages/home/sidebar/ChatSwitcherList.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import {View, FlatList} from 'react-native';
import styles from '../../../styles/StyleSheet';
import ChatSwitcherOptionPropTypes from './ChatSwitcherOptionPropTypes';
-import ChatSwitcherRow from './ChatSwitcherRow';
+import ChatLinkRow from './ChatLinkRow';
import KeyboardSpacer from '../../../components/KeyboardSpacer';
const propTypes = {
@@ -35,11 +35,12 @@ const ChatSwitcherList = ({
data={options}
keyExtractor={option => (option.type === 'user' ? option.alternateText : String(option.reportID))}
renderItem={({item, index}) => (
-
)}
extraData={focusedIndex}
diff --git a/src/pages/home/sidebar/ChatSwitcherRow.js b/src/pages/home/sidebar/ChatSwitcherRow.js
deleted file mode 100644
index 82afb56590f..00000000000
--- a/src/pages/home/sidebar/ChatSwitcherRow.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import {
- Image,
- Text,
- TouchableOpacity,
- View,
-} from 'react-native';
-import styles from '../../../styles/StyleSheet';
-import ChatSwitcherOptionPropTypes from './ChatSwitcherOptionPropTypes';
-
-const propTypes = {
- // Option to allow the user to choose from can be type 'report' or 'user'
- option: ChatSwitcherOptionPropTypes.isRequired,
-
- // Whether this option is currently in focus so we can modify its style
- optionIsFocused: PropTypes.bool.isRequired,
-
- // A function that is called when an option is selected. Selected option is passed as a param
- onSelectRow: PropTypes.func.isRequired,
-
- // Callback that adds a user to the pending list of Group DM users
- onAddToGroup: PropTypes.func.isRequired,
-};
-
-const ChatSwitcherRow = ({
- option,
- optionIsFocused,
- onSelectRow,
- onAddToGroup,
-}) => {
- const isUserRow = option.type === 'user';
- const textStyle = optionIsFocused
- ? styles.sidebarLinkActiveText
- : styles.sidebarLinkText;
- const textUnreadStyle = option.isUnread
- ? [textStyle, styles.sidebarLinkTextUnread] : [textStyle];
- return (
-
- onSelectRow(option)}
- style={[
- styles.flexGrow1,
- styles.chatSwitcherItemAvatarNameWrapper,
- ]}
- >
-
- {
- option.icon
- && (
-
-
-
- )
- }
-
- {option.text === option.alternateText ? (
-
- {option.alternateText}
-
- ) : (
- <>
-
- {option.text}
-
-
- {option.alternateText}
-
- >
- )}
-
-
-
- {isUserRow && (
-
- onAddToGroup(option)}
- >
-
- Add
-
-
-
- )}
-
- );
-};
-
-ChatSwitcherRow.propTypes = propTypes;
-ChatSwitcherRow.displayName = 'ChatSwitcherRow';
-
-export default ChatSwitcherRow;
diff --git a/src/pages/home/sidebar/SidebarLink.js b/src/pages/home/sidebar/SidebarLink.js
deleted file mode 100644
index 00ac1888c1d..00000000000
--- a/src/pages/home/sidebar/SidebarLink.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import {View} from 'react-native';
-import Text from '../../../components/Text';
-import styles from '../../../styles/StyleSheet';
-import PressableLink from '../../../components/PressableLink';
-import ROUTES from '../../../ROUTES';
-
-const propTypes = {
- // The ID of the report for this link
- reportID: PropTypes.number.isRequired,
-
- // The name of the report to use as the text for this link
- reportName: PropTypes.string,
-
- // Toggles the hamburger menu open and closed
- onLinkClick: PropTypes.func.isRequired,
-
- // Does the report for this link have unread comments?
- isUnread: PropTypes.bool,
-
- // Whether this is the report currently in view
- isActiveReport: PropTypes.bool.isRequired,
-};
-
-const defaultProps = {
- isUnread: false,
- reportName: '',
-};
-
-const SidebarLink = (props) => {
- const linkWrapperActiveStyle = props.isActiveReport && styles.sidebarLinkWrapperActive;
- const linkActiveStyle = props.isActiveReport ? styles.sidebarLinkActive : null;
- const textActiveStyle = props.isActiveReport ? styles.sidebarLinkActiveText : styles.sidebarLinkText;
- const textActiveUnreadStyle = props.isUnread
- ? [textActiveStyle, styles.sidebarLinkTextUnread] : [textActiveStyle];
-
- return (
-
-
-
-
-
- {props.reportName}
-
-
-
-
-
- );
-};
-
-SidebarLink.displayName = 'SidebarLink';
-SidebarLink.propTypes = propTypes;
-SidebarLink.defaultProps = defaultProps;
-
-export default SidebarLink;
diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js
index 81bad1bc7ae..8734e8f2eae 100644
--- a/src/pages/home/sidebar/SidebarLinks.js
+++ b/src/pages/home/sidebar/SidebarLinks.js
@@ -3,15 +3,16 @@ import {View, ScrollView} from 'react-native';
import _ from 'underscore';
import PropTypes from 'prop-types';
import lodashOrderby from 'lodash.orderby';
+import get from 'lodash.get';
import {withOnyx} from 'react-native-onyx';
import styles from '../../../styles/StyleSheet';
import Text from '../../../components/Text';
-import SidebarLink from './SidebarLink';
import ONYXKEYS from '../../../ONYXKEYS';
import ChatSwitcherView from './ChatSwitcherView';
import SafeAreaInsetPropTypes from '../../SafeAreaInsetPropTypes';
import compose from '../../../libs/compose';
import {withRouter} from '../../../libs/Router';
+import ChatLinkRow from './ChatLinkRow';
const propTypes = {
// These are from withRouter
@@ -34,10 +35,13 @@ const propTypes = {
})),
isChatSwitcherActive: PropTypes.bool,
+
+ personalDetails: PropTypes.object,
};
const defaultProps = {
reports: {},
isChatSwitcherActive: false,
+ personalDetails: {},
};
const SidebarLinks = (props) => {
@@ -80,17 +84,25 @@ const SidebarLinks = (props) => {
{/* A report will not have a report name if it hasn't been fetched from the server yet */}
{/* so nothing is rendered */}
- {_.map(reportsToDisplay, report => report.reportName && (
- 0}
- onLinkClick={onLinkClick}
- isActiveReport={report.reportID === reportIDInUrl}
- isPinned={report.isPinned}
- />
- ))}
+ {_.map(reportsToDisplay, (report) => {
+ const participantDetails = get(report, 'participants.length', 0) === 1 ? get(props.personalDetails, report.participants[0], '') : '';
+ return report.reportName && (
+ 0,
+ }}
+ onSelectRow={onLinkClick}
+ optionIsFocused={report.reportID === reportIDInUrl}
+ />
+ );
+ })}
);
@@ -106,5 +118,8 @@ export default compose(
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
},
+ personalDetails: {
+ key: ONYXKEYS.PERSONAL_DETAILS,
+ },
}),
)(SidebarLinks);