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

[$8000] Mac / Safari - Copy to clipboard Tooltip doesn't show copied on clicking the clipboard icon. #13146

Closed
kavimuru opened this issue Nov 29, 2022 · 385 comments
Assignees
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor Reviewing Has a PR in review

Comments

@kavimuru
Copy link

kavimuru commented Nov 29, 2022

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Action Performed:

  1. Go to any chat
  2. Click on the participant title to open the details view
  3. Click on the Copy to clipboard icon 📋 in the email.
  4. Notice that the tooltip is shown for Copy to clipboard but not Copied after the text is copied.
    (Videos to compare Chrome and Safari are attached)

Expected Result:

Copied tooltip should be shown

Actual Result:

Copied tooltip after the text is copied doesn't show up

Workaround:

unknown

Platform:

Where is this issue occurring?

  • Web - Mac / Safari

Version Number: 1.2.33-2
Reproducible in staging?: Y
Reproducible in production?: Y
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Notes/Photos/Videos:

copied-tooltip-not-showingup-safari.mov
copied-tooltip-not-showingup-chrome.mov
Recording.19.mp4

Expensify/Expensify Issue URL:
Issue reported by: @mananjadhav
Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1669714466881009

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~014886ff5b8f1db983
  • Upwork Job ID: 1598039428548734976
  • Last Price Increase: 2022-12-29
@kavimuru kavimuru added Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels Nov 29, 2022
@melvin-bot
Copy link

melvin-bot bot commented Nov 29, 2022

