Skip to content

[$250] mWeb - Search - In search, scrolling the page doesn't close the keypad. #61521

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

Open
1 of 8 tasks
jponikarchuk opened this issue May 6, 2025 · 20 comments
Open
1 of 8 tasks
Assignees
Labels
Bug Something is broken. Auto assigns a BugZero manager. External Added to denote the issue can be worked on by a contributor Reviewing Has a PR in review Weekly KSv2

Comments

@jponikarchuk
Copy link

jponikarchuk commented May 6, 2025

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


Version Number: V9.1.40-1
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from TestRail: N/a
Email or phone of affected tester (no customers): Slottwo1 sivappa2@gmail.com
Issue reported by: Applause Internal Team
Device used: Redminote note 10s android 13 phone
App Component: Chat Report View

Action Performed:

  1. Go to https://staging.new.expensify.com/home
  2. Login account with more chats
  3. Tap search
  4. Scroll the page up and down

Expected Result:

In search, scrolling the page must close the keypad.

Actual Result:

In search, scrolling the page doesn't close the keypad.

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

1.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021922351372001950494
  • Upwork Job ID: 1922351372001950494
  • Last Price Increase: 2025-05-13
  • Automatic offers:
    • truph01 | Contributor | 107372286
Issue OwnerCurrent Issue Owner: @Beamanator
@jponikarchuk jponikarchuk added Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels May 6, 2025
Copy link

melvin-bot bot commented May 6, 2025

