Bläddra i källkod

optimization text search

RoyLiu 4 år sedan
förälder
incheckning
c94e645046
4 ändrade filer med 73 tillägg och 26 borttagningar
  1. 12 1
      components/Search/index.tsx
  2. 7 1
      components/Search/styled.ts
  3. 19 6
      containers/Search.tsx
  4. 35 18
      helpers/search.ts

+ 12 - 1
components/Search/index.tsx

@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
 
 import Button from '../Button';
 import Portal from '../Portal';
+import Loading from '../Loading';
 
 import {
   Wrapper,
@@ -10,6 +11,7 @@ import {
   Input,
   ResultInfo,
   ArrowButton,
+  LoadingWrapper,
 } from './styled';
 
 type Props = {
@@ -18,7 +20,8 @@ type Props = {
   onEnter: (val: string) => void;
   onPrev: () => void;
   onNext: () => void;
-  isActive?: boolean;
+  isActive: boolean;
+  isProcessing: boolean;
   close: () => void;
 };
 
@@ -29,6 +32,7 @@ const Search: React.FC<Props> = ({
   onNext,
   onEnter,
   isActive = false,
+  isProcessing = false,
   close,
 }: Props) => {
   const { t } = useTranslation('toolbar');
@@ -58,6 +62,13 @@ const Search: React.FC<Props> = ({
             onKeyDown={handleKeyDown}
           />
           <ResultInfo>
+            {isProcessing ? (
+              <LoadingWrapper>
+                <Loading />
+              </LoadingWrapper>
+            ) : (
+              ''
+            )}
             {matchesTotal ? `${current} / ${matchesTotal}` : ''}
           </ResultInfo>
         </InputWrapper>

+ 7 - 1
components/Search/styled.ts

@@ -27,7 +27,7 @@ export const InputWrapper = styled.div`
   display: flex;
   justify-content: space-between;
   align-items: center;
-  padding: 10px 14px;
+  padding: 10px;
 `;
 
 export const Input = styled.input`
@@ -91,3 +91,9 @@ export const ArrowButton = styled('button')<{ variant: string }>`
           }
         `}
 `;
+
+export const LoadingWrapper = styled.div`
+  transform: scale(0.7);
+  transform-origin: right;
+  margin-top: 3px;
+`;

+ 19 - 6
containers/Search.tsx

@@ -11,8 +11,10 @@ import { scrollIntoView } from '../helpers/utility';
 let timer: ReturnType<typeof setTimeout> = setTimeout(() => '', 100);
 
 let localMatchesMap: MatchType[] = [];
+// const localTotal = 0;
 
 const Search: React.FC = () => {
+  // const [isProcessing, setProcessing] = useState(false);
   const [matchTotal, setMatchTotal] = useState(0);
 
   const [
@@ -44,10 +46,16 @@ const Search: React.FC = () => {
         });
         setMatchesMap(localMatchesMap);
       });
-
+      // localTotal += matches.length;
       setMatchTotal(cur => cur + matches.length);
     }
 
+    // if (pageNum === totalPage) {
+    // setMatchesMap(localMatchesMap);
+    // setMatchTotal(localTotal);
+    // setProcessing(false);
+    // }
+
     if (pageNum < totalPage) {
       await getMatchTextIndex(pageNum + 1, queryStr);
     }
@@ -59,6 +67,7 @@ const Search: React.FC = () => {
 
   const reset = (): void => {
     localMatchesMap = [];
+    // localTotal = 0;
     setMatchesMap([]);
     setMatchTotal(0);
     setCurrentIndex(-1);
@@ -68,11 +77,12 @@ const Search: React.FC = () => {
   const handleSearch = (val: string): void => {
     if (!val) return;
 
-    const queryStr = normalize(val.toLowerCase());
-    if (queryStr !== queryString) {
+    const newQueryString = normalize(val.toLowerCase());
+    if (newQueryString !== queryString) {
+      // setProcessing(true);
       reset();
-      setQueryString(queryStr);
-      startSearchPdf(queryStr);
+      setQueryString(newQueryString);
+      startSearchPdf(newQueryString);
     }
   };
 
@@ -105,8 +115,10 @@ const Search: React.FC = () => {
         } else {
           highlightTarget(match, color);
         }
+      } else {
+        highlightTarget(match, color);
       }
-    }, 200);
+    }, 300);
   };
 
   const handleClickPrev = (): void => {
@@ -165,6 +177,7 @@ const Search: React.FC = () => {
       onEnter={handleSearch}
       isActive={navbarState === 'search'}
       close={handleClose}
+      isProcessing={false}
     />
   );
 };

