Skip to content

Commit

Permalink
update profile
Browse files Browse the repository at this point in the history
  • Loading branch information
pompurin404 committed Aug 5, 2024
1 parent 8d7ae19 commit 1cc68b5
Show file tree
Hide file tree
Showing 10 changed files with 343 additions and 61 deletions.
6 changes: 5 additions & 1 deletion src/main/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@ export {
getProfileConfig,
addProfileItem,
removeProfileItem,
createProfile
createProfile,
getProfileStr,
setProfileStr,
changeCurrentProfile,
updateProfileItem
} from './profile'
34 changes: 29 additions & 5 deletions src/main/config/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,21 @@ export async function changeCurrentProfile(id: string): Promise<void> {
}
}

export async function updateProfileItem(item: IProfileItem): Promise<void> {
const index = profileConfig.items.findIndex((i) => i.id === item.id)
profileConfig.items[index] = item
fs.writeFileSync(profileConfigPath(), yaml.stringify(profileConfig))
window?.webContents.send('profileConfigUpdated')
}

export async function addProfileItem(item: Partial<IProfileItem>): Promise<void> {
const newItem = await createProfile(item)
profileConfig.items.push(newItem)
if (profileConfig.items.find((i) => i.id === newItem.id)) {
updateProfileItem(newItem)
} else {
profileConfig.items.push(newItem)
}

if (!getProfileConfig().current) {
changeCurrentProfile(newItem.id)
}
Expand Down Expand Up @@ -134,7 +146,7 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi
if (headers['subscription-userinfo']) {
newItem.extra = parseSubinfo(headers['subscription-userinfo'])
}
fs.writeFileSync(profilePath(id), data, 'utf-8')
setProfileStr(id, data)
} catch (e) {
dialog.showErrorBox('Failed to fetch remote profile', `${e}\nurl: ${item.url}`)
throw new Error(`Failed to fetch remote profile ${e}`)
Expand All @@ -150,21 +162,33 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi
throw new Error('File is required for local profile')
}
const data = item.file
fs.writeFileSync(profilePath(id), yaml.stringify(data))
setProfileStr(id, data)
break
}
}

return newItem
}

export function getProfileStr(id: string): string {
return fs.readFileSync(profilePath(id), 'utf-8')
}

export function setProfileStr(id: string, content: string): void {
fs.writeFileSync(profilePath(id), content, 'utf-8')
if (id === getProfileConfig().current) {
getCurrentProfile(true)
restartCore()
}
}

