AstrOOnauta / react-native-international-phone-number

⚛️ International mobile phone number input component for React Native 📱
https://snack.expo.dev/@astroonauta/react-native-international-phone-number
ISC License
272 stars 45 forks source link

If the device's direction is RTL, input is reversed. #70

Open Bilal-Abdeen opened 8 months ago

Bilal-Abdeen commented 8 months ago

Thank you for the excellent library. If the user has an RTL (Right-To-Left) language as the default language on the device, the different parts of the phone number are reversed. For example, if the user enters 123 456, this library displays 456 123. This occurs regardless of the app's support for RTL!

To reproduce:

  1. add an RTL language, e.g. Arabic, from the device's settings to your device/emulator
  2. Make the RTL language the default language. If you do not know how to read the language you selected, make sure you know the sequence to change the language back. Otherwise, you would need to reset the device/emulator to remove that language.
  3. enter 123 456 in <PhoneInput>. What will be displayed is 456 123.

Notes:

  1. A customMask with no spaces, e.g. "#######", can be used as a workaround. However, we lose the excellent masking capability of the library!
  2. Using a TextInput component from React-Native works fine! I could not find which part of the library's code causes the issue.
  3. You can use the following to force React-Native to use LTR. This does NOT fix the problem!
    
    import { I18nManager, } from "react-native";
    import RNRestart from "react-native-restart";
    import { getLocales } from "react-native-localize";

// get: (1) React-Native direction setting, & (2) the default language setting on the device const localesList = getLocales(); // console.log("I18nManager.isRTL:", I18nManager.isRTL, "localesList[0]?.isRTL", localesList[0]?.isRTL, "localesList[0]?.languageCode", localesList[0]?.languageCode, );

// force LTR and restart the app (for the setting to have an effect.) I18nManager.allowRTL(false); I18nManager.forceRTL(false); RNRestart.restart();

AstrOOnauta commented 3 weeks ago

Hello @Bilal-Abdeen , Thanks for your contribution! Next version this will be up.

Bilal-Abdeen commented 3 weeks ago

@AstrOOnauta Thank you very much for implementing my PR 69. However, this PR fixes issue #68. However, this issue is still there. Please open it again.

By the way, I think the problem is in the masking function algorithm. However, I could not find which part of the code needs updating.

AstrOOnauta commented 3 weeks ago

Hey @Bilal-Abdeen ...let me know if I understand this: in RTL mode the phone number is displayed in reverse mode? likes the number 123456789 (LTR) will be 987654321 (RTL)??

PPHelios commented 3 weeks ago

@AstrOOnauta Thank you for the great library, @Bilal-Abdeen Thank you for your work, regarding the issue I also had to manually alter the library to support this, I also added a functionality to change arabic numbers(١٢٣٤) to (1234). I can share my code with you so you can implement it in a future version as I don't have time currently to create PR.

Bilal-Abdeen commented 3 weeks ago

Hey @Bilal-Abdeen ...let me know if I understand this: in RTL mode the phone number is displayed in reverse mode? likes the number 123456789 (LTR) will be 987654321 (RTL)??

It is reversed only when a mask with a space is used. So, (123 456) is displayed as (456 123.)

AstrOOnauta commented 3 weeks ago

@PPHelios Ooh great! When you have a time, please..share your logic! Thanks for this...

@Bilal-Abdeen Understand, this is so crazy :O

PPHelios commented 3 weeks ago

@Bilal-Abdeen I also ultered the mask as some users use 0 before the number which excheeds the mask length and some didn't.

Screenshot_20241023_050413_com.estatech.bdoonwasyt.jpg

Bilal-Abdeen commented 3 weeks ago

@AstrOOnauta Thank you for the great library, @Bilal-Abdeen Thank you for your work, regarding the issue I also had to manually alter the library to support this, I also added a functionality to change arabic numbers(١٢٣٤) to (1234). I can share my code with you so you can implement it in a future version as I don't have time currently to create PR.

Yes, please share your code. I will see if I and/or @AstrOOnauta can make a PR of it.

Bilal-Abdeen commented 3 weeks ago

@PPHelios Ooh great! When your have a time, please..share your logic! Thanks for this... @Bilal-Abdeen Understand, this is so crazy :O

It seems very strange. I found the same issue in other phone number libraries. I think it has something to do with an auto-reverse functionality of React-Native when RTL is used.

