From 2a09811e8833f478b8f4aed976b27156dff6ff5a Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 28 Nov 2023 13:33:47 +0100 Subject: [PATCH 01/34] update import --- src/components/Composer/index.android.js | 4 ++-- src/components/Composer/index.ios.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Composer/index.android.js b/src/components/Composer/index.android.js index 7b72e17ae5fe..a1d6d514149b 100644 --- a/src/components/Composer/index.android.js +++ b/src/components/Composer/index.android.js @@ -3,7 +3,7 @@ import React, {useCallback, useEffect, useMemo, useRef} from 'react'; import _ from 'underscore'; import RNTextInput from '@components/RNTextInput'; import * as ComposerUtils from '@libs/ComposerUtils'; -import {getComposerMaxHeightStyle} from '@styles/StyleUtils'; +import * as StyleUtils from '@styles/StyleUtils'; import themeColors from '@styles/themes/default'; const propTypes = { @@ -92,7 +92,7 @@ function Composer({shouldClear, onClear, isDisabled, maxLines, forwardedRef, isC onClear(); }, [shouldClear, onClear]); - const maxHeightStyle = useMemo(() => getComposerMaxHeightStyle(maxLines, isComposerFullSize), [isComposerFullSize, maxLines]); + const maxHeightStyle = useMemo(() => StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), [isComposerFullSize, maxLines]); return ( getComposerMaxHeightStyle(maxLines, isComposerFullSize), [isComposerFullSize, maxLines]); + const maxHeightStyle = useMemo(() => StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), [isComposerFullSize, maxLines]); // On native layers we like to have the Text Input not focused so the // user can read new chats without the keyboard in the way of the view. From db57bf3ecc192ac805ed37e2d3367327c7332a96 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 28 Nov 2023 13:42:17 +0100 Subject: [PATCH 02/34] simplify android and ios implementations --- src/components/Composer/index.ios.js | 130 ------------------ .../{index.android.js => index.native.js} | 7 +- 2 files changed, 4 insertions(+), 133 deletions(-) delete mode 100644 src/components/Composer/index.ios.js rename src/components/Composer/{index.android.js => index.native.js} (99%) diff --git a/src/components/Composer/index.ios.js b/src/components/Composer/index.ios.js deleted file mode 100644 index 18f625c25a0d..000000000000 --- a/src/components/Composer/index.ios.js +++ /dev/null @@ -1,130 +0,0 @@ -import PropTypes from 'prop-types'; -import React, {useCallback, useEffect, useMemo, useRef} from 'react'; -import _ from 'underscore'; -import RNTextInput from '@components/RNTextInput'; -import * as ComposerUtils from '@libs/ComposerUtils'; -import * as StyleUtils from '@styles/StyleUtils'; -import themeColors from '@styles/themes/default'; - -const propTypes = { - /** If the input should clear, it actually gets intercepted instead of .clear() */ - shouldClear: PropTypes.bool, - - /** A ref to forward to the text input */ - forwardedRef: PropTypes.func, - - /** When the input has cleared whoever owns this input should know about it */ - onClear: PropTypes.func, - - /** Set focus to this component the first time it renders. - * Override this in case you need to set focus on one field out of many, or when you want to disable autoFocus */ - autoFocus: PropTypes.bool, - - /** Prevent edits and interactions like focus for this input. */ - isDisabled: PropTypes.bool, - - /** Selection Object */ - selection: PropTypes.shape({ - start: PropTypes.number, - end: PropTypes.number, - }), - - /** Whether the full composer can be opened */ - isFullComposerAvailable: PropTypes.bool, - - /** Maximum number of lines in the text input */ - maxLines: PropTypes.number, - - /** Allow the full composer to be opened */ - setIsFullComposerAvailable: PropTypes.func, - - /** Whether the composer is full size */ - isComposerFullSize: PropTypes.bool, - - /** General styles to apply to the text input */ - // eslint-disable-next-line react/forbid-prop-types - style: PropTypes.any, -}; - -const defaultProps = { - shouldClear: false, - onClear: () => {}, - autoFocus: false, - isDisabled: false, - forwardedRef: null, - selection: { - start: 0, - end: 0, - }, - maxLines: undefined, - isFullComposerAvailable: false, - setIsFullComposerAvailable: () => {}, - isComposerFullSize: false, - style: null, -}; - -function Composer({shouldClear, onClear, isDisabled, maxLines, forwardedRef, isComposerFullSize, setIsFullComposerAvailable, ...props}) { - const textInput = useRef(null); - - /** - * Set the TextInput Ref - * @param {Element} el - */ - const setTextInputRef = useCallback((el) => { - textInput.current = el; - if (!_.isFunction(forwardedRef) || textInput.current === null) { - return; - } - - // This callback prop is used by the parent component using the constructor to - // get a ref to the inner textInput element e.g. if we do - // this.textInput = el} /> this will not - // return a ref to the component, but rather the HTML element by default - forwardedRef(textInput.current); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - useEffect(() => { - if (!shouldClear) { - return; - } - textInput.current.clear(); - onClear(); - }, [shouldClear, onClear]); - - const maxHeightStyle = useMemo(() => StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), [isComposerFullSize, maxLines]); - - // On native layers we like to have the Text Input not focused so the - // user can read new chats without the keyboard in the way of the view. - // On Android the selection prop is required on the TextInput but this prop has issues on IOS - const propsToPass = _.omit(props, 'selection'); - return ( - ComposerUtils.updateNumberOfLines({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e)} - rejectResponderTermination={false} - smartInsertDelete={false} - style={[...props.style, maxHeightStyle]} - readOnly={isDisabled} - /> - ); -} - -Composer.propTypes = propTypes; -Composer.defaultProps = defaultProps; - -const ComposerWithRef = React.forwardRef((props, ref) => ( - -)); - -ComposerWithRef.displayName = 'ComposerWithRef'; - -export default ComposerWithRef; diff --git a/src/components/Composer/index.android.js b/src/components/Composer/index.native.js similarity index 99% rename from src/components/Composer/index.android.js rename to src/components/Composer/index.native.js index a1d6d514149b..5bec0f701ec5 100644 --- a/src/components/Composer/index.android.js +++ b/src/components/Composer/index.native.js @@ -7,9 +7,6 @@ import * as StyleUtils from '@styles/StyleUtils'; import themeColors from '@styles/themes/default'; const propTypes = { - /** Maximum number of lines in the text input */ - maxLines: PropTypes.number, - /** If the input should clear, it actually gets intercepted instead of .clear() */ shouldClear: PropTypes.bool, @@ -32,6 +29,9 @@ const propTypes = { end: PropTypes.number, }), + /** Maximum number of lines in the text input */ + maxLines: PropTypes.number, + /** Whether the full composer can be opened */ isFullComposerAvailable: PropTypes.bool, @@ -103,6 +103,7 @@ function Composer({shouldClear, onClear, isDisabled, maxLines, forwardedRef, isC ref={setTextInputRef} onContentSizeChange={(e) => ComposerUtils.updateNumberOfLines({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e)} rejectResponderTermination={false} + smartInsertDelete={false} textAlignVertical="center" style={[...props.style, maxHeightStyle]} readOnly={isDisabled} From 170729c859d9daa171094c6c41b7b8014af45d5d Mon Sep 17 00:00:00 2001 From: MitchExpensify <36425901+MitchExpensify@users.noreply.github.com> Date: Tue, 21 Nov 2023 15:30:41 -0800 Subject: [PATCH 03/34] Update Introducing-Expensify-Chat.md Fixing so the help steps are numbered --- .../chat/Introducing-Expensify-Chat.md | 69 ++++++++++--------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/docs/articles/new-expensify/chat/Introducing-Expensify-Chat.md b/docs/articles/new-expensify/chat/Introducing-Expensify-Chat.md index 669d960275e6..25ccdefad261 100644 --- a/docs/articles/new-expensify/chat/Introducing-Expensify-Chat.md +++ b/docs/articles/new-expensify/chat/Introducing-Expensify-Chat.md @@ -24,30 +24,30 @@ After downloading the app, log into your new.expensify.com account (you’ll use ## How to send messages -Click **+** then **Send message** in New Expensify -Choose **Chat** -Search for any name, email or phone number -Select the individual to begin chatting +1. Click **+** then **Send message** in New Expensify +2. Choose **Chat** +3. Search for any name, email or phone number +4. Select the individual to begin chatting ## How to create a group -Click **+**, then **Send message** in New Expensify -Search for any name, email or phone number -Click **Add to group** -Group participants are listed with a green check -Repeat steps 1-3 to add more participants to the group -Click **Create chat** to start chatting +1. Click **+**, then **Send message** in New Expensify +2. Search for any name, email or phone number +3. Click **Add to group** +4. Group participants are listed with a green check +5. Repeat steps 1-3 to add more participants to the group +6. Click **Create chat** to start chatting ## How to create a room -Click **+**, then **Send message** in New Expensify -Click **Room** -Enter a room name that doesn’t already exist on the intended Workspace -Choose the Workspace you want to associate the room with. -Choose the room’s visibility setting: -Private: Only people explicitly invited can find the room* -Restricted: Workspace members can find the room* -Public: Anyone can find the room +1. Click **+**, then **Send message** in New Expensify +2. Click **Room** +3. Enter a room name that doesn’t already exist on the intended Workspace +4. Choose the Workspace you want to associate the room with. +5. Choose the room’s visibility setting: +6. Private: Only people explicitly invited can find the room* +7. Restricted: Workspace members can find the room* +8. Public: Anyone can find the room *Anyone, including non-Workspace Members, can be invited to a Private or Restricted room. @@ -56,26 +56,29 @@ Public: Anyone can find the room You can invite people to a Group or Room by @mentioning them or from the Members pane. ## Mentions: -Type **@** and start typing the person’s name or email address -Choose one or more contacts -Input message, if desired, then send + +1. Type **@** and start typing the person’s name or email address +2. Choose one or more contacts +3. Input message, if desired, then send ## Members pane invites: -Click the **Room** or **Group** header -Select **Members** -Click **Invite** -Find and select any contact/s you’d like to invite -Click **Next** -Write a custom invitation if you like -Click **Invite** + +1. Click the **Room** or **Group** header +2. Select **Members** +3. Click **Invite** +4. Find and select any contact/s you’d like to invite +5. Click **Next** +6. Write a custom invitation if you like +7. Click **Invite** ## Members pane removals: -Click the **Room** or **Group** header -Select **Members** -Find and select any contact/s you’d like to remove -Click **Remove** -Click **Remove members** + +1. Click the **Room** or **Group** header +2. Select **Members** +3. Find and select any contact/s you’d like to remove +4. Click **Remove** +5. Click **Remove members** ## How to format text From bbafbeabff805857f0f60ac4b24c010c25921aae Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Fri, 3 Nov 2023 09:23:20 +0100 Subject: [PATCH 04/34] start migrating PlaidLink to TypeScript --- .../{index.native.js => index.native.tsx} | 17 ++++++++-------- .../PlaidLink/{index.js => index.tsx} | 20 ++++++++----------- 2 files changed, 17 insertions(+), 20 deletions(-) rename src/components/PlaidLink/{index.native.js => index.native.tsx} (66%) rename src/components/PlaidLink/{index.js => index.tsx} (70%) diff --git a/src/components/PlaidLink/index.native.js b/src/components/PlaidLink/index.native.tsx similarity index 66% rename from src/components/PlaidLink/index.native.js rename to src/components/PlaidLink/index.native.tsx index 7d995d03926b..e1e9e7756620 100644 --- a/src/components/PlaidLink/index.native.js +++ b/src/components/PlaidLink/index.native.tsx @@ -1,27 +1,28 @@ import {useEffect} from 'react'; -import {dismissLink, openLink, useDeepLinkRedirector, usePlaidEmitter} from 'react-native-plaid-link-sdk'; +import {dismissLink, LinkEvent, openLink, useDeepLinkRedirector, usePlaidEmitter} from 'react-native-plaid-link-sdk'; import Log from '@libs/Log'; import CONST from '@src/CONST'; import {plaidLinkDefaultProps, plaidLinkPropTypes} from './plaidLinkPropTypes'; +import PlaidLinkProps from './types'; -function PlaidLink(props) { +function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: PlaidLinkProps) { useDeepLinkRedirector(); - usePlaidEmitter((event) => { + usePlaidEmitter((event: LinkEvent) => { Log.info('[PlaidLink] Handled Plaid Event: ', false, event); - props.onEvent(event.eventName, event.metadata); + onEvent?.(event.eventName, event.metadata); }); useEffect(() => { - props.onEvent(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN, {}); + onEvent?.(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN, {}); openLink({ tokenConfig: { - token: props.token, + token, }, onSuccess: ({publicToken, metadata}) => { - props.onSuccess({publicToken, metadata}); + onSuccess({publicToken, metadata}); }, onExit: (exitError, metadata) => { Log.info('[PlaidLink] Exit: ', false, {exitError, metadata}); - props.onExit(); + onExit(); }, }); diff --git a/src/components/PlaidLink/index.js b/src/components/PlaidLink/index.tsx similarity index 70% rename from src/components/PlaidLink/index.js rename to src/components/PlaidLink/index.tsx index 790206f34ce7..39b9ffda54b2 100644 --- a/src/components/PlaidLink/index.js +++ b/src/components/PlaidLink/index.tsx @@ -1,35 +1,33 @@ import {useCallback, useEffect, useState} from 'react'; -import {usePlaidLink} from 'react-plaid-link'; +import {PlaidLinkOnSuccessMetadata, usePlaidLink} from 'react-plaid-link'; import Log from '@libs/Log'; -import {plaidLinkDefaultProps, plaidLinkPropTypes} from './plaidLinkPropTypes'; +import PlaidLinkProps from './types'; -function PlaidLink(props) { +function PlaidLink({token, onSuccess = () => {}, onError = () => {}, onExit = () => {}, onEvent, receivedRedirectURI}: PlaidLinkProps) { const [isPlaidLoaded, setIsPlaidLoaded] = useState(false); - const onSuccess = props.onSuccess; - const onError = props.onError; const successCallback = useCallback( - (publicToken, metadata) => { + (publicToken: string, metadata: PlaidLinkOnSuccessMetadata) => { onSuccess({publicToken, metadata}); }, [onSuccess], ); const {open, ready, error} = usePlaidLink({ - token: props.token, + token, onSuccess: successCallback, onExit: (exitError, metadata) => { Log.info('[PlaidLink] Exit: ', false, {exitError, metadata}); - props.onExit(); + onExit(); }, onEvent: (event, metadata) => { Log.info('[PlaidLink] Event: ', false, {event, metadata}); - props.onEvent(event, metadata); + onEvent?.(event, metadata); }, onLoad: () => setIsPlaidLoaded(true), // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the // user to their respective bank platform - receivedRedirectUri: props.receivedRedirectURI, + receivedRedirectUri: receivedRedirectURI, }); useEffect(() => { @@ -52,7 +50,5 @@ function PlaidLink(props) { return null; } -PlaidLink.propTypes = plaidLinkPropTypes; -PlaidLink.defaultProps = plaidLinkDefaultProps; PlaidLink.displayName = 'PlaidLink'; export default PlaidLink; From 231211a0d5408bfca96875528298e21c6feb24b3 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Fri, 3 Nov 2023 09:23:54 +0100 Subject: [PATCH 05/34] migrate PlaidLinks native module to TypeScript, create a file for types --- .../{index.android.js => index.android.ts} | 0 .../{index.ios.js => index.ios.ts} | 0 src/components/PlaidLink/types.ts | 24 +++++++++++++++++++ 3 files changed, 24 insertions(+) rename src/components/PlaidLink/nativeModule/{index.android.js => index.android.ts} (100%) rename src/components/PlaidLink/nativeModule/{index.ios.js => index.ios.ts} (100%) create mode 100644 src/components/PlaidLink/types.ts diff --git a/src/components/PlaidLink/nativeModule/index.android.js b/src/components/PlaidLink/nativeModule/index.android.ts similarity index 100% rename from src/components/PlaidLink/nativeModule/index.android.js rename to src/components/PlaidLink/nativeModule/index.android.ts diff --git a/src/components/PlaidLink/nativeModule/index.ios.js b/src/components/PlaidLink/nativeModule/index.ios.ts similarity index 100% rename from src/components/PlaidLink/nativeModule/index.ios.js rename to src/components/PlaidLink/nativeModule/index.ios.ts diff --git a/src/components/PlaidLink/types.ts b/src/components/PlaidLink/types.ts new file mode 100644 index 000000000000..06b81d06b5c9 --- /dev/null +++ b/src/components/PlaidLink/types.ts @@ -0,0 +1,24 @@ +import {PlaidLinkOnEvent, PlaidLinkOnSuccessMetadata} from 'react-plaid-link'; + +type PlaidLinkProps = { + // Plaid Link SDK public token used to initialize the Plaid SDK + token: string; + + // Callback to execute once the user taps continue after successfully entering their account information + onSuccess?: (args: {publicToken?: string; metadata: PlaidLinkOnSuccessMetadata}) => void; + + // Callback to execute when there is an error event emitted by the Plaid SDK + onError?: (error: ErrorEvent | null) => void; + + // Callback to execute when the user leaves the Plaid widget flow without entering any information + onExit?: () => void; + + // Callback to execute whenever a Plaid event occurs + onEvent?: PlaidLinkOnEvent; + + // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the + // user to their respective bank platform + receivedRedirectURI?: string; +}; + +export default PlaidLinkProps; From a88d04761c46b651bd1f270edc5f29eb86a048b4 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 6 Nov 2023 15:59:55 +0100 Subject: [PATCH 06/34] migrate native PlaidLink to TypeScript --- src/components/PlaidLink/index.native.tsx | 12 +++---- .../PlaidLink/plaidLinkPropTypes.js | 31 ------------------- src/components/PlaidLink/types.ts | 7 +++-- 3 files changed, 9 insertions(+), 41 deletions(-) delete mode 100644 src/components/PlaidLink/plaidLinkPropTypes.js diff --git a/src/components/PlaidLink/index.native.tsx b/src/components/PlaidLink/index.native.tsx index e1e9e7756620..874d7c77414c 100644 --- a/src/components/PlaidLink/index.native.tsx +++ b/src/components/PlaidLink/index.native.tsx @@ -2,26 +2,26 @@ import {useEffect} from 'react'; import {dismissLink, LinkEvent, openLink, useDeepLinkRedirector, usePlaidEmitter} from 'react-native-plaid-link-sdk'; import Log from '@libs/Log'; import CONST from '@src/CONST'; -import {plaidLinkDefaultProps, plaidLinkPropTypes} from './plaidLinkPropTypes'; import PlaidLinkProps from './types'; function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: PlaidLinkProps) { useDeepLinkRedirector(); usePlaidEmitter((event: LinkEvent) => { - Log.info('[PlaidLink] Handled Plaid Event: ', false, event); + Log.info('[PlaidLink] Handled Plaid Event: ', false, event.eventName); onEvent?.(event.eventName, event.metadata); }); useEffect(() => { - onEvent?.(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN, {}); + onEvent?.(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN); openLink({ tokenConfig: { token, + noLoadingState: false, }, onSuccess: ({publicToken, metadata}) => { onSuccess({publicToken, metadata}); }, - onExit: (exitError, metadata) => { - Log.info('[PlaidLink] Exit: ', false, {exitError, metadata}); + onExit: ({error, metadata}) => { + Log.info('[PlaidLink] Exit: ', false, {error, metadata}); onExit(); }, }); @@ -36,8 +36,6 @@ function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: Pl return null; } -PlaidLink.propTypes = plaidLinkPropTypes; -PlaidLink.defaultProps = plaidLinkDefaultProps; PlaidLink.displayName = 'PlaidLink'; export default PlaidLink; diff --git a/src/components/PlaidLink/plaidLinkPropTypes.js b/src/components/PlaidLink/plaidLinkPropTypes.js deleted file mode 100644 index 6d647d26f17e..000000000000 --- a/src/components/PlaidLink/plaidLinkPropTypes.js +++ /dev/null @@ -1,31 +0,0 @@ -import PropTypes from 'prop-types'; - -const plaidLinkPropTypes = { - // Plaid Link SDK public token used to initialize the Plaid SDK - token: PropTypes.string.isRequired, - - // Callback to execute once the user taps continue after successfully entering their account information - onSuccess: PropTypes.func, - - // Callback to execute when there is an error event emitted by the Plaid SDK - onError: PropTypes.func, - - // Callback to execute when the user leaves the Plaid widget flow without entering any information - onExit: PropTypes.func, - - // Callback to execute whenever a Plaid event occurs - onEvent: PropTypes.func, - - // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the - // user to their respective bank platform - receivedRedirectURI: PropTypes.string, -}; - -const plaidLinkDefaultProps = { - onSuccess: () => {}, - onError: () => {}, - onExit: () => {}, - receivedRedirectURI: null, -}; - -export {plaidLinkPropTypes, plaidLinkDefaultProps}; diff --git a/src/components/PlaidLink/types.ts b/src/components/PlaidLink/types.ts index 06b81d06b5c9..4fc44cbf9b9c 100644 --- a/src/components/PlaidLink/types.ts +++ b/src/components/PlaidLink/types.ts @@ -1,11 +1,12 @@ -import {PlaidLinkOnEvent, PlaidLinkOnSuccessMetadata} from 'react-plaid-link'; +import {LinkEventMetadata, LinkSuccessMetadata} from 'react-native-plaid-link-sdk'; +import {PlaidLinkOnEventMetadata, PlaidLinkOnSuccessMetadata, PlaidLinkStableEvent} from 'react-plaid-link'; type PlaidLinkProps = { // Plaid Link SDK public token used to initialize the Plaid SDK token: string; // Callback to execute once the user taps continue after successfully entering their account information - onSuccess?: (args: {publicToken?: string; metadata: PlaidLinkOnSuccessMetadata}) => void; + onSuccess?: (args: {publicToken?: string; metadata: PlaidLinkOnSuccessMetadata | LinkSuccessMetadata}) => void; // Callback to execute when there is an error event emitted by the Plaid SDK onError?: (error: ErrorEvent | null) => void; @@ -14,7 +15,7 @@ type PlaidLinkProps = { onExit?: () => void; // Callback to execute whenever a Plaid event occurs - onEvent?: PlaidLinkOnEvent; + onEvent?: (eventName: PlaidLinkStableEvent | string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the // user to their respective bank platform From eacebd2c6e12d71540d7bab3ef4adf5065fa1b7e Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Tue, 7 Nov 2023 12:00:22 +0100 Subject: [PATCH 07/34] make onEvent a required prop to avoid optional chaining --- src/components/PlaidLink/index.native.tsx | 4 ++-- src/components/PlaidLink/index.tsx | 2 +- src/components/PlaidLink/types.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/PlaidLink/index.native.tsx b/src/components/PlaidLink/index.native.tsx index 874d7c77414c..b9accb0c0ad7 100644 --- a/src/components/PlaidLink/index.native.tsx +++ b/src/components/PlaidLink/index.native.tsx @@ -8,10 +8,10 @@ function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: Pl useDeepLinkRedirector(); usePlaidEmitter((event: LinkEvent) => { Log.info('[PlaidLink] Handled Plaid Event: ', false, event.eventName); - onEvent?.(event.eventName, event.metadata); + onEvent(event.eventName, event.metadata); }); useEffect(() => { - onEvent?.(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN); + onEvent(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN); openLink({ tokenConfig: { token, diff --git a/src/components/PlaidLink/index.tsx b/src/components/PlaidLink/index.tsx index 39b9ffda54b2..2109771473aa 100644 --- a/src/components/PlaidLink/index.tsx +++ b/src/components/PlaidLink/index.tsx @@ -21,7 +21,7 @@ function PlaidLink({token, onSuccess = () => {}, onError = () => {}, onExit = () }, onEvent: (event, metadata) => { Log.info('[PlaidLink] Event: ', false, {event, metadata}); - onEvent?.(event, metadata); + onEvent(event, metadata); }, onLoad: () => setIsPlaidLoaded(true), diff --git a/src/components/PlaidLink/types.ts b/src/components/PlaidLink/types.ts index 4fc44cbf9b9c..fe23e09151ca 100644 --- a/src/components/PlaidLink/types.ts +++ b/src/components/PlaidLink/types.ts @@ -15,7 +15,7 @@ type PlaidLinkProps = { onExit?: () => void; // Callback to execute whenever a Plaid event occurs - onEvent?: (eventName: PlaidLinkStableEvent | string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; + onEvent: (eventName: PlaidLinkStableEvent | string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the // user to their respective bank platform From 8e62b62b6eab86925fe37a6c58e94c15e331d28f Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Fri, 17 Nov 2023 09:02:10 +0100 Subject: [PATCH 08/34] remove unused nativeModule --- src/components/PlaidLink/nativeModule/index.android.ts | 3 --- src/components/PlaidLink/nativeModule/index.ios.ts | 3 --- 2 files changed, 6 deletions(-) delete mode 100644 src/components/PlaidLink/nativeModule/index.android.ts delete mode 100644 src/components/PlaidLink/nativeModule/index.ios.ts diff --git a/src/components/PlaidLink/nativeModule/index.android.ts b/src/components/PlaidLink/nativeModule/index.android.ts deleted file mode 100644 index d4280feddb8e..000000000000 --- a/src/components/PlaidLink/nativeModule/index.android.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {NativeModules} from 'react-native'; - -export default NativeModules.PlaidAndroid; diff --git a/src/components/PlaidLink/nativeModule/index.ios.ts b/src/components/PlaidLink/nativeModule/index.ios.ts deleted file mode 100644 index 78d4315eac2d..000000000000 --- a/src/components/PlaidLink/nativeModule/index.ios.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {NativeModules} from 'react-native'; - -export default NativeModules.RNLinksdk; From a966eb3392d765491070ea070c02e69f67608510 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 27 Nov 2023 13:41:14 +0100 Subject: [PATCH 09/34] pass event to Log.info --- src/components/PlaidLink/index.native.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PlaidLink/index.native.tsx b/src/components/PlaidLink/index.native.tsx index b9accb0c0ad7..02d4669bc861 100644 --- a/src/components/PlaidLink/index.native.tsx +++ b/src/components/PlaidLink/index.native.tsx @@ -7,7 +7,7 @@ import PlaidLinkProps from './types'; function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: PlaidLinkProps) { useDeepLinkRedirector(); usePlaidEmitter((event: LinkEvent) => { - Log.info('[PlaidLink] Handled Plaid Event: ', false, event.eventName); + Log.info('[PlaidLink] Handled Plaid Event: ', false, {...event}); onEvent(event.eventName, event.metadata); }); useEffect(() => { From d7553080efebcda8e4f2fc02631a1c12ca58bf95 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 27 Nov 2023 13:45:11 +0100 Subject: [PATCH 10/34] allow metadata to be undefined in onEvent --- src/components/AddPlaidBankAccount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index ec4ddd623929..0b23704b5b26 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -209,7 +209,7 @@ function AddPlaidBankAccount({ // Handle Plaid login errors (will potentially reset plaid token and item depending on the error) if (event === 'ERROR') { Log.hmmm('[PlaidLink] Error: ', metadata); - if (bankAccountID && metadata.error_code) { + if (bankAccountID && metadata && metadata.error_code) { BankAccounts.handlePlaidError(bankAccountID, metadata.error_code, metadata.error_message, metadata.request_id); } } From 624875cc26a1d0365e01f4eccffb52219cfa16ed Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 27 Nov 2023 13:49:00 +0100 Subject: [PATCH 11/34] make publicToken required param --- src/components/PlaidLink/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PlaidLink/types.ts b/src/components/PlaidLink/types.ts index fe23e09151ca..dda6d9d869cb 100644 --- a/src/components/PlaidLink/types.ts +++ b/src/components/PlaidLink/types.ts @@ -6,7 +6,7 @@ type PlaidLinkProps = { token: string; // Callback to execute once the user taps continue after successfully entering their account information - onSuccess?: (args: {publicToken?: string; metadata: PlaidLinkOnSuccessMetadata | LinkSuccessMetadata}) => void; + onSuccess?: (args: {publicToken: string; metadata: PlaidLinkOnSuccessMetadata | LinkSuccessMetadata}) => void; // Callback to execute when there is an error event emitted by the Plaid SDK onError?: (error: ErrorEvent | null) => void; From a8af74a8761d5e060858b702a92457ec7fec0ee1 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 27 Nov 2023 14:11:36 +0100 Subject: [PATCH 12/34] change eventName type to string --- src/components/PlaidLink/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/PlaidLink/types.ts b/src/components/PlaidLink/types.ts index dda6d9d869cb..1034eb935f74 100644 --- a/src/components/PlaidLink/types.ts +++ b/src/components/PlaidLink/types.ts @@ -1,5 +1,5 @@ import {LinkEventMetadata, LinkSuccessMetadata} from 'react-native-plaid-link-sdk'; -import {PlaidLinkOnEventMetadata, PlaidLinkOnSuccessMetadata, PlaidLinkStableEvent} from 'react-plaid-link'; +import {PlaidLinkOnEventMetadata, PlaidLinkOnSuccessMetadata} from 'react-plaid-link'; type PlaidLinkProps = { // Plaid Link SDK public token used to initialize the Plaid SDK @@ -15,7 +15,7 @@ type PlaidLinkProps = { onExit?: () => void; // Callback to execute whenever a Plaid event occurs - onEvent: (eventName: PlaidLinkStableEvent | string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; + onEvent: (eventName: string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the // user to their respective bank platform From 019cd14886dfa8921a133f5d0c86436dc5c1ecec Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Mon, 27 Nov 2023 17:41:41 +0530 Subject: [PATCH 13/34] Correct return types --- src/pages/settings/InitialSettingsPage.js | 4 ++-- src/pages/workspace/WorkspacesListPage.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index 1bd57bcab32b..d6decff5a208 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -281,9 +281,9 @@ function InitialSettingsPage(props) { const getMenuItems = useMemo(() => { /** * @param {Boolean} isPaymentItem whether the item being rendered is the payments menu item - * @returns {Number} the user wallet balance + * @returns {String|undefined} the user's wallet balance */ - const getWalletBalance = (isPaymentItem) => isPaymentItem && CurrencyUtils.convertToDisplayString(props.userWallet.currentBalance); + const getWalletBalance = (isPaymentItem) => isPaymentItem ? CurrencyUtils.convertToDisplayString(props.userWallet.currentBalance) : undefined; return ( <> diff --git a/src/pages/workspace/WorkspacesListPage.js b/src/pages/workspace/WorkspacesListPage.js index 1e51c64a711c..2749ccb52b96 100755 --- a/src/pages/workspace/WorkspacesListPage.js +++ b/src/pages/workspace/WorkspacesListPage.js @@ -114,7 +114,7 @@ function WorkspacesListPage({policies, allPolicyMembers, reimbursementAccount, u /** * @param {Boolean} isPaymentItem whether the item being rendered is the payments menu item - * @returns {Number} the user wallet balance + * @returns {String|undefined} the user's wallet balance */ function getWalletBalance(isPaymentItem) { return isPaymentItem ? CurrencyUtils.convertToDisplayString(userWallet.currentBalance) : undefined; From b2f9eab37124a4f5cc6d23a50942218eed0eb2ca Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Mon, 27 Nov 2023 20:36:20 +0530 Subject: [PATCH 14/34] Fix lint --- src/pages/settings/InitialSettingsPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index d6decff5a208..61950e14337f 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -283,7 +283,7 @@ function InitialSettingsPage(props) { * @param {Boolean} isPaymentItem whether the item being rendered is the payments menu item * @returns {String|undefined} the user's wallet balance */ - const getWalletBalance = (isPaymentItem) => isPaymentItem ? CurrencyUtils.convertToDisplayString(props.userWallet.currentBalance) : undefined; + const getWalletBalance = (isPaymentItem) => (isPaymentItem ? CurrencyUtils.convertToDisplayString(props.userWallet.currentBalance) : undefined); return ( <> From 54b2c9b34666ac6263e0524f04a2a49c94b7e3fa Mon Sep 17 00:00:00 2001 From: Yauheni Pasiukevich Date: Wed, 22 Nov 2023 13:35:11 +0100 Subject: [PATCH 15/34] fix type for activate card flow --- src/libs/actions/Card.js | 2 +- src/pages/settings/Wallet/ActivatePhysicalCardPage.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Card.js b/src/libs/actions/Card.js index 9adcd3803766..68642bd8fdf1 100644 --- a/src/libs/actions/Card.js +++ b/src/libs/actions/Card.js @@ -93,7 +93,7 @@ function requestReplacementExpensifyCard(cardId, reason) { /** * Activates the physical Expensify card based on the last four digits of the card number * - * @param {Number} cardLastFourDigits + * @param {String} cardLastFourDigits * @param {Number} cardID */ function activatePhysicalExpensifyCard(cardLastFourDigits, cardID) { diff --git a/src/pages/settings/Wallet/ActivatePhysicalCardPage.js b/src/pages/settings/Wallet/ActivatePhysicalCardPage.js index e20721b5db4a..3534ef5c064c 100644 --- a/src/pages/settings/Wallet/ActivatePhysicalCardPage.js +++ b/src/pages/settings/Wallet/ActivatePhysicalCardPage.js @@ -123,7 +123,7 @@ function ActivatePhysicalCardPage({ return; } - CardSettings.activatePhysicalExpensifyCard(Number(lastFourDigits), cardID); + CardSettings.activatePhysicalExpensifyCard(lastFourDigits, cardID); }, [lastFourDigits, cardID, translate]); if (_.isEmpty(physicalCard)) { From c5584ecc1d6ab8d015847eeb29d8254204822535 Mon Sep 17 00:00:00 2001 From: Artem Makushov Date: Tue, 28 Nov 2023 13:46:48 +0100 Subject: [PATCH 16/34] removed an extra space --- src/languages/en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index d661ee1ad97b..7bc9c985ad66 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1952,7 +1952,7 @@ export default { buttonText1: 'Request money, ', buttonText2: `get $${CONST.REFERRAL_PROGRAM.REVENUE}.`, header: `Request money, get $${CONST.REFERRAL_PROGRAM.REVENUE}`, - body1: `Request money from a new Expensify account. Get $${CONST.REFERRAL_PROGRAM.REVENUE} once they start an annual subscription with two or more active members and make the first two payments toward their Expensify bill.`, + body1: `Request money from a new Expensify account. Get $${CONST.REFERRAL_PROGRAM.REVENUE} once they start an annual subscription with two or more active members and make the first two payments toward their Expensify bill.`, }, [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY]: { buttonText1: 'Send money, ', From dcc202ad7739d03e834d500c357aa553bc91e447 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 28 Nov 2023 18:11:48 +0100 Subject: [PATCH 17/34] update patches --- ...eact-native+0.72.4+002+NumberOfLines.patch | 632 ++++++++++++++++++ ...ive+0.72.4+004+ModalKeyboardFlashing.patch | 18 + 2 files changed, 650 insertions(+) create mode 100644 patches/react-native+0.72.4+002+NumberOfLines.patch create mode 100644 patches/react-native+0.72.4+004+ModalKeyboardFlashing.patch diff --git a/patches/react-native+0.72.4+002+NumberOfLines.patch b/patches/react-native+0.72.4+002+NumberOfLines.patch new file mode 100644 index 000000000000..16fec4bc8363 --- /dev/null +++ b/patches/react-native+0.72.4+002+NumberOfLines.patch @@ -0,0 +1,632 @@ +diff --git a/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js b/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js +index 6f69329..d531bee 100644 +--- a/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js ++++ b/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js +@@ -144,6 +144,8 @@ const RCTTextInputViewConfig = { + placeholder: true, + autoCorrect: true, + multiline: true, ++ numberOfLines: true, ++ maximumNumberOfLines: true, + textContentType: true, + maxLength: true, + autoCapitalize: true, +diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts b/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts +index 8badb2a..b19f197 100644 +--- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts ++++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts +@@ -347,12 +347,6 @@ export interface TextInputAndroidProps { + */ + inlineImagePadding?: number | undefined; + +- /** +- * Sets the number of lines for a TextInput. +- * Use it with multiline set to true to be able to fill the lines. +- */ +- numberOfLines?: number | undefined; +- + /** + * Sets the return key to the label. Use it instead of `returnKeyType`. + * @platform android +@@ -663,11 +657,30 @@ export interface TextInputProps + */ + maxLength?: number | undefined; + ++ /** ++ * Sets the maximum number of lines for a TextInput. ++ * Use it with multiline set to true to be able to fill the lines. ++ */ ++ maxNumberOfLines?: number | undefined; ++ + /** + * If true, the text input can be multiple lines. The default value is false. + */ + multiline?: boolean | undefined; + ++ /** ++ * Sets the number of lines for a TextInput. ++ * Use it with multiline set to true to be able to fill the lines. ++ */ ++ numberOfLines?: number | undefined; ++ ++ /** ++ * Sets the number of rows for a TextInput. ++ * Use it with multiline set to true to be able to fill the lines. ++ */ ++ rows?: number | undefined; ++ ++ + /** + * Callback that is called when the text input is blurred + */ +diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js b/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js +index 7ed4579..b1d994e 100644 +--- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js ++++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js +@@ -343,26 +343,12 @@ type AndroidProps = $ReadOnly<{| + */ + inlineImagePadding?: ?number, + +- /** +- * Sets the number of lines for a `TextInput`. Use it with multiline set to +- * `true` to be able to fill the lines. +- * @platform android +- */ +- numberOfLines?: ?number, +- + /** + * Sets the return key to the label. Use it instead of `returnKeyType`. + * @platform android + */ + returnKeyLabel?: ?string, + +- /** +- * Sets the number of rows for a `TextInput`. Use it with multiline set to +- * `true` to be able to fill the lines. +- * @platform android +- */ +- rows?: ?number, +- + /** + * When `false`, it will prevent the soft keyboard from showing when the field is focused. + * Defaults to `true`. +@@ -632,6 +618,12 @@ export type Props = $ReadOnly<{| + */ + keyboardType?: ?KeyboardType, + ++ /** ++ * Sets the maximum number of lines for a `TextInput`. Use it with multiline set to ++ * `true` to be able to fill the lines. ++ */ ++ maxNumberOfLines?: ?number, ++ + /** + * Specifies largest possible scale a font can reach when `allowFontScaling` is enabled. + * Possible values: +@@ -653,6 +645,12 @@ export type Props = $ReadOnly<{| + */ + multiline?: ?boolean, + ++ /** ++ * Sets the number of lines for a `TextInput`. Use it with multiline set to ++ * `true` to be able to fill the lines. ++ */ ++ numberOfLines?: ?number, ++ + /** + * Callback that is called when the text input is blurred. + */ +@@ -814,6 +812,12 @@ export type Props = $ReadOnly<{| + */ + returnKeyType?: ?ReturnKeyType, + ++ /** ++ * Sets the number of rows for a `TextInput`. Use it with multiline set to ++ * `true` to be able to fill the lines. ++ */ ++ rows?: ?number, ++ + /** + * If `true`, the text input obscures the text entered so that sensitive text + * like passwords stay secure. The default value is `false`. Does not work with 'multiline={true}'. +diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.js b/node_modules/react-native/Libraries/Components/TextInput/TextInput.js +index 2127191..542fc06 100644 +--- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.js ++++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.js +@@ -390,7 +390,6 @@ type AndroidProps = $ReadOnly<{| + /** + * Sets the number of lines for a `TextInput`. Use it with multiline set to + * `true` to be able to fill the lines. +- * @platform android + */ + numberOfLines?: ?number, + +@@ -403,10 +402,14 @@ type AndroidProps = $ReadOnly<{| + /** + * Sets the number of rows for a `TextInput`. Use it with multiline set to + * `true` to be able to fill the lines. +- * @platform android + */ + rows?: ?number, + ++ /** ++ * Sets the maximum number of lines the TextInput can have. ++ */ ++ maxNumberOfLines?: ?number, ++ + /** + * When `false`, it will prevent the soft keyboard from showing when the field is focused. + * Defaults to `true`. +@@ -1069,6 +1072,9 @@ function InternalTextInput(props: Props): React.Node { + accessibilityState, + id, + tabIndex, ++ rows, ++ numberOfLines, ++ maxNumberOfLines, + selection: propsSelection, + ...otherProps + } = props; +@@ -1427,6 +1433,8 @@ function InternalTextInput(props: Props): React.Node { + focusable={tabIndex !== undefined ? !tabIndex : focusable} + mostRecentEventCount={mostRecentEventCount} + nativeID={id ?? props.nativeID} ++ numberOfLines={props.rows ?? props.numberOfLines} ++ maximumNumberOfLines={maxNumberOfLines} + onBlur={_onBlur} + onKeyPressSync={props.unstable_onKeyPressSync} + onChange={_onChange} +@@ -1482,6 +1490,7 @@ function InternalTextInput(props: Props): React.Node { + mostRecentEventCount={mostRecentEventCount} + nativeID={id ?? props.nativeID} + numberOfLines={props.rows ?? props.numberOfLines} ++ maximumNumberOfLines={maxNumberOfLines} + onBlur={_onBlur} + onChange={_onChange} + onFocus={_onFocus} +diff --git a/node_modules/react-native/Libraries/Text/Text.js b/node_modules/react-native/Libraries/Text/Text.js +index df548af..e02f5da 100644 +--- a/node_modules/react-native/Libraries/Text/Text.js ++++ b/node_modules/react-native/Libraries/Text/Text.js +@@ -18,7 +18,11 @@ import processColor from '../StyleSheet/processColor'; + import {getAccessibilityRoleFromRole} from '../Utilities/AcessibilityMapping'; + import Platform from '../Utilities/Platform'; + import TextAncestor from './TextAncestor'; +-import {NativeText, NativeVirtualText} from './TextNativeComponent'; ++import { ++ CONTAINS_MAX_NUMBER_OF_LINES_RENAME, ++ NativeText, ++ NativeVirtualText, ++} from './TextNativeComponent'; + import * as React from 'react'; + import {useContext, useMemo, useState} from 'react'; + +@@ -59,6 +63,7 @@ const Text: React.AbstractComponent< + pressRetentionOffset, + role, + suppressHighlighting, ++ numberOfLines, + ...restProps + } = props; + +@@ -192,14 +197,33 @@ const Text: React.AbstractComponent< + } + } + +- let numberOfLines = restProps.numberOfLines; ++ let numberOfLinesValue = numberOfLines; + if (numberOfLines != null && !(numberOfLines >= 0)) { + console.error( + `'numberOfLines' in must be a non-negative number, received: ${numberOfLines}. The value will be set to 0.`, + ); +- numberOfLines = 0; ++ numberOfLinesValue = 0; + } + ++ const numberOfLinesProps = useMemo((): { ++ maximumNumberOfLines?: ?number, ++ numberOfLines?: ?number, ++ } => { ++ // FIXME: Current logic is breaking all Text components. ++ // if (CONTAINS_MAX_NUMBER_OF_LINES_RENAME) { ++ // return { ++ // maximumNumberOfLines: numberOfLinesValue, ++ // }; ++ // } else { ++ // return { ++ // numberOfLines: numberOfLinesValue, ++ // }; ++ // } ++ return { ++ maximumNumberOfLines: numberOfLinesValue, ++ }; ++ }, [numberOfLinesValue]); ++ + const hasTextAncestor = useContext(TextAncestor); + + const _accessible = Platform.select({ +@@ -241,7 +265,6 @@ const Text: React.AbstractComponent< + isHighlighted={isHighlighted} + isPressable={isPressable} + nativeID={id ?? nativeID} +- numberOfLines={numberOfLines} + ref={forwardedRef} + selectable={_selectable} + selectionColor={selectionColor} +@@ -252,6 +275,7 @@ const Text: React.AbstractComponent< + + #import ++#import ++#import + + @implementation RCTMultilineTextInputViewManager + +@@ -17,8 +19,21 @@ - (UIView *)view + return [[RCTMultilineTextInputView alloc] initWithBridge:self.bridge]; + } + ++- (RCTShadowView *)shadowView ++{ ++ RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[super shadowView]; ++ ++ shadowView.maximumNumberOfLines = 0; ++ shadowView.exactNumberOfLines = 0; ++ ++ return shadowView; ++} ++ + #pragma mark - Multiline (aka TextView) specific properties + + RCT_REMAP_VIEW_PROPERTY(dataDetectorTypes, backedTextInputView.dataDetectorTypes, UIDataDetectorTypes) + ++RCT_EXPORT_SHADOW_PROPERTY(maximumNumberOfLines, NSInteger) ++RCT_REMAP_SHADOW_PROPERTY(numberOfLines, exactNumberOfLines, NSInteger) ++ + @end +diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h +index 8f4cf7e..6238ebc 100644 +--- a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h ++++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h +@@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN + @property (nonatomic, copy, nullable) NSString *text; + @property (nonatomic, copy, nullable) NSString *placeholder; + @property (nonatomic, assign) NSInteger maximumNumberOfLines; ++@property (nonatomic, assign) NSInteger exactNumberOfLines; + @property (nonatomic, copy, nullable) RCTDirectEventBlock onContentSizeChange; + + - (void)uiManagerWillPerformMounting; +diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m +index 04d2446..9d77743 100644 +--- a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m ++++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m +@@ -218,7 +218,22 @@ - (NSAttributedString *)measurableAttributedText + + - (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize + { +- NSAttributedString *attributedText = [self measurableAttributedText]; ++ NSMutableAttributedString *attributedText = [[self measurableAttributedText] mutableCopy]; ++ ++ /* ++ * The block below is responsible for setting the exact height of the view in lines ++ * Unfortunatelly, iOS doesn't export any easy way to do it. So we set maximumNumberOfLines ++ * prop and then add random lines at the front. However, they are only used for layout ++ * so they are not visible on the screen. ++ */ ++ if (self.exactNumberOfLines) { ++ NSMutableString *newLines = [NSMutableString stringWithCapacity:self.exactNumberOfLines]; ++ for (NSUInteger i = 0UL; i < self.exactNumberOfLines; ++i) { ++ [newLines appendString:@"\n"]; ++ } ++ [attributedText insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:self.textAttributes.effectiveTextAttributes] atIndex:0]; ++ _maximumNumberOfLines = self.exactNumberOfLines; ++ } + + if (!_textStorage) { + _textContainer = [NSTextContainer new]; +diff --git a/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m b/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m +index 413ac42..56d039c 100644 +--- a/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m ++++ b/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m +@@ -19,6 +19,7 @@ - (RCTShadowView *)shadowView + RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[super shadowView]; + + shadowView.maximumNumberOfLines = 1; ++ shadowView.exactNumberOfLines = 0; + + return shadowView; + } +diff --git a/node_modules/react-native/Libraries/Text/TextNativeComponent.js b/node_modules/react-native/Libraries/Text/TextNativeComponent.js +index 0d59904..3216e43 100644 +--- a/node_modules/react-native/Libraries/Text/TextNativeComponent.js ++++ b/node_modules/react-native/Libraries/Text/TextNativeComponent.js +@@ -9,6 +9,7 @@ + */ + + import {createViewConfig} from '../NativeComponent/ViewConfig'; ++import getNativeComponentAttributes from '../ReactNative/getNativeComponentAttributes'; + import UIManager from '../ReactNative/UIManager'; + import createReactNativeComponentClass from '../Renderer/shims/createReactNativeComponentClass'; + import {type HostComponent} from '../Renderer/shims/ReactNativeTypes'; +@@ -18,6 +19,7 @@ import {type TextProps} from './TextProps'; + + type NativeTextProps = $ReadOnly<{ + ...TextProps, ++ maximumNumberOfLines?: ?number, + isHighlighted?: ?boolean, + selectionColor?: ?ProcessedColorValue, + onClick?: ?(event: PressEvent) => mixed, +@@ -31,7 +33,7 @@ const textViewConfig = { + validAttributes: { + isHighlighted: true, + isPressable: true, +- numberOfLines: true, ++ maximumNumberOfLines: true, + ellipsizeMode: true, + allowFontScaling: true, + dynamicTypeRamp: true, +@@ -73,6 +75,12 @@ export const NativeText: HostComponent = + createViewConfig(textViewConfig), + ): any); + ++const jestIsDefined = typeof jest !== 'undefined'; ++export const CONTAINS_MAX_NUMBER_OF_LINES_RENAME: boolean = jestIsDefined ++ ? true ++ : getNativeComponentAttributes('RCTText')?.NativeProps ++ ?.maximumNumberOfLines === 'number'; ++ + export const NativeVirtualText: HostComponent = + !global.RN$Bridgeless && !UIManager.hasViewManagerConfig('RCTVirtualText') + ? NativeText +diff --git a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp +index 2994aca..fff0d5e 100644 +--- a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp ++++ b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp +@@ -16,6 +16,7 @@ namespace facebook::react { + + bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { + return std::tie( ++ numberOfLines, + maximumNumberOfLines, + ellipsizeMode, + textBreakStrategy, +@@ -23,6 +24,7 @@ bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { + includeFontPadding, + android_hyphenationFrequency) == + std::tie( ++ rhs.numberOfLines, + rhs.maximumNumberOfLines, + rhs.ellipsizeMode, + rhs.textBreakStrategy, +@@ -42,6 +44,7 @@ bool ParagraphAttributes::operator!=(const ParagraphAttributes &rhs) const { + #if RN_DEBUG_STRING_CONVERTIBLE + SharedDebugStringConvertibleList ParagraphAttributes::getDebugProps() const { + return { ++ debugStringConvertibleItem("numberOfLines", numberOfLines), + debugStringConvertibleItem("maximumNumberOfLines", maximumNumberOfLines), + debugStringConvertibleItem("ellipsizeMode", ellipsizeMode), + debugStringConvertibleItem("textBreakStrategy", textBreakStrategy), +diff --git a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h +index f5f87c6..b7d1e90 100644 +--- a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h ++++ b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h +@@ -30,6 +30,11 @@ class ParagraphAttributes : public DebugStringConvertible { + public: + #pragma mark - Fields + ++ /* ++ * Number of lines which paragraph takes. ++ */ ++ int numberOfLines{}; ++ + /* + * Maximum number of lines which paragraph can take. + * Zero value represents "no limit". +@@ -92,6 +97,7 @@ struct hash { + const facebook::react::ParagraphAttributes &attributes) const { + return folly::hash::hash_combine( + 0, ++ attributes.numberOfLines, + attributes.maximumNumberOfLines, + attributes.ellipsizeMode, + attributes.textBreakStrategy, +diff --git a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h +index 8687b89..eab75f4 100644 +--- a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h ++++ b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h +@@ -835,10 +835,16 @@ inline ParagraphAttributes convertRawProp( + ParagraphAttributes const &defaultParagraphAttributes) { + auto paragraphAttributes = ParagraphAttributes{}; + +- paragraphAttributes.maximumNumberOfLines = convertRawProp( ++ paragraphAttributes.numberOfLines = convertRawProp( + context, + rawProps, + "numberOfLines", ++ sourceParagraphAttributes.numberOfLines, ++ defaultParagraphAttributes.numberOfLines); ++ paragraphAttributes.maximumNumberOfLines = convertRawProp( ++ context, ++ rawProps, ++ "maximumNumberOfLines", + sourceParagraphAttributes.maximumNumberOfLines, + defaultParagraphAttributes.maximumNumberOfLines); + paragraphAttributes.ellipsizeMode = convertRawProp( +@@ -913,6 +919,7 @@ inline std::string toString(AttributedString::Range const &range) { + inline folly::dynamic toDynamic( + const ParagraphAttributes ¶graphAttributes) { + auto values = folly::dynamic::object(); ++ values("numberOfLines", paragraphAttributes.numberOfLines); + values("maximumNumberOfLines", paragraphAttributes.maximumNumberOfLines); + values("ellipsizeMode", toString(paragraphAttributes.ellipsizeMode)); + values("textBreakStrategy", toString(paragraphAttributes.textBreakStrategy)); +@@ -1118,6 +1125,7 @@ constexpr static MapBuffer::Key PA_KEY_TEXT_BREAK_STRATEGY = 2; + constexpr static MapBuffer::Key PA_KEY_ADJUST_FONT_SIZE_TO_FIT = 3; + constexpr static MapBuffer::Key PA_KEY_INCLUDE_FONT_PADDING = 4; + constexpr static MapBuffer::Key PA_KEY_HYPHENATION_FREQUENCY = 5; ++constexpr static MapBuffer::Key PA_KEY_NUMBER_OF_LINES = 6; + + inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { + auto builder = MapBufferBuilder(); +@@ -1135,6 +1143,8 @@ inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { + builder.putString( + PA_KEY_HYPHENATION_FREQUENCY, + toString(paragraphAttributes.android_hyphenationFrequency)); ++ builder.putInt( ++ PA_KEY_NUMBER_OF_LINES, paragraphAttributes.numberOfLines); + + return builder.build(); + } +diff --git a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp +index 9953e22..98eb3da 100644 +--- a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp ++++ b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp +@@ -56,6 +56,10 @@ AndroidTextInputProps::AndroidTextInputProps( + "numberOfLines", + sourceProps.numberOfLines, + {0})), ++ maximumNumberOfLines(CoreFeatures::enablePropIteratorSetter? sourceProps.maximumNumberOfLines : convertRawProp(context, rawProps, ++ "maximumNumberOfLines", ++ sourceProps.maximumNumberOfLines, ++ {0})), + disableFullscreenUI(CoreFeatures::enablePropIteratorSetter? sourceProps.disableFullscreenUI : convertRawProp(context, rawProps, + "disableFullscreenUI", + sourceProps.disableFullscreenUI, +@@ -281,6 +285,12 @@ void AndroidTextInputProps::setProp( + value, + paragraphAttributes, + maximumNumberOfLines, ++ "maximumNumberOfLines"); ++ REBUILD_FIELD_SWITCH_CASE( ++ paDefaults, ++ value, ++ paragraphAttributes, ++ numberOfLines, + "numberOfLines"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, value, paragraphAttributes, ellipsizeMode, "ellipsizeMode"); +@@ -323,6 +333,7 @@ void AndroidTextInputProps::setProp( + } + + switch (hash) { ++ RAW_SET_PROP_SWITCH_CASE_BASIC(maximumNumberOfLines); + RAW_SET_PROP_SWITCH_CASE_BASIC(autoComplete); + RAW_SET_PROP_SWITCH_CASE_BASIC(returnKeyLabel); + RAW_SET_PROP_SWITCH_CASE_BASIC(numberOfLines); +@@ -422,6 +433,7 @@ void AndroidTextInputProps::setProp( + // TODO T53300085: support this in codegen; this was hand-written + folly::dynamic AndroidTextInputProps::getDynamic() const { + folly::dynamic props = folly::dynamic::object(); ++ props["maximumNumberOfLines"] = maximumNumberOfLines; + props["autoComplete"] = autoComplete; + props["returnKeyLabel"] = returnKeyLabel; + props["numberOfLines"] = numberOfLines; +diff --git a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h +index ba39ebb..ead28e3 100644 +--- a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h ++++ b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h +@@ -84,6 +84,7 @@ class AndroidTextInputProps final : public ViewProps, public BaseTextProps { + std::string autoComplete{}; + std::string returnKeyLabel{}; + int numberOfLines{0}; ++ int maximumNumberOfLines{0}; + bool disableFullscreenUI{false}; + std::string textBreakStrategy{}; + SharedColor underlineColorAndroid{}; +diff --git a/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm b/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +index 368c334..a1bb33e 100644 +--- a/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm ++++ b/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +@@ -244,26 +244,51 @@ - (void)getRectWithAttributedString:(AttributedString)attributedString + + #pragma mark - Private + +-- (NSTextStorage *)_textStorageForNSAttributesString:(NSAttributedString *)attributedString +++- (NSTextStorage *)_textStorageForNSAttributesString:(NSAttributedString *)inputAttributedString + paragraphAttributes:(ParagraphAttributes)paragraphAttributes + size:(CGSize)size + { +- NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:size]; ++ NSMutableAttributedString *attributedString = [ inputAttributedString mutableCopy]; ++ ++ /* ++ * The block below is responsible for setting the exact height of the view in lines ++ * Unfortunatelly, iOS doesn't export any easy way to do it. So we set maximumNumberOfLines ++ * prop and then add random lines at the front. However, they are only used for layout ++ * so they are not visible on the screen. This method is used for drawing only for Paragraph component ++ * but we set exact height in lines only on TextInput that doesn't use it. ++ */ ++ if (paragraphAttributes.numberOfLines) { ++ paragraphAttributes.maximumNumberOfLines = paragraphAttributes.numberOfLines; ++ NSMutableString *newLines = [NSMutableString stringWithCapacity: paragraphAttributes.numberOfLines]; ++ for (NSUInteger i = 0UL; i < paragraphAttributes.numberOfLines; ++i) { ++ // K is added on purpose. New line seems to be not enough for NTtextContainer ++ [newLines appendString:@"K\n"]; ++ } ++ NSDictionary * attributesOfFirstCharacter = [inputAttributedString attributesAtIndex:0 effectiveRange:NULL]; + +- textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5. +- textContainer.lineBreakMode = paragraphAttributes.maximumNumberOfLines > 0 +- ? RCTNSLineBreakModeFromEllipsizeMode(paragraphAttributes.ellipsizeMode) +- : NSLineBreakByClipping; +- textContainer.maximumNumberOfLines = paragraphAttributes.maximumNumberOfLines; ++ [attributedString insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:attributesOfFirstCharacter] atIndex:0]; ++ } ++ ++ NSTextContainer *textContainer = [NSTextContainer new]; + + NSLayoutManager *layoutManager = [NSLayoutManager new]; + layoutManager.usesFontLeading = NO; + [layoutManager addTextContainer:textContainer]; + +- NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString]; ++ NSTextStorage *textStorage = [NSTextStorage new]; + + [textStorage addLayoutManager:layoutManager]; + ++ textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5. ++ textContainer.lineBreakMode = paragraphAttributes.maximumNumberOfLines > 0 ++ ? RCTNSLineBreakModeFromEllipsizeMode(paragraphAttributes.ellipsizeMode) ++ : NSLineBreakByClipping; ++ textContainer.size = size; ++ textContainer.maximumNumberOfLines = paragraphAttributes.maximumNumberOfLines; ++ ++ [textStorage replaceCharactersInRange:(NSRange){0, textStorage.length} withAttributedString:attributedString]; ++ ++ + if (paragraphAttributes.adjustsFontSizeToFit) { + CGFloat minimumFontSize = !isnan(paragraphAttributes.minimumFontSize) ? paragraphAttributes.minimumFontSize : 4.0; + CGFloat maximumFontSize = !isnan(paragraphAttributes.maximumFontSize) ? paragraphAttributes.maximumFontSize : 96.0; diff --git a/patches/react-native+0.72.4+004+ModalKeyboardFlashing.patch b/patches/react-native+0.72.4+004+ModalKeyboardFlashing.patch new file mode 100644 index 000000000000..84a233894f94 --- /dev/null +++ b/patches/react-native+0.72.4+004+ModalKeyboardFlashing.patch @@ -0,0 +1,18 @@ +diff --git a/node_modules/react-native/React/Views/RCTModalHostViewManager.m b/node_modules/react-native/React/Views/RCTModalHostViewManager.m +index 4b9f9ad..b72984c 100644 +--- a/node_modules/react-native/React/Views/RCTModalHostViewManager.m ++++ b/node_modules/react-native/React/Views/RCTModalHostViewManager.m +@@ -79,6 +79,13 @@ RCT_EXPORT_MODULE() + if (self->_presentationBlock) { + self->_presentationBlock([modalHostView reactViewController], viewController, animated, completionBlock); + } else { ++ // In our App, If an input is blurred and a modal is opened, the rootView will become the firstResponder, which ++ // will cause system to retain a wrong keyboard state, and then the keyboard to flicker when the modal is closed. ++ // We first resign the rootView to avoid this problem. ++ UIWindow *window = RCTKeyWindow(); ++ if (window && window.rootViewController && [window.rootViewController.view isFirstResponder]) { ++ [window.rootViewController.view resignFirstResponder]; ++ } + [[modalHostView reactViewController] presentViewController:viewController + animated:animated + completion:completionBlock]; From 09e2c45787ab5a84abf87fb859b73a66845fafd5 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 28 Nov 2023 18:15:33 +0100 Subject: [PATCH 18/34] fix ios --- .../{index.native.js => index.android.js} | 3 +- src/components/Composer/index.ios.js | 140 ++++++++++++++++++ .../updateNumberOfLines/index.native.ts | 3 + .../updateNumberOfLines/types.ts | 2 +- 4 files changed, 146 insertions(+), 2 deletions(-) rename src/components/Composer/{index.native.js => index.android.js} (98%) create mode 100644 src/components/Composer/index.ios.js diff --git a/src/components/Composer/index.native.js b/src/components/Composer/index.android.js similarity index 98% rename from src/components/Composer/index.native.js rename to src/components/Composer/index.android.js index 5bec0f701ec5..3a8011b33f6a 100644 --- a/src/components/Composer/index.native.js +++ b/src/components/Composer/index.android.js @@ -98,12 +98,13 @@ function Composer({shouldClear, onClear, isDisabled, maxLines, forwardedRef, isC ComposerUtils.updateNumberOfLines({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e)} rejectResponderTermination={false} - smartInsertDelete={false} + smartInsertDelete textAlignVertical="center" style={[...props.style, maxHeightStyle]} readOnly={isDisabled} diff --git a/src/components/Composer/index.ios.js b/src/components/Composer/index.ios.js new file mode 100644 index 000000000000..8204d38c3406 --- /dev/null +++ b/src/components/Composer/index.ios.js @@ -0,0 +1,140 @@ +import PropTypes from 'prop-types'; +import React, {useCallback, useEffect, useMemo, useRef} from 'react'; +import _ from 'underscore'; +import RNTextInput from '@components/RNTextInput'; +import * as ComposerUtils from '@libs/ComposerUtils'; +import styles from '@styles/styles'; +import themeColors from '@styles/themes/default'; + +const propTypes = { + /** If the input should clear, it actually gets intercepted instead of .clear() */ + shouldClear: PropTypes.bool, + + /** A ref to forward to the text input */ + forwardedRef: PropTypes.func, + + /** When the input has cleared whoever owns this input should know about it */ + onClear: PropTypes.func, + + /** Set focus to this component the first time it renders. + * Override this in case you need to set focus on one field out of many, or when you want to disable autoFocus */ + autoFocus: PropTypes.bool, + + /** Prevent edits and interactions like focus for this input. */ + isDisabled: PropTypes.bool, + + /** Selection Object */ + selection: PropTypes.shape({ + start: PropTypes.number, + end: PropTypes.number, + }), + + /** Whether the full composer can be opened */ + isFullComposerAvailable: PropTypes.bool, + + /** Maximum number of lines in the text input */ + maxLines: PropTypes.number, + + /** Allow the full composer to be opened */ + setIsFullComposerAvailable: PropTypes.func, + + /** Whether the composer is full size */ + isComposerFullSize: PropTypes.bool, + + /** General styles to apply to the text input */ + // eslint-disable-next-line react/forbid-prop-types + style: PropTypes.any, +}; + +const defaultProps = { + shouldClear: false, + onClear: () => {}, + autoFocus: false, + isDisabled: false, + forwardedRef: null, + selection: { + start: 0, + end: 0, + }, + maxLines: undefined, + isFullComposerAvailable: false, + setIsFullComposerAvailable: () => {}, + isComposerFullSize: false, + style: null, +}; + +function Composer({shouldClear, onClear, isDisabled, maxLines, forwardedRef, isComposerFullSize, setIsFullComposerAvailable, ...props}) { + const textInput = useRef(null); + + /** + * Set the TextInput Ref + * @param {Element} el + */ + const setTextInputRef = useCallback((el) => { + textInput.current = el; + if (!_.isFunction(forwardedRef) || textInput.current === null) { + return; + } + + // This callback prop is used by the parent component using the constructor to + // get a ref to the inner textInput element e.g. if we do + // this.textInput = el} /> this will not + // return a ref to the component, but rather the HTML element by default + forwardedRef(textInput.current); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + if (!shouldClear) { + return; + } + textInput.current.clear(); + onClear(); + }, [shouldClear, onClear]); + + /** + * Set maximum number of lines + * @return {Number} + */ + const maxNumberOfLines = useMemo(() => { + if (isComposerFullSize) { + return; + } + return maxLines; + }, [isComposerFullSize, maxLines]); + + // On native layers we like to have the Text Input not focused so the + // user can read new chats without the keyboard in the way of the view. + // On Android the selection prop is required on the TextInput but this prop has issues on IOS + const propsToPass = _.omit(props, 'selection'); + return ( + ComposerUtils.updateNumberOfLines({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e)} + rejectResponderTermination={false} + smartInsertDelete={false} + maxNumberOfLines={maxNumberOfLines} + style={[...props.style, styles.verticalAlignMiddle]} + /* eslint-disable-next-line react/jsx-props-no-spreading */ + {...propsToPass} + readOnly={isDisabled} + /> + ); +} + +Composer.propTypes = propTypes; +Composer.defaultProps = defaultProps; + +const ComposerWithRef = React.forwardRef((props, ref) => ( + +)); + +ComposerWithRef.displayName = 'ComposerWithRef'; + +export default ComposerWithRef; diff --git a/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts b/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts index df9292ecd690..2da1c3e485d6 100644 --- a/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts +++ b/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts @@ -11,11 +11,14 @@ const updateNumberOfLines: UpdateNumberOfLines = (props, event) => { const lineHeight = styles.textInputCompose.lineHeight ?? 0; const paddingTopAndBottom = styles.textInputComposeSpacing.paddingVertical * 2; const inputHeight = event?.nativeEvent?.contentSize?.height ?? null; + if (!inputHeight) { return; } const numberOfLines = getNumberOfLines(lineHeight, paddingTopAndBottom, inputHeight); updateIsFullComposerAvailable(props, numberOfLines); + + return numberOfLines; }; export default updateNumberOfLines; diff --git a/src/libs/ComposerUtils/updateNumberOfLines/types.ts b/src/libs/ComposerUtils/updateNumberOfLines/types.ts index b0f9ba48ddc2..828c67624bd5 100644 --- a/src/libs/ComposerUtils/updateNumberOfLines/types.ts +++ b/src/libs/ComposerUtils/updateNumberOfLines/types.ts @@ -1,6 +1,6 @@ import {NativeSyntheticEvent, TextInputContentSizeChangeEventData} from 'react-native'; import ComposerProps from '@libs/ComposerUtils/types'; -type UpdateNumberOfLines = (props: ComposerProps, event: NativeSyntheticEvent) => void; +type UpdateNumberOfLines = (props: ComposerProps, event: NativeSyntheticEvent) => number | void; export default UpdateNumberOfLines; From 47318dce468793e435f530e8578c8367c3a9f3ef Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 28 Nov 2023 18:15:39 +0100 Subject: [PATCH 19/34] update the comment --- src/styles/StyleUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/StyleUtils.ts b/src/styles/StyleUtils.ts index 279704cd278c..a0fd15dad2fd 100644 --- a/src/styles/StyleUtils.ts +++ b/src/styles/StyleUtils.ts @@ -1391,7 +1391,7 @@ function getDotIndicatorTextStyles(isErrorText = true): TextStyle { } /** - * Returns container styles for showing the icons in MultipleAvatars/SubscriptAvatar + * Get the style for setting the maximum height of the composer component */ function getComposerMaxHeightStyle(maxLines: number, isComposerFullSize: boolean): ViewStyle | undefined { const composerLineHeight = styles.textInputCompose.lineHeight ?? 0; From 786a859897ec5f1a0130be01901eba44f5592893 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 28 Nov 2023 22:28:35 +0100 Subject: [PATCH 20/34] simplify ios implementation --- src/components/Composer/index.ios.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/components/Composer/index.ios.js b/src/components/Composer/index.ios.js index 8204d38c3406..51ff66f5747d 100644 --- a/src/components/Composer/index.ios.js +++ b/src/components/Composer/index.ios.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import React, {useCallback, useEffect, useMemo, useRef} from 'react'; +import React, {useCallback, useEffect, useRef} from 'react'; import _ from 'underscore'; import RNTextInput from '@components/RNTextInput'; import * as ComposerUtils from '@libs/ComposerUtils'; @@ -92,17 +92,6 @@ function Composer({shouldClear, onClear, isDisabled, maxLines, forwardedRef, isC onClear(); }, [shouldClear, onClear]); - /** - * Set maximum number of lines - * @return {Number} - */ - const maxNumberOfLines = useMemo(() => { - if (isComposerFullSize) { - return; - } - return maxLines; - }, [isComposerFullSize, maxLines]); - // On native layers we like to have the Text Input not focused so the // user can read new chats without the keyboard in the way of the view. // On Android the selection prop is required on the TextInput but this prop has issues on IOS @@ -115,7 +104,7 @@ function Composer({shouldClear, onClear, isDisabled, maxLines, forwardedRef, isC onContentSizeChange={(e) => ComposerUtils.updateNumberOfLines({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e)} rejectResponderTermination={false} smartInsertDelete={false} - maxNumberOfLines={maxNumberOfLines} + maxNumberOfLines={isComposerFullSize ? undefined : maxLines} style={[...props.style, styles.verticalAlignMiddle]} /* eslint-disable-next-line react/jsx-props-no-spreading */ {...propsToPass} From 3938bb6355fdb4d94d467cd493bb9483cbb8ceb9 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 28 Nov 2023 22:40:36 +0100 Subject: [PATCH 21/34] simplify composer --- ...eact-native+0.72.4+002+NumberOfLines.patch | 632 ------------------ ...ive+0.72.4+004+ModalKeyboardFlashing.patch | 18 - src/components/Composer/index.ios.js | 129 ---- .../{index.android.js => index.native.js} | 0 4 files changed, 779 deletions(-) delete mode 100644 patches/react-native+0.72.4+002+NumberOfLines.patch delete mode 100644 patches/react-native+0.72.4+004+ModalKeyboardFlashing.patch delete mode 100644 src/components/Composer/index.ios.js rename src/components/Composer/{index.android.js => index.native.js} (100%) diff --git a/patches/react-native+0.72.4+002+NumberOfLines.patch b/patches/react-native+0.72.4+002+NumberOfLines.patch deleted file mode 100644 index 16fec4bc8363..000000000000 --- a/patches/react-native+0.72.4+002+NumberOfLines.patch +++ /dev/null @@ -1,632 +0,0 @@ -diff --git a/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js b/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js -index 6f69329..d531bee 100644 ---- a/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js -+++ b/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js -@@ -144,6 +144,8 @@ const RCTTextInputViewConfig = { - placeholder: true, - autoCorrect: true, - multiline: true, -+ numberOfLines: true, -+ maximumNumberOfLines: true, - textContentType: true, - maxLength: true, - autoCapitalize: true, -diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts b/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts -index 8badb2a..b19f197 100644 ---- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts -+++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts -@@ -347,12 +347,6 @@ export interface TextInputAndroidProps { - */ - inlineImagePadding?: number | undefined; - -- /** -- * Sets the number of lines for a TextInput. -- * Use it with multiline set to true to be able to fill the lines. -- */ -- numberOfLines?: number | undefined; -- - /** - * Sets the return key to the label. Use it instead of `returnKeyType`. - * @platform android -@@ -663,11 +657,30 @@ export interface TextInputProps - */ - maxLength?: number | undefined; - -+ /** -+ * Sets the maximum number of lines for a TextInput. -+ * Use it with multiline set to true to be able to fill the lines. -+ */ -+ maxNumberOfLines?: number | undefined; -+ - /** - * If true, the text input can be multiple lines. The default value is false. - */ - multiline?: boolean | undefined; - -+ /** -+ * Sets the number of lines for a TextInput. -+ * Use it with multiline set to true to be able to fill the lines. -+ */ -+ numberOfLines?: number | undefined; -+ -+ /** -+ * Sets the number of rows for a TextInput. -+ * Use it with multiline set to true to be able to fill the lines. -+ */ -+ rows?: number | undefined; -+ -+ - /** - * Callback that is called when the text input is blurred - */ -diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js b/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js -index 7ed4579..b1d994e 100644 ---- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js -+++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js -@@ -343,26 +343,12 @@ type AndroidProps = $ReadOnly<{| - */ - inlineImagePadding?: ?number, - -- /** -- * Sets the number of lines for a `TextInput`. Use it with multiline set to -- * `true` to be able to fill the lines. -- * @platform android -- */ -- numberOfLines?: ?number, -- - /** - * Sets the return key to the label. Use it instead of `returnKeyType`. - * @platform android - */ - returnKeyLabel?: ?string, - -- /** -- * Sets the number of rows for a `TextInput`. Use it with multiline set to -- * `true` to be able to fill the lines. -- * @platform android -- */ -- rows?: ?number, -- - /** - * When `false`, it will prevent the soft keyboard from showing when the field is focused. - * Defaults to `true`. -@@ -632,6 +618,12 @@ export type Props = $ReadOnly<{| - */ - keyboardType?: ?KeyboardType, - -+ /** -+ * Sets the maximum number of lines for a `TextInput`. Use it with multiline set to -+ * `true` to be able to fill the lines. -+ */ -+ maxNumberOfLines?: ?number, -+ - /** - * Specifies largest possible scale a font can reach when `allowFontScaling` is enabled. - * Possible values: -@@ -653,6 +645,12 @@ export type Props = $ReadOnly<{| - */ - multiline?: ?boolean, - -+ /** -+ * Sets the number of lines for a `TextInput`. Use it with multiline set to -+ * `true` to be able to fill the lines. -+ */ -+ numberOfLines?: ?number, -+ - /** - * Callback that is called when the text input is blurred. - */ -@@ -814,6 +812,12 @@ export type Props = $ReadOnly<{| - */ - returnKeyType?: ?ReturnKeyType, - -+ /** -+ * Sets the number of rows for a `TextInput`. Use it with multiline set to -+ * `true` to be able to fill the lines. -+ */ -+ rows?: ?number, -+ - /** - * If `true`, the text input obscures the text entered so that sensitive text - * like passwords stay secure. The default value is `false`. Does not work with 'multiline={true}'. -diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.js b/node_modules/react-native/Libraries/Components/TextInput/TextInput.js -index 2127191..542fc06 100644 ---- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.js -+++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.js -@@ -390,7 +390,6 @@ type AndroidProps = $ReadOnly<{| - /** - * Sets the number of lines for a `TextInput`. Use it with multiline set to - * `true` to be able to fill the lines. -- * @platform android - */ - numberOfLines?: ?number, - -@@ -403,10 +402,14 @@ type AndroidProps = $ReadOnly<{| - /** - * Sets the number of rows for a `TextInput`. Use it with multiline set to - * `true` to be able to fill the lines. -- * @platform android - */ - rows?: ?number, - -+ /** -+ * Sets the maximum number of lines the TextInput can have. -+ */ -+ maxNumberOfLines?: ?number, -+ - /** - * When `false`, it will prevent the soft keyboard from showing when the field is focused. - * Defaults to `true`. -@@ -1069,6 +1072,9 @@ function InternalTextInput(props: Props): React.Node { - accessibilityState, - id, - tabIndex, -+ rows, -+ numberOfLines, -+ maxNumberOfLines, - selection: propsSelection, - ...otherProps - } = props; -@@ -1427,6 +1433,8 @@ function InternalTextInput(props: Props): React.Node { - focusable={tabIndex !== undefined ? !tabIndex : focusable} - mostRecentEventCount={mostRecentEventCount} - nativeID={id ?? props.nativeID} -+ numberOfLines={props.rows ?? props.numberOfLines} -+ maximumNumberOfLines={maxNumberOfLines} - onBlur={_onBlur} - onKeyPressSync={props.unstable_onKeyPressSync} - onChange={_onChange} -@@ -1482,6 +1490,7 @@ function InternalTextInput(props: Props): React.Node { - mostRecentEventCount={mostRecentEventCount} - nativeID={id ?? props.nativeID} - numberOfLines={props.rows ?? props.numberOfLines} -+ maximumNumberOfLines={maxNumberOfLines} - onBlur={_onBlur} - onChange={_onChange} - onFocus={_onFocus} -diff --git a/node_modules/react-native/Libraries/Text/Text.js b/node_modules/react-native/Libraries/Text/Text.js -index df548af..e02f5da 100644 ---- a/node_modules/react-native/Libraries/Text/Text.js -+++ b/node_modules/react-native/Libraries/Text/Text.js -@@ -18,7 +18,11 @@ import processColor from '../StyleSheet/processColor'; - import {getAccessibilityRoleFromRole} from '../Utilities/AcessibilityMapping'; - import Platform from '../Utilities/Platform'; - import TextAncestor from './TextAncestor'; --import {NativeText, NativeVirtualText} from './TextNativeComponent'; -+import { -+ CONTAINS_MAX_NUMBER_OF_LINES_RENAME, -+ NativeText, -+ NativeVirtualText, -+} from './TextNativeComponent'; - import * as React from 'react'; - import {useContext, useMemo, useState} from 'react'; - -@@ -59,6 +63,7 @@ const Text: React.AbstractComponent< - pressRetentionOffset, - role, - suppressHighlighting, -+ numberOfLines, - ...restProps - } = props; - -@@ -192,14 +197,33 @@ const Text: React.AbstractComponent< - } - } - -- let numberOfLines = restProps.numberOfLines; -+ let numberOfLinesValue = numberOfLines; - if (numberOfLines != null && !(numberOfLines >= 0)) { - console.error( - `'numberOfLines' in must be a non-negative number, received: ${numberOfLines}. The value will be set to 0.`, - ); -- numberOfLines = 0; -+ numberOfLinesValue = 0; - } - -+ const numberOfLinesProps = useMemo((): { -+ maximumNumberOfLines?: ?number, -+ numberOfLines?: ?number, -+ } => { -+ // FIXME: Current logic is breaking all Text components. -+ // if (CONTAINS_MAX_NUMBER_OF_LINES_RENAME) { -+ // return { -+ // maximumNumberOfLines: numberOfLinesValue, -+ // }; -+ // } else { -+ // return { -+ // numberOfLines: numberOfLinesValue, -+ // }; -+ // } -+ return { -+ maximumNumberOfLines: numberOfLinesValue, -+ }; -+ }, [numberOfLinesValue]); -+ - const hasTextAncestor = useContext(TextAncestor); - - const _accessible = Platform.select({ -@@ -241,7 +265,6 @@ const Text: React.AbstractComponent< - isHighlighted={isHighlighted} - isPressable={isPressable} - nativeID={id ?? nativeID} -- numberOfLines={numberOfLines} - ref={forwardedRef} - selectable={_selectable} - selectionColor={selectionColor} -@@ -252,6 +275,7 @@ const Text: React.AbstractComponent< - - #import -+#import -+#import - - @implementation RCTMultilineTextInputViewManager - -@@ -17,8 +19,21 @@ - (UIView *)view - return [[RCTMultilineTextInputView alloc] initWithBridge:self.bridge]; - } - -+- (RCTShadowView *)shadowView -+{ -+ RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[super shadowView]; -+ -+ shadowView.maximumNumberOfLines = 0; -+ shadowView.exactNumberOfLines = 0; -+ -+ return shadowView; -+} -+ - #pragma mark - Multiline (aka TextView) specific properties - - RCT_REMAP_VIEW_PROPERTY(dataDetectorTypes, backedTextInputView.dataDetectorTypes, UIDataDetectorTypes) - -+RCT_EXPORT_SHADOW_PROPERTY(maximumNumberOfLines, NSInteger) -+RCT_REMAP_SHADOW_PROPERTY(numberOfLines, exactNumberOfLines, NSInteger) -+ - @end -diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h -index 8f4cf7e..6238ebc 100644 ---- a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h -+++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h -@@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN - @property (nonatomic, copy, nullable) NSString *text; - @property (nonatomic, copy, nullable) NSString *placeholder; - @property (nonatomic, assign) NSInteger maximumNumberOfLines; -+@property (nonatomic, assign) NSInteger exactNumberOfLines; - @property (nonatomic, copy, nullable) RCTDirectEventBlock onContentSizeChange; - - - (void)uiManagerWillPerformMounting; -diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m -index 04d2446..9d77743 100644 ---- a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m -+++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m -@@ -218,7 +218,22 @@ - (NSAttributedString *)measurableAttributedText - - - (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize - { -- NSAttributedString *attributedText = [self measurableAttributedText]; -+ NSMutableAttributedString *attributedText = [[self measurableAttributedText] mutableCopy]; -+ -+ /* -+ * The block below is responsible for setting the exact height of the view in lines -+ * Unfortunatelly, iOS doesn't export any easy way to do it. So we set maximumNumberOfLines -+ * prop and then add random lines at the front. However, they are only used for layout -+ * so they are not visible on the screen. -+ */ -+ if (self.exactNumberOfLines) { -+ NSMutableString *newLines = [NSMutableString stringWithCapacity:self.exactNumberOfLines]; -+ for (NSUInteger i = 0UL; i < self.exactNumberOfLines; ++i) { -+ [newLines appendString:@"\n"]; -+ } -+ [attributedText insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:self.textAttributes.effectiveTextAttributes] atIndex:0]; -+ _maximumNumberOfLines = self.exactNumberOfLines; -+ } - - if (!_textStorage) { - _textContainer = [NSTextContainer new]; -diff --git a/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m b/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m -index 413ac42..56d039c 100644 ---- a/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m -+++ b/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m -@@ -19,6 +19,7 @@ - (RCTShadowView *)shadowView - RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[super shadowView]; - - shadowView.maximumNumberOfLines = 1; -+ shadowView.exactNumberOfLines = 0; - - return shadowView; - } -diff --git a/node_modules/react-native/Libraries/Text/TextNativeComponent.js b/node_modules/react-native/Libraries/Text/TextNativeComponent.js -index 0d59904..3216e43 100644 ---- a/node_modules/react-native/Libraries/Text/TextNativeComponent.js -+++ b/node_modules/react-native/Libraries/Text/TextNativeComponent.js -@@ -9,6 +9,7 @@ - */ - - import {createViewConfig} from '../NativeComponent/ViewConfig'; -+import getNativeComponentAttributes from '../ReactNative/getNativeComponentAttributes'; - import UIManager from '../ReactNative/UIManager'; - import createReactNativeComponentClass from '../Renderer/shims/createReactNativeComponentClass'; - import {type HostComponent} from '../Renderer/shims/ReactNativeTypes'; -@@ -18,6 +19,7 @@ import {type TextProps} from './TextProps'; - - type NativeTextProps = $ReadOnly<{ - ...TextProps, -+ maximumNumberOfLines?: ?number, - isHighlighted?: ?boolean, - selectionColor?: ?ProcessedColorValue, - onClick?: ?(event: PressEvent) => mixed, -@@ -31,7 +33,7 @@ const textViewConfig = { - validAttributes: { - isHighlighted: true, - isPressable: true, -- numberOfLines: true, -+ maximumNumberOfLines: true, - ellipsizeMode: true, - allowFontScaling: true, - dynamicTypeRamp: true, -@@ -73,6 +75,12 @@ export const NativeText: HostComponent = - createViewConfig(textViewConfig), - ): any); - -+const jestIsDefined = typeof jest !== 'undefined'; -+export const CONTAINS_MAX_NUMBER_OF_LINES_RENAME: boolean = jestIsDefined -+ ? true -+ : getNativeComponentAttributes('RCTText')?.NativeProps -+ ?.maximumNumberOfLines === 'number'; -+ - export const NativeVirtualText: HostComponent = - !global.RN$Bridgeless && !UIManager.hasViewManagerConfig('RCTVirtualText') - ? NativeText -diff --git a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp -index 2994aca..fff0d5e 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp -+++ b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp -@@ -16,6 +16,7 @@ namespace facebook::react { - - bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { - return std::tie( -+ numberOfLines, - maximumNumberOfLines, - ellipsizeMode, - textBreakStrategy, -@@ -23,6 +24,7 @@ bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { - includeFontPadding, - android_hyphenationFrequency) == - std::tie( -+ rhs.numberOfLines, - rhs.maximumNumberOfLines, - rhs.ellipsizeMode, - rhs.textBreakStrategy, -@@ -42,6 +44,7 @@ bool ParagraphAttributes::operator!=(const ParagraphAttributes &rhs) const { - #if RN_DEBUG_STRING_CONVERTIBLE - SharedDebugStringConvertibleList ParagraphAttributes::getDebugProps() const { - return { -+ debugStringConvertibleItem("numberOfLines", numberOfLines), - debugStringConvertibleItem("maximumNumberOfLines", maximumNumberOfLines), - debugStringConvertibleItem("ellipsizeMode", ellipsizeMode), - debugStringConvertibleItem("textBreakStrategy", textBreakStrategy), -diff --git a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h -index f5f87c6..b7d1e90 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h -+++ b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h -@@ -30,6 +30,11 @@ class ParagraphAttributes : public DebugStringConvertible { - public: - #pragma mark - Fields - -+ /* -+ * Number of lines which paragraph takes. -+ */ -+ int numberOfLines{}; -+ - /* - * Maximum number of lines which paragraph can take. - * Zero value represents "no limit". -@@ -92,6 +97,7 @@ struct hash { - const facebook::react::ParagraphAttributes &attributes) const { - return folly::hash::hash_combine( - 0, -+ attributes.numberOfLines, - attributes.maximumNumberOfLines, - attributes.ellipsizeMode, - attributes.textBreakStrategy, -diff --git a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h -index 8687b89..eab75f4 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h -+++ b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h -@@ -835,10 +835,16 @@ inline ParagraphAttributes convertRawProp( - ParagraphAttributes const &defaultParagraphAttributes) { - auto paragraphAttributes = ParagraphAttributes{}; - -- paragraphAttributes.maximumNumberOfLines = convertRawProp( -+ paragraphAttributes.numberOfLines = convertRawProp( - context, - rawProps, - "numberOfLines", -+ sourceParagraphAttributes.numberOfLines, -+ defaultParagraphAttributes.numberOfLines); -+ paragraphAttributes.maximumNumberOfLines = convertRawProp( -+ context, -+ rawProps, -+ "maximumNumberOfLines", - sourceParagraphAttributes.maximumNumberOfLines, - defaultParagraphAttributes.maximumNumberOfLines); - paragraphAttributes.ellipsizeMode = convertRawProp( -@@ -913,6 +919,7 @@ inline std::string toString(AttributedString::Range const &range) { - inline folly::dynamic toDynamic( - const ParagraphAttributes ¶graphAttributes) { - auto values = folly::dynamic::object(); -+ values("numberOfLines", paragraphAttributes.numberOfLines); - values("maximumNumberOfLines", paragraphAttributes.maximumNumberOfLines); - values("ellipsizeMode", toString(paragraphAttributes.ellipsizeMode)); - values("textBreakStrategy", toString(paragraphAttributes.textBreakStrategy)); -@@ -1118,6 +1125,7 @@ constexpr static MapBuffer::Key PA_KEY_TEXT_BREAK_STRATEGY = 2; - constexpr static MapBuffer::Key PA_KEY_ADJUST_FONT_SIZE_TO_FIT = 3; - constexpr static MapBuffer::Key PA_KEY_INCLUDE_FONT_PADDING = 4; - constexpr static MapBuffer::Key PA_KEY_HYPHENATION_FREQUENCY = 5; -+constexpr static MapBuffer::Key PA_KEY_NUMBER_OF_LINES = 6; - - inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { - auto builder = MapBufferBuilder(); -@@ -1135,6 +1143,8 @@ inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { - builder.putString( - PA_KEY_HYPHENATION_FREQUENCY, - toString(paragraphAttributes.android_hyphenationFrequency)); -+ builder.putInt( -+ PA_KEY_NUMBER_OF_LINES, paragraphAttributes.numberOfLines); - - return builder.build(); - } -diff --git a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp -index 9953e22..98eb3da 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp -+++ b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp -@@ -56,6 +56,10 @@ AndroidTextInputProps::AndroidTextInputProps( - "numberOfLines", - sourceProps.numberOfLines, - {0})), -+ maximumNumberOfLines(CoreFeatures::enablePropIteratorSetter? sourceProps.maximumNumberOfLines : convertRawProp(context, rawProps, -+ "maximumNumberOfLines", -+ sourceProps.maximumNumberOfLines, -+ {0})), - disableFullscreenUI(CoreFeatures::enablePropIteratorSetter? sourceProps.disableFullscreenUI : convertRawProp(context, rawProps, - "disableFullscreenUI", - sourceProps.disableFullscreenUI, -@@ -281,6 +285,12 @@ void AndroidTextInputProps::setProp( - value, - paragraphAttributes, - maximumNumberOfLines, -+ "maximumNumberOfLines"); -+ REBUILD_FIELD_SWITCH_CASE( -+ paDefaults, -+ value, -+ paragraphAttributes, -+ numberOfLines, - "numberOfLines"); - REBUILD_FIELD_SWITCH_CASE( - paDefaults, value, paragraphAttributes, ellipsizeMode, "ellipsizeMode"); -@@ -323,6 +333,7 @@ void AndroidTextInputProps::setProp( - } - - switch (hash) { -+ RAW_SET_PROP_SWITCH_CASE_BASIC(maximumNumberOfLines); - RAW_SET_PROP_SWITCH_CASE_BASIC(autoComplete); - RAW_SET_PROP_SWITCH_CASE_BASIC(returnKeyLabel); - RAW_SET_PROP_SWITCH_CASE_BASIC(numberOfLines); -@@ -422,6 +433,7 @@ void AndroidTextInputProps::setProp( - // TODO T53300085: support this in codegen; this was hand-written - folly::dynamic AndroidTextInputProps::getDynamic() const { - folly::dynamic props = folly::dynamic::object(); -+ props["maximumNumberOfLines"] = maximumNumberOfLines; - props["autoComplete"] = autoComplete; - props["returnKeyLabel"] = returnKeyLabel; - props["numberOfLines"] = numberOfLines; -diff --git a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h -index ba39ebb..ead28e3 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h -+++ b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h -@@ -84,6 +84,7 @@ class AndroidTextInputProps final : public ViewProps, public BaseTextProps { - std::string autoComplete{}; - std::string returnKeyLabel{}; - int numberOfLines{0}; -+ int maximumNumberOfLines{0}; - bool disableFullscreenUI{false}; - std::string textBreakStrategy{}; - SharedColor underlineColorAndroid{}; -diff --git a/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm b/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm -index 368c334..a1bb33e 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm -+++ b/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm -@@ -244,26 +244,51 @@ - (void)getRectWithAttributedString:(AttributedString)attributedString - - #pragma mark - Private - --- (NSTextStorage *)_textStorageForNSAttributesString:(NSAttributedString *)attributedString -++- (NSTextStorage *)_textStorageForNSAttributesString:(NSAttributedString *)inputAttributedString - paragraphAttributes:(ParagraphAttributes)paragraphAttributes - size:(CGSize)size - { -- NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:size]; -+ NSMutableAttributedString *attributedString = [ inputAttributedString mutableCopy]; -+ -+ /* -+ * The block below is responsible for setting the exact height of the view in lines -+ * Unfortunatelly, iOS doesn't export any easy way to do it. So we set maximumNumberOfLines -+ * prop and then add random lines at the front. However, they are only used for layout -+ * so they are not visible on the screen. This method is used for drawing only for Paragraph component -+ * but we set exact height in lines only on TextInput that doesn't use it. -+ */ -+ if (paragraphAttributes.numberOfLines) { -+ paragraphAttributes.maximumNumberOfLines = paragraphAttributes.numberOfLines; -+ NSMutableString *newLines = [NSMutableString stringWithCapacity: paragraphAttributes.numberOfLines]; -+ for (NSUInteger i = 0UL; i < paragraphAttributes.numberOfLines; ++i) { -+ // K is added on purpose. New line seems to be not enough for NTtextContainer -+ [newLines appendString:@"K\n"]; -+ } -+ NSDictionary * attributesOfFirstCharacter = [inputAttributedString attributesAtIndex:0 effectiveRange:NULL]; - -- textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5. -- textContainer.lineBreakMode = paragraphAttributes.maximumNumberOfLines > 0 -- ? RCTNSLineBreakModeFromEllipsizeMode(paragraphAttributes.ellipsizeMode) -- : NSLineBreakByClipping; -- textContainer.maximumNumberOfLines = paragraphAttributes.maximumNumberOfLines; -+ [attributedString insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:attributesOfFirstCharacter] atIndex:0]; -+ } -+ -+ NSTextContainer *textContainer = [NSTextContainer new]; - - NSLayoutManager *layoutManager = [NSLayoutManager new]; - layoutManager.usesFontLeading = NO; - [layoutManager addTextContainer:textContainer]; - -- NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString]; -+ NSTextStorage *textStorage = [NSTextStorage new]; - - [textStorage addLayoutManager:layoutManager]; - -+ textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5. -+ textContainer.lineBreakMode = paragraphAttributes.maximumNumberOfLines > 0 -+ ? RCTNSLineBreakModeFromEllipsizeMode(paragraphAttributes.ellipsizeMode) -+ : NSLineBreakByClipping; -+ textContainer.size = size; -+ textContainer.maximumNumberOfLines = paragraphAttributes.maximumNumberOfLines; -+ -+ [textStorage replaceCharactersInRange:(NSRange){0, textStorage.length} withAttributedString:attributedString]; -+ -+ - if (paragraphAttributes.adjustsFontSizeToFit) { - CGFloat minimumFontSize = !isnan(paragraphAttributes.minimumFontSize) ? paragraphAttributes.minimumFontSize : 4.0; - CGFloat maximumFontSize = !isnan(paragraphAttributes.maximumFontSize) ? paragraphAttributes.maximumFontSize : 96.0; diff --git a/patches/react-native+0.72.4+004+ModalKeyboardFlashing.patch b/patches/react-native+0.72.4+004+ModalKeyboardFlashing.patch deleted file mode 100644 index 84a233894f94..000000000000 --- a/patches/react-native+0.72.4+004+ModalKeyboardFlashing.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/node_modules/react-native/React/Views/RCTModalHostViewManager.m b/node_modules/react-native/React/Views/RCTModalHostViewManager.m -index 4b9f9ad..b72984c 100644 ---- a/node_modules/react-native/React/Views/RCTModalHostViewManager.m -+++ b/node_modules/react-native/React/Views/RCTModalHostViewManager.m -@@ -79,6 +79,13 @@ RCT_EXPORT_MODULE() - if (self->_presentationBlock) { - self->_presentationBlock([modalHostView reactViewController], viewController, animated, completionBlock); - } else { -+ // In our App, If an input is blurred and a modal is opened, the rootView will become the firstResponder, which -+ // will cause system to retain a wrong keyboard state, and then the keyboard to flicker when the modal is closed. -+ // We first resign the rootView to avoid this problem. -+ UIWindow *window = RCTKeyWindow(); -+ if (window && window.rootViewController && [window.rootViewController.view isFirstResponder]) { -+ [window.rootViewController.view resignFirstResponder]; -+ } - [[modalHostView reactViewController] presentViewController:viewController - animated:animated - completion:completionBlock]; diff --git a/src/components/Composer/index.ios.js b/src/components/Composer/index.ios.js deleted file mode 100644 index 51ff66f5747d..000000000000 --- a/src/components/Composer/index.ios.js +++ /dev/null @@ -1,129 +0,0 @@ -import PropTypes from 'prop-types'; -import React, {useCallback, useEffect, useRef} from 'react'; -import _ from 'underscore'; -import RNTextInput from '@components/RNTextInput'; -import * as ComposerUtils from '@libs/ComposerUtils'; -import styles from '@styles/styles'; -import themeColors from '@styles/themes/default'; - -const propTypes = { - /** If the input should clear, it actually gets intercepted instead of .clear() */ - shouldClear: PropTypes.bool, - - /** A ref to forward to the text input */ - forwardedRef: PropTypes.func, - - /** When the input has cleared whoever owns this input should know about it */ - onClear: PropTypes.func, - - /** Set focus to this component the first time it renders. - * Override this in case you need to set focus on one field out of many, or when you want to disable autoFocus */ - autoFocus: PropTypes.bool, - - /** Prevent edits and interactions like focus for this input. */ - isDisabled: PropTypes.bool, - - /** Selection Object */ - selection: PropTypes.shape({ - start: PropTypes.number, - end: PropTypes.number, - }), - - /** Whether the full composer can be opened */ - isFullComposerAvailable: PropTypes.bool, - - /** Maximum number of lines in the text input */ - maxLines: PropTypes.number, - - /** Allow the full composer to be opened */ - setIsFullComposerAvailable: PropTypes.func, - - /** Whether the composer is full size */ - isComposerFullSize: PropTypes.bool, - - /** General styles to apply to the text input */ - // eslint-disable-next-line react/forbid-prop-types - style: PropTypes.any, -}; - -const defaultProps = { - shouldClear: false, - onClear: () => {}, - autoFocus: false, - isDisabled: false, - forwardedRef: null, - selection: { - start: 0, - end: 0, - }, - maxLines: undefined, - isFullComposerAvailable: false, - setIsFullComposerAvailable: () => {}, - isComposerFullSize: false, - style: null, -}; - -function Composer({shouldClear, onClear, isDisabled, maxLines, forwardedRef, isComposerFullSize, setIsFullComposerAvailable, ...props}) { - const textInput = useRef(null); - - /** - * Set the TextInput Ref - * @param {Element} el - */ - const setTextInputRef = useCallback((el) => { - textInput.current = el; - if (!_.isFunction(forwardedRef) || textInput.current === null) { - return; - } - - // This callback prop is used by the parent component using the constructor to - // get a ref to the inner textInput element e.g. if we do - // this.textInput = el} /> this will not - // return a ref to the component, but rather the HTML element by default - forwardedRef(textInput.current); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - useEffect(() => { - if (!shouldClear) { - return; - } - textInput.current.clear(); - onClear(); - }, [shouldClear, onClear]); - - // On native layers we like to have the Text Input not focused so the - // user can read new chats without the keyboard in the way of the view. - // On Android the selection prop is required on the TextInput but this prop has issues on IOS - const propsToPass = _.omit(props, 'selection'); - return ( - ComposerUtils.updateNumberOfLines({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e)} - rejectResponderTermination={false} - smartInsertDelete={false} - maxNumberOfLines={isComposerFullSize ? undefined : maxLines} - style={[...props.style, styles.verticalAlignMiddle]} - /* eslint-disable-next-line react/jsx-props-no-spreading */ - {...propsToPass} - readOnly={isDisabled} - /> - ); -} - -Composer.propTypes = propTypes; -Composer.defaultProps = defaultProps; - -const ComposerWithRef = React.forwardRef((props, ref) => ( - -)); - -ComposerWithRef.displayName = 'ComposerWithRef'; - -export default ComposerWithRef; diff --git a/src/components/Composer/index.android.js b/src/components/Composer/index.native.js similarity index 100% rename from src/components/Composer/index.android.js rename to src/components/Composer/index.native.js From 88ad1d9a0ba6efe401476d0b3289a53c3dbe606c Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 28 Nov 2023 22:43:45 +0100 Subject: [PATCH 22/34] remove unused changes --- src/libs/ComposerUtils/updateNumberOfLines/index.native.ts | 2 -- src/libs/ComposerUtils/updateNumberOfLines/types.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts b/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts index 2da1c3e485d6..1911413e3d05 100644 --- a/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts +++ b/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts @@ -17,8 +17,6 @@ const updateNumberOfLines: UpdateNumberOfLines = (props, event) => { } const numberOfLines = getNumberOfLines(lineHeight, paddingTopAndBottom, inputHeight); updateIsFullComposerAvailable(props, numberOfLines); - - return numberOfLines; }; export default updateNumberOfLines; diff --git a/src/libs/ComposerUtils/updateNumberOfLines/types.ts b/src/libs/ComposerUtils/updateNumberOfLines/types.ts index 828c67624bd5..b0f9ba48ddc2 100644 --- a/src/libs/ComposerUtils/updateNumberOfLines/types.ts +++ b/src/libs/ComposerUtils/updateNumberOfLines/types.ts @@ -1,6 +1,6 @@ import {NativeSyntheticEvent, TextInputContentSizeChangeEventData} from 'react-native'; import ComposerProps from '@libs/ComposerUtils/types'; -type UpdateNumberOfLines = (props: ComposerProps, event: NativeSyntheticEvent) => number | void; +type UpdateNumberOfLines = (props: ComposerProps, event: NativeSyntheticEvent) => void; export default UpdateNumberOfLines; From cbf1e667fb845c429906d8943d881f16f166976e Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 28 Nov 2023 22:44:18 +0100 Subject: [PATCH 23/34] remove empty line --- src/libs/ComposerUtils/updateNumberOfLines/index.native.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts b/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts index 1911413e3d05..df9292ecd690 100644 --- a/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts +++ b/src/libs/ComposerUtils/updateNumberOfLines/index.native.ts @@ -11,7 +11,6 @@ const updateNumberOfLines: UpdateNumberOfLines = (props, event) => { const lineHeight = styles.textInputCompose.lineHeight ?? 0; const paddingTopAndBottom = styles.textInputComposeSpacing.paddingVertical * 2; const inputHeight = event?.nativeEvent?.contentSize?.height ?? null; - if (!inputHeight) { return; } From 8d44ecdc0d7d93d185af72ca635fe47a472ba3bc Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Sat, 2 Dec 2023 20:51:12 +0100 Subject: [PATCH 24/34] remove unused style --- src/styles/styles.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/styles/styles.ts b/src/styles/styles.ts index 983f1ba82caa..98a68a9dfc1c 100644 --- a/src/styles/styles.ts +++ b/src/styles/styles.ts @@ -331,10 +331,6 @@ const styles = (theme: ThemeColors) => textAlign: 'left', }, - verticalAlignMiddle: { - verticalAlign: 'middle', - }, - verticalAlignTop: { verticalAlign: 'top', }, From cb7785b60a00384a3d12887ca538cc1a27d9255d Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Sun, 3 Dec 2023 01:25:10 +0100 Subject: [PATCH 25/34] don't build android from source --- android/settings.gradle | 9 --------- 1 file changed, 9 deletions(-) diff --git a/android/settings.gradle b/android/settings.gradle index c2bb3db7845a..680dfbc32521 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -16,12 +16,3 @@ project(':react-native-dev-menu').projectDir = new File(rootProject.projectDir, apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' includeBuild('../node_modules/@react-native/gradle-plugin') - -includeBuild('../node_modules/react-native') { - dependencySubstitution { - substitute(module("com.facebook.react:react-android")).using(project(":packages:react-native:ReactAndroid")) - substitute(module("com.facebook.react:react-native")).using(project(":packages:react-native:ReactAndroid")) - substitute(module("com.facebook.react:hermes-android")).using(project(":packages:react-native:ReactAndroid:hermes-engine")) - substitute(module("com.facebook.react:hermes-engine")).using(project(":packages:react-native:ReactAndroid:hermes-engine")) - } -} From 558dbee176c47bb4335143320c71e755e5b5364e Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 5 Dec 2023 11:54:03 +0100 Subject: [PATCH 26/34] remove patch --- ...ve+0.72.4+002+ModalKeyboardFlashing.patch} | 0 ...eact-native+0.72.4+002+NumberOfLines.patch | 978 ------------------ 2 files changed, 978 deletions(-) rename patches/{react-native+0.72.4+004+ModalKeyboardFlashing.patch => react-native+0.72.4+002+ModalKeyboardFlashing.patch} (100%) delete mode 100644 patches/react-native+0.72.4+002+NumberOfLines.patch diff --git a/patches/react-native+0.72.4+004+ModalKeyboardFlashing.patch b/patches/react-native+0.72.4+002+ModalKeyboardFlashing.patch similarity index 100% rename from patches/react-native+0.72.4+004+ModalKeyboardFlashing.patch rename to patches/react-native+0.72.4+002+ModalKeyboardFlashing.patch diff --git a/patches/react-native+0.72.4+002+NumberOfLines.patch b/patches/react-native+0.72.4+002+NumberOfLines.patch deleted file mode 100644 index 75422f84708e..000000000000 --- a/patches/react-native+0.72.4+002+NumberOfLines.patch +++ /dev/null @@ -1,978 +0,0 @@ -diff --git a/node_modules/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js b/node_modules/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js -index 55b770d..4073836 100644 ---- a/node_modules/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js -+++ b/node_modules/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js -@@ -179,6 +179,13 @@ export type NativeProps = $ReadOnly<{| - */ - numberOfLines?: ?Int32, - -+ /** -+ * Sets the maximum number of lines for a `TextInput`. Use it with multiline set to -+ * `true` to be able to fill the lines. -+ * @platform android -+ */ -+ maximumNumberOfLines?: ?Int32, -+ - /** - * When `false`, if there is a small amount of space available around a text input - * (e.g. landscape orientation on a phone), the OS may choose to have the user edit -diff --git a/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js b/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js -index 6f69329..d531bee 100644 ---- a/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js -+++ b/node_modules/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js -@@ -144,6 +144,8 @@ const RCTTextInputViewConfig = { - placeholder: true, - autoCorrect: true, - multiline: true, -+ numberOfLines: true, -+ maximumNumberOfLines: true, - textContentType: true, - maxLength: true, - autoCapitalize: true, -diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts b/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts -index 8badb2a..b19f197 100644 ---- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts -+++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.d.ts -@@ -347,12 +347,6 @@ export interface TextInputAndroidProps { - */ - inlineImagePadding?: number | undefined; - -- /** -- * Sets the number of lines for a TextInput. -- * Use it with multiline set to true to be able to fill the lines. -- */ -- numberOfLines?: number | undefined; -- - /** - * Sets the return key to the label. Use it instead of `returnKeyType`. - * @platform android -@@ -663,11 +657,30 @@ export interface TextInputProps - */ - maxLength?: number | undefined; - -+ /** -+ * Sets the maximum number of lines for a TextInput. -+ * Use it with multiline set to true to be able to fill the lines. -+ */ -+ maxNumberOfLines?: number | undefined; -+ - /** - * If true, the text input can be multiple lines. The default value is false. - */ - multiline?: boolean | undefined; - -+ /** -+ * Sets the number of lines for a TextInput. -+ * Use it with multiline set to true to be able to fill the lines. -+ */ -+ numberOfLines?: number | undefined; -+ -+ /** -+ * Sets the number of rows for a TextInput. -+ * Use it with multiline set to true to be able to fill the lines. -+ */ -+ rows?: number | undefined; -+ -+ - /** - * Callback that is called when the text input is blurred - */ -diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js b/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js -index 7ed4579..b1d994e 100644 ---- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js -+++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.flow.js -@@ -343,26 +343,12 @@ type AndroidProps = $ReadOnly<{| - */ - inlineImagePadding?: ?number, - -- /** -- * Sets the number of lines for a `TextInput`. Use it with multiline set to -- * `true` to be able to fill the lines. -- * @platform android -- */ -- numberOfLines?: ?number, -- - /** - * Sets the return key to the label. Use it instead of `returnKeyType`. - * @platform android - */ - returnKeyLabel?: ?string, - -- /** -- * Sets the number of rows for a `TextInput`. Use it with multiline set to -- * `true` to be able to fill the lines. -- * @platform android -- */ -- rows?: ?number, -- - /** - * When `false`, it will prevent the soft keyboard from showing when the field is focused. - * Defaults to `true`. -@@ -632,6 +618,12 @@ export type Props = $ReadOnly<{| - */ - keyboardType?: ?KeyboardType, - -+ /** -+ * Sets the maximum number of lines for a `TextInput`. Use it with multiline set to -+ * `true` to be able to fill the lines. -+ */ -+ maxNumberOfLines?: ?number, -+ - /** - * Specifies largest possible scale a font can reach when `allowFontScaling` is enabled. - * Possible values: -@@ -653,6 +645,12 @@ export type Props = $ReadOnly<{| - */ - multiline?: ?boolean, - -+ /** -+ * Sets the number of lines for a `TextInput`. Use it with multiline set to -+ * `true` to be able to fill the lines. -+ */ -+ numberOfLines?: ?number, -+ - /** - * Callback that is called when the text input is blurred. - */ -@@ -814,6 +812,12 @@ export type Props = $ReadOnly<{| - */ - returnKeyType?: ?ReturnKeyType, - -+ /** -+ * Sets the number of rows for a `TextInput`. Use it with multiline set to -+ * `true` to be able to fill the lines. -+ */ -+ rows?: ?number, -+ - /** - * If `true`, the text input obscures the text entered so that sensitive text - * like passwords stay secure. The default value is `false`. Does not work with 'multiline={true}'. -diff --git a/node_modules/react-native/Libraries/Components/TextInput/TextInput.js b/node_modules/react-native/Libraries/Components/TextInput/TextInput.js -index 2127191..542fc06 100644 ---- a/node_modules/react-native/Libraries/Components/TextInput/TextInput.js -+++ b/node_modules/react-native/Libraries/Components/TextInput/TextInput.js -@@ -390,7 +390,6 @@ type AndroidProps = $ReadOnly<{| - /** - * Sets the number of lines for a `TextInput`. Use it with multiline set to - * `true` to be able to fill the lines. -- * @platform android - */ - numberOfLines?: ?number, - -@@ -403,10 +402,14 @@ type AndroidProps = $ReadOnly<{| - /** - * Sets the number of rows for a `TextInput`. Use it with multiline set to - * `true` to be able to fill the lines. -- * @platform android - */ - rows?: ?number, - -+ /** -+ * Sets the maximum number of lines the TextInput can have. -+ */ -+ maxNumberOfLines?: ?number, -+ - /** - * When `false`, it will prevent the soft keyboard from showing when the field is focused. - * Defaults to `true`. -@@ -1069,6 +1072,9 @@ function InternalTextInput(props: Props): React.Node { - accessibilityState, - id, - tabIndex, -+ rows, -+ numberOfLines, -+ maxNumberOfLines, - selection: propsSelection, - ...otherProps - } = props; -@@ -1427,6 +1433,8 @@ function InternalTextInput(props: Props): React.Node { - focusable={tabIndex !== undefined ? !tabIndex : focusable} - mostRecentEventCount={mostRecentEventCount} - nativeID={id ?? props.nativeID} -+ numberOfLines={props.rows ?? props.numberOfLines} -+ maximumNumberOfLines={maxNumberOfLines} - onBlur={_onBlur} - onKeyPressSync={props.unstable_onKeyPressSync} - onChange={_onChange} -@@ -1482,6 +1490,7 @@ function InternalTextInput(props: Props): React.Node { - mostRecentEventCount={mostRecentEventCount} - nativeID={id ?? props.nativeID} - numberOfLines={props.rows ?? props.numberOfLines} -+ maximumNumberOfLines={maxNumberOfLines} - onBlur={_onBlur} - onChange={_onChange} - onFocus={_onFocus} -diff --git a/node_modules/react-native/Libraries/Text/Text.js b/node_modules/react-native/Libraries/Text/Text.js -index df548af..e02f5da 100644 ---- a/node_modules/react-native/Libraries/Text/Text.js -+++ b/node_modules/react-native/Libraries/Text/Text.js -@@ -18,7 +18,11 @@ import processColor from '../StyleSheet/processColor'; - import {getAccessibilityRoleFromRole} from '../Utilities/AcessibilityMapping'; - import Platform from '../Utilities/Platform'; - import TextAncestor from './TextAncestor'; --import {NativeText, NativeVirtualText} from './TextNativeComponent'; -+import { -+ CONTAINS_MAX_NUMBER_OF_LINES_RENAME, -+ NativeText, -+ NativeVirtualText, -+} from './TextNativeComponent'; - import * as React from 'react'; - import {useContext, useMemo, useState} from 'react'; - -@@ -59,6 +63,7 @@ const Text: React.AbstractComponent< - pressRetentionOffset, - role, - suppressHighlighting, -+ numberOfLines, - ...restProps - } = props; - -@@ -192,14 +197,33 @@ const Text: React.AbstractComponent< - } - } - -- let numberOfLines = restProps.numberOfLines; -+ let numberOfLinesValue = numberOfLines; - if (numberOfLines != null && !(numberOfLines >= 0)) { - console.error( - `'numberOfLines' in must be a non-negative number, received: ${numberOfLines}. The value will be set to 0.`, - ); -- numberOfLines = 0; -+ numberOfLinesValue = 0; - } - -+ const numberOfLinesProps = useMemo((): { -+ maximumNumberOfLines?: ?number, -+ numberOfLines?: ?number, -+ } => { -+ // FIXME: Current logic is breaking all Text components. -+ // if (CONTAINS_MAX_NUMBER_OF_LINES_RENAME) { -+ // return { -+ // maximumNumberOfLines: numberOfLinesValue, -+ // }; -+ // } else { -+ // return { -+ // numberOfLines: numberOfLinesValue, -+ // }; -+ // } -+ return { -+ maximumNumberOfLines: numberOfLinesValue, -+ }; -+ }, [numberOfLinesValue]); -+ - const hasTextAncestor = useContext(TextAncestor); - - const _accessible = Platform.select({ -@@ -241,7 +265,6 @@ const Text: React.AbstractComponent< - isHighlighted={isHighlighted} - isPressable={isPressable} - nativeID={id ?? nativeID} -- numberOfLines={numberOfLines} - ref={forwardedRef} - selectable={_selectable} - selectionColor={selectionColor} -@@ -252,6 +275,7 @@ const Text: React.AbstractComponent< - - #import -+#import -+#import - - @implementation RCTMultilineTextInputViewManager - -@@ -17,8 +19,21 @@ - (UIView *)view - return [[RCTMultilineTextInputView alloc] initWithBridge:self.bridge]; - } - -+- (RCTShadowView *)shadowView -+{ -+ RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[super shadowView]; -+ -+ shadowView.maximumNumberOfLines = 0; -+ shadowView.exactNumberOfLines = 0; -+ -+ return shadowView; -+} -+ - #pragma mark - Multiline (aka TextView) specific properties - - RCT_REMAP_VIEW_PROPERTY(dataDetectorTypes, backedTextInputView.dataDetectorTypes, UIDataDetectorTypes) - -+RCT_EXPORT_SHADOW_PROPERTY(maximumNumberOfLines, NSInteger) -+RCT_REMAP_SHADOW_PROPERTY(numberOfLines, exactNumberOfLines, NSInteger) -+ - @end -diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h -index 8f4cf7e..6238ebc 100644 ---- a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h -+++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.h -@@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN - @property (nonatomic, copy, nullable) NSString *text; - @property (nonatomic, copy, nullable) NSString *placeholder; - @property (nonatomic, assign) NSInteger maximumNumberOfLines; -+@property (nonatomic, assign) NSInteger exactNumberOfLines; - @property (nonatomic, copy, nullable) RCTDirectEventBlock onContentSizeChange; - - - (void)uiManagerWillPerformMounting; -diff --git a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m -index 04d2446..9d77743 100644 ---- a/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m -+++ b/node_modules/react-native/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m -@@ -218,7 +218,22 @@ - (NSAttributedString *)measurableAttributedText - - - (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize - { -- NSAttributedString *attributedText = [self measurableAttributedText]; -+ NSMutableAttributedString *attributedText = [[self measurableAttributedText] mutableCopy]; -+ -+ /* -+ * The block below is responsible for setting the exact height of the view in lines -+ * Unfortunatelly, iOS doesn't export any easy way to do it. So we set maximumNumberOfLines -+ * prop and then add random lines at the front. However, they are only used for layout -+ * so they are not visible on the screen. -+ */ -+ if (self.exactNumberOfLines) { -+ NSMutableString *newLines = [NSMutableString stringWithCapacity:self.exactNumberOfLines]; -+ for (NSUInteger i = 0UL; i < self.exactNumberOfLines; ++i) { -+ [newLines appendString:@"\n"]; -+ } -+ [attributedText insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:self.textAttributes.effectiveTextAttributes] atIndex:0]; -+ _maximumNumberOfLines = self.exactNumberOfLines; -+ } - - if (!_textStorage) { - _textContainer = [NSTextContainer new]; -diff --git a/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m b/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m -index 413ac42..56d039c 100644 ---- a/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m -+++ b/node_modules/react-native/Libraries/Text/TextInput/Singleline/RCTSinglelineTextInputViewManager.m -@@ -19,6 +19,7 @@ - (RCTShadowView *)shadowView - RCTBaseTextInputShadowView *shadowView = (RCTBaseTextInputShadowView *)[super shadowView]; - - shadowView.maximumNumberOfLines = 1; -+ shadowView.exactNumberOfLines = 0; - - return shadowView; - } -diff --git a/node_modules/react-native/Libraries/Text/TextNativeComponent.js b/node_modules/react-native/Libraries/Text/TextNativeComponent.js -index 0d59904..3216e43 100644 ---- a/node_modules/react-native/Libraries/Text/TextNativeComponent.js -+++ b/node_modules/react-native/Libraries/Text/TextNativeComponent.js -@@ -9,6 +9,7 @@ - */ - - import {createViewConfig} from '../NativeComponent/ViewConfig'; -+import getNativeComponentAttributes from '../ReactNative/getNativeComponentAttributes'; - import UIManager from '../ReactNative/UIManager'; - import createReactNativeComponentClass from '../Renderer/shims/createReactNativeComponentClass'; - import {type HostComponent} from '../Renderer/shims/ReactNativeTypes'; -@@ -18,6 +19,7 @@ import {type TextProps} from './TextProps'; - - type NativeTextProps = $ReadOnly<{ - ...TextProps, -+ maximumNumberOfLines?: ?number, - isHighlighted?: ?boolean, - selectionColor?: ?ProcessedColorValue, - onClick?: ?(event: PressEvent) => mixed, -@@ -31,7 +33,7 @@ const textViewConfig = { - validAttributes: { - isHighlighted: true, - isPressable: true, -- numberOfLines: true, -+ maximumNumberOfLines: true, - ellipsizeMode: true, - allowFontScaling: true, - dynamicTypeRamp: true, -@@ -73,6 +75,12 @@ export const NativeText: HostComponent = - createViewConfig(textViewConfig), - ): any); - -+const jestIsDefined = typeof jest !== 'undefined'; -+export const CONTAINS_MAX_NUMBER_OF_LINES_RENAME: boolean = jestIsDefined -+ ? true -+ : getNativeComponentAttributes('RCTText')?.NativeProps -+ ?.maximumNumberOfLines === 'number'; -+ - export const NativeVirtualText: HostComponent = - !global.RN$Bridgeless && !UIManager.hasViewManagerConfig('RCTVirtualText') - ? NativeText -diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java -index 8cab407..ad5fa96 100644 ---- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java -+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java -@@ -12,5 +12,6 @@ public class ViewDefaults { - - public static final float FONT_SIZE_SP = 14.0f; - public static final int LINE_HEIGHT = 0; -- public static final int NUMBER_OF_LINES = Integer.MAX_VALUE; -+ public static final int NUMBER_OF_LINES = -1; -+ public static final int MAXIMUM_NUMBER_OF_LINES = Integer.MAX_VALUE; - } -diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java -index 3f76fa7..7a5d096 100644 ---- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java -+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java -@@ -96,6 +96,7 @@ public class ViewProps { - public static final String LETTER_SPACING = "letterSpacing"; - public static final String NEEDS_OFFSCREEN_ALPHA_COMPOSITING = "needsOffscreenAlphaCompositing"; - public static final String NUMBER_OF_LINES = "numberOfLines"; -+ public static final String MAXIMUM_NUMBER_OF_LINES = "maximumNumberOfLines"; - public static final String ELLIPSIZE_MODE = "ellipsizeMode"; - public static final String ADJUSTS_FONT_SIZE_TO_FIT = "adjustsFontSizeToFit"; - public static final String MINIMUM_FONT_SCALE = "minimumFontScale"; -diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java -index b5811c7..96eef96 100644 ---- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java -+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java -@@ -303,6 +303,7 @@ public abstract class ReactBaseTextShadowNode extends LayoutShadowNode { - protected boolean mIsAccessibilityLink = false; - - protected int mNumberOfLines = UNSET; -+ protected int mMaxNumberOfLines = UNSET; - protected int mTextAlign = Gravity.NO_GRAVITY; - protected int mTextBreakStrategy = - (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ? 0 : Layout.BREAK_STRATEGY_HIGH_QUALITY; -@@ -387,6 +388,12 @@ public abstract class ReactBaseTextShadowNode extends LayoutShadowNode { - markUpdated(); - } - -+ @ReactProp(name = ViewProps.MAXIMUM_NUMBER_OF_LINES, defaultInt = UNSET) -+ public void setMaxNumberOfLines(int numberOfLines) { -+ mMaxNumberOfLines = numberOfLines == 0 ? UNSET : numberOfLines; -+ markUpdated(); -+ } -+ - @ReactProp(name = ViewProps.LINE_HEIGHT, defaultFloat = Float.NaN) - public void setLineHeight(float lineHeight) { - mTextAttributes.setLineHeight(lineHeight); -diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java -index 7b5d0c1..c3032eb 100644 ---- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java -+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java -@@ -49,8 +49,8 @@ public abstract class ReactTextAnchorViewManager minimumFontSize -- && (mNumberOfLines != UNSET && layout.getLineCount() > mNumberOfLines -+ && (mMaxNumberOfLines != UNSET && layout.getLineCount() > mMaxNumberOfLines - || heightMode != YogaMeasureMode.UNDEFINED && layout.getHeight() > height)) { - // TODO: We could probably use a smarter algorithm here. This will require 0(n) - // measurements -@@ -124,9 +124,9 @@ public class ReactTextShadowNode extends ReactBaseTextShadowNode { - } - - final int lineCount = -- mNumberOfLines == UNSET -+ mMaxNumberOfLines == UNSET - ? layout.getLineCount() -- : Math.min(mNumberOfLines, layout.getLineCount()); -+ : Math.min(mMaxNumberOfLines, layout.getLineCount()); - - // Instead of using `layout.getWidth()` (which may yield a significantly larger width for - // text that is wrapping), compute width using the longest line. -diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java -index 190bc27..c2bcdc1 100644 ---- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java -+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java -@@ -87,7 +87,7 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie - - mReactBackgroundManager = new ReactViewBackgroundManager(this); - -- mNumberOfLines = ViewDefaults.NUMBER_OF_LINES; -+ mNumberOfLines = ViewDefaults.MAXIMUM_NUMBER_OF_LINES; - mAdjustsFontSizeToFit = false; - mLinkifyMaskType = 0; - mNotifyOnInlineViewLayout = false; -@@ -576,7 +576,7 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie - } - - public void setNumberOfLines(int numberOfLines) { -- mNumberOfLines = numberOfLines == 0 ? ViewDefaults.NUMBER_OF_LINES : numberOfLines; -+ mNumberOfLines = numberOfLines == 0 ? ViewDefaults.MAXIMUM_NUMBER_OF_LINES : numberOfLines; - setSingleLine(mNumberOfLines == 1); - setMaxLines(mNumberOfLines); - } -@@ -596,7 +596,7 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie - public void updateView() { - @Nullable - TextUtils.TruncateAt ellipsizeLocation = -- mNumberOfLines == ViewDefaults.NUMBER_OF_LINES || mAdjustsFontSizeToFit -+ mNumberOfLines == ViewDefaults.MAXIMUM_NUMBER_OF_LINES || mAdjustsFontSizeToFit - ? null - : mEllipsizeLocation; - setEllipsize(ellipsizeLocation); -diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java -index 561a2d0..9409cfc 100644 ---- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java -+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java -@@ -18,6 +18,7 @@ import android.text.SpannableStringBuilder; - import android.text.Spanned; - import android.text.StaticLayout; - import android.text.TextPaint; -+import android.text.TextUtils; - import android.util.LayoutDirection; - import android.util.LruCache; - import android.view.View; -@@ -65,6 +66,7 @@ public class TextLayoutManager { - private static final String TEXT_BREAK_STRATEGY_KEY = "textBreakStrategy"; - private static final String HYPHENATION_FREQUENCY_KEY = "android_hyphenationFrequency"; - private static final String MAXIMUM_NUMBER_OF_LINES_KEY = "maximumNumberOfLines"; -+ private static final String NUMBER_OF_LINES_KEY = "numberOfLines"; - private static final LruCache sSpannableCache = - new LruCache<>(spannableCacheSize); - private static final ConcurrentHashMap sTagToSpannableCache = -@@ -385,6 +387,48 @@ public class TextLayoutManager { - ? paragraphAttributes.getInt(MAXIMUM_NUMBER_OF_LINES_KEY) - : UNSET; - -+ int numberOfLines = -+ paragraphAttributes.hasKey(NUMBER_OF_LINES_KEY) -+ ? paragraphAttributes.getInt(NUMBER_OF_LINES_KEY) -+ : UNSET; -+ -+ int lines = layout.getLineCount(); -+ if (numberOfLines != UNSET && numberOfLines != 0 && numberOfLines >= lines && text.length() > 0) { -+ int numberOfEmptyLines = numberOfLines - lines; -+ SpannableStringBuilder ssb = new SpannableStringBuilder(); -+ -+ // for some reason a newline on end causes issues with computing height so we add a character -+ if (text.toString().endsWith("\n")) { -+ ssb.append("A"); -+ } -+ -+ for (int i = 0; i < numberOfEmptyLines; ++i) { -+ ssb.append("\nA"); -+ } -+ -+ Object[] spans = text.getSpans(0, 0, Object.class); -+ for (Object span : spans) { // It's possible we need to set exl-exl -+ ssb.setSpan(span, 0, ssb.length(), text.getSpanFlags(span)); -+ }; -+ -+ text = new SpannableStringBuilder(TextUtils.concat(text, ssb)); -+ boring = null; -+ layout = createLayout( -+ text, -+ boring, -+ width, -+ widthYogaMeasureMode, -+ includeFontPadding, -+ textBreakStrategy, -+ hyphenationFrequency); -+ } -+ -+ -+ if (numberOfLines != UNSET && numberOfLines != 0) { -+ maximumNumberOfLines = numberOfLines; -+ } -+ -+ - int calculatedLineCount = - maximumNumberOfLines == UNSET || maximumNumberOfLines == 0 - ? layout.getLineCount() -diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java -index 0d118f0..0ae44b7 100644 ---- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java -+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java -@@ -18,6 +18,7 @@ import android.text.SpannableStringBuilder; - import android.text.Spanned; - import android.text.StaticLayout; - import android.text.TextPaint; -+import android.text.TextUtils; - import android.util.LayoutDirection; - import android.util.LruCache; - import android.view.View; -@@ -61,6 +62,7 @@ public class TextLayoutManagerMapBuffer { - public static final short PA_KEY_ADJUST_FONT_SIZE_TO_FIT = 3; - public static final short PA_KEY_INCLUDE_FONT_PADDING = 4; - public static final short PA_KEY_HYPHENATION_FREQUENCY = 5; -+ public static final short PA_KEY_NUMBER_OF_LINES = 6; - - private static final boolean ENABLE_MEASURE_LOGGING = ReactBuildConfig.DEBUG && false; - -@@ -399,6 +401,47 @@ public class TextLayoutManagerMapBuffer { - ? paragraphAttributes.getInt(PA_KEY_MAX_NUMBER_OF_LINES) - : UNSET; - -+ int numberOfLines = -+ paragraphAttributes.contains(PA_KEY_NUMBER_OF_LINES) -+ ? paragraphAttributes.getInt(PA_KEY_NUMBER_OF_LINES) -+ : UNSET; -+ -+ int lines = layout.getLineCount(); -+ if (numberOfLines != UNSET && numberOfLines != 0 && numberOfLines > lines && text.length() > 0) { -+ int numberOfEmptyLines = numberOfLines - lines; -+ SpannableStringBuilder ssb = new SpannableStringBuilder(); -+ -+ // for some reason a newline on end causes issues with computing height so we add a character -+ if (text.toString().endsWith("\n")) { -+ ssb.append("A"); -+ } -+ -+ for (int i = 0; i < numberOfEmptyLines; ++i) { -+ ssb.append("\nA"); -+ } -+ -+ Object[] spans = text.getSpans(0, 0, Object.class); -+ for (Object span : spans) { // It's possible we need to set exl-exl -+ ssb.setSpan(span, 0, ssb.length(), text.getSpanFlags(span)); -+ }; -+ -+ text = new SpannableStringBuilder(TextUtils.concat(text, ssb)); -+ boring = null; -+ layout = createLayout( -+ text, -+ boring, -+ width, -+ widthYogaMeasureMode, -+ includeFontPadding, -+ textBreakStrategy, -+ hyphenationFrequency); -+ } -+ -+ if (numberOfLines != UNSET && numberOfLines != 0) { -+ maximumNumberOfLines = numberOfLines; -+ } -+ -+ - int calculatedLineCount = - maximumNumberOfLines == UNSET || maximumNumberOfLines == 0 - ? layout.getLineCount() -diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java -index ced37be..ef2f321 100644 ---- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java -+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java -@@ -548,7 +548,13 @@ public class ReactEditText extends AppCompatEditText - * href='https://android.googlesource.com/platform/frameworks/base/+/jb-release/core/java/android/widget/TextView.java'>TextView.java} - */ - if (isMultiline()) { -+ // we save max lines as setSingleLines overwrites it -+ // https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/TextView.java#10671 -+ int maxLines = getMaxLines(); - setSingleLine(false); -+ if (maxLines != -1) { -+ setMaxLines(maxLines); -+ } - } - - // We override the KeyListener so that all keys on the soft input keyboard as well as hardware -diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java -index a850510..c59be1d 100644 ---- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java -+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputLocalData.java -@@ -41,9 +41,9 @@ public final class ReactTextInputLocalData { - public void apply(EditText editText) { - editText.setText(mText); - editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); -+ editText.setInputType(mInputType); - editText.setMinLines(mMinLines); - editText.setMaxLines(mMaxLines); -- editText.setInputType(mInputType); - editText.setHint(mPlaceholder); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - editText.setBreakStrategy(mBreakStrategy); -diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java -index b27ace4..c6a2d63 100644 ---- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java -+++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java -@@ -737,9 +737,18 @@ public class ReactTextInputManager extends BaseViewManager= Build.VERSION_CODES.M -diff --git a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp -index 2994aca..fff0d5e 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp -+++ b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp -@@ -16,6 +16,7 @@ namespace facebook::react { - - bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { - return std::tie( -+ numberOfLines, - maximumNumberOfLines, - ellipsizeMode, - textBreakStrategy, -@@ -23,6 +24,7 @@ bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { - includeFontPadding, - android_hyphenationFrequency) == - std::tie( -+ rhs.numberOfLines, - rhs.maximumNumberOfLines, - rhs.ellipsizeMode, - rhs.textBreakStrategy, -@@ -42,6 +44,7 @@ bool ParagraphAttributes::operator!=(const ParagraphAttributes &rhs) const { - #if RN_DEBUG_STRING_CONVERTIBLE - SharedDebugStringConvertibleList ParagraphAttributes::getDebugProps() const { - return { -+ debugStringConvertibleItem("numberOfLines", numberOfLines), - debugStringConvertibleItem("maximumNumberOfLines", maximumNumberOfLines), - debugStringConvertibleItem("ellipsizeMode", ellipsizeMode), - debugStringConvertibleItem("textBreakStrategy", textBreakStrategy), -diff --git a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h -index f5f87c6..b7d1e90 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h -+++ b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h -@@ -30,6 +30,11 @@ class ParagraphAttributes : public DebugStringConvertible { - public: - #pragma mark - Fields - -+ /* -+ * Number of lines which paragraph takes. -+ */ -+ int numberOfLines{}; -+ - /* - * Maximum number of lines which paragraph can take. - * Zero value represents "no limit". -@@ -92,6 +97,7 @@ struct hash { - const facebook::react::ParagraphAttributes &attributes) const { - return folly::hash::hash_combine( - 0, -+ attributes.numberOfLines, - attributes.maximumNumberOfLines, - attributes.ellipsizeMode, - attributes.textBreakStrategy, -diff --git a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h -index 8687b89..eab75f4 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h -+++ b/node_modules/react-native/ReactCommon/react/renderer/attributedstring/conversions.h -@@ -835,10 +835,16 @@ inline ParagraphAttributes convertRawProp( - ParagraphAttributes const &defaultParagraphAttributes) { - auto paragraphAttributes = ParagraphAttributes{}; - -- paragraphAttributes.maximumNumberOfLines = convertRawProp( -+ paragraphAttributes.numberOfLines = convertRawProp( - context, - rawProps, - "numberOfLines", -+ sourceParagraphAttributes.numberOfLines, -+ defaultParagraphAttributes.numberOfLines); -+ paragraphAttributes.maximumNumberOfLines = convertRawProp( -+ context, -+ rawProps, -+ "maximumNumberOfLines", - sourceParagraphAttributes.maximumNumberOfLines, - defaultParagraphAttributes.maximumNumberOfLines); - paragraphAttributes.ellipsizeMode = convertRawProp( -@@ -913,6 +919,7 @@ inline std::string toString(AttributedString::Range const &range) { - inline folly::dynamic toDynamic( - const ParagraphAttributes ¶graphAttributes) { - auto values = folly::dynamic::object(); -+ values("numberOfLines", paragraphAttributes.numberOfLines); - values("maximumNumberOfLines", paragraphAttributes.maximumNumberOfLines); - values("ellipsizeMode", toString(paragraphAttributes.ellipsizeMode)); - values("textBreakStrategy", toString(paragraphAttributes.textBreakStrategy)); -@@ -1118,6 +1125,7 @@ constexpr static MapBuffer::Key PA_KEY_TEXT_BREAK_STRATEGY = 2; - constexpr static MapBuffer::Key PA_KEY_ADJUST_FONT_SIZE_TO_FIT = 3; - constexpr static MapBuffer::Key PA_KEY_INCLUDE_FONT_PADDING = 4; - constexpr static MapBuffer::Key PA_KEY_HYPHENATION_FREQUENCY = 5; -+constexpr static MapBuffer::Key PA_KEY_NUMBER_OF_LINES = 6; - - inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { - auto builder = MapBufferBuilder(); -@@ -1135,6 +1143,8 @@ inline MapBuffer toMapBuffer(const ParagraphAttributes ¶graphAttributes) { - builder.putString( - PA_KEY_HYPHENATION_FREQUENCY, - toString(paragraphAttributes.android_hyphenationFrequency)); -+ builder.putInt( -+ PA_KEY_NUMBER_OF_LINES, paragraphAttributes.numberOfLines); - - return builder.build(); - } -diff --git a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp -index 9953e22..98eb3da 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp -+++ b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp -@@ -56,6 +56,10 @@ AndroidTextInputProps::AndroidTextInputProps( - "numberOfLines", - sourceProps.numberOfLines, - {0})), -+ maximumNumberOfLines(CoreFeatures::enablePropIteratorSetter? sourceProps.maximumNumberOfLines : convertRawProp(context, rawProps, -+ "maximumNumberOfLines", -+ sourceProps.maximumNumberOfLines, -+ {0})), - disableFullscreenUI(CoreFeatures::enablePropIteratorSetter? sourceProps.disableFullscreenUI : convertRawProp(context, rawProps, - "disableFullscreenUI", - sourceProps.disableFullscreenUI, -@@ -281,6 +285,12 @@ void AndroidTextInputProps::setProp( - value, - paragraphAttributes, - maximumNumberOfLines, -+ "maximumNumberOfLines"); -+ REBUILD_FIELD_SWITCH_CASE( -+ paDefaults, -+ value, -+ paragraphAttributes, -+ numberOfLines, - "numberOfLines"); - REBUILD_FIELD_SWITCH_CASE( - paDefaults, value, paragraphAttributes, ellipsizeMode, "ellipsizeMode"); -@@ -323,6 +333,7 @@ void AndroidTextInputProps::setProp( - } - - switch (hash) { -+ RAW_SET_PROP_SWITCH_CASE_BASIC(maximumNumberOfLines); - RAW_SET_PROP_SWITCH_CASE_BASIC(autoComplete); - RAW_SET_PROP_SWITCH_CASE_BASIC(returnKeyLabel); - RAW_SET_PROP_SWITCH_CASE_BASIC(numberOfLines); -@@ -422,6 +433,7 @@ void AndroidTextInputProps::setProp( - // TODO T53300085: support this in codegen; this was hand-written - folly::dynamic AndroidTextInputProps::getDynamic() const { - folly::dynamic props = folly::dynamic::object(); -+ props["maximumNumberOfLines"] = maximumNumberOfLines; - props["autoComplete"] = autoComplete; - props["returnKeyLabel"] = returnKeyLabel; - props["numberOfLines"] = numberOfLines; -diff --git a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h -index ba39ebb..ead28e3 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h -+++ b/node_modules/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h -@@ -84,6 +84,7 @@ class AndroidTextInputProps final : public ViewProps, public BaseTextProps { - std::string autoComplete{}; - std::string returnKeyLabel{}; - int numberOfLines{0}; -+ int maximumNumberOfLines{0}; - bool disableFullscreenUI{false}; - std::string textBreakStrategy{}; - SharedColor underlineColorAndroid{}; -diff --git a/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm b/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm -index 368c334..a1bb33e 100644 ---- a/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm -+++ b/node_modules/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm -@@ -244,26 +244,51 @@ - (void)getRectWithAttributedString:(AttributedString)attributedString - - #pragma mark - Private - --- (NSTextStorage *)_textStorageForNSAttributesString:(NSAttributedString *)attributedString -++- (NSTextStorage *)_textStorageForNSAttributesString:(NSAttributedString *)inputAttributedString - paragraphAttributes:(ParagraphAttributes)paragraphAttributes - size:(CGSize)size - { -- NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:size]; -+ NSMutableAttributedString *attributedString = [ inputAttributedString mutableCopy]; -+ -+ /* -+ * The block below is responsible for setting the exact height of the view in lines -+ * Unfortunatelly, iOS doesn't export any easy way to do it. So we set maximumNumberOfLines -+ * prop and then add random lines at the front. However, they are only used for layout -+ * so they are not visible on the screen. This method is used for drawing only for Paragraph component -+ * but we set exact height in lines only on TextInput that doesn't use it. -+ */ -+ if (paragraphAttributes.numberOfLines) { -+ paragraphAttributes.maximumNumberOfLines = paragraphAttributes.numberOfLines; -+ NSMutableString *newLines = [NSMutableString stringWithCapacity: paragraphAttributes.numberOfLines]; -+ for (NSUInteger i = 0UL; i < paragraphAttributes.numberOfLines; ++i) { -+ // K is added on purpose. New line seems to be not enough for NTtextContainer -+ [newLines appendString:@"K\n"]; -+ } -+ NSDictionary * attributesOfFirstCharacter = [inputAttributedString attributesAtIndex:0 effectiveRange:NULL]; - -- textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5. -- textContainer.lineBreakMode = paragraphAttributes.maximumNumberOfLines > 0 -- ? RCTNSLineBreakModeFromEllipsizeMode(paragraphAttributes.ellipsizeMode) -- : NSLineBreakByClipping; -- textContainer.maximumNumberOfLines = paragraphAttributes.maximumNumberOfLines; -+ [attributedString insertAttributedString:[[NSAttributedString alloc] initWithString:newLines attributes:attributesOfFirstCharacter] atIndex:0]; -+ } -+ -+ NSTextContainer *textContainer = [NSTextContainer new]; - - NSLayoutManager *layoutManager = [NSLayoutManager new]; - layoutManager.usesFontLeading = NO; - [layoutManager addTextContainer:textContainer]; - -- NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString]; -+ NSTextStorage *textStorage = [NSTextStorage new]; - - [textStorage addLayoutManager:layoutManager]; - -+ textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5. -+ textContainer.lineBreakMode = paragraphAttributes.maximumNumberOfLines > 0 -+ ? RCTNSLineBreakModeFromEllipsizeMode(paragraphAttributes.ellipsizeMode) -+ : NSLineBreakByClipping; -+ textContainer.size = size; -+ textContainer.maximumNumberOfLines = paragraphAttributes.maximumNumberOfLines; -+ -+ [textStorage replaceCharactersInRange:(NSRange){0, textStorage.length} withAttributedString:attributedString]; -+ -+ - if (paragraphAttributes.adjustsFontSizeToFit) { - CGFloat minimumFontSize = !isnan(paragraphAttributes.minimumFontSize) ? paragraphAttributes.minimumFontSize : 4.0; - CGFloat maximumFontSize = !isnan(paragraphAttributes.maximumFontSize) ? paragraphAttributes.maximumFontSize : 96.0; From bd003728830a32ae638cdcb756813e604c7f477e Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 9 Jan 2024 14:31:32 +0100 Subject: [PATCH 27/34] remove empty line --- android/settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/settings.gradle b/android/settings.gradle index 40aefc6f2405..950ca5388131 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -18,4 +18,4 @@ include ':app' includeBuild('../node_modules/@react-native/gradle-plugin') apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle") -useExpoModules() +useExpoModules() \ No newline at end of file From 0384181fd7a473e7d83efe96fce9177e660a9892 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 9 Jan 2024 14:32:18 +0100 Subject: [PATCH 28/34] add back empty lien at EOF --- android/settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/settings.gradle b/android/settings.gradle index 950ca5388131..40aefc6f2405 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -18,4 +18,4 @@ include ':app' includeBuild('../node_modules/@react-native/gradle-plugin') apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle") -useExpoModules() \ No newline at end of file +useExpoModules() From d872300bcb879c4e9b447e116b74d539cd6c3e36 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Fri, 12 Jan 2024 17:18:14 +0100 Subject: [PATCH 29/34] remove empty line --- src/components/Composer/index.native.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/Composer/index.native.tsx b/src/components/Composer/index.native.tsx index c63a379ffeaa..c079091268ef 100644 --- a/src/components/Composer/index.native.tsx +++ b/src/components/Composer/index.native.tsx @@ -84,5 +84,4 @@ function Composer( } Composer.displayName = 'Composer'; - export default React.forwardRef(Composer); From 0bb8337928ef0d3a1dc216258116fd309abccc1d Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Fri, 12 Jan 2024 17:18:22 +0100 Subject: [PATCH 30/34] add empty line --- src/components/Composer/index.native.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Composer/index.native.tsx b/src/components/Composer/index.native.tsx index c079091268ef..c63a379ffeaa 100644 --- a/src/components/Composer/index.native.tsx +++ b/src/components/Composer/index.native.tsx @@ -84,4 +84,5 @@ function Composer( } Composer.displayName = 'Composer'; + export default React.forwardRef(Composer); From c3676a73facd197c57d2c64bd2e2cd910b42df99 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Fri, 12 Jan 2024 17:26:47 +0100 Subject: [PATCH 31/34] rename prop --- src/components/Composer/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index 19b7bb6bb30a..a38f120ff237 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -367,7 +367,7 @@ function Composer( /* eslint-disable-next-line react/jsx-props-no-spreading */ {...props} onSelectionChange={addCursorPositionToSelectionChange} - rows={numberOfLines} + numberOfLines={numberOfLines} disabled={isDisabled} onKeyPress={handleKeyPress} onFocus={(e) => { From f2fc0de7c68ac5e222cc408d0c3582c00dfdfc75 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 18 Jan 2024 16:09:49 +0100 Subject: [PATCH 32/34] revert rows prop change --- src/components/Composer/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index f3a471335f0d..3c2caf020ef7 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -368,7 +368,7 @@ function Composer( /* eslint-disable-next-line react/jsx-props-no-spreading */ {...props} onSelectionChange={addCursorPositionToSelectionChange} - numberOfLines={numberOfLines} + rows={numberOfLines} disabled={isDisabled} onKeyPress={handleKeyPress} onFocus={(e) => { From 8f5f879da515b998472f5cbd4ffdc33428e9fadb Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Fri, 19 Jan 2024 16:19:08 +0100 Subject: [PATCH 33/34] fix: prop --- src/components/Composer/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index 3c2caf020ef7..f3a471335f0d 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -368,7 +368,7 @@ function Composer( /* eslint-disable-next-line react/jsx-props-no-spreading */ {...props} onSelectionChange={addCursorPositionToSelectionChange} - rows={numberOfLines} + numberOfLines={numberOfLines} disabled={isDisabled} onKeyPress={handleKeyPress} onFocus={(e) => { From 706336a7a4d1396f44161b54822ba78b32c617f6 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 23 Jan 2024 17:24:21 +0100 Subject: [PATCH 34/34] update Podfile.lock --- ios/Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 776dcb544ee6..4cdf61554a6b 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1967,7 +1967,7 @@ SPEC CHECKSUMS: SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 Turf: 13d1a92d969ca0311bbc26e8356cca178ce95da2 VisionCamera: 7d13aae043ffb38b224a0f725d1e23ca9c190fe7 - Yoga: e64aa65de36c0832d04e8c7bd614396c77a80047 + Yoga: 13c8ef87792450193e117976337b8527b49e8c03 PODFILE CHECKSUM: 0ccbb4f2406893c6e9f266dc1e7470dcd72885d2