support edit theme

This commit is contained in:
pompurin404 2024-09-21 22:52:39 +08:00
parent bce9d249ce
commit 67a4a3a395
No known key found for this signature in database
5 changed files with 111 additions and 5 deletions

View File

@ -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)
}

View File

@ -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) => {

View 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

View File

@ -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>
</>
}
>

View File

@ -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> {