support new profile

This commit is contained in:
pompurin404 2024-08-31 21:50:13 +08:00
parent 1f90ae2eed
commit d8b9d59dbb
No known key found for this signature in database
8 changed files with 136 additions and 65 deletions

View File

@ -5,6 +5,7 @@
### New Features ### New Features
- 支持使用外部编辑器打开文件 - 支持使用外部编辑器打开文件
- 支持新建订阅/覆写
- 添加窗口置顶按钮 - 添加窗口置顶按钮
- 允许禁用系统标题栏 - 允许禁用系统标题栏
- 重写连接页面 - 重写连接页面

View File

@ -2,6 +2,7 @@ export const defaultConfig: IAppConfig = {
core: 'mihomo', core: 'mihomo',
silentStart: false, silentStart: false,
appTheme: 'system', appTheme: 'system',
useWindowFrame: true,
proxyInTray: true, proxyInTray: true,
maxLogDays: 7, maxLogDays: 7,
proxyCols: 'auto', proxyCols: 'auto',

View File

@ -104,7 +104,7 @@ const App: React.FC = () => {
// ignore // ignore
} }
} }
}, [appTheme]) }, [appTheme, systemTheme])
const onDragEnd = async (event: DragEndEvent): Promise<void> => { const onDragEnd = async (event: DragEndEvent): Promise<void> => {
const { active, over } = event const { active, over } = event

View File

@ -36,7 +36,7 @@ const BasePage = forwardRef<HTMLDivElement, Props>((props, ref) => {
<div className="sticky top-0 z-40 h-[49px] w-full bg-background"> <div className="sticky top-0 z-40 h-[49px] w-full bg-background">
<div className="app-drag p-2 flex justify-between h-[48px]"> <div className="app-drag p-2 flex justify-between h-[48px]">
<div className="title h-full text-lg leading-[32px]">{props.title}</div> <div className="title h-full text-lg leading-[32px]">{props.title}</div>
<div style={{ marginRight: overlayWidth }} className="header h-full"> <div style={{ marginRight: overlayWidth }} className="header flex gap-2 h-full">
{props.header} {props.header}
</div> </div>
</div> </div>

View File

@ -1,4 +1,12 @@
import { Button, Divider, Input } from '@nextui-org/react' import {
Button,
Divider,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownTrigger,
Input
} from '@nextui-org/react'
import BasePage from '@renderer/components/base/base-page' import BasePage from '@renderer/components/base/base-page'
import { getFilePath, readTextFile } from '@renderer/utils/ipc' import { getFilePath, readTextFile } from '@renderer/utils/ipc'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
@ -14,6 +22,7 @@ import {
import { SortableContext } from '@dnd-kit/sortable' import { SortableContext } from '@dnd-kit/sortable'
import { useOverrideConfig } from '@renderer/hooks/use-override-config' import { useOverrideConfig } from '@renderer/hooks/use-override-config'
import OverrideItem from '@renderer/components/override/override-item' import OverrideItem from '@renderer/components/override/override-item'
import { FaPlus } from 'react-icons/fa6'
const Override: React.FC = () => { const Override: React.FC = () => {
const { const {
@ -115,7 +124,7 @@ const Override: React.FC = () => {
<> <>
<Button <Button
size="sm" size="sm"
className="app-nodrag mr-2" className="app-nodrag"
onPress={() => { onPress={() => {
open('https://mihomo.party/guides/function/override/yaml/') open('https://mihomo.party/guides/function/override/yaml/')
}} }}
@ -165,27 +174,52 @@ const Override: React.FC = () => {
> >
</Button> </Button>
<Button <Dropdown>
size="sm" <DropdownTrigger>
color="primary" <Button className="ml-2" size="sm" isIconOnly color="primary">
className="ml-2" <FaPlus />
onPress={() => { </Button>
getFilePath(['js', 'yaml']).then(async (files) => { </DropdownTrigger>
if (files?.length) { <DropdownMenu
const content = await readTextFile(files[0]) onAction={async (key) => {
const fileName = files[0].split('/').pop()?.split('\\').pop() if (key === 'open') {
try {
const files = await getFilePath(['js', 'yaml'])
if (files?.length) {
const content = await readTextFile(files[0])
const fileName = files[0].split('/').pop()?.split('\\').pop()
await addOverrideItem({
name: fileName,
type: 'local',
file: content,
ext: fileName?.endsWith('.js') ? 'js' : 'yaml'
})
}
} catch (e) {
alert(e)
}
} else if (key === 'new-yaml') {
await addOverrideItem({ await addOverrideItem({
name: fileName, name: '新建YAML',
type: 'local', type: 'local',
file: content, file: '# https://mihomo.party/guides/function/override/yaml/',
ext: fileName?.endsWith('.js') ? 'js' : 'yaml' ext: 'yaml'
})
} else if (key === 'new-js') {
await addOverrideItem({
name: '新建JS',
type: 'local',
file: '// https://mihomo.party/guides/function/override/js/\nfunction main(config) {\n return config\n}',
ext: 'js'
}) })
} }
}) }}
}} >
> <DropdownItem key="open"></DropdownItem>
<DropdownItem key="new-yaml"> YAML</DropdownItem>
</Button> <DropdownItem key="new-js"> JavaScript</DropdownItem>
</DropdownMenu>
</Dropdown>
</div> </div>
<Divider /> <Divider />
</div> </div>

View File

@ -1,4 +1,13 @@
import { Button, Checkbox, Divider, Input } from '@nextui-org/react' import {
Button,
Checkbox,
Divider,
Dropdown,
DropdownItem,
DropdownMenu,
DropdownTrigger,
Input
} from '@nextui-org/react'
import BasePage from '@renderer/components/base/base-page' import BasePage from '@renderer/components/base/base-page'
import ProfileItem from '@renderer/components/profiles/profile-item' import ProfileItem from '@renderer/components/profiles/profile-item'
import { useProfileConfig } from '@renderer/hooks/use-profile-config' import { useProfileConfig } from '@renderer/hooks/use-profile-config'
@ -14,6 +23,7 @@ import {
DragEndEvent DragEndEvent
} from '@dnd-kit/core' } from '@dnd-kit/core'
import { SortableContext } from '@dnd-kit/sortable' import { SortableContext } from '@dnd-kit/sortable'
import { FaPlus } from 'react-icons/fa6'
const Profiles: React.FC = () => { const Profiles: React.FC = () => {
const { const {
@ -101,27 +111,38 @@ const Profiles: React.FC = () => {
ref={pageRef} ref={pageRef}
title="订阅管理" title="订阅管理"
header={ header={
<Button <>
size="sm" <Button
className="app-nodrag" size="sm"
color="primary" className="app-nodrag"
isLoading={updating} onPress={async () => {
onPress={async () => { open('https://mihomo.party/ads/airport/')
setUpdating(true) }}
for (const item of items) { >
if (item.id === current) continue
if (item.type !== 'remote') continue </Button>
await addProfileItem(item) <Button
} size="sm"
const currentItem = items.find((item) => item.id === current) className="app-nodrag"
if (currentItem && currentItem.type === 'remote') { color="primary"
await addProfileItem(currentItem) isLoading={updating}
} onPress={async () => {
setUpdating(false) setUpdating(true)
}} for (const item of items) {
> if (item.id === current) continue
if (item.type !== 'remote') continue
</Button> await addProfileItem(item)
}
const currentItem = items.find((item) => item.id === current)
if (currentItem && currentItem.type === 'remote') {
await addProfileItem(currentItem)
}
setUpdating(false)
}}
>
</Button>
</>
} }
> >
<div className="sticky top-0 z-40 bg-background"> <div className="sticky top-0 z-40 bg-background">
@ -165,25 +186,38 @@ const Profiles: React.FC = () => {
> >
</Button> </Button>
<Button <Dropdown>
size="sm" <DropdownTrigger>
color="primary" <Button className="ml-2" size="sm" isIconOnly color="primary">
className="ml-2" <FaPlus />
onPress={async () => { </Button>
try { </DropdownTrigger>
const files = await getFilePath(['yml', 'yaml']) <DropdownMenu
if (files?.length) { onAction={async (key) => {
const content = await readTextFile(files[0]) if (key === 'open') {
const fileName = files[0].split('/').pop()?.split('\\').pop() try {
await addProfileItem({ name: fileName, type: 'local', file: content }) const files = await getFilePath(['yml', 'yaml'])
if (files?.length) {
const content = await readTextFile(files[0])
const fileName = files[0].split('/').pop()?.split('\\').pop()
await addProfileItem({ name: fileName, type: 'local', file: content })
}
} catch (e) {
alert(e)
}
} else if (key === 'new') {
await addProfileItem({
name: '新建订阅',
type: 'local',
file: 'proxies: []\nproxy-groups: []\nrules: []'
})
} }
} catch (e) { }}
alert(e) >
} <DropdownItem key="open"></DropdownItem>
}} <DropdownItem key="new"></DropdownItem>
> </DropdownMenu>
</Dropdown>
</Button>
</div> </div>
<Divider /> <Divider />
</div> </div>

View File

@ -110,10 +110,11 @@ const Proxies: React.FC = () => {
<BasePage <BasePage
title="代理组" title="代理组"
header={ header={
<div className="app-nodrag"> <>
<Button <Button
size="sm" size="sm"
isIconOnly isIconOnly
className="app-nodrag"
onPress={() => { onPress={() => {
patchAppConfig({ patchAppConfig({
proxyDisplayOrder: proxyDisplayOrder:
@ -136,7 +137,7 @@ const Proxies: React.FC = () => {
<Button <Button
size="sm" size="sm"
isIconOnly isIconOnly
className="ml-2" className="app-nodrag"
onPress={() => { onPress={() => {
patchAppConfig({ patchAppConfig({
proxyDisplayMode: proxyDisplayMode === 'simple' ? 'full' : 'simple' proxyDisplayMode: proxyDisplayMode === 'simple' ? 'full' : 'simple'
@ -149,7 +150,7 @@ const Proxies: React.FC = () => {
<CgDetailsLess size={20} title="简洁信息" /> <CgDetailsLess size={20} title="简洁信息" />
)} )}
</Button> </Button>
</div> </>
} }
> >
<div className="h-[calc(100vh-50px)]"> <div className="h-[calc(100vh-50px)]">

View File

@ -18,7 +18,7 @@ const Settings: React.FC = () => {
isIconOnly isIconOnly
size="sm" size="sm"
title="官方文档" title="官方文档"
className="app-nodrag mr-2" className="app-nodrag"
onPress={() => { onPress={() => {
window.open('https://mihomo.party') window.open('https://mihomo.party')
}} }}