From 17fc54ba261e4a44096eaeca318d56d216a5b173 Mon Sep 17 00:00:00 2001 From: daledah Date: Mon, 9 Dec 2024 22:04:45 +0700 Subject: [PATCH 1/2] fix: enable paste html in compose box and fix regressions --- .../Composer/implementation/index.tsx | 4 +++- .../TextInput/BaseTextInput/index.native.tsx | 3 +++ .../TextInput/BaseTextInput/index.tsx | 7 +++++-- src/hooks/useHtmlPaste/index.ts | 21 +++++-------------- src/hooks/useHtmlPaste/types.ts | 2 +- .../PrivateNotes/PrivateNotesEditPage.tsx | 3 --- 6 files changed, 17 insertions(+), 23 deletions(-) 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 9de6b6dd6d089..58b67ccd30081 100644 --- a/src/components/TextInput/BaseTextInput/index.native.tsx +++ b/src/components/TextInput/BaseTextInput/index.native.tsx @@ -16,6 +16,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 e36ae60255fc1..3372eefc6ee8a 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, Animated, StyleSheet, View} from 'react-native'; import Checkbox from '@components/Checkbox'; import FormHelpMessage from '@components/FormHelpMessage'; @@ -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'; @@ -104,6 +105,8 @@ function BaseTextInput( const input = useRef(null); const isLabelActive = useRef(initialActiveLabel); + 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 6199a36abdcab..fd0f1cabbe675 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 type UseHtmlPaste from './types'; @@ -27,9 +26,7 @@ const insertAtCaret = (target: HTMLElement, text: string) => { } }; -const useHtmlPaste: UseHtmlPaste = (textInputRef, preHtmlPasteCallback, removeListenerOnScreenBlur = false) => { - const navigation = useNavigation(); - +const useHtmlPaste: UseHtmlPaste = (textInputRef, preHtmlPasteCallback, isActive = false) => { /** * Set pasted text to clipboard * @param {String} text @@ -129,27 +126,19 @@ const useHtmlPaste: UseHtmlPaste = (textInputRef, preHtmlPasteCallback, removeLi ); useEffect(() => { + if (!isActive) { + return; + } // 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)); - } - 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 305ebe5fbd0fe..c73be9be9d5ad 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, ) => void; export default UseHtmlPaste; 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(() => { From ba9f86adb2f7e96e6a6f9b39ea695abf03f88eb6 Mon Sep 17 00:00:00 2001 From: daledah Date: Mon, 9 Dec 2024 22:45:45 +0700 Subject: [PATCH 2/2] fix: lint --- src/hooks/useHtmlPaste/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hooks/useHtmlPaste/index.ts b/src/hooks/useHtmlPaste/index.ts index fd0f1cabbe675..7a2670d140c10 100644 --- a/src/hooks/useHtmlPaste/index.ts +++ b/src/hooks/useHtmlPaste/index.ts @@ -3,6 +3,7 @@ import Parser from '@libs/Parser'; import type UseHtmlPaste from './types'; const insertByCommand = (text: string) => { + // eslint-disable-next-line deprecation/deprecation document.execCommand('insertText', false, text); };