Skip to content

Commit

Permalink
Add provider file view/edit
Browse files Browse the repository at this point in the history
  • Loading branch information
xishang0128 committed Nov 20, 2024
1 parent 7b1fc24 commit e265317
Show file tree
Hide file tree
Showing 13 changed files with 356 additions and 99 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
"@electron-toolkit/preload": "^3.0.1",
"@electron-toolkit/utils": "^3.0.0",
"@mihomo-party/sysproxy": "^2.0.4",
"@types/crypto-js": "^4.2.2",
"adm-zip": "^0.5.16",
"axios": "^1.7.7",
"chokidar": "^4.0.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.13",
"express": "^5.0.1",
"iconv-lite": "^0.6.3",
Expand Down
16 changes: 16 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/main/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export {
getCurrentProfileItem,
getProfileItem,
getProfileConfig,
getFileStr,
setFileStr,
setProfileConfig,
addProfileItem,
removeProfileItem,
Expand Down
28 changes: 24 additions & 4 deletions src/main/config/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,10 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi
res = await axios.get(item.url, {
proxy: newItem.useProxy
? {
protocol: 'http',
host: '127.0.0.1',
port: mixedPort
}
protocol: 'http',
host: '127.0.0.1',
port: mixedPort
}
: false,
headers: {
'User-Agent': userAgent || 'clash.meta'
Expand Down Expand Up @@ -220,3 +220,23 @@ function parseSubinfo(str: string): ISubscriptionUserInfo {
})
return obj
}

function isAbsolutePath(path: string): boolean {
return path.startsWith('/') || /^[a-zA-Z]:\\/.test(path);
}

export async function getFileStr(path: string): Promise<string> {
if (isAbsolutePath(path)) {
return await readFile(path, 'utf-8')
} else {
return await readFile(mihomoProfileWorkDir(path), 'utf-8')
}
}

export async function setFileStr(path: string, content: string): Promise<void> {
if (isAbsolutePath(path)) {
await writeFile(path, content, 'utf-8')
} else {
await writeFile(mihomoProfileWorkDir(path), content, 'utf-8')
}
}
16 changes: 13 additions & 3 deletions src/main/core/mihomoApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ export const mihomoUpdateProxyProviders = async (name: string): Promise<void> =>
return await instance.put(`/providers/proxies/${encodeURIComponent(name)}`)
}

export const mihomoRunProxyProviders = async (): Promise<IMihomoProxyProviders> => {
const runtime = await getRuntimeConfig()
return runtime?.['proxy-providers']
}

export const mihomoRuleProviders = async (): Promise<IMihomoRuleProviders> => {
const instance = await getAxios()
return await instance.get('/providers/rules')
Expand All @@ -124,6 +129,11 @@ export const mihomoUpdateRuleProviders = async (name: string): Promise<void> =>
return await instance.put(`/providers/rules/${encodeURIComponent(name)}`)
}

export const mihomoRunRuleProviders = async (): Promise<IMihomoRuleProviders> => {
const runtime = await getRuntimeConfig()
return runtime?.['rule-providers']
}

