diff --git a/packages/desktop-client/src/components/mobile/transactions/FocusableAmountInput.tsx b/packages/desktop-client/src/components/mobile/transactions/FocusableAmountInput.tsx index 6f3c66845e8137b8e5d2754085b2ad80c75ab95d..b2caac449f1f9feaedd022d9c9eff30e1e1e13db 100644 --- a/packages/desktop-client/src/components/mobile/transactions/FocusableAmountInput.tsx +++ b/packages/desktop-client/src/components/mobile/transactions/FocusableAmountInput.tsx @@ -9,9 +9,9 @@ import React, { } from 'react'; import { - toRelaxedNumber, amountToCurrency, - getNumberFormat, + appendDecimals, + currencyToAmount, } from 'loot-core/src/shared/util'; import { useLocalPref } from '../../../hooks/useLocalPref'; @@ -67,10 +67,6 @@ const AmountInput = memo(function AmountInput({ setValue(initialValue); }, [initialValue]); - const parseText = () => { - return toRelaxedNumber(text.replace(/[,.]/, getNumberFormat().separator)); - }; - const onKeyUp: HTMLProps<HTMLInputElement>['onKeyUp'] = e => { if (e.key === 'Backspace' && text === '') { setEditing(true); @@ -83,7 +79,7 @@ const AmountInput = memo(function AmountInput({ }; const applyText = () => { - const parsed = parseText(); + const parsed = currencyToAmount(text) || 0; const newValue = editing ? parsed : value; setValue(Math.abs(newValue)); @@ -111,16 +107,7 @@ const AmountInput = memo(function AmountInput({ }; const onChangeText = (text: string) => { - if (text.slice(-1) === '.') { - text = text.slice(0, -1); - } - if (!hideFraction) { - text = text.replaceAll(/[,.]/g, ''); - text = text.replace(/^0+(?!$)/, ''); - text = text.padStart(3, '0'); - text = text.slice(0, -2) + '.' + text.slice(-2); - } - + text = appendDecimals(text, hideFraction); setEditing(true); setText(text); props.onChangeValue?.(text); @@ -163,7 +150,7 @@ const AmountInput = memo(function AmountInput({ }} data-testid="amount-fake-input" > - {editing ? amountToCurrency(text) : amountToCurrency(value)} + {editing ? text : amountToCurrency(value)} </Text> </View> ); diff --git a/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx b/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx index a489185137df64a2c9b81c2e3bb2850cfeed0641..78cc7f5cd24b901490f7bf321660d10537ae10f6 100644 --- a/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx +++ b/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx @@ -333,6 +333,7 @@ const ChildTransactionEdit = forwardRef( onClearActiveEdit(); } }} + autoDecimals={true} /> </View> </View> diff --git a/packages/desktop-client/src/components/util/AmountInput.tsx b/packages/desktop-client/src/components/util/AmountInput.tsx index c0831412438e102b48d6cb43a91229b03580bbcc..cde149e0c60e2c5f9e6829463162fc79e4f4a419 100644 --- a/packages/desktop-client/src/components/util/AmountInput.tsx +++ b/packages/desktop-client/src/components/util/AmountInput.tsx @@ -8,8 +8,9 @@ import React, { } from 'react'; import { evalArithmetic } from 'loot-core/src/shared/arithmetic'; -import { amountToInteger } from 'loot-core/src/shared/util'; +import { amountToInteger, appendDecimals } from 'loot-core/src/shared/util'; +import { useLocalPref } from '../../hooks/useLocalPref'; import { useMergedRefs } from '../../hooks/useMergedRefs'; import { SvgAdd, SvgSubtract } from '../../icons/v1'; import { type CSSProperties, theme } from '../../style'; @@ -31,6 +32,7 @@ type AmountInputProps = { textStyle?: CSSProperties; focused?: boolean; disabled?: boolean; + autoDecimals?: boolean; }; export function AmountInput({ @@ -46,6 +48,7 @@ export function AmountInput({ textStyle, focused, disabled = false, + autoDecimals = false, }: AmountInputProps) { const format = useFormat(); const negative = (initialValue === 0 && zeroSign === '-') || initialValue < 0; @@ -57,6 +60,7 @@ export function AmountInput({ const buttonRef = useRef(); const ref = useRef<HTMLInputElement>(null); const mergedRef = useMergedRefs<HTMLInputElement>(inputRef, ref); + const [hideFraction = false] = useLocalPref('hideFraction'); useEffect(() => { if (focused) { @@ -74,6 +78,7 @@ export function AmountInput({ } function onInputTextChange(val) { + val = autoDecimals ? appendDecimals(val, hideFraction) : val; setValue(val ? val : ''); onChangeValue?.(val); } diff --git a/packages/loot-core/src/shared/util.ts b/packages/loot-core/src/shared/util.ts index 2a8d0e8cde1d47d62071b3647070ea781d7d6098..ac2680712d955a224133d82545d2981487245654 100644 --- a/packages/loot-core/src/shared/util.ts +++ b/packages/loot-core/src/shared/util.ts @@ -199,6 +199,24 @@ export function titleFirst(str: string) { return str[0].toUpperCase() + str.slice(1); } +export function appendDecimals( + amountText: string, + hideDecimals = false, +): string { + const { separator } = getNumberFormat(); + let result = amountText; + if (result.slice(-1) === separator) { + result = result.slice(0, -1); + } + if (!hideDecimals) { + result = result.replaceAll(/[,.]/g, ''); + result = result.replace(/^0+(?!$)/, ''); + result = result.padStart(3, '0'); + result = result.slice(0, -2) + separator + result.slice(-2); + } + return amountToCurrency(currencyToAmount(result)); +} + type NumberFormats = | 'comma-dot' | 'dot-comma' diff --git a/upcoming-release-notes/2746.md b/upcoming-release-notes/2746.md new file mode 100644 index 0000000000000000000000000000000000000000..2311b55b589a723784b74ea1c65e1cfc6bd066de --- /dev/null +++ b/upcoming-release-notes/2746.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [joel-jeremy] +--- + +Auto insert decimals to mobile split transaction amounts.