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

[HOLD 2023-10-16] [$125] mweb/Safari - Composer - Cursor does not moved to a new line in the composer when tapped on the "return" #28501

Closed
1 of 6 tasks
lanitochka17 opened this issue Sep 29, 2023 · 30 comments
Assignees
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 Engineering Internal Requires API changes or must be handled by Expensify staff Reviewing Has a PR in review

Comments

@lanitochka17
Copy link

lanitochka17 commented Sep 29, 2023

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


Issue found when executing PR #27490

Action Performed:

  1. Open https://staging.new.expensify.com/
  2. Tap on any listed conversation in LHN
  3. Tap on the composer box
  4. Write any words
  5. Tap on the "return" button on keayboard

Expected Result:

Cursor should be moved to a new line

Actual Result:

Nothing happened. The cursor remains on the same line

Workaround:

Unknown

Platforms:

Which of our officially supported platforms is this issue occurring on?

  • Android / native
  • Android / Chrome
  • iOS / native
  • iOS / Safari
  • MacOS / Chrome / Safari
  • MacOS / Desktop

Version Number: 1.3.75-0

Reproducible in staging?: Yes

Reproducible in production?: No

If this was caught during regression testing, add the test name, ID and link from TestRail:

Email or phone of affected tester (no customers):

Logs: https://stackoverflow.com/c/expensify/questions/4856

Notes/Photos/Videos: Any additional supporting documentation

Bug6219214_1696001683570.RPReplay_Final1696001647.mp4

Expensify/Expensify Issue URL:

Issue reported by: Applause - Internal Team

Slack conversation:

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~01a307034471edf3f5
  • Upwork Job ID: 1713885684306395136
  • Last Price Increase: 2023-10-16
@lanitochka17 lanitochka17 added DeployBlockerCash This issue or pull request should block deployment Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels Sep 29, 2023
@melvin-bot
Copy link

melvin-bot bot commented Sep 29, 2023

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

@melvin-bot
Copy link

melvin-bot bot commented Sep 29, 2023

