Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a group chat info view with participants information. #2178

Merged
merged 12 commits into from
Apr 14, 2021

Conversation

npsedhain
Copy link
Contributor

Details

Added a modal view to show the list of all the participants in the group chat.

Fixed Issues

Fixes GH_LINK_ISSUE_2105

Tests

  1. Go to a group chat page.
  2. Click on the title bar with the participants' names.
  3. A modal with the participants' information appears.
  4. On clicking each of the participants, the details page with each participant's information is displayed.

Tested On

  • Web
  • Mobile Web
  • Desktop
  • iOS
  • Android

Screenshots

Web

image
image

Mobile Web

image
image

Desktop

image
image

iOS

aaaaaa
bbbbb

Android

image
image

@npsedhain npsedhain requested a review from a team as a code owner March 31, 2021 20:42
@MelvinBot MelvinBot requested review from Luke9389 and removed request for a team March 31, 2021 20:43
Copy link
Contributor

@Luke9389 Luke9389 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello! This is looking great! Thanks for your contribution. I've left some comments here, some little stuff, some questions (I'm not too familiar with this part of our codebase), and some other stylistic ideas. I'm gonna go ahead and request another reviewer for redundancy.

},
];

return final.map(item => ({...item, participantsList: [item]}));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we adding the participantsList key?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OptionsList component seems to use the text to display from within the participantsList key. It was pretty weird for me too, but it threw error without it.

Copy link
Contributor

@Luke9389 Luke9389 Apr 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @npsedhain thanks for your patience while I was looking into this. Here were my concerns:

  1. We're sending two copies of the same data, nested in itself
  2. We're putting a single object into an array just to satisfy a proptype rule

These two concerns acted as a red flag for me, indicating that we were holding something wrong.

I started my investigation by looking at the other place in which OptionsList is used. The items that are usually in sections.data are not single people but whole reports (chats). While Options list looks like the correct component for the job, it was actually written with a different purpose in mind.

Two potential avenues forward:

  1. Don't worry about it. It works so whatever.
  2. Write a component that's actually meant for this.

To help us suss this out, I'd like to include @marcaaron in this decision. He wrote much of OptionsList and is very knowledgeable in the codebase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @Luke9389, I will the changes as suggested by @marcaaron, i.e., only sending the two keys needed.

@Luke9389 Luke9389 requested a review from NikkiWines April 1, 2021 00:45
@npsedhain
Copy link
Contributor Author

@Luke9389, I have pushed the recommended changes. Please feel free to go through it again and let me know if you have any more suggestions!

@Luke9389
Copy link
Contributor

Luke9389 commented Apr 1, 2021

Will do, thanks @npsedhain

Copy link
Contributor

@NikkiWines NikkiWines left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good. Agreed with @Luke9389 that the duplicated participantsList is pretty weird and should be modified.

Also, just a note that the report view disappears from the background when navigating from the participants page to the details page, which isn't ideal.

Screen.Recording.2021-04-01.at.4.30.04.PM.mov

const {icons, participants, reportName} = report;
const displayNames = reportName.split(', ');

const members = participants.reduce((list, login, idx) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we prefer to use non-abbreviated variable names wherever possible so idx should be index

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NikkiWines, regarding the report view disappearing when navigating to the details page, I found it to be a little weird as well. But when I navigated across the application, it occurred to me that it was an existing problem. I can take a look at what exactly is causing that issue.
For example, also happens in the route /iou/request

@@ -67,6 +67,12 @@ export default {
Details_Root: ROUTES.DETAILS_WITH_LOGIN,
},
},
Participants: {
initialRouteName: 'Participants_Root',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for initialRouteName here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's required as well, thanks for pointing it out.

@trjExpensify
Copy link
Contributor

👋 Couple of thoughts:

  1. Is there a reason why we aren't letting a user navigate back to the participant list, after they go a level deeper to the individual profile view? Forcing a user to close the modal and reopen it to go back seems sub-optimal, so I'd suggest we add a < caret to allow for a user to go back.

  2. We're using Participants as the header title. This should be Details as per the supplied mock, right?

(Granted, when we add more settings/functionality to the Details side modal in the future, we may have a sub-page for the participants list, but even then my vote would be to refer to them as Members as that's a bit more consumer-friendly).

Copy link
Contributor

@marcaaron marcaaron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can’t comment on the thread below for some reason to respond to @Luke9389 but to answer the questions...

It probably doesn't matter that much that we have some weird data nesting going on here. It doesn't make much sense to me, but I don't see it hurting anything. It's used here to create tooltips which I'm assuming we will also want here for consistency.

https://github.com/Expensify/Expensify.cash/blob/106c52b2410bfab984b8cc7ba786fd2affcc29aa/src/pages/home/sidebar/OptionRowTitle/index.js#L89-L105

So if we want to lean this out a bit we can pass only [{login, displayName}] here instead.

}).isRequired,

