From b421b4eb1f634005b5103d7019d1a3c44f86a96f Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Sun, 3 Dec 2023 13:27:50 +0700 Subject: [PATCH 1/5] #19642 fix scroll on vitual view when keyboard open --- src/components/Composer/index.js | 16 +++++++++-- src/hooks/useScrollBarVisible/index.native.ts | 7 +++++ src/hooks/useScrollBarVisible/index.ts | 28 +++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/hooks/useScrollBarVisible/index.native.ts create mode 100644 src/hooks/useScrollBarVisible/index.ts diff --git a/src/components/Composer/index.js b/src/components/Composer/index.js index 4bb3df5c1b85..9bb849f23af6 100755 --- a/src/components/Composer/index.js +++ b/src/components/Composer/index.js @@ -8,6 +8,7 @@ import RNTextInput from '@components/RNTextInput'; import Text from '@components/Text'; import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import withNavigation from '@components/withNavigation'; +import useScrollBarVisible from '@hooks/useScrollBarVisible'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as Browser from '@libs/Browser'; import compose from '@libs/compose'; @@ -180,6 +181,7 @@ function Composer({ const [caretContent, setCaretContent] = useState(''); const [valueBeforeCaret, setValueBeforeCaret] = useState(''); const [textInputWidth, setTextInputWidth] = useState(''); + const isScrollBarVisible = useScrollBarVisible(textInput, value); useEffect(() => { if (!shouldClear) { @@ -418,18 +420,26 @@ function Composer({ ); - const inputStyleMemo = useMemo( - () => [ + const scrollStyleMemo = useMemo(() => { + if (Browser.isMobileSafari()) { + return isScrollBarVisible ? [styles.overflowScroll, styles.overscrollBehaviorContain] : styles.overflowHidden; + } + return [ // We are hiding the scrollbar to prevent it from reducing the text input width, // so we can get the correct scroll height while calculating the number of lines. numberOfLines < maxLines ? styles.overflowHidden : {}, + ]; + }, [isScrollBarVisible, maxLines, numberOfLines, styles.overflowHidden, styles.overflowScroll, styles.overscrollBehaviorContain]); + const inputStyleMemo = useMemo( + () => [ StyleSheet.flatten([style, {outline: 'none'}]), StyleUtils.getComposeTextAreaPadding(numberOfLines, isComposerFullSize), Browser.isMobileSafari() || Browser.isSafari() ? styles.rtlTextRenderForSafari : {}, + scrollStyleMemo, ], - [numberOfLines, maxLines, styles.overflowHidden, styles.rtlTextRenderForSafari, style, StyleUtils, isComposerFullSize], + [numberOfLines, scrollStyleMemo, styles.rtlTextRenderForSafari, style, StyleUtils, isComposerFullSize], ); return ( diff --git a/src/hooks/useScrollBarVisible/index.native.ts b/src/hooks/useScrollBarVisible/index.native.ts new file mode 100644 index 000000000000..37df393cbc6e --- /dev/null +++ b/src/hooks/useScrollBarVisible/index.native.ts @@ -0,0 +1,7 @@ +/** + * Native doesn't have the DOM, so we just return null. + * + */ +const useScrollBarVisible = () => null; + +export default useScrollBarVisible; diff --git a/src/hooks/useScrollBarVisible/index.ts b/src/hooks/useScrollBarVisible/index.ts new file mode 100644 index 000000000000..91ccf0d7ba8b --- /dev/null +++ b/src/hooks/useScrollBarVisible/index.ts @@ -0,0 +1,28 @@ +import {useCallback, useEffect, useState} from 'react'; + +const useScrollBarVisible = (ref: React.RefObject, value: string) => { + const [isScrollBarVisible, setIsScrollBarVisible] = useState(false); + + const handleResize = useCallback(() => { + if (!ref.current) { + return; + } + const {scrollHeight, clientHeight} = ref.current; + setIsScrollBarVisible(scrollHeight > clientHeight); + }, [ref]); + + useEffect(() => { + if (!ref.current || !('ResizeObserver' in (window || {}))) { + return; + } + + const resizeObserver = new ResizeObserver(handleResize); + resizeObserver.observe(ref.current); + return () => { + resizeObserver.disconnect(); + }; + }, [handleResize, ref, value]); + return isScrollBarVisible; +}; + +export default useScrollBarVisible; From ae6ffbaca5a68cd46d03db73d0e28775927e8f30 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Tue, 12 Dec 2023 22:55:25 +0700 Subject: [PATCH 2/5] add shouldScrollContain props for composer --- src/components/Composer/index.js | 9 +++++++-- .../ComposerWithSuggestions/ComposerWithSuggestions.js | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/Composer/index.js b/src/components/Composer/index.js index 9bb849f23af6..f152573645d1 100755 --- a/src/components/Composer/index.js +++ b/src/components/Composer/index.js @@ -87,6 +87,9 @@ const propTypes = { /** Whether the sull composer is open */ isComposerFullSize: PropTypes.bool, + /** Should set scroll behavior is contain for composer */ + shouldScrollContain: PropTypes.bool, + ...withLocalizePropTypes, }; @@ -114,6 +117,7 @@ const defaultProps = { checkComposerVisibility: () => false, isReportActionCompose: false, isComposerFullSize: false, + shouldScrollContain: false, }; /** @@ -165,6 +169,7 @@ function Composer({ selection: selectionProp, isReportActionCompose, isComposerFullSize, + shouldScrollContain, ...props }) { const theme = useTheme(); @@ -421,7 +426,7 @@ function Composer({ ); const scrollStyleMemo = useMemo(() => { - if (Browser.isMobileSafari()) { + if (shouldScrollContain) { return isScrollBarVisible ? [styles.overflowScroll, styles.overscrollBehaviorContain] : styles.overflowHidden; } return [ @@ -429,7 +434,7 @@ function Composer({ // so we can get the correct scroll height while calculating the number of lines. numberOfLines < maxLines ? styles.overflowHidden : {}, ]; - }, [isScrollBarVisible, maxLines, numberOfLines, styles.overflowHidden, styles.overflowScroll, styles.overscrollBehaviorContain]); + }, [shouldScrollContain, isScrollBarVisible, maxLines, numberOfLines, styles.overflowHidden, styles.overflowScroll, styles.overscrollBehaviorContain]); const inputStyleMemo = useMemo( () => [ diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js index f5a321f72799..4bd600c761bf 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js @@ -10,6 +10,7 @@ import useDebounce from '@hooks/useDebounce'; import useLocalize from '@hooks/useLocalize'; import usePrevious from '@hooks/usePrevious'; import useWindowDimensions from '@hooks/useWindowDimensions'; +import * as Browser from '@libs/Browser'; import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus'; import compose from '@libs/compose'; import * as ComposerUtils from '@libs/ComposerUtils'; @@ -556,6 +557,7 @@ function ComposerWithSuggestions({ setComposerHeight(composerLayoutHeight); }} onScroll={hideSuggestionMenu} + shouldScrollContain={Browser.isMobileSafari()} /> From 83a1e4c80bbd3a796a10675eb0c5145848bb508c Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Wed, 13 Dec 2023 01:51:24 +0700 Subject: [PATCH 3/5] update naming code review --- src/components/Composer/index.js | 16 ++++++++-------- src/hooks/useIsScrollBarVisible/index.native.ts | 7 +++++++ .../index.ts | 4 ++-- src/hooks/useScrollBarVisible/index.native.ts | 7 ------- .../ComposerWithSuggestions.js | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) create mode 100644 src/hooks/useIsScrollBarVisible/index.native.ts rename src/hooks/{useScrollBarVisible => useIsScrollBarVisible}/index.ts (83%) delete mode 100644 src/hooks/useScrollBarVisible/index.native.ts diff --git a/src/components/Composer/index.js b/src/components/Composer/index.js index f152573645d1..713439671162 100755 --- a/src/components/Composer/index.js +++ b/src/components/Composer/index.js @@ -8,7 +8,7 @@ import RNTextInput from '@components/RNTextInput'; import Text from '@components/Text'; import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; import withNavigation from '@components/withNavigation'; -import useScrollBarVisible from '@hooks/useScrollBarVisible'; +import useIsScrollBarVisible from '@hooks/useIsScrollBarVisible'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as Browser from '@libs/Browser'; import compose from '@libs/compose'; @@ -87,8 +87,8 @@ const propTypes = { /** Whether the sull composer is open */ isComposerFullSize: PropTypes.bool, - /** Should set scroll behavior is contain for composer */ - shouldScrollContain: PropTypes.bool, + /** Should make the input only scroll inside the element avoid scroll out to parent */ + shouldContainScroll: PropTypes.bool, ...withLocalizePropTypes, }; @@ -117,7 +117,7 @@ const defaultProps = { checkComposerVisibility: () => false, isReportActionCompose: false, isComposerFullSize: false, - shouldScrollContain: false, + shouldContainScroll: false, }; /** @@ -169,7 +169,7 @@ function Composer({ selection: selectionProp, isReportActionCompose, isComposerFullSize, - shouldScrollContain, + shouldContainScroll, ...props }) { const theme = useTheme(); @@ -186,7 +186,7 @@ function Composer({ const [caretContent, setCaretContent] = useState(''); const [valueBeforeCaret, setValueBeforeCaret] = useState(''); const [textInputWidth, setTextInputWidth] = useState(''); - const isScrollBarVisible = useScrollBarVisible(textInput, value); + const isScrollBarVisible = useIsScrollBarVisible(textInput, value); useEffect(() => { if (!shouldClear) { @@ -426,7 +426,7 @@ function Composer({ ); const scrollStyleMemo = useMemo(() => { - if (shouldScrollContain) { + if (shouldContainScroll) { return isScrollBarVisible ? [styles.overflowScroll, styles.overscrollBehaviorContain] : styles.overflowHidden; } return [ @@ -434,7 +434,7 @@ function Composer({ // so we can get the correct scroll height while calculating the number of lines. numberOfLines < maxLines ? styles.overflowHidden : {}, ]; - }, [shouldScrollContain, isScrollBarVisible, maxLines, numberOfLines, styles.overflowHidden, styles.overflowScroll, styles.overscrollBehaviorContain]); + }, [shouldContainScroll, isScrollBarVisible, maxLines, numberOfLines, styles.overflowHidden, styles.overflowScroll, styles.overscrollBehaviorContain]); const inputStyleMemo = useMemo( () => [ diff --git a/src/hooks/useIsScrollBarVisible/index.native.ts b/src/hooks/useIsScrollBarVisible/index.native.ts new file mode 100644 index 000000000000..a461e1b7b074 --- /dev/null +++ b/src/hooks/useIsScrollBarVisible/index.native.ts @@ -0,0 +1,7 @@ +/** + * Native doesn't have the DOM, so we just return null. + * + */ +const useIsScrollBarVisible = () => null; + +export default useIsScrollBarVisible; diff --git a/src/hooks/useScrollBarVisible/index.ts b/src/hooks/useIsScrollBarVisible/index.ts similarity index 83% rename from src/hooks/useScrollBarVisible/index.ts rename to src/hooks/useIsScrollBarVisible/index.ts index 91ccf0d7ba8b..4ab3a7bb24db 100644 --- a/src/hooks/useScrollBarVisible/index.ts +++ b/src/hooks/useIsScrollBarVisible/index.ts @@ -1,6 +1,6 @@ import {useCallback, useEffect, useState} from 'react'; -const useScrollBarVisible = (ref: React.RefObject, value: string) => { +const useIsScrollBarVisible = (ref: React.RefObject, value: string) => { const [isScrollBarVisible, setIsScrollBarVisible] = useState(false); const handleResize = useCallback(() => { @@ -25,4 +25,4 @@ const useScrollBarVisible = (ref: React.RefObject null; - -export default useScrollBarVisible; diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js index 4bd600c761bf..2ff7506b50a8 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js @@ -557,7 +557,7 @@ function ComposerWithSuggestions({ setComposerHeight(composerLayoutHeight); }} onScroll={hideSuggestionMenu} - shouldScrollContain={Browser.isMobileSafari()} + shouldContainScroll={Browser.isMobileSafari()} /> From 9c694f48e1fd9880d1b5ef54f313ba00843ef7bb Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Wed, 13 Dec 2023 07:11:02 +0500 Subject: [PATCH 4/5] feat: add a new permission for reportFields --- src/CONST.ts | 1 + src/libs/Permissions.ts | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index 6f1fe37f661d..692ac1dfdf69 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -252,6 +252,7 @@ const CONST = { BETA_COMMENT_LINKING: 'commentLinking', POLICY_ROOMS: 'policyRooms', VIOLATIONS: 'violations', + REPORT_FIELDS: 'reportFields', }, BUTTON_STATES: { DEFAULT: 'default', diff --git a/src/libs/Permissions.ts b/src/libs/Permissions.ts index 43e7ef9fbbc8..9cde613ebb5a 100644 --- a/src/libs/Permissions.ts +++ b/src/libs/Permissions.ts @@ -18,6 +18,10 @@ function canUseCommentLinking(betas: OnyxEntry): boolean { return !!betas?.includes(CONST.BETAS.BETA_COMMENT_LINKING) || canUseAllBetas(betas); } +function canUseReportFields(betas: OnyxEntry): boolean { + return !!betas?.includes(CONST.BETAS.REPORT_FIELDS) || canUseAllBetas(betas); +} + /** * We're requiring you to be added to the policy rooms beta on dev, * since contributors have been reporting a number of false issues related to the feature being under development. @@ -45,4 +49,5 @@ export default { canUsePolicyRooms, canUseLinkPreviews, canUseViolations, + canUseReportFields, }; From c28008be0177bcf7fc87db32d3e05048ecb9eb17 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Wed, 13 Dec 2023 15:04:41 +0000 Subject: [PATCH 5/5] fix: upgrade electron-serve from 1.1.0 to 1.2.0 Snyk has created this PR to upgrade electron-serve from 1.1.0 to 1.2.0. See this package in npm: https://www.npmjs.com/package/electron-serve See this project in Snyk: https://app.snyk.io/org/expensify/project/9535b87d-14b8-434b-873d-3a25a2cba0bc?utm_source=github&utm_medium=referral&page=upgrade-pr --- desktop/package-lock.json | 20 +++++++++++++------- desktop/package.json | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/desktop/package-lock.json b/desktop/package-lock.json index bfeb58ceec05..39b186beb022 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -9,7 +9,7 @@ "dependencies": { "electron-context-menu": "^2.3.0", "electron-log": "^4.4.7", - "electron-serve": "^1.0.0", + "electron-serve": "^1.2.0", "electron-updater": "^6.1.6", "node-machine-id": "^1.1.12" } @@ -145,9 +145,15 @@ "integrity": "sha512-uFZQdgevOp9Fn5lDOrJMU/bmmYxDLZitbIHJM7VXN+cpB59ZnPt1FQL4bOf/Dl2gaIMPYJEfXx38GvJma5iV6A==" }, "node_modules/electron-serve": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/electron-serve/-/electron-serve-1.1.0.tgz", - "integrity": "sha512-tQJBCbXKoKCfkBC143QCqnEtT1s8dNE2V+b/82NF6lxnGO/2Q3a3GSLHtKl3iEDQgdzTf9pH7p418xq2rXbz1Q==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/electron-serve/-/electron-serve-1.2.0.tgz", + "integrity": "sha512-zJG3wisMrDn2G/gnjrhyB074COvly1FnS0U7Edm8bfXLB8MYX7UtwR9/y2LkFreYjzQHm9nEbAfgCmF+9M9LHQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/electron-updater": { "version": "6.1.6", @@ -530,9 +536,9 @@ "integrity": "sha512-uFZQdgevOp9Fn5lDOrJMU/bmmYxDLZitbIHJM7VXN+cpB59ZnPt1FQL4bOf/Dl2gaIMPYJEfXx38GvJma5iV6A==" }, "electron-serve": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/electron-serve/-/electron-serve-1.1.0.tgz", - "integrity": "sha512-tQJBCbXKoKCfkBC143QCqnEtT1s8dNE2V+b/82NF6lxnGO/2Q3a3GSLHtKl3iEDQgdzTf9pH7p418xq2rXbz1Q==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/electron-serve/-/electron-serve-1.2.0.tgz", + "integrity": "sha512-zJG3wisMrDn2G/gnjrhyB074COvly1FnS0U7Edm8bfXLB8MYX7UtwR9/y2LkFreYjzQHm9nEbAfgCmF+9M9LHQ==" }, "electron-updater": { "version": "6.1.6", diff --git a/desktop/package.json b/desktop/package.json index a6b92bde81c4..7689c18f0dbd 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -6,7 +6,7 @@ "dependencies": { "electron-context-menu": "^2.3.0", "electron-log": "^4.4.7", - "electron-serve": "^1.0.0", + "electron-serve": "^1.2.0", "electron-updater": "^6.1.6", "node-machine-id": "^1.1.12" },