mirror of
https://github.com/pompurin404/mihomo-party.git
synced 2024-11-16 03:32:17 +08:00
setup config
This commit is contained in:
parent
35a9dcca4f
commit
4c851ef97a
|
@ -119,6 +119,10 @@ export function disableAutoRun(): void {
|
||||||
}
|
}
|
||||||
if (process.platform === 'linux') {
|
if (process.platform === 'linux') {
|
||||||
const desktopFilePath = `${app.getPath('home')}/.config/autostart/${appName}.desktop`
|
const desktopFilePath = `${app.getPath('home')}/.config/autostart/${appName}.desktop`
|
||||||
|
try {
|
||||||
fs.rmSync(desktopFilePath)
|
fs.rmSync(desktopFilePath)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,24 @@
|
||||||
import { ipcMain } from 'electron'
|
import { ipcMain } from 'electron'
|
||||||
import { mihomoVersion } from './mihomo-api'
|
import { mihomoVersion } from './mihomo-api'
|
||||||
import { checkAutoRun, disableAutoRun, enableAutoRun } from './autoRun'
|
import { checkAutoRun, disableAutoRun, enableAutoRun } from './autoRun'
|
||||||
|
import {
|
||||||
|
getAppConfig,
|
||||||
|
setAppConfig,
|
||||||
|
getControledMihomoConfig,
|
||||||
|
setControledMihomoConfig
|
||||||
|
} from './config'
|
||||||
|
|
||||||
export function registerIpcMainHandlers(): void {
|
export function registerIpcMainHandlers(): void {
|
||||||
ipcMain.handle('mihomoVersion', mihomoVersion)
|
ipcMain.handle('mihomoVersion', mihomoVersion)
|
||||||
ipcMain.handle('checkAutoRun', checkAutoRun)
|
ipcMain.handle('checkAutoRun', checkAutoRun)
|
||||||
ipcMain.handle('enableAutoRun', enableAutoRun)
|
ipcMain.handle('enableAutoRun', enableAutoRun)
|
||||||
ipcMain.handle('disableAutoRun', disableAutoRun)
|
ipcMain.handle('disableAutoRun', disableAutoRun)
|
||||||
|
ipcMain.handle('getAppConfig', (_e, force) => getAppConfig(force))
|
||||||
|
ipcMain.handle('setAppConfig', (_e, config) => {
|
||||||
|
setAppConfig(config)
|
||||||
|
})
|
||||||
|
ipcMain.handle('getControledMihomoConfig', (_e, force) => getControledMihomoConfig(force))
|
||||||
|
ipcMain.handle('setControledMihomoConfig', (_e, config) => {
|
||||||
|
setControledMihomoConfig(config)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
50
src/main/config.ts
Normal file
50
src/main/config.ts
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import yaml from 'yaml'
|
||||||
|
import fs from 'fs'
|
||||||
|
import { app } from 'electron'
|
||||||
|
import path from 'path'
|
||||||
|
import { defaultConfig } from './template'
|
||||||
|
|
||||||
|
const dataDir = app.getPath('userData')
|
||||||
|
const appConfigPath = path.join(dataDir, 'config.yaml')
|
||||||
|
const controledMihomoConfigPath = path.join(dataDir, 'mihomo.yaml')
|
||||||
|
|
||||||
|
export let appConfig: IAppConfig
|
||||||
|
export let controledMihomoConfig: Partial<IMihomoConfig>
|
||||||
|
|
||||||
|
export function initConfig(): void {
|
||||||
|
if (!fs.existsSync(dataDir)) {
|
||||||
|
fs.mkdirSync(dataDir)
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(appConfigPath)) {
|
||||||
|
fs.writeFileSync(appConfigPath, yaml.stringify(defaultConfig))
|
||||||
|
}
|
||||||
|
if (!fs.existsSync(controledMihomoConfigPath)) {
|
||||||
|
fs.writeFileSync(controledMihomoConfigPath, yaml.stringify({}))
|
||||||
|
}
|
||||||
|
getAppConfig(true)
|
||||||
|
getControledMihomoConfig(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAppConfig(force = false): IAppConfig {
|
||||||
|
if (force || !appConfig) {
|
||||||
|
appConfig = yaml.parse(fs.readFileSync(appConfigPath, 'utf-8'))
|
||||||
|
}
|
||||||
|
return appConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setAppConfig(patch: Partial<IAppConfig>): void {
|
||||||
|
appConfig = Object.assign(appConfig, patch)
|
||||||
|
fs.writeFileSync(appConfigPath, yaml.stringify(appConfig))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getControledMihomoConfig(force = false): Partial<IMihomoConfig> {
|
||||||
|
if (force || !controledMihomoConfig) {
|
||||||
|
controledMihomoConfig = yaml.parse(fs.readFileSync(controledMihomoConfigPath, 'utf-8'))
|
||||||
|
}
|
||||||
|
return controledMihomoConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setControledMihomoConfig(patch: Partial<IMihomoConfig>): void {
|
||||||
|
controledMihomoConfig = Object.assign(controledMihomoConfig, patch)
|
||||||
|
fs.writeFileSync(controledMihomoConfigPath, yaml.stringify(controledMihomoConfig))
|
||||||
|
}
|
|
@ -4,11 +4,14 @@ import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
||||||
import pngIcon from '../../resources/icon.png?asset'
|
import pngIcon from '../../resources/icon.png?asset'
|
||||||
import icoIcon from '../../resources/icon.ico?asset'
|
import icoIcon from '../../resources/icon.ico?asset'
|
||||||
import { registerIpcMainHandlers } from './cmds'
|
import { registerIpcMainHandlers } from './cmds'
|
||||||
|
import { initConfig, appConfig } from './config'
|
||||||
|
|
||||||
let window: BrowserWindow | null = null
|
let window: BrowserWindow | null = null
|
||||||
let tray: Tray | null = null
|
let tray: Tray | null = null
|
||||||
let trayContextMenu: Menu | null = null
|
let trayContextMenu: Menu | null = null
|
||||||
|
|
||||||
|
initConfig()
|
||||||
|
|
||||||
function createWindow(): void {
|
function createWindow(): void {
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
window = new BrowserWindow({
|
window = new BrowserWindow({
|
||||||
|
@ -26,8 +29,10 @@ function createWindow(): void {
|
||||||
})
|
})
|
||||||
|
|
||||||
window.on('ready-to-show', () => {
|
window.on('ready-to-show', () => {
|
||||||
|
if (!appConfig.silentStart) {
|
||||||
window?.show()
|
window?.show()
|
||||||
window?.focusOnWebView()
|
window?.focusOnWebView()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
window.on('close', (event) => {
|
window.on('close', (event) => {
|
||||||
|
|
3
src/main/template.ts
Normal file
3
src/main/template.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const defaultConfig: IAppConfig = {
|
||||||
|
silentStart: false
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import { useLocation, useNavigate, useRoutes } from 'react-router-dom'
|
||||||
import OutboundModeSwitcher from '@renderer/components/sider/outbound-mode-switcher'
|
import OutboundModeSwitcher from '@renderer/components/sider/outbound-mode-switcher'
|
||||||
import SysproxySwitcher from '@renderer/components/sider/sysproxy-switcher'
|
import SysproxySwitcher from '@renderer/components/sider/sysproxy-switcher'
|
||||||
import TunSwitcher from '@renderer/components/sider/tun-switcher'
|
import TunSwitcher from '@renderer/components/sider/tun-switcher'
|
||||||
import { Button } from '@nextui-org/react'
|
import { Button, Divider } from '@nextui-org/react'
|
||||||
import { IoSettings } from 'react-icons/io5'
|
import { IoSettings } from 'react-icons/io5'
|
||||||
import routes from '@renderer/routes'
|
import routes from '@renderer/routes'
|
||||||
import ProfileCard from '@renderer/components/sider/profile-card'
|
import ProfileCard from '@renderer/components/sider/profile-card'
|
||||||
|
@ -14,7 +14,7 @@ import OverrideCard from '@renderer/components/sider/override-card'
|
||||||
import ConnCard from '@renderer/components/sider/conn-card'
|
import ConnCard from '@renderer/components/sider/conn-card'
|
||||||
import LogCard from '@renderer/components/sider/log-card'
|
import LogCard from '@renderer/components/sider/log-card'
|
||||||
|
|
||||||
function App(): JSX.Element {
|
const App: React.FC = () => {
|
||||||
const { setTheme } = useTheme()
|
const { setTheme } = useTheme()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
@ -41,7 +41,7 @@ function App(): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-[100vh] flex">
|
<div className="w-full h-[100vh] flex">
|
||||||
<div className="side w-[250px] h-full border-r border-default-200">
|
<div className="side w-[250px] h-full">
|
||||||
<div className="flex justify-between h-[32px] m-2">
|
<div className="flex justify-between h-[32px] m-2">
|
||||||
<h3 className="select-none text-lg font-bold leading-[32px]">出站模式</h3>
|
<h3 className="select-none text-lg font-bold leading-[32px]">出站模式</h3>
|
||||||
<Button
|
<Button
|
||||||
|
@ -81,7 +81,8 @@ function App(): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="main w-[calc(100%-250px)] h-full overflow-y-auto">{page}</div>
|
<Divider orientation="vertical" />
|
||||||
|
<div className="main w-[calc(100%-251px)] h-full overflow-y-auto">{page}</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,31 @@
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer utilities {
|
*::-webkit-scrollbar {
|
||||||
/* Hide scrollbar for Chrome, Safari and Opera */
|
width: 8px;
|
||||||
.no-scrollbar::-webkit-scrollbar {
|
height: 6px;
|
||||||
display: none;
|
}
|
||||||
|
|
||||||
|
/* Light mode */
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
*::-webkit-scrollbar-thumb {
|
||||||
|
background: #c0c1c58f;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #c0c1c550;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode */
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
*::-webkit-scrollbar-thumb {
|
||||||
|
background: #c0c1c550;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #c0c1c58f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
src/renderer/src/components/base/base-page.tsx
Normal file
25
src/renderer/src/components/base/base-page.tsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Divider } from '@nextui-org/divider'
|
||||||
|
interface Props {
|
||||||
|
title?: React.ReactNode
|
||||||
|
header?: React.ReactNode
|
||||||
|
children?: React.ReactNode
|
||||||
|
contentClassName?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const BasePage: React.FC<Props> = (props) => {
|
||||||
|
return (
|
||||||
|
<div className="w-full h-full overflow-y-auto custom-scrollbar">
|
||||||
|
<div className="sticky top-0 z-40 h-[48px] w-full backdrop-blur">
|
||||||
|
<div className="p-2 flex justify-between">
|
||||||
|
<div className="select-none title h-full text-lg leading-[32px]">{props.title}</div>
|
||||||
|
<div className="header h-full">{props.header}</div>
|
||||||
|
</div>
|
||||||
|
<Divider />
|
||||||
|
</div>
|
||||||
|
<div className="content">{props.children}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BasePage
|
16
src/renderer/src/components/settings/setting-card.tsx
Normal file
16
src/renderer/src/components/settings/setting-card.tsx
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Card, CardBody } from '@nextui-org/react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children?: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const SettingCard: React.FC<Props> = (props) => {
|
||||||
|
return (
|
||||||
|
<Card className="m-2">
|
||||||
|
<CardBody>{props.children}</CardBody>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SettingCard
|
28
src/renderer/src/components/settings/setting-item.tsx
Normal file
28
src/renderer/src/components/settings/setting-item.tsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { Divider } from '@nextui-org/react'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
title: React.ReactNode
|
||||||
|
actions?: React.ReactNode
|
||||||
|
children?: React.ReactNode
|
||||||
|
divider?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const SettingItem: React.FC<Props> = (props) => {
|
||||||
|
const { divider = false } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="h-[32px] w-full flex justify-between">
|
||||||
|
<div className="h-full flex items-center">
|
||||||
|
<h4 className="h-full select-none text-md leading-[32px]">{props.title}</h4>
|
||||||
|
<div>{props.actions}</div>
|
||||||
|
</div>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
{divider && <Divider className="my-2" />}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SettingItem
|
|
@ -2,7 +2,7 @@ import { Button, Card, CardBody, CardFooter, Chip } from '@nextui-org/react'
|
||||||
import { IoLink } from 'react-icons/io5'
|
import { IoLink } from 'react-icons/io5'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
export default function ConnCard(): JSX.Element {
|
const ConnCard: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
|
||||||
|
@ -33,3 +33,5 @@ export default function ConnCard(): JSX.Element {
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default ConnCard
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
|
||||||
import { IoJournal } from 'react-icons/io5'
|
import { IoJournal } from 'react-icons/io5'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
export default function LogCard(): JSX.Element {
|
const LogCard: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
|
||||||
|
@ -30,3 +30,5 @@ export default function LogCard(): JSX.Element {
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default LogCard
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
import { Tabs, Tab } from '@nextui-org/react'
|
import { Tabs, Tab } from '@nextui-org/react'
|
||||||
import { Key, useState } from 'react'
|
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
|
||||||
|
import { Key } from 'react'
|
||||||
|
|
||||||
|
const OutboundModeSwitcher: React.FC = () => {
|
||||||
|
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
|
||||||
|
const { mode } = controledMihomoConfig || {}
|
||||||
|
|
||||||
export default function OutboundModeSwitcher(): JSX.Element {
|
|
||||||
const [mode, setMode] = useState<OutboundMode>('rule')
|
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
fullWidth
|
fullWidth
|
||||||
color="primary"
|
color="primary"
|
||||||
selectedKey={mode}
|
selectedKey={mode}
|
||||||
onSelectionChange={(key: Key) => setMode(key as OutboundMode)}
|
onSelectionChange={(key: Key) => patchControledMihomoConfig({ mode: key as OutboundMode })}
|
||||||
>
|
>
|
||||||
<Tab
|
<Tab
|
||||||
className={`select-none ${mode === 'rule' ? 'font-bold' : ''}`}
|
className={`select-none ${mode === 'rule' ? 'font-bold' : ''}`}
|
||||||
|
@ -28,3 +31,5 @@ export default function OutboundModeSwitcher(): JSX.Element {
|
||||||
</Tabs>
|
</Tabs>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default OutboundModeSwitcher
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Button, Card, CardBody, CardFooter, Switch } from '@nextui-org/react'
|
||||||
import { MdFormatOverline } from 'react-icons/md'
|
import { MdFormatOverline } from 'react-icons/md'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
export default function OverrideCard(): JSX.Element {
|
const OverrideCard: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
|
||||||
|
@ -31,3 +31,5 @@ export default function OverrideCard(): JSX.Element {
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default OverrideCard
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Button, Card, CardBody, CardFooter, Slider } from '@nextui-org/react'
|
||||||
import { IoMdRefresh } from 'react-icons/io'
|
import { IoMdRefresh } from 'react-icons/io'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
export default function ProfileCard(): JSX.Element {
|
const ProfileCard: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
|
||||||
|
@ -27,3 +27,5 @@ export default function ProfileCard(): JSX.Element {
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default ProfileCard
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
|
||||||
import { SiSpeedtest } from 'react-icons/si'
|
import { SiSpeedtest } from 'react-icons/si'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
export default function ProxyCard(): JSX.Element {
|
const ProxyCard: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
|
||||||
|
@ -27,3 +27,5 @@ export default function ProxyCard(): JSX.Element {
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default ProxyCard
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Button, Card, CardBody, CardFooter, Chip } from '@nextui-org/react'
|
||||||
import { IoGitNetwork } from 'react-icons/io5'
|
import { IoGitNetwork } from 'react-icons/io5'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
export default function RuleCard(): JSX.Element {
|
const RuleCard: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
|
||||||
|
@ -33,3 +33,5 @@ export default function RuleCard(): JSX.Element {
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default RuleCard
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Button, Card, CardBody, CardFooter, Switch } from '@nextui-org/react'
|
import { Button, Card, CardBody, CardFooter, Switch } from '@nextui-org/react'
|
||||||
import { IoSettings } from 'react-icons/io5'
|
import { IoSettings } from 'react-icons/io5'
|
||||||
|
|
||||||
export default function SysproxySwitcher(): JSX.Element {
|
const SysproxySwitcher: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<Card className="w-[50%] mr-1">
|
<Card className="w-[50%] mr-1">
|
||||||
<CardBody className="pb-1 pt-0 px-0">
|
<CardBody className="pb-1 pt-0 px-0">
|
||||||
|
@ -18,3 +18,5 @@ export default function SysproxySwitcher(): JSX.Element {
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default SysproxySwitcher
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Button, Card, CardBody, CardFooter, Switch } from '@nextui-org/react'
|
import { Button, Card, CardBody, CardFooter, Switch } from '@nextui-org/react'
|
||||||
import { IoSettings } from 'react-icons/io5'
|
import { IoSettings } from 'react-icons/io5'
|
||||||
|
|
||||||
export default function SysproxySwitcher(): JSX.Element {
|
const TunSwitcher: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<Card className="w-[50%] ml-1">
|
<Card className="w-[50%] ml-1">
|
||||||
<CardBody className="pb-1 pt-0 px-0">
|
<CardBody className="pb-1 pt-0 px-0">
|
||||||
|
@ -18,3 +18,5 @@ export default function SysproxySwitcher(): JSX.Element {
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default TunSwitcher
|
||||||
|
|
23
src/renderer/src/hooks/use-config.tsx
Normal file
23
src/renderer/src/hooks/use-config.tsx
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import useSWR from 'swr'
|
||||||
|
import { getAppConfig, setAppConfig } from '@renderer/utils/ipc'
|
||||||
|
|
||||||
|
interface RetuenType {
|
||||||
|
appConfig: IAppConfig | undefined
|
||||||
|
mutateAppConfig: () => void
|
||||||
|
patchAppConfig: (value: Partial<IAppConfig>) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useAppConfig = (): RetuenType => {
|
||||||
|
const { data: appConfig, mutate: mutateAppConfig } = useSWR('getConfig', () => getAppConfig())
|
||||||
|
|
||||||
|
const patchAppConfig = async (value: Partial<IAppConfig>): Promise<void> => {
|
||||||
|
await setAppConfig(value)
|
||||||
|
await mutateAppConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
appConfig,
|
||||||
|
mutateAppConfig,
|
||||||
|
patchAppConfig
|
||||||
|
}
|
||||||
|
}
|
26
src/renderer/src/hooks/use-controled-mihomo-config.tsx
Normal file
26
src/renderer/src/hooks/use-controled-mihomo-config.tsx
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import useSWR from 'swr'
|
||||||
|
import { getControledMihomoConfig, setControledMihomoConfig } from '@renderer/utils/ipc'
|
||||||
|
|
||||||
|
interface RetuenType {
|
||||||
|
controledMihomoConfig: Partial<IMihomoConfig> | undefined
|
||||||
|
mutateControledMihomoConfig: () => void
|
||||||
|
patchControledMihomoConfig: (value: Partial<IMihomoConfig>) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useControledMihomoConfig = (): RetuenType => {
|
||||||
|
const { data: controledMihomoConfig, mutate: mutateControledMihomoConfig } = useSWR(
|
||||||
|
'getControledMihomoConfig',
|
||||||
|
() => getControledMihomoConfig()
|
||||||
|
)
|
||||||
|
|
||||||
|
const patchControledMihomoConfig = async (value: Partial<IMihomoConfig>): Promise<void> => {
|
||||||
|
await setControledMihomoConfig(value)
|
||||||
|
await mutateControledMihomoConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
controledMihomoConfig,
|
||||||
|
mutateControledMihomoConfig,
|
||||||
|
patchControledMihomoConfig
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
export default function Connections(): JSX.Element {
|
const Connections: React.FC = () => {
|
||||||
return <div>Connections</div>
|
return <div>Connections</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Connections
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
export default function Logs(): JSX.Element {
|
const Logs: React.FC = () => {
|
||||||
return <div>Logs</div>
|
return <div>Logs</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Logs
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
export default function Override(): JSX.Element {
|
const Override: React.FC = () => {
|
||||||
return <div>Override</div>
|
return <div>Override</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Override
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
export default function Profiles(): JSX.Element {
|
const Profiles: React.FC = () => {
|
||||||
return <div>Profiles</div>
|
return <div>Profiles</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Profiles
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
export default function Proxies(): JSX.Element {
|
const Proxies: React.FC = () => {
|
||||||
return <div>Proxies</div>
|
return <div>Proxies</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Proxies
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
export default function Rules(): JSX.Element {
|
const Rules: React.FC = () => {
|
||||||
return <div>Rules</div>
|
return <div>Rules</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Rules
|
||||||
|
|
|
@ -1,35 +1,65 @@
|
||||||
import { Button } from '@nextui-org/react'
|
import { Button, Switch } from '@nextui-org/react'
|
||||||
import { checkAutoRun, enableAutoRun, disableAutoRun } from '@renderer/utils/api'
|
import BasePage from '@renderer/components/base/base-page'
|
||||||
|
import SettingCard from '@renderer/components/settings/setting-card'
|
||||||
|
import SettingItem from '@renderer/components/settings/setting-item'
|
||||||
|
import { useAppConfig } from '@renderer/hooks/use-config'
|
||||||
|
import { checkAutoRun, enableAutoRun, disableAutoRun } from '@renderer/utils/ipc'
|
||||||
|
import { IoLogoGithub } from 'react-icons/io5'
|
||||||
|
|
||||||
import useSWR from 'swr'
|
import useSWR from 'swr'
|
||||||
|
|
||||||
export default function Settings(): JSX.Element {
|
const Settings: React.FC = () => {
|
||||||
const { data, error, isLoading, mutate } = useSWR('checkAutoRun', checkAutoRun, {
|
const { data: enable, mutate } = useSWR('checkAutoRun', checkAutoRun, {
|
||||||
errorRetryCount: 5,
|
errorRetryCount: 5,
|
||||||
errorRetryInterval: 200
|
errorRetryInterval: 200
|
||||||
})
|
})
|
||||||
|
|
||||||
if (error) return <div>failed to load</div>
|
const { appConfig, patchAppConfig } = useAppConfig()
|
||||||
if (isLoading) return <div>loading...</div>
|
const { silentStart = false } = appConfig || {}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<BasePage
|
||||||
{`${data}`}
|
title="设置"
|
||||||
|
header={
|
||||||
<Button
|
<Button
|
||||||
onPress={async () => {
|
isIconOnly
|
||||||
await enableAutoRun()
|
size="sm"
|
||||||
await mutate()
|
onPress={() => {
|
||||||
|
window.open('https://github.com/pompurin404/mihomo-party')
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
enable
|
<IoLogoGithub className="text-lg" />
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
}
|
||||||
onPress={async () => {
|
|
||||||
await disableAutoRun()
|
|
||||||
await mutate()
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
disable
|
<SettingCard>
|
||||||
</Button>
|
<SettingItem title="开机自启" divider>
|
||||||
</div>
|
<Switch
|
||||||
|
size="sm"
|
||||||
|
isSelected={enable}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
if (v) {
|
||||||
|
enableAutoRun()
|
||||||
|
} else {
|
||||||
|
disableAutoRun()
|
||||||
|
}
|
||||||
|
mutate(v)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SettingItem>
|
||||||
|
<SettingItem title="静默启动">
|
||||||
|
<Switch
|
||||||
|
size="sm"
|
||||||
|
isSelected={silentStart}
|
||||||
|
onValueChange={(v) => {
|
||||||
|
patchAppConfig({ silentStart: v })
|
||||||
|
mutate()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SettingItem>
|
||||||
|
</SettingCard>
|
||||||
|
</BasePage>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Settings
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
export async function mihomoVersion(): Promise<IMihomoVersion> {
|
|
||||||
return await window.electron.ipcRenderer.invoke('mihomoVersion')
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function checkAutoRun(): Promise<boolean> {
|
|
||||||
return await window.electron.ipcRenderer.invoke('checkAutoRun')
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function enableAutoRun(): Promise<void> {
|
|
||||||
await window.electron.ipcRenderer.invoke('enableAutoRun')
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function disableAutoRun(): Promise<void> {
|
|
||||||
await window.electron.ipcRenderer.invoke('disableAutoRun')
|
|
||||||
}
|
|
31
src/renderer/src/utils/ipc.ts
Normal file
31
src/renderer/src/utils/ipc.ts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
export async function mihomoVersion(): Promise<IMihomoVersion> {
|
||||||
|
return await window.electron.ipcRenderer.invoke('mihomoVersion')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function checkAutoRun(): Promise<boolean> {
|
||||||
|
return await window.electron.ipcRenderer.invoke('checkAutoRun')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function enableAutoRun(): Promise<void> {
|
||||||
|
await window.electron.ipcRenderer.invoke('enableAutoRun')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function disableAutoRun(): Promise<void> {
|
||||||
|
await window.electron.ipcRenderer.invoke('disableAutoRun')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAppConfig(force = false): Promise<IAppConfig> {
|
||||||
|
return await window.electron.ipcRenderer.invoke('getAppConfig', force)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setAppConfig(patch: Partial<IAppConfig>): Promise<void> {
|
||||||
|
await window.electron.ipcRenderer.invoke('setAppConfig', patch)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getControledMihomoConfig(force = false): Promise<Partial<IMihomoConfig>> {
|
||||||
|
return await window.electron.ipcRenderer.invoke('getControledMihomoConfig', force)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setControledMihomoConfig(patch: Partial<IMihomoConfig>): Promise<void> {
|
||||||
|
await window.electron.ipcRenderer.invoke('setControledMihomoConfig', patch)
|
||||||
|
}
|
11
src/shared/types.d.ts
vendored
11
src/shared/types.d.ts
vendored
|
@ -4,3 +4,14 @@ interface IMihomoVersion {
|
||||||
version: string
|
version: string
|
||||||
meta: boolean
|
meta: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IAppConfig {
|
||||||
|
silentStart: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IMihomoConfig {
|
||||||
|
mode: OutboundMode
|
||||||
|
'mixed-port': number
|
||||||
|
'socks-port'?: number
|
||||||
|
port?: number
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"src/renderer/src/**/*",
|
"src/renderer/src/**/*",
|
||||||
"src/renderer/src/**/*.tsx",
|
"src/renderer/src/**/*.tsx",
|
||||||
"src/preload/*.d.ts",
|
"src/preload/*.d.ts",
|
||||||
"src/shared/**/*.d.ts"
|
"src/shared/*.d.ts"
|
||||||
],
|
],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user