improve error handling

This commit is contained in:
pompurin404 2024-08-13 17:34:36 +08:00
parent bedf3f8173
commit 2d6e8f5fd0
No known key found for this signature in database
17 changed files with 190 additions and 114 deletions

View File

@ -94,7 +94,7 @@ const ProfileItem: React.FC<Props> = (props) => {
return list
}, [info])
const onMenuAction = (key: Key): void => {
const onMenuAction = async (key: Key): Promise<void> => {
switch (key) {
case 'edit-info': {
setOpenInfo(true)
@ -105,7 +105,7 @@ const ProfileItem: React.FC<Props> = (props) => {
break
}
case 'delete': {
removeProfileItem(info.id)
await removeProfileItem(info.id)
mutateProfileConfig()
break
}
@ -177,15 +177,10 @@ const ProfileItem: React.FC<Props> = (props) => {
variant="light"
color="default"
disabled={updating}
onPress={() => {
onPress={async () => {
setUpdating(true)
addProfileItem(info)
.catch((e) => {
alert(e)
})
.finally(() => {
setUpdating(false)
})
await addProfileItem(info)
setUpdating(false)
}}
>
<IoMdRefresh

View File

@ -115,16 +115,16 @@ const GeoData: React.FC = () => {
size="sm"
isIconOnly
variant="light"
onPress={() => {
onPress={async () => {
setUpdating(true)
mihomoUpgradeGeo()
.catch((e) => {
new Notification('更新失败', { body: e.message })
})
.finally(() => {
new Notification('Geo 数据库更新成功')
setUpdating(false)
})
try {
await mihomoUpgradeGeo()
new Notification('Geo 数据库更新成功')
} catch (e) {
alert(e)
} finally {
setUpdating(false)
}
}}
>
<IoMdRefresh className={`text-lg ${updating ? 'animate-spin' : ''}`} />

View File

@ -20,18 +20,22 @@ const ProxyProvider: React.FC = () => {
}, [data])
const [updating, setUpdating] = useState(Array(providers.length).fill(false))
const onUpdate = (name: string, index: number): void => {
const onUpdate = async (name: string, index: number): Promise<void> => {
setUpdating((prev) => {
prev[index] = true
return [...prev]
})
mihomoUpdateProxyProviders(name).finally(() => {
try {
await mihomoUpdateProxyProviders(name)
mutate()
} catch (e) {
alert(e)
} finally {
setUpdating((prev) => {
prev[index] = false
return [...prev]
})
mutate()
})
}
}
if (!providers.length) {

View File

@ -15,18 +15,22 @@ const RuleProvider: React.FC = () => {
}, [data])
const [updating, setUpdating] = useState(Array(providers.length).fill(false))
const onUpdate = (name: string, index: number): void => {
const onUpdate = async (name: string, index: number): Promise<void> => {
setUpdating((prev) => {
prev[index] = true
return [...prev]
})
mihomoUpdateRuleProviders(name).finally(() => {
try {
await mihomoUpdateRuleProviders(name)
mutate()
} catch (e) {
alert(e)
} finally {
setUpdating((prev) => {
prev[index] = false
return [...prev]
})
mutate()
})
}
}
if (!providers.length) {

View File

@ -22,9 +22,6 @@ const MihomoCoreCard: React.FC = () => {
useEffect(() => {
const token = PubSub.subscribe('mihomo-core-changed', () => {
mutate()
setTimeout(() => {
mutate()
}, 1000)
})
window.electron.ipcRenderer.on('mihomoMemory', (_e, info: IMihomoMemoryInfo) => {
setMem(info.inuse)
@ -70,11 +67,13 @@ const MihomoCoreCard: React.FC = () => {
variant="light"
color="default"
onPress={async () => {
await restartCore()
mutate()
setTimeout(() => {
try {
await restartCore()
} catch (e) {
alert(e)
} finally {
mutate()
}, 2000)
}
}}
>
<IoMdRefresh className={`${match ? 'text-white' : 'text-foreground'} text-[24px]`} />

View File

@ -87,11 +87,10 @@ const ProfileCard: React.FC = () => {
disabled={updating}
variant="light"
color="default"
onPress={() => {
onPress={async () => {
setUpdating(true)
addProfileItem(info).finally(() => {
setUpdating(false)
})
await addProfileItem(info)
setUpdating(false)
}}
>
<IoMdRefresh

View File

@ -12,9 +12,14 @@ export const useAppConfig = (listenUpdate = false): RetuenType => {
const { data: appConfig, mutate: mutateAppConfig } = useSWR('getConfig', () => getAppConfig())
const patchAppConfig = async (value: Partial<IAppConfig>): Promise<void> => {
await patch(value)
mutateAppConfig()
window.electron.ipcRenderer.send('appConfigUpdated')
try {
await patch(value)
} catch (e) {
alert(e)
} finally {
mutateAppConfig()
window.electron.ipcRenderer.send('appConfigUpdated')
}
}
useEffect(() => {

View File

@ -15,9 +15,14 @@ export const useControledMihomoConfig = (listenUpdate = false): RetuenType => {
)
const patchControledMihomoConfig = async (value: Partial<IMihomoConfig>): Promise<void> => {
await patch(value)
mutateControledMihomoConfig()
window.electron.ipcRenderer.send('controledMihomoConfigUpdated')
try {
await patch(value)
} catch (e) {
alert(e)
} finally {
mutateControledMihomoConfig()
window.electron.ipcRenderer.send('controledMihomoConfigUpdated')
}
}
useEffect(() => {

View File

@ -22,23 +22,43 @@ export const useOverrideConfig = (): RetuenType => {
)
const setOverrideConfig = async (config: IOverrideConfig): Promise<void> => {
await set(config)
mutateOverrideConfig()
try {
await set(config)
} catch (e) {
alert(e)
} finally {
mutateOverrideConfig()
}
}
const addOverrideItem = async (item: Partial<IOverrideItem>): Promise<void> => {
await add(item)
mutateOverrideConfig()
try {
await add(item)
} catch (e) {
alert(e)
} finally {
mutateOverrideConfig()
}
}
const removeOverrideItem = async (id: string): Promise<void> => {
await remove(id)
mutateOverrideConfig()
try {
await remove(id)
} catch (e) {
alert(e)
} finally {
mutateOverrideConfig()
}
}
const updateOverrideItem = async (item: IOverrideItem): Promise<void> => {
await update(item)
mutateOverrideConfig()
try {
await update(item)
} catch (e) {
alert(e)
} finally {
mutateOverrideConfig()
}
}
return {

View File

@ -25,28 +25,53 @@ export const useProfileConfig = (): RetuenType => {
)
const setProfileConfig = async (config: IProfileConfig): Promise<void> => {
await set(config)
mutateProfileConfig()
try {
await set(config)
} catch (e) {
alert(e)
} finally {
mutateProfileConfig()
}
}
const addProfileItem = async (item: Partial<IProfileItem>): Promise<void> => {
await add(item)
mutateProfileConfig()
try {
await add(item)
} catch (e) {
alert(e)
} finally {
mutateProfileConfig()
}
}
const removeProfileItem = async (id: string): Promise<void> => {
await remove(id)
mutateProfileConfig()
try {
await remove(id)
} catch (e) {
alert(e)
} finally {
mutateProfileConfig()
}
}
const updateProfileItem = async (item: IProfileItem): Promise<void> => {
await update(item)
mutateProfileConfig()
try {
await update(item)
} catch (e) {
alert(e)
} finally {
mutateProfileConfig()
}
}
const changeCurrentProfile = async (id: string): Promise<void> => {
await change(id)
mutateProfileConfig()
try {
await change(id)
} catch (e) {
alert(e)
} finally {
mutateProfileConfig()
}
}
useEffect(() => {

View File

@ -59,8 +59,14 @@ const Mihomo: React.FC = () => {
size="sm"
selectedKeys={new Set([core])}
onSelectionChange={async (v) => {
await patchAppConfig({ core: v.currentKey as 'mihomo' | 'mihomo-alpha' })
restartCore().then(() => PubSub.publish('mihomo-core-changed'))
try {
await patchAppConfig({ core: v.currentKey as 'mihomo' | 'mihomo-alpha' })
await restartCore()
} catch (e) {
alert(e)
} finally {
PubSub.publish('mihomo-core-changed')
}
}}
>
<SelectItem key="mihomo">{CoreMap['mihomo']}</SelectItem>

View File

@ -33,13 +33,8 @@ const Profiles: React.FC = () => {
const sensors = useSensors(useSensor(PointerSensor))
const handleImport = async (): Promise<void> => {
setImporting(true)
try {
await addProfileItem({ name: '', type: 'remote', url })
} catch (e) {
alert(e)
} finally {
setImporting(false)
}
await addProfileItem({ name: '', type: 'remote', url })
setImporting(false)
}
const pageRef = useRef<HTMLDivElement>(null)
@ -75,11 +70,11 @@ const Profiles: React.FC = () => {
if (event.dataTransfer?.files) {
const file = event.dataTransfer.files[0]
if (file.name.endsWith('.yml') || file.name.endsWith('.yaml')) {
const content = await readTextFile(file.path)
try {
const content = await readTextFile(file.path)
await addProfileItem({ name: file.name, type: 'local', file: content })
} finally {
setFileOver(false)
} catch (e) {
alert(e)
}
} else {
alert('不支持的文件类型')
@ -135,14 +130,17 @@ const Profiles: React.FC = () => {
size="sm"
color="primary"
className="ml-2"
onPress={() => {
getFilePath(['yml', 'yaml']).then(async (files) => {
onPress={async () => {
try {
const files = await getFilePath(['yml', 'yaml'])
if (files?.length) {
const content = await readTextFile(files[0])
const fileName = files[0].split('/').pop()?.split('\\').pop()
await addProfileItem({ name: fileName, type: 'local', file: content })
}
})
} catch (e) {
alert(e)
}
}}
>
@ -167,11 +165,7 @@ const Profiles: React.FC = () => {
updateProfileItem={updateProfileItem}
info={item}
onClick={async () => {
try {
await changeCurrentProfile(item.id)
} catch (e) {
alert(e)
}
await changeCurrentProfile(item.id)
}}
/>
))}

View File

@ -83,13 +83,12 @@ const Proxies: React.FC = () => {
return { groupCounts, allProxies }
}, [groups, isOpen, proxyDisplayOrder])
const onChangeProxy = (group: string, proxy: string): void => {
mihomoChangeProxy(group, proxy).then(() => {
if (autoCloseConnection) {
mihomoCloseAllConnections()
}
mutate()
})
const onChangeProxy = async (group: string, proxy: string): Promise<void> => {
await mihomoChangeProxy(group, proxy)
if (autoCloseConnection) {
await mihomoCloseAllConnections()
}
mutate()
}
const onProxyDelay = async (proxy: string, url?: string): Promise<IMihomoDelay> => {
@ -152,7 +151,7 @@ const Proxies: React.FC = () => {
style={{ height: 'calc(100vh - 50px)' }}
groupCounts={groupCounts}
groupContent={(index) => {
return (
return groups[index] ? (
<div
className={`w-full pt-2 ${index === groupCounts.length - 1 && !isOpen[index] ? 'pb-2' : ''} px-2`}
>
@ -242,6 +241,8 @@ const Proxies: React.FC = () => {
</CardBody>
</Card>
</div>
) : (
<div>Never See This</div>
)
}}
itemContent={(index, groupIndex) => {

View File

@ -86,13 +86,18 @@ const Settings: React.FC = () => {
<Switch
size="sm"
isSelected={enable}
onValueChange={(v) => {
if (v) {
enableAutoRun()
} else {
disableAutoRun()
onValueChange={async (v) => {
try {
if (v) {
await enableAutoRun()
} else {
await disableAutoRun()
}
} catch (e) {
alert(e)
} finally {
mutate()
}
mutate()
}}
/>
</SettingItem>
@ -196,17 +201,22 @@ const Settings: React.FC = () => {
<SettingItem title="检查更新" divider>
<Button
size="sm"
onPress={() => {
checkUpdate().then((v) => {
if (v) {
new window.Notification(`v${v}版本已发布`, { body: '点击前往下载' }).onclick =
(): void => {
open(`https://github.com/pompurin404/mihomo-party/releases/tag/v${v}`)
}
onPress={async () => {
try {
const version = await checkUpdate()
if (version) {
new window.Notification(`v${version}版本已发布`, {
body: '点击前往下载'
}).onclick = (): void => {
open(`https://github.com/pompurin404/mihomo-party/releases/tag/v${version}`)
}
} else {
new window.Notification('当前已是最新版本', { body: '无需更新' })
}
})
} catch (e) {
alert(e)
}
}}
>

View File

@ -5,7 +5,7 @@ import SettingItem from '@renderer/components/base/base-setting-item'
import PacEditorViewer from '@renderer/components/sysproxy/pac-editor-modal'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import { platform } from '@renderer/utils/init'
import { triggerSysProxy } from '@renderer/utils/ipc'
import { openUWPTool, triggerSysProxy } from '@renderer/utils/ipc'
import { Key, useState } from 'react'
import React from 'react'
import { MdDeleteForever } from 'react-icons/md'
@ -90,7 +90,8 @@ const Sysproxy: React.FC = () => {
try {
await triggerSysProxy(true)
await patchAppConfig({ sysProxy: { enable: true } })
} catch {
} catch (e) {
alert(e)
await patchAppConfig({ sysProxy: { enable: false } })
}
}
@ -141,8 +142,8 @@ const Sysproxy: React.FC = () => {
<SettingItem title="UWP 工具" divider>
<Button
size="sm"
onPress={() => {
window.electron.ipcRenderer.invoke('openUWPTool')
onPress={async () => {
await openUWPTool()
}}
>
UWP

View File

@ -71,13 +71,17 @@ const Tun: React.FC = () => {
size="sm"
color="primary"
isLoading={loading}
onPress={() => {
onPress={async () => {
setLoading(true)
setupFirewall()
.then(() => {
new Notification('防火墙重设成功')
})
.finally(() => setLoading(false))
try {
await setupFirewall()
new Notification('防火墙重设成功')
await restartCore()
} catch (e) {
alert(e)
} finally {
setLoading(false)
}
}}
>

View File

@ -233,6 +233,10 @@ export async function getPlatform(): Promise<NodeJS.Platform> {
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('platform'))
}
export async function openUWPTool(): Promise<void> {
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('openUWPTool'))
}
export async function setupFirewall(): Promise<void> {
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('setupFirewall'))
}