mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-26 20:50:30 +08:00
support new profile
This commit is contained in:
parent
1f90ae2eed
commit
d8b9d59dbb
@ -5,6 +5,7 @@
|
||||
### New Features
|
||||
|
||||
- 支持使用外部编辑器打开文件
|
||||
- 支持新建订阅/覆写
|
||||
- 添加窗口置顶按钮
|
||||
- 允许禁用系统标题栏
|
||||
- 重写连接页面
|
||||
|
||||
@ -2,6 +2,7 @@ export const defaultConfig: IAppConfig = {
|
||||
core: 'mihomo',
|
||||
silentStart: false,
|
||||
appTheme: 'system',
|
||||
useWindowFrame: true,
|
||||
proxyInTray: true,
|
||||
maxLogDays: 7,
|
||||
proxyCols: 'auto',
|
||||
|
||||
@ -104,7 +104,7 @@ const App: React.FC = () => {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}, [appTheme])
|
||||
}, [appTheme, systemTheme])
|
||||
|
||||
const onDragEnd = async (event: DragEndEvent): Promise<void> => {
|
||||
const { active, over } = event
|
||||
|
||||
@ -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="app-drag p-2 flex justify-between h-[48px]">
|
||||
<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}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -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 { getFilePath, readTextFile } from '@renderer/utils/ipc'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
@ -14,6 +22,7 @@ import {
|
||||
import { SortableContext } from '@dnd-kit/sortable'
|
||||
import { useOverrideConfig } from '@renderer/hooks/use-override-config'
|
||||
import OverrideItem from '@renderer/components/override/override-item'
|
||||
import { FaPlus } from 'react-icons/fa6'
|
||||
|
||||
const Override: React.FC = () => {
|
||||
const {
|
||||
@ -115,7 +124,7 @@ const Override: React.FC = () => {
|
||||
<>
|
||||
<Button
|
||||
size="sm"
|
||||
className="app-nodrag mr-2"
|
||||
className="app-nodrag"
|
||||
onPress={() => {
|
||||
open('https://mihomo.party/guides/function/override/yaml/')
|
||||
}}
|
||||
@ -165,27 +174,52 @@ const Override: React.FC = () => {
|
||||
>
|
||||
导入
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
color="primary"
|
||||
className="ml-2"
|
||||
onPress={() => {
|
||||
getFilePath(['js', 'yaml']).then(async (files) => {
|
||||
if (files?.length) {
|
||||
const content = await readTextFile(files[0])
|
||||
const fileName = files[0].split('/').pop()?.split('\\').pop()
|
||||
<Dropdown>
|
||||
<DropdownTrigger>
|
||||
<Button className="ml-2" size="sm" isIconOnly color="primary">
|
||||
<FaPlus />
|
||||
</Button>
|
||||
</DropdownTrigger>
|
||||
<DropdownMenu
|
||||
onAction={async (key) => {
|
||||
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({
|
||||
name: fileName,
|
||||
name: '新建YAML',
|
||||
type: 'local',
|
||||
file: content,
|
||||
ext: fileName?.endsWith('.js') ? 'js' : 'yaml'
|
||||
file: '# https://mihomo.party/guides/function/override/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'
|
||||
})
|
||||
}
|
||||
})
|
||||
}}
|
||||
>
|
||||
打开
|
||||
</Button>
|
||||
}}
|
||||
>
|
||||
<DropdownItem key="open">打开</DropdownItem>
|
||||
<DropdownItem key="new-yaml">新建 YAML</DropdownItem>
|
||||
<DropdownItem key="new-js">新建 JavaScript</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<Divider />
|
||||
</div>
|
||||
|
||||
@ -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 ProfileItem from '@renderer/components/profiles/profile-item'
|
||||
import { useProfileConfig } from '@renderer/hooks/use-profile-config'
|
||||
@ -14,6 +23,7 @@ import {
|
||||
DragEndEvent
|
||||
} from '@dnd-kit/core'
|
||||
import { SortableContext } from '@dnd-kit/sortable'
|
||||
import { FaPlus } from 'react-icons/fa6'
|
||||
|
||||
const Profiles: React.FC = () => {
|
||||
const {
|
||||
@ -101,27 +111,38 @@ const Profiles: React.FC = () => {
|
||||
ref={pageRef}
|
||||
title="订阅管理"
|
||||
header={
|
||||
<Button
|
||||
size="sm"
|
||||
className="app-nodrag"
|
||||
color="primary"
|
||||
isLoading={updating}
|
||||
onPress={async () => {
|
||||
setUpdating(true)
|
||||
for (const item of items) {
|
||||
if (item.id === current) continue
|
||||
if (item.type !== 'remote') continue
|
||||
await addProfileItem(item)
|
||||
}
|
||||
const currentItem = items.find((item) => item.id === current)
|
||||
if (currentItem && currentItem.type === 'remote') {
|
||||
await addProfileItem(currentItem)
|
||||
}
|
||||
setUpdating(false)
|
||||
}}
|
||||
>
|
||||
更新全部订阅
|
||||
</Button>
|
||||
<>
|
||||
<Button
|
||||
size="sm"
|
||||
className="app-nodrag"
|
||||
onPress={async () => {
|
||||
open('https://mihomo.party/ads/airport/')
|
||||
}}
|
||||
>
|
||||
订阅推荐
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
className="app-nodrag"
|
||||
color="primary"
|
||||
isLoading={updating}
|
||||
onPress={async () => {
|
||||
setUpdating(true)
|
||||
for (const item of items) {
|
||||
if (item.id === current) continue
|
||||
if (item.type !== 'remote') continue
|
||||
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">
|
||||
@ -165,25 +186,38 @@ const Profiles: React.FC = () => {
|
||||
>
|
||||
导入
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
color="primary"
|
||||
className="ml-2"
|
||||
onPress={async () => {
|
||||
try {
|
||||
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 })
|
||||
<Dropdown>
|
||||
<DropdownTrigger>
|
||||
<Button className="ml-2" size="sm" isIconOnly color="primary">
|
||||
<FaPlus />
|
||||
</Button>
|
||||
</DropdownTrigger>
|
||||
<DropdownMenu
|
||||
onAction={async (key) => {
|
||||
if (key === 'open') {
|
||||
try {
|
||||
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)
|
||||
}
|
||||
}}
|
||||
>
|
||||
打开
|
||||
</Button>
|
||||
}}
|
||||
>
|
||||
<DropdownItem key="open">打开</DropdownItem>
|
||||
<DropdownItem key="new">新建</DropdownItem>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<Divider />
|
||||
</div>
|
||||
|
||||
@ -110,10 +110,11 @@ const Proxies: React.FC = () => {
|
||||
<BasePage
|
||||
title="代理组"
|
||||
header={
|
||||
<div className="app-nodrag">
|
||||
<>
|
||||
<Button
|
||||
size="sm"
|
||||
isIconOnly
|
||||
className="app-nodrag"
|
||||
onPress={() => {
|
||||
patchAppConfig({
|
||||
proxyDisplayOrder:
|
||||
@ -136,7 +137,7 @@ const Proxies: React.FC = () => {
|
||||
<Button
|
||||
size="sm"
|
||||
isIconOnly
|
||||
className="ml-2"
|
||||
className="app-nodrag"
|
||||
onPress={() => {
|
||||
patchAppConfig({
|
||||
proxyDisplayMode: proxyDisplayMode === 'simple' ? 'full' : 'simple'
|
||||
@ -149,7 +150,7 @@ const Proxies: React.FC = () => {
|
||||
<CgDetailsLess size={20} title="简洁信息" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<div className="h-[calc(100vh-50px)]">
|
||||
|
||||
@ -18,7 +18,7 @@ const Settings: React.FC = () => {
|
||||
isIconOnly
|
||||
size="sm"
|
||||
title="官方文档"
|
||||
className="app-nodrag mr-2"
|
||||
className="app-nodrag"
|
||||
onPress={() => {
|
||||
window.open('https://mihomo.party')
|
||||
}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user