Forráskód Böngészése

Add write mode configs.

oldj 3 éve
szülő
commit
ccb6f5ed4f

+ 2 - 0
src/common/default_configs.ts

@@ -1,6 +1,7 @@
 import { LocaleName } from '@root/common/i18n'
 import { FolderModeType } from './data.d'
 
+export type WriteModeType = null | 'overwrite' | 'append'
 export type ThemeType = 'light' | 'dark' | 'system'
 export type ProtocolType = 'http' | 'https'
 export type DefaultLocaleType = LocaleName | undefined
@@ -11,6 +12,7 @@ const configs = {
   left_panel_width: 270,
 
   // preferences
+  write_mode: null as WriteModeType,
   history_limit: 50,
   locale: undefined as DefaultLocaleType,
   theme: 'light' as ThemeType,

+ 1 - 0
src/common/events.ts

@@ -23,6 +23,7 @@ export default {
   show_about: 'show_about',
   show_history: 'show_history',
   show_preferences: 'show_preferences',
+  show_set_write_mode: 'show_set_write_mode',
   show_source: 'show_source',
   show_sudo_password_input: 'show_sudo_password_input',
   system_hosts_updated: 'system_hosts_updated',

+ 8 - 0
src/common/i18n/languages/en.ts

@@ -10,6 +10,7 @@ export default {
   acknowledgement: 'Acknowledgement',
   advanced: 'Advanced',
   all: 'All',
+  append: 'Append',
   auto_refresh: 'Auto refresh',
   btn_cancel: 'Cancel',
   btn_ok: 'OK',
@@ -108,6 +109,7 @@ export default {
   next: 'Next',
   no_access_to_hosts: 'No permission to write to the Hosts file.',
   no_record: 'No record',
+  overwrite: 'Overwrite',
   password: 'Password',
   paste: 'Paste',
   port: 'Port',
@@ -175,6 +177,12 @@ export default {
   where_is_my_data: 'Where is my data stored?',
   where_is_my_hosts: 'Where is my hosts file?',
   window: 'Window',
+  write_mode: 'Write mode',
+  write_mode_append_help:
+    'Append the new records to the end of the system hosts file.',
+  write_mode_overwrite_help:
+    'Overwrite the system hosts file with the new records.',
+  write_mode_set: 'Set the write mode',
   your_data_is: 'Your data files are stored in:',
   your_hosts_file_is: 'Your hosts file is located at:',
   zoom: 'Zoom',

+ 8 - 0
src/common/i18n/languages/fr.ts

@@ -10,6 +10,7 @@ export default {
   acknowledgement: 'Remerciements',
   advanced: 'Avancé',
   all: 'Tout',
+  append: 'Ajouter',
   auto_refresh: 'Rafraîchissement automatique',
   btn_cancel: 'Annuler',
   btn_ok: 'OK',
@@ -108,6 +109,7 @@ export default {
   next: 'Suivant',
   no_access_to_hosts: 'Aucune autorisation pour écrire dans le fichier hosts.',
   no_record: 'Aucun enregistrement',
+  overwrite: 'Écraser',
   password: 'Mot de passe',
   paste: 'Coller',
   port: 'Port',
@@ -176,6 +178,12 @@ export default {
   where_is_my_data: 'Où sont stockées mes données ?',
   where_is_my_hosts: 'Où est mon fichier hosts ?',
   window: 'Fenêtre',
+  write_mode: "Mode d'écriture",
+  write_mode_append_help:
+    "Ajoutez les nouveaux enregistrements à la fin du fichier d'hôtes système.",
+  write_mode_overwrite_help:
+    "Écrasez le fichier d'hôtes système avec les nouveaux enregistrements.",
+  write_mode_set: "Définir le mode d'écriture",
   your_data_is: 'Les fichiers contenant vos données sont stockés ici :',
   your_hosts_file_is: 'Votre fichier hosts est situé ici :',
   zoom: 'Zoom',

+ 7 - 1
src/common/i18n/languages/zh.ts

@@ -12,6 +12,7 @@ const lang: LanguageDict = {
   acknowledgement: '特别致谢',
   advanced: '高级',
   all: '全部',
+  append: '追加',
   auto_refresh: '自动刷新',
   btn_cancel: '取消',
   btn_ok: '确定',
@@ -56,6 +57,7 @@ const lang: LanguageDict = {
   help: 'Help',
   hide: '隐藏',
   hide_at_launch: '启动时隐藏',
+  hide_dock_icon: '隐藏任务栏(Dock)图标',
   hide_history: '隐藏历史记录',
   hide_others: '隐藏其他',
   homepage: '主页',
@@ -92,7 +94,6 @@ const lang: LanguageDict = {
   migrate_confirm:
     'SwitchHosts v4.0 使用了新的数据存储格式,是否迁移旧数据为新格式?',
   migrate_data: '迁移数据',
-  hide_dock_icon: '隐藏任务栏(Dock)图标',
   minimize: '最小化',
   minute: '分钟',
   minutes: '分钟',
@@ -106,6 +107,7 @@ const lang: LanguageDict = {
   next: '下一个',
   no_access_to_hosts: '没有写入 Hosts 文件的权限。',
   no_record: '没有记录',
+  overwrite: '覆盖',
   password: '密码',
   paste: '粘贴',
   port: '端口',
@@ -171,6 +173,10 @@ const lang: LanguageDict = {
   where_is_my_data: '我的数据存储在哪里?',
   where_is_my_hosts: '我的 hosts 文件在哪里?',
   window: 'Window',
+  write_mode: '写入模式',
+  write_mode_append_help: '新记录将追加到现有系统 hosts 文件末尾。',
+  write_mode_overwrite_help: '新记录将覆盖现有系统 hosts 文件。',
+  write_mode_set: '设置写入模式',
   your_data_is: '你的数据在:',
   your_hosts_file_is: '你的 hosts 文件在:',
   zoom: '缩放',

+ 10 - 1
src/renderer/components/List/index.tsx

@@ -57,7 +57,14 @@ const List = (props: Props) => {
   }, [hosts_data])
 
   const onToggleItem = async (id: string, on: boolean) => {
+    console.log(`writeMode: ${configs?.write_mode}`)
     console.log(`toggle hosts #${id} as ${on ? 'on' : 'off'}`)
+
+    if (!configs?.write_mode) {
+      agent.broadcast(events.show_set_write_mode, { id, on })
+      return
+    }
+
     const new_list = setOnStateOfItem(
       hosts_data.list,
       id,
@@ -77,6 +84,8 @@ const List = (props: Props) => {
     }
   }
 
+  const toSetWriteMode = async () => {}
+
   const writeHostsToSystem = async (
     list?: IHostsListObject[],
     options?: IHostsWriteOptions,
@@ -134,7 +143,7 @@ const List = (props: Props) => {
   }
 
   if (!is_tray) {
-    useOnBroadcast(events.toggle_item, onToggleItem, [hosts_data])
+    useOnBroadcast(events.toggle_item, onToggleItem, [hosts_data, configs])
     useOnBroadcast(events.write_hosts_to_system, writeHostsToSystem, [
       hosts_data,
     ])

+ 37 - 5
src/renderer/components/Pref/General.tsx

@@ -16,7 +16,7 @@ import {
   RadioGroup,
   Select,
   VStack,
-  Stack
+  Stack,
 } from '@chakra-ui/react'
 import { agent } from '@renderer/core/agent'
 import { http_api_port } from '@root/common/constants'
@@ -67,7 +67,7 @@ const General = (props: IProps) => {
         </HStack>
       </FormControl>
 
-      <FormControl pb={6}>
+      <FormControl>
         <HStack>
           <FormLabel w={label_width}>{lang.choice_mode}</FormLabel>
           <VStack align="left">
@@ -95,6 +95,36 @@ const General = (props: IProps) => {
         </HStack>
       </FormControl>
 
+      <FormControl pb={6}>
+        <HStack>
+          <FormLabel w={label_width}>{lang.write_mode}</FormLabel>
+          <VStack align="left">
+            <RadioGroup
+              value={data.write_mode || ''}
+              onChange={(v) =>
+                onChange({
+                  write_mode: v as ConfigsType['write_mode'],
+                })
+              }
+            >
+              <HStack spacing={10}>
+                <Radio value="append">
+                  <Box>{lang.append}</Box>
+                </Radio>
+                <Radio value="overwrite">
+                  <Box>{lang.overwrite}</Box>
+                </Radio>
+              </HStack>
+            </RadioGroup>
+            <FormHelperText>
+              {data.write_mode === 'append' && lang.write_mode_append_help}
+              {data.write_mode === 'overwrite' &&
+                lang.write_mode_overwrite_help}
+            </FormHelperText>
+          </VStack>
+        </HStack>
+      </FormControl>
+
       {platform === 'darwin' ? (
         <FormControl>
           <HStack>
@@ -163,9 +193,11 @@ const General = (props: IProps) => {
           </FormHelperText>
           <Stack pl={6} mt={1} spacing={1}>
             <Checkbox
-                isDisabled={!data.http_api_on}
-                isChecked={data.http_api_only_local}
-                onChange={(e) => onChange({ http_api_only_local: e.target.checked })}
+              isDisabled={!data.http_api_on}
+              isChecked={data.http_api_only_local}
+              onChange={(e) =>
+                onChange({ http_api_only_local: e.target.checked })
+              }
             >
               {lang.http_api_only_local}
             </Checkbox>

+ 8 - 0
src/renderer/components/SetWriteMode.less

@@ -0,0 +1,8 @@
+@import "../styles/common";
+
+.root {
+}
+
+.label {
+  margin: 10px 0 20px 0;
+}

+ 105 - 0
src/renderer/components/SetWriteMode.tsx

@@ -0,0 +1,105 @@
+/**
+ * @author: oldj
+ * @homepage: https://oldj.net
+ */
+
+import { useModel } from '@@/plugin-model/useModel'
+import {
+  Box,
+  Button,
+  HStack,
+  Modal,
+  ModalBody,
+  ModalCloseButton,
+  ModalContent,
+  ModalFooter,
+  ModalOverlay,
+  Radio,
+  RadioGroup,
+} from '@chakra-ui/react'
+import { agent } from '@renderer/core/agent'
+import useOnBroadcast from '@renderer/core/useOnBroadcast'
+import { IHostsListObject } from '@root/common/data'
+import events from '@root/common/events'
+import React, { useState } from 'react'
+import styles from './SetWriteMode.less'
+import { WriteModeType } from '@root/common/default_configs'
+
+interface Props {}
+
+interface IPendingData {
+  id: string
+  on: boolean
+}
+
+const SetWriteMode = (props: Props) => {
+  const { configs, updateConfigs } = useModel('useConfigs')
+  const { lang } = useModel('useI18n')
+  const [is_show, setIsShow] = useState(false)
+  const ipt_ref = React.useRef<HTMLInputElement>(null)
+  const [write_mode, setWriteMode] = useState<WriteModeType>(null)
+  const [pending_data, setPendingData] = useState<IPendingData | undefined>(
+    undefined,
+  )
+
+  const onCancel = () => {
+    setIsShow(false)
+  }
+
+  const onOk = async () => {
+    await updateConfigs({ write_mode })
+    setIsShow(false)
+
+    if (pending_data && pending_data.id) {
+      agent.broadcast(events.toggle_item, pending_data.id, pending_data.on)
+    }
+  }
+
+  useOnBroadcast(
+    events.show_set_write_mode,
+    (data?: IPendingData) => {
+      setIsShow(true)
+      setPendingData(data)
+      agent.broadcast(events.active_main_window)
+    },
+    [],
+  )
+
+  if (!is_show) return null
+
+  return (
+    <Modal initialFocusRef={ipt_ref} isOpen={is_show} onClose={onCancel}>
+      <ModalOverlay />
+      <ModalContent>
+        <ModalCloseButton />
+        <ModalBody pb={6}>
+          <div className={styles.label}>{lang.write_mode_set}</div>
+          <RadioGroup
+            value={write_mode || undefined}
+            onChange={(v) => setWriteMode(v as WriteModeType)}
+          >
+            <HStack spacing={10}>
+              <Radio value={'append'}>追加</Radio>
+              <Radio value={'overwrite'}>覆盖</Radio>
+            </HStack>
+          </RadioGroup>
+
+          <Box h={8} mt={4} opacity={0.5}>
+            {write_mode === 'append' && lang.write_mode_append_help}
+            {write_mode === 'overwrite' && lang.write_mode_overwrite_help}
+          </Box>
+        </ModalBody>
+        <ModalFooter>
+          <Button variant="outline" onClick={onCancel} mr={3}>
+            {lang.btn_cancel}
+          </Button>
+          <Button colorScheme="blue" onClick={onOk}>
+            {lang.btn_ok}
+          </Button>
+        </ModalFooter>
+      </ModalContent>
+    </Modal>
+  )
+}
+
+export default SetWriteMode

+ 2 - 0
src/renderer/pages/index.tsx

@@ -16,6 +16,7 @@ import clsx from 'clsx'
 import React, { useEffect, useState } from 'react'
 import TopBar from '../components/TopBar'
 import styles from './index.less'
+import SetWriteMode from '@renderer/components/SetWriteMode'
 
 export default () => {
   const [loading, setLoading] = useState(true)
@@ -135,6 +136,7 @@ export default () => {
 
       <EditHostsInfo />
       <SudoPasswordInput />
+      <SetWriteMode />
       <PreferencePanel />
       <History />
       <About />