mirror of
https://github.com/pompurin404/mihomo-party.git
synced 2024-11-16 11:42:19 +08:00
support delete backup file
Some checks are pending
Build / windows (arm64) (push) Waiting to run
Build / windows (ia32) (push) Waiting to run
Build / windows (x64) (push) Waiting to run
Build / linux (arm64) (push) Waiting to run
Build / linux (x64) (push) Waiting to run
Build / macos (arm64) (push) Waiting to run
Build / macos (x64) (push) Waiting to run
Build / updater (push) Blocked by required conditions
Build / aur-release-updater (mihomo-party) (push) Blocked by required conditions
Build / aur-release-updater (mihomo-party-bin) (push) Blocked by required conditions
Build / aur-release-updater (mihomo-party-electron) (push) Blocked by required conditions
Build / aur-release-updater (mihomo-party-electron-bin) (push) Blocked by required conditions
Build / aur-git-updater (push) Waiting to run
Some checks are pending
Build / windows (arm64) (push) Waiting to run
Build / windows (ia32) (push) Waiting to run
Build / windows (x64) (push) Waiting to run
Build / linux (arm64) (push) Waiting to run
Build / linux (x64) (push) Waiting to run
Build / macos (arm64) (push) Waiting to run
Build / macos (x64) (push) Waiting to run
Build / updater (push) Blocked by required conditions
Build / aur-release-updater (mihomo-party) (push) Blocked by required conditions
Build / aur-release-updater (mihomo-party-bin) (push) Blocked by required conditions
Build / aur-release-updater (mihomo-party-electron) (push) Blocked by required conditions
Build / aur-release-updater (mihomo-party-electron-bin) (push) Blocked by required conditions
Build / aur-git-updater (push) Waiting to run
This commit is contained in:
parent
ba484070ae
commit
be04031e82
|
@ -1,3 +1,7 @@
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
- 支持删除 Webdav 备份文件
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
- 修复拨号网络系统代理问题
|
- 修复拨号网络系统代理问题
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
"@mihomo-party/sysproxy": "^2.0.0",
|
"@mihomo-party/sysproxy": "^2.0.0",
|
||||||
"adm-zip": "^0.5.15",
|
"adm-zip": "^0.5.15",
|
||||||
"axios": "^1.7.3",
|
"axios": "^1.7.3",
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"webdav": "^5.7.1",
|
"webdav": "^5.7.1",
|
||||||
"ws": "^8.18.0",
|
"ws": "^8.18.0",
|
||||||
"yaml": "^2.5.0"
|
"yaml": "^2.5.0"
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
"@electron-toolkit/eslint-config-ts": "^2.0.0",
|
"@electron-toolkit/eslint-config-ts": "^2.0.0",
|
||||||
"@electron-toolkit/tsconfig": "^1.0.1",
|
"@electron-toolkit/tsconfig": "^1.0.1",
|
||||||
"@nextui-org/react": "^2.4.6",
|
"@nextui-org/react": "^2.4.6",
|
||||||
|
"@types/adm-zip": "^0.5.5",
|
||||||
"@types/node": "^22.1.0",
|
"@types/node": "^22.1.0",
|
||||||
"@types/pubsub-js": "^1.8.6",
|
"@types/pubsub-js": "^1.8.6",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
|
@ -46,7 +48,6 @@
|
||||||
"@vitejs/plugin-react": "^4.3.1",
|
"@vitejs/plugin-react": "^4.3.1",
|
||||||
"apexcharts": "^3.52.0",
|
"apexcharts": "^3.52.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"dayjs": "^1.11.12",
|
|
||||||
"electron": "^31.3.1",
|
"electron": "^31.3.1",
|
||||||
"electron-builder": "^25.0.3",
|
"electron-builder": "^25.0.3",
|
||||||
"electron-vite": "^2.3.0",
|
"electron-vite": "^2.3.0",
|
||||||
|
|
|
@ -23,6 +23,9 @@ importers:
|
||||||
axios:
|
axios:
|
||||||
specifier: ^1.7.3
|
specifier: ^1.7.3
|
||||||
version: 1.7.4
|
version: 1.7.4
|
||||||
|
dayjs:
|
||||||
|
specifier: ^1.11.13
|
||||||
|
version: 1.11.13
|
||||||
webdav:
|
webdav:
|
||||||
specifier: ^5.7.1
|
specifier: ^5.7.1
|
||||||
version: 5.7.1
|
version: 5.7.1
|
||||||
|
@ -54,6 +57,9 @@ importers:
|
||||||
'@nextui-org/react':
|
'@nextui-org/react':
|
||||||
specifier: ^2.4.6
|
specifier: ^2.4.6
|
||||||
version: 2.4.6(@types/react@18.3.3)(framer-motion@11.3.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.10)
|
version: 2.4.6(@types/react@18.3.3)(framer-motion@11.3.28(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwindcss@3.4.10)
|
||||||
|
'@types/adm-zip':
|
||||||
|
specifier: ^0.5.5
|
||||||
|
version: 0.5.5
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.1.0
|
specifier: ^22.1.0
|
||||||
version: 22.4.0
|
version: 22.4.0
|
||||||
|
@ -78,9 +84,6 @@ importers:
|
||||||
autoprefixer:
|
autoprefixer:
|
||||||
specifier: ^10.4.20
|
specifier: ^10.4.20
|
||||||
version: 10.4.20(postcss@8.4.41)
|
version: 10.4.20(postcss@8.4.41)
|
||||||
dayjs:
|
|
||||||
specifier: ^1.11.12
|
|
||||||
version: 1.11.12
|
|
||||||
electron:
|
electron:
|
||||||
specifier: ^31.3.1
|
specifier: ^31.3.1
|
||||||
version: 31.4.0
|
version: 31.4.0
|
||||||
|
@ -1961,6 +1964,9 @@ packages:
|
||||||
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
|
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
|
|
||||||
|
'@types/adm-zip@0.5.5':
|
||||||
|
resolution: {integrity: sha512-YCGstVMjc4LTY5uK9/obvxBya93axZOVOyf2GSUulADzmLhYE45u2nAssCs/fWBs1Ifq5Vat75JTPwd5XZoPJw==}
|
||||||
|
|
||||||
'@types/babel__core@7.20.5':
|
'@types/babel__core@7.20.5':
|
||||||
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
|
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
|
||||||
|
|
||||||
|
@ -2583,8 +2589,8 @@ packages:
|
||||||
resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==}
|
resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
dayjs@1.11.12:
|
dayjs@1.11.13:
|
||||||
resolution: {integrity: sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==}
|
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
|
||||||
|
|
||||||
debug@4.3.6:
|
debug@4.3.6:
|
||||||
resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==}
|
resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==}
|
||||||
|
@ -7531,6 +7537,10 @@ snapshots:
|
||||||
|
|
||||||
'@tootallnate/once@2.0.0': {}
|
'@tootallnate/once@2.0.0': {}
|
||||||
|
|
||||||
|
'@types/adm-zip@0.5.5':
|
||||||
|
dependencies:
|
||||||
|
'@types/node': 22.4.0
|
||||||
|
|
||||||
'@types/babel__core@7.20.5':
|
'@types/babel__core@7.20.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.25.3
|
'@babel/parser': 7.25.3
|
||||||
|
@ -8304,7 +8314,7 @@ snapshots:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
is-data-view: 1.0.1
|
is-data-view: 1.0.1
|
||||||
|
|
||||||
dayjs@1.11.12: {}
|
dayjs@1.11.13: {}
|
||||||
|
|
||||||
debug@4.3.6:
|
debug@4.3.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { getAppConfig } from '../config'
|
import { getAppConfig } from '../config'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
import AdmZip from 'adm-zip'
|
import AdmZip from 'adm-zip'
|
||||||
import {
|
import {
|
||||||
appConfigPath,
|
appConfigPath,
|
||||||
|
@ -23,7 +24,8 @@ export async function webdavBackup(): Promise<boolean> {
|
||||||
zip.addLocalFile(overrideConfigPath())
|
zip.addLocalFile(overrideConfigPath())
|
||||||
zip.addLocalFolder(profilesDir(), 'profiles')
|
zip.addLocalFolder(profilesDir(), 'profiles')
|
||||||
zip.addLocalFolder(overrideDir(), 'override')
|
zip.addLocalFolder(overrideDir(), 'override')
|
||||||
const zipFileName = `backup-${new Date().toISOString().replace(/:/g, '-')}.zip`
|
const date = new Date()
|
||||||
|
const zipFileName = `Backup_${dayjs(date).format('YYYY-MM-DD_HH-mm-ss')}.zip`
|
||||||
|
|
||||||
const client = createClient(webdavUrl, {
|
const client = createClient(webdavUrl, {
|
||||||
username: webdavUsername,
|
username: webdavUsername,
|
||||||
|
@ -47,8 +49,8 @@ export async function webdavRestore(filename: string): Promise<void> {
|
||||||
username: webdavUsername,
|
username: webdavUsername,
|
||||||
password: webdavPassword
|
password: webdavPassword
|
||||||
})
|
})
|
||||||
const zipData = await client.getFileContents(`/mihomo-party/${filename}`)
|
const zipData = await client.getFileContents(`mihomo-party/${filename}`)
|
||||||
const zip = new AdmZip(zipData)
|
const zip = new AdmZip(zipData as Buffer)
|
||||||
zip.extractAllTo(dataDir(), true)
|
zip.extractAllTo(dataDir(), true)
|
||||||
app.relaunch()
|
app.relaunch()
|
||||||
app.quit()
|
app.quit()
|
||||||
|
@ -70,3 +72,15 @@ export async function listWebdavBackups(): Promise<string[]> {
|
||||||
return files.data.map((file) => file.basename)
|
return files.data.map((file) => file.basename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function webdavDelete(filename: string): Promise<void> {
|
||||||
|
const webdav = await import('webdav')
|
||||||
|
const createClient = webdav.createClient
|
||||||
|
const { webdavUrl = '', webdavUsername = '', webdavPassword = '' } = await getAppConfig()
|
||||||
|
|
||||||
|
const client = createClient(webdavUrl, {
|
||||||
|
username: webdavUsername,
|
||||||
|
password: webdavPassword
|
||||||
|
})
|
||||||
|
await client.deleteFile(`mihomo-party/${filename}`)
|
||||||
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ import { checkUpdate, downloadAndInstallUpdate } from '../resolve/autoUpdater'
|
||||||
import { getFilePath, openUWPTool, readTextFile, setNativeTheme, setupFirewall } from '../sys/misc'
|
import { getFilePath, openUWPTool, readTextFile, setNativeTheme, setupFirewall } from '../sys/misc'
|
||||||
import { getRuntimeConfig, getRuntimeConfigStr } from '../core/factory'
|
import { getRuntimeConfig, getRuntimeConfigStr } from '../core/factory'
|
||||||
import { isPortable, setPortable } from './dirs'
|
import { isPortable, setPortable } from './dirs'
|
||||||
import { listWebdavBackups, webdavBackup, webdavRestore } from '../resolve/backup'
|
import { listWebdavBackups, webdavBackup, webdavDelete, webdavRestore } from '../resolve/backup'
|
||||||
import { getInterfaces } from '../sys/interface'
|
import { getInterfaces } from '../sys/interface'
|
||||||
import { copyEnv } from '../resolve/tray'
|
import { copyEnv } from '../resolve/tray'
|
||||||
import { registerShortcut } from '../resolve/shortcut'
|
import { registerShortcut } from '../resolve/shortcut'
|
||||||
|
@ -162,6 +162,7 @@ export function registerIpcMainHandlers(): void {
|
||||||
ipcMain.handle('webdavBackup', ipcErrorWrapper(webdavBackup))
|
ipcMain.handle('webdavBackup', ipcErrorWrapper(webdavBackup))
|
||||||
ipcMain.handle('webdavRestore', (_e, filename) => ipcErrorWrapper(webdavRestore)(filename))
|
ipcMain.handle('webdavRestore', (_e, filename) => ipcErrorWrapper(webdavRestore)(filename))
|
||||||
ipcMain.handle('listWebdavBackups', ipcErrorWrapper(listWebdavBackups))
|
ipcMain.handle('listWebdavBackups', ipcErrorWrapper(listWebdavBackups))
|
||||||
|
ipcMain.handle('webdavDelete', (_e, filename) => ipcErrorWrapper(webdavDelete)(filename))
|
||||||
ipcMain.handle('registerShortcut', (_e, oldShortcut, newShortcut, action) =>
|
ipcMain.handle('registerShortcut', (_e, oldShortcut, newShortcut, action) =>
|
||||||
ipcErrorWrapper(registerShortcut)(oldShortcut, newShortcut, action)
|
ipcErrorWrapper(registerShortcut)(oldShortcut, newShortcut, action)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button } from '@nextui-org/react'
|
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button } from '@nextui-org/react'
|
||||||
import { webdavRestore } from '@renderer/utils/ipc'
|
import { webdavDelete, webdavRestore } from '@renderer/utils/ipc'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
|
import { MdDeleteForever } from 'react-icons/md'
|
||||||
interface Props {
|
interface Props {
|
||||||
filenames: string[]
|
filenames: string[]
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
}
|
}
|
||||||
const WebdavRestoreModal: React.FC<Props> = (props) => {
|
const WebdavRestoreModal: React.FC<Props> = (props) => {
|
||||||
const { filenames, onClose } = props
|
const { filenames: names, onClose } = props
|
||||||
|
const [filenames, setFilenames] = useState<string[]>(names)
|
||||||
const [restoring, setRestoring] = useState(false)
|
const [restoring, setRestoring] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -24,25 +26,42 @@ const WebdavRestoreModal: React.FC<Props> = (props) => {
|
||||||
<div className="flex justify-center">还没有备份</div>
|
<div className="flex justify-center">还没有备份</div>
|
||||||
) : (
|
) : (
|
||||||
filenames.map((filename) => (
|
filenames.map((filename) => (
|
||||||
<Button
|
<div className="flex" key={filename}>
|
||||||
size="sm"
|
<Button
|
||||||
fullWidth
|
size="sm"
|
||||||
key={filename}
|
fullWidth
|
||||||
isLoading={restoring}
|
isLoading={restoring}
|
||||||
variant="flat"
|
variant="flat"
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
setRestoring(true)
|
setRestoring(true)
|
||||||
try {
|
try {
|
||||||
await webdavRestore(filename)
|
await webdavRestore(filename)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert(`恢复失败: ${e}`)
|
alert(`恢复失败: ${e}`)
|
||||||
} finally {
|
} finally {
|
||||||
setRestoring(false)
|
setRestoring(false)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{filename}
|
{filename}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
color="warning"
|
||||||
|
variant="flat"
|
||||||
|
className="ml-2"
|
||||||
|
onClick={async () => {
|
||||||
|
try {
|
||||||
|
await webdavDelete(filename)
|
||||||
|
setFilenames(filenames.filter((name) => name !== filename))
|
||||||
|
} catch (e) {
|
||||||
|
alert(`删除失败: ${e}`)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MdDeleteForever className="text-lg" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
|
@ -283,6 +283,10 @@ export async function listWebdavBackups(): Promise<string[]> {
|
||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('listWebdavBackups'))
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('listWebdavBackups'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function webdavDelete(filename: string): Promise<void> {
|
||||||
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('webdavDelete', filename))
|
||||||
|
}
|
||||||
|
|
||||||
export async function quitApp(): Promise<void> {
|
export async function quitApp(): Promise<void> {
|
||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('quitApp'))
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('quitApp'))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user