PPHelios commented 2 weeks ago

@Bilal-Abdeen @AstrOOnauta I'm sorry not to create a repo and contribute on this as I'm currently working on a project, Find attached .zip folder with the modified package. I'm using version 0.7.6 The changes are commented in the following files: index.js, countries.js and getInputMask.js For the left to right numbers I used the language prop to change the flex direction in index.js Hope this could help you.

react-native-international-phone-number.zip

Bilal-Abdeen commented 2 weeks ago

@PPHelios Thank you very much for sharing your version of the library. I installed it. It does fix the order of the 3 visual components (flag, country code & phone number.) I liked your smart solution of using flexDirection in index.js. This issue is now fixed in version 0.8.0 using an alternative approach. I am not sure if my approach (in 0.8.0) is better or yours! I think they are both equally good. If you believe yours is better for any reason, please let us know. I would make a new PR to update the library accordingly.

The screenshot you shared with us shows an important fix for another issue (the mask parts reversed.) I used your version, but sill have the issue!. Am I missing something? How did you fix this in your project?

To make sure we are talking about the same thing, I am talking about the following problem.

  1. add an RTL language, e.g. Arabic, from the device's settings to your device/emulator
  2. Make the RTL language the default language
  3. enter 123 456 in . It displays is 456 123. This is the problem I am still facing. How did you fix it?

Your input is highly appreciated!

PPHelios commented 2 weeks ago

@Bilal-Abdeen I didn't do anything special regarding using the component, the direction of numbers should be handled by the system, i will include my component maybe I forgot something.

I don't know if it's the cause but why don't you try switching the language directly from the app.

<PhoneInput value={value} onChangePhoneNumber={value => onChange(toEnDigit(value))} selectedCountry={selectedCountry} onChangeSelectedCountry={country => setSelectedCountry(country) } language={isArabic ? 'ar' : 'en'} theme={isThemeDark ? 'dark' : 'light'} defaultCountry="EG" disabled={loading} onSubmitEditing={() => passwordRef.current.focus()} returnKeyType="next" autoFocus={true} blurOnSubmit={false} phoneInputStyles={{ flagContainer: {width: 120, borderRadius: isArabic ? 7 : 0}, input: { fontSize: 15, }, }} modalStyles={{ searchInput: { color: isThemeDark ? 'white' : 'black', }, callingCode: { fontSize: 16, // fontWeight: 'bold', color: isThemeDark ? 'white' : 'black', }, countryName: { fontSize: 16, // fontWeight: 'bold', color: isThemeDark ? 'white' : 'black', }, }} /> )} />

Bilal-Abdeen commented 2 weeks ago

@PPHelios Thank you very much for sharing that. Can you, please, send the code for the following functions? onChange & toEnDigit?

PPHelios commented 2 weeks ago

@Bilal-Abdeen onChange comes from "react-hook-form".

Find below the toEnDigit function export const toEnDigit = persianString => { let normalizedInput = persianString; if (typeof persianString !== 'string') { normalizedInput = String(persianString); } const englishDigits = normalizedInput.replace(/[٠-۹]/g, persianDigit => persianDigit.charCodeAt(0) & 15); return englishDigits; };

Bilal-Abdeen commented 2 weeks ago

@PPHelios Thank you for that. I am not sure I understand what you mean by onChange comes from "react-hook-form". If it is not too much to ask, can you share the relevant code as well? Probably react-hook-form does some formatting, which fixes the issue of the reverse ordering of the different parts of the masked phone number!

Bilal-Abdeen commented 2 weeks ago

@PPHelios and @AstrOOnauta, I think I discovered why @PPHelios'a code works. It seems to be because of the property phoneInputStyles={{ flagContainer: { width: 120, }, }}!!!!

<PhoneInput
   ....
   phoneInputStyles={{ flagContainer: { width: 120, }, }}
/>

This is strange. This styling is applied to <TouchableOpacity>, which surrounds the flag & country code. I am not sure how this affects the <TextInput> following the <TouchableOpacity>!!!

For now, it seems that using phoneInputStyles={{ flagContainer: { width: 120, }, }} is a good, temporary "workaround" for the issue.

arakovskis commented 1 day ago

Can confirm that adding width to flagContainer fixes problem with mask. image image

Also, it breaks when you apply styles like fontFamily to input.