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

TextInput clears text when secureTextEntry is true #35668

Open
AlgoRoots opened this issue Dec 17, 2022 · 13 comments · May be fixed by #45964
Open

TextInput clears text when secureTextEntry is true #35668

AlgoRoots opened this issue Dec 17, 2022 · 13 comments · May be fixed by #45964
Labels
Component: TextInput Related to the TextInput component. Needs: Triage 🔍

Comments

@AlgoRoots
Copy link

AlgoRoots commented Dec 17, 2022

Description

Hi, I am having an issue with my UITextField, When a secureTextEntry is true and I try to edit it, it keeps getting cleared.
I understand that it works as intended by IOS, but I would like to keep password value when I try to edit.

Version

0.70.0

Output of npx react-native info

System:
OS: macOS 12.3.1
CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 30.74 MB / 16.00 GB
Shell: 5.8 - /bin/zsh
Binaries:
Node: 16.15.0 - /usr/local/bin/node
Yarn: 1.22.17 - /usr/local/bin/yarn
npm: 9.2.0 - ~/reactnative/node_modules/.bin/npm
Watchman: 2022.10.03.00 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.11.3 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 21.4, iOS 15.5, macOS 12.3, tvOS 15.4, watchOS 8.5
Android SDK: Not Found
IDEs:
Android Studio: 2021.3 AI-213.7172.25.2113.9014738
Xcode: 13.4.1/13F100 - /usr/bin/xcodebuild
Languages:
Java: 11.0.16.1 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: ^18.2.0 => 18.2.0
react-native: ^0.70.0 => 0.70.6
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found

Steps to reproduce

2022-12-17 08 15 35

Snack, code example, screenshot, or link to a repository

After looking for a workaround, I was able to modify native code in node module using patch-package

Here is the path i tried to edit code
// node_modules/react-native/
// Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m

Before

// node_modules/react-native/   
// Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m


- (BOOL)textField:(__unused UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
  NSString *newText =
    [_backedTextInputView.textInputDelegate textInputShouldChangeText:string inRange:range];

  if (newText == nil) {
    return NO;
  }

  if ([newText isEqualToString:string]) {
    _textDidChangeIsComing = YES;
    return YES;
  }

  NSMutableAttributedString *attributedString = [_backedTextInputView.attributedText mutableCopy];
  [attributedString replaceCharactersInRange:range withString:newText];
  [_backedTextInputView setAttributedText:[attributedString copy]];

  // Setting selection to the end of the replaced text.
  UITextPosition *position =
    [_backedTextInputView positionFromPosition:_backedTextInputView.beginningOfDocument
                                        offset:(range.location + newText.length)];
  [_backedTextInputView setSelectedTextRange:[_backedTextInputView textRangeFromPosition:position toPosition:position]
                              notifyDelegate:YES];

  [self textFieldDidChange];

  return NO;
}

After

// node_modules/react-native/   
// Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m


- (BOOL)textField:(__unused UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    //Setting the new text.
    NSString *updatedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    textField.text = updatedString;

    //Setting the cursor at the right place
    NSRange selectedRange = NSMakeRange(range.location + string.length, 0);
    UITextPosition* from = [textField positionFromPosition:textField.beginningOfDocument offset:selectedRange.location];
    UITextPosition* to = [textField positionFromPosition:from offset:selectedRange.length];
    textField.selectedTextRange = [textField textRangeFromPosition:from toPosition:to];

    //Sending an action
    [textField sendActionsForControlEvents:UIControlEventEditingChanged];

    return NO;
}

it solved the password reset problem. However As you can see, there is a major flaw in this code.

The variable called _backedTextInputView has disappeared, and modified code has applied to all textField, so consonants and vowels are separated when writing in Korean.

So, I wonder if there is a way to apply the after code written above only when secureTextEntry is true while maintaining the existing code.

p.s. I wonder if React-native team can generate the corresponding props. (e.g. textFiled.clearsOnBeginEditing.)

@react-native-bot react-native-bot added the Component: TextInput Related to the TextInput component. label Dec 17, 2022
@NarekAvagyan777
Copy link

Hey I have the same problem but I can't find the code inside node_modules/react-native to change it. Please help!!!

@AlgoRoots
Copy link
Author

AlgoRoots commented Jul 28, 2023

@NarekAvagyan777 Sorry for late reply, you can change native code below path.
node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m

Copy link

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Jan 25, 2024
@D4uS1
Copy link

D4uS1 commented Jan 31, 2024

This issue still exists. Do you have any workarouns?

@github-actions github-actions bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Feb 1, 2024
@saqlaan
Copy link

saqlaan commented Mar 2, 2024

Issue is still happening on IOS.

@musiinator
Copy link

how to get rid of that yellow background for inputs when u choose to "use a strong password"?

@adnan-khan1122
Copy link

adnan-khan1122 commented Aug 8, 2024

