From 8b23d6a945954691acba64e4e83ff72229266b89 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Thu, 28 Mar 2024 23:42:56 +0700 Subject: [PATCH 1/6] 39061 adjust virtual viewport with smart app banner --- src/CONST.ts | 1 + src/hooks/useViewportOffsetTop/index.ts | 40 ++++++++++++++++++------- src/pages/home/ReportScreen.tsx | 3 +- web/index.html | 1 + 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index c57ac575f7e6..d6504abfd753 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -864,6 +864,7 @@ const CONST = { COMMENT_LENGTH_DEBOUNCE_TIME: 500, SEARCH_OPTION_LIST_DEBOUNCE_TIME: 300, RESIZE_DEBOUNCE_TIME: 100, + VISUAL_VIEWPORT_DELAY: 50, }, PRIORITY_MODE: { GSD: 'gsd', diff --git a/src/hooks/useViewportOffsetTop/index.ts b/src/hooks/useViewportOffsetTop/index.ts index 56fb19187c4f..29e144f4933e 100644 --- a/src/hooks/useViewportOffsetTop/index.ts +++ b/src/hooks/useViewportOffsetTop/index.ts @@ -1,40 +1,60 @@ -import {useEffect, useRef, useState} from 'react'; +import {useCallback, useEffect, useRef, useState} from 'react'; import addViewportResizeListener from '@libs/VisualViewport'; +import CONST from '@src/CONST'; /** * A hook that returns the offset of the top edge of the visual viewport */ export default function useViewportOffsetTop(shouldAdjustScrollView = false): number { const [viewportOffsetTop, setViewportOffsetTop] = useState(0); - const initialHeight = useRef(window.visualViewport?.height ?? window.innerHeight).current; + const initialHeight = useRef(0); const cachedDefaultOffsetTop = useRef(0); - useEffect(() => { - const updateOffsetTop = (event?: Event) => { + + const updateOffsetTop = useCallback( + (event?: Event) => { let targetOffsetTop = window.visualViewport?.offsetTop ?? 0; if (event?.target instanceof VisualViewport) { targetOffsetTop = event.target.offsetTop; } - if (shouldAdjustScrollView && window.visualViewport) { - const adjustScrollY = Math.round(initialHeight - window.visualViewport.height); + console.log(`___________ UpdateOffsetTop ___________`, window.visualViewport?.height, {initialHeight: initialHeight.current}); + if (shouldAdjustScrollView && window.visualViewport && initialHeight.current) { + const adjustScrollY = Math.round(initialHeight.current - window.visualViewport.height); + console.log(`___________ ___________`, { adjustScrollY, cachedDefaultOffsetTop: cachedDefaultOffsetTop.current }); if (cachedDefaultOffsetTop.current === 0) { + console.log(`___________ CASE 0 ___________`, {targetOffsetTop}); cachedDefaultOffsetTop.current = targetOffsetTop; } if (adjustScrollY > targetOffsetTop) { + console.log(`___________ CASE 1 ___________`, {adjustScrollY, targetOffsetTop}); setViewportOffsetTop(adjustScrollY); } else if (targetOffsetTop !== 0 && adjustScrollY === targetOffsetTop) { + console.log(`___________ CASE 2 ___________`, {adjustScrollY, targetOffsetTop, cachedDefaultOffsetTop: cachedDefaultOffsetTop.current}); setViewportOffsetTop(cachedDefaultOffsetTop.current); } else { + console.log(`___________ CASE 3 ___________`, {adjustScrollY, targetOffsetTop}); setViewportOffsetTop(targetOffsetTop); } } else { - setViewportOffsetTop(targetOffsetTop); + console.log(`___________ CASE 4. ___________`, {targetOffsetTop, event}); + setViewportOffsetTop(0); } - }; - updateOffsetTop(); + }, + [shouldAdjustScrollView], + ); + + useEffect(() => { return addViewportResizeListener(updateOffsetTop); - }, [initialHeight, shouldAdjustScrollView]); + }, [shouldAdjustScrollView, updateOffsetTop]); + + useEffect(() => { + setTimeout(() => { + initialHeight.current = window.visualViewport?.height ?? window.innerHeight; + console.log(`___________ INIT ___________`, initialHeight.current); + updateOffsetTop(); + }, CONST.TIMING.RESIZE_DEBOUNCE_TIME); + }, [updateOffsetTop]); useEffect(() => { if (!shouldAdjustScrollView) { diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index bbaf708d8a7d..6b0ffec1a463 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -263,7 +263,8 @@ function ReportScreen({ Performance.markStart(CONST.TIMING.CHAT_RENDER); } const [isComposerFocus, setIsComposerFocus] = useState(false); - const viewportOffsetTop = useViewportOffsetTop(Browser.isMobileSafari() && isComposerFocus && !modal?.willAlertModalBecomeVisible); + const shouldAdjustScrollView = useMemo(() => Browser.isMobileSafari() && isComposerFocus && !modal?.willAlertModalBecomeVisible, [isComposerFocus, modal]); + const viewportOffsetTop = useViewportOffsetTop(shouldAdjustScrollView); const {reportPendingAction, reportErrors} = ReportUtils.getReportOfflinePendingActionAndErrors(report); const screenWrapperStyle: ViewStyle[] = [styles.appContent, styles.flex1, {marginTop: viewportOffsetTop}]; diff --git a/web/index.html b/web/index.html index fb97293ebda5..a3baee84f7a5 100644 --- a/web/index.html +++ b/web/index.html @@ -13,6 +13,7 @@ + From caa9da5ec40596e2bca05ef4a3179fb5e21e8360 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Fri, 29 Mar 2024 02:23:03 +0700 Subject: [PATCH 2/6] remove log, fix lint & prettier --- src/CONST.ts | 1 - src/hooks/useViewportOffsetTop/index.ts | 12 +----------- web/index.html | 1 - 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index d6504abfd753..c57ac575f7e6 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -864,7 +864,6 @@ const CONST = { COMMENT_LENGTH_DEBOUNCE_TIME: 500, SEARCH_OPTION_LIST_DEBOUNCE_TIME: 300, RESIZE_DEBOUNCE_TIME: 100, - VISUAL_VIEWPORT_DELAY: 50, }, PRIORITY_MODE: { GSD: 'gsd', diff --git a/src/hooks/useViewportOffsetTop/index.ts b/src/hooks/useViewportOffsetTop/index.ts index 29e144f4933e..36cf47c0c553 100644 --- a/src/hooks/useViewportOffsetTop/index.ts +++ b/src/hooks/useViewportOffsetTop/index.ts @@ -17,41 +17,31 @@ export default function useViewportOffsetTop(shouldAdjustScrollView = false): nu targetOffsetTop = event.target.offsetTop; } - console.log(`___________ UpdateOffsetTop ___________`, window.visualViewport?.height, {initialHeight: initialHeight.current}); if (shouldAdjustScrollView && window.visualViewport && initialHeight.current) { const adjustScrollY = Math.round(initialHeight.current - window.visualViewport.height); - console.log(`___________ ___________`, { adjustScrollY, cachedDefaultOffsetTop: cachedDefaultOffsetTop.current }); if (cachedDefaultOffsetTop.current === 0) { - console.log(`___________ CASE 0 ___________`, {targetOffsetTop}); cachedDefaultOffsetTop.current = targetOffsetTop; } if (adjustScrollY > targetOffsetTop) { - console.log(`___________ CASE 1 ___________`, {adjustScrollY, targetOffsetTop}); setViewportOffsetTop(adjustScrollY); } else if (targetOffsetTop !== 0 && adjustScrollY === targetOffsetTop) { - console.log(`___________ CASE 2 ___________`, {adjustScrollY, targetOffsetTop, cachedDefaultOffsetTop: cachedDefaultOffsetTop.current}); setViewportOffsetTop(cachedDefaultOffsetTop.current); } else { - console.log(`___________ CASE 3 ___________`, {adjustScrollY, targetOffsetTop}); setViewportOffsetTop(targetOffsetTop); } } else { - console.log(`___________ CASE 4. ___________`, {targetOffsetTop, event}); setViewportOffsetTop(0); } }, [shouldAdjustScrollView], ); - useEffect(() => { - return addViewportResizeListener(updateOffsetTop); - }, [shouldAdjustScrollView, updateOffsetTop]); + useEffect(() => addViewportResizeListener(updateOffsetTop), [shouldAdjustScrollView, updateOffsetTop]); useEffect(() => { setTimeout(() => { initialHeight.current = window.visualViewport?.height ?? window.innerHeight; - console.log(`___________ INIT ___________`, initialHeight.current); updateOffsetTop(); }, CONST.TIMING.RESIZE_DEBOUNCE_TIME); }, [updateOffsetTop]); diff --git a/web/index.html b/web/index.html index a3baee84f7a5..fb97293ebda5 100644 --- a/web/index.html +++ b/web/index.html @@ -13,7 +13,6 @@ - From 57afe613dc4327c8a6db56168448a2a974b1b344 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Tue, 9 Apr 2024 01:18:34 +0700 Subject: [PATCH 3/6] remove set timeout --- src/hooks/useViewportOffsetTop/index.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/hooks/useViewportOffsetTop/index.ts b/src/hooks/useViewportOffsetTop/index.ts index 36cf47c0c553..54ce19b8f02f 100644 --- a/src/hooks/useViewportOffsetTop/index.ts +++ b/src/hooks/useViewportOffsetTop/index.ts @@ -1,13 +1,11 @@ import {useCallback, useEffect, useRef, useState} from 'react'; import addViewportResizeListener from '@libs/VisualViewport'; -import CONST from '@src/CONST'; /** * A hook that returns the offset of the top edge of the visual viewport */ export default function useViewportOffsetTop(shouldAdjustScrollView = false): number { const [viewportOffsetTop, setViewportOffsetTop] = useState(0); - const initialHeight = useRef(0); const cachedDefaultOffsetTop = useRef(0); const updateOffsetTop = useCallback( @@ -16,9 +14,10 @@ export default function useViewportOffsetTop(shouldAdjustScrollView = false): nu if (event?.target instanceof VisualViewport) { targetOffsetTop = event.target.offsetTop; } - - if (shouldAdjustScrollView && window.visualViewport && initialHeight.current) { - const adjustScrollY = Math.round(initialHeight.current - window.visualViewport.height); + + if (shouldAdjustScrollView && window.visualViewport) { + const clientHeight = document.body.clientHeight; + const adjustScrollY = Math.round(clientHeight - window.visualViewport.height); if (cachedDefaultOffsetTop.current === 0) { cachedDefaultOffsetTop.current = targetOffsetTop; } @@ -31,7 +30,7 @@ export default function useViewportOffsetTop(shouldAdjustScrollView = false): nu setViewportOffsetTop(targetOffsetTop); } } else { - setViewportOffsetTop(0); + setViewportOffsetTop(targetOffsetTop); } }, [shouldAdjustScrollView], @@ -39,13 +38,6 @@ export default function useViewportOffsetTop(shouldAdjustScrollView = false): nu useEffect(() => addViewportResizeListener(updateOffsetTop), [shouldAdjustScrollView, updateOffsetTop]); - useEffect(() => { - setTimeout(() => { - initialHeight.current = window.visualViewport?.height ?? window.innerHeight; - updateOffsetTop(); - }, CONST.TIMING.RESIZE_DEBOUNCE_TIME); - }, [updateOffsetTop]); - useEffect(() => { if (!shouldAdjustScrollView) { return; From a3155d8f4c9040bb4dac891b073c156099581c61 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Tue, 9 Apr 2024 01:23:54 +0700 Subject: [PATCH 4/6] fix prettier --- src/hooks/useViewportOffsetTop/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useViewportOffsetTop/index.ts b/src/hooks/useViewportOffsetTop/index.ts index 54ce19b8f02f..7799065c9cb5 100644 --- a/src/hooks/useViewportOffsetTop/index.ts +++ b/src/hooks/useViewportOffsetTop/index.ts @@ -14,7 +14,7 @@ export default function useViewportOffsetTop(shouldAdjustScrollView = false): nu if (event?.target instanceof VisualViewport) { targetOffsetTop = event.target.offsetTop; } - + if (shouldAdjustScrollView && window.visualViewport) { const clientHeight = document.body.clientHeight; const adjustScrollY = Math.round(clientHeight - window.visualViewport.height); From 0376edeb0080cadc4c0a4dcbf88f3926ee2e0bdc Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Wed, 10 Apr 2024 00:51:49 +0700 Subject: [PATCH 5/6] update scroll behavior --- src/hooks/useViewportOffsetTop/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hooks/useViewportOffsetTop/index.ts b/src/hooks/useViewportOffsetTop/index.ts index 7799065c9cb5..bba57d563283 100644 --- a/src/hooks/useViewportOffsetTop/index.ts +++ b/src/hooks/useViewportOffsetTop/index.ts @@ -36,13 +36,13 @@ export default function useViewportOffsetTop(shouldAdjustScrollView = false): nu [shouldAdjustScrollView], ); - useEffect(() => addViewportResizeListener(updateOffsetTop), [shouldAdjustScrollView, updateOffsetTop]); + useEffect(() => addViewportResizeListener(updateOffsetTop), [updateOffsetTop]); useEffect(() => { if (!shouldAdjustScrollView) { return; } - window.scrollTo({top: viewportOffsetTop}); + window.scrollTo({top: viewportOffsetTop, behavior: 'instant'}); }, [shouldAdjustScrollView, viewportOffsetTop]); return viewportOffsetTop; From 283e46ff10ef31ab66a1a4c93726e808224dd710 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Wed, 10 Apr 2024 23:03:43 +0700 Subject: [PATCH 6/6] cleanup condition adjust scroll view for web --- src/hooks/useViewportOffsetTop/index.ts | 3 ++- src/pages/home/ReportScreen.tsx | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hooks/useViewportOffsetTop/index.ts b/src/hooks/useViewportOffsetTop/index.ts index bba57d563283..da2325a7e13f 100644 --- a/src/hooks/useViewportOffsetTop/index.ts +++ b/src/hooks/useViewportOffsetTop/index.ts @@ -1,4 +1,5 @@ import {useCallback, useEffect, useRef, useState} from 'react'; +import * as Browser from '@libs/Browser'; import addViewportResizeListener from '@libs/VisualViewport'; /** @@ -15,7 +16,7 @@ export default function useViewportOffsetTop(shouldAdjustScrollView = false): nu targetOffsetTop = event.target.offsetTop; } - if (shouldAdjustScrollView && window.visualViewport) { + if (Browser.isMobileSafari() && shouldAdjustScrollView && window.visualViewport) { const clientHeight = document.body.clientHeight; const adjustScrollY = Math.round(clientHeight - window.visualViewport.height); if (cachedDefaultOffsetTop.current === 0) { diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 11c6e4b26b50..798c526c93cc 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -27,7 +27,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useViewportOffsetTop from '@hooks/useViewportOffsetTop'; import useWindowDimensions from '@hooks/useWindowDimensions'; import Timing from '@libs/actions/Timing'; -import * as Browser from '@libs/Browser'; import Navigation from '@libs/Navigation/Navigation'; import clearReportNotifications from '@libs/Notification/clearReportNotifications'; import Performance from '@libs/Performance'; @@ -275,7 +274,7 @@ function ReportScreen({ Performance.markStart(CONST.TIMING.CHAT_RENDER); } const [isComposerFocus, setIsComposerFocus] = useState(false); - const shouldAdjustScrollView = useMemo(() => Browser.isMobileSafari() && isComposerFocus && !modal?.willAlertModalBecomeVisible, [isComposerFocus, modal]); + const shouldAdjustScrollView = useMemo(() => isComposerFocus && !modal?.willAlertModalBecomeVisible, [isComposerFocus, modal]); const viewportOffsetTop = useViewportOffsetTop(shouldAdjustScrollView); const {reportPendingAction, reportErrors} = ReportUtils.getReportOfflinePendingActionAndErrors(report);