From 75f7c6da2f6fbcc4bf0464760739623d724f39ea Mon Sep 17 00:00:00 2001
From: balibabu <cike8899@users.noreply.github.com>
Date: Tue, 26 Mar 2024 14:51:34 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20by=20obtaining=20the=20width=20and=20hei?=
 =?UTF-8?q?ght=20of=20the=20pdf=20and=20passing=20it=20to=20b=E2=80=A6=20(?=
 =?UTF-8?q?#151)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix: by obtaining the width and height of the pdf and passing it to boundingRect, the problem of inaccurate positioning of file highlighting is fixed

* feat: remove actualPositions from buildChunkHighlights
---
 web/src/components/pdf-previewer/index.tsx    | 113 ++++++++++--------
 web/src/hooks/documentHooks.ts                |  21 +++-
 web/src/less/mixins.less                      |   8 +-
 .../components/document-preview/preview.tsx   | 112 +++++++++--------
 .../components/knowledge-chunk/hooks.ts       |  20 +++-
 web/src/utils/documentUtils.ts                |  20 ++--
 6 files changed, 166 insertions(+), 128 deletions(-)

diff --git a/web/src/components/pdf-previewer/index.tsx b/web/src/components/pdf-previewer/index.tsx
index a9b64a6..b101eda 100644
--- a/web/src/components/pdf-previewer/index.tsx
+++ b/web/src/components/pdf-previewer/index.tsx
@@ -35,7 +35,7 @@ const HighlightPopup = ({
 
 const DocumentPreviewer = ({ chunk, documentId, visible }: IProps) => {
   const url = useGetDocumentUrl(documentId);
-  const state = useGetChunkHighlights(chunk);
+  const { highlights: state, setWidthAndHeight } = useGetChunkHighlights(chunk);
   const ref = useRef<(highlight: IHighlight) => void>(() => {});
   const [loaded, setLoaded] = useState(false);
 
@@ -59,59 +59,68 @@ const DocumentPreviewer = ({ chunk, documentId, visible }: IProps) => {
         beforeLoad={<Skeleton active />}
         workerSrc="/pdfjs-dist/pdf.worker.min.js"
       >
-        {(pdfDocument) => (
-          <PdfHighlighter
-            pdfDocument={pdfDocument}
-            enableAreaSelection={(event) => event.altKey}
-            onScrollChange={resetHash}
-            scrollRef={(scrollTo) => {
-              ref.current = scrollTo;
-              setLoaded(true);
-            }}
-            onSelectionFinished={() => null}
-            highlightTransform={(
-              highlight,
-              index,
-              setTip,
-              hideTip,
-              viewportToScaled,
-              screenshot,
-              isScrolledTo,
-            ) => {
-              const isTextHighlight = !Boolean(
-                highlight.content && highlight.content.image,
-              );
+        {(pdfDocument) => {
+          pdfDocument.getPage(1).then((page) => {
+            const viewport = page.getViewport({ scale: 1 });
+            const width = viewport.width;
+            const height = viewport.height;
+            setWidthAndHeight(width, height);
+          });
 
-              const component = isTextHighlight ? (
-                <Highlight
-                  isScrolledTo={isScrolledTo}
-                  position={highlight.position}
-                  comment={highlight.comment}
-                />
-              ) : (
-                <AreaHighlight
-                  isScrolledTo={isScrolledTo}
-                  highlight={highlight}
-                  onChange={() => {}}
-                />
-              );
+          return (
+            <PdfHighlighter
+              pdfDocument={pdfDocument}
+              enableAreaSelection={(event) => event.altKey}
+              onScrollChange={resetHash}
+              scrollRef={(scrollTo) => {
+                ref.current = scrollTo;
+                setLoaded(true);
+              }}
+              onSelectionFinished={() => null}
+              highlightTransform={(
+                highlight,
+                index,
+                setTip,
+                hideTip,
+                viewportToScaled,
+                screenshot,
+                isScrolledTo,
+              ) => {
+                const isTextHighlight = !Boolean(
+                  highlight.content && highlight.content.image,
+                );
 
-              return (
-                <Popup
-                  popupContent={<HighlightPopup {...highlight} />}
-                  onMouseOver={(popupContent) =>
-                    setTip(highlight, () => popupContent)
-                  }
-                  onMouseOut={hideTip}
-                  key={index}
-                >
-                  {component}
-                </Popup>
-              );
-            }}
-            highlights={state}
-          />
-        )}
+                const component = isTextHighlight ? (
+                  <Highlight
+                    isScrolledTo={isScrolledTo}
+                    position={highlight.position}
+                    comment={highlight.comment}
+                  />
+                ) : (
+                  <AreaHighlight
+                    isScrolledTo={isScrolledTo}
+                    highlight={highlight}
+                    onChange={() => {}}
+                  />
+                );
+
+                return (
+                  <Popup
+                    popupContent={<HighlightPopup {...highlight} />}
+                    onMouseOver={(popupContent) =>
+                      setTip(highlight, () => popupContent)
+                    }
+                    onMouseOut={hideTip}
+                    key={index}
+                  >
+                    {component}
+                  </Popup>
+                );
+              }}
+              highlights={state}
+            />
+          );
+        }}
       </PdfLoader>
     </div>
   );
diff --git a/web/src/hooks/documentHooks.ts b/web/src/hooks/documentHooks.ts
index f3b75bf..19dae5c 100644
--- a/web/src/hooks/documentHooks.ts
+++ b/web/src/hooks/documentHooks.ts
@@ -2,7 +2,7 @@ import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge';
 import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
 import { api_host } from '@/utils/api';
 import { buildChunkHighlights } from '@/utils/documentUtils';
-import { useCallback, useMemo } from 'react';
+import { useCallback, useMemo, useState } from 'react';
 import { IHighlight } from 'react-pdf-highlighter';
 import { useDispatch, useSelector } from 'umi';
 import { useGetKnowledgeSearchParams } from './routeHook';
@@ -15,12 +15,23 @@ export const useGetDocumentUrl = (documentId: string) => {
   return url;
 };
 
-export const useGetChunkHighlights = (selectedChunk: IChunk): IHighlight[] => {
+export const useGetChunkHighlights = (selectedChunk: IChunk) => {
+  const [size, setSize] = useState({ width: 849, height: 1200 });
+
   const highlights: IHighlight[] = useMemo(() => {
-    return buildChunkHighlights(selectedChunk);
-  }, [selectedChunk]);
+    return buildChunkHighlights(selectedChunk, size);
+  }, [selectedChunk, size]);
+
+  const setWidthAndHeight = (width: number, height: number) => {
+    setSize((pre) => {
+      if (pre.height !== height || pre.width !== width) {
+        return { height, width };
+      }
+      return pre;
+    });
+  };
 
-  return highlights;
+  return { highlights, setWidthAndHeight };
 };
 
 export const useFetchDocumentList = () => {
diff --git a/web/src/less/mixins.less b/web/src/less/mixins.less
index 85c808a..b5256f7 100644
--- a/web/src/less/mixins.less
+++ b/web/src/less/mixins.less
@@ -9,11 +9,11 @@
 
   caption {
     color: @blurBackground;
-    font-size: 20px;
-    height: 50px;
-    line-height: 50px;
+    font-size: 14px;
+    height: 20px;
+    line-height: 20px;
     font-weight: 600;
-    margin-bottom: 10px;
+    margin-bottom: 6px;
   }
 
   th {
diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/preview.tsx b/web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/preview.tsx
index 6ec4f65..f228e8e 100644
--- a/web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/preview.tsx
+++ b/web/src/pages/add-knowledge/components/knowledge-chunk/components/document-preview/preview.tsx
@@ -30,7 +30,8 @@ const HighlightPopup = ({
 // TODO: merge with DocumentPreviewer
 const Preview = ({ selectedChunkId }: IProps) => {
   const url = useGetDocumentUrl();
-  const state = useGetChunkHighlights(selectedChunkId);
+  const { highlights: state, setWidthAndHeight } =
+    useGetChunkHighlights(selectedChunkId);
   const ref = useRef<(highlight: IHighlight) => void>(() => {});
 
   const resetHash = () => {};
@@ -48,58 +49,67 @@ const Preview = ({ selectedChunkId }: IProps) => {
         beforeLoad={<Skeleton active />}
         workerSrc="/pdfjs-dist/pdf.worker.min.js"
       >
-        {(pdfDocument) => (
-          <PdfHighlighter
-            pdfDocument={pdfDocument}
-            enableAreaSelection={(event) => event.altKey}
-            onScrollChange={resetHash}
-            scrollRef={(scrollTo) => {
-              ref.current = scrollTo;
-            }}
-            onSelectionFinished={() => null}
-            highlightTransform={(
-              highlight,
-              index,
-              setTip,
-              hideTip,
-              viewportToScaled,
-              screenshot,
-              isScrolledTo,
-            ) => {
-              const isTextHighlight = !Boolean(
-                highlight.content && highlight.content.image,
-              );
+        {(pdfDocument) => {
+          pdfDocument.getPage(1).then((page) => {
+            const viewport = page.getViewport({ scale: 1 });
+            const width = viewport.width;
+            const height = viewport.height;
+            setWidthAndHeight(width, height);
+          });
 
-              const component = isTextHighlight ? (
-                <Highlight
-                  isScrolledTo={isScrolledTo}
-                  position={highlight.position}
-                  comment={highlight.comment}
-                />
-              ) : (
-                <AreaHighlight
-                  isScrolledTo={isScrolledTo}
-                  highlight={highlight}
-                  onChange={() => {}}
-                />
-              );
+          return (
+            <PdfHighlighter
+              pdfDocument={pdfDocument}
+              enableAreaSelection={(event) => event.altKey}
+              onScrollChange={resetHash}
+              scrollRef={(scrollTo) => {
+                ref.current = scrollTo;
+              }}
+              onSelectionFinished={() => null}
+              highlightTransform={(
+                highlight,
+                index,
+                setTip,
+                hideTip,
+                viewportToScaled,
+                screenshot,
+                isScrolledTo,
+              ) => {
+                const isTextHighlight = !Boolean(
+                  highlight.content && highlight.content.image,
+                );
 
-              return (
-                <Popup
-                  popupContent={<HighlightPopup {...highlight} />}
-                  onMouseOver={(popupContent) =>
-                    setTip(highlight, () => popupContent)
-                  }
-                  onMouseOut={hideTip}
-                  key={index}
-                >
-                  {component}
-                </Popup>
-              );
-            }}
-            highlights={state}
-          />
-        )}
+                const component = isTextHighlight ? (
+                  <Highlight
+                    isScrolledTo={isScrolledTo}
+                    position={highlight.position}
+                    comment={highlight.comment}
+                  />
+                ) : (
+                  <AreaHighlight
+                    isScrolledTo={isScrolledTo}
+                    highlight={highlight}
+                    onChange={() => {}}
+                  />
+                );
+
+                return (
+                  <Popup
+                    popupContent={<HighlightPopup {...highlight} />}
+                    onMouseOver={(popupContent) =>
+                      setTip(highlight, () => popupContent)
+                    }
+                    onMouseOut={hideTip}
+                    key={index}
+                  >
+                    {component}
+                  </Popup>
+                );
+              }}
+              highlights={state}
+            />
+          );
+        }}
       </PdfLoader>
     </div>
   );
diff --git a/web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts b/web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts
index 59bf2fd..724f14e 100644
--- a/web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts
+++ b/web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts
@@ -36,16 +36,24 @@ export const useGetSelectedChunk = (selectedChunkId: string) => {
   );
 };
 
-export const useGetChunkHighlights = (
-  selectedChunkId: string,
-): IHighlight[] => {
+export const useGetChunkHighlights = (selectedChunkId: string) => {
+  const [size, setSize] = useState({ width: 849, height: 1200 });
   const selectedChunk: IChunk = useGetSelectedChunk(selectedChunkId);
 
   const highlights: IHighlight[] = useMemo(() => {
-    return buildChunkHighlights(selectedChunk);
-  }, [selectedChunk]);
+    return buildChunkHighlights(selectedChunk, size);
+  }, [selectedChunk, size]);
 
-  return highlights;
+  const setWidthAndHeight = (width: number, height: number) => {
+    setSize((pre) => {
+      if (pre.height !== height || pre.width !== width) {
+        return { height, width };
+      }
+      return pre;
+    });
+  };
+
+  return { highlights, setWidthAndHeight };
 };
 
 export const useSelectChunkListLoading = () => {
diff --git a/web/src/utils/documentUtils.ts b/web/src/utils/documentUtils.ts
index 4119fa9..45e8968 100644
--- a/web/src/utils/documentUtils.ts
+++ b/web/src/utils/documentUtils.ts
@@ -2,20 +2,20 @@ import { IChunk } from '@/interfaces/database/knowledge';
 import { UploadFile } from 'antd';
 import { v4 as uuid } from 'uuid';
 
-export const buildChunkHighlights = (selectedChunk: IChunk) => {
+export const buildChunkHighlights = (
+  selectedChunk: IChunk,
+  size: { width: number; height: number },
+) => {
   return Array.isArray(selectedChunk?.positions) &&
     selectedChunk.positions.every((x) => Array.isArray(x))
     ? selectedChunk?.positions?.map((x) => {
-        const actualPositions = x.map((y, index) =>
-          index !== 0 ? y / 0.7 : y,
-        );
         const boundingRect = {
-          width: 849,
-          height: 1200,
-          x1: actualPositions[1],
-          x2: actualPositions[2],
-          y1: actualPositions[3],
-          y2: actualPositions[4],
+          width: size.width,
+          height: size.height,
+          x1: x[1],
+          x2: x[2],
+          y1: x[3],
+          y2: x[4],
         };
         return {
           id: uuid(),
-- 
GitLab