mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 13:10:30 +08:00
add postinstall for macOS
This commit is contained in:
parent
64ed2864dc
commit
2164aa7520
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@ -199,6 +199,7 @@ jobs:
|
|||||||
npm_config_target_arch: ${{ matrix.arch }}
|
npm_config_target_arch: ${{ matrix.arch }}
|
||||||
run: |
|
run: |
|
||||||
sed -i "" -e "s/productName: mihomo-party/productName: Mihomo Party/" electron-builder.yml
|
sed -i "" -e "s/productName: mihomo-party/productName: Mihomo Party/" electron-builder.yml
|
||||||
|
chmod +x build/pkg-scripts/postinstall
|
||||||
pnpm build:mac --${{ matrix.arch }}
|
pnpm build:mac --${{ matrix.arch }}
|
||||||
- name: Generate checksums
|
- name: Generate checksums
|
||||||
run: pnpm checksum .pkg
|
run: pnpm checksum .pkg
|
||||||
|
|||||||
6
build/pkg-scripts/postinstall
Normal file
6
build/pkg-scripts/postinstall
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
chown root:admin $2/Mihomo\ Party.app/Contents/Resources/sidecar/mihomo
|
||||||
|
chown root:admin $2/Mihomo\ Party.app/Contents/Resources/sidecar/mihomo-alpha
|
||||||
|
chmod +s $2/Mihomo\ Party.app/Contents/Resources/sidecar/mihomo
|
||||||
|
chmod +s $2/Mihomo\ Party.app/Contents/Resources/sidecar/mihomo-alpha
|
||||||
|
exit 0
|
||||||
10
changelog.md
10
changelog.md
@ -1,3 +1,11 @@
|
|||||||
|
### Breaking Changes
|
||||||
|
|
||||||
|
- macOS 改用 pkg 安装方式,不再支持 dmg 安装方式,因此本次更新需要手动下载安装包进行安装
|
||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
- Linux 不再存储 root 密码
|
- macOS/Linux 均不再存储 root 密码
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- 修复 macOS 10.15 无法安装的问题
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import {
|
|||||||
patchAppConfig,
|
patchAppConfig,
|
||||||
patchControledMihomoConfig
|
patchControledMihomoConfig
|
||||||
} from '../config'
|
} from '../config'
|
||||||
import { app, dialog, ipcMain, net, safeStorage } from 'electron'
|
import { app, dialog, ipcMain, net } from 'electron'
|
||||||
import {
|
import {
|
||||||
startMihomoTraffic,
|
startMihomoTraffic,
|
||||||
startMihomoConnections,
|
startMihomoConnections,
|
||||||
@ -57,27 +57,12 @@ let child: ChildProcess
|
|||||||
let retry = 10
|
let retry = 10
|
||||||
|
|
||||||
export async function startCore(detached = false): Promise<Promise<void>[]> {
|
export async function startCore(detached = false): Promise<Promise<void>[]> {
|
||||||
const {
|
const { core = 'mihomo', autoSetDNS = true, diffWorkDir = false } = await getAppConfig()
|
||||||
core = 'mihomo',
|
|
||||||
autoSetDNS = true,
|
|
||||||
encryptedPassword,
|
|
||||||
diffWorkDir = false
|
|
||||||
} = await getAppConfig()
|
|
||||||
const { 'log-level': logLevel } = await getControledMihomoConfig()
|
const { 'log-level': logLevel } = await getControledMihomoConfig()
|
||||||
if (existsSync(path.join(dataDir(), 'core.pid'))) {
|
if (existsSync(path.join(dataDir(), 'core.pid'))) {
|
||||||
const pid = parseInt(await readFile(path.join(dataDir(), 'core.pid'), 'utf-8'))
|
const pid = parseInt(await readFile(path.join(dataDir(), 'core.pid'), 'utf-8'))
|
||||||
try {
|
try {
|
||||||
process.kill(pid, 'SIGINT')
|
process.kill(pid, 'SIGINT')
|
||||||
} catch {
|
|
||||||
if (process.platform === 'darwin' && encryptedPassword && isEncryptionAvailable()) {
|
|
||||||
const execPromise = promisify(exec)
|
|
||||||
const password = safeStorage.decryptString(Buffer.from(encryptedPassword))
|
|
||||||
try {
|
|
||||||
await execPromise(`echo "${password}" | sudo -S kill ${pid}`)
|
|
||||||
} catch {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
await rm(path.join(dataDir(), 'core.pid'))
|
await rm(path.join(dataDir(), 'core.pid'))
|
||||||
}
|
}
|
||||||
@ -85,7 +70,6 @@ export async function startCore(detached = false): Promise<Promise<void>[]> {
|
|||||||
const { current } = await getProfileConfig()
|
const { current } = await getProfileConfig()
|
||||||
const { tun } = await getControledMihomoConfig()
|
const { tun } = await getControledMihomoConfig()
|
||||||
const corePath = mihomoCorePath(core)
|
const corePath = mihomoCorePath(core)
|
||||||
await autoGrantCorePermition(corePath)
|
|
||||||
await generateProfile()
|
await generateProfile()
|
||||||
await checkProfile()
|
await checkProfile()
|
||||||
await stopCore()
|
await stopCore()
|
||||||
@ -242,24 +226,6 @@ async function checkProfile(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function autoGrantCorePermition(corePath: string): Promise<void> {
|
|
||||||
if (process.platform !== 'darwin') return
|
|
||||||
const { encryptedPassword } = await getAppConfig()
|
|
||||||
const execPromise = promisify(exec)
|
|
||||||
if (encryptedPassword && isEncryptionAvailable()) {
|
|
||||||
try {
|
|
||||||
const password = safeStorage.decryptString(Buffer.from(encryptedPassword))
|
|
||||||
if (process.platform === 'darwin') {
|
|
||||||
await execPromise(`echo "${password}" | sudo -S chown root:admin "${corePath}"`)
|
|
||||||
await execPromise(`echo "${password}" | sudo -S chmod +sx "${corePath}"`)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
patchAppConfig({ encryptedPassword: undefined })
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function manualGrantCorePermition(password?: string): Promise<void> {
|
export async function manualGrantCorePermition(password?: string): Promise<void> {
|
||||||
const { core = 'mihomo' } = await getAppConfig()
|
const { core = 'mihomo' } = await getAppConfig()
|
||||||
const corePath = mihomoCorePath(core)
|
const corePath = mihomoCorePath(core)
|
||||||
@ -275,27 +241,19 @@ export async function manualGrantCorePermition(password?: string): Promise<void>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isEncryptionAvailable(): boolean {
|
export async function getDefaultDevice(): Promise<string> {
|
||||||
return safeStorage.isEncryptionAvailable()
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getDefaultDevice(password?: string): Promise<string> {
|
|
||||||
const execPromise = promisify(exec)
|
const execPromise = promisify(exec)
|
||||||
let sudo = ''
|
const { stdout: deviceOut } = await execPromise(`route -n get default`)
|
||||||
if (password) sudo = `echo "${password}" | sudo -S `
|
|
||||||
const { stdout: deviceOut } = await execPromise(`${sudo}route -n get default`)
|
|
||||||
let device = deviceOut.split('\n').find((s) => s.includes('interface:'))
|
let device = deviceOut.split('\n').find((s) => s.includes('interface:'))
|
||||||
device = device?.trim().split(' ').slice(1).join(' ')
|
device = device?.trim().split(' ').slice(1).join(' ')
|
||||||
if (!device) throw new Error('Get device failed')
|
if (!device) throw new Error('Get device failed')
|
||||||
return device
|
return device
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDefaultService(password?: string): Promise<string> {
|
async function getDefaultService(): Promise<string> {
|
||||||
const execPromise = promisify(exec)
|
const execPromise = promisify(exec)
|
||||||
let sudo = ''
|
const device = await getDefaultDevice()
|
||||||
if (password) sudo = `echo "${password}" | sudo -S `
|
const { stdout: order } = await execPromise(`networksetup -listnetworkserviceorder`)
|
||||||
const device = await getDefaultDevice(password)
|
|
||||||
const { stdout: order } = await execPromise(`${sudo}networksetup -listnetworkserviceorder`)
|
|
||||||
const block = order.split('\n\n').find((s) => s.includes(`Device: ${device}`))
|
const block = order.split('\n\n').find((s) => s.includes(`Device: ${device}`))
|
||||||
if (!block) throw new Error('Get networkservice failed')
|
if (!block) throw new Error('Get networkservice failed')
|
||||||
for (const line of block.split('\n')) {
|
for (const line of block.split('\n')) {
|
||||||
@ -306,12 +264,10 @@ async function getDefaultService(password?: string): Promise<string> {
|
|||||||
throw new Error('Get service failed')
|
throw new Error('Get service failed')
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getOriginDNS(password?: string): Promise<void> {
|
async function getOriginDNS(): Promise<void> {
|
||||||
const execPromise = promisify(exec)
|
const execPromise = promisify(exec)
|
||||||
let sudo = ''
|
const service = await getDefaultService()
|
||||||
if (password) sudo = `echo "${password}" | sudo -S `
|
const { stdout: dns } = await execPromise(`networksetup -getdnsservers "${service}"`)
|
||||||
const service = await getDefaultService(password)
|
|
||||||
const { stdout: dns } = await execPromise(`${sudo}networksetup -getdnsservers "${service}"`)
|
|
||||||
if (dns.startsWith("There aren't any DNS Servers set on")) {
|
if (dns.startsWith("There aren't any DNS Servers set on")) {
|
||||||
await patchAppConfig({ originDNS: 'Empty' })
|
await patchAppConfig({ originDNS: 'Empty' })
|
||||||
} else {
|
} else {
|
||||||
@ -319,25 +275,19 @@ async function getOriginDNS(password?: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setDNS(dns: string, password?: string): Promise<void> {
|
async function setDNS(dns: string): Promise<void> {
|
||||||
const service = await getDefaultService(password)
|
const service = await getDefaultService()
|
||||||
let sudo = ''
|
|
||||||
if (password) sudo = `echo "${password}" | sudo -S `
|
|
||||||
const execPromise = promisify(exec)
|
const execPromise = promisify(exec)
|
||||||
await execPromise(`${sudo}networksetup -setdnsservers "${service}" ${dns}`)
|
await execPromise(`networksetup -setdnsservers "${service}" ${dns}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setPublicDNS(): Promise<void> {
|
async function setPublicDNS(): Promise<void> {
|
||||||
if (process.platform !== 'darwin') return
|
if (process.platform !== 'darwin') return
|
||||||
if (net.isOnline()) {
|
if (net.isOnline()) {
|
||||||
const { originDNS, encryptedPassword } = await getAppConfig()
|
const { originDNS } = await getAppConfig()
|
||||||
if (!originDNS) {
|
if (!originDNS) {
|
||||||
let password: string | undefined
|
await getOriginDNS()
|
||||||
if (encryptedPassword && isEncryptionAvailable()) {
|
await setDNS('223.5.5.5')
|
||||||
password = safeStorage.decryptString(Buffer.from(encryptedPassword))
|
|
||||||
}
|
|
||||||
await getOriginDNS(password)
|
|
||||||
await setDNS('223.5.5.5', password)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (setPublicDNSTimer) clearTimeout(setPublicDNSTimer)
|
if (setPublicDNSTimer) clearTimeout(setPublicDNSTimer)
|
||||||
@ -348,13 +298,9 @@ async function setPublicDNS(): Promise<void> {
|
|||||||
async function recoverDNS(): Promise<void> {
|
async function recoverDNS(): Promise<void> {
|
||||||
if (process.platform !== 'darwin') return
|
if (process.platform !== 'darwin') return
|
||||||
if (net.isOnline()) {
|
if (net.isOnline()) {
|
||||||
const { originDNS, encryptedPassword } = await getAppConfig()
|
const { originDNS } = await getAppConfig()
|
||||||
if (originDNS) {
|
if (originDNS) {
|
||||||
let password: string | undefined
|
await setDNS(originDNS)
|
||||||
if (encryptedPassword && isEncryptionAvailable()) {
|
|
||||||
password = safeStorage.decryptString(Buffer.from(encryptedPassword))
|
|
||||||
}
|
|
||||||
await setDNS(originDNS, password)
|
|
||||||
await patchAppConfig({ originDNS: undefined })
|
await patchAppConfig({ originDNS: undefined })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -91,20 +91,9 @@ export async function downloadAndInstallUpdate(version: string): Promise<void> {
|
|||||||
if (file.endsWith('.pkg')) {
|
if (file.endsWith('.pkg')) {
|
||||||
try {
|
try {
|
||||||
const execPromise = promisify(exec)
|
const execPromise = promisify(exec)
|
||||||
const name = exePath().split('.app')[0].replace('/Applications/', '')
|
const shell = `installer -pkg ${path.join(dataDir(), file).replace(' ', '\\\\ ')} -target /`
|
||||||
await execPromise(
|
const command = `do shell script "${shell}" with administrator privileges`
|
||||||
`hdiutil attach "${path.join(dataDir(), file)}" -mountpoint "/Volumes/mihomo-party" -nobrowse`
|
await execPromise(`osascript -e '${command}'`)
|
||||||
)
|
|
||||||
try {
|
|
||||||
await execPromise(`mv "/Applications/${name}.app" /tmp`)
|
|
||||||
await execPromise('cp -R "/Volumes/mihomo-party/Mihomo Party.app" /Applications/')
|
|
||||||
await execPromise(`rm -rf "/tmp/${name}.app"`)
|
|
||||||
} catch (e) {
|
|
||||||
await execPromise(`mv "/tmp/${name}.app" /Applications`)
|
|
||||||
throw e
|
|
||||||
} finally {
|
|
||||||
await execPromise('hdiutil detach "/Volumes/mihomo-party"')
|
|
||||||
}
|
|
||||||
app.relaunch()
|
app.relaunch()
|
||||||
app.quit()
|
app.quit()
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@ -216,7 +216,7 @@ async function migration(): Promise<void> {
|
|||||||
await patchAppConfig({ disableTray: false })
|
await patchAppConfig({ disableTray: false })
|
||||||
}
|
}
|
||||||
// remove password
|
// remove password
|
||||||
if (process.platform === 'linux' && encryptedPassword) {
|
if (encryptedPassword) {
|
||||||
await patchAppConfig({ encryptedPassword: undefined })
|
await patchAppConfig({ encryptedPassword: undefined })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { app, dialog, ipcMain, safeStorage } from 'electron'
|
import { app, dialog, ipcMain } from 'electron'
|
||||||
import {
|
import {
|
||||||
mihomoChangeProxy,
|
mihomoChangeProxy,
|
||||||
mihomoCloseAllConnections,
|
mihomoCloseAllConnections,
|
||||||
@ -51,12 +51,7 @@ import {
|
|||||||
subStoreFrontendPort,
|
subStoreFrontendPort,
|
||||||
subStorePort
|
subStorePort
|
||||||
} from '../resolve/server'
|
} from '../resolve/server'
|
||||||
import {
|
import { manualGrantCorePermition, quitWithoutCore, restartCore } from '../core/manager'
|
||||||
isEncryptionAvailable,
|
|
||||||
manualGrantCorePermition,
|
|
||||||
quitWithoutCore,
|
|
||||||
restartCore
|
|
||||||
} from '../core/manager'
|
|
||||||
import { triggerSysProxy } from '../sys/sysproxy'
|
import { triggerSysProxy } from '../sys/sysproxy'
|
||||||
import { checkUpdate, downloadAndInstallUpdate } from '../resolve/autoUpdater'
|
import { checkUpdate, downloadAndInstallUpdate } from '../resolve/autoUpdater'
|
||||||
import {
|
import {
|
||||||
@ -172,8 +167,6 @@ export function registerIpcMainHandlers(): void {
|
|||||||
ipcMain.handle('restartCore', ipcErrorWrapper(restartCore))
|
ipcMain.handle('restartCore', ipcErrorWrapper(restartCore))
|
||||||
ipcMain.handle('startMonitor', (_e, detached) => ipcErrorWrapper(startMonitor)(detached))
|
ipcMain.handle('startMonitor', (_e, detached) => ipcErrorWrapper(startMonitor)(detached))
|
||||||
ipcMain.handle('triggerSysProxy', (_e, enable) => ipcErrorWrapper(triggerSysProxy)(enable))
|
ipcMain.handle('triggerSysProxy', (_e, enable) => ipcErrorWrapper(triggerSysProxy)(enable))
|
||||||
ipcMain.handle('isEncryptionAvailable', isEncryptionAvailable)
|
|
||||||
ipcMain.handle('encryptString', (_e, str) => encryptString(str))
|
|
||||||
ipcMain.handle('manualGrantCorePermition', (_e, password) =>
|
ipcMain.handle('manualGrantCorePermition', (_e, password) =>
|
||||||
ipcErrorWrapper(manualGrantCorePermition)(password)
|
ipcErrorWrapper(manualGrantCorePermition)(password)
|
||||||
)
|
)
|
||||||
@ -256,7 +249,3 @@ export function registerIpcMainHandlers(): void {
|
|||||||
ipcMain.handle('quitWithoutCore', ipcErrorWrapper(quitWithoutCore))
|
ipcMain.handle('quitWithoutCore', ipcErrorWrapper(quitWithoutCore))
|
||||||
ipcMain.handle('quitApp', () => app.quit())
|
ipcMain.handle('quitApp', () => app.quit())
|
||||||
}
|
}
|
||||||
|
|
||||||
function encryptString(str: string): number[] {
|
|
||||||
return safeStorage.encryptString(str).toJSON().data
|
|
||||||
}
|
|
||||||
|
|||||||
@ -3,19 +3,16 @@ import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-c
|
|||||||
import BorderSwitch from '@renderer/components/base/border-swtich'
|
import BorderSwitch from '@renderer/components/base/border-swtich'
|
||||||
import { TbDeviceIpadHorizontalBolt } from 'react-icons/tb'
|
import { TbDeviceIpadHorizontalBolt } from 'react-icons/tb'
|
||||||
import { useLocation } from 'react-router-dom'
|
import { useLocation } from 'react-router-dom'
|
||||||
import { encryptString, isEncryptionAvailable, restartCore } from '@renderer/utils/ipc'
|
import { restartCore } from '@renderer/utils/ipc'
|
||||||
import { useSortable } from '@dnd-kit/sortable'
|
import { useSortable } from '@dnd-kit/sortable'
|
||||||
import { CSS } from '@dnd-kit/utilities'
|
import { CSS } from '@dnd-kit/utilities'
|
||||||
import { platform } from '@renderer/utils/init'
|
import React from 'react'
|
||||||
import React, { useState } from 'react'
|
|
||||||
import { useAppConfig } from '@renderer/hooks/use-app-config'
|
import { useAppConfig } from '@renderer/hooks/use-app-config'
|
||||||
import BasePasswordModal from '../base/base-password-modal'
|
|
||||||
|
|
||||||
const TunSwitcher: React.FC = () => {
|
const TunSwitcher: React.FC = () => {
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const match = location.pathname.includes('/tun') || false
|
const match = location.pathname.includes('/tun') || false
|
||||||
const [openPasswordModal, setOpenPasswordModal] = useState(false)
|
const { appConfig } = useAppConfig()
|
||||||
const { appConfig, patchAppConfig } = useAppConfig()
|
|
||||||
const { tunCardStatus = 'col-span-1' } = appConfig || {}
|
const { tunCardStatus = 'col-span-1' } = appConfig || {}
|
||||||
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
|
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
|
||||||
const { tun } = controledMihomoConfig || {}
|
const { tun } = controledMihomoConfig || {}
|
||||||
@ -32,19 +29,6 @@ const TunSwitcher: React.FC = () => {
|
|||||||
})
|
})
|
||||||
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
|
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
|
||||||
const onChange = async (enable: boolean): Promise<void> => {
|
const onChange = async (enable: boolean): Promise<void> => {
|
||||||
if (enable && platform === 'darwin') {
|
|
||||||
const encryptionAvailable = await isEncryptionAvailable()
|
|
||||||
if (!appConfig?.encryptedPassword && encryptionAvailable) {
|
|
||||||
setOpenPasswordModal(true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!appConfig?.encryptedPassword && !encryptionAvailable) {
|
|
||||||
alert('加密不可用,请手动给内核授权')
|
|
||||||
await patchAppConfig({ encryptedPassword: [] })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
await patchControledMihomoConfig({ tun: { enable }, dns: { enable: true } })
|
await patchControledMihomoConfig({ tun: { enable }, dns: { enable: true } })
|
||||||
} else {
|
} else {
|
||||||
@ -65,24 +49,6 @@ const TunSwitcher: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
className={`${tunCardStatus} tun-card`}
|
className={`${tunCardStatus} tun-card`}
|
||||||
>
|
>
|
||||||
{openPasswordModal && (
|
|
||||||
<BasePasswordModal
|
|
||||||
onCancel={() => setOpenPasswordModal(false)}
|
|
||||||
onConfirm={async (password: string) => {
|
|
||||||
try {
|
|
||||||
const encrypted = await encryptString(password)
|
|
||||||
await patchAppConfig({ encryptedPassword: encrypted })
|
|
||||||
await patchControledMihomoConfig({ tun: { enable: true }, dns: { enable: true } })
|
|
||||||
await restartCore()
|
|
||||||
window.electron.ipcRenderer.send('updateTrayMenu')
|
|
||||||
setOpenPasswordModal(false)
|
|
||||||
} catch (e) {
|
|
||||||
alert(e)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
fullWidth
|
fullWidth
|
||||||
ref={setNodeRef}
|
ref={setNodeRef}
|
||||||
|
|||||||
@ -89,7 +89,7 @@ const Mihomo: React.FC = () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
PubSub.publish('mihomo-core-changed')
|
PubSub.publish('mihomo-core-changed')
|
||||||
}, 2000)
|
}, 2000)
|
||||||
if (platform === 'linux') {
|
if (platform !== 'win32') {
|
||||||
new Notification('内核权限丢失', {
|
new Notification('内核权限丢失', {
|
||||||
body: '内核升级成功,若要使用虚拟网卡(Tun),请到虚拟网卡页面重新手动授权内核'
|
body: '内核升级成功,若要使用虚拟网卡(Tun),请到虚拟网卡页面重新手动授权内核'
|
||||||
})
|
})
|
||||||
|
|||||||
@ -199,14 +199,6 @@ export async function triggerSysProxy(enable: boolean): Promise<void> {
|
|||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('triggerSysProxy', enable))
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('triggerSysProxy', enable))
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function isEncryptionAvailable(): Promise<boolean> {
|
|
||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('isEncryptionAvailable'))
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function encryptString(str: string): Promise<number[]> {
|
|
||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('encryptString', str))
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function manualGrantCorePermition(password?: string): Promise<void> {
|
export async function manualGrantCorePermition(password?: string): Promise<void> {
|
||||||
return ipcErrorWrapper(
|
return ipcErrorWrapper(
|
||||||
await window.electron.ipcRenderer.invoke('manualGrantCorePermition', password)
|
await window.electron.ipcRenderer.invoke('manualGrantCorePermition', password)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user