Skip to content

Commit

Permalink
Merge pull request #439 from Expensify/stites-showRoomsInSwitcher
Browse files Browse the repository at this point in the history
Show chat rooms in chat switcher
  • Loading branch information
tgolen authored Sep 22, 2020
2 parents b9a4807 + b33ac84 commit 2da6a48
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 31 deletions.
32 changes: 16 additions & 16 deletions src/page/home/sidebar/ChatSwitcherList.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ const propTypes = {

// An array of options to allow the user to choose from
options: PropTypes.arrayOf(PropTypes.shape({
// The login of a person (either email or phone number)
login: PropTypes.string.isRequired,
// The full name of the user if available
text: PropTypes.string.isRequired,

// The login (email/phone number) of the user, or the name of the chat room
alternateText: PropTypes.string.isRequired,

// The URL of the person's avatar
avatarURL: PropTypes.string.isRequired,
avatarURL: PropTypes.string,

// The full name of the person (first + last), could be empty
fullName: PropTypes.string,
// A function that is called when an option is selected. Selected option is passed as a param
callback: PropTypes.func.isRequired,
})),

// A function that is called when an option is selected. Selected option is passed as a param
onSelect: PropTypes.func.isRequired,
};
const defaultProps = {
options: [],
};

const ChatSwitcherList = ({focusedIndex, options, onSelect}) => (
const ChatSwitcherList = ({focusedIndex, options}) => (
<View style={[styles.chatSwitcherItemList]}>
{options.length > 0 && _.map(options, (option, i) => {
const optionIsFocused = i === focusedIndex;
Expand All @@ -41,8 +41,8 @@ const ChatSwitcherList = ({focusedIndex, options, onSelect}) => (
: styles.sidebarLinkText;
return (
<TouchableOpacity
key={option.login}
onPress={() => onSelect(option)}
key={option.alternateText}
onPress={() => option.callback(option)}
>
<View
style={[
Expand All @@ -55,22 +55,22 @@ const ChatSwitcherList = ({focusedIndex, options, onSelect}) => (
>
<View style={[styles.chatSwitcherAvatar, styles.mr2]}>
<Image
source={{uri: option.avatarURL}}
source={{uri: option.icon}}
style={[styles.chatSwitcherAvatarImage]}
/>
</View>
<View style={[styles.flex1]}>
{option.fullName === '' ? (
{option.text === '' ? (
<Text style={[textStyle, styles.h3]} numberOfLines={1}>
{option.login}
{option.alternateText}
</Text>
) : (
<>
<Text style={[textStyle, styles.h3]} numberOfLines={1}>
{option.fullName}
{option.text}
</Text>
<Text style={[textStyle, styles.textMicro]} numberOfLines={1}>
{option.login}
{option.alternateText}
</Text>
</>
)}
Expand Down
84 changes: 69 additions & 15 deletions src/page/home/sidebar/ChatSwitcherView.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import KeyboardShortcut from '../../../lib/KeyboardShortcut';
import ChatSwitcherList from './ChatSwitcherList';
import ChatSwitcherSearchForm from './ChatSwitcherSearchForm';
import {fetchOrCreateChatReport} from '../../../lib/actions/Report';
import {redirect} from '../../../lib/actions/App';
import CONFIG from '../../../CONFIG';

const personalDetailsPropTypes = PropTypes.shape({
// The login of the person (either email or phone number)
Expand Down Expand Up @@ -48,6 +50,12 @@ const propTypes = {
// with their details
personalDetails: PropTypes.objectOf(personalDetailsPropTypes),

// All reports that have been shared with the user
reports: PropTypes.shape({
reportID: PropTypes.number,
reportName: PropTypes.string,
}),

// The personal details of the person who is currently logged in
session: PropTypes.shape({
// The email of the person who is currently logged in
Expand All @@ -56,6 +64,7 @@ const propTypes = {
};
const defaultProps = {
personalDetails: {},
reports: {},
session: null,
};

Expand All @@ -67,7 +76,8 @@ class ChatSwitcherView extends React.Component {

this.handleKeyPress = this.handleKeyPress.bind(this);
this.reset = this.reset.bind(this);
this.fetchChatReportAndRedirect = this.fetchChatReportAndRedirect.bind(this);
this.selectUser = this.selectUser.bind(this);
this.selectReport = this.selectReport.bind(this);
this.triggerOnFocusCallback = this.triggerOnFocusCallback.bind(this);
this.updateSearch = this.updateSearch.bind(this);

Expand All @@ -93,6 +103,28 @@ class ChatSwitcherView extends React.Component {
KeyboardShortcut.unsubscribe('K');
}

/**
* Fetch the chat report and then redirect to the new report
*
* @param {object} option
* @param {string} option.login
*/
selectUser(option) {
fetchOrCreateChatReport([this.props.session.email, option.login]);
this.reset();
}

/**
* Fetch the chat report and then redirect to the new report
*
* @param {object} option
* @param {string} option.reportID
*/
selectReport(option) {
redirect(option.reportID);
this.reset();
}

/**
* Reset the component to it's default state and blur the input
*
Expand Down Expand Up @@ -125,17 +157,6 @@ class ChatSwitcherView extends React.Component {
});
}

/**
* Fetch the chat report and then redirect to the new report
*
* @param {object} option
* @param {string} option.value
*/
fetchChatReportAndRedirect(option) {
fetchOrCreateChatReport([this.props.session.email, option.login]);
this.reset();
}

/**
* When arrow keys are pressed, the focused option needs to change
* When enter key is pressed, the highlighted option is selected
Expand Down Expand Up @@ -213,13 +234,43 @@ class ChatSwitcherView extends React.Component {
// duplicate options to the list (because one option can match multiple regex patterns).
// A Set is used here so that duplicate values are automatically removed.
const matches = new Set();
const searchOptions = _.values(this.props.personalDetails);

// Get a list of all users we can send messages to and make their details generic
const personalDetailOptions = _.chain(this.props.personalDetails)
.values()
.map(personalDetail => ({
text: personalDetail.fullName,
alternateText: personalDetail.login,
searchText: personalDetail.displayNameWithEmail,
icon: personalDetail.avatarURL,
login: personalDetail.login,
callback: this.selectUser,
}))
.value();

// Get a list of all reports we can send messages to
// Filter the reports to only group chats
// Make the report details generic
const reportOptions = _.chain(this.props.reports)
.values()
.filter(report => report.reportNameValuePairs && report.reportNameValuePairs.type === 'expense')
.map(report => ({
text: '',
alternateText: report.reportName,
searchText: report.reportName,
reportID: report.reportID,
icon: CONFIG.FAVICON.DEFAULT,
callback: this.selectReport,
}))
.value();

const searchOptions = _.union(personalDetailOptions, reportOptions);

for (let i = 0; i < matchRegexes.length; i++) {
if (matches.size < this.maxSearchResults) {
for (let j = 0; j < searchOptions.length; j++) {
const option = searchOptions[j];
const valueToSearch = option.displayNameWithEmail.replace(new RegExp(/&nbsp;/g), '');
const valueToSearch = option.searchText.replace(new RegExp(/&nbsp;/g), '');
const isMatch = matchRegexes[i].test(valueToSearch);

// Make sure we don't include the same option twice (automatically handled be using a `Set`)
Expand Down Expand Up @@ -261,7 +312,6 @@ class ChatSwitcherView extends React.Component {
/>

<ChatSwitcherList
onSelect={this.fetchChatReportAndRedirect}
focusedIndex={this.state.focusedIndex}
options={this.state.options}
/>
Expand All @@ -277,6 +327,10 @@ export default withIon({
personalDetails: {
key: IONKEYS.PERSONAL_DETAILS,
},
reports: {
key: `${IONKEYS.REPORT}_[0-9]+$`,
indexBy: 'reportID',
},
session: {
key: IONKEYS.SESSION,
},
Expand Down

0 comments on commit 2da6a48

Please sign in to comment.