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

Andrew 3313 link context menu #3931

Merged

Conversation

Drewfergusson
Copy link
Contributor

@Drewfergusson Drewfergusson commented Jul 8, 2021

@roryabraham

Details

In order to enable a context menu on secondary actions (right-clicking on desktops or long-pressing on mobile), I created a reusable component called PressbaleWithContextMenu that would wrap anything that you wanted to have a context menu. I then applied this to the tags in the RenderHTML component. PressableWithContextMenu can also be used when we go to add actions to images or any other element.

I did copy a lot of functions and logic from the existing ReportActionItem. There wasn't a great way to reuse that code. Since we're now using that same popover logic in more places the logic needed to be in its own isolated component. I could have used mixins or inherited those functions but it would have created a dependency. I think as an optimization the ReportActionItems should implement the reusable PressableWithContextMenu as well.

Fixed Issues

#3313

Tests

  1. Create a message containing a valid URL (ex https://expensify.com)
  2. Send the message
  3. Once the message is sent, notice that the link/URL has turned blue
  4. Long-press on the blue link (or right-click)
  5. You should be prompted with the option "Copy URL to Clipboard", click this option
  6. You should now have that URL in your clipboard as a simple string.
  7. Paste the URL into any pastable location (notepad, another message, etc)

QA Steps

Tested On

  • Web
  • Mobile Web
  • Desktop
  • iOS iPhone Xs iOS 14.6
  • Android

Screenshots

iOS

mobile-test.mov

Web

image
image

Mobile Web

image

Desktop

image

Android

@Drewfergusson Drewfergusson requested a review from a team as a code owner July 8, 2021 13:35
@MelvinBot MelvinBot requested review from puneetlath and removed request for a team July 8, 2021 13:35
@github-actions
Copy link
Contributor

github-actions bot commented Jul 8, 2021

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@Drewfergusson
Copy link
Contributor Author

Still working on testing, just creating this PR as a placeholder

@roryabraham roryabraham self-requested a review July 8, 2021 17:40
@roryabraham
Copy link
Contributor

Okay, @Drewfergusson, just ping me when this is ready for review.

@roryabraham
Copy link
Contributor

Also, just FYI for the future, you can always create a draft PR if your PR is not yet ready for review. 👍

@Drewfergusson
Copy link
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@Drewfergusson
Copy link
Contributor Author

@roryabraham @puneetlath this PR is ready for review. Testing evidence is attached.

@roryabraham
Copy link
Contributor

Sorry for the delay @Drewfergusson, I was out-of-office last week and should be able to review this soon. However, it seems that there is now a merge conflict you'll need to resolve.

@parasharrajat
Copy link
Member

To add more to the context, I think we should hold here as there is ongoing changes of refactoring the ContextMenu. #4194.

@Drewfergusson
Copy link
Contributor Author

I'm glad @parasharrajat commented because, yes I did resolve another merge conflict and I saw @parasharrajat was moving the context menu for more general use.

@roryabraham, as he said, I may have to wait until he is finished.

@roryabraham
Copy link
Contributor

@Drewfergusson #4194 is merged, so feel free to resolve conflicts and start working on this again when you're ready.

@Drewfergusson
Copy link
Contributor Author

@roryabraham merge conflicts resolved and did a quick sanity test on web and iOS to ensure the features are still working. Please review when you have a chance

Copy link
Contributor

@roryabraham roryabraham left a comment

Choose a reason for hiding this comment

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

Great work so far!

src/languages/en.js Outdated Show resolved Hide resolved
src/components/PressableWithContextMenu.js Outdated Show resolved Hide resolved
src/components/PressableWithContextMenu.js Outdated Show resolved Hide resolved
src/components/PressableWithContextMenu.js Outdated Show resolved Hide resolved
src/components/PressableWithContextMenu.js Outdated Show resolved Hide resolved
src/components/PressableWithContextMenu.js Outdated Show resolved Hide resolved
src/components/PressableWithContextMenu.js Outdated Show resolved Hide resolved
src/components/PressableWithContextMenu.js Outdated Show resolved Hide resolved
@roryabraham roryabraham self-requested a review August 3, 2021 14:11
Copy link
Contributor

@roryabraham roryabraham left a comment

Choose a reason for hiding this comment

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

Meant to hit "request changes" 🤦

Copy link
Member

@parasharrajat parasharrajat left a comment

Choose a reason for hiding this comment

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

I am probably late to the party but We migrated our ContextMenu code to the Singleton component. and the same should be followed here. Although changes are awesome, you are using nested ReportActionContext which is something that we have moved away from.

@roryabraham Do you think a refactor is needed? It's going to be small changes you just have to call methods from the ReportActionContextMenu to show and hide the menu.

src/components/RenderHTML/BaseRenderHTML.js Outdated Show resolved Hide resolved
import {Clipboard as ClipboardIcon, Checkmark} from '../Icon/Expensicons';


export default function anchorContextMenuOptions(href, translate) {
Copy link
Member

Choose a reason for hiding this comment

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

It's better to add this action to ContextMenuAction and manage the list of actions on the context menu by manipulating the array on the main PopoverReportActionContextmenu.

this action's definition will never change. Will it?

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 that the list of context actions will need to be dynamic depending on the context. So by default it will be the existing menu, but if we longPress on a link, we'll show "Copy URL to Clipboard".

Copy link
Contributor

Choose a reason for hiding this comment

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

So yeah I think we're on the same page here 🙃

side note: ContextMenuActions.js should be renamed contextMenuActions.js because it doesn't export a React component

Copy link
Member

Choose a reason for hiding this comment

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

yeah. My idea was to use the shouldShow flag on actions and manage the actions on the context menu. So we just need to pass the keys to actions. Something like that.

>
{children}
</Text>
<PressableWithContextMenu contextMenuItems={anchorContextMenuOptions(href, translate)}>
Copy link
Member

Choose a reason for hiding this comment

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

Just Wrap this Anchor in PressableWithSecondaryInteraction
and Call the methods from ReportActionContextMenu.js.

@roryabraham
Copy link
Contributor

@Drewfergusson another concern here is performance. We recently merged a PR that elevated the existing PopoverReportActionContextMenu to be a sibling of the main FlatList used for a chat. In so doing, we removed a huge amount of duplicate rendering logic from individual ReportActionItem components, and got a big performance boost.

Since this PR adds a new popover menu for each link in a chat, I'm pretty sure it will cause a substantial performance regression. To avoid this, I think we need to continue to reuse the single PopoverReportActionContextMenu per chat. A few quick notes to get you started:

  • This ReportActionContextMenu file is actually not a component, but a set of functions that can be used to control the main PopoverReportActionContextMenu. (it should really be camelCase instead of PascalCase)
  • We might not really need PressableWithContextMenu anymore. Instead, I think we just need be able to dynamically provide different context actions to the main PopoverReportActionContextMenu. You could probably do that by moving your anchor context actions into here.

@roryabraham
Copy link
Contributor

hehe @parasharrajat I was too slow to send my last comment before you got a review in 😏

@parasharrajat
Copy link
Member

Actually, I was just leaving a trail for you to catch up. So eventually you had to write all that stuff. 😉. @roryabraham.

@Drewfergusson
Copy link
Contributor Author

Drewfergusson commented Aug 4, 2021

Hey @parasharrajat, just took a look at your changes. The single context menu is a huge improvement ✨ . I will work to implement copying links by controlling this menu. The popover currently does seem tightly coupled to report actions (it requires you to pass in a reportAction object or it breaks everything). So I will have to make it function for other use cases. I will work to push a PR soon. @roryabraham

@parasharrajat
Copy link
Member

@Drewfergusson I think you can pass the default values for extra keys.
Look at the state to see what is the default and you have disable extra actions which are not needed.

Using your logic, you can pass in the actions. in your case, Copy the link to clipboard, and Open link.
and Configure contextMenu to take dynamic actions. this should work.

Copy link
Contributor

@roryabraham roryabraham left a comment

Choose a reason for hiding this comment

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

Overall approach looks great! It's a much simpler PR than before, which is good. Went ahead and requested a few changes with the current implementation.

linkRef.current,
);
}
}
onPress={() => (shouldDownloadFile ? fileDownload(href) : Linking.openURL(href))}
Copy link
Member