Bug0 Triage Checklist (Main S/O)

  • This "bug" occurs on a supported platform (ensure Platforms in OP are ✅)
  • This bug is not a duplicate report (check E/App issues and #expensify-bugs)
    • If it is, comment with a link to the original report, close the issue and add any novel details to the original issue instead
  • This bug is reproducible using the reproduction steps in the OP. S/O
    • If the reproduction steps are clear and you're unable to reproduce the bug, check with the reporter and QA first, then close the issue.
    • If the reproduction steps aren't clear and you determine the correct steps, please update the OP.
  • This issue is filled out as thoroughly and clearly as possible
    • Pay special attention to the title, results, platforms where the bug occurs, and if the bug happens on staging/production.
  • I have reviewed and subscribed to the linked Slack conversation to ensure Slack/Github stay in sync

@OSBotify
Copy link
Contributor

👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open StagingDeployCash deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:

  1. Identify the pull request that introduced this issue and revert it.
  2. Find someone who can quickly fix the issue.
  3. Fix the issue yourself.

@melvin-bot
Copy link

melvin-bot bot commented Sep 29, 2023

Triggered auto assignment to @chiragsalian (Engineering), see https://stackoverflow.com/c/expensify/questions/4319 for more details.

@lanitochka17
Copy link
Author

The issue is not reproducible with a 1.3.75.3 build

RPReplay_Final1696009728.mp4

@chiragsalian
Copy link
Contributor

i cannot reproduce either, closing issue.

@bernhardoj
Copy link
Contributor

@lanitochka17 @chiragsalian I can still reproduce it on the latest main.

Screen.Recording.2023-09-30.at.18.09.29.mov

@abdulrahuman5196
Copy link
Contributor

@chiragsalian / @trjExpensify I am able to reproduce the issue in staging itself. Could you kindly check and re-open this issue?

@mountiny
Copy link
Contributor

mountiny commented Oct 1, 2023

@mountiny mountiny reopened this Oct 1, 2023
@mountiny
Copy link
Contributor

mountiny commented Oct 1, 2023

@abdulrahuman5196 @bernhardoj have you got fixes on tour mind? Or offending pr?

@bernhardoj
Copy link
Contributor

I switched to the commit before this PR and the issue is gone. I don't know how it's related though.

@bernhardoj
Copy link
Contributor

Proposal

Please re-state the problem that we are trying to solve in this issue.

Pressing Enter doesn't add new lines on the mobile web.

What is the root cause of that problem?

TL;DR
The enter key is consumed by BaseReportActionContextMenu keyboard listener.

useKeyboardShortcut(
CONST.KEYBOARD_SHORTCUTS.ENTER,
(event) => {
if (!menuItemRefs.current[focusedIndex]) {
return;
}
// Ensures the event does not cause side-effects beyond the context menu, e.g. when an outside element is focused
if (event) {
event.stopPropagation();
}
menuItemRefs.current[focusedIndex].triggerPressAndUpdateSuccess();
setFocusedIndex(-1);
},
{isActive: shouldEnableArrowNavigation},
);

Details:
The enter keyboard listener is subscribed if BaseReportActionContextMenu is visible and not mini. The not mini usage of BaseReportActionContextMenu is on PopoverReportActionContextMenu.

<PopoverWithMeasuredContent
isVisible={isPopoverVisible}
onClose={hideContextMenu}
onModalShow={runAndResetOnPopoverShow}
onModalHide={runAndResetOnPopoverHide}
anchorPosition={popoverAnchorPosition.current}
animationIn="fadeIn"
disableAnimation={false}
animationOutTiming={1}
shouldSetModalVisibility={false}
fullscreen
withoutOverlay
anchorRef={anchorRef}
>
<BaseReportActionContextMenu
isVisible
type={typeRef.current}
reportID={reportIDRef.current}
reportActionID={reportActionIDRef.current}
draftMessage={reportActionDraftMessageRef.current}
selection={selectionRef.current}
isArchivedRoom={isRoomArchived}
isChronosReport={isChronosReportEnabled}
isPinnedChat={isChatPinned}
isUnreadChat={hasUnreadMessages}
anchor={contextMenuTargetNode}
contentRef={contentRef}
originalReportID={originalReportIDRef.current}
/>
</PopoverWithMeasuredContent>

Notice that isVisible is always true for BaseReportActionContextMenu. But that should not be the problem because we wrap it inside PopoverWithMeasuredContent which will not render the children if isVisible is false. Before this PR, when PopoverWithMeasuredContent isVisible is false, BaseReportActionContextMenu is hidden (not rendered). But that's not the case now. Now, BaseReportActionContextMenu is always rendered (but not visible to the user), thus the enter keyboard listener is still active.

That is because initially PopoverWithMeasuredContent will render the children (by wrapping it in a View) to measure the size.

return isContentMeasured ? (
<Popover
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
anchorPosition={shiftedAnchorPosition}
>
<View onLayout={measurePopover}>{props.children}</View>
</Popover>
) : (
/*
This is an invisible view used to measure the size of the popover,
before it ever needs to be displayed.
We do this because we need to know its dimensions in order to correctly animate the popover,
but we can't measure its dimensions without first rendering it.
*/
<View
style={styles.invisiblePopover}
onLayout={measurePopover}
>
{props.children}
</View>
);

After the measurement is done (onLayout is called), PopoverWithMeasuredContent will wrap the children with Popover. However, onLayout is never called. I found that onLayout won't be called if the children don't have a size.

In our case BaseReportActionContextMenu is the children and it renders context menu items from ContextMenuActions that are filtered by each context menu shouldShow.

const shouldShowFilter = (contextAction) =>
contextAction.shouldShow(
props.type,
reportAction,
props.isArchivedRoom,
props.betas,
props.anchor,
props.isChronosReport,
props.reportID,
props.isPinnedChat,
props.isUnreadChat,
isOffline,
);
const shouldEnableArrowNavigation = !props.isMini && (props.isVisible || shouldKeepOpen);
const filteredContextMenuActions = _.filter(ContextMenuActions, shouldShowFilter);

But the problem is, all context menu is filtered out and that is because when PopoverReportActionContextMenu is not visible, props.type is an empty string


<BaseReportActionContextMenu
isVisible
type={typeRef.current}

and most of the context menu items rely on type, for example.

shouldShow: (type, reportAction) => type === CONTEXT_MENU_TYPES.REPORT_ACTION && _.has(reportAction, 'message') && !ReportActionsUtils.isMessageDeleted(reportAction),

Previously, props.type was undefined so it uses the default value which is CONTEXT_MENU_TYPES.REPORT_ACTION and the filtering gives us 2 items, copy to clipboard, and mark as unread.

What changes do you think we should make in order to solve the problem?

The simplest solution is to set the initial value of type back to undefined.

What alternative solutions did you explore? (Optional)

Honestly, it feels wrong to have 2 context menu items rendered by default when we are not opening any context menu. So, I think having an empty type is better and it's good to not render the invisible view of PopoverWithMeasuredContent if isVisible is false.

) : (
/*
This is an invisible view used to measure the size of the popover,
before it ever needs to be displayed.
We do this because we need to know its dimensions in order to correctly animate the popover,
but we can't measure its dimensions without first rendering it.
*/
<View
style={styles.invisiblePopover}
onLayout={measurePopover}
>
{props.children}
</View>
);

: props.isVisible && (invisibleView)

OR

{props.isVisible && props.children}

@abdulrahuman5196
Copy link
Contributor

@bernhardoj

Your proposal here works fine. But I don't think it is the proper fix.

