Revert "功能: 新增应用代理管理页面,支持按应用开关代理"

This reverts commit 09ed12c67f.
This commit is contained in:
Memory
2026-04-26 12:44:09 +08:00
committed by GitHub
parent 82436d2fbf
commit f494ff7d00
21 changed files with 6 additions and 506 deletions

3
.gitignore vendored
View File

@@ -11,6 +11,3 @@ out
party.md party.md
CLAUDE.md CLAUDE.md
tsconfig.node.tsbuildinfo tsconfig.node.tsbuildinfo
.omc
.claude
debug

View File

@@ -4,6 +4,3 @@ pnpm-lock.yaml
LICENSE.md LICENSE.md
tsconfig.json tsconfig.json
tsconfig.*.json tsconfig.*.json
.omc
.claude
debug

View File

@@ -39,8 +39,3 @@ export async function patchAppConfig(patch: Partial<IAppConfig>): Promise<void>
}) })
await appConfigWriteQueue await appConfigWriteQueue
} }
export async function getAppProxyRules(): Promise<IAppProxyRule[]> {
const { appProxyRules = [] } = await getAppConfig()
return appProxyRules
}

View File

@@ -1,4 +1,4 @@
export { getAppConfig, patchAppConfig, getAppProxyRules } from './app' export { getAppConfig, patchAppConfig } from './app'
export { getControledMihomoConfig, patchControledMihomoConfig } from './controledMihomo' export { getControledMihomoConfig, patchControledMihomoConfig } from './controledMihomo'
export { export {
getProfile, getProfile,

View File

@@ -73,9 +73,7 @@ export async function generateProfile(): Promise<string | undefined> {
const overrideIds = await getOrderedOverrideIds(current) const overrideIds = await getOrderedOverrideIds(current)
const profileWithNormalOverride = await applyOverrides(baseProfile, overrideIds.normal) const profileWithNormalOverride = await applyOverrides(baseProfile, overrideIds.normal)
const profileWithRuleOverride = await applyRuleOverride(current, profileWithNormalOverride) const profileWithRuleOverride = await applyRuleOverride(current, profileWithNormalOverride)
const { appProxyRules = [] } = await getAppConfig() const currentProfile = await applyOverrides(profileWithRuleOverride, overrideIds.smart)
const profileWithAppProxy = applyAppProxyRules(profileWithRuleOverride, appProxyRules)
const currentProfile = await applyOverrides(profileWithAppProxy, overrideIds.smart)
let controledMihomoConfig = await getControledMihomoConfig() let controledMihomoConfig = await getControledMihomoConfig()
// 根据开关状态过滤控制配置 // 根据开关状态过滤控制配置
@@ -117,18 +115,6 @@ export async function generateProfile(): Promise<string | undefined> {
return current return current
} }
function applyAppProxyRules(profile: IMihomoConfig, rules: IAppProxyRule[]): IMihomoConfig {
const disabledApps = rules.filter(
(r) => !r.enabled && r.processName && !r.processName.includes(',')
)
if (disabledApps.length === 0) return profile
const profileRules = (profile.rules || []) as unknown as string[]
const processRules = disabledApps.map((r) => `PROCESS-NAME,${r.processName},DIRECT`)
profile.rules = [...processRules, ...profileRules] as unknown as []
return profile
}
async function applyRuleOverride( async function applyRuleOverride(
current: string | undefined, current: string | undefined,
profile: IMihomoConfig profile: IMihomoConfig

View File

@@ -33,7 +33,6 @@ import {
patchAppConfig, patchAppConfig,
getControledMihomoConfig, getControledMihomoConfig,
patchControledMihomoConfig, patchControledMihomoConfig,
getAppProxyRules,
getProfileConfig, getProfileConfig,
getCurrentProfileItem, getCurrentProfileItem,
getProfileItem, getProfileItem,
@@ -250,7 +249,7 @@ const asyncHandlers: Record<string, AsyncFn> = {
patchAppConfig, patchAppConfig,
getControledMihomoConfig, getControledMihomoConfig,
patchControledMihomoConfig, patchControledMihomoConfig,
getAppProxyRules, // Profile
getProfileConfig, getProfileConfig,
setProfileConfig, setProfileConfig,
getCurrentProfileItem, getCurrentProfileItem,

View File

@@ -40,7 +40,6 @@ export const defaultConfig: IAppConfig = {
'resource', 'resource',
'override', 'override',
'connection', 'connection',
'apps',
'mihomo', 'mihomo',
'dns', 'dns',
'sniff', 'sniff',
@@ -63,9 +62,7 @@ export const defaultConfig: IAppConfig = {
enableTproxyPort: false, enableTproxyPort: false,
testProfileOnStart: true, testProfileOnStart: true,
useHotReloadProfile: false, useHotReloadProfile: false,
hotReloadProfileAutoCloseConnection: false, hotReloadProfileAutoCloseConnection: false
appProxyRules: [],
appsCardStatus: 'col-span-1'
} }
export const defaultControledMihomoConfig: Partial<IMihomoConfig> = { export const defaultControledMihomoConfig: Partial<IMihomoConfig> = {

View File

@@ -33,7 +33,6 @@ const validInvokeChannels = [
'patchAppConfig', 'patchAppConfig',
'getControledMihomoConfig', 'getControledMihomoConfig',
'patchControledMihomoConfig', 'patchControledMihomoConfig',
'getAppProxyRules',
'resetAppConfig', 'resetAppConfig',
// Profile // Profile
'getProfileConfig', 'getProfileConfig',

View File

@@ -34,7 +34,6 @@ import { TitleBarOverlayOptions } from 'electron'
import SubStoreCard from '@renderer/components/sider/substore-card' import SubStoreCard from '@renderer/components/sider/substore-card'
import NetworkCard from '@renderer/components/sider/network-card' import NetworkCard from '@renderer/components/sider/network-card'
import UsageCard from '@renderer/components/sider/usage-card' import UsageCard from '@renderer/components/sider/usage-card'
import AppsCard from '@renderer/components/sider/apps-card'
import { useTrafficLogger } from '@renderer/hooks/use-traffic-logger' import { useTrafficLogger } from '@renderer/hooks/use-traffic-logger'
import { createTourDriver, getDriver, startTourIfNeeded } from '@renderer/utils/tour' import { createTourDriver, getDriver, startTourIfNeeded } from '@renderer/utils/tour'
import 'driver.js/dist/driver.css' import 'driver.js/dist/driver.css'
@@ -54,7 +53,6 @@ const ALL_SIDER_KEYS = [
'resource', 'resource',
'override', 'override',
'connection', 'connection',
'apps',
'mihomo', 'mihomo',
'dns', 'dns',
'sniff', 'sniff',
@@ -88,7 +86,6 @@ const App: React.FC = () => {
'resource', 'resource',
'override', 'override',
'connection', 'connection',
'apps',
'mihomo', 'mihomo',
'dns', 'dns',
'sniff', 'sniff',
@@ -191,7 +188,6 @@ const App: React.FC = () => {
proxy: 'proxies', proxy: 'proxies',
mihomo: 'mihomo', mihomo: 'mihomo',
connection: 'connections', connection: 'connections',
apps: 'apps',
dns: 'dns', dns: 'dns',
sniff: 'sniffer', sniff: 'sniffer',
log: 'logs', log: 'logs',
@@ -210,7 +206,6 @@ const App: React.FC = () => {
proxy: ProxyCard, proxy: ProxyCard,
mihomo: MihomoCoreCard, mihomo: MihomoCoreCard,
connection: ConnCard, connection: ConnCard,
apps: AppsCard,
dns: DNSCard, dns: DNSCard,
sniff: SniffCard, sniff: SniffCard,
log: LogCard, log: LogCard,

View File

@@ -267,7 +267,7 @@ const NetworkTopologyCard: React.FC = () => {
} }
window.electron.ipcRenderer.on('mihomoConnections', handler) window.electron.ipcRenderer.on('mihomoConnections', handler)
return () => { return () => {
window.electron.ipcRenderer.removeListener('mihomoConnections', handler) window.electron.ipcRenderer.removeAllListeners('mihomoConnections')
} }
}, [isPaused]) }, [isPaused])

View File

@@ -1,106 +0,0 @@
import { Button, Card, CardBody, CardFooter, Tooltip } from '@heroui/react'
import { MdApps } from 'react-icons/md'
import { useLocation, useNavigate } from 'react-router-dom'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import React from 'react'
import { useTranslation } from 'react-i18next'
interface Props {
iconOnly?: boolean
}
const AppsCard: React.FC<Props> = (props) => {
const { t } = useTranslation()
const { appConfig } = useAppConfig()
const { iconOnly } = props
const {
appsCardStatus = 'col-span-1',
disableAnimations = false,
appProxyRules = []
} = appConfig || {}
const bypassedCount = appProxyRules.filter((r) => !r.enabled).length
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/apps')
const {
attributes,
listeners,
setNodeRef,
transform: tf,
transition,
isDragging
} = useSortable({ id: 'apps' })
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
if (iconOnly) {
return (
<div className={`${appsCardStatus} flex justify-center`}>
<Tooltip content={t('sider.cards.apps')} placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/apps')
}}
>
<MdApps className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{
position: 'relative',
transform: CSS.Transform.toString(transform),
transition,
zIndex: isDragging ? 'calc(infinity)' : undefined
}}
className={`${appsCardStatus} apps-card`}
>
<Card
fullWidth
ref={setNodeRef}
{...attributes}
{...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${disableAnimations ? '' : `motion-reduce:transition-transform-background ${isDragging ? 'scale-[0.95] tap-highlight-transparent' : ''}`}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"
variant="flat"
color="default"
>
<MdApps
className={`${match ? 'text-primary-foreground' : 'text-foreground'} text-[24px] font-bold`}
/>
</Button>
{bypassedCount > 0 && (
<span
className={`text-xs mt-2 mr-2 ${match ? 'text-primary-foreground/70' : 'text-foreground/50'}`}
>
{bypassedCount} {t('apps.bypassed')}
</span>
)}
</div>
</CardBody>
<CardFooter className="pt-1">
<h3
className={`text-md font-bold sider-card-title ${match ? 'text-primary-foreground' : 'text-foreground'}`}
>
{t('sider.cards.apps')}
</h3>
</CardFooter>
</Card>
</div>
)
}
export default AppsCard

View File

@@ -323,14 +323,6 @@
"sider.cards.logs": "Logs", "sider.cards.logs": "Logs",
"sider.cards.substore": "Sub-Store", "sider.cards.substore": "Sub-Store",
"sider.cards.network": "Network Info", "sider.cards.network": "Network Info",
"sider.cards.apps": "Apps",
"apps.title": "App Proxy",
"apps.search": "Search apps",
"apps.connections": "connections",
"apps.bypassed": "Bypassed",
"apps.noApps": "No active connections",
"apps.warning.noProcess": "Process detection is off. Enable \"Find Process Mode\" for this feature to work.",
"apps.warning.noRuleMode": "Rules are not effective in current outbound mode. Switch to \"Rule\" mode.",
"network.title": "Network Info", "network.title": "Network Info",
"network.ipCard.title": "Current IP", "network.ipCard.title": "Current IP",
"network.ipAddress": "IP Address", "network.ipAddress": "IP Address",

View File

@@ -298,14 +298,6 @@
"sider.cards.logs": "گزارش‌ها", "sider.cards.logs": "گزارش‌ها",
"sider.cards.substore": "ساب استور", "sider.cards.substore": "ساب استور",
"sider.cards.network": "اطلاعات شبکه", "sider.cards.network": "اطلاعات شبکه",
"sider.cards.apps": "اپلیکیشن‌ها",
"apps.title": "پروکسی برنامه",
"apps.search": "جستجوی برنامه",
"apps.connections": "اتصال",
"apps.bypassed": "دور زده",
"apps.noApps": "اتصال فعالی نیست",
"apps.warning.noProcess": "تشخیص فرآیند خاموش است.",
"apps.warning.noRuleMode": "قوانین در حالت فعلی فعال نیستند.",
"network.title": "اطلاعات شبکه", "network.title": "اطلاعات شبکه",
"network.ipCard.title": "IP فعلی", "network.ipCard.title": "IP فعلی",
"network.ipAddress": "آدرس IP", "network.ipAddress": "آدرس IP",

View File

@@ -300,14 +300,6 @@
"sider.cards.logs": "Журналы", "sider.cards.logs": "Журналы",
"sider.cards.substore": "Sub-Store", "sider.cards.substore": "Sub-Store",
"sider.cards.network": "Сетевая информация", "sider.cards.network": "Сетевая информация",
"sider.cards.apps": "Приложения",
"apps.title": "Прокси приложений",
"apps.search": "Поиск приложений",
"apps.connections": "соединений",
"apps.bypassed": "Обойдён",
"apps.noApps": "Нет активных соединений",
"apps.warning.noProcess": "Обнаружение процессов отключено.",
"apps.warning.noRuleMode": "Правила не действуют в текущем режиме.",
"network.title": "Сетевая информация", "network.title": "Сетевая информация",
"network.ipCard.title": "Текущий IP", "network.ipCard.title": "Текущий IP",
"network.ipAddress": "IP-адрес", "network.ipAddress": "IP-адрес",

View File

@@ -323,14 +323,6 @@
"sider.cards.logs": "日志", "sider.cards.logs": "日志",
"sider.cards.substore": "Sub-Store", "sider.cards.substore": "Sub-Store",
"sider.cards.network": "网络信息", "sider.cards.network": "网络信息",
"sider.cards.apps": "应用",
"apps.title": "应用代理",
"apps.search": "搜索应用",
"apps.connections": "个连接",
"apps.bypassed": "已绕过",
"apps.noApps": "暂无活跃连接",
"apps.warning.noProcess": "进程检测已关闭,请开启\"查找进程模式\"以使用此功能。",
"apps.warning.noRuleMode": "当前出站模式下规则不生效,请切换到\"规则\"模式。",
"network.title": "网络信息", "network.title": "网络信息",
"network.ipCard.title": "当前 IP", "network.ipCard.title": "当前 IP",
"network.ipAddress": "IP 地址", "network.ipAddress": "IP 地址",

View File

@@ -323,14 +323,6 @@
"sider.cards.logs": "日誌", "sider.cards.logs": "日誌",
"sider.cards.substore": "Sub-Store", "sider.cards.substore": "Sub-Store",
"sider.cards.network": "網路資訊", "sider.cards.network": "網路資訊",
"sider.cards.apps": "應用",
"apps.title": "應用代理",
"apps.search": "搜尋應用",
"apps.connections": "個連線",
"apps.bypassed": "已繞過",
"apps.noApps": "暫無活躍連線",
"apps.warning.noProcess": "進程檢測已關閉,請開啟「查找進程模式」以使用此功能。",
"apps.warning.noRuleMode": "當前出站模式下規則不生效,請切換到「規則」模式。",
"network.title": "網路資訊", "network.title": "網路資訊",
"network.ipCard.title": "目前 IP", "network.ipCard.title": "目前 IP",
"network.ipAddress": "IP 位址", "network.ipAddress": "IP 位址",

View File

@@ -1,304 +0,0 @@
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Virtuoso } from 'react-virtuoso'
import { Avatar, Input, Switch, Card, CardBody } from '@heroui/react'
import { MdApps, MdSearch, MdWarning } from 'react-icons/md'
import { IoLogoApple } from 'react-icons/io5'
import BasePage from '@renderer/components/base/base-page'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
import {
patchAppConfig,
mihomoHotReloadConfig,
getIconDataURL,
getAppName
} from '@renderer/utils/ipc'
import { calcTraffic } from '@renderer/utils/calc'
import { getIconFromCache, saveIconToCache } from '@renderer/utils/icon-cache'
import { cropAndPadTransparent } from '@renderer/utils/image'
import { platform } from '@renderer/utils/init'
interface AppGroup {
processName: string
processPath: string
connections: IMihomoConnectionDetail[]
upload: number
download: number
uploadSpeed: number
downloadSpeed: number
}
const Apps: React.FC = () => {
const { t } = useTranslation()
const { appConfig } = useAppConfig()
const { controledMihomoConfig } = useControledMihomoConfig()
const [appGroups, setAppGroups] = useState<AppGroup[]>([])
const [proxyRules, setProxyRules] = useState<IAppProxyRule[]>([])
const [filter, setFilter] = useState('')
const [iconMap, setIconMap] = useState<Record<string, string>>({})
const [appNameCache, setAppNameCache] = useState<Record<string, string>>({})
const iconProcessingRef = useRef<Set<string>>(new Set())
const appNameProcessingRef = useRef<Set<string>>(new Set())
const findProcessMode = controledMihomoConfig?.['find-process-mode'] || 'strict'
const mode = controledMihomoConfig?.mode || 'rule'
// Load proxy rules from config
useEffect(() => {
if (appConfig?.appProxyRules) {
setProxyRules(appConfig.appProxyRules)
}
}, [appConfig?.appProxyRules])
// Listen to mihomoConnections
useEffect(() => {
const handler = (_e: unknown, ...args: unknown[]): void => {
const info = args[0] as IMihomoConnectionsInfo
if (!info.connections) return
const groupMap = new Map<string, AppGroup>()
for (const conn of info.connections) {
const processName = conn.metadata.process || 'Unknown'
const processPath = conn.metadata.processPath || ''
const key = processName
if (!groupMap.has(key)) {
groupMap.set(key, {
processName,
processPath,
connections: [],
upload: 0,
download: 0,
uploadSpeed: 0,
downloadSpeed: 0
})
}
const group = groupMap.get(key)
if (!group) return
group.connections.push(conn)
group.upload += conn.upload
group.download += conn.download
group.uploadSpeed += conn.uploadSpeed || 0
group.downloadSpeed += conn.downloadSpeed || 0
}
const groups = Array.from(groupMap.values()).sort(
(a, b) => b.download + b.upload - (a.download + a.upload)
)
setAppGroups(groups)
}
window.electron.ipcRenderer.on('mihomoConnections', handler)
return () => {
window.electron.ipcRenderer.removeListener('mihomoConnections', handler)
}
}, [])
// Load icons
useEffect(() => {
if (findProcessMode === 'off') return
const queue: string[] = []
for (const group of appGroups) {
if (!group.processPath) continue
if (iconMap[group.processPath]) continue
if (getIconFromCache(group.processPath)) continue
if (!queue.includes(group.processPath)) {
queue.push(group.processPath)
}
}
if (queue.length === 0) return
const processQueue = (): void => {
const path = queue.shift()
if (!path) return
if (iconProcessingRef.current.has(path)) {
if (queue.length > 0) setTimeout(processQueue, 50)
return
}
iconProcessingRef.current.add(path)
getIconDataURL(path)
.then((dataUrl) => {
if (platform !== 'darwin' && dataUrl) {
return cropAndPadTransparent(dataUrl)
}
return dataUrl
})
.then((dataUrl) => {
if (dataUrl) {
saveIconToCache(path, dataUrl)
setIconMap((prev) => ({ ...prev, [path]: dataUrl }))
}
})
.catch(() => {})
.finally(() => {
iconProcessingRef.current.delete(path)
if (queue.length > 0) setTimeout(processQueue, 50)
})
}
setTimeout(processQueue, 10)
}, [appGroups, iconMap, findProcessMode])
// Load app names
useEffect(() => {
if (platform !== 'darwin') return
const queue: string[] = []
for (const group of appGroups) {
if (!group.processPath) continue
if (appNameCache[group.processPath]) continue
if (!queue.includes(group.processPath)) {
queue.push(group.processPath)
}
}
if (queue.length === 0) return
const processQueue = (): void => {
const path = queue.shift()
if (!path) return
if (appNameProcessingRef.current.has(path)) {
if (queue.length > 0) setTimeout(processQueue, 100)
return
}
appNameProcessingRef.current.add(path)
getAppName(path)
.then((name) => {
if (name) {
setAppNameCache((prev) => ({ ...prev, [path]: name }))
}
})
.catch(() => {})
.finally(() => {
appNameProcessingRef.current.delete(path)
if (queue.length > 0) setTimeout(processQueue, 100)
})
}
setTimeout(processQueue, 10)
}, [appGroups, appNameCache])
// Toggle app proxy
const handleToggle = useCallback(
async (processName: string, processPath: string, enabled: boolean) => {
let newRules: IAppProxyRule[]
const existing = proxyRules.find((r) => r.processName === processName)
if (existing) {
newRules = proxyRules.map((r) => (r.processName === processName ? { ...r, enabled } : r))
} else {
newRules = [...proxyRules, { processName, processPath, enabled }]
}
setProxyRules(newRules)
try {
await patchAppConfig({ appProxyRules: newRules })
await mihomoHotReloadConfig()
} catch {
setProxyRules(proxyRules)
}
},
[proxyRules]
)
// Filter
const filteredGroups = useMemo(() => {
if (!filter) return appGroups
const lowerFilter = filter.toLowerCase()
return appGroups.filter(
(g) =>
g.processName.toLowerCase().includes(lowerFilter) ||
(appNameCache[g.processPath] || '').toLowerCase().includes(lowerFilter)
)
}, [appGroups, filter, appNameCache])
const isProcessOff = findProcessMode === 'off'
const isNotRuleMode = mode !== 'rule'
return (
<BasePage title={t('apps.title')}>
{/* Warning banners */}
{isProcessOff && (
<div className="mx-2 mt-2 flex items-center gap-2 rounded-lg bg-warning-100 p-3 text-sm text-warning-700 dark:bg-warning-900/30 dark:text-warning-400">
<MdWarning className="text-lg flex-shrink-0" />
<span>{t('apps.warning.noProcess')}</span>
</div>
)}
{isNotRuleMode && (
<div className="mx-2 mt-2 flex items-center gap-2 rounded-lg bg-warning-100 p-3 text-sm text-warning-700 dark:bg-warning-900/30 dark:text-warning-400">
<MdWarning className="text-lg flex-shrink-0" />
<span>{t('apps.warning.noRuleMode')}</span>
</div>
)}
<div className="px-2 pt-2">
<Input
size="sm"
placeholder={t('apps.search')}
value={filter}
onValueChange={setFilter}
startContent={<MdSearch className="text-foreground/50" />}
/>
</div>
{filteredGroups.length === 0 ? (
<div className="flex flex-col items-center justify-center py-20 text-foreground/50">
<MdApps className="text-5xl mb-2" />
<span>{t('apps.noApps')}</span>
</div>
) : (
<div className="h-[calc(100vh-180px)]">
<Virtuoso
data={filteredGroups}
itemContent={(_, group) => {
const rule = proxyRules.find((r) => r.processName === group.processName)
const isEnabled = rule ? rule.enabled : true
const isUnknown = group.processName === 'Unknown'
const iconUrl =
findProcessMode !== 'off' && group.processPath
? iconMap[group.processPath] || getIconFromCache(group.processPath) || ''
: ''
const displayName =
group.processPath && appNameCache[group.processPath]
? appNameCache[group.processPath]
: group.processName
return (
<Card className="m-2" radius="sm">
<CardBody className="flex flex-row items-center gap-3 px-3 py-2">
<Avatar
src={iconUrl}
icon={iconUrl ? undefined : <IoLogoApple />}
className="flex-shrink-0"
size="sm"
radius="sm"
/>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2">
<span className="text-sm font-medium truncate">{displayName}</span>
<span className="text-xs text-foreground/50 flex-shrink-0">
{group.connections.length} {t('apps.connections')}
</span>
</div>
<div className="text-xs text-foreground/50 flex gap-2">
<span> {calcTraffic(group.uploadSpeed)}/s</span>
<span> {calcTraffic(group.downloadSpeed)}/s</span>
<span> {calcTraffic(group.upload)}</span>
<span> {calcTraffic(group.download)}</span>
</div>
</div>
<Switch
size="sm"
isSelected={isEnabled}
isDisabled={isUnknown || isProcessOff}
onValueChange={(val) =>
handleToggle(group.processName, group.processPath, val)
}
color={isEnabled ? 'primary' : 'danger'}
/>
</CardBody>
</Card>
)
}}
/>
</div>
)}
</BasePage>
)
}
export default Apps

View File

@@ -427,7 +427,7 @@ const Connections: React.FC = () => {
} }
return (): void => { return (): void => {
window.electron.ipcRenderer.removeListener('mihomoConnections', handler) window.electron.ipcRenderer.removeAllListeners('mihomoConnections')
} }
}, [isPaused]) }, [isPaused])
const togglePause = useCallback(() => { const togglePause = useCallback(() => {

View File

@@ -7,7 +7,6 @@ import Settings from '@renderer/pages/settings'
import Profiles from '@renderer/pages/profiles' import Profiles from '@renderer/pages/profiles'
import Logs from '@renderer/pages/logs' import Logs from '@renderer/pages/logs'
import Connections from '@renderer/pages/connections' import Connections from '@renderer/pages/connections'
import Apps from '@renderer/pages/apps'
import Mihomo from '@renderer/pages/mihomo' import Mihomo from '@renderer/pages/mihomo'
import Sysproxy from '@renderer/pages/sysproxy' import Sysproxy from '@renderer/pages/sysproxy'
import Tun from '@renderer/pages/tun' import Tun from '@renderer/pages/tun'
@@ -61,10 +60,6 @@ const routes = [
path: '/connections', path: '/connections',
element: <Connections /> element: <Connections />
}, },
{
path: '/apps',
element: <Apps />
},
{ {
path: '/override', path: '/override',
element: <Override /> element: <Override />

View File

@@ -46,7 +46,6 @@ interface IpcApi {
patchAppConfig: (patch: Partial<IAppConfig>) => Promise<void> patchAppConfig: (patch: Partial<IAppConfig>) => Promise<void>
getControledMihomoConfig: (force?: boolean) => Promise<Partial<IMihomoConfig>> getControledMihomoConfig: (force?: boolean) => Promise<Partial<IMihomoConfig>>
patchControledMihomoConfig: (patch: Partial<IMihomoConfig>) => Promise<void> patchControledMihomoConfig: (patch: Partial<IMihomoConfig>) => Promise<void>
getAppProxyRules: () => Promise<IAppProxyRule[]>
resetAppConfig: () => Promise<void> resetAppConfig: () => Promise<void>
// Profile // Profile
getProfileConfig: (force?: boolean) => Promise<IProfileConfig> getProfileConfig: (force?: boolean) => Promise<IProfileConfig>
@@ -204,7 +203,6 @@ export const {
patchAppConfig, patchAppConfig,
getControledMihomoConfig, getControledMihomoConfig,
patchControledMihomoConfig, patchControledMihomoConfig,
getAppProxyRules,
resetAppConfig, resetAppConfig,
// Profile // Profile
getProfileConfig, getProfileConfig,

View File

@@ -236,12 +236,6 @@ interface ISysProxyConfig {
pacScript?: string pacScript?: string
} }
interface IAppProxyRule {
processName: string
processPath: string
enabled: boolean
}
interface IAppConfig { interface IAppConfig {
core: 'mihomo' | 'mihomo-alpha' | 'mihomo-smart' | 'mihomo-specific' core: 'mihomo' | 'mihomo-alpha' | 'mihomo-smart' | 'mihomo-specific'
specificVersion?: string specificVersion?: string
@@ -291,8 +285,6 @@ interface IAppConfig {
sysproxyCardStatus?: CardStatus sysproxyCardStatus?: CardStatus
tunCardStatus?: CardStatus tunCardStatus?: CardStatus
usageCardStatus?: CardStatus usageCardStatus?: CardStatus
appsCardStatus?: CardStatus
appProxyRules?: IAppProxyRule[]
githubToken?: string githubToken?: string
useSubStore: boolean useSubStore: boolean
subStoreHost?: string subStoreHost?: string