+ 35 - 18
helpers/search.ts

@@ -12,15 +12,16 @@ export const extractTextItems = async (
 
   for (let j = 0, len = textContent.length; j < len; j += 1) {
     // add whitespace in front if start character is Uppercase
-    if (
-      textContent[j].str.match(/^[A-Z]/) &&
-      j > 0 &&
-      textContent[j - 1].str !== ' '
-    ) {
-      strBuf.push(` ${textContent[j].str}`);
-    } else {
-      strBuf.push(textContent[j].str);
-    }
+    strBuf.push(textContent[j].str);
+    // if (
+    //   textContent[j].str.match(/^[A-Z]/) &&
+    //   j > 0 &&
+    //   textContent[j - 1].str !== ' '
+    // ) {
+    //   strBuf.push(` ${textContent[j].str}`);
+    // } else {
+    //   strBuf.push(textContent[j].str);
+    // }
   }
 
   return strBuf;
@@ -79,13 +80,16 @@ const appendTextToDiv = async (
   fromOffset: number,
   toOffset: number | undefined,
   highlight: boolean,
-  id: string
+  id: string,
+  queryStr = ''
 ): Promise<any> => {
   const textContentItem = await extractTextItems(getPage);
 
   const domElement = domElements[divIdx];
   const content = textContentItem[divIdx].substring(fromOffset, toOffset);
-  const node = document.createTextNode(content);
+  const node = document.createTextNode(
+    queryStr ? content.replace(queryStr, '') : content
+  );
   const span = document.createElement('span');
 
   if (highlight) {
@@ -94,8 +98,6 @@ const appendTextToDiv = async (
     span.appendChild(node);
     domElement.appendChild(span);
   } else {
-    // eslint-disable-next-line no-param-reassign
-    domElement.textContent = '';
     domElement.appendChild(node);
   }
 };
@@ -103,7 +105,8 @@ const appendTextToDiv = async (
 const beginText = async (
   domElements: HTMLElement[],
   getPage: () => Promise<any>,
-  begin: Record<string, any>
+  begin: Record<string, any>,
+  queryStr: string
 ): Promise<any> => {
   const { divIdx } = begin;
   const domElement = domElements[divIdx];
@@ -111,7 +114,16 @@ const beginText = async (
   if (domElement) {
     // eslint-disable-next-line no-param-reassign
     domElement.textContent = '';
-    appendTextToDiv(domElements, getPage, divIdx, 0, begin.offset, false, '');
+    appendTextToDiv(
+      domElements,
+      getPage,
+      divIdx,
+      0,
+      begin.offset,
+      false,
+      '',
+      queryStr
+    );
   }
 };
 
@@ -125,7 +137,7 @@ export const renderMatches = async (
   const textContentItem = await extractTextItems(getPage);
   const { begin, end } = convertMatches(queryStr, matchIndex, textContentItem);
 
-  beginText(domElements, getPage, begin);
+  beginText(domElements, getPage, begin, queryStr);
 
   if (begin.divIdx === end.divIdx) {
     appendTextToDiv(
@@ -152,7 +164,12 @@ export const renderMatches = async (
           );
           break;
         case end.divIdx:
-          beginText(domElements, getPage, { divIdx: end.divIdx, offset: 0 });
+          beginText(
+            domElements,
+            getPage,
+            { divIdx: end.divIdx, offset: 0 },
+            queryStr
+          );
           appendTextToDiv(
             domElements,
             getPage,
@@ -164,7 +181,7 @@ export const renderMatches = async (
           );
           break;
         default: {
-          beginText(domElements, getPage, { divIdx: i, offset: 0 });
+          beginText(domElements, getPage, { divIdx: i, offset: 0 }, queryStr);
           appendTextToDiv(domElements, getPage, i, 0, undefined, true, id);
           break;
         }