From 393a32bcfeaa330a436ced4ec7d86d3b7f0c2fd0 Mon Sep 17 00:00:00 2001 From: xmk23333 Date: Sun, 14 Dec 2025 21:46:43 +0800 Subject: [PATCH] feat: add WebDAV certificate ignore option and improve event listener cleanup --- src/main/resolve/backup.ts | 16 ++++- .../src/components/settings/webdav-config.tsx | 18 +++++- src/renderer/src/hooks/use-app-config.tsx | 7 ++- .../src/hooks/use-controled-mihomo-config.tsx | 7 ++- src/renderer/src/hooks/use-groups.tsx | 7 ++- src/renderer/src/hooks/use-profile-config.tsx | 7 ++- src/renderer/src/hooks/use-rules.tsx | 7 ++- src/renderer/src/locales/en-US.json | 1 + src/renderer/src/locales/fa-IR.json | 1 + src/renderer/src/locales/ru-RU.json | 1 + src/renderer/src/locales/zh-CN.json | 1 + src/renderer/src/locales/zh-TW.json | 1 + src/renderer/src/pages/mihomo.tsx | 59 ++++++++++++------- src/renderer/src/pages/profiles.tsx | 4 +- src/renderer/src/pages/proxies.tsx | 31 ++++++++-- src/renderer/src/pages/tun.tsx | 3 +- src/shared/types.d.ts | 1 + 17 files changed, 120 insertions(+), 52 deletions(-) diff --git a/src/main/resolve/backup.ts b/src/main/resolve/backup.ts index 639b484..6006670 100644 --- a/src/main/resolve/backup.ts +++ b/src/main/resolve/backup.ts @@ -1,6 +1,7 @@ import { getAppConfig } from '../config' import dayjs from 'dayjs' import AdmZip from 'adm-zip' +import https from 'https' import { appConfigPath, controledMihomoConfigPath, @@ -34,13 +35,22 @@ async function getWebDAVClient(): Promise { webdavUsername = '', webdavPassword = '', webdavDir = 'clash-party', - webdavMaxBackups = 0 + webdavMaxBackups = 0, + webdavIgnoreCert = false } = await getAppConfig() - const client = createClient(webdavUrl, { + const clientOptions: Parameters[1] = { username: webdavUsername, password: webdavPassword - }) + } + + if (webdavIgnoreCert) { + clientOptions.httpsAgent = new https.Agent({ + rejectUnauthorized: false + }) + } + + const client = createClient(webdavUrl, clientOptions) return { client, webdavDir, webdavMaxBackups } } diff --git a/src/renderer/src/components/settings/webdav-config.tsx b/src/renderer/src/components/settings/webdav-config.tsx index 5c28785..9659c59 100644 --- a/src/renderer/src/components/settings/webdav-config.tsx +++ b/src/renderer/src/components/settings/webdav-config.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react' import SettingCard from '../base/base-setting-card' import { toast } from '@renderer/components/base/toast' import SettingItem from '../base/base-setting-item' -import { Button, Input, Select, SelectItem } from '@heroui/react' +import { Button, Input, Select, SelectItem, Switch } from '@heroui/react' import { listWebdavBackups, webdavBackup, reinitWebdavBackupScheduler } from '@renderer/utils/ipc' import WebdavRestoreModal from './webdav-restore-modal' import debounce from '@renderer/utils/debounce' @@ -19,7 +19,8 @@ const WebdavConfig: React.FC = () => { webdavPassword, webdavDir = 'clash-party', webdavMaxBackups = 0, - webdavBackupCron + webdavBackupCron, + webdavIgnoreCert = false } = appConfig || {} const [backuping, setBackuping] = useState(false) const [restoring, setRestoring] = useState(false) @@ -32,7 +33,8 @@ const WebdavConfig: React.FC = () => { webdavPassword, webdavDir, webdavMaxBackups, - webdavBackupCron + webdavBackupCron, + webdavIgnoreCert }) const setWebdavDebounce = debounce( ({ webdavUrl, webdavUsername, webdavPassword, webdavDir, webdavMaxBackups, webdavBackupCron }) => { @@ -139,6 +141,16 @@ const WebdavConfig: React.FC = () => { 20 + + { + setWebdav({ ...webdav, webdavIgnoreCert: v }) + patchAppConfig({ webdavIgnoreCert: v }) + }} + /> +
{webdavBackupCron !== webdav.webdavBackupCron && ( diff --git a/src/renderer/src/hooks/use-app-config.tsx b/src/renderer/src/hooks/use-app-config.tsx index 72dff27..bf415a0 100644 --- a/src/renderer/src/hooks/use-app-config.tsx +++ b/src/renderer/src/hooks/use-app-config.tsx @@ -25,11 +25,12 @@ export const AppConfigProvider: React.FC<{ children: ReactNode }> = ({ children } React.useEffect(() => { - window.electron.ipcRenderer.on('appConfigUpdated', () => { + const handler = (): void => { mutateAppConfig() - }) + } + window.electron.ipcRenderer.on('appConfigUpdated', handler) return (): void => { - window.electron.ipcRenderer.removeAllListeners('appConfigUpdated') + window.electron.ipcRenderer.removeListener('appConfigUpdated', handler) } }, []) diff --git a/src/renderer/src/hooks/use-controled-mihomo-config.tsx b/src/renderer/src/hooks/use-controled-mihomo-config.tsx index a89cd30..a1b0a7a 100644 --- a/src/renderer/src/hooks/use-controled-mihomo-config.tsx +++ b/src/renderer/src/hooks/use-controled-mihomo-config.tsx @@ -30,11 +30,12 @@ export const ControledMihomoConfigProvider: React.FC<{ children: ReactNode }> = } React.useEffect(() => { - window.electron.ipcRenderer.on('controledMihomoConfigUpdated', () => { + const handler = (): void => { mutateControledMihomoConfig() - }) + } + window.electron.ipcRenderer.on('controledMihomoConfigUpdated', handler) return (): void => { - window.electron.ipcRenderer.removeAllListeners('controledMihomoConfigUpdated') + window.electron.ipcRenderer.removeListener('controledMihomoConfigUpdated', handler) } }, []) diff --git a/src/renderer/src/hooks/use-groups.tsx b/src/renderer/src/hooks/use-groups.tsx index 557dc18..4458311 100644 --- a/src/renderer/src/hooks/use-groups.tsx +++ b/src/renderer/src/hooks/use-groups.tsx @@ -20,11 +20,12 @@ export const GroupsProvider: React.FC<{ children: ReactNode }> = ({ children }) }) React.useEffect(() => { - window.electron.ipcRenderer.on('groupsUpdated', () => { + const handler = (): void => { mutate() - }) + } + window.electron.ipcRenderer.on('groupsUpdated', handler) return (): void => { - window.electron.ipcRenderer.removeAllListeners('groupsUpdated') + window.electron.ipcRenderer.removeListener('groupsUpdated', handler) } }, []) diff --git a/src/renderer/src/hooks/use-profile-config.tsx b/src/renderer/src/hooks/use-profile-config.tsx index fa949d3..4d9a2be 100644 --- a/src/renderer/src/hooks/use-profile-config.tsx +++ b/src/renderer/src/hooks/use-profile-config.tsx @@ -119,11 +119,12 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child } React.useEffect(() => { - window.electron.ipcRenderer.on('profileConfigUpdated', () => { + const handler = (): void => { mutateProfileConfig() - }) + } + window.electron.ipcRenderer.on('profileConfigUpdated', handler) return (): void => { - window.electron.ipcRenderer.removeAllListeners('profileConfigUpdated') + window.electron.ipcRenderer.removeListener('profileConfigUpdated', handler) } }, []) diff --git a/src/renderer/src/hooks/use-rules.tsx b/src/renderer/src/hooks/use-rules.tsx index 357880d..411be1d 100644 --- a/src/renderer/src/hooks/use-rules.tsx +++ b/src/renderer/src/hooks/use-rules.tsx @@ -16,11 +16,12 @@ export const RulesProvider: React.FC<{ children: ReactNode }> = ({ children }) = }) React.useEffect(() => { - window.electron.ipcRenderer.on('rulesUpdated', () => { + const handler = (): void => { mutate() - }) + } + window.electron.ipcRenderer.on('rulesUpdated', handler) return (): void => { - window.electron.ipcRenderer.removeAllListeners('rulesUpdated') + window.electron.ipcRenderer.removeListener('rulesUpdated', handler) } }, []) diff --git a/src/renderer/src/locales/en-US.json b/src/renderer/src/locales/en-US.json index 7f7f46d..4de05f8 100644 --- a/src/renderer/src/locales/en-US.json +++ b/src/renderer/src/locales/en-US.json @@ -236,6 +236,7 @@ "webdav.username": "WebDAV Username", "webdav.password": "WebDAV Password", "webdav.maxBackups": "Max Backups", + "webdav.ignoreCert": "Ignore Certificate", "webdav.noLimit": "No Limit", "webdav.backup": "Backup", "webdav.backup.cron.title": "Schedule Config Backup", diff --git a/src/renderer/src/locales/fa-IR.json b/src/renderer/src/locales/fa-IR.json index b8eedb0..fa93e4e 100644 --- a/src/renderer/src/locales/fa-IR.json +++ b/src/renderer/src/locales/fa-IR.json @@ -211,6 +211,7 @@ "webdav.username": "نام کاربری WebDAV", "webdav.password": "رمز عبور WebDAV", "webdav.maxBackups": "حداکثر نسخه پشتیبان", + "webdav.ignoreCert": "نادیده گرفتن گواهی", "webdav.noLimit": "بدون محدودیت", "webdav.backup": "پشتیبان‌گیری", "webdav.backup.cron.title": "زمانبندی پشتیبان‌گیری پیکربندی", diff --git a/src/renderer/src/locales/ru-RU.json b/src/renderer/src/locales/ru-RU.json index b8fd524..415d2f8 100644 --- a/src/renderer/src/locales/ru-RU.json +++ b/src/renderer/src/locales/ru-RU.json @@ -211,6 +211,7 @@ "webdav.username": "Имя пользователя WebDAV", "webdav.password": "Пароль WebDAV", "webdav.maxBackups": "Максимум резервных копий", + "webdav.ignoreCert": "Игнорировать сертификат", "webdav.noLimit": "Без ограничений", "webdav.backup": "Резервное копирование", "webdav.backup.cron.title": "Расписание резервного копирования", diff --git a/src/renderer/src/locales/zh-CN.json b/src/renderer/src/locales/zh-CN.json index 33748ba..ba21a5e 100644 --- a/src/renderer/src/locales/zh-CN.json +++ b/src/renderer/src/locales/zh-CN.json @@ -236,6 +236,7 @@ "webdav.username": "WebDAV 用户名", "webdav.password": "WebDAV 密码", "webdav.maxBackups": "最大备份数", + "webdav.ignoreCert": "忽略证书验证", "webdav.noLimit": "不限制", "webdav.backup": "备份", "webdav.backup.cron.title": "定时备份配置", diff --git a/src/renderer/src/locales/zh-TW.json b/src/renderer/src/locales/zh-TW.json index 771509e..c88e627 100644 --- a/src/renderer/src/locales/zh-TW.json +++ b/src/renderer/src/locales/zh-TW.json @@ -236,6 +236,7 @@ "webdav.username": "WebDAV 用戶名", "webdav.password": "WebDAV 密碼", "webdav.maxBackups": "最大備份數", + "webdav.ignoreCert": "忽略證書驗證", "webdav.noLimit": "不限制", "webdav.backup": "備份", "webdav.backup.cron.title": "定時備份配置", diff --git a/src/renderer/src/pages/mihomo.tsx b/src/renderer/src/pages/mihomo.tsx index 69cd945..e150fd4 100644 --- a/src/renderer/src/pages/mihomo.tsx +++ b/src/renderer/src/pages/mihomo.tsx @@ -620,8 +620,10 @@ const Mihomo: React.FC = () => { type="number" value={smartCollectorSize.toString()} onValueChange={async (v: string) => { - let num = parseInt(v) - await patchAppConfig({ smartCollectorSize: num }) + const num = parseInt(v) + if (!isNaN(num)) { + await patchAppConfig({ smartCollectorSize: num }) + } }} onBlur={async (e) => { let num = parseInt(e.target.value) @@ -690,9 +692,11 @@ const Mihomo: React.FC = () => { min={0} onValueChange={(v) => { const port = parseInt(v) - setMixedPortInput(port) - patchAppConfig({ showMixedPort: port }) - setIsManualPortChange(true) + if (!isNaN(port)) { + setMixedPortInput(port) + patchAppConfig({ showMixedPort: port }) + setIsManualPortChange(true) + } }} />
- {lanDisallowedIpsInput.join('') !== lanDisallowedIps.join('') && ( + {JSON.stringify(lanDisallowedIpsInput) !== JSON.stringify(lanDisallowedIps) && (