export const mihomoChangeProxy = async (group: string, proxy: string): Promise<IMihomoProxy> => {
const instance = await getAxios()
return await instance.put(`/proxies/${encodeURIComponent(group)}`, { name: proxy })
Expand Down Expand Up @@ -194,9 +204,9 @@ const mihomoTraffic = async (): Promise<void> => {
if (process.platform !== 'linux') {
tray?.setToolTip(
'↑' +
`${calcTraffic(json.up)}/s`.padStart(9) +
'\n↓' +
`${calcTraffic(json.down)}/s`.padStart(9)
`${calcTraffic(json.up)}/s`.padStart(9) +
'\n↓' +
`${calcTraffic(json.down)}/s`.padStart(9)
)
}
floatingWindow?.webContents.send('mihomoTraffic', json)
Expand Down
8 changes: 8 additions & 0 deletions src/main/utils/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
mihomoProxies,
mihomoProxyDelay,
mihomoProxyProviders,
mihomoRunProxyProviders,
mihomoRuleProviders,
mihomoRunRuleProviders,
mihomoRules,
mihomoUnfixedProxy,
mihomoUpdateProxyProviders,
Expand All @@ -31,6 +33,8 @@ import {
removeProfileItem,
changeCurrentProfile,
getProfileStr,
getFileStr,
setFileStr,
setProfileStr,
updateProfileItem,
setProfileConfig,
Expand Down Expand Up @@ -115,10 +119,12 @@ export function registerIpcMainHandlers(): void {
ipcMain.handle('mihomoProxies', ipcErrorWrapper(mihomoProxies))
ipcMain.handle('mihomoGroups', ipcErrorWrapper(mihomoGroups))
ipcMain.handle('mihomoProxyProviders', ipcErrorWrapper(mihomoProxyProviders))
ipcMain.handle('mihomoRunProxyProviders', ipcErrorWrapper(mihomoRunProxyProviders))
ipcMain.handle('mihomoUpdateProxyProviders', (_e, name) =>
ipcErrorWrapper(mihomoUpdateProxyProviders)(name)
)
ipcMain.handle('mihomoRuleProviders', ipcErrorWrapper(mihomoRuleProviders))
ipcMain.handle('mihomoRunRuleProviders', ipcErrorWrapper(mihomoRunRuleProviders))
ipcMain.handle('mihomoUpdateRuleProviders', (_e, name) =>
ipcErrorWrapper(mihomoUpdateRuleProviders)(name)
)
Expand Down Expand Up @@ -151,6 +157,8 @@ export function registerIpcMainHandlers(): void {
ipcMain.handle('getCurrentProfileItem', ipcErrorWrapper(getCurrentProfileItem))
ipcMain.handle('getProfileItem', (_e, id) => ipcErrorWrapper(getProfileItem)(id))
ipcMain.handle('getProfileStr', (_e, id) => ipcErrorWrapper(getProfileStr)(id))
ipcMain.handle('getFileStr', (_e, path) => ipcErrorWrapper(getFileStr)(path))
ipcMain.handle('setFileStr', (_e, path, str) => ipcErrorWrapper(setFileStr)(path, str))
ipcMain.handle('setProfileStr', (_e, id, str) => ipcErrorWrapper(setProfileStr)(id, str))
ipcMain.handle('updateProfileItem', (_e, item) => ipcErrorWrapper(updateProfileItem)(item))
ipcMain.handle('changeCurrentProfile', (_e, id) => ipcErrorWrapper(changeCurrentProfile)(id))
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/src/components/base/base-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import pac from 'types-pac/pac.d.ts?raw'
import { useTheme } from 'next-themes'
import { nanoid } from 'nanoid'
import React from 'react'
type Language = 'yaml' | 'javascript' | 'css'
type Language = 'yaml' | 'javascript' | 'css' | 'json' | 'text'

interface Props {
value: string
Expand Down Expand Up @@ -125,9 +125,9 @@ export const BaseEditor: React.FC<Props> = (props) => {
options={{
tabSize: ['yaml', 'javascript', 'json'].includes(language) ? 2 : 4, // 根据语言类型设置缩进大小
minimap: {
enabled: document.documentElement.clientWidth >= 1500 // 超过一定宽度显示minimap滚动条
enabled: document.documentElement.clientWidth >= 1500 // 超过一定宽度显示 minimap 滚动条
},
mouseWheelZoom: true, // 按住Ctrl滚轮调节缩放比例
mouseWheelZoom: true, // 按住 Ctrl 滚轮调节缩放比例
readOnly: readOnly, // 只读模式
renderValidationDecorations: 'on', // 只读模式下显示校验信息
quickSuggestions: {
Expand Down
140 changes: 91 additions & 49 deletions src/renderer/src/components/resources/proxy-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,42 @@
import { mihomoProxyProviders, mihomoUpdateProxyProviders } from '@renderer/utils/ipc'
import { Fragment, useMemo, useState } from 'react'
import { mihomoProxyProviders, mihomoUpdateProxyProviders, mihomoRunProxyProviders } from '@renderer/utils/ipc'
import { Fragment, useEffect, useMemo, useState } from 'react'
import Viewer from './viewer'
import useSWR from 'swr'
import SettingCard from '../base/base-setting-card'
import SettingItem from '../base/base-setting-item'
import { Button, Chip } from '@nextui-org/react'
import { IoMdRefresh } from 'react-icons/io'
import { IoMdRefresh, IoMdEye } from 'react-icons/io'
import { CgLoadbarDoc } from 'react-icons/cg'
import dayjs from 'dayjs'
import { calcTraffic } from '@renderer/utils/calc'
import { getHash } from '@renderer/utils/hash'

const ProxyProvider: React.FC = () => {
const [ShowProvider, setShowProvider] = useState(false)
const [ShowPath, setShowPath] = useState('')
const [ShowType, setShowType] = useState('')

useEffect(() => {
const fetchProviderPath = async (name: string) => {
try {
const providers = await mihomoRunProxyProviders()
const provider = providers[name]
if (provider?.path) {
setShowPath(provider.path)
} else if (provider?.url) {
setShowPath(`proxies/` + getHash(provider.url))
}
setShowProvider(true)
} catch (error) {
setShowPath('')
}
}

if (ShowPath != '') {
fetchProviderPath(ShowPath)
}
}, [ShowProvider, ShowPath])

const { data, mutate } = useSWR('mihomoProxyProviders', mihomoProxyProviders)
const providers = useMemo(() => {
if (!data) return []
Expand Down Expand Up @@ -45,6 +73,7 @@ const ProxyProvider: React.FC = () => {

return (
<SettingCard>
{ShowProvider && <Viewer onClose={() => { setShowProvider(false); setShowPath(''); setShowType('')}} path={ShowPath} type={ShowType} />}
<SettingItem title="代理集合" divider>
<Button
size="sm"
Expand All @@ -58,56 +87,69 @@ const ProxyProvider: React.FC = () => {
更新全部
</Button>
</SettingItem>
{providers.map((provider, index) => {
return (
<Fragment key={provider.name}>
{providers.map((provider, index) => (
<Fragment key={provider.name}>
<SettingItem
title={provider.name}
actions={
<Chip className="ml-2" size="sm">
{provider.proxies?.length || 0}
</Chip>
}
divider={!provider.subscriptionInfo && index !== providers.length - 1}
>
<div className="flex h-[32px] leading-[32px] text-foreground-500">
<div>{dayjs(provider.updatedAt).fromNow()}</div>
<Button
isIconOnly
className="ml-2"
size="sm"
onPress={() => {
onUpdate(provider.name, index)
}}
>
<IoMdRefresh className={`text-lg ${updating[index] ? 'animate-spin' : ''}`} />
</Button>
<Button
isIconOnly
className="ml-2"
size="sm"
>
<IoMdEye className="text-lg" />
</Button>
<Button
isIconOnly
className="ml-2"
size="sm"
onPress={() => {
setShowType(provider.vehicleType)
setShowPath(provider.name)
}}
>
<CgLoadbarDoc className="text-lg" />
</Button>
</div>
</SettingItem>
{provider.subscriptionInfo && (
<SettingItem
title={provider.name}
actions={
<Chip className="ml-2" size="sm">
{provider.proxies?.length || 0}
</Chip>
}
divider={!provider.subscriptionInfo && index !== providers.length - 1}
>
{
<div className="flex h-[32px] leading-[32px] text-foreground-500">
<div>{dayjs(provider.updatedAt).fromNow()}</div>
<Button
isIconOnly
className="ml-2"
size="sm"
onPress={() => {
onUpdate(provider.name, index)
}}
>
<IoMdRefresh className={`text-lg ${updating[index] ? 'animate-spin' : ''}`} />
</Button>
divider={index !== providers.length - 1}
title={
<div className="text-foreground-500">
{`${calcTraffic(
provider.subscriptionInfo.Upload + provider.subscriptionInfo.Download
)} / ${calcTraffic(provider.subscriptionInfo.Total)}`}
</div>
}
>
<div className="h-[32px] leading-[32px] text-foreground-500">
{provider.subscriptionInfo.Expire
? dayjs.unix(provider.subscriptionInfo.Expire).format('YYYY-MM-DD')
: '长期有效'}
</div>
</SettingItem>
{provider.subscriptionInfo && (
<SettingItem
divider={index !== providers.length - 1}
title={
<div className="text-foreground-500">{`${calcTraffic(
provider.subscriptionInfo.Upload + provider.subscriptionInfo.Download
)}
/${calcTraffic(provider.subscriptionInfo.Total)}`}</div>
}
>
{provider.subscriptionInfo && (
<div className="h-[32px] leading-[32px] text-foreground-500">
{provider.subscriptionInfo.Expire
? dayjs.unix(provider.subscriptionInfo.Expire).format('YYYY-MM-DD')
: '长期有效'}
</div>
)}
</SettingItem>
)}
</Fragment>
)
})}
)}
</Fragment>
))}
</SettingCard>
)
}
Expand Down
Loading

0 comments on commit e265317

Please sign in to comment.