diff --git a/src/components/Composer/implementation/index.tsx b/src/components/Composer/implementation/index.tsx index 98ac9e00a98a9..5af76a2406b51 100755 --- a/src/components/Composer/implementation/index.tsx +++ b/src/components/Composer/implementation/index.tsx @@ -1,4 +1,5 @@ import type {MarkdownStyle} from '@expensify/react-native-live-markdown'; +import {useIsFocused} from '@react-navigation/native'; import lodashDebounce from 'lodash/debounce'; import type {BaseSyntheticEvent, ForwardedRef} from 'react'; import React, {useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; @@ -252,7 +253,8 @@ function Composer( // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps }, [isComposerFullSize]); - useHtmlPaste(textInput, handlePaste, true); + const isActive = useIsFocused(); + useHtmlPaste(textInput, handlePaste, isActive); useEffect(() => { setIsRendered(true); diff --git a/src/components/TextInput/BaseTextInput/index.native.tsx b/src/components/TextInput/BaseTextInput/index.native.tsx index cdfcb22f1f2c0..605fb284bf241 100644 --- a/src/components/TextInput/BaseTextInput/index.native.tsx +++ b/src/components/TextInput/BaseTextInput/index.native.tsx @@ -17,6 +17,7 @@ import Text from '@components/Text'; import * as styleConst from '@components/TextInput/styleConst'; import TextInputClearButton from '@components/TextInput/TextInputClearButton'; import TextInputLabel from '@components/TextInput/TextInputLabel'; +import useHtmlPaste from '@hooks/useHtmlPaste'; import useLocalize from '@hooks/useLocalize'; import useMarkdownStyle from '@hooks/useMarkdownStyle'; import useStyleUtils from '@hooks/useStyleUtils'; @@ -99,6 +100,8 @@ function BaseTextInput( const input = useRef(null); const isLabelActive = useRef(initialActiveLabel); + useHtmlPaste(input, undefined, isMarkdownEnabled); + // AutoFocus which only works on mount: useEffect(() => { // We are manually managing focus to prevent this issue: https://github.com/Expensify/App/issues/4514 diff --git a/src/components/TextInput/BaseTextInput/index.tsx b/src/components/TextInput/BaseTextInput/index.tsx index 00675ca4ccd6c..45aa868ad2199 100644 --- a/src/components/TextInput/BaseTextInput/index.tsx +++ b/src/components/TextInput/BaseTextInput/index.tsx @@ -1,7 +1,7 @@ import {Str} from 'expensify-common'; -import type {ForwardedRef} from 'react'; +import type {ForwardedRef, MutableRefObject} from 'react'; import React, {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import type {GestureResponderEvent, LayoutChangeEvent, NativeSyntheticEvent, StyleProp, TextInputFocusEventData, ViewStyle} from 'react-native'; +import type {GestureResponderEvent, LayoutChangeEvent, NativeSyntheticEvent, StyleProp, TextInput, TextInputFocusEventData, ViewStyle} from 'react-native'; import {ActivityIndicator, StyleSheet, View} from 'react-native'; import {useSharedValue, withSpring} from 'react-native-reanimated'; import Checkbox from '@components/Checkbox'; @@ -18,6 +18,7 @@ import Text from '@components/Text'; import * as styleConst from '@components/TextInput/styleConst'; import TextInputClearButton from '@components/TextInput/TextInputClearButton'; import TextInputLabel from '@components/TextInput/TextInputLabel'; +import useHtmlPaste from '@hooks/useHtmlPaste'; import useLocalize from '@hooks/useLocalize'; import useMarkdownStyle from '@hooks/useMarkdownStyle'; import useStyleUtils from '@hooks/useStyleUtils'; @@ -107,6 +108,8 @@ function BaseTextInput( const isLabelActive = useRef(initialActiveLabel); const didScrollToEndRef = useRef(false); + useHtmlPaste(input as MutableRefObject, undefined, isMarkdownEnabled); + // AutoFocus which only works on mount: useEffect(() => { // We are manually managing focus to prevent this issue: https://github.com/Expensify/App/issues/4514 diff --git a/src/hooks/useHtmlPaste/index.ts b/src/hooks/useHtmlPaste/index.ts index ebffbf1b54b6e..1a7e62f3141e7 100644 --- a/src/hooks/useHtmlPaste/index.ts +++ b/src/hooks/useHtmlPaste/index.ts @@ -1,4 +1,3 @@ -import {useNavigation} from '@react-navigation/native'; import {useCallback, useEffect} from 'react'; import Parser from '@libs/Parser'; import CONST from '@src/CONST'; @@ -38,9 +37,7 @@ const insertAtCaret = (target: HTMLElement, insertedText: string, maxLength: num } }; -const useHtmlPaste: UseHtmlPaste = (textInputRef, preHtmlPasteCallback, removeListenerOnScreenBlur = false, maxLength = CONST.MAX_COMMENT_LENGTH + 1) => { - const navigation = useNavigation(); - +const useHtmlPaste: UseHtmlPaste = (textInputRef, preHtmlPasteCallback, isActive = false, maxLength = CONST.MAX_COMMENT_LENGTH + 1) => { /** * Set pasted text to clipboard * @param {String} text @@ -145,27 +142,16 @@ const useHtmlPaste: UseHtmlPaste = (textInputRef, preHtmlPasteCallback, removeLi ); useEffect(() => { - // we need to re-register listener on navigation focus/blur if the component (like Composer) is not unmounting - // when navigating away to different screen (report) to avoid paste event on other screen being wrongly handled - // by current screen paste listener - let unsubscribeFocus: () => void; - let unsubscribeBlur: () => void; - if (removeListenerOnScreenBlur) { - unsubscribeFocus = navigation.addListener('focus', () => document.addEventListener('paste', handlePaste, true)); - unsubscribeBlur = navigation.addListener('blur', () => document.removeEventListener('paste', handlePaste, true)); + if (!isActive) { + return; } - document.addEventListener('paste', handlePaste, true); return () => { - if (removeListenerOnScreenBlur) { - unsubscribeFocus(); - unsubscribeBlur(); - } document.removeEventListener('paste', handlePaste, true); }; // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps - }, []); + }, [isActive]); }; export default useHtmlPaste; diff --git a/src/hooks/useHtmlPaste/types.ts b/src/hooks/useHtmlPaste/types.ts index 0aaa12a49ac9f..65778463f80ec 100644 --- a/src/hooks/useHtmlPaste/types.ts +++ b/src/hooks/useHtmlPaste/types.ts @@ -4,7 +4,7 @@ import type {TextInput} from 'react-native'; type UseHtmlPaste = ( textInputRef: MutableRefObject<(HTMLTextAreaElement & TextInput) | TextInput | null>, preHtmlPasteCallback?: (event: ClipboardEvent) => boolean, - removeListenerOnScreenBlur?: boolean, + isActive?: boolean, maxLength?: number, // Maximum length of the text input value after pasting ) => void; diff --git a/src/pages/PrivateNotes/PrivateNotesEditPage.tsx b/src/pages/PrivateNotes/PrivateNotesEditPage.tsx index a0370ef6cbbdc..4d084cfa924d2 100644 --- a/src/pages/PrivateNotes/PrivateNotesEditPage.tsx +++ b/src/pages/PrivateNotes/PrivateNotesEditPage.tsx @@ -12,7 +12,6 @@ import type {AnimatedTextInputRef} from '@components/RNTextInput'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; -import useHtmlPaste from '@hooks/useHtmlPaste'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; @@ -66,8 +65,6 @@ function PrivateNotesEditPage({route, report, accountID}: PrivateNotesEditPagePr const privateNotesInput = useRef(null); const focusTimeoutRef = useRef(null); - useHtmlPaste(privateNotesInput); - useFocusEffect( useCallback(() => { focusTimeoutRef.current = setTimeout(() => {