mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-27 05:00:30 +08:00
set proxy for Sub-Store and support control whether allow LAN connections to Sub-Store
This commit is contained in:
parent
ea5397f250
commit
710780456a
@ -1,8 +1,9 @@
|
|||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
- 支持多个订阅切换分别保存选择的节点
|
- Sub-Store 请求默认经过内核代理
|
||||||
- 支持在对话框直接拖动窗口
|
- 允许控制是否允许局域网连接 Sub-Store
|
||||||
|
- 全局模式时自动置顶 GLOBAL 代理组
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
- 修复订阅显示样式错误
|
- 修复下拉菜单组件样式异常
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import express from 'express'
|
|||||||
export let pacPort: number
|
export let pacPort: number
|
||||||
export let subStorePort: number
|
export let subStorePort: number
|
||||||
export let subStoreFrontendPort: number
|
export let subStoreFrontendPort: number
|
||||||
|
let subStoreFrontendServer: http.Server
|
||||||
|
let subStoreBackendWorker: Worker
|
||||||
|
|
||||||
const defaultPacScript = `
|
const defaultPacScript = `
|
||||||
function FindProxyForURL(url, host) {
|
function FindProxyForURL(url, host) {
|
||||||
@ -56,28 +58,42 @@ export async function startPacServer(): Promise<void> {
|
|||||||
server.unref()
|
server.unref()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function startSubStoreServer(): Promise<void> {
|
export async function startSubStoreFrontendServer(): Promise<void> {
|
||||||
|
const { useSubStore = true, subStoreHost = '127.0.0.1' } = await getAppConfig()
|
||||||
|
if (!useSubStore) return
|
||||||
|
await stopSubStoreFrontendServer()
|
||||||
|
subStoreFrontendPort = await findAvailablePort(14122)
|
||||||
|
const app = express()
|
||||||
|
app.use(express.static(path.join(resourcesFilesDir(), 'sub-store-frontend')))
|
||||||
|
subStoreFrontendServer = app.listen(subStoreFrontendPort, subStoreHost)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function stopSubStoreFrontendServer(): Promise<void> {
|
||||||
|
if (subStoreFrontendServer) {
|
||||||
|
subStoreFrontendServer.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function startSubStoreBackendServer(): Promise<void> {
|
||||||
const {
|
const {
|
||||||
useSubStore = true,
|
useSubStore = true,
|
||||||
useCustomSubStore = false,
|
useCustomSubStore = false,
|
||||||
|
subStoreHost = '127.0.0.1',
|
||||||
subStoreBackendSyncCron = '',
|
subStoreBackendSyncCron = '',
|
||||||
subStoreBackendDownloadCron = '',
|
subStoreBackendDownloadCron = '',
|
||||||
subStoreBackendUploadCron = ''
|
subStoreBackendUploadCron = ''
|
||||||
} = await getAppConfig()
|
} = await getAppConfig()
|
||||||
|
const { 'mixed-port': port = 7890 } = await getControledMihomoConfig()
|
||||||
if (!useSubStore) return
|
if (!useSubStore) return
|
||||||
if (!subStoreFrontendPort) {
|
if (!useCustomSubStore) {
|
||||||
subStoreFrontendPort = await findAvailablePort(14122)
|
await stopSubStoreBackendServer()
|
||||||
const app = express()
|
|
||||||
app.use(express.static(path.join(resourcesFilesDir(), 'sub-store-frontend')))
|
|
||||||
app.listen(subStoreFrontendPort)
|
|
||||||
}
|
|
||||||
if (!useCustomSubStore && !subStorePort) {
|
|
||||||
subStorePort = await findAvailablePort(38324)
|
subStorePort = await findAvailablePort(38324)
|
||||||
const icon = nativeImage.createFromPath(subStoreIcon)
|
const icon = nativeImage.createFromPath(subStoreIcon)
|
||||||
icon.toDataURL()
|
icon.toDataURL()
|
||||||
new Worker(path.join(resourcesFilesDir(), 'sub-store.bundle.js'), {
|
subStoreBackendWorker = new Worker(path.join(resourcesFilesDir(), 'sub-store.bundle.js'), {
|
||||||
env: {
|
env: {
|
||||||
SUB_STORE_BACKEND_API_PORT: subStorePort.toString(),
|
SUB_STORE_BACKEND_API_PORT: subStorePort.toString(),
|
||||||
|
SUB_STORE_BACKEND_API_HOST: subStoreHost,
|
||||||
SUB_STORE_DATA_BASE_PATH: subStoreDir(),
|
SUB_STORE_DATA_BASE_PATH: subStoreDir(),
|
||||||
SUB_STORE_BACKEND_CUSTOM_ICON: icon.toDataURL(),
|
SUB_STORE_BACKEND_CUSTOM_ICON: icon.toDataURL(),
|
||||||
SUB_STORE_BACKEND_CUSTOM_NAME: 'Mihomo Party',
|
SUB_STORE_BACKEND_CUSTOM_NAME: 'Mihomo Party',
|
||||||
@ -85,8 +101,17 @@ export async function startSubStoreServer(): Promise<void> {
|
|||||||
SUB_STORE_BACKEND_DOWNLOAD_CRON: subStoreBackendDownloadCron,
|
SUB_STORE_BACKEND_DOWNLOAD_CRON: subStoreBackendDownloadCron,
|
||||||
SUB_STORE_BACKEND_UPLOAD_CRON: subStoreBackendUploadCron,
|
SUB_STORE_BACKEND_UPLOAD_CRON: subStoreBackendUploadCron,
|
||||||
SUB_STORE_MMDB_COUNTRY_PATH: path.join(mihomoWorkDir(), 'country.mmdb'),
|
SUB_STORE_MMDB_COUNTRY_PATH: path.join(mihomoWorkDir(), 'country.mmdb'),
|
||||||
SUB_STORE_MMDB_ASN_PATH: path.join(mihomoWorkDir(), 'ASN.mmdb')
|
SUB_STORE_MMDB_ASN_PATH: path.join(mihomoWorkDir(), 'ASN.mmdb'),
|
||||||
|
HTTP_PROXY: `http://127.0.0.1:${port}`,
|
||||||
|
HTTPS_PROXY: `http://127.0.0.1:${port}`,
|
||||||
|
ALL_PROXY: `http://127.0.0.1:${port}`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function stopSubStoreBackendServer(): Promise<void> {
|
||||||
|
if (subStoreBackendWorker) {
|
||||||
|
subStoreBackendWorker.terminate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -25,7 +25,11 @@ import yaml from 'yaml'
|
|||||||
import { mkdir, writeFile, copyFile, rm, readdir } from 'fs/promises'
|
import { mkdir, writeFile, copyFile, rm, readdir } from 'fs/promises'
|
||||||
import { existsSync } from 'fs'
|
import { existsSync } from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { startPacServer, startSubStoreServer } from '../resolve/server'
|
import {
|
||||||
|
startPacServer,
|
||||||
|
startSubStoreBackendServer,
|
||||||
|
startSubStoreFrontendServer
|
||||||
|
} from '../resolve/server'
|
||||||
import { triggerSysProxy } from '../sys/sysproxy'
|
import { triggerSysProxy } from '../sys/sysproxy'
|
||||||
import {
|
import {
|
||||||
getAppConfig,
|
getAppConfig,
|
||||||
@ -231,7 +235,8 @@ export async function init(): Promise<void> {
|
|||||||
await initFiles()
|
await initFiles()
|
||||||
await cleanup()
|
await cleanup()
|
||||||
await startPacServer()
|
await startPacServer()
|
||||||
await startSubStoreServer()
|
await startSubStoreFrontendServer()
|
||||||
|
await startSubStoreBackendServer()
|
||||||
const { sysProxy } = await getAppConfig()
|
const { sysProxy } = await getAppConfig()
|
||||||
try {
|
try {
|
||||||
await triggerSysProxy(sysProxy.enable)
|
await triggerSysProxy(sysProxy.enable)
|
||||||
|
|||||||
@ -43,7 +43,14 @@ import {
|
|||||||
setOverride,
|
setOverride,
|
||||||
updateOverrideItem
|
updateOverrideItem
|
||||||
} from '../config'
|
} from '../config'
|
||||||
import { startSubStoreServer, subStoreFrontendPort, subStorePort } from '../resolve/server'
|
import {
|
||||||
|
startSubStoreFrontendServer,
|
||||||
|
startSubStoreBackendServer,
|
||||||
|
stopSubStoreFrontendServer,
|
||||||
|
stopSubStoreBackendServer,
|
||||||
|
subStoreFrontendPort,
|
||||||
|
subStorePort
|
||||||
|
} from '../resolve/server'
|
||||||
import {
|
import {
|
||||||
isEncryptionAvailable,
|
isEncryptionAvailable,
|
||||||
manualGrantCorePermition,
|
manualGrantCorePermition,
|
||||||
@ -190,7 +197,13 @@ export function registerIpcMainHandlers(): void {
|
|||||||
ipcMain.handle('registerShortcut', (_e, oldShortcut, newShortcut, action) =>
|
ipcMain.handle('registerShortcut', (_e, oldShortcut, newShortcut, action) =>
|
||||||
ipcErrorWrapper(registerShortcut)(oldShortcut, newShortcut, action)
|
ipcErrorWrapper(registerShortcut)(oldShortcut, newShortcut, action)
|
||||||
)
|
)
|
||||||
ipcMain.handle('startSubStoreServer', () => ipcErrorWrapper(startSubStoreServer)())
|
ipcMain.handle('startSubStoreFrontendServer', () =>
|
||||||
|
ipcErrorWrapper(startSubStoreFrontendServer)()
|
||||||
|
)
|
||||||
|
ipcMain.handle('stopSubStoreFrontendServer', () => ipcErrorWrapper(stopSubStoreFrontendServer)())
|
||||||
|
ipcMain.handle('startSubStoreBackendServer', () => ipcErrorWrapper(startSubStoreBackendServer)())
|
||||||
|
ipcMain.handle('stopSubStoreBackendServer', () => ipcErrorWrapper(stopSubStoreBackendServer)())
|
||||||
|
|
||||||
ipcMain.handle('subStorePort', () => subStorePort)
|
ipcMain.handle('subStorePort', () => subStorePort)
|
||||||
ipcMain.handle('subStoreFrontendPort', () => subStoreFrontendPort)
|
ipcMain.handle('subStoreFrontendPort', () => subStoreFrontendPort)
|
||||||
ipcMain.handle('subStoreSubs', () => ipcErrorWrapper(subStoreSubs)())
|
ipcMain.handle('subStoreSubs', () => ipcErrorWrapper(subStoreSubs)())
|
||||||
|
|||||||
@ -2,7 +2,12 @@ import React, { useState } from 'react'
|
|||||||
import SettingCard from '@renderer/components/base/base-setting-card'
|
import SettingCard from '@renderer/components/base/base-setting-card'
|
||||||
import SettingItem from '@renderer/components/base/base-setting-item'
|
import SettingItem from '@renderer/components/base/base-setting-item'
|
||||||
import { Button, Input, Switch } from '@nextui-org/react'
|
import { Button, Input, Switch } from '@nextui-org/react'
|
||||||
import { startSubStoreServer } from '@renderer/utils/ipc'
|
import {
|
||||||
|
startSubStoreFrontendServer,
|
||||||
|
startSubStoreBackendServer,
|
||||||
|
stopSubStoreFrontendServer,
|
||||||
|
stopSubStoreBackendServer
|
||||||
|
} from '@renderer/utils/ipc'
|
||||||
import { useAppConfig } from '@renderer/hooks/use-app-config'
|
import { useAppConfig } from '@renderer/hooks/use-app-config'
|
||||||
import debounce from '@renderer/utils/debounce'
|
import debounce from '@renderer/utils/debounce'
|
||||||
import { isValidCron } from 'cron-validator'
|
import { isValidCron } from 'cron-validator'
|
||||||
@ -12,6 +17,7 @@ const SubStoreConfig: React.FC = () => {
|
|||||||
const {
|
const {
|
||||||
useSubStore = true,
|
useSubStore = true,
|
||||||
useCustomSubStore = false,
|
useCustomSubStore = false,
|
||||||
|
subStoreHost = '127.0.0.1',
|
||||||
customSubStoreUrl,
|
customSubStoreUrl,
|
||||||
subStoreBackendSyncCron,
|
subStoreBackendSyncCron,
|
||||||
subStoreBackendDownloadCron,
|
subStoreBackendDownloadCron,
|
||||||
@ -31,14 +37,20 @@ const SubStoreConfig: React.FC = () => {
|
|||||||
useState(subStoreBackendUploadCron)
|
useState(subStoreBackendUploadCron)
|
||||||
return (
|
return (
|
||||||
<SettingCard title="Sub-Store 设置">
|
<SettingCard title="Sub-Store 设置">
|
||||||
<SettingItem title="启用 Sub-Store" divider>
|
<SettingItem title="启用 Sub-Store" divider={useSubStore}>
|
||||||
<Switch
|
<Switch
|
||||||
size="sm"
|
size="sm"
|
||||||
isSelected={useSubStore}
|
isSelected={useSubStore}
|
||||||
onValueChange={async (v) => {
|
onValueChange={async (v) => {
|
||||||
try {
|
try {
|
||||||
await patchAppConfig({ useSubStore: v })
|
await patchAppConfig({ useSubStore: v })
|
||||||
if (v) await startSubStoreServer()
|
if (v) {
|
||||||
|
await startSubStoreFrontendServer()
|
||||||
|
await startSubStoreBackendServer()
|
||||||
|
} else {
|
||||||
|
await stopSubStoreFrontendServer()
|
||||||
|
await stopSubStoreBackendServer()
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert(e)
|
alert(e)
|
||||||
}
|
}
|
||||||
@ -46,138 +58,163 @@ const SubStoreConfig: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
{useSubStore && (
|
{useSubStore && (
|
||||||
<SettingItem title="使用自建 Sub-Store 后端" divider>
|
|
||||||
<Switch
|
|
||||||
size="sm"
|
|
||||||
isSelected={useCustomSubStore}
|
|
||||||
onValueChange={async (v) => {
|
|
||||||
try {
|
|
||||||
await patchAppConfig({ useCustomSubStore: v })
|
|
||||||
if (!v) await startSubStoreServer()
|
|
||||||
} catch (e) {
|
|
||||||
alert(e)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SettingItem>
|
|
||||||
)}
|
|
||||||
{useCustomSubStore ? (
|
|
||||||
<SettingItem title="自建 Sub-Store 后端地址">
|
|
||||||
<Input
|
|
||||||
size="sm"
|
|
||||||
className="w-[60%]"
|
|
||||||
value={customSubStoreUrlValue}
|
|
||||||
placeholder="必须包含协议头"
|
|
||||||
onValueChange={(v: string) => {
|
|
||||||
setCustomSubStoreUrlValue(v)
|
|
||||||
setCustomSubStoreUrl(v)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SettingItem>
|
|
||||||
) : (
|
|
||||||
<>
|
<>
|
||||||
<SettingItem title="定时同步订阅/文件" divider>
|
<SettingItem title="允许局域网连接" divider>
|
||||||
<div className="flex w-[60%] gap-2">
|
<Switch
|
||||||
{subStoreBackendSyncCronValue !== subStoreBackendSyncCron && (
|
size="sm"
|
||||||
<Button
|
isSelected={subStoreHost === '0.0.0.0'}
|
||||||
size="sm"
|
onValueChange={async (v) => {
|
||||||
color="primary"
|
try {
|
||||||
onPress={async () => {
|
if (v) {
|
||||||
if (
|
await patchAppConfig({ subStoreHost: '0.0.0.0' })
|
||||||
!subStoreBackendSyncCronValue ||
|
} else {
|
||||||
isValidCron(subStoreBackendSyncCronValue)
|
await patchAppConfig({ subStoreHost: '127.0.0.1' })
|
||||||
) {
|
}
|
||||||
await patchAppConfig({
|
await startSubStoreFrontendServer()
|
||||||
subStoreBackendSyncCron: subStoreBackendSyncCronValue
|
await startSubStoreBackendServer()
|
||||||
})
|
} catch (e) {
|
||||||
new Notification('重启应用生效')
|
alert(e)
|
||||||
} else {
|
}
|
||||||
alert('Cron 表达式无效')
|
}}
|
||||||
}
|
/>
|
||||||
}}
|
</SettingItem>
|
||||||
>
|
<SettingItem title="使用自建 Sub-Store 后端" divider>
|
||||||
确认
|
<Switch
|
||||||
</Button>
|
size="sm"
|
||||||
)}
|
isSelected={useCustomSubStore}
|
||||||
|
onValueChange={async (v) => {
|
||||||
|
try {
|
||||||
|
await patchAppConfig({ useCustomSubStore: v })
|
||||||
|
if (v) {
|
||||||
|
await stopSubStoreBackendServer()
|
||||||
|
} else {
|
||||||
|
await startSubStoreBackendServer()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
alert(e)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SettingItem>
|
||||||
|
{useCustomSubStore ? (
|
||||||
|
<SettingItem title="自建 Sub-Store 后端地址">
|
||||||
<Input
|
<Input
|
||||||
size="sm"
|
size="sm"
|
||||||
className="flex-grown"
|
className="w-[60%]"
|
||||||
value={subStoreBackendSyncCronValue}
|
value={customSubStoreUrlValue}
|
||||||
placeholder="Cron 表达式"
|
placeholder="必须包含协议头"
|
||||||
onValueChange={(v: string) => {
|
onValueChange={(v: string) => {
|
||||||
setSubStoreBackendSyncCronValue(v)
|
setCustomSubStoreUrlValue(v)
|
||||||
|
setCustomSubStoreUrl(v)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</SettingItem>
|
||||||
</SettingItem>
|
) : (
|
||||||
<SettingItem title="定时恢复配置" divider>
|
<>
|
||||||
<div className="flex w-[60%] gap-2">
|
<SettingItem title="定时同步订阅/文件" divider>
|
||||||
{subStoreBackendDownloadCronValue !== subStoreBackendDownloadCron && (
|
<div className="flex w-[60%] gap-2">
|
||||||
<Button
|
{subStoreBackendSyncCronValue !== subStoreBackendSyncCron && (
|
||||||
size="sm"
|
<Button
|
||||||
color="primary"
|
size="sm"
|
||||||
onPress={async () => {
|
color="primary"
|
||||||
if (
|
onPress={async () => {
|
||||||
!subStoreBackendDownloadCronValue ||
|
if (
|
||||||
isValidCron(subStoreBackendDownloadCronValue)
|
!subStoreBackendSyncCronValue ||
|
||||||
) {
|
isValidCron(subStoreBackendSyncCronValue)
|
||||||
await patchAppConfig({
|
) {
|
||||||
subStoreBackendDownloadCron: subStoreBackendDownloadCronValue
|
await patchAppConfig({
|
||||||
})
|
subStoreBackendSyncCron: subStoreBackendSyncCronValue
|
||||||
new Notification('重启应用生效')
|
})
|
||||||
} else {
|
new Notification('重启应用生效')
|
||||||
alert('Cron 表达式无效')
|
} else {
|
||||||
}
|
alert('Cron 表达式无效')
|
||||||
}}
|
}
|
||||||
>
|
}}
|
||||||
确认
|
>
|
||||||
</Button>
|
确认
|
||||||
)}
|
</Button>
|
||||||
<Input
|
)}
|
||||||
size="sm"
|
<Input
|
||||||
className="flex-grown"
|
size="sm"
|
||||||
value={subStoreBackendDownloadCronValue}
|
className="flex-grown"
|
||||||
placeholder="Cron 表达式"
|
value={subStoreBackendSyncCronValue}
|
||||||
onValueChange={(v: string) => {
|
placeholder="Cron 表达式"
|
||||||
setSubStoreBackendDownloadCronValue(v)
|
onValueChange={(v: string) => {
|
||||||
}}
|
setSubStoreBackendSyncCronValue(v)
|
||||||
/>
|
}}
|
||||||
</div>
|
/>
|
||||||
</SettingItem>
|
</div>
|
||||||
<SettingItem title="定时备份配置">
|
</SettingItem>
|
||||||
<div className="flex w-[60%] gap-2">
|
<SettingItem title="定时恢复配置" divider>
|
||||||
{subStoreBackendUploadCronValue !== subStoreBackendUploadCron && (
|
<div className="flex w-[60%] gap-2">
|
||||||
<Button
|
{subStoreBackendDownloadCronValue !== subStoreBackendDownloadCron && (
|
||||||
size="sm"
|
<Button
|
||||||
color="primary"
|
size="sm"
|
||||||
onPress={async () => {
|
color="primary"
|
||||||
if (
|
onPress={async () => {
|
||||||
!subStoreBackendUploadCronValue ||
|
if (
|
||||||
isValidCron(subStoreBackendUploadCronValue)
|
!subStoreBackendDownloadCronValue ||
|
||||||
) {
|
isValidCron(subStoreBackendDownloadCronValue)
|
||||||
await patchAppConfig({
|
) {
|
||||||
subStoreBackendUploadCron: subStoreBackendUploadCronValue
|
await patchAppConfig({
|
||||||
})
|
subStoreBackendDownloadCron: subStoreBackendDownloadCronValue
|
||||||
new Notification('重启应用生效')
|
})
|
||||||
} else {
|
new Notification('重启应用生效')
|
||||||
alert('Cron 表达式无效')
|
} else {
|
||||||
}
|
alert('Cron 表达式无效')
|
||||||
}}
|
}
|
||||||
>
|
}}
|
||||||
确认
|
>
|
||||||
</Button>
|
确认
|
||||||
)}
|
</Button>
|
||||||
<Input
|
)}
|
||||||
size="sm"
|
<Input
|
||||||
className="flex-grown"
|
size="sm"
|
||||||
value={subStoreBackendUploadCronValue}
|
className="flex-grown"
|
||||||
placeholder="Cron 表达式"
|
value={subStoreBackendDownloadCronValue}
|
||||||
onValueChange={(v: string) => {
|
placeholder="Cron 表达式"
|
||||||
setSubStoreBackendUploadCronValue(v)
|
onValueChange={(v: string) => {
|
||||||
}}
|
setSubStoreBackendDownloadCronValue(v)
|
||||||
/>
|
}}
|
||||||
</div>
|
/>
|
||||||
</SettingItem>
|
</div>
|
||||||
|
</SettingItem>
|
||||||
|
<SettingItem title="定时备份配置">
|
||||||
|
<div className="flex w-[60%] gap-2">
|
||||||
|
{subStoreBackendUploadCronValue !== subStoreBackendUploadCron && (
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
color="primary"
|
||||||
|
onPress={async () => {
|
||||||
|
if (
|
||||||
|
!subStoreBackendUploadCronValue ||
|
||||||
|
isValidCron(subStoreBackendUploadCronValue)
|
||||||
|
) {
|
||||||
|
await patchAppConfig({
|
||||||
|
subStoreBackendUploadCron: subStoreBackendUploadCronValue
|
||||||
|
})
|
||||||
|
new Notification('重启应用生效')
|
||||||
|
} else {
|
||||||
|
alert('Cron 表达式无效')
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Input
|
||||||
|
size="sm"
|
||||||
|
className="flex-grown"
|
||||||
|
value={subStoreBackendUploadCronValue}
|
||||||
|
placeholder="Cron 表达式"
|
||||||
|
onValueChange={(v: string) => {
|
||||||
|
setSubStoreBackendUploadCronValue(v)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</SettingItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</SettingCard>
|
</SettingCard>
|
||||||
|
|||||||
@ -8,7 +8,12 @@ import { platform } from '@renderer/utils/init'
|
|||||||
import { FaNetworkWired } from 'react-icons/fa'
|
import { FaNetworkWired } from 'react-icons/fa'
|
||||||
import { IoMdCloudDownload } from 'react-icons/io'
|
import { IoMdCloudDownload } from 'react-icons/io'
|
||||||
import PubSub from 'pubsub-js'
|
import PubSub from 'pubsub-js'
|
||||||
import { mihomoUpgrade, restartCore, triggerSysProxy } from '@renderer/utils/ipc'
|
import {
|
||||||
|
mihomoUpgrade,
|
||||||
|
restartCore,
|
||||||
|
startSubStoreBackendServer,
|
||||||
|
triggerSysProxy
|
||||||
|
} from '@renderer/utils/ipc'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import InterfaceModal from '@renderer/components/mihomo/interface-modal'
|
import InterfaceModal from '@renderer/components/mihomo/interface-modal'
|
||||||
import { MdDeleteForever } from 'react-icons/md'
|
import { MdDeleteForever } from 'react-icons/md'
|
||||||
@ -129,6 +134,7 @@ const Mihomo: React.FC = () => {
|
|||||||
className="mr-2"
|
className="mr-2"
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
await onChangeNeedRestart({ 'mixed-port': mixedPortInput })
|
await onChangeNeedRestart({ 'mixed-port': mixedPortInput })
|
||||||
|
await startSubStoreBackendServer()
|
||||||
if (sysProxy?.enable) {
|
if (sysProxy?.enable) {
|
||||||
triggerSysProxy(true)
|
triggerSysProxy(true)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -307,8 +307,20 @@ export async function getGistUrl(): Promise<string> {
|
|||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('getGistUrl'))
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('getGistUrl'))
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function startSubStoreServer(): Promise<void> {
|
export async function startSubStoreFrontendServer(): Promise<void> {
|
||||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('startSubStoreServer'))
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('startSubStoreFrontendServer'))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function stopSubStoreFrontendServer(): Promise<void> {
|
||||||
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('stopSubStoreFrontendServer'))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function startSubStoreBackendServer(): Promise<void> {
|
||||||
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('startSubStoreBackendServer'))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function stopSubStoreBackendServer(): Promise<void> {
|
||||||
|
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('stopSubStoreBackendServer'))
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function subStorePort(): Promise<number> {
|
export async function subStorePort(): Promise<number> {
|
||||||
|
|||||||
1
src/shared/types.d.ts
vendored
1
src/shared/types.d.ts
vendored
@ -231,6 +231,7 @@ interface IAppConfig {
|
|||||||
tunCardStatus?: CardStatus
|
tunCardStatus?: CardStatus
|
||||||
githubToken?: string
|
githubToken?: string
|
||||||
useSubStore: boolean
|
useSubStore: boolean
|
||||||
|
subStoreHost?: string
|
||||||
subStoreBackendSyncCron?: string
|
subStoreBackendSyncCron?: string
|
||||||
subStoreBackendDownloadCron?: string
|
subStoreBackendDownloadCron?: string
|
||||||
subStoreBackendUploadCron?: string
|
subStoreBackendUploadCron?: string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user