The simplest solution is to set the initial value of type back to undefined.

Same for the alternative solution as well.

: props.isVisible && (invisibleView)

We shouldn't even come to this place(children rendering) if the popover is not rendered.

AFAIK, The popover layout will only happen if user clicks to show popover. In First layout, an invisible view will be rendered to calculate size, followed by proper renders of popovers.
If as you the BaseReportActionContextMenu is swallowing the enter key newly, we should find why and fix the same?

I know you had tried to explain the same here. But could point to how this happens? I am not seeing any rendering logic changes based on isVisible param in the PR.

Before this #27221, when PopoverWithMeasuredContent isVisible is false, BaseReportActionContextMenu is hidden (not rendered). But that's not the case now.

Do Let me know if I am missing something.

@bernhardoj
Copy link
Contributor

The popover layout will only happen if user clicks to show popover. In First layout, an invisible view will be rendered to calculate size, followed by proper renders of popovers.

This process is done even without clicking the button to show the popover. My alternative solution won't allow the measurement to happen if it's not visible.

I know you had tried to explain the same here. But could point to how this happens? I am not seeing any rendering logic changes based on isVisible param in the PR.

The type initial value change from the PR that causes the issue. The empty type making the measurement never completes.

@OlimpiaZurek
Copy link
Contributor

Checked changes from this PR and have the same finding as in the proposal Setting the type as string instead of undefined causes this issue, so to fix is we should set the initial value of type back to undefined.

@mountiny
Copy link
Contributor

mountiny commented Oct 2, 2023

Thanks @bernhardoj I have asked @OlimpiaZurek as a PR author to raise a fix PR but given we will use your solution, we will reward you 25% of standard bounty so $125

@bernhardoj
Copy link
Contributor

@mountiny thanks!

@trjExpensify
Copy link
Contributor

Assigning @bernhardoj to the issue to keep track of that for when this is ready for payment.

@trjExpensify trjExpensify changed the title mweb/Safari - Composer - Cursor does not moved to a new line in the composer when tapped on the "return" [$125] mweb/Safari - Composer - Cursor does not moved to a new line in the composer when tapped on the "return" Oct 2, 2023
@melvin-bot
Copy link

melvin-bot bot commented Oct 2, 2023

⚠️ Could not update price automatically because there is no linked Upwork Job ID. The BZ team member will need to update the price manually in Upwork.

@mountiny mountiny assigned mountiny and unassigned chiragsalian Oct 2, 2023
@mountiny
Copy link
Contributor

mountiny commented Oct 2, 2023

Assigning myself for mnagement and handling the PR review

@mountiny mountiny added Daily KSv2 and removed Hourly KSv2 Daily KSv2 DeployBlockerCash This issue or pull request should block deployment labels Oct 2, 2023
@mountiny
Copy link
Contributor

mountiny commented Oct 2, 2023

This is fixed in staging, removing blocker label

@mountiny mountiny added the Reviewing Has a PR in review label Oct 4, 2023
@melvin-bot
Copy link

melvin-bot bot commented Oct 12, 2023

@trjExpensify, @mountiny, @bernhardoj Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

@trjExpensify
Copy link
Contributor

What's the dealio here? We're ready to pay @bernhardoj $125 for this?

@mountiny mountiny added the Awaiting Payment Auto-added when associated PR is deployed to production label Oct 15, 2023
@mountiny mountiny changed the title [$125] mweb/Safari - Composer - Cursor does not moved to a new line in the composer when tapped on the "return" [HOLD 2023-10-16] [$125] mweb/Safari - Composer - Cursor does not moved to a new line in the composer when tapped on the "return" Oct 15, 2023
@mountiny
Copy link
Contributor

Yep I think we are good to pay, the checklist is not needed I think, it was already clearly identified what pr was this regression from and the author has addressed it using fix provided by @bernhardoj

@trjExpensify trjExpensify added the Internal Requires API changes or must be handled by Expensify staff label Oct 16, 2023
@melvin-bot
Copy link

melvin-bot bot commented Oct 16, 2023

Job added to Upwork: https://www.upwork.com/jobs/~01a307034471edf3f5

@melvin-bot
Copy link

melvin-bot bot commented Oct 16, 2023

Triggered auto assignment to Contributor Plus for review of internal employee PR - @situchan (Internal)

@trjExpensify
Copy link
Contributor

(needed a job created in Upwork, removing @situchan).

@trjExpensify
Copy link
Contributor

@bernhardoj sent you an offer for $125!

@bernhardoj
Copy link
Contributor

bernhardoj commented Oct 16, 2023

Thanks! Accepted. @trjExpensify

@trjExpensify
Copy link
Contributor

Paid!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 Engineering Internal Requires API changes or must be handled by Expensify staff Reviewing Has a PR in review
Projects
None yet
Development

No branches or pull requests

9 participants