瀏覽代碼

Add functions for searching.

oldj 4 年之前
父節點
當前提交
b826e8d601
共有 4 個文件被更改,包括 116 次插入4 次删除
  1. 9 0
      src/common/types.d.ts
  2. 57 0
      src/main/actions/find/findBy.ts
  3. 1 0
      src/main/actions/index.ts
  4. 49 4
      src/renderer/pages/find.tsx

+ 9 - 0
src/common/types.d.ts

@@ -4,6 +4,7 @@
  * @homepage: https://oldj.net
  */
 
+import { HostsType } from '@root/common/data'
 import { MenuItemConstructorOptions } from 'electron'
 import { default as lang } from './i18n/languages/en'
 
@@ -20,3 +21,11 @@ export interface IPopupMenuOption {
   menu_id: string;
   items: IMenuItemOption[];
 }
+
+export interface IFindResultItem {
+  item_id: string;
+  item_type: HostsType;
+  line: number;
+  start: number;
+  end: number;
+}

+ 57 - 0
src/main/actions/find/findBy.ts

@@ -0,0 +1,57 @@
+/**
+ * @author: oldj
+ * @homepage: https://oldj.net
+ */
+
+import getContentOfHosts from '@main/actions/hosts/getContent'
+import { flatten } from '@root/common/hostsFn'
+import { IFindResultItem } from '@root/common/types'
+import { getList } from '../index'
+
+interface IFindOptions {
+  is_regexp: boolean;
+  is_ignore_case: boolean;
+}
+
+const findInContent = (content: string, exp: string | RegExp, options: IFindOptions): Omit<IFindResultItem, 'item_id' | 'item_type'>[] => {
+  let result_items: IFindResultItem[] = []
+
+  let result = {
+    line: -1,
+    start: -1,
+    end: -1,
+  }
+
+  // todo ...
+
+  return result_items
+}
+
+export default async (keyword: string, options: IFindOptions): Promise<IFindResultItem[]> => {
+  console.log(keyword)
+  let result_items: IFindResultItem[] = []
+
+  let tree = await getList()
+  let items = flatten(tree)
+
+  let exp: string | RegExp = keyword
+  if (options.is_regexp) {
+    exp = new RegExp(exp, options.is_ignore_case ? 'ig' : 'g')
+  }
+
+  for (let item of items) {
+    const item_type = item.type || 'local'
+    if (item_type === 'group' || item_type === 'folder') {
+      continue
+    }
+    let content = await getContentOfHosts(item.id)
+    let found = findInContent(content, exp, options)
+    result_items = [...result_items, ...found.map(i => ({
+      ...i,
+      item_id: item.id,
+      item_type,
+    }))]
+  }
+
+  return result_items
+}

+ 1 - 0
src/main/actions/index.ts

@@ -46,6 +46,7 @@ export { default as closeMainWindow } from './closeMainWindow'
 export { default as quit } from './quit'
 
 export { default as findShow } from './find/show'
+export { default as findBy } from './find/findBy'
 
 export { default as migrateCheck } from './migrate/checkIfMigration'
 export { default as migrateData } from './migrate/migrateData'

+ 49 - 4
src/renderer/pages/find.tsx

@@ -15,9 +15,12 @@ import {
   useColorMode,
   VStack,
 } from '@chakra-ui/react'
-import { agent } from '@renderer/core/agent'
+import { actions, agent } from '@renderer/core/agent'
 import useOnBroadcast from '@renderer/core/useOnBroadcast'
-import React, { useEffect } from 'react'
+import { IFindResultItem } from '@root/common/types'
+import { useDebounce } from 'ahooks'
+import lodash from 'lodash'
+import React, { useEffect, useState } from 'react'
 import { IoSearch } from 'react-icons/io5'
 import styles from './find.less'
 
@@ -29,6 +32,12 @@ const find = (props: Props) => {
   const { lang, setLocale } = useModel('useI18n')
   const { configs, loadConfigs } = useModel('useConfigs')
   const { colorMode, setColorMode } = useColorMode()
+  const [keyword, setKeyword] = useState('')
+  const [replact_to, setReplaceTo] = useState('')
+  const [is_regexp, setIsRegExp] = useState(false)
+  const [is_ignore_case, setIsIgnoreCase] = useState(false)
+  const [find_result, setFindResult] = useState<IFindResultItem[]>([])
+  const debounced_keyword = useDebounce(keyword, { wait: 500 })
 
   const init = async () => {
     if (!configs) return
@@ -55,8 +64,27 @@ const find = (props: Props) => {
     document.title = lang.find_and_replace
   }, [lang])
 
+  useEffect(() => {
+    doFind(debounced_keyword)
+  }, [debounced_keyword, is_regexp, is_ignore_case])
+
   useOnBroadcast('config_updated', loadConfigs)
 
+  const doFind = lodash.debounce(async (v: string) => {
+    console.log('find by:', v)
+    if (!v) {
+      setFindResult([])
+      return
+    }
+
+    let result = await actions.findBy(v, {
+      is_regexp,
+      is_ignore_case,
+    })
+    setFindResult(result)
+    console.log(result)
+  }, 500)
+
   return (
     <div className={styles.root}>
       <VStack
@@ -69,8 +97,13 @@ const find = (props: Props) => {
             children={<IoSearch color="gray.300"/>}
           />
           <Input
+            autoFocus={true}
             placeholder="keywords"
             variant="flushed"
+            value={keyword}
+            onChange={(e) => {
+              setKeyword(e.target.value)
+            }}
           />
         </InputGroup>
 
@@ -82,6 +115,10 @@ const find = (props: Props) => {
           <Input
             placeholder="replace to"
             variant="flushed"
+            value={replact_to}
+            onChange={(e) => {
+              setReplaceTo(e.target.value)
+            }}
           />
         </InputGroup>
 
@@ -92,8 +129,14 @@ const find = (props: Props) => {
           spacing={4}
           // justifyContent="flex-start"
         >
-          <Checkbox>{lang.regexp}</Checkbox>
-          <Checkbox>{lang.ignore_case}</Checkbox>
+          <Checkbox
+            checked={is_regexp}
+            onChange={(e) => setIsRegExp(e.target.checked)}
+          >{lang.regexp}</Checkbox>
+          <Checkbox
+            checked={is_ignore_case}
+            onChange={(e) => setIsIgnoreCase(e.target.checked)}
+          >{lang.ignore_case}</Checkbox>
         </HStack>
 
         <Box
@@ -114,11 +157,13 @@ const find = (props: Props) => {
           <Button
             size="sm"
             variant="outline"
+            isDisabled={find_result.length === 0}
           >{lang.replace_all}</Button>
           <Button
             size="sm"
             variant="solid"
             colorScheme="blue"
+            isDisabled={find_result.length === 0}
           >{lang.replace}</Button>
         </HStack>
       </VStack>