Skip to content

[HOLD on #48160] fix: autoGrow prop on mobile is handled by native platform #50238

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

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/AmountTextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type AmountTextInputProps = {

/** Hide the focus styles on TextInput */
hideFocusedState?: boolean;
} & Pick<BaseTextInputProps, 'autoFocus' | 'autoGrowExtraSpace'>;
} & Pick<BaseTextInputProps, 'autoFocus'>;

function AmountTextInput(
{
Expand Down
33 changes: 14 additions & 19 deletions src/components/MoneyRequestAmountInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ import React, {useCallback, useEffect, useImperativeHandle, useRef, useState} fr
import type {NativeSyntheticEvent, StyleProp, TextStyle, ViewStyle} from 'react-native';
import useLocalize from '@hooks/useLocalize';
import {useMouseContext} from '@hooks/useMouseContext';
import * as Browser from '@libs/Browser';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import {isMobileSafari} from '@libs/Browser';
import {convertToFrontendAmountAsString, getCurrencyDecimals} from '@libs/CurrencyUtils';
import getOperatingSystem from '@libs/getOperatingSystem';
import * as MoneyRequestUtils from '@libs/MoneyRequestUtils';
import {replaceAllDigits, replaceCommasWithPeriod, stripCommaFromAmount, stripDecimalsFromAmount, stripSpacesFromAmount, validateAmount} from '@libs/MoneyRequestUtils';
import shouldIgnoreSelectionWhenUpdatedManually from '@libs/shouldIgnoreSelectionWhenUpdatedManually';
import CONST from '@src/CONST';
import isTextInputFocused from './TextInput/BaseTextInput/isTextInputFocused';
import type {BaseTextInputRef} from './TextInput/BaseTextInput/types';
import TextInputWithCurrencySymbol from './TextInputWithCurrencySymbol';
import type {TextInputWithCurrencySymbolProps} from './TextInputWithCurrencySymbol/types';

type CurrentMoney = {amount: string; currency: string};

Expand Down Expand Up @@ -92,7 +91,7 @@ type MoneyRequestAmountInputProps = {

/** The width of inner content */
contentWidth?: number;
} & Pick<TextInputWithCurrencySymbolProps, 'autoGrowExtraSpace'>;
};

type Selection = {
start: number;
Expand All @@ -107,7 +106,7 @@ const getNewSelection = (oldSelection: Selection, prevLength: number, newLength:
return {start: cursorPosition, end: cursorPosition};
};

const defaultOnFormatAmount = (amount: number, currency?: string) => CurrencyUtils.convertToFrontendAmountAsString(amount, currency ?? CONST.CURRENCY.USD);
const defaultOnFormatAmount = (amount: number, currency?: string) => convertToFrontendAmountAsString(amount, currency ?? CONST.CURRENCY.USD);

function MoneyRequestAmountInput(
{
Expand All @@ -127,7 +126,6 @@ function MoneyRequestAmountInput(
hideFocusedState = true,
shouldKeepUserInput = false,
autoGrow = true,
autoGrowExtraSpace,
contentWidth,
...props
}: MoneyRequestAmountInputProps,
Expand All @@ -139,7 +137,7 @@ function MoneyRequestAmountInput(

const amountRef = useRef<string | undefined>(undefined);

const decimals = CurrencyUtils.getCurrencyDecimals(currency);
const decimals = getCurrencyDecimals(currency);
const selectedAmountAsString = amount ? onFormatAmount(amount, currency) : '';

const [currentAmount, setCurrentAmount] = useState(selectedAmountAsString);
Expand All @@ -161,13 +159,11 @@ function MoneyRequestAmountInput(
(newAmount: string) => {
// Remove spaces from the newAmount value because Safari on iOS adds spaces when pasting a copied value
// More info: https://github.com/Expensify/App/issues/16974
const newAmountWithoutSpaces = MoneyRequestUtils.stripSpacesFromAmount(newAmount);
const finalAmount = newAmountWithoutSpaces.includes('.')
? MoneyRequestUtils.stripCommaFromAmount(newAmountWithoutSpaces)
: MoneyRequestUtils.replaceCommasWithPeriod(newAmountWithoutSpaces);
const newAmountWithoutSpaces = stripSpacesFromAmount(newAmount);
const finalAmount = newAmountWithoutSpaces.includes('.') ? stripCommaFromAmount(newAmountWithoutSpaces) : replaceCommasWithPeriod(newAmountWithoutSpaces);
// Use a shallow copy of selection to trigger setSelection
// More info: https://github.com/Expensify/App/issues/16385
if (!MoneyRequestUtils.validateAmount(finalAmount, decimals)) {
if (!validateAmount(finalAmount, decimals)) {
setSelection((prevSelection) => ({...prevSelection}));
return;
}
Expand All @@ -176,7 +172,7 @@ function MoneyRequestAmountInput(

willSelectionBeUpdatedManually.current = true;
let hasSelectionBeenSet = false;
const strippedAmount = MoneyRequestUtils.stripCommaFromAmount(finalAmount);
const strippedAmount = stripCommaFromAmount(finalAmount);
amountRef.current = strippedAmount;
setCurrentAmount((prevAmount) => {
const isForwardDelete = prevAmount.length > strippedAmount.length && forwardDeletePressedRef.current;
Expand Down Expand Up @@ -233,12 +229,12 @@ function MoneyRequestAmountInput(
// Modifies the amount to match the decimals for changed currency.
useEffect(() => {
// If the changed currency supports decimals, we can return
if (MoneyRequestUtils.validateAmount(currentAmount, decimals)) {
if (validateAmount(currentAmount, decimals)) {
return;
}

// If the changed currency doesn't support decimals, we can strip the decimals
setNewAmount(MoneyRequestUtils.stripDecimalsFromAmount(currentAmount));
setNewAmount(stripDecimalsFromAmount(currentAmount));

// we want to update only when decimals change (setNewAmount also changes when decimals change).
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
Expand All @@ -249,7 +245,7 @@ function MoneyRequestAmountInput(
*/
const textInputKeyPress = ({nativeEvent}: NativeSyntheticEvent<KeyboardEvent>) => {
const key = nativeEvent?.key.toLowerCase();
if (Browser.isMobileSafari() && key === CONST.PLATFORM_SPECIFIC_KEYS.CTRL.DEFAULT) {
if (isMobileSafari() && key === CONST.PLATFORM_SPECIFIC_KEYS.CTRL.DEFAULT) {
// Optimistically anticipate forward-delete on iOS Safari (in cases where the Mac Accessiblity keyboard is being
// used for input). If the Control-D shortcut doesn't get sent, the ref will still be reset on the next key press.
forwardDeletePressedRef.current = true;
Expand All @@ -276,7 +272,7 @@ function MoneyRequestAmountInput(
});
}, [amount, currency, onFormatAmount, formatAmountOnBlur, maxLength]);

const formattedAmount = MoneyRequestUtils.replaceAllDigits(currentAmount, toLocaleDigit);
const formattedAmount = replaceAllDigits(currentAmount, toLocaleDigit);

const {setMouseDown, setMouseUp} = useMouseContext();
const handleMouseDown = (e: React.MouseEvent<Element, MouseEvent>) => {
Expand All @@ -291,7 +287,6 @@ function MoneyRequestAmountInput(
return (
<TextInputWithCurrencySymbol
autoGrow={autoGrow}
autoGrowExtraSpace={autoGrowExtraSpace}
disableKeyboard={disableKeyboard}
formattedAmount={formattedAmount}
onChangeAmount={setNewAmount}
Expand Down
32 changes: 2 additions & 30 deletions src/components/TextInput/BaseTextInput/index.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ function BaseTextInput(
autoFocus = false,
disableKeyboard = false,
autoGrow = false,
autoGrowExtraSpace = 0,
autoGrowHeight = false,
maxAutoGrowHeight,
hideFocusedState = false,
Expand Down Expand Up @@ -256,7 +255,6 @@ function BaseTextInput(
styles.textInputContainer,
textInputContainerStyles,
!!contentWidth && StyleUtils.getWidthStyle(textInputWidth),
autoGrow && StyleUtils.getAutoGrowWidthInputContainerStyles(textInputWidth, autoGrowExtraSpace),
!hideFocusedState && isFocused && styles.borderColorFocus,
(!!hasError || !!errorText) && styles.borderColorDanger,
autoGrowHeight && {scrollPaddingTop: typeof maxAutoGrowHeight === 'number' ? 2 * maxAutoGrowHeight : undefined},
Expand Down Expand Up @@ -351,8 +349,8 @@ function BaseTextInput(
placeholderTextColor={placeholderTextColor ?? theme.placeholderText}
underlineColorAndroid="transparent"
style={[
styles.flex1,
styles.w100,
!autoGrow && styles.flex1,
!autoGrow && styles.w100,
inputStyle,
(!hasLabel || isMultiline) && styles.pv0,
inputPaddingLeft,
Expand Down Expand Up @@ -463,32 +461,6 @@ function BaseTextInput(
</Text>
</View>
)}
{/*
Text input component doesn't support auto grow by default.
This text view is used to calculate width or height of the input value given textStyle in this component.
This Text component is intentionally positioned out of the screen.
*/}
{(!!autoGrow || autoGrowHeight) && !isAutoGrowHeightMarkdown && (
<Text
style={[
inputStyle,
autoGrowHeight && styles.autoGrowHeightHiddenInput(width ?? 0, typeof maxAutoGrowHeight === 'number' ? maxAutoGrowHeight : undefined),
styles.hiddenElementOutsideOfWindow,
styles.visibilityHidden,
]}
onLayout={(e) => {
if (e.nativeEvent.layout.width === 0 && e.nativeEvent.layout.height === 0) {
return;
}
// Add +2 to width so that cursor is not cut off / covered at the end of text content
setTextInputWidth(e.nativeEvent.layout.width + 2);
setTextInputHeight(e.nativeEvent.layout.height);
}}
>
{/* \u200B added to solve the issue of not expanding the text input enough when the value ends with '\n' (https://github.com/Expensify/App/issues/21271) */}
{value ? `${value}${value.endsWith('\n') ? '\u200B' : ''}` : placeholder}
</Text>
)}
</>
);
}
Expand Down
3 changes: 0 additions & 3 deletions src/components/TextInput/BaseTextInput/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ type CustomBaseTextInputProps = {
*/
autoGrow?: boolean;

/** If autoGrow is enabled, this reserves extra space for incoming characters to prevent flickering on native platforms. */
autoGrowExtraSpace?: number;

/**
* Autogrow input container height based on the entered text
*/
Expand Down
2 changes: 1 addition & 1 deletion src/components/TextInputWithCurrencySymbol/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ type BaseTextInputWithCurrencySymbolProps = {

/** Hide the focus styles on TextInput */
hideFocusedState?: boolean;
} & Pick<BaseTextInputProps, 'autoFocus' | 'autoGrow' | 'autoGrowExtraSpace' | 'contentWidth' | 'onPress'>;
} & Pick<BaseTextInputProps, 'autoFocus' | 'autoGrow' | 'contentWidth' | 'onPress'>;

type TextInputWithCurrencySymbolProps = Omit<BaseTextInputWithCurrencySymbolProps, 'onSelectionChange'> & {
onSelectionChange?: (start: number, end: number) => void;
Expand Down
2 changes: 0 additions & 2 deletions src/pages/iou/MoneyRequestAmountForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {convertToDisplayString, convertToFrontendAmountAsInteger, convertToFront
import {canUseTouchScreen as canUseTouchScreenUtil} from '@libs/DeviceCapabilities';
import {addLeadingZero} from '@libs/MoneyRequestUtils';
import Navigation from '@libs/Navigation/Navigation';
import variables from '@styles/variables';
import type {BaseTextInputRef} from '@src/components/TextInput/BaseTextInput/types';
import CONST from '@src/CONST';
import type {Route} from '@src/ROUTES';
Expand Down Expand Up @@ -257,7 +256,6 @@ function MoneyRequestAmountForm(
>
<MoneyRequestAmountInput
amount={amount}
autoGrowExtraSpace={variables.w80}
currency={currency}
isCurrencyPressable={isCurrencyPressable}
onCurrencyButtonPress={onCurrencyButtonPress}
Expand Down
Loading