export function getCurrentProfile(force = false): Partial<IMihomoConfig> {
if (force || !currentProfile) {
const current = getProfileConfig().current
if (current) {
currentProfile = yaml.parse(fs.readFileSync(profilePath(current), 'utf-8'))
currentProfile = yaml.parse(getProfileStr(current))
} else {
currentProfile = yaml.parse(fs.readFileSync(profilePath('default'), 'utf-8'))
currentProfile = yaml.parse(getProfileStr('default'))
}
}
return currentProfile
Expand Down
10 changes: 8 additions & 2 deletions src/main/utils/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ import {
getCurrentProfileItem,
getProfileItem,
addProfileItem,
removeProfileItem
removeProfileItem,
changeCurrentProfile,
getProfileStr,
setProfileStr,
updateProfileItem
} from '../config'
import { isEncryptionAvailable, restartCore } from '../core/manager'
import { triggerSysProxy } from '../resolve/sysproxy'
import { changeCurrentProfile } from '../config/profile'

export function registerIpcMainHandlers(): void {
ipcMain.handle('mihomoVersion', mihomoVersion)
Expand All @@ -52,6 +55,9 @@ export function registerIpcMainHandlers(): void {
ipcMain.handle('getProfileConfig', (_e, force) => getProfileConfig(force))
ipcMain.handle('getCurrentProfileItem', getCurrentProfileItem)
ipcMain.handle('getProfileItem', (_e, id) => getProfileItem(id))
ipcMain.handle('getProfileStr', (_e, id) => getProfileStr(id))
ipcMain.handle('setProfileStr', (_e, id, str) => setProfileStr(id, str))
ipcMain.handle('updateProfileItem', (_e, item) => updateProfileItem(item))
ipcMain.handle('changeCurrentProfile', (_e, id) => changeCurrentProfile(id))
ipcMain.handle('addProfileItem', (_e, item) => addProfileItem(item))
ipcMain.handle('removeProfileItem', (_e, id) => removeProfileItem(id))
Expand Down
77 changes: 77 additions & 0 deletions src/renderer/src/components/profiles/edit-file-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button } from '@nextui-org/react'
import React, { useEffect, useState } from 'react'
import MonacoEditor, { monaco } from 'react-monaco-editor'
import { useTheme } from 'next-themes'
import { getProfileStr, setProfileStr } from '@renderer/utils/ipc'
interface Props {
id: string
onClose: () => void
}
const EditFileModal: React.FC<Props> = (props) => {
const { id, onClose } = props
const [currData, setCurrData] = useState('')
const { theme } = useTheme()

const editorDidMount = (editor: monaco.editor.IStandaloneCodeEditor): void => {
window.electron.ipcRenderer.on('resize', () => {
editor.layout()
})
}

const editorWillUnmount = (editor: monaco.editor.IStandaloneCodeEditor): void => {
window.electron.ipcRenderer.removeAllListeners('resize')
editor.dispose()
}

const getContent = async (): Promise<void> => {
setCurrData(await getProfileStr(id))
}

useEffect(() => {
getContent()
}, [])

return (
<Modal size="5xl" hideCloseButton isOpen={true} scrollBehavior="inside">
<ModalContent className="h-full w-[calc(100%-100px)]">
<ModalHeader className="flex">编辑订阅</ModalHeader>
<ModalBody className="h-full">
<MonacoEditor
height="100%"
language="yaml"
value={currData}
theme={theme === 'dark' ? 'vs-dark' : 'vs'}
options={{
minimap: {
enabled: false
},
mouseWheelZoom: true,
fontFamily: `Fira Code, JetBrains Mono, Roboto Mono, "Source Code Pro", Consolas, Menlo, Monaco, monospace, "Courier New", "Apple Color Emoji"`,
fontLigatures: true, // 连字符
smoothScrolling: true // 平滑滚动
}}
editorDidMount={editorDidMount}
editorWillUnmount={editorWillUnmount}
onChange={(value) => setCurrData(value)}
/>
</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onClose}>
取消
</Button>
<Button
color="primary"
onPress={async () => {
await setProfileStr(id, currData)
onClose()
}}
>
确认
</Button>
</ModalFooter>
</ModalContent>
</Modal>
)
}

export default EditFileModal
79 changes: 79 additions & 0 deletions src/renderer/src/components/profiles/edit-info-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {
Modal,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
Button,
Input
} from '@nextui-org/react'
import React, { useState } from 'react'
import SettingItem from '../base/base-setting-item'
interface Props {
item: IProfileItem
updateProfileItem: (item: IProfileItem) => Promise<void>
onClose: () => void
}
const EditInfoModal: React.FC<Props> = (props) => {
const { item, updateProfileItem, onClose } = props
const [values, setValues] = useState(item)

const onSave = async (): Promise<void> => {
await updateProfileItem(values)
onClose()
}

return (
<Modal hideCloseButton isOpen={true} scrollBehavior="inside">
<ModalContent>
<ModalHeader className="flex">编辑信息</ModalHeader>
<ModalBody>
<SettingItem title="名称">
<Input
size="sm"
className="w-[200px]"
value={values.name}
onValueChange={(v) => {
setValues({ ...values, name: v })
}}
/>
</SettingItem>
{values.url && (
<SettingItem title="订阅地址">
<Input
size="sm"
className="w-[200px]"
value={values.url}
onValueChange={(v) => {
setValues({ ...values, url: v })
}}
/>
</SettingItem>
)}

<SettingItem title="更新间隔(分钟)">
<Input
size="sm"
type="number"
className="w-[200px]"
value={values.interval?.toString() ?? ''}
onValueChange={(v) => {
setValues({ ...values, interval: parseInt(v) })
}}
/>
</SettingItem>
</ModalBody>
<ModalFooter>
<Button variant="light" onPress={onClose}>
取消
</Button>
<Button color="primary" onPress={onSave}>
保存
</Button>
</ModalFooter>
</ModalContent>
</Modal>
)
}

export default EditInfoModal
Loading

0 comments on commit 1cc68b5

Please sign in to comment.