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

feat(amount-input-screen): allow for pasting values in amount input s… #2854

Merged
merged 7 commits into from
Dec 8, 2023

Conversation

MaxwellDG
Copy link
Contributor

Addresses issue #2497

I've added the ability to paste into the amount screen.
This accounts for:

  • validating that it's only numerical and/or decimals
  • not opening the keyboard
  • maintaining that there can varying amounts of integers after the decimal (depending on the currency)
  • maintains auto-formatting with commas for ease of viewing
  • combining the stateful input of pastes with numpad inputs

PS While working on this I noticed a large problem. There are dozens of currencies that use commas instead of decimals to differentiate between the 'dollar' and 'cent' (or whatever they call them) values. The library we're using for countries accounts for this but our numpad and input does not. This means anyone trying to input partial values is blocked. If you'd like to see for yourself, try Albanian money. I've opened an issue for this #2853

@nicolasburtey
Copy link
Member

nicolasburtey commented Dec 1, 2023

There are dozens of currencies that use commas instead of decimals to differentiate between the 'dollar' and 'cent' (or whatever they call them) values.

this has less to do with currency but more with the language / country settings actually.

ie: in France, we would show
100€
100$

while in the US we would have:
€100
$100

In Javascript, this would be a way on how to properly show the currency amount: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat

Comment on lines 121 to 138
if (action.payload.key.length > 1) {
// here the whole numberPadNumber will be formatted and replaced
// unlike the several sections below which append to the value(s)
const num = Number(action.payload.key)
// format to float if number has decimal - otherwise integer
const formatted: string =
num % 1 === 0 ? num.toString() : num.toFixed(numberOfDecimalsAllowed)
const splitByDecimal = formatted.split(".")

return {
...state,
numberPadNumber: {
majorAmount: splitByDecimal[0],
hasDecimal: splitByDecimal.length > 1,
minorAmount: splitByDecimal[1] ?? "",
},
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while I think the code is working, I don't think this is the cleaner way to manage the paste of a code

we use a reducer to have a clean boundary between different action, and it would be better to have an action dedicated to the use case when the user paste a code. effectively what this would looks like is that there would be a third action, ie case NumberPadReducerActionType.PasteAmount that would trigger this piece of code.

this would also avoid the casting here https://github.com/GaloyMoney/galoy-mobile/pull/2854/files#diff-f90138f20708f2a12f53a72c46c65505a8dd601948f85ee3f6ca3f22a6c8c6c4R67

this casting is misleading because we force a large value to be a Key which by definition should be a single digit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea i get that. Ill be back online in a couple days and Ill make a new reducer action. Makes sense following that pattern more

Copy link
Contributor Author

@MaxwellDG MaxwellDG Dec 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolasburtey The type for 'Keys' I added felt a bit weird, but I believe its the best option. You'll notice starting from amount-input-screen-ui.tsx line 69 I go from string -> Number -> string -> Number -> string again. If you think that's weird let me know and I can explain the rationale.

@nicolasburtey
Copy link
Member

The Logic on the PR looks good but I think we need an refactoring iteration so that the code doesn't casting and has better function boundary

Comment on lines 62 to 72
onChangeText={(e) => {
// remove commas for ease of calculation later on
const val = e.replaceAll(",", "")
// TODO adjust for currencies that use commas instead of decimals

// test for string input that can be either numerical or float
if (/^\d*\.?\d*$/.test(val)) {
const num = Number(val)
onPaste(`${num}`)
}
}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this code executed both for the case when we add a key or when we paste a string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I double-checked, and no - it's only when the user changes the input field directly themselves.

@@ -54,6 +61,8 @@ export const Key = {

export type Key = (typeof Key)[keyof typeof Key]

export type Keys = `${number | ""}${"." | ""}${number | ""}`
Copy link
Member

@nicolasburtey nicolasburtey Dec 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assuming Keys is what the user can paste, I don't think it make sense really a type. because ultimately the user could paste anything: a string, a number. I think we will want to validate / trim the input to make sure that if the user paste something incorrect, this is correctly handled.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

said another way, I don't think we need a Keys type at all, and we can accept a string instead that should be tentatively converted to a number.

Copy link
Contributor Author

@MaxwellDG MaxwellDG Dec 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea i agree the Keys type seemed unnecessary. Removing that would streamline the code here too by removing unnecessary type conversions. Ill adjust the whole process to accept a number.

The safety and validation is already there too. Note the regex matching on line 68 in amount-input-screen-ui.tsx.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh and i'll throw in that trim() too

@nicolasburtey
Copy link
Member

The PR looks much better overall, but I think we need a proper validation on what the user is pasting, to properly manage the case when the input is not convertible into a number.

@MaxwellDG
Copy link
Contributor Author

MaxwellDG commented Dec 6, 2023

The PR looks much better overall, but I think we need a proper validation on what the user is pasting, to properly manage the case when the input is not convertible into a number.

You don't think the regex string matching is enough? Currently if the value can't be formatted into a number then it is a no-op and doesn't allow it to be pasted.

@nicolasburtey
Copy link
Member

The PR looks much better overall, but I think we need a proper validation on what the user is pasting, to properly manage the case when the input is not convertible into a number.

You don't think the regex string matching is enough? Currently if the value can't be formatted into a number then it is a no-op and doesn't allow it to be pasted.

ok I think that might be good enough

@nicolasburtey nicolasburtey merged commit 0d49abe into GaloyMoney:main Dec 8, 2023
7 checks passed
@MaxwellDG MaxwellDG deleted the feature/input-currency-val branch December 8, 2023 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants