From d8ff2cb806adf47213d0b11593acfcecf54f3564 Mon Sep 17 00:00:00 2001 From: Red J Adaya Date: Fri, 5 Jul 2024 00:07:06 +0800 Subject: [PATCH] height adjuster (#94) This hook observes and returns the current height of a component. --- frontend/app/hook/useParentHeight.tsx | 40 +++++++++++++++++++++++++++ frontend/app/view/webview.tsx | 37 ++++++------------------- 2 files changed, 49 insertions(+), 28 deletions(-) create mode 100644 frontend/app/hook/useParentHeight.tsx diff --git a/frontend/app/hook/useParentHeight.tsx b/frontend/app/hook/useParentHeight.tsx new file mode 100644 index 000000000..08c2c6f84 --- /dev/null +++ b/frontend/app/hook/useParentHeight.tsx @@ -0,0 +1,40 @@ +// Copyright 2024, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import debounce from "lodash.debounce"; +import { useCallback, useEffect, useState } from "react"; + +const useParentHeight = (ref: React.RefObject) => { + const [height, setHeight] = useState(null); + + const updateHeight = useCallback(() => { + if (ref.current) { + const parentHeight = ref.current.getBoundingClientRect().height || 0; + setHeight(parentHeight); + } + }, []); + + const debouncedUpdateHeight = useCallback(debounce(updateHeight, 100), [updateHeight]); + + useEffect(() => { + const resizeObserver = new ResizeObserver(() => { + debouncedUpdateHeight(); + }); + + if (ref.current) { + resizeObserver.observe(ref.current); + updateHeight(); + } + + return () => { + if (ref.current) { + resizeObserver.unobserve(ref.current); + } + debouncedUpdateHeight.cancel(); + }; + }, [debouncedUpdateHeight, updateHeight]); + + return height; +}; + +export { useParentHeight }; diff --git a/frontend/app/view/webview.tsx b/frontend/app/view/webview.tsx index 805ed4891..315789520 100644 --- a/frontend/app/view/webview.tsx +++ b/frontend/app/view/webview.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { Button } from "@/app/element/button"; +import { useParentHeight } from "@/app/hook/useParentHeight"; import { getApi } from "@/app/store/global"; import { WebviewTag } from "electron"; import React, { memo, useEffect, useRef, useState } from "react"; @@ -16,26 +17,19 @@ interface WebViewProps { const WebView = memo(({ parentRef, initialUrl }: WebViewProps) => { const [url, setUrl] = useState(initialUrl); const [inputUrl, setInputUrl] = useState(initialUrl); // Separate state for the input field - const [webViewHeight, setWebViewHeight] = useState(0); const [isLoading, setIsLoading] = useState(false); const webviewRef = useRef(null); const inputRef = useRef(null); - const historyStack = useRef([]); const historyIndex = useRef(-1); const recentUrls = useRef<{ [key: string]: number }>({}); - const getWebViewHeight = () => { - const inputHeight = inputRef.current?.getBoundingClientRect().height; - const parentHeight = parentRef.current?.getBoundingClientRect().height; - return parentHeight - (inputHeight + 35); - }; + const parentHeight = useParentHeight(parentRef); + const inputHeight = inputRef.current?.getBoundingClientRect().height || 0; + const webViewHeight = parentHeight - (inputHeight + 35); useEffect(() => { - const webviewHeight = getWebViewHeight(); - setWebViewHeight(webviewHeight); - historyStack.current.push(initialUrl); historyIndex.current = 0; @@ -99,6 +93,10 @@ const WebView = memo(({ parentRef, initialUrl }: WebViewProps) => { } }, [initialUrl]); + // useEffect(() => { + // setWebViewHeight(getWebViewHeight()); + // }, [parentHeight, getWebViewHeight]); + useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if ((event.ctrlKey || event.metaKey) && event.key === "l") { @@ -115,34 +113,17 @@ const WebView = memo(({ parentRef, initialUrl }: WebViewProps) => { } }; - const handleResize = () => { - const webviewHeight = getWebViewHeight(); - setWebViewHeight(webviewHeight); - }; - const parentElement = parentRef.current; if (parentElement) { parentElement.addEventListener("keydown", handleKeyDown); } - // Use ResizeObserver to observe changes in the height of parentRef - const resizeObserver = new ResizeObserver((entries) => { - for (let entry of entries) { - if (entry.target === parentElement) { - handleResize(); - } - } - }); - - resizeObserver.observe(parentElement); - return () => { if (parentElement) { parentElement.removeEventListener("keydown", handleKeyDown); } - resizeObserver.disconnect(); }; - }, []); + }, [parentRef]); const ensureUrlScheme = (url: string) => { if (/^(localhost|(\d{1,3}\.){3}\d{1,3})(:\d+)?/.test(url)) {