mirror of
https://github.com/pompurin404/mihomo-party.git
synced 2024-11-15 19:22:31 +08:00
support edit theme
This commit is contained in:
parent
6592a7a278
commit
71f3f786b9
|
@ -1,4 +1,4 @@
|
|||
import { copyFile, readdir, readFile } from 'fs/promises'
|
||||
import { copyFile, readdir, readFile, writeFile } from 'fs/promises'
|
||||
import { themesDir } from '../utils/dirs'
|
||||
import path from 'path'
|
||||
import axios from 'axios'
|
||||
|
@ -56,9 +56,17 @@ export async function importThemes(files: string[]): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
export async function readTheme(theme: string): Promise<string> {
|
||||
if (!existsSync(path.join(themesDir(), theme))) return ''
|
||||
return await readFile(path.join(themesDir(), theme), 'utf-8')
|
||||
}
|
||||
|
||||
export async function writeTheme(theme: string, css: string): Promise<void> {
|
||||
await writeFile(path.join(themesDir(), theme), css)
|
||||
}
|
||||
|
||||
export async function applyTheme(theme: string): Promise<void> {
|
||||
if (!existsSync(path.join(themesDir(), theme))) return
|
||||
const css = await readFile(path.join(themesDir(), theme), 'utf-8')
|
||||
const css = await readTheme(theme)
|
||||
await mainWindow?.webContents.removeInsertedCSS(insertedCSSKey || '')
|
||||
insertedCSSKey = await mainWindow?.webContents.insertCSS(css)
|
||||
}
|
||||
|
|
|
@ -65,7 +65,14 @@ import { getInterfaces } from '../sys/interface'
|
|||
import { copyEnv } from '../resolve/tray'
|
||||
import { registerShortcut } from '../resolve/shortcut'
|
||||
import { mainWindow } from '..'
|
||||
import { applyTheme, fetchThemes, importThemes, resolveThemes } from '../resolve/theme'
|
||||
import {
|
||||
applyTheme,
|
||||
fetchThemes,
|
||||
importThemes,
|
||||
readTheme,
|
||||
resolveThemes,
|
||||
writeTheme
|
||||
} from '../resolve/theme'
|
||||
import { subStoreCollections, subStoreSubs } from '../core/subStoreApi'
|
||||
import { logDir } from './dirs'
|
||||
import path from 'path'
|
||||
|
@ -205,6 +212,8 @@ export function registerIpcMainHandlers(): void {
|
|||
ipcMain.handle('resolveThemes', () => ipcErrorWrapper(resolveThemes)())
|
||||
ipcMain.handle('fetchThemes', () => ipcErrorWrapper(fetchThemes)())
|
||||
ipcMain.handle('importThemes', (_e, file) => ipcErrorWrapper(importThemes)(file))
|
||||
ipcMain.handle('readTheme', (_e, theme) => ipcErrorWrapper(readTheme)(theme))
|
||||
ipcMain.handle('writeTheme', (_e, theme, css) => ipcErrorWrapper(writeTheme)(theme, css))
|
||||
ipcMain.handle('applyTheme', (_e, theme) => ipcErrorWrapper(applyTheme)(theme))
|
||||
ipcMain.handle('copyEnv', (_e, type) => ipcErrorWrapper(copyEnv)(type))
|
||||
ipcMain.handle('alert', (_e, msg) => {
|
||||
|
|
54
src/renderer/src/components/settings/css-editor-modal.tsx
Normal file
54
src/renderer/src/components/settings/css-editor-modal.tsx
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button } from '@nextui-org/react'
|
||||
import { BaseEditor } from '@renderer/components/base/base-editor'
|
||||
import { readTheme } from '@renderer/utils/ipc'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
interface Props {
|
||||
theme: string
|
||||
onCancel: () => void
|
||||
onConfirm: (script: string) => void
|
||||
}
|
||||
const CSSEditorModal: React.FC<Props> = (props) => {
|
||||
const { theme, onCancel, onConfirm } = props
|
||||
const [currData, setCurrData] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
if (theme) {
|
||||
readTheme(theme).then((css) => {
|
||||
setCurrData(css)
|
||||
})
|
||||
}
|
||||
}, [theme])
|
||||
|
||||
return (
|
||||
<Modal
|
||||
backdrop="blur"
|
||||
classNames={{ backdrop: 'top-[48px]' }}
|
||||
size="5xl"
|
||||
hideCloseButton
|
||||
isOpen={true}
|
||||
onOpenChange={onCancel}
|
||||
scrollBehavior="inside"
|
||||
>
|
||||
<ModalContent className="h-full w-[calc(100%-100px)]">
|
||||
<ModalHeader className="flex pb-0">编辑主题</ModalHeader>
|
||||
<ModalBody className="h-full">
|
||||
<BaseEditor
|
||||
language="css"
|
||||
value={currData}
|
||||
onChange={(value) => setCurrData(value || '')}
|
||||
/>
|
||||
</ModalBody>
|
||||
<ModalFooter className="pt-0">
|
||||
<Button size="sm" variant="light" onPress={onCancel}>
|
||||
取消
|
||||
</Button>
|
||||
<Button size="sm" color="primary" onPress={() => onConfirm(currData)}>
|
||||
确认
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default CSSEditorModal
|
|
@ -5,6 +5,7 @@ import { Button, Input, Select, SelectItem, Switch, Tab, Tabs, Tooltip } from '@
|
|||
import { BiCopy, BiSolidFileImport } from 'react-icons/bi'
|
||||
import useSWR from 'swr'
|
||||
import {
|
||||
applyTheme,
|
||||
checkAutoRun,
|
||||
copyEnv,
|
||||
disableAutoRun,
|
||||
|
@ -14,17 +15,21 @@ import {
|
|||
importThemes,
|
||||
relaunchApp,
|
||||
resolveThemes,
|
||||
restartCore
|
||||
restartCore,
|
||||
writeTheme
|
||||
} from '@renderer/utils/ipc'
|
||||
import { useAppConfig } from '@renderer/hooks/use-app-config'
|
||||
import { platform } from '@renderer/utils/init'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { IoIosHelpCircle, IoMdCloudDownload } from 'react-icons/io'
|
||||
import { MdEditDocument } from 'react-icons/md'
|
||||
import CSSEditorModal from './css-editor-modal'
|
||||
|
||||
const GeneralConfig: React.FC = () => {
|
||||
const { data: enable, mutate: mutateEnable } = useSWR('checkAutoRun', checkAutoRun)
|
||||
const { appConfig, patchAppConfig } = useAppConfig()
|
||||
const [customThemes, setCustomThemes] = useState<{ key: string; label: string }[]>()
|
||||
const [openCSSEditor, setOpenCSSEditor] = useState(false)
|
||||
const [fetching, setFetching] = useState(false)
|
||||
const { setTheme } = useTheme()
|
||||
const {
|
||||
|
@ -49,6 +54,17 @@ const GeneralConfig: React.FC = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
{openCSSEditor && (
|
||||
<CSSEditorModal
|
||||
theme={customTheme}
|
||||
onCancel={() => setOpenCSSEditor(false)}
|
||||
onConfirm={async (css: string) => {
|
||||
await writeTheme(customTheme, css)
|
||||
await applyTheme(customTheme)
|
||||
setOpenCSSEditor(false)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<SettingCard>
|
||||
<SettingItem title="开机自启" divider>
|
||||
<Switch
|
||||
|
@ -261,6 +277,17 @@ const GeneralConfig: React.FC = () => {
|
|||
>
|
||||
<BiSolidFileImport className="text-lg" />
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
isIconOnly
|
||||
title="编辑主题"
|
||||
variant="light"
|
||||
onPress={async () => {
|
||||
setOpenCSSEditor(true)
|
||||
}}
|
||||
>
|
||||
<MdEditDocument className="text-lg" />
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
|
|
|
@ -343,6 +343,14 @@ export async function importThemes(files: string[]): Promise<void> {
|
|||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('importThemes', files))
|
||||
}
|
||||
|
||||
export async function readTheme(theme: string): Promise<string> {
|
||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('readTheme', theme))
|
||||
}
|
||||
|
||||
export async function writeTheme(theme: string, css: string): Promise<void> {
|
||||
return ipcErrorWrapper(await window.electron.ipcRenderer.invoke('writeTheme', theme, css))
|
||||
}
|
||||
|
||||
let applyThemeRunning = false
|
||||
const waitList: string[] = []
|
||||
export async function applyTheme(theme: string): Promise<void> {
|
||||
|
|
Loading…
Reference in New Issue
Block a user