Choose a reason for hiding this comment

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

I think, It should have an action on the contextMenu as well. Open Link which can follow what you are doing now.

Not sure if the click to open feature is yet planned. cc: @roryabraham.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@roryabraham can you clarify @parasharrajat 's comment here? Doesn't seem like a bad idea to add Open Link to the context menu however in my testing a single/normal press opens the link. Not sure the exact scenario where they would get a download instead of going to the link.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I missed this. Yeah, I don't think we really need Open Link in the context menu, but since you've already added it we can leave it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's ask in #expensify-open-source

@Drewfergusson
Copy link
Contributor Author

@roryabraham @parasharrajat I have updated the code based on your feedback. I even went ahead and added the 'Open Link' option to the context menu as suggested by @parasharrajat. It's working on desktop and iOS simulator. If you approve the code I will add all other test evidence.

Would love to get this one across the finish line :)

Copy link
Contributor

@roryabraham roryabraham left a comment

Choose a reason for hiding this comment

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

Looking good now. Just a few minor code style changes and lint errors that need to be resolved.

@Drewfergusson
Copy link
Contributor Author

@roryabraham changes made and testing evidence/screenshots attached.

Copy link
Contributor

@roryabraham roryabraham left a comment

Choose a reason for hiding this comment

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

Looks like some change here broke the mini ReportActionContextMenu that should appear on hover:

image

Copy link
Contributor

@roryabraham roryabraham 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 things:

  1. We can get rid of this context action. It never shows and is useless.
  2. I figured out why the mini ReportActionContextMenu isn't displayed. Here's how to fix it (in BaseReportActionContextMenu):

image

src/pages/home/report/ContextMenu/ContextMenuActions.js Outdated Show resolved Hide resolved
@Drewfergusson
Copy link
Contributor Author

@roryabraham I removed the copy link option (as well as the associated translations and imports). I also applied your fix to the mini context menu. I confirmed it's working. Good catch, I didn't even notice that feature until you pointed it out.

@roryabraham roryabraham merged commit b858fff into Expensify:main Aug 11, 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.

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by @roryabraham in version: 1.0.85-10 🚀

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

@isagoico
Copy link

@Drewfergusson Hello! We're only able to see the Copy to clipboard option. The Open link option from the screenshots is not displayed, is this expected? It's a bit confusing since the QA steps doesn't mention it but the screenshots show it.

@roryabraham
Copy link
Contributor

Hi @isagoico, we removed the Open Link option that was displayed in the screenshots – what you've described is the expected behavior. Sorry for the confusion!

@botify
Copy link

botify commented Aug 25, 2021

This has been deployed to production and is now subject to a 7-day regression period.
If no regressions arise, payment will be issued on 2021-09-01. 🎊

@OSBotify
Copy link
Contributor

🚀 Deployed to production by @roryabraham in version: 1.0.86-11 🚀

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

@botify
Copy link

botify commented Aug 30, 2021

This has been deployed to production and is now subject to a 7-day regression period.
If no regressions arise, payment will be issued on 2021-09-06. 🎊

@@ -30,6 +30,7 @@ class PressableWithSecondaryInteraction extends Component {
*/
executeSecondaryInteractionOnContextMenu(e) {
const selection = window.getSelection().toString();
e.stopPropagation();
Copy link
Contributor

Choose a reason for hiding this comment

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

Hi, why do we need this line? It seems to be unnecessary. cc @roryabraham @parasharrajat @puneetlath @Drewfergusson

Copy link
Member

@parasharrajat parasharrajat Sep 14, 2023

Choose a reason for hiding this comment

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

This prevents event bubbling when this component is nested. We do not want nested and parent component both to trigger the action.

This happens for nested links in the message. When link context menu is triggered, message context menu should not override it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, so you mean by this case?
image

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.

7 participants