Triggered auto assignment to @muttmuure (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

@linhvovan29546
Copy link
Contributor

linhvovan29546 commented May 7, 2025

Proposal

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

mWeb - Search - In search, scrolling the page doesn't close the keypad.

What is the root cause of that problem?

We already have logic to dismiss the keyboard on scroll, which works as expected in other parts of the app.

const defaultOnScroll = () => {
// Only dismiss the keyboard whenever the user scrolls the screen
if (!isScreenTouched) {
return;
}
Keyboard.dismiss();
};

However, it doesn’t work in the search screen because the search input is rendered via the SearchAutocompleteInput component.

Looking deeper, this component uses a TextInput with the type markdown, which on the web renders as a div with contentEditable. As a result, calling Keyboard.dismiss() has no effect in this OP
https://github.com/Expensify/react-native-live-markdown/blob/main/src/MarkdownTextInput.web.tsx#L772-L775

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

I think we can fix this by manually blur the input instead of relying on Keyboard.dismiss(). Here's the approach:

  • Introduce a new props dismissExternalKeyboard in the SelectionList component.
  • In the defaultOnScroll handler, call dismissExternalKeyboard() to hide the keyboard.
    const defaultOnScroll = () => {
    // Only dismiss the keyboard whenever the user scrolls the screen
    if (!isScreenTouched) {
    return;
    }
    Keyboard.dismiss();
    };
    const defaultOnScroll = () => {
        // Only dismiss the keyboard whenever the user scrolls the screen
        if (!isScreenTouched) {
            return;
        }
        if(dismissExternalKeyboard){
            dismissExternalKeyboard();
            return
        }
        Keyboard.dismiss();
    };
const dismissExternalKeyboard = () => {
    textInputRef?.current?.blur();
}; 
...
            <SelectionList<OptionData | SearchQueryItem>
                dismissExternalKeyboard={dismissExternalKeyboard}
                ...
                        textInputRef={textInputRef}

Note: We should also check other components like SearchPageHeaderInput and apply the same solution

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

Since this is a keyboard interaction issue specific to web behavior, automated testing isn't necessary in this case.

What alternative solutions did you explore? (Optional)

@melvin-bot melvin-bot bot added the Overdue label May 9, 2025
@truph01
Copy link
Contributor

truph01 commented May 9, 2025

Proposal

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

  • When using search, scrolling the page does not dismiss the on-screen keyboard.

What is the root cause of that problem?


var dismissKeyboard = () => {
  TextInputState.blurTextInput(TextInputState.currentlyFocusedField());
};

See: https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/modules/dismissKeyboard/index.js


TextInputState._currentlyFocusedNode = hostNode;
  • However, for <div contenteditable="true" />, TextInputState.currentlyFocusedField() returns null because there is no logic to update TextInputState._currentlyFocusedNode in this case. This is the root cause of the bug.

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

To resolve this, we need to ensure that TextInputState._currentlyFocusedNode is also updated for <div contenteditable="true" /> elements. This requires two steps:

Step 1: Export TextInputState from react-native-web so it can be used externally.

Update this logic:
https://github.com/necolas/react-native-web/blob/922c134f2b7c428cc19daaeb3cac4b6a4c8ec6a3/packages/react-native-web/src/exports/NativeModules/index.js#L10-L15

From:


import UIManager from '../UIManager';

// NativeModules shim
const NativeModules = {
  UIManager
};

To:


import UIManager from '../UIManager';
import TextInputState from '../../modules/TextInputState';

// NativeModules shim
const NativeModules = {
  UIManager,
  TextInputState
};

Step 2: Update the TextInputState._currentlyFocusedNode when the contenteditable div receives focus.

Modify the logic here:
https://github.com/Expensify/react-native-live-markdown/blob/0a5c7736d876ad11762aa88c736c1c9b860eedc7/src/MarkdownTextInput.web.tsx#L552-L553

From:


const handleFocus = useCallback(event => {

To:


const handleFocus = useCallback(event => {
  NativeModules.TextInputState._currentlyFocusedNode = hostNode;

What alternative solutions did you explore? (Optional)

  • After implementing Step 1, another option is to update TextInputState._currentlyFocusedNode directly within the Expensify app instead of react-native-live-markdown. For example, update:
    <AnimatedMarkdownTextInput

To:


<AnimatedMarkdownTextInput
    onFocus={(e) => {
        props?.onFocus?.(e);
        NativeModules.TextInputState._currentlyFocusedNode = e.target;
    }}
/>

Copy link

melvin-bot bot commented May 12, 2025

@muttmuure Eep! 4 days overdue now. Issues have feelings too...

@muttmuure muttmuure moved this to Bugs and Follow Up Issues in #expensify-bugs May 13, 2025
@muttmuure muttmuure added the External Added to denote the issue can be worked on by a contributor label May 13, 2025
@melvin-bot melvin-bot bot changed the title mWeb - Search - In search, scrolling the page doesn't close the keypad. [$250] mWeb - Search - In search, scrolling the page doesn't close the keypad. May 13, 2025
Copy link

melvin-bot bot commented May 13, 2025

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

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label May 13, 2025
Copy link

melvin-bot bot commented May 13, 2025

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

@melvin-bot melvin-bot bot removed the Overdue label May 13, 2025
@parasharrajat
Copy link
Member

Interesting issue.

I see that solving this issue on the lib level is not that complex so I think we can solve it at react-native-live-markdown lib.

Instead of exposing the UiManager which can't be done being internal module, we can access the TextInputState via TextInput.State. Then we can overide the _currentlyFocusedNode via TextInput.State.focusTextInput in focus handler.

@truph01's proposal aligns more with this approach thus I prefer their solution.

🎀 👀 🎀 C+ reviewed

Copy link

melvin-bot bot commented May 13, 2025

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

@parasharrajat
Copy link
Member

Feedback:

Looking deeper, this component uses a TextInput with the type markdown, which on the web renders as a div with contentEditable. As a result, calling Keyboard.dismiss() has no effect in this OP

@linhvovan29546 I see that you were on the point in your root cause but you didn't explain why calling Keyboard.dismiss() has no effect. Let's try to add those details to add more value to your proposals.

@Beamanator
Copy link
Contributor

So @parasharrajat do you think we should hold on hiring for now?

@parasharrajat
Copy link
Member

parasharrajat commented May 14, 2025

@Beamanator Here is my main decision #61521 (comment). We can proceed with implementation.

@parasharrajat
Copy link
Member

@Beamanator Bump.

@melvin-bot melvin-bot bot added the Overdue label May 16, 2025
@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label May 20, 2025
Copy link

melvin-bot bot commented May 20, 2025

📣 @truph01 🎉 An offer has been automatically sent to your Upwork account for the Contributor role 🎉 Thanks for contributing to the Expensify app!

Offer link
Upwork job
Please accept the offer and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑‍💻
Keep in mind: Code of Conduct | Contributing 📖

@truph01
Copy link
Contributor

truph01 commented May 20, 2025

@parasharrajat PR is ready

@parasharrajat
Copy link
Member

Let's wait for maintainer review.

@melvin-bot melvin-bot bot added the Overdue label May 22, 2025
@parasharrajat
Copy link
Member

parasharrajat commented May 23, 2025

Upstream lib PR is in progress. Close to merge.

Copy link

melvin-bot bot commented May 23, 2025

@Beamanator Whoops! This issue is 2 days overdue. Let's get this updated quick!

@parasharrajat
Copy link
Member

@truph01 First PR is done. Waiting for next one...

@melvin-bot melvin-bot bot added Reviewing Has a PR in review Weekly KSv2 and removed Daily KSv2 Overdue labels May 26, 2025
@truph01
Copy link
Contributor

truph01 commented May 26, 2025

@parasharrajat PR is ready

@parasharrajat
Copy link
Member

parasharrajat commented May 27, 2025

The version in app is updated in #62788 so we don't need #62811 now.

Let's track #62788 timeline for payment of this issue. Thanks.

cc: @muttmuure

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. External Added to denote the issue can be worked on by a contributor Reviewing Has a PR in review Weekly KSv2
Projects
Status: Bugs and Follow Up Issues
Development

No branches or pull requests

6 participants