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

Bug: Hitting backspace on android removes both characters which are adjacent to the caret #1973

Closed
StormVanDerPol opened this issue Apr 25, 2022 · 13 comments · Fixed by #2412
Assignees

Comments

@StormVanDerPol
Copy link

When you have a collapsed selection, aren't in composition mode, and you hit backspace in the middle of a word using Android Keyboard apps like Gboard or Microsoft SwiftKey, both characters adjacent to the caret will be removed, instead of just the character prior to the caret.

Video for demonstration:

screen-20220425-1423472.mp4

Lexical version: 0.2.4
Android: 12

Steps To Reproduce

  1. go to https://playground.lexical.dev/
  2. place your caret in any word, e.g. "Playground", between letter "o" and "u"
  3. Hit backspace
  4. It should now say "Playgrnd" instead of "Playgrund"

The current behavior

Hitting backspace removes both characters adjacent to the caret.

The expected behavior

Hitting backspace removes only the character prior to the caret.

@aearly
Copy link

aearly commented Jun 13, 2022

I can reproduce this using the standard Android keyboard in Android Chrome. Android Firefox does not have the same behavior.

@trueadm trueadm self-assigned this Jun 13, 2022
@trueadm
Copy link
Collaborator

trueadm commented Jun 13, 2022

I'll take a look tomorrow! :)

@StormVanDerPol
Copy link
Author

@trueadm seems like a recent change caused a regression. Just had some people complain describing this bug. Tested on my pixel 5 and sadly it's happening again.
Can we re-open this?

@trueadm
Copy link
Collaborator

trueadm commented Dec 23, 2022

@StormVanDerPol Would you mind helping me find what version of Lexical was the culprit? Was it 0.7? I wonder if it might have been #3434.

@thegreatercurve
Copy link
Contributor

@StormVanDerPol Would you mind helping me find what version of Lexical was the culprit? Was it 0.7? I wonder if it might have been #3434.

@trueadm I'm checking out some very old PRs from before 0.7 and I can seem to replicate this issue, on Chromium only though.

@trueadm
Copy link
Collaborator

trueadm commented Dec 23, 2022

I wonder if a change in Chromium may have caused this then? :O

I also wonder if this logic still holds true on Android: https://github.com/facebook/lexical/blame/main/packages/lexical/src/LexicalEvents.ts#L423

@StormVanDerPol
Copy link
Author

StormVanDerPol commented Dec 23, 2022

@trueadm we're still on 0.6.4. I can reproduce it in the latest playground however.

I went around and tested a bunch of older vercel previews and seems this regression happened quite some time ago, sorry for not catching it earlier.

Everything works as intended in PR #2412, which was your fix. However it already didn't work in the relevant release 0.3.4 (#2443).

I also tried #2416 which edits the same bit of code and here too it is broken, maybe it's related

Edit: I still think it's weird, I remember it was working as intended in my app at some point, so I feel that at the very least 0.3.4 should've been good, maybe you're on to something when you said a change in Chromium may have helped in messing stuff up

@trueadm
Copy link
Collaborator

trueadm commented Dec 23, 2022

This was definitely working as intended until recently. I have a feeling that #2416 may have "broken" the fix in the latest Chromium changes relating to the selection.

With the duplication occurring, I'm guessing the logic to call event.preventDefault(); isn't working?

@trueadm
Copy link
Collaborator

trueadm commented Dec 23, 2022

So what I think might be happening, is that a recent change in Chromium has caused this logic:

https://github.com/facebook/lexical/blob/main/packages/lexical/src/LexicalEvents.ts#L450-L459

To now no longer "recover" to a previously good range selection. Meaning the logic below it isn't being executed properly because it thinks selection is null. With some debugging I think we can first determine if this might be true, and then work to figure out how we can get a valid selection so we can properly trigger a character deletion.

@trueadm
Copy link
Collaborator

trueadm commented Dec 23, 2022

It could also be that event.preventDefault() is no longer actually blocking the backspace anymore on Chromium Android. Which is clearly a regression in Chromium itself!

@thegreatercurve
Copy link
Contributor

thegreatercurve commented Dec 23, 2022

Tried the below on Chromium Android and it looks like a definite browser issue:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>preventDefault example for deleteContentBackward</title>
  </head>
  <body>
    <div contenteditable="true" id="contenteditable">
      <p>Text to edit and in which to use backspace.</p>
    </div>
    <script>
      document
        .querySelector("#contenteditable")
        .addEventListener("beforeinput", (event) => {
          if (event.inputType === "deleteContentBackward") {
            event.preventDefault();
            // I would expect the backspace to be prevented, but it still deletes the previous character.
          }
        });
    </script>
  </body>
</html>

@thegreatercurve
Copy link
Contributor

Logged a related Chromium bug here: https://bugs.chromium.org/p/chromium/issues/detail?id=1403455

@bilobom
Copy link

bilobom commented Oct 9, 2023

Interesting discussion, I have some concerns i would like to raise:
1- if it's regression in chromium and that it would be solved in newer versions, how to solve this issue for older versions ?
2- We have code in production and we assume meta does as well with this package, how is this resolved on their part ? or is it left as is ?
3- This issue has been risen multiple time in #4941, #4374, #4340, #4149, #3896, #1973 and the solution is to wait for chromium to fix it. what are we suppose to tell our users ? wait ?
4- Codemirror manage to solve this issue here two year ago, they ditched reliance on preventDefault , can this be ported here ?

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

Successfully merging a pull request may close this issue.

6 participants