From 02b2315b9e91a1b96800045c82d23bedb018b164 Mon Sep 17 00:00:00 2001 From: ntdiary <2471314@gmail.com> Date: Tue, 16 Apr 2024 22:56:51 +0800 Subject: [PATCH 1/2] clean up mobile safari code --- src/libs/updateMultilineInputRange/index.ts | 11 ++---- .../report/ReportActionItemMessageEdit.tsx | 35 ++++--------------- 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/src/libs/updateMultilineInputRange/index.ts b/src/libs/updateMultilineInputRange/index.ts index f5d71c5e2038..d0bc1c306dac 100644 --- a/src/libs/updateMultilineInputRange/index.ts +++ b/src/libs/updateMultilineInputRange/index.ts @@ -1,4 +1,3 @@ -import * as Browser from '@libs/Browser'; import type UpdateMultilineInputRange from './types'; /** @@ -17,14 +16,10 @@ const updateMultilineInputRange: UpdateMultilineInputRange = (input, shouldAutoF if ('value' in input && input.value && input.setSelectionRange) { const length = input.value.length; - - // For mobile Safari, updating the selection prop on an unfocused input will cause it to automatically gain focus - // and subsequent programmatic focus shifts (e.g., modal focus trap) to show the blue frame (:focus-visible style), - // so we need to ensure that it is only updated after focus. - const shouldSetSelection = !(Browser.isMobileSafari() && !shouldAutoFocus); - if (shouldSetSelection) { - input.setSelectionRange(length, length); + if (!shouldAutoFocus) { + return; } + input.setSelectionRange(length, length); // eslint-disable-next-line no-param-reassign input.scrollTop = input.scrollHeight; } diff --git a/src/pages/home/report/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx index fc3c92434fc4..8920f789e167 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx @@ -22,7 +22,6 @@ import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; -import * as Browser from '@libs/Browser'; import * as ComposerUtils from '@libs/ComposerUtils'; import * as EmojiUtils from '@libs/EmojiUtils'; import focusComposerWithDelay from '@libs/focusComposerWithDelay'; @@ -68,7 +67,6 @@ type ReportActionItemMessageEditProps = { const emojiButtonID = 'emojiButton'; const messageEditInput = 'messageEditInput'; -const isMobileSafari = Browser.isMobileSafari(); const shouldUseForcedSelectionRange = shouldUseEmojiPickerSelection(); function ReportActionItemMessageEdit( @@ -84,14 +82,6 @@ function ReportActionItemMessageEdit( const {isSmallScreenWidth} = useWindowDimensions(); const prevDraftMessage = usePrevious(draftMessage); - const getInitialSelection = () => { - if (isMobileSafari) { - return {start: 0, end: 0}; - } - - const length = draftMessage.length; - return {start: length, end: length}; - }; const emojisPresentBefore = useRef([]); const [draft, setDraft] = useState(() => { if (draftMessage) { @@ -99,7 +89,7 @@ function ReportActionItemMessageEdit( } return draftMessage; }); - const [selection, setSelection] = useState(getInitialSelection); + const [selection, setSelection] = useState({start: 0, end: 0}); const [isFocused, setIsFocused] = useState(false); const {hasExceededMaxCommentLength, validateCommentMaxLength} = useHandleExceedMaxCommentLength(); const [modal, setModal] = useState({ @@ -171,23 +161,10 @@ function ReportActionItemMessageEdit( ); useEffect(() => { - // For mobile Safari, updating the selection prop on an unfocused input will cause it to automatically gain focus - // and subsequent programmatic focus shifts (e.g., modal focus trap) to show the blue frame (:focus-visible style), - // so we need to ensure that it is only updated after focus. - if (isMobileSafari) { - setDraft((prevDraft) => { - setSelection({ - start: prevDraft.length, - end: prevDraft.length, - }); - return prevDraft; - }); - - // Scroll content of textInputRef to bottom - if (textInputRef.current) { - textInputRef.current.scrollTop = textInputRef.current.scrollHeight; - } - } + setSelection({ + start: draftMessage.length, + end: draftMessage.length, + }); return () => { InputFocus.callback(() => setIsFocused(false)); @@ -208,7 +185,7 @@ function ReportActionItemMessageEdit( // Show the main composer when the focused message is deleted from another client // to prevent the main composer stays hidden until we swtich to another chat. setShouldShowComposeInputKeyboardAware(true); - }; + } // eslint-disable-next-line react-hooks/exhaustive-deps -- this cleanup needs to be called only on unmount }, [action.reportActionID]); From f1b18c3aed1739881beef486e46201602a8b54b6 Mon Sep 17 00:00:00 2001 From: ntdiary <2471314@gmail.com> Date: Fri, 3 May 2024 00:51:49 +0800 Subject: [PATCH 2/2] update selection --- src/libs/updateMultilineInputRange/index.ts | 5 ++--- .../home/report/ReportActionItemMessageEdit.tsx | 16 ++++++---------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/libs/updateMultilineInputRange/index.ts b/src/libs/updateMultilineInputRange/index.ts index d0bc1c306dac..a0ad76096922 100644 --- a/src/libs/updateMultilineInputRange/index.ts +++ b/src/libs/updateMultilineInputRange/index.ts @@ -16,10 +16,9 @@ const updateMultilineInputRange: UpdateMultilineInputRange = (input, shouldAutoF if ('value' in input && input.value && input.setSelectionRange) { const length = input.value.length; - if (!shouldAutoFocus) { - return; + if (shouldAutoFocus) { + input.setSelectionRange(length, length); } - input.setSelectionRange(length, length); // eslint-disable-next-line no-param-reassign input.scrollTop = input.scrollHeight; } diff --git a/src/pages/home/report/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx index 3d7305cdb168..eda3264b1824 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx @@ -89,7 +89,7 @@ function ReportActionItemMessageEdit( } return draftMessage; }); - const [selection, setSelection] = useState({start: 0, end: 0}); + const [selection, setSelection] = useState({start: draft.length, end: draft.length}); const [isFocused, setIsFocused] = useState(false); const {hasExceededMaxCommentLength, validateCommentMaxLength} = useHandleExceedMaxCommentLength(); const [modal, setModal] = useState({ @@ -160,13 +160,8 @@ function ReportActionItemMessageEdit( [action.reportActionID], ); - useEffect(() => { - setSelection({ - start: draftMessage.length, - end: draftMessage.length, - }); - - return () => { + useEffect( + () => () => { InputFocus.callback(() => setIsFocused(false)); InputFocus.inputFocusChange(false); @@ -185,9 +180,10 @@ function ReportActionItemMessageEdit( // Show the main composer when the focused message is deleted from another client // to prevent the main composer stays hidden until we swtich to another chat. setShouldShowComposeInputKeyboardAware(true); - } + }, // eslint-disable-next-line react-hooks/exhaustive-deps -- this cleanup needs to be called only on unmount - }, [action.reportActionID]); + [action.reportActionID], + ); // show the composer after editing is complete for devices that hide the composer during editing. useEffect(() => () => ComposerActions.setShouldShowComposeInput(true), []);