Skip to content

Commit

Permalink
Merge pull request #49180 from software-mansion-labs/fix/percentage-form
Browse files Browse the repository at this point in the history
iOS Rules - Text cursor moves to front after entering the third digit in Percentage field
  • Loading branch information
iwiznia committed Sep 24, 2024
2 parents 42558e9 + af0d705 commit 026ae4f
Showing 1 changed file with 2 additions and 25 deletions.
27 changes: 2 additions & 25 deletions src/components/PercentageForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type {ForwardedRef} from 'react';
import React, {forwardRef, useCallback, useMemo, useRef, useState} from 'react';
import type {NativeSyntheticEvent, TextInputSelectionChangeEventData} from 'react-native';
import React, {forwardRef, useCallback, useMemo, useRef} from 'react';
import useLocalize from '@hooks/useLocalize';
import * as MoneyRequestUtils from '@libs/MoneyRequestUtils';
import CONST from '@src/CONST';
Expand All @@ -21,28 +20,13 @@ type PercentageFormProps = {
label?: string;
};

/**
* Returns the new selection object based on the updated amount's length
*/
const getNewSelection = (oldSelection: {start: number; end: number}, prevLength: number, newLength: number) => {
const cursorPosition = oldSelection.end + (newLength - prevLength);
return {start: cursorPosition, end: cursorPosition};
};

function PercentageForm({value: amount, errorText, onInputChange, label, ...rest}: PercentageFormProps, forwardedRef: ForwardedRef<BaseTextInputRef>) {
const {toLocaleDigit, numberFormat} = useLocalize();

const textInput = useRef<BaseTextInputRef | null>(null);

const currentAmount = useMemo(() => (typeof amount === 'string' ? amount : ''), [amount]);

const [selection, setSelection] = useState({
start: currentAmount.length,
end: currentAmount.length,
});

const forwardDeletePressedRef = useRef(false);

/**
* Sets the selection and the amount accordingly to the value passed to the input
* @param newAmount - Changed amount from user input
Expand All @@ -55,16 +39,13 @@ function PercentageForm({value: amount, errorText, onInputChange, label, ...rest
// Use a shallow copy of selection to trigger setSelection
// More info: https://github.com/Expensify/App/issues/16385
if (!MoneyRequestUtils.validatePercentage(newAmountWithoutSpaces)) {
setSelection((prevSelection) => ({...prevSelection}));
return;
}

const strippedAmount = MoneyRequestUtils.stripCommaFromAmount(newAmountWithoutSpaces);
const isForwardDelete = currentAmount.length > strippedAmount.length && forwardDeletePressedRef.current;
setSelection(getNewSelection(selection, isForwardDelete ? strippedAmount.length : currentAmount.length, strippedAmount.length));
onInputChange?.(strippedAmount);
},
[currentAmount, onInputChange, selection],
[onInputChange],
);

const formattedAmount = MoneyRequestUtils.replaceAllDigits(currentAmount, toLocaleDigit);
Expand All @@ -84,10 +65,6 @@ function PercentageForm({value: amount, errorText, onInputChange, label, ...rest
}
textInput.current = ref;
}}
selection={selection}
onSelectionChange={(e: NativeSyntheticEvent<TextInputSelectionChangeEventData>) => {
setSelection(e.nativeEvent.selection);
}}
suffixCharacter="%"
keyboardType={CONST.KEYBOARD_TYPE.DECIMAL_PAD}
// eslint-disable-next-line react/jsx-props-no-spreading
Expand Down

0 comments on commit 026ae4f

Please sign in to comment.