mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2026-02-10 19:50:28 +08:00
refactor: simplify ipc with proxy pattern and split startCore into smaller functions
This commit is contained in:
parent
a5d2114363
commit
075132397c
@ -4,7 +4,7 @@ import { promisify } from 'util'
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import os from 'os'
|
import os from 'os'
|
||||||
import { createWriteStream, existsSync } from 'fs'
|
import { createWriteStream, existsSync } from 'fs'
|
||||||
import chokidar from 'chokidar'
|
import chokidar, { FSWatcher } from 'chokidar'
|
||||||
import { app, ipcMain } from 'electron'
|
import { app, ipcMain } from 'electron'
|
||||||
import { mainWindow } from '../window'
|
import { mainWindow } from '../window'
|
||||||
import {
|
import {
|
||||||
@ -69,15 +69,38 @@ export {
|
|||||||
export { getDefaultDevice } from './dns'
|
export { getDefaultDevice } from './dns'
|
||||||
|
|
||||||
const execFilePromise = promisify(execFile)
|
const execFilePromise = promisify(execFile)
|
||||||
|
const ctlParam = process.platform === 'win32' ? '-ext-ctl-pipe' : '-ext-ctl-unix'
|
||||||
|
|
||||||
chokidar.watch(path.join(mihomoCoreDir(), 'meta-update'), {}).on('unlinkDir', async () => {
|
// 核心进程状态
|
||||||
|
let child: ChildProcess
|
||||||
|
let retry = 10
|
||||||
|
let isRestarting = false
|
||||||
|
|
||||||
|
// 文件监听器
|
||||||
|
let coreWatcher: FSWatcher | null = null
|
||||||
|
|
||||||
|
// 初始化核心文件监听
|
||||||
|
export function initCoreWatcher(): void {
|
||||||
|
if (coreWatcher) return
|
||||||
|
|
||||||
|
coreWatcher = chokidar.watch(path.join(mihomoCoreDir(), 'meta-update'), {})
|
||||||
|
coreWatcher.on('unlinkDir', async () => {
|
||||||
try {
|
try {
|
||||||
await stopCore(true)
|
await stopCore(true)
|
||||||
await startCore()
|
await startCore()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
safeShowErrorBox('mihomo.error.coreStartFailed', `${e}`)
|
safeShowErrorBox('mihomo.error.coreStartFailed', `${e}`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理核心文件监听
|
||||||
|
export function cleanupCoreWatcher(): void {
|
||||||
|
if (coreWatcher) {
|
||||||
|
coreWatcher.close()
|
||||||
|
coreWatcher = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 动态生成 IPC 路径
|
// 动态生成 IPC 路径
|
||||||
export const getMihomoIpcPath = (): string => {
|
export const getMihomoIpcPath = (): string => {
|
||||||
@ -96,14 +119,20 @@ export const getMihomoIpcPath = (): string => {
|
|||||||
return `/tmp/mihomo-party-${uid}-${processId}.sock`
|
return `/tmp/mihomo-party-${uid}-${processId}.sock`
|
||||||
}
|
}
|
||||||
|
|
||||||
const ctlParam = process.platform === 'win32' ? '-ext-ctl-pipe' : '-ext-ctl-unix'
|
// 核心配置接口
|
||||||
|
interface CoreConfig {
|
||||||
|
corePath: string
|
||||||
|
workDir: string
|
||||||
|
ipcPath: string
|
||||||
|
logLevel: LogLevel
|
||||||
|
tunEnabled: boolean
|
||||||
|
autoSetDNS: boolean
|
||||||
|
cpuPriority: string
|
||||||
|
detached: boolean
|
||||||
|
}
|
||||||
|
|
||||||
let child: ChildProcess
|
// 准备核心配置
|
||||||
let retry = 10
|
async function prepareCore(detached: boolean): Promise<CoreConfig> {
|
||||||
let isRestarting = false
|
|
||||||
|
|
||||||
export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|
||||||
// 合并配置读取,避免多次 await
|
|
||||||
const [appConfig, mihomoConfig] = await Promise.all([
|
const [appConfig, mihomoConfig] = await Promise.all([
|
||||||
getAppConfig(),
|
getAppConfig(),
|
||||||
getControledMihomoConfig()
|
getControledMihomoConfig()
|
||||||
@ -116,7 +145,7 @@ export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|||||||
mihomoCpuPriority = 'PRIORITY_NORMAL'
|
mihomoCpuPriority = 'PRIORITY_NORMAL'
|
||||||
} = appConfig
|
} = appConfig
|
||||||
|
|
||||||
const { 'log-level': logLevel, tun } = mihomoConfig
|
const { 'log-level': logLevel = 'info' as LogLevel, tun } = mihomoConfig
|
||||||
|
|
||||||
// 清理旧进程
|
// 清理旧进程
|
||||||
const pidPath = path.join(dataDir(), 'core.pid')
|
const pidPath = path.join(dataDir(), 'core.pid')
|
||||||
@ -131,8 +160,6 @@ export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const corePath = mihomoCorePath(core)
|
|
||||||
|
|
||||||
// 管理 Smart 内核覆写配置
|
// 管理 Smart 内核覆写配置
|
||||||
await manageSmartOverride()
|
await manageSmartOverride()
|
||||||
|
|
||||||
@ -142,6 +169,7 @@ export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|||||||
await stopCore()
|
await stopCore()
|
||||||
await cleanupSocketFile()
|
await cleanupSocketFile()
|
||||||
|
|
||||||
|
// 设置 DNS
|
||||||
if (tun?.enable && autoSetDNS) {
|
if (tun?.enable && autoSetDNS) {
|
||||||
try {
|
try {
|
||||||
await setPublicDNS()
|
await setPublicDNS()
|
||||||
@ -151,39 +179,57 @@ export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取动态 IPC 路径
|
// 获取动态 IPC 路径
|
||||||
const dynamicIpcPath = getMihomoIpcPath()
|
const ipcPath = getMihomoIpcPath()
|
||||||
managerLogger.info(`Using IPC path: ${dynamicIpcPath}`)
|
managerLogger.info(`Using IPC path: ${ipcPath}`)
|
||||||
|
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
await validateWindowsPipeAccess(dynamicIpcPath)
|
await validateWindowsPipeAccess(ipcPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 内核日志输出
|
return {
|
||||||
|
corePath: mihomoCorePath(core),
|
||||||
|
workDir: diffWorkDir ? mihomoProfileWorkDir(current) : mihomoWorkDir(),
|
||||||
|
ipcPath,
|
||||||
|
logLevel,
|
||||||
|
tunEnabled: tun?.enable ?? false,
|
||||||
|
autoSetDNS,
|
||||||
|
cpuPriority: mihomoCpuPriority,
|
||||||
|
detached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动核心进程
|
||||||
|
function spawnCoreProcess(config: CoreConfig): ChildProcess {
|
||||||
|
const { corePath, workDir, ipcPath, cpuPriority, detached } = config
|
||||||
|
|
||||||
const stdout = createWriteStream(coreLogPath(), { flags: 'a' })
|
const stdout = createWriteStream(coreLogPath(), { flags: 'a' })
|
||||||
const stderr = createWriteStream(coreLogPath(), { flags: 'a' })
|
const stderr = createWriteStream(coreLogPath(), { flags: 'a' })
|
||||||
|
|
||||||
child = spawn(
|
const proc = spawn(corePath, ['-d', workDir, ctlParam, ipcPath], {
|
||||||
corePath,
|
|
||||||
['-d', diffWorkDir ? mihomoProfileWorkDir(current) : mihomoWorkDir(), ctlParam, dynamicIpcPath],
|
|
||||||
{
|
|
||||||
detached,
|
detached,
|
||||||
stdio: detached ? 'ignore' : undefined
|
stdio: detached ? 'ignore' : undefined
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
if (process.platform === 'win32' && child.pid) {
|
if (process.platform === 'win32' && proc.pid) {
|
||||||
os.setPriority(child.pid, os.constants.priority[mihomoCpuPriority])
|
os.setPriority(proc.pid, os.constants.priority[cpuPriority as keyof typeof os.constants.priority])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detached) {
|
if (!detached) {
|
||||||
managerLogger.info(
|
proc.stdout?.pipe(stdout)
|
||||||
`Core process detached successfully on ${process.platform}, PID: ${child.pid}`
|
proc.stderr?.pipe(stderr)
|
||||||
)
|
|
||||||
child.unref()
|
|
||||||
return [new Promise(() => {})]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
child.on('close', async (code, signal) => {
|
return proc
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置核心进程事件监听
|
||||||
|
function setupCoreListeners(
|
||||||
|
proc: ChildProcess,
|
||||||
|
logLevel: LogLevel,
|
||||||
|
resolve: (value: Promise<void>[]) => void,
|
||||||
|
reject: (reason: unknown) => void
|
||||||
|
): void {
|
||||||
|
proc.on('close', async (code, signal) => {
|
||||||
managerLogger.info(`Core closed, code: ${code}, signal: ${signal}`)
|
managerLogger.info(`Core closed, code: ${code}, signal: ${signal}`)
|
||||||
|
|
||||||
if (isRestarting) {
|
if (isRestarting) {
|
||||||
@ -200,20 +246,19 @@ export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
child.stdout?.pipe(stdout)
|
proc.stdout?.on('data', async (data) => {
|
||||||
child.stderr?.pipe(stderr)
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
child.stdout?.on('data', async (data) => {
|
|
||||||
const str = data.toString()
|
const str = data.toString()
|
||||||
|
|
||||||
|
// TUN 权限错误
|
||||||
if (str.includes('configure tun interface: operation not permitted')) {
|
if (str.includes('configure tun interface: operation not permitted')) {
|
||||||
patchControledMihomoConfig({ tun: { enable: false } })
|
patchControledMihomoConfig({ tun: { enable: false } })
|
||||||
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
mainWindow?.webContents.send('controledMihomoConfigUpdated')
|
||||||
ipcMain.emit('updateTrayMenu')
|
ipcMain.emit('updateTrayMenu')
|
||||||
reject(i18next.t('tun.error.tunPermissionDenied'))
|
reject(i18next.t('tun.error.tunPermissionDenied'))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 控制器监听错误
|
||||||
const isControllerError =
|
const isControllerError =
|
||||||
(process.platform !== 'win32' && str.includes('External controller unix listen error')) ||
|
(process.platform !== 'win32' && str.includes('External controller unix listen error')) ||
|
||||||
(process.platform === 'win32' && str.includes('External controller pipe listen error'))
|
(process.platform === 'win32' && str.includes('External controller pipe listen error'))
|
||||||
@ -232,8 +277,10 @@ export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reject(i18next.t('mihomo.error.externalControllerListenError'))
|
reject(i18next.t('mihomo.error.externalControllerListenError'))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// API 就绪
|
||||||
const isApiReady =
|
const isApiReady =
|
||||||
(process.platform !== 'win32' && str.includes('RESTful API unix listening at')) ||
|
(process.platform !== 'win32' && str.includes('RESTful API unix listening at')) ||
|
||||||
(process.platform === 'win32' && str.includes('RESTful API pipe listening at'))
|
(process.platform === 'win32' && str.includes('RESTful API pipe listening at'))
|
||||||
@ -241,7 +288,7 @@ export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|||||||
if (isApiReady) {
|
if (isApiReady) {
|
||||||
resolve([
|
resolve([
|
||||||
new Promise((innerResolve) => {
|
new Promise((innerResolve) => {
|
||||||
child.stdout?.on('data', async (innerData) => {
|
proc.stdout?.on('data', async (innerData) => {
|
||||||
if (
|
if (
|
||||||
innerData.toString().toLowerCase().includes('start initial compatible provider default')
|
innerData.toString().toLowerCase().includes('start initial compatible provider default')
|
||||||
) {
|
) {
|
||||||
@ -268,9 +315,27 @@ export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|||||||
retry = 10
|
retry = 10
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动核心
|
||||||
|
export async function startCore(detached = false): Promise<Promise<void>[]> {
|
||||||
|
const config = await prepareCore(detached)
|
||||||
|
child = spawnCoreProcess(config)
|
||||||
|
|
||||||
|
if (detached) {
|
||||||
|
managerLogger.info(
|
||||||
|
`Core process detached successfully on ${process.platform}, PID: ${child.pid}`
|
||||||
|
)
|
||||||
|
child.unref()
|
||||||
|
return [new Promise(() => {})]
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
setupCoreListeners(child, config.logLevel, resolve, reject)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 停止核心
|
||||||
export async function stopCore(force = false): Promise<void> {
|
export async function stopCore(force = false): Promise<void> {
|
||||||
try {
|
try {
|
||||||
if (!force) {
|
if (!force) {
|
||||||
@ -299,6 +364,7 @@ export async function stopCore(force = false): Promise<void> {
|
|||||||
await cleanupSocketFile()
|
await cleanupSocketFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重启核心
|
||||||
export async function restartCore(): Promise<void> {
|
export async function restartCore(): Promise<void> {
|
||||||
if (isRestarting) {
|
if (isRestarting) {
|
||||||
managerLogger.info('Core restart already in progress, skipping duplicate request')
|
managerLogger.info('Core restart already in progress, skipping duplicate request')
|
||||||
@ -316,6 +382,7 @@ export async function restartCore(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保持核心运行
|
||||||
export async function keepCoreAlive(): Promise<void> {
|
export async function keepCoreAlive(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await startCore(true)
|
await startCore(true)
|
||||||
@ -327,6 +394,7 @@ export async function keepCoreAlive(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 退出但保持核心运行
|
||||||
export async function quitWithoutCore(): Promise<void> {
|
export async function quitWithoutCore(): Promise<void> {
|
||||||
managerLogger.info(`Starting lightweight mode on platform: ${process.platform}`)
|
managerLogger.info(`Starting lightweight mode on platform: ${process.platform}`)
|
||||||
|
|
||||||
@ -346,6 +414,7 @@ export async function quitWithoutCore(): Promise<void> {
|
|||||||
app.exit()
|
app.exit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查配置文件
|
||||||
async function checkProfile(
|
async function checkProfile(
|
||||||
current: string | undefined,
|
current: string | undefined,
|
||||||
core: string = 'mihomo',
|
core: string = 'mihomo',
|
||||||
|
|||||||
@ -10,7 +10,8 @@ import {
|
|||||||
checkHighPrivilegeCore,
|
checkHighPrivilegeCore,
|
||||||
restartAsAdmin,
|
restartAsAdmin,
|
||||||
initAdminStatus,
|
initAdminStatus,
|
||||||
checkAdminPrivileges
|
checkAdminPrivileges,
|
||||||
|
initCoreWatcher
|
||||||
} from './core/manager'
|
} from './core/manager'
|
||||||
import { createTray } from './resolve/tray'
|
import { createTray } from './resolve/tray'
|
||||||
import { init, initBasic, safeShowErrorBox } from './utils/init'
|
import { init, initBasic, safeShowErrorBox } from './utils/init'
|
||||||
@ -149,6 +150,7 @@ app.whenReady().then(async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
initCoreWatcher()
|
||||||
const [startPromise] = await startCore()
|
const [startPromise] = await startCore()
|
||||||
startPromise.then(async () => {
|
startPromise.then(async () => {
|
||||||
await initProfileUpdater()
|
await initProfileUpdater()
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { promisify } from 'util'
|
|||||||
import { stat } from 'fs/promises'
|
import { stat } from 'fs/promises'
|
||||||
import { existsSync } from 'fs'
|
import { existsSync } from 'fs'
|
||||||
import { app, powerMonitor } from 'electron'
|
import { app, powerMonitor } from 'electron'
|
||||||
import { stopCore } from './core/manager'
|
import { stopCore, cleanupCoreWatcher } from './core/manager'
|
||||||
import { triggerSysProxy } from './sys/sysproxy'
|
import { triggerSysProxy } from './sys/sysproxy'
|
||||||
import { exePath } from './utils/dirs'
|
import { exePath } from './utils/dirs'
|
||||||
|
|
||||||
@ -56,12 +56,14 @@ export function setupPlatformSpecifics(): void {
|
|||||||
export function setupAppLifecycle(): void {
|
export function setupAppLifecycle(): void {
|
||||||
app.on('before-quit', async (e) => {
|
app.on('before-quit', async (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
cleanupCoreWatcher()
|
||||||
await triggerSysProxy(false)
|
await triggerSysProxy(false)
|
||||||
await stopCore()
|
await stopCore()
|
||||||
app.exit()
|
app.exit()
|
||||||
})
|
})
|
||||||
|
|
||||||
powerMonitor.on('shutdown', async () => {
|
powerMonitor.on('shutdown', async () => {
|
||||||
|
cleanupCoreWatcher()
|
||||||
triggerSysProxy(false)
|
triggerSysProxy(false)
|
||||||
await stopCore()
|
await stopCore()
|
||||||
app.exit()
|
app.exit()
|
||||||
|
|||||||
@ -12,189 +12,309 @@ async function invoke<T>(channel: string, ...args: unknown[]): Promise<T> {
|
|||||||
return checkIpcError<T>(response)
|
return checkIpcError<T>(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mihomo API
|
// IPC API 类型定义
|
||||||
export const mihomoVersion = (): Promise<IMihomoVersion> => invoke('mihomoVersion')
|
interface IpcApi {
|
||||||
export const mihomoCloseConnection = (id: string): Promise<void> =>
|
// Mihomo API
|
||||||
invoke('mihomoCloseConnection', id)
|
mihomoVersion: () => Promise<IMihomoVersion>
|
||||||
export const mihomoCloseAllConnections = (): Promise<void> => invoke('mihomoCloseAllConnections')
|
mihomoCloseConnection: (id: string) => Promise<void>
|
||||||
export const mihomoRules = (): Promise<IMihomoRulesInfo> => invoke('mihomoRules')
|
mihomoCloseAllConnections: () => Promise<void>
|
||||||
export const mihomoProxies = (): Promise<IMihomoProxies> => invoke('mihomoProxies')
|
mihomoRules: () => Promise<IMihomoRulesInfo>
|
||||||
export const mihomoGroups = (): Promise<IMihomoMixedGroup[]> => invoke('mihomoGroups')
|
mihomoProxies: () => Promise<IMihomoProxies>
|
||||||
export const mihomoProxyProviders = (): Promise<IMihomoProxyProviders> =>
|
mihomoGroups: () => Promise<IMihomoMixedGroup[]>
|
||||||
invoke('mihomoProxyProviders')
|
mihomoProxyProviders: () => Promise<IMihomoProxyProviders>
|
||||||
export const mihomoUpdateProxyProviders = (name: string): Promise<void> =>
|
mihomoUpdateProxyProviders: (name: string) => Promise<void>
|
||||||
invoke('mihomoUpdateProxyProviders', name)
|
mihomoRuleProviders: () => Promise<IMihomoRuleProviders>
|
||||||
export const mihomoRuleProviders = (): Promise<IMihomoRuleProviders> =>
|
mihomoUpdateRuleProviders: (name: string) => Promise<void>
|
||||||
invoke('mihomoRuleProviders')
|
mihomoChangeProxy: (group: string, proxy: string) => Promise<IMihomoProxy>
|
||||||
export const mihomoUpdateRuleProviders = (name: string): Promise<void> =>
|
mihomoUnfixedProxy: (group: string) => Promise<IMihomoProxy>
|
||||||
invoke('mihomoUpdateRuleProviders', name)
|
mihomoUpgradeGeo: () => Promise<void>
|
||||||
export const mihomoChangeProxy = (group: string, proxy: string): Promise<IMihomoProxy> =>
|
mihomoUpgrade: () => Promise<void>
|
||||||
invoke('mihomoChangeProxy', group, proxy)
|
mihomoUpgradeUI: () => Promise<void>
|
||||||
export const mihomoUnfixedProxy = (group: string): Promise<IMihomoProxy> =>
|
mihomoUpgradeConfig: () => Promise<void>
|
||||||
invoke('mihomoUnfixedProxy', group)
|
mihomoProxyDelay: (proxy: string, url?: string) => Promise<IMihomoDelay>
|
||||||
export const mihomoUpgradeGeo = (): Promise<void> => invoke('mihomoUpgradeGeo')
|
mihomoGroupDelay: (group: string, url?: string) => Promise<IMihomoGroupDelay>
|
||||||
export const mihomoUpgrade = (): Promise<void> => invoke('mihomoUpgrade')
|
patchMihomoConfig: (patch: Partial<IMihomoConfig>) => Promise<void>
|
||||||
export const mihomoUpgradeUI = (): Promise<void> => invoke('mihomoUpgradeUI')
|
mihomoSmartGroupWeights: (groupName: string) => Promise<Record<string, number>>
|
||||||
export const mihomoUpgradeConfig = (): Promise<void> => invoke('mihomoUpgradeConfig')
|
mihomoSmartFlushCache: (configName?: string) => Promise<void>
|
||||||
export const mihomoProxyDelay = (proxy: string, url?: string): Promise<IMihomoDelay> =>
|
getSmartOverrideContent: () => Promise<string | null>
|
||||||
invoke('mihomoProxyDelay', proxy, url)
|
// AutoRun
|
||||||
export const mihomoGroupDelay = (group: string, url?: string): Promise<IMihomoGroupDelay> =>
|
checkAutoRun: () => Promise<boolean>
|
||||||
invoke('mihomoGroupDelay', group, url)
|
enableAutoRun: () => Promise<void>
|
||||||
export const patchMihomoConfig = (patch: Partial<IMihomoConfig>): Promise<void> =>
|
disableAutoRun: () => Promise<void>
|
||||||
invoke('patchMihomoConfig', patch)
|
// Config
|
||||||
export const mihomoSmartGroupWeights = (groupName: string): Promise<Record<string, number>> =>
|
getAppConfig: (force?: boolean) => Promise<IAppConfig>
|
||||||
invoke('mihomoSmartGroupWeights', groupName)
|
patchAppConfig: (patch: Partial<IAppConfig>) => Promise<void>
|
||||||
export const mihomoSmartFlushCache = (configName?: string): Promise<void> =>
|
getControledMihomoConfig: (force?: boolean) => Promise<Partial<IMihomoConfig>>
|
||||||
invoke('mihomoSmartFlushCache', configName)
|
patchControledMihomoConfig: (patch: Partial<IMihomoConfig>) => Promise<void>
|
||||||
export const getSmartOverrideContent = (): Promise<string | null> =>
|
resetAppConfig: () => Promise<void>
|
||||||
invoke('getSmartOverrideContent')
|
// Profile
|
||||||
|
getProfileConfig: (force?: boolean) => Promise<IProfileConfig>
|
||||||
|
setProfileConfig: (config: IProfileConfig) => Promise<void>
|
||||||
|
getCurrentProfileItem: () => Promise<IProfileItem>
|
||||||
|
getProfileItem: (id: string | undefined) => Promise<IProfileItem>
|
||||||
|
getProfileStr: (id: string) => Promise<string>
|
||||||
|
setProfileStr: (id: string, str: string) => Promise<void>
|
||||||
|
addProfileItem: (item: Partial<IProfileItem>) => Promise<void>
|
||||||
|
removeProfileItem: (id: string) => Promise<void>
|
||||||
|
updateProfileItem: (item: IProfileItem) => Promise<void>
|
||||||
|
changeCurrentProfile: (id: string) => Promise<void>
|
||||||
|
addProfileUpdater: (item: IProfileItem) => Promise<void>
|
||||||
|
removeProfileUpdater: (id: string) => Promise<void>
|
||||||
|
// Override
|
||||||
|
getOverrideConfig: (force?: boolean) => Promise<IOverrideConfig>
|
||||||
|
setOverrideConfig: (config: IOverrideConfig) => Promise<void>
|
||||||
|
getOverrideItem: (id: string) => Promise<IOverrideItem | undefined>
|
||||||
|
addOverrideItem: (item: Partial<IOverrideItem>) => Promise<void>
|
||||||
|
removeOverrideItem: (id: string) => Promise<void>
|
||||||
|
updateOverrideItem: (item: IOverrideItem) => Promise<void>
|
||||||
|
getOverride: (id: string, ext: 'js' | 'yaml' | 'log') => Promise<string>
|
||||||
|
setOverride: (id: string, ext: 'js' | 'yaml', str: string) => Promise<void>
|
||||||
|
// File
|
||||||
|
getFileStr: (path: string) => Promise<string>
|
||||||
|
setFileStr: (path: string, str: string) => Promise<void>
|
||||||
|
convertMrsRuleset: (path: string, behavior: string) => Promise<string>
|
||||||
|
getRuntimeConfig: () => Promise<IMihomoConfig>
|
||||||
|
getRuntimeConfigStr: () => Promise<string>
|
||||||
|
getRuleStr: (id: string) => Promise<string>
|
||||||
|
setRuleStr: (id: string, str: string) => Promise<void>
|
||||||
|
getFilePath: (ext: string[]) => Promise<string[] | undefined>
|
||||||
|
readTextFile: (filePath: string) => Promise<string>
|
||||||
|
openFile: (type: 'profile' | 'override', id: string, ext?: 'yaml' | 'js') => Promise<void>
|
||||||
|
// Core
|
||||||
|
restartCore: () => Promise<void>
|
||||||
|
startMonitor: () => Promise<void>
|
||||||
|
quitWithoutCore: () => Promise<void>
|
||||||
|
// System
|
||||||
|
triggerSysProxy: (enable: boolean) => Promise<void>
|
||||||
|
checkTunPermissions: () => Promise<boolean>
|
||||||
|
grantTunPermissions: () => Promise<void>
|
||||||
|
manualGrantCorePermition: () => Promise<void>
|
||||||
|
checkAdminPrivileges: () => Promise<boolean>
|
||||||
|
restartAsAdmin: () => Promise<void>
|
||||||
|
checkMihomoCorePermissions: () => Promise<boolean>
|
||||||
|
checkHighPrivilegeCore: () => Promise<boolean>
|
||||||
|
showTunPermissionDialog: () => Promise<boolean>
|
||||||
|
showErrorDialog: (title: string, message: string) => Promise<void>
|
||||||
|
openUWPTool: () => Promise<void>
|
||||||
|
setupFirewall: () => Promise<void>
|
||||||
|
getInterfaces: () => Promise<Record<string, NetworkInterfaceInfo[]>>
|
||||||
|
setNativeTheme: (theme: 'system' | 'light' | 'dark') => Promise<void>
|
||||||
|
copyEnv: (type: 'bash' | 'cmd' | 'powershell') => Promise<void>
|
||||||
|
// Update
|
||||||
|
checkUpdate: () => Promise<IAppVersion | undefined>
|
||||||
|
downloadAndInstallUpdate: (version: string) => Promise<void>
|
||||||
|
getVersion: () => Promise<string>
|
||||||
|
platform: () => Promise<NodeJS.Platform>
|
||||||
|
fetchMihomoTags: (
|
||||||
|
forceRefresh?: boolean
|
||||||
|
) => Promise<{ name: string; zipball_url: string; tarball_url: string }[]>
|
||||||
|
installSpecificMihomoCore: (version: string) => Promise<void>
|
||||||
|
clearMihomoVersionCache: () => Promise<void>
|
||||||
|
// Backup
|
||||||
|
webdavBackup: () => Promise<boolean>
|
||||||
|
webdavRestore: (filename: string) => Promise<void>
|
||||||
|
listWebdavBackups: () => Promise<string[]>
|
||||||
|
webdavDelete: (filename: string) => Promise<void>
|
||||||
|
reinitWebdavBackupScheduler: () => Promise<void>
|
||||||
|
exportLocalBackup: () => Promise<boolean>
|
||||||
|
importLocalBackup: () => Promise<boolean>
|
||||||
|
// SubStore
|
||||||
|
startSubStoreFrontendServer: () => Promise<void>
|
||||||
|
stopSubStoreFrontendServer: () => Promise<void>
|
||||||
|
startSubStoreBackendServer: () => Promise<void>
|
||||||
|
stopSubStoreBackendServer: () => Promise<void>
|
||||||
|
downloadSubStore: () => Promise<void>
|
||||||
|
subStorePort: () => Promise<number>
|
||||||
|
subStoreFrontendPort: () => Promise<number>
|
||||||
|
subStoreSubs: () => Promise<ISubStoreSub[]>
|
||||||
|
subStoreCollections: () => Promise<ISubStoreSub[]>
|
||||||
|
// Theme
|
||||||
|
resolveThemes: () => Promise<{ key: string; label: string; content: string }[]>
|
||||||
|
fetchThemes: () => Promise<void>
|
||||||
|
importThemes: (files: string[]) => Promise<void>
|
||||||
|
readTheme: (theme: string) => Promise<string>
|
||||||
|
writeTheme: (theme: string, css: string) => Promise<void>
|
||||||
|
// Tray
|
||||||
|
showTrayIcon: () => Promise<void>
|
||||||
|
closeTrayIcon: () => Promise<void>
|
||||||
|
updateTrayIcon: () => Promise<void>
|
||||||
|
// Window
|
||||||
|
showMainWindow: () => Promise<void>
|
||||||
|
closeMainWindow: () => Promise<void>
|
||||||
|
triggerMainWindow: () => Promise<void>
|
||||||
|
showFloatingWindow: () => Promise<void>
|
||||||
|
closeFloatingWindow: () => Promise<void>
|
||||||
|
showContextMenu: () => Promise<void>
|
||||||
|
setAlwaysOnTop: (alwaysOnTop: boolean) => Promise<void>
|
||||||
|
isAlwaysOnTop: () => Promise<boolean>
|
||||||
|
openDevTools: () => Promise<void>
|
||||||
|
createHeapSnapshot: () => Promise<void>
|
||||||
|
// Shortcut
|
||||||
|
registerShortcut: (oldShortcut: string, newShortcut: string, action: string) => Promise<boolean>
|
||||||
|
// Misc
|
||||||
|
getGistUrl: () => Promise<string>
|
||||||
|
getImageDataURL: (url: string) => Promise<string>
|
||||||
|
relaunchApp: () => Promise<void>
|
||||||
|
quitApp: () => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
// AutoRun
|
// 使用 Proxy 自动生成 IPC 调用
|
||||||
export const checkAutoRun = (): Promise<boolean> => invoke('checkAutoRun')
|
const ipc = new Proxy({} as IpcApi, {
|
||||||
export const enableAutoRun = (): Promise<void> => invoke('enableAutoRun')
|
get:
|
||||||
export const disableAutoRun = (): Promise<void> => invoke('disableAutoRun')
|
<K extends keyof IpcApi>(_: IpcApi, channel: K) =>
|
||||||
|
(...args: Parameters<IpcApi[K]>) =>
|
||||||
|
invoke(channel, ...args)
|
||||||
|
})
|
||||||
|
|
||||||
// Config
|
// 导出所有 IPC 方法
|
||||||
export const getAppConfig = (force = false): Promise<IAppConfig> => invoke('getAppConfig', force)
|
export const {
|
||||||
export const patchAppConfig = (patch: Partial<IAppConfig>): Promise<void> =>
|
// Mihomo API
|
||||||
invoke('patchAppConfig', patch)
|
mihomoVersion,
|
||||||
export const getControledMihomoConfig = (force = false): Promise<Partial<IMihomoConfig>> =>
|
mihomoCloseConnection,
|
||||||
invoke('getControledMihomoConfig', force)
|
mihomoCloseAllConnections,
|
||||||
export const patchControledMihomoConfig = (patch: Partial<IMihomoConfig>): Promise<void> =>
|
mihomoRules,
|
||||||
invoke('patchControledMihomoConfig', patch)
|
mihomoProxies,
|
||||||
export const resetAppConfig = (): Promise<void> => invoke('resetAppConfig')
|
mihomoGroups,
|
||||||
|
mihomoProxyProviders,
|
||||||
|
mihomoUpdateProxyProviders,
|
||||||
|
mihomoRuleProviders,
|
||||||
|
mihomoUpdateRuleProviders,
|
||||||
|
mihomoChangeProxy,
|
||||||
|
mihomoUnfixedProxy,
|
||||||
|
mihomoUpgradeGeo,
|
||||||
|
mihomoUpgrade,
|
||||||
|
mihomoUpgradeUI,
|
||||||
|
mihomoUpgradeConfig,
|
||||||
|
mihomoProxyDelay,
|
||||||
|
mihomoGroupDelay,
|
||||||
|
patchMihomoConfig,
|
||||||
|
mihomoSmartGroupWeights,
|
||||||
|
mihomoSmartFlushCache,
|
||||||
|
getSmartOverrideContent,
|
||||||
|
// AutoRun
|
||||||
|
checkAutoRun,
|
||||||
|
enableAutoRun,
|
||||||
|
disableAutoRun,
|
||||||
|
// Config
|
||||||
|
getAppConfig,
|
||||||
|
patchAppConfig,
|
||||||
|
getControledMihomoConfig,
|
||||||
|
patchControledMihomoConfig,
|
||||||
|
resetAppConfig,
|
||||||
|
// Profile
|
||||||
|
getProfileConfig,
|
||||||
|
setProfileConfig,
|
||||||
|
getCurrentProfileItem,
|
||||||
|
getProfileItem,
|
||||||
|
getProfileStr,
|
||||||
|
setProfileStr,
|
||||||
|
addProfileItem,
|
||||||
|
removeProfileItem,
|
||||||
|
updateProfileItem,
|
||||||
|
changeCurrentProfile,
|
||||||
|
addProfileUpdater,
|
||||||
|
removeProfileUpdater,
|
||||||
|
// Override
|
||||||
|
getOverrideConfig,
|
||||||
|
setOverrideConfig,
|
||||||
|
getOverrideItem,
|
||||||
|
addOverrideItem,
|
||||||
|
removeOverrideItem,
|
||||||
|
updateOverrideItem,
|
||||||
|
getOverride,
|
||||||
|
setOverride,
|
||||||
|
// File
|
||||||
|
getFileStr,
|
||||||
|
setFileStr,
|
||||||
|
convertMrsRuleset,
|
||||||
|
getRuntimeConfig,
|
||||||
|
getRuntimeConfigStr,
|
||||||
|
getRuleStr,
|
||||||
|
setRuleStr,
|
||||||
|
getFilePath,
|
||||||
|
readTextFile,
|
||||||
|
openFile,
|
||||||
|
// Core
|
||||||
|
restartCore,
|
||||||
|
startMonitor,
|
||||||
|
quitWithoutCore,
|
||||||
|
// System
|
||||||
|
triggerSysProxy,
|
||||||
|
checkTunPermissions,
|
||||||
|
grantTunPermissions,
|
||||||
|
manualGrantCorePermition,
|
||||||
|
checkAdminPrivileges,
|
||||||
|
restartAsAdmin,
|
||||||
|
checkMihomoCorePermissions,
|
||||||
|
checkHighPrivilegeCore,
|
||||||
|
showTunPermissionDialog,
|
||||||
|
showErrorDialog,
|
||||||
|
openUWPTool,
|
||||||
|
setupFirewall,
|
||||||
|
getInterfaces,
|
||||||
|
setNativeTheme,
|
||||||
|
copyEnv,
|
||||||
|
// Update
|
||||||
|
checkUpdate,
|
||||||
|
downloadAndInstallUpdate,
|
||||||
|
getVersion,
|
||||||
|
fetchMihomoTags,
|
||||||
|
installSpecificMihomoCore,
|
||||||
|
clearMihomoVersionCache,
|
||||||
|
// Backup
|
||||||
|
webdavBackup,
|
||||||
|
webdavRestore,
|
||||||
|
listWebdavBackups,
|
||||||
|
webdavDelete,
|
||||||
|
reinitWebdavBackupScheduler,
|
||||||
|
exportLocalBackup,
|
||||||
|
importLocalBackup,
|
||||||
|
// SubStore
|
||||||
|
startSubStoreFrontendServer,
|
||||||
|
stopSubStoreFrontendServer,
|
||||||
|
startSubStoreBackendServer,
|
||||||
|
stopSubStoreBackendServer,
|
||||||
|
downloadSubStore,
|
||||||
|
subStorePort,
|
||||||
|
subStoreFrontendPort,
|
||||||
|
subStoreSubs,
|
||||||
|
subStoreCollections,
|
||||||
|
// Theme
|
||||||
|
resolveThemes,
|
||||||
|
fetchThemes,
|
||||||
|
importThemes,
|
||||||
|
readTheme,
|
||||||
|
writeTheme,
|
||||||
|
// Tray
|
||||||
|
showTrayIcon,
|
||||||
|
closeTrayIcon,
|
||||||
|
updateTrayIcon,
|
||||||
|
// Window
|
||||||
|
showMainWindow,
|
||||||
|
closeMainWindow,
|
||||||
|
triggerMainWindow,
|
||||||
|
showFloatingWindow,
|
||||||
|
closeFloatingWindow,
|
||||||
|
showContextMenu,
|
||||||
|
setAlwaysOnTop,
|
||||||
|
isAlwaysOnTop,
|
||||||
|
openDevTools,
|
||||||
|
createHeapSnapshot,
|
||||||
|
// Shortcut
|
||||||
|
registerShortcut,
|
||||||
|
// Misc
|
||||||
|
getGistUrl,
|
||||||
|
getImageDataURL,
|
||||||
|
relaunchApp,
|
||||||
|
quitApp
|
||||||
|
} = ipc
|
||||||
|
|
||||||
// Profile
|
// platform 需要重命名导出
|
||||||
export const getProfileConfig = (force = false): Promise<IProfileConfig> =>
|
export const getPlatform = ipc.platform
|
||||||
invoke('getProfileConfig', force)
|
|
||||||
export const setProfileConfig = (config: IProfileConfig): Promise<void> =>
|
|
||||||
invoke('setProfileConfig', config)
|
|
||||||
export const getCurrentProfileItem = (): Promise<IProfileItem> => invoke('getCurrentProfileItem')
|
|
||||||
export const getProfileItem = (id: string | undefined): Promise<IProfileItem> =>
|
|
||||||
invoke('getProfileItem', id)
|
|
||||||
export const getProfileStr = (id: string): Promise<string> => invoke('getProfileStr', id)
|
|
||||||
export const setProfileStr = (id: string, str: string): Promise<void> =>
|
|
||||||
invoke('setProfileStr', id, str)
|
|
||||||
export const addProfileItem = (item: Partial<IProfileItem>): Promise<void> =>
|
|
||||||
invoke('addProfileItem', item)
|
|
||||||
export const removeProfileItem = (id: string): Promise<void> => invoke('removeProfileItem', id)
|
|
||||||
export const updateProfileItem = (item: IProfileItem): Promise<void> =>
|
|
||||||
invoke('updateProfileItem', item)
|
|
||||||
export const changeCurrentProfile = (id: string): Promise<void> =>
|
|
||||||
invoke('changeCurrentProfile', id)
|
|
||||||
export const addProfileUpdater = (item: IProfileItem): Promise<void> =>
|
|
||||||
invoke('addProfileUpdater', item)
|
|
||||||
export const removeProfileUpdater = (id: string): Promise<void> =>
|
|
||||||
invoke('removeProfileUpdater', id)
|
|
||||||
|
|
||||||
// Override
|
// 需要特殊处理的函数
|
||||||
export const getOverrideConfig = (force = false): Promise<IOverrideConfig> =>
|
|
||||||
invoke('getOverrideConfig', force)
|
|
||||||
export const setOverrideConfig = (config: IOverrideConfig): Promise<void> =>
|
|
||||||
invoke('setOverrideConfig', config)
|
|
||||||
export const getOverrideItem = (id: string): Promise<IOverrideItem | undefined> =>
|
|
||||||
invoke('getOverrideItem', id)
|
|
||||||
export const addOverrideItem = (item: Partial<IOverrideItem>): Promise<void> =>
|
|
||||||
invoke('addOverrideItem', item)
|
|
||||||
export const removeOverrideItem = (id: string): Promise<void> => invoke('removeOverrideItem', id)
|
|
||||||
export const updateOverrideItem = (item: IOverrideItem): Promise<void> =>
|
|
||||||
invoke('updateOverrideItem', item)
|
|
||||||
export const getOverride = (id: string, ext: 'js' | 'yaml' | 'log'): Promise<string> =>
|
|
||||||
invoke('getOverride', id, ext)
|
|
||||||
export const setOverride = (id: string, ext: 'js' | 'yaml', str: string): Promise<void> =>
|
|
||||||
invoke('setOverride', id, ext, str)
|
|
||||||
|
|
||||||
// File
|
|
||||||
export const getFileStr = (path: string): Promise<string> => invoke('getFileStr', path)
|
|
||||||
export const setFileStr = (path: string, str: string): Promise<void> =>
|
|
||||||
invoke('setFileStr', path, str)
|
|
||||||
export const convertMrsRuleset = (path: string, behavior: string): Promise<string> =>
|
|
||||||
invoke('convertMrsRuleset', path, behavior)
|
|
||||||
export const getRuntimeConfig = (): Promise<IMihomoConfig> => invoke('getRuntimeConfig')
|
|
||||||
export const getRuntimeConfigStr = (): Promise<string> => invoke('getRuntimeConfigStr')
|
|
||||||
export const getRuleStr = (id: string): Promise<string> => invoke('getRuleStr', id)
|
|
||||||
export const setRuleStr = (id: string, str: string): Promise<void> => invoke('setRuleStr', id, str)
|
|
||||||
export const getFilePath = (ext: string[]): Promise<string[] | undefined> =>
|
|
||||||
invoke('getFilePath', ext)
|
|
||||||
export const readTextFile = (filePath: string): Promise<string> => invoke('readTextFile', filePath)
|
|
||||||
export const openFile = (
|
|
||||||
type: 'profile' | 'override',
|
|
||||||
id: string,
|
|
||||||
ext?: 'yaml' | 'js'
|
|
||||||
): Promise<void> => invoke('openFile', type, id, ext)
|
|
||||||
|
|
||||||
// Core
|
|
||||||
export const restartCore = (): Promise<void> => invoke('restartCore')
|
|
||||||
export const startMonitor = (): Promise<void> => invoke('startMonitor')
|
|
||||||
export const quitWithoutCore = (): Promise<void> => invoke('quitWithoutCore')
|
|
||||||
|
|
||||||
// System
|
|
||||||
export const triggerSysProxy = (enable: boolean): Promise<void> => invoke('triggerSysProxy', enable)
|
|
||||||
export const checkTunPermissions = (): Promise<boolean> => invoke('checkTunPermissions')
|
|
||||||
export const grantTunPermissions = (): Promise<void> => invoke('grantTunPermissions')
|
|
||||||
export const manualGrantCorePermition = (): Promise<void> => invoke('manualGrantCorePermition')
|
|
||||||
export const checkAdminPrivileges = (): Promise<boolean> => invoke('checkAdminPrivileges')
|
|
||||||
export const restartAsAdmin = (): Promise<void> => invoke('restartAsAdmin')
|
|
||||||
export const checkMihomoCorePermissions = (): Promise<boolean> =>
|
|
||||||
invoke('checkMihomoCorePermissions')
|
|
||||||
export const checkHighPrivilegeCore = (): Promise<boolean> => invoke('checkHighPrivilegeCore')
|
|
||||||
export const showTunPermissionDialog = (): Promise<boolean> => invoke('showTunPermissionDialog')
|
|
||||||
export const showErrorDialog = (title: string, message: string): Promise<void> =>
|
|
||||||
invoke('showErrorDialog', title, message)
|
|
||||||
export const openUWPTool = (): Promise<void> => invoke('openUWPTool')
|
|
||||||
export const setupFirewall = (): Promise<void> => invoke('setupFirewall')
|
|
||||||
export const getInterfaces = (): Promise<Record<string, NetworkInterfaceInfo[]>> =>
|
|
||||||
invoke('getInterfaces')
|
|
||||||
export const setNativeTheme = (theme: 'system' | 'light' | 'dark'): Promise<void> =>
|
|
||||||
invoke('setNativeTheme', theme)
|
|
||||||
export const copyEnv = (type: 'bash' | 'cmd' | 'powershell'): Promise<void> =>
|
|
||||||
invoke('copyEnv', type)
|
|
||||||
|
|
||||||
// Update
|
|
||||||
export const checkUpdate = (): Promise<IAppVersion | undefined> => invoke('checkUpdate')
|
|
||||||
export const downloadAndInstallUpdate = (version: string): Promise<void> =>
|
|
||||||
invoke('downloadAndInstallUpdate', version)
|
|
||||||
export const getVersion = (): Promise<string> => invoke('getVersion')
|
|
||||||
export const getPlatform = (): Promise<NodeJS.Platform> => invoke('platform')
|
|
||||||
export const fetchMihomoTags = (
|
|
||||||
forceRefresh = false
|
|
||||||
): Promise<{ name: string; zipball_url: string; tarball_url: string }[]> =>
|
|
||||||
invoke('fetchMihomoTags', forceRefresh)
|
|
||||||
export const installSpecificMihomoCore = (version: string): Promise<void> =>
|
|
||||||
invoke('installSpecificMihomoCore', version)
|
|
||||||
export const clearMihomoVersionCache = (): Promise<void> => invoke('clearMihomoVersionCache')
|
|
||||||
|
|
||||||
// Backup
|
|
||||||
export const webdavBackup = (): Promise<boolean> => invoke('webdavBackup')
|
|
||||||
export const webdavRestore = (filename: string): Promise<void> => invoke('webdavRestore', filename)
|
|
||||||
export const listWebdavBackups = (): Promise<string[]> => invoke('listWebdavBackups')
|
|
||||||
export const webdavDelete = (filename: string): Promise<void> => invoke('webdavDelete', filename)
|
|
||||||
export const reinitWebdavBackupScheduler = (): Promise<void> =>
|
|
||||||
invoke('reinitWebdavBackupScheduler')
|
|
||||||
export const exportLocalBackup = (): Promise<boolean> => invoke('exportLocalBackup')
|
|
||||||
export const importLocalBackup = (): Promise<boolean> => invoke('importLocalBackup')
|
|
||||||
|
|
||||||
// SubStore
|
|
||||||
export const startSubStoreFrontendServer = (): Promise<void> =>
|
|
||||||
invoke('startSubStoreFrontendServer')
|
|
||||||
export const stopSubStoreFrontendServer = (): Promise<void> => invoke('stopSubStoreFrontendServer')
|
|
||||||
export const startSubStoreBackendServer = (): Promise<void> => invoke('startSubStoreBackendServer')
|
|
||||||
export const stopSubStoreBackendServer = (): Promise<void> => invoke('stopSubStoreBackendServer')
|
|
||||||
export const downloadSubStore = (): Promise<void> => invoke('downloadSubStore')
|
|
||||||
export const subStorePort = (): Promise<number> => invoke('subStorePort')
|
|
||||||
export const subStoreFrontendPort = (): Promise<number> => invoke('subStoreFrontendPort')
|
|
||||||
export const subStoreSubs = (): Promise<ISubStoreSub[]> => invoke('subStoreSubs')
|
|
||||||
export const subStoreCollections = (): Promise<ISubStoreSub[]> => invoke('subStoreCollections')
|
|
||||||
|
|
||||||
// Theme
|
|
||||||
export const resolveThemes = (): Promise<{ key: string; label: string; content: string }[]> =>
|
|
||||||
invoke('resolveThemes')
|
|
||||||
export const fetchThemes = (): Promise<void> => invoke('fetchThemes')
|
|
||||||
export const importThemes = (files: string[]): Promise<void> => invoke('importThemes', files)
|
|
||||||
export const readTheme = (theme: string): Promise<string> => invoke('readTheme', theme)
|
|
||||||
export const writeTheme = (theme: string, css: string): Promise<void> =>
|
|
||||||
invoke('writeTheme', theme, css)
|
|
||||||
|
|
||||||
|
// applyTheme: 防抖处理,避免频繁调用
|
||||||
let applyThemeRunning = false
|
let applyThemeRunning = false
|
||||||
let pendingTheme: string | null = null
|
let pendingTheme: string | null = null
|
||||||
|
|
||||||
@ -216,21 +336,7 @@ export async function applyTheme(theme: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tray
|
// setTitleBarOverlay: 需要静默处理不支持的平台
|
||||||
export const showTrayIcon = (): Promise<void> => invoke('showTrayIcon')
|
|
||||||
export const closeTrayIcon = (): Promise<void> => invoke('closeTrayIcon')
|
|
||||||
export const updateTrayIcon = (): Promise<void> => invoke('updateTrayIcon')
|
|
||||||
export function updateTrayIconImmediate(sysProxyEnabled: boolean, tunEnabled: boolean): void {
|
|
||||||
window.electron.ipcRenderer.invoke('updateTrayIconImmediate', sysProxyEnabled, tunEnabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Window
|
|
||||||
export const showMainWindow = (): Promise<void> => invoke('showMainWindow')
|
|
||||||
export const closeMainWindow = (): Promise<void> => invoke('closeMainWindow')
|
|
||||||
export const triggerMainWindow = (): Promise<void> => invoke('triggerMainWindow')
|
|
||||||
export const showFloatingWindow = (): Promise<void> => invoke('showFloatingWindow')
|
|
||||||
export const closeFloatingWindow = (): Promise<void> => invoke('closeFloatingWindow')
|
|
||||||
export const showContextMenu = (): Promise<void> => invoke('showContextMenu')
|
|
||||||
export async function setTitleBarOverlay(overlay: TitleBarOverlayOptions): Promise<void> {
|
export async function setTitleBarOverlay(overlay: TitleBarOverlayOptions): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await invoke<void>('setTitleBarOverlay', overlay)
|
await invoke<void>('setTitleBarOverlay', overlay)
|
||||||
@ -238,21 +344,8 @@ export async function setTitleBarOverlay(overlay: TitleBarOverlayOptions): Promi
|
|||||||
// Not supported on this platform
|
// Not supported on this platform
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const setAlwaysOnTop = (alwaysOnTop: boolean): Promise<void> =>
|
|
||||||
invoke('setAlwaysOnTop', alwaysOnTop)
|
|
||||||
export const isAlwaysOnTop = (): Promise<boolean> => invoke('isAlwaysOnTop')
|
|
||||||
export const openDevTools = (): Promise<void> => invoke('openDevTools')
|
|
||||||
export const createHeapSnapshot = (): Promise<void> => invoke('createHeapSnapshot')
|
|
||||||
|
|
||||||
// Shortcut
|
// updateTrayIconImmediate: 同步调用,不等待结果
|
||||||
export const registerShortcut = (
|
export function updateTrayIconImmediate(sysProxyEnabled: boolean, tunEnabled: boolean): void {
|
||||||
oldShortcut: string,
|
window.electron.ipcRenderer.invoke('updateTrayIconImmediate', sysProxyEnabled, tunEnabled)
|
||||||
newShortcut: string,
|
}
|
||||||
action: string
|
|
||||||
): Promise<boolean> => invoke('registerShortcut', oldShortcut, newShortcut, action)
|
|
||||||
|
|
||||||
// Misc
|
|
||||||
export const getGistUrl = (): Promise<string> => invoke('getGistUrl')
|
|
||||||
export const getImageDataURL = (url: string): Promise<string> => invoke('getImageDataURL', url)
|
|
||||||
export const relaunchApp = (): Promise<void> => invoke('relaunchApp')
|
|
||||||
export const quitApp = (): Promise<void> => invoke('quitApp')
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user