@AlgoRoots Thanks for sharing the solution, but it's leading to another issue. The swipe-to-type gesture was not working, and the IOS app was hanging and crashing. Here's the modified code with a solution to both issues.

  - (BOOL)textField:(__unused UITextField *)textField shouldChangeCharactersInRange:(NSRange)range 
   replacementString:(NSString *)string {
    // Step 1: Handle secureTextEntry to avoid text clearing
    if (textField.isSecureTextEntry) {
        // Setting the new text to avoid the text clearing issue
        NSString *updatedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
        textField.text = updatedString;

        // Step 2: Set the cursor at the right place
        NSRange selectedRange = NSMakeRange(range.location + string.length, 0);
        UITextPosition* from = [textField positionFromPosition:textField.beginningOfDocument offset:selectedRange.location];
        UITextPosition* to = [textField positionFromPosition:from offset:selectedRange.length];
        textField.selectedTextRange = [textField textRangeFromPosition:from toPosition:to];

        // Step 3: Send an action to notify of the change
        [textField sendActionsForControlEvents:UIControlEventEditingChanged];

        return NO;
    }

    // Step 4: Handle regular text entry to support swipe gestures
    NSString *newText = [_backedTextInputView.textInputDelegate textInputShouldChangeText:string inRange:range];
    if (newText == nil) {
        return NO;
    }

    if ([newText isEqualToString:string]) {
        _textDidChangeIsComing = YES;
        return YES;
    }

    NSMutableAttributedString *attributedString = [_backedTextInputView.attributedText mutableCopy];
    [attributedString replaceCharactersInRange:range withString:newText];
    [_backedTextInputView setAttributedText:[attributedString copy]];

    // Setting selection to the end of the replaced text.
    UITextPosition *position = [_backedTextInputView positionFromPosition:_backedTextInputView.beginningOfDocument offset:(range.location + newText.length)];
    [_backedTextInputView setSelectedTextRange:[_backedTextInputView textRangeFromPosition:position toPosition:position] notifyDelegate:YES];

    [self textFieldDidChange];

    return NO;
}
```

@angvp
Copy link

angvp commented Aug 8, 2024

@AlgoRoots Thanks for sharing the solution, but it's leading to another issue. The swipe-to-type gesture was not working, and the IOS app was hanging and crashing. Here's the modified code with a solution to both issues.

    // Step 1: Handle secureTextEntry to avoid text clearing
    if (textField.isSecureTextEntry) {
        // Setting the new text to avoid the text clearing issue
        NSString *updatedString = [textField.text stringByReplacingCharactersInRange:range withString:string];
        textField.text = updatedString;

        // Step 2: Set the cursor at the right place
        NSRange selectedRange = NSMakeRange(range.location + string.length, 0);
        UITextPosition* from = [textField positionFromPosition:textField.beginningOfDocument offset:selectedRange.location];
        UITextPosition* to = [textField positionFromPosition:from offset:selectedRange.length];
        textField.selectedTextRange = [textField textRangeFromPosition:from toPosition:to];

        // Step 3: Send an action to notify of the change
        [textField sendActionsForControlEvents:UIControlEventEditingChanged];

        return NO;
    }

    // Step 4: Handle regular text entry to support swipe gestures
    NSString *newText = [_backedTextInputView.textInputDelegate textInputShouldChangeText:string inRange:range];
    if (newText == nil) {
        return NO;
    }

    if ([newText isEqualToString:string]) {
        _textDidChangeIsComing = YES;
        return YES;
    }

    NSMutableAttributedString *attributedString = [_backedTextInputView.attributedText mutableCopy];
    [attributedString replaceCharactersInRange:range withString:newText];
    [_backedTextInputView setAttributedText:[attributedString copy]];

    // Setting selection to the end of the replaced text.
    UITextPosition *position = [_backedTextInputView positionFromPosition:_backedTextInputView.beginningOfDocument offset:(range.location + newText.length)];
    [_backedTextInputView setSelectedTextRange:[_backedTextInputView textRangeFromPosition:position toPosition:position] notifyDelegate:YES];

    [self textFieldDidChange];

    return NO;
}

Care to create a patch and a PR? thanks!

adnan-khan1122 added a commit to adnan-khan1122/react-native that referenced this issue Aug 9, 2024
When a secureTextEntry is true and I try to edit it, it keeps getting cleared.

This PR solves this by patching function `shouldChangeCharactersInRange` adding
a condition that checks `isSecureTextEntry` in `textfield` is true so overrides
the behaviour of clearing the text, the change was done in the file `RCTBackedTextInputDelegateAdapter.mm`

This fixes facebook#35668
@shubhamguptadream11
Copy link
Collaborator

#46154

@angvp
Copy link

angvp commented Aug 29, 2024

I believe @adnan-khan1122 is waiting for feedback on #45964 that PR should close this and #46154

@alimurad-1
Copy link

alimurad-1 commented Sep 20, 2024

I am working on a project with react native
"react-native": "0.74.1",
and I've tried both the @adnan-khan1122 and @AlgoRoots solution by pasting the code in the file mentioned above as
node_modules/react-native/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m

but I am still facing the issue

did i miss a step or the patch is no longer compatible with new version

@adnan-khan1122
Copy link

adnan-khan1122 commented Sep 20, 2024

@alimurad-1 patch is still valid. Don't forget to apply patching after adding code using npx patch-package react-native and re-install IOS app. It should work.

@alimurad-1
Copy link

@alimurad-1 patch is still valid. Don't forget to apply patching after adding code using npx patch-package react-native and re-install IOS app. It should work.

reinstalling the app resolved the issue...thank you

adnan-khan1122 added a commit to adnan-khan1122/react-native that referenced this issue Oct 4, 2024
When a secureTextEntry is true and I try to edit it, it keeps getting cleared.

This PR solves this by patching function `shouldChangeCharactersInRange` adding
a condition that checks `isSecureTextEntry` in `textfield` is true so overrides
the behaviour of clearing the text, the change was done in the file `RCTBackedTextInputDelegateAdapter.mm`

This fixes facebook#35668
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: TextInput Related to the TextInput component. Needs: Triage 🔍
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants