tttstudios / react-native-otp-input

Tiny Javascript library which provides an elegant UI for user to input one time passcode.
MIT License
521 stars 238 forks source link

Fix for input cramming on a single input field upon copying OTP from clipboard. #224

Open jpaviron1738 opened 9 months ago

jpaviron1738 commented 9 months ago

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch @twotalltotems/react-native-otp-input@1.3.11 for the project I'm working on.

Hi I noticed that OTP are cramming initially on a single input field upon copying from clipboard. I decided to fix the weird behavior with MaskInput.

Here is the diff that solved my problem:

diff --git a/node_modules/@twotalltotems/react-native-otp-input/dist/index.js b/node_modules/@twotalltotems/react-native-otp-input/dist/index.js
index 71580b8..17fb443 100644
--- a/node_modules/@twotalltotems/react-native-otp-input/dist/index.js
+++ b/node_modules/@twotalltotems/react-native-otp-input/dist/index.js
@@ -4,6 +4,8 @@ import Clipboard from '@react-native-community/clipboard';
 import styles from './styles';
 import { isAutoFillSupported } from './helpers/device';
 import { codeToArray } from './helpers/codeToArray';
+import MaskInput from 'react-native-mask-input';
+
 export default class OTPInputView extends Component {
     constructor(props) {
         super(props);
@@ -131,9 +133,20 @@ export default class OTPInputView extends Component {
             const { clearInputs, placeholderCharacter, placeholderTextColor } = this.props;
             const { color: defaultPlaceholderTextColor } = { ...defaultTextFieldStyle, ...codeInputFieldStyle };
             return (<View pointerEvents="none" key={index + "view"} testID="inputSlotView">
-                <TextInput testID="textInput" underlineColorAndroid='rgba(0,0,0,0)' style={selectedIndex === index ? [defaultTextFieldStyle, codeInputFieldStyle, codeInputHighlightStyle] : [defaultTextFieldStyle, codeInputFieldStyle]} ref={ref => { this.fields[index] = ref; }} onChangeText={text => {
+                {index === 0 ? (<View>
+                <TextInput testID="textInput" underlineColorAndroid='rgba(0,0,0,0)' style={selectedIndex === index ? [defaultTextFieldStyle, codeInputFieldStyle, codeInputHighlightStyle, {color:'transparent'}] : [defaultTextFieldStyle, codeInputFieldStyle, {color:'transparent'}]} ref={ref => { this.fields[index] = ref; }} onChangeText={text => {
                 this.handleChangeText(index, text);
             }} onKeyPress={({ nativeEvent: { key } }) => { this.handleKeyPressTextInput(index, key); }} value={!clearInputs ? digits[index] : ""} keyboardAppearance={keyboardAppearance} keyboardType={keyboardType} textContentType={isAutoFillSupported ? "oneTimeCode" : "none"} key={index} selectionColor={selectionColor} secureTextEntry={secureTextEntry} editable={editable} placeholder={placeholderCharacter} placeholderTextColor={placeholderTextColor || defaultPlaceholderTextColor}/>
+                <MaskInput
+                  value={!clearInputs ? digits[index] : ""}
+                    maxLength={1}
+                    style={selectedIndex === index ? [defaultTextFieldStyle, codeInputFieldStyle, codeInputHighlightStyle, {position:'absolute'}] : [defaultTextFieldStyle, codeInputFieldStyle, {position: 'absolute'}]}
+                />
+                </View>) : (
+                <TextInput testID="textInput" underlineColorAndroid='rgba(0,0,0,0)' style={selectedIndex === index ? [defaultTextFieldStyle, codeInputFieldStyle, codeInputHighlightStyle] : [defaultTextFieldStyle, codeInputFieldStyle]} ref={ref => { this.fields[index] = ref; }} onChangeText={text => {
+                this.handleChangeText(index, text);
+            }} onKeyPress={({ nativeEvent: { key } }) => { this.handleKeyPressTextInput(index, key); }} value={!clearInputs ? digits[index] : ""} keyboardAppearance={keyboardAppearance} keyboardType={keyboardType} textContentType={isAutoFillSupported ? "oneTimeCode" : "none"} key={index} selectionColor={selectionColor} secureTextEntry={secureTextEntry} editable={editable} placeholder={placeholderCharacter} placeholderTextColor={placeholderTextColor || defaultPlaceholderTextColor}/>) }
+
             </View>);
         };
         this.renderTextFields = () => {

This issue body was partially generated by patch-package.

xcdincay commented 8 months ago

@jpaviron1738 thank you for your fix. How can we implement this?

ser-emejia commented 7 months ago

@jpaviron1738 thank you for your fix. How can we implement this?

Did you find any solution?

Navjot-Sharma commented 2 months ago

For anyone wondering how to implement it, create 'patches' folder at the project root (parallel to package.json file). Create a new file in it '@twotalltotems+react-native-otp-input+1.3.11.patch'. Copy the above code mentioned at top and paste in the file. Add 'react-native-mask-input' package to project. yarn add react-native-mask-input

In package.json under "scripts" key, add "postinstall": "patch-package",

Run yarn install or yarn postinstall