Triggered auto assignment to @kevinksullivan (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details.

@allroundexperts
Copy link
Contributor

Proposal

Issue

This PR:
#12572
introduced resetsOnClickOutside to the Hoverable component. This causes this issue on Safari.

Fix

Remove the resetsOnClickOutside property. It's not really checking if the click is outside. It resets the state nonetheless.

diff --git a/src/components/Tooltip/index.js b/src/components/Tooltip/index.js
index 8d3a34549..af46f8154 100644
--- a/src/components/Tooltip/index.js
+++ b/src/components/Tooltip/index.js
@@ -189,7 +189,6 @@ class Tooltip extends PureComponent {
                     containerStyles={this.props.containerStyles}
                     onHoverIn={this.showTooltip}
                     onHoverOut={this.hideTooltip}
-                    resetsOnClickOutside
                 >
                     {child}
                 </Hoverable>

Result

Screen.Recording.2022-11-30.at.5.43.34.AM.mov

@Pujan92
Copy link
Contributor

Pujan92 commented Nov 30, 2022

Proposal

As resetsOnClickOutside added to solve this issue, we can pass value false for our use case(for copy actions)

resetsOnClickOutside

resetsOnClickOutside={!_.isUndefined(this.props.resetsOnClickOutside) ? this.props.resetsOnClickOutside : true}

<Tooltip text={text}>

<Tooltip text={text} resetsOnClickOutside={false}>

@kevinksullivan kevinksullivan added the External Added to denote the issue can be worked on by a contributor label Nov 30, 2022
@melvin-bot
Copy link

melvin-bot bot commented Nov 30, 2022

Current assignee @kevinksullivan is eligible for the External assigner, not assigning anyone new.

@melvin-bot melvin-bot bot changed the title Mac / Safari - Copy to clipboard Tooltip doesn't show copied on clicking the clipboard icon. [$1000] Mac / Safari - Copy to clipboard Tooltip doesn't show copied on clicking the clipboard icon. Nov 30, 2022
@melvin-bot
Copy link

melvin-bot bot commented Nov 30, 2022

Job added to Upwork: https://www.upwork.com/jobs/~014886ff5b8f1db983

@melvin-bot
Copy link

melvin-bot bot commented Nov 30, 2022

Triggered auto assignment to Contributor-plus team member for initial proposal review - @mananjadhav (External)

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Nov 30, 2022
@melvin-bot
Copy link

melvin-bot bot commented Nov 30, 2022

Triggered auto assignment to @francoisl (External), see https://stackoverflow.com/c/expensify/questions/7972 for more details.

@s77rt
Copy link
Contributor

s77rt commented Nov 30, 2022

Proposal

diff --git a/src/components/Hoverable/hoverablePropTypes.js b/src/components/Hoverable/hoverablePropTypes.js
index 07b8a8741e..c17fa804b6 100644
--- a/src/components/Hoverable/hoverablePropTypes.js
+++ b/src/components/Hoverable/hoverablePropTypes.js
@@ -19,9 +19,6 @@ const propTypes = {
 
     /** Function that executes when the mouse leaves the children. */
     onHoverOut: PropTypes.func,
-
-    // If the mouse clicks outside, should we dismiss hover?
-    resetsOnClickOutside: PropTypes.bool,
 };
 
 const defaultProps = {
@@ -29,7 +26,6 @@ const defaultProps = {
     containerStyles: [],
     onHoverIn: () => {},
     onHoverOut: () => {},
-    resetsOnClickOutside: false,
 };
 
 export {
diff --git a/src/components/Hoverable/index.js b/src/components/Hoverable/index.js
index f06ed56027..b4703d7cfc 100644
--- a/src/components/Hoverable/index.js
+++ b/src/components/Hoverable/index.js
@@ -16,13 +16,9 @@ class Hoverable extends Component {
         };
 
         this.wrapperView = null;
-
-        this.resetHoverStateOnOutsideClick = this.resetHoverStateOnOutsideClick.bind(this);
     }
 
     componentDidMount() {
-        document.addEventListener('mousedown', this.resetHoverStateOnOutsideClick);
-
         // we like to Block the hover on touch devices but we keep it for Hybrid devices so
         // following logic blocks hover on touch devices.
         this.disableHover = () => {
@@ -38,7 +34,6 @@ class Hoverable extends Component {
     }
 
     componentWillUnmount() {
-        document.removeEventListener('mousedown', this.resetHoverStateOnOutsideClick);
         document.removeEventListener('touchstart', this.disableHover);
         document.removeEventListener('touchmove', this.enableHover);
     }
@@ -50,7 +45,8 @@ class Hoverable extends Component {
      */
     setIsHovered(isHovered) {
         if (isHovered !== this.state.isHovered && !(isHovered && this.hoverDisabled)) {
-            this.setState({isHovered}, isHovered ? this.props.onHoverIn : this.props.onHoverOut);
+            this.setState({isHovered});
+            isHovered ? this.props.onHoverIn() : this.props.onHoverOut();
         }
 
         // we reset the Hover block in case touchmove was not first after touctstart
@@ -59,28 +55,6 @@ class Hoverable extends Component {
         }
     }
 
-    /**
-     * If the user clicks outside this component, we want to make sure that the hover state is set to false.
-     * There are some edge cases where the mouse can leave the component without the `onMouseLeave` event firing,
-     * leaving this Hoverable in the incorrect state.
-     * One such example is when a modal is opened while this component is hovered, and you click outside the component
-     * to close the modal.
-     *
-     * @param {Object} event - A click event
-     */
-    resetHoverStateOnOutsideClick(event) {
-        if (!this.state.isHovered) {
-            return;
-        }
-        if (this.props.resetsOnClickOutside) {
-            this.setIsHovered(false);
-            return;
-        }
-        if (this.wrapperView && !this.wrapperView.contains(event.target)) {
-            this.setIsHovered(false);
-        }
-    }
-
     render() {
         if (this.props.absolute && React.isValidElement(this.props.children)) {
             return React.cloneElement(React.Children.only(this.props.children), {
diff --git a/src/components/Tooltip/index.js b/src/components/Tooltip/index.js
index 8d3a345492..af46f8154d 100644
--- a/src/components/Tooltip/index.js
+++ b/src/components/Tooltip/index.js
@@ -189,7 +189,6 @@ class Tooltip extends PureComponent {
                     containerStyles={this.props.containerStyles}
                     onHoverIn={this.showTooltip}
                     onHoverOut={this.hideTooltip}
-                    resetsOnClickOutside
                 >
                     {child}
                 </Hoverable>

Details

First of all, in this GH issue the bug is #12025 (we are basically reopening the issue)
The applied fix #12572 is hacky and causes this problem. Why hacky? because it does not address the root issue and the proposed fix can be bypassed by pressing enter instead of a mouse click.

The root issue is the use of <Freeze /> where the callback of setState is suspended thus the this.props.onHoverOut is not called and the tooltip become stuck.
Ideally and the simplest solution is to exclude <Hoverable /> Unfortunately this does not seem as a feature that exists and I don't think we should get rid of <Freeze /> either, so we have to fix it in another approach.

In my proposal, I have basically reverted the previous PR and decoupled the functions calls to be called immediately and not in the callback. This however means that the functions may get called before the isHovered state is actually updated, given that this is not a serious matter I'd say that's an okay price to pay, not ideal but better.

@mananjadhav
Copy link
Collaborator

Thanks for the proposal everyone. I am somewhat inclined towards @s77rt's proposal but don't like the fact that it is hacky.

The root issue is the use of where the callback of setState is suspended

I couldn't confirm this statement. I did a quick search and couldn't find any related issues as well. Can you point me to some doc, issue where we can confirm.

I am going to also tag @rushatgabhane @getusha to see if they've come across this when they solved the linked issue.

@allroundexperts @Pujan92 I don't want to revert this without knowing the impact or causing regression. Do you have any strong arguments for your proposals?

@s77rt
Copy link
Contributor

s77rt commented Dec 1, 2022

@mananjadhav Just disable the <Freeze /> by passing prop freeze={false} You will notice it will work just fine.
Unfortunately I can't find a clear statement about the setState callback, that's something I deducted
Docs may be worth checking:
https://github.com/software-mansion/react-freeze#when-component-subtree-is-frozen-what-happens-to-state-changes-that-are-executed-on-that-subtree
https://beta.reactjs.org/apis/react/Suspense

@Pujan92
Copy link
Contributor

Pujan92 commented Dec 1, 2022

@Pujan92 I don't want to revert this without knowing the impact or causing regression. Do you have any strong arguments for your proposals?

In my proposal, I am conveying to pass value to the resetsOnClickOutside property for our use case and I think it isn't related to revert.

@getusha
Copy link
Contributor

getusha commented Dec 1, 2022

@mananjadhav
After some inspection i have confirmed that this only happens when we click it on the edge/corners of the clickable.

New.Expensify.4.mp4

Can anyone confirm this? it helps

@s77rt
Copy link
Contributor

s77rt commented Dec 1, 2022

@getusha Are you testing on Safari?

@getusha
Copy link
Contributor

getusha commented Dec 1, 2022

Testing on chrome.
IMO It can't be platform specific issue.

@s77rt
Copy link
Contributor

s77rt commented Dec 1, 2022

It's browser specific, my guess is that onMouseEnter is triggered again on Chrome but not on Safari.. But this is not the root issue.

@getusha
Copy link
Contributor

getusha commented Dec 1, 2022

Right! makes sense i see onMouseEnter is supported on specific versions, so we can use onMouseOver which is supported on every browser.

@rushatgabhane
Copy link
Member

@getusha looks like you have a proposal

@s77rt
Copy link
Contributor

s77rt commented Dec 1, 2022

Right! makes sense i see onMouseEnter is supported on specific versions, so we can use onMouseOver which is supported on every browser.

Not exactly what I meant, the event is supported by Safari but not fired at the same conditions as Chrome

@fedirjh
Copy link
Contributor

fedirjh commented Dec 1, 2022

This is a regression from #12572 , the proposed solution behave like onclick event , it does reset the hovered state on all click events even when pointer is inside the Hoverable , and I think that's wrong

        if (this.props.resetsOnClickOutside) {
             this.setIsHovered(false);
             return;
         }

I agree with @Ollyws #12025 (comment) and @s77rt #13146 (comment) for their proposal , the root issue for the other issue #12025 is that the state isn't updating (frozen) when navigation to other screens , the onMouseLeave event is firing correclty but the state isn't updating nor triggering the callback to hide the tooltip

@melvin-bot
Copy link

melvin-bot bot commented Dec 1, 2022

Looks like something related to react-navigation may have been mentioned in this issue discussion.

As a reminder, please make sure that all proposals are not workarounds and that any and all attempt to fix the issue holistically have been made before proceeding with a solution. Proposals to change our DeprecatedCustomActions.js files should not be accepted.

Feel free to drop a note in #expensify-open-source with any questions.

@vijeeshin
Copy link

vijeeshin commented Dec 1, 2022

Proposal
Screenshot 2022-12-01 at 10 22 49 PM

Screenshot 2022-12-01 at 10 22 55 PM

Generally in Browsers, the Tooltip is triggered on mouse hover/over action. In our case, When the element is changed, the mouse is already on the element, on this situation mouse hovering/over the event(subsequent tooltip display) will trigger only if there is a mouse movement. otherwise, we have to explicitly trigger the hover event or tooltip display show program. In this solution, I have bubbled the click event to trigger the mouse hover event.

@francoisl
Copy link
Contributor

Thanks for the proposals and explanations about the root issue, everyone. It looks like @s77rt has a good proposal. @mananjadhav do the new explanations answer the questions you had?

@vijeeshin's proposal looks pretty straightforward too, though admittedly I don't understand how and why changing the event listener from mousedown to click solves the issue. Is it because Safari doesn't fire mousedown the same way as other browsers?

@mallenexpensify
Copy link
Contributor

@mananjadhav can you address in the #contributor-plus Slack channel? Please provide reasoning and details, if we issue compensation, the goal would be to try to processize or document this edge case so we can reference again in the future. Also... saw 344 hidden items above 😨

@mallenexpensify
Copy link
Contributor

mallenexpensify commented Jan 17, 2023

@s77rt paid $12000
@mananjadhav paid $250
anything missing!??!!?

We need to fill this out too. @mollfpr can you tackle the first three? @kevinksullivan, can you do the last one?

BugZero Checklist: The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed:

  • The PR that introduced the bug has been identified. Link to the PR:
  • The offending PR has been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake. Link to comment:
  • A discussion in #expensify-bugs has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner. Link to discussion:
  • A regression test has been added or updated so that the same bug will not reach production again. Link to the GH issue for creating the test here:

@mollfpr
Copy link
Contributor

mollfpr commented Jan 17, 2023

@mollfpr
Copy link
Contributor

mollfpr commented Jan 17, 2023

Done @mallenexpensify @kevinksullivan

@mallenexpensify
Copy link
Contributor

Compensating @mananjadhav 25% of the job price for their C+ work before they went OOO. This issue has close to 400 comments 😮 and there were multiple proposals that Manan reviewed.
I've added details to our Pricing Precedent - Contributor pay - edge cases - partial pay doc.

@mananjadhav
Copy link
Collaborator

Thanks a lot @mallenexpensify for the consideration.

@jatinsonijs
Copy link
Contributor

  • @jatinsonijs your compensation should be associated with a separate GH, right?

@mallenexpensify can you plz help here for regression bonus, I cannot comment on linked issue #14121

@mallenexpensify
Copy link
Contributor

Addressed #14121 (comment)
Thanks for the ping @jatinsonijs

@getusha
Copy link
Contributor

getusha commented Jan 19, 2023

Just to leave a note here 😄, this solution is temporary since it breaks accessibility (can confirm TAB, all clickable have two focus) Currently we are ignoring those issues but when we start to fix accessibility this solution is must to remove.

@s77rt
Copy link
Contributor

s77rt commented Jan 19, 2023

@getusha That's wrong. All we have to do is pass absolute prop. This has been addressed already.

@getusha
Copy link
Contributor

getusha commented Jan 19, 2023

@s77rt if it can be fixed why it's not fixed yet?

@s77rt
Copy link
Contributor

s77rt commented Jan 19, 2023

@getusha As I said this has been addressed already, we opted not to do it.

@parasharrajat
Copy link
Member

As I said this has been addressed already, we opted not to do it.

@s77rt Do you mind sharing the link to the discussion?

@parasharrajat
Copy link
Member

parasharrajat commented Mar 10, 2023

Linked PR for this issue caused a regression #15796.

cc: @mollfpr

@getusha
Copy link
Contributor

getusha commented Apr 15, 2023

Just to leave a note here 😄, this solution is temporary since it breaks accessibility (can confirm TAB, all clickable have two focus) Currently we are ignoring those issues but when we start to fix accessibility this solution is must to remove.

This PR was reverted here as it was a temporary solution for this issue.
cc @mollfpr @francoisl

@s77rt
Copy link
Contributor

s77rt commented Apr 15, 2023

We are not reverting the PR for that case, we are not really reverting as the main purpose of that PR is to remove resetsOnClickOutside which is still removed (i.e. do not hide Tooltip on click).

In the linked PR we are actually reintroducing the bugs that we were trying to fix here:

  1. Tooltip for Back button being stuck
  2. Tooltip stays visible until you move the mouse

The first bug will be resolved after Navigation Reboot so it's okay. But the second bug will persist.

Results after that PR:

Kooha-2023-04-15-06-52-52.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor Reviewing Has a PR in review
Projects
None yet
Development

No branches or pull requests