// The chat priority mode
priorityMode: PropTypes.string.isRequired,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I don't think we need to know this...

},
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only need to subscribe to a single report here's an example of where we do that

https://github.com/Expensify/Expensify.cash/blob/106c52b2410bfab984b8cc7ba786fd2affcc29aa/src/pages/home/report/ReportActionsView.js#L392-L394

The function can access props in it's argument so you can pull off the reportID via the route.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for helping, will refactor this one to listen to a single report.

hideSectionHeaders
showTitleTooltip
disableFocusOptions
optionMode={priorityMode === CONST.PRIORITY_MODE.GSD ? 'compact' : 'default'}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really only relevant in the side bar and can maybe just be set to 'default' here to help simplify things.

alternateText: personalDetail.login,
keyForList: `${participants.length}`,
tooltipText: personalDetail.login,
displayName: personalDetail.displayName,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can take this out and everything about myPersonalDetails. There's really no need to include the current user here because:

  • They know already that they're a participant in the chat
  • They should be accessing their profile via settings

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcaaron, I looked at a couple of chat applications and found them to have the individual's information listed there too. I can totally remove it if that's not something we want it in here.

const members = participants.reduce((list, login, idx) => {
list.push({
alternateText: login,
displayName: displayNames[idx],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works, but it's not really the correct way to access these display names and will break in a future where report names are not structured as they are today.

Instead we should subscribe to the personalDetails key. Then grab everything we need like this:

const userPersonalDetails = props.personalDetails[login];
const displayName = userPersonalDetails.displayName;
const avatar = userPersonalDetails.avatar;

etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the suggestion, will make the change.

const {icons, participants, reportName} = report;
const displayNames = reportName.split(', ');

const members = participants.reduce((list, login, idx) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use _.reduce() and _.map() etc for consistency.

<View
pointerEvents="box-none"
style={[
styles.detailsPageContainer,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than use a page container style that belongs to another page (DetailsPage) we should make this style more generic so it makes sense to use in both contexts.

styles.detailsPageContainer,
]}
>
{ participants.length
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an empty space here before participants

@@ -83,6 +83,9 @@ const HeaderView = (props) => {
if (participants.length === 1) {
Navigation.navigate(ROUTES.getDetailsRoute(participants[0]));
}
if (participants.length > 1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than check if participants.length > 1 we can just return early when the length === 1 then in all other cases navigate to the new view.

@npsedhain npsedhain changed the title Create a group chat info view with participants information. [WIP] Create a group chat info view with participants information. Apr 3, 2021
@npsedhain
Copy link
Contributor Author

@marcaaron, I have implemented the details page navigation as per your suggestion. Let me know if you have any concerns. This should solve the issue of the details page exiting the stack which used to make the report page disappear.

cc: @trjExpensify @NikkiWines

Screen.Recording.2021-04-06.at.9.17.45.AM.mov

@npsedhain npsedhain changed the title [WIP] Create a group chat info view with participants information. Create a group chat info view with participants information. Apr 6, 2021
@marcaaron
Copy link
Contributor

marcaaron commented Apr 6, 2021

@npsedhain Thanks, but it's strange that we cannot go back to view the full list again? We should add a < in the top left corner so we can navigate back to the large list of users. cc @trjExpensify to confirm.

@trjExpensify
Copy link
Contributor

Yep, I agree we should add a < to the top left of that screen. 👍

Copy link
Contributor

@marcaaron marcaaron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few more comments on this one. Looking better :)

<DetailsModalStack.Screen
name="Details_Root"
headerShown={false}
path={ROUTES.REPORT_ID}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think we need this.

component={DetailsPage}
options={{
...defaultSubRouteOptions,
title: 'ParticipantsParticipant',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will show in a browser tab as ParticipantsParticipant since title sets this text as the webpage title.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps a better format would be

Report > Participants > {display name of participant}

But I'm not sure we need to figure this out right now and can maybe just leave out the title entirely.

@@ -79,6 +81,31 @@ const DetailsModalStackNavigator = () => (
</DetailsModalStack.Navigator>
);

const ParticipantsModalStackNavigator = () => (
<ParticipantsModalStack.Navigator
path={ROUTES.PARTICIPANTS}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure these path props are not doing anything and the "path" concept is left over from something we have since removed.

src/ROUTES.js Outdated
PARTICIPANTS: 'participants',
PARTICIPANTS_WITH_REPORT: 'participants/:reportID',
getParticipantsRoute: reportID => `participants/${reportID}`,
REPORT_ID: '/:reportID',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem like any route we are using...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah the path prop didn't seem to help out there. Will remove this. Thanks for pointing out.

src/ROUTES.js Outdated
getParticipantsRoute: reportID => `participants/${reportID}`,
REPORT_ID: '/:reportID',
PARTICIPANTS_PARTICIPANT_DETAIL: '/participants/:reportID/:login',
getParticipantsPartipantDetail: (reportID, login) => `/participants/${reportID}/${login}`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"participants participant detail" could be more descriptive... e.g. maybe should be REPORT_PARTICIPANTS and REPORT_PARTICIPANT.

As for the routes, is there any reason we can't make these routes...

/r/:reportID/participants

/r/:reportID/participants/:login

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup we can do this, thanks for the suggestion.

@@ -34,6 +34,7 @@ import {
IOUBillStackNavigator,
IOURequestModalStackNavigator,
DetailsModalStackNavigator,
ParticipantsModalStackNavigator,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd update all instances of Participants* to ReportParticipants so that it's clearer what we are dealing with.

name="Participants_Root"
component={ParticipantsPage}
options={{
...defaultSubRouteOptions,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be able to pass these to the navigator instead and prevent having to add this stuff to every screen.

@marcaaron
Copy link
Contributor

There are some conflicts here as well that need to be resolved before we can merge this.

@Luke9389
Copy link
Contributor

Luke9389 commented Apr 6, 2021

Regarding the < to go back, we do have an Icon, BackArrow that will work well for this.

@marcaaron
Copy link
Contributor

@Luke9389 pretty sure this is built into the header component already https://github.com/Expensify/Expensify.cash/blob/b6d7d60e0d59c68ddf16f1c437033c77f6c8f9e7/src/components/HeaderWithCloseButton.js#L24-L25

Just want to make sure we are not reimplementing behavior we already have, thanks!

@npsedhain
Copy link
Contributor Author

@marcaaron Thanks for the feedbacks, will implement the changes first thing tomorrow and will let you know.

@npsedhain npsedhain force-pushed the npsedhain-groupchat-detail branch from 1a8df7c to c0592bf Compare April 8, 2021 04:22
@npsedhain
Copy link
Contributor Author

@marcaaron I have made all the recommended changes, let me know if there is anything else.

Copy link
Contributor

@marcaaron marcaaron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just have a few more minor comments. Looks really nice!

@@ -82,8 +82,6 @@ module.exports = run;

const _ = __nccwpck_require__(4987);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't seem like these files are supposed to be here...?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually didn't add this. Seem to have been added by @deetergp, a week ago in another PR!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most likely you merged in the main branch and didn't fix conflicts correctly. Regardless, this file should not be showing with changes in this PR and will need to be fixed before merging.

/>
<DetailsModalStack.Screen
name="Details_Root"
headerShown={false}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary because this was passed to navigator screenOptions already?

Participants: {
screens: {
Participants_Root: ROUTES.REPORT_PARTICIPANTS,
Details_Root: ROUTES.REPORT_PARTICIPANT,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a blocker but this should probably be Participants_Details to follow a similar convention as the settings modal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok now it is a blocker because I think we cannot have Details_Root existing in two navigators? Can we change this to:

ReportParticipants_Root
ReportParticipants_Details

@@ -38,11 +38,13 @@ const DetailsPage = ({personalDetails, route}) => {
<HeaderWithCloseButton
title="Details"
onCloseButtonPress={Navigation.dismissModal}
shouldShowBackButton
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this need a conditional. We don't want to show a back button when there is no modal screen to go back e.g. when there's only one participant

2021-04-08_15-57-10

* Returns all the participants in the active report
*
* @param {Object} report The active report object
* @param {Array} personalDetails The personal details of the users
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an Object.

Copy link
Contributor

@NikkiWines NikkiWines left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of comments but overall really coming together

const propTypes = {
/* Onyx Props */
// The personal details of the person who is logged in
personalDetails: PropTypes.shape({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have personalDetailsPropType.js which you can import instead of redefining the props here.

@npsedhain
Copy link
Contributor Author

I have pushed changes including all the recent comments. Please, do let me know if there is more.
cc: @marcaaron @NikkiWines

@@ -82,8 +82,6 @@ module.exports = run;

const _ = __nccwpck_require__(4987);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most likely you merged in the main branch and didn't fix conflicts correctly. Regardless, this file should not be showing with changes in this PR and will need to be fixed before merging.

Copy link
Contributor

@NikkiWines NikkiWines left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from the modifications to the .github/ files, this is looking good. Had one minor question about using login vs userLogin

alternateText: userLogin,
displayName: userPersonalDetail.displayName,
icons: [userPersonalDetail.avatar],
keyForList: login,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason to not use userLogin here as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, just thought using it for the key would be fine, but will do it for consistency's sake. Thank you for the suggestion.

@npsedhain
Copy link
Contributor Author

@marcaaron, I have fixed the changes shown in the github actions folder and resolved conflicts.

@NikkiWines
Copy link
Contributor

@npsedhain looks like there are still some conflicts here.

@npsedhain
Copy link
Contributor Author

@NikkiWines Will fix them ASAP.

@npsedhain
Copy link
Contributor Author

@NikkiWines Done!

Participants: {
screens: {
Participants_Root: ROUTES.REPORT_PARTICIPANTS,
Details_Root: ROUTES.REPORT_PARTICIPANT,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok now it is a blocker because I think we cannot have Details_Root existing in two navigators? Can we change this to:

ReportParticipants_Root
ReportParticipants_Details

@@ -37,12 +40,14 @@ const DetailsPage = ({personalDetails, route}) => {
<ScreenWrapper>
<HeaderWithCloseButton
title="Details"
shouldShowBackButton={!!route.params.reportID}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like an implementation detail. Can we make this more explicit by adding something above like:

// If we have a reportID param this means that we arrived here via the ParticipantsPage and should be allowed to navigate back to it
const shouldShowBackButton = Boolean(route.params.reportID);

Copy link
Contributor

@NikkiWines NikkiWines left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks good, but I'm seeing an issue where I can't see the details page for an account with an SMS login though their details do exist. Looks like it's because of login: userLogin, which should be using login in that case. My bad for not catching that when I recommended that change earlier.

Screen.Recording.2021-04-13.at.11.05.29.AM.mov
Screen.Recording.2021-04-13.at.11.06.38.AM.mov

@npsedhain
Copy link
Contributor Author

@marcaaron @NikkiWines
Hey, guys, I've made the changes. Feel free to let me know how this looks.

Copy link
Contributor

@marcaaron marcaaron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your patience and for all the changes. LGTM.

Copy link
Contributor

@NikkiWines NikkiWines left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great 👍

@marcaaron marcaaron requested a review from Luke9389 April 14, 2021 17:47
@marcaaron
Copy link
Contributor

All yours @Luke9389

@Luke9389
Copy link
Contributor

Thanks for helping with the reviews @marcaaron and @NikkiWines

@Luke9389 Luke9389 merged commit 90f3ceb into Expensify:master Apr 14, 2021
@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@laurenreidexpensify
Copy link
Contributor

laurenreidexpensify commented Apr 15, 2021

Thanks @npsedhain - we will issue payment on 21 April assuming no regressions.

@npsedhain
Copy link
Contributor Author

Thanks @laurenreidexpensify, but I think you tagged the wrong person. 😅

@laurenreidexpensify
Copy link
Contributor

Sorry @npsedhain!!! My bad 🤦🏽‍♀️

@OSBotify
Copy link
Contributor

🚀 [Deployed](https://github.com/Expensify/Expensify.cash
/actions/runs/765130740) 🚀 to
staging on Mon Apr 19 2021 at 22:41:56 GMT+0000 (Coordinated Universal Time)

platform result
🤖 android 🤖 success ✅
🖥 desktop 🖥 success ✅
🍎 iOS 🍎 success ✅
🕸 web 🕸 success ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create a group chat info view, with additional participant info
7 participants