feat: added data folder

This commit is contained in:
kangfenmao 2024-11-19 18:48:57 +08:00
parent 6d665fa926
commit 518a3b26b6
12 changed files with 143 additions and 74 deletions

View File

@ -2,6 +2,7 @@ import path from 'node:path'
import { ThemeMode } from '@types' import { ThemeMode } from '@types'
import { BrowserWindow, ipcMain, session, shell } from 'electron' import { BrowserWindow, ipcMain, session, shell } from 'electron'
import log from 'electron-log'
import { titleBarOverlayDark, titleBarOverlayLight } from './config' import { titleBarOverlayDark, titleBarOverlayLight } from './config'
import AppUpdater from './services/AppUpdater' import AppUpdater from './services/AppUpdater'
@ -23,7 +24,9 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
version: app.getVersion(), version: app.getVersion(),
isPackaged: app.isPackaged, isPackaged: app.isPackaged,
appPath: app.getAppPath(), appPath: app.getAppPath(),
filesPath: path.join(app.getPath('userData'), 'Data', 'Files') filesPath: path.join(app.getPath('userData'), 'Data', 'Files'),
appDataPath: app.getPath('userData'),
logsPath: log.transports.file.getFile().path
})) }))
ipcMain.handle('app:proxy', async (_, proxy: string) => { ipcMain.handle('app:proxy', async (_, proxy: string) => {
@ -110,4 +113,9 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
// export // export
ipcMain.handle('export:word', exportService.exportToWord) ipcMain.handle('export:word', exportService.exportToWord)
// open path
ipcMain.handle('open:path', async (_, path: string) => {
await shell.openPath(path)
})
} }

View File

@ -1,7 +1,7 @@
import { ElectronAPI } from '@electron-toolkit/preload' import { ElectronAPI } from '@electron-toolkit/preload'
import { FileType } from '@renderer/types' import { FileType } from '@renderer/types'
import { WebDavConfig } from '@renderer/types' import { WebDavConfig } from '@renderer/types'
import { LanguageVarious } from '@renderer/types' import { AppInfo, LanguageVarious } from '@renderer/types'
import type { OpenDialogOptions } from 'electron' import type { OpenDialogOptions } from 'electron'
import { Readable } from 'stream' import { Readable } from 'stream'
@ -9,12 +9,7 @@ declare global {
interface Window { interface Window {
electron: ElectronAPI electron: ElectronAPI
api: { api: {
getAppInfo: () => Promise<{ getAppInfo: () => Promise<AppInfo>
version: string
isPackaged: boolean
appPath: string
filesPath: string
}>
checkForUpdate: () => void checkForUpdate: () => void
openWebsite: (url: string) => void openWebsite: (url: string) => void
setProxy: (proxy: string | undefined) => void setProxy: (proxy: string | undefined) => void
@ -57,6 +52,7 @@ declare global {
export: { export: {
toWord: (markdown: string, fileName: string) => Promise<void> toWord: (markdown: string, fileName: string) => Promise<void>
} }
openPath: (path: string) => Promise<void>
} }
} }
} }

View File

@ -45,7 +45,8 @@ const api = {
}, },
export: { export: {
toWord: (markdown: string, fileName: string) => ipcRenderer.invoke('export:word', markdown, fileName) toWord: (markdown: string, fileName: string) => ipcRenderer.invoke('export:word', markdown, fileName)
} },
openPath: (path: string) => ipcRenderer.invoke('open:path', path)
} }
// Use `contextBridge` APIs to expose Electron APIs to // Use `contextBridge` APIs to expose Electron APIs to

View File

@ -348,6 +348,9 @@
"topic.position.right": "Right", "topic.position.right": "Right",
"topic.show.time": "Show Topic Time", "topic.show.time": "Show Topic Time",
"display.title": "Display Settings", "display.title": "Display Settings",
"data.title": "Data Directory",
"data.app_data": "App Data",
"data.app_logs": "App Logs",
"shortcuts": { "shortcuts": {
"title": "Keyboard Shortcuts", "title": "Keyboard Shortcuts",
"action": "Action", "action": "Action",

View File

@ -348,6 +348,9 @@
"topic.position.right": "Справа", "topic.position.right": "Справа",
"topic.show.time": "Показывать время топика", "topic.show.time": "Показывать время топика",
"display.title": "Настройки отображения", "display.title": "Настройки отображения",
"data.title": "Каталог данных",
"data.app_data": "Данные приложения",
"data.app_logs": "Логи приложения",
"shortcuts": { "shortcuts": {
"title": "Горячие клавиши", "title": "Горячие клавиши",
"action": "Действие", "action": "Действие",

View File

@ -336,6 +336,9 @@
"topic.position.right": "右侧", "topic.position.right": "右侧",
"topic.show.time": "显示话题时间", "topic.show.time": "显示话题时间",
"display.title": "显示设置", "display.title": "显示设置",
"data.title": "数据目录",
"data.app_data": "应用数据",
"data.app_logs": "应用日志",
"shortcuts": { "shortcuts": {
"title": "快捷方式", "title": "快捷方式",
"action": "操作", "action": "操作",

View File

@ -336,6 +336,9 @@
"topic.position.right": "右側", "topic.position.right": "右側",
"topic.show.time": "顯示話題時間", "topic.show.time": "顯示話題時間",
"display.title": "顯示設定", "display.title": "顯示設定",
"data.title": "數據目錄",
"data.app_data": "應用數據",
"data.app_logs": "應用日誌",
"shortcuts": { "shortcuts": {
"title": "快速方式", "title": "快速方式",
"action": "操作", "action": "操作",

View File

@ -1,61 +1,102 @@
import { FolderOpenOutlined, SaveOutlined } from '@ant-design/icons' import { FileSearchOutlined, FolderOpenOutlined, SaveOutlined } from '@ant-design/icons'
import { HStack, VStack } from '@renderer/components/Layout' import { HStack, VStack } from '@renderer/components/Layout'
import { backup, reset, restore } from '@renderer/services/BackupService' import { backup, reset, restore } from '@renderer/services/BackupService'
import { Button } from 'antd' import { AppInfo } from '@renderer/types'
import { FC } from 'react' import { Button, Typography } from 'antd'
import { FC, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Link, Route, Routes } from 'react-router-dom' import { Link } from 'react-router-dom'
import styled from 'styled-components'
import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from '..' import { SettingContainer, SettingDivider, SettingGroup, SettingRow, SettingRowTitle, SettingTitle } from '..'
import WebDavSettings from './WebDavSettings' import WebDavSettings from './WebDavSettings'
const DataSettings: FC = () => { const DataSettings: FC = () => {
const { t } = useTranslation() const { t } = useTranslation()
const [appInfo, setAppInfo] = useState<AppInfo>()
useEffect(() => {
window.api.getAppInfo().then(setAppInfo)
}, [])
const handleOpenPath = (path: string) => {
if (path?.endsWith('log')) {
const dirPath = path.split(/[/\\]/).slice(0, -1).join('/')
window.api.openPath(dirPath)
} else {
window.api.openPath(path)
}
}
return ( return (
<Routes> <SettingContainer>
<Route <SettingGroup>
path="/" <SettingTitle>{t('settings.data')}</SettingTitle>
element={ <SettingDivider />
<SettingContainer> <SettingRow>
<SettingTitle>{t('settings.data')}</SettingTitle> <SettingRowTitle>{t('settings.data.webdav.title')}</SettingRowTitle>
<SettingDivider /> <VStack gap="5px">
<SettingRow style={{ minHeight: 32 }}> <Link to="/settings/data/webdav" style={{ color: 'var(--color-text-2)' }}>
<SettingRowTitle>{t('settings.data.webdav.title')}</SettingRowTitle> <Button>{t('settings.general.view_webdav_settings')}</Button>
<VStack gap="5px"> </Link>
<Link to="/settings/data/webdav" style={{ color: 'var(--color-text-2)' }}> </VStack>
<Button>{t('settings.general.view_webdav_settings')}</Button> </SettingRow>
</Link> <SettingDivider />
</VStack> <SettingRow>
</SettingRow> <SettingRowTitle>{t('settings.general.backup.title')}</SettingRowTitle>
<SettingDivider /> <HStack gap="5px" justifyContent="space-between">
<SettingRow> <Button onClick={backup} icon={<SaveOutlined />}>
<SettingRowTitle>{t('settings.general.backup.title')}</SettingRowTitle> {t('settings.general.backup.button')}
<HStack gap="5px" justifyContent="space-between"> </Button>
<Button onClick={backup} icon={<SaveOutlined />}> <Button onClick={restore} icon={<FolderOpenOutlined />}>
{t('settings.general.backup.button')} {t('settings.general.restore.button')}
</Button> </Button>
<Button onClick={restore} icon={<FolderOpenOutlined />}> </HStack>
{t('settings.general.restore.button')} </SettingRow>
</Button> <SettingDivider />
</HStack> <SettingRow>
</SettingRow> <SettingRowTitle>{t('settings.general.reset.title')}</SettingRowTitle>
<SettingDivider /> <HStack gap="5px">
<SettingRow> <Button onClick={reset} danger>
<SettingRowTitle>{t('settings.general.reset.title')}</SettingRowTitle> {t('settings.general.reset.button')}
<HStack gap="5px"> </Button>
<Button onClick={reset} danger> </HStack>
{t('settings.general.reset.button')} </SettingRow>
</Button> </SettingGroup>
</HStack> <SettingGroup>
</SettingRow> <WebDavSettings />
<SettingDivider /> </SettingGroup>
</SettingContainer> <SettingGroup>
} <SettingTitle>{t('settings.data.title')}</SettingTitle>
/> <SettingDivider />
<Route path="webdav" element={<WebDavSettings />} /> <SettingRow>
</Routes> <SettingRowTitle>{t('settings.data.app_data')}</SettingRowTitle>
<HStack alignItems="center" gap="5px">
<Typography.Text style={{ color: 'var(--color-text-3)' }}>{appInfo?.appDataPath}</Typography.Text>
<StyledIcon onClick={() => handleOpenPath(appInfo?.appDataPath)} />
</HStack>
</SettingRow>
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.data.app_logs')}</SettingRowTitle>
<HStack alignItems="center" gap="5px">
<Typography.Text style={{ color: 'var(--color-text-3)' }}>{appInfo?.logsPath}</Typography.Text>
<StyledIcon onClick={() => handleOpenPath(appInfo?.logsPath)} />
</HStack>
</SettingRow>
</SettingGroup>
</SettingContainer>
) )
} }
const StyledIcon = styled(FileSearchOutlined)`
color: var(--color-text-2);
cursor: pointer;
transition: color 0.3s;
&:hover {
color: var(--color-text-1);
}
`
export default DataSettings export default DataSettings

View File

@ -9,11 +9,11 @@ import {
setWebdavPath as _setWebdavPath, setWebdavPath as _setWebdavPath,
setWebdavUser as _setWebdavUser setWebdavUser as _setWebdavUser
} from '@renderer/store/settings' } from '@renderer/store/settings'
import { Breadcrumb, Button, Input } from 'antd' import { Button, Input } from 'antd'
import { FC, useState } from 'react' import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from '..' import { SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from '..'
const WebDavSettings: FC = () => { const WebDavSettings: FC = () => {
const { const {
@ -58,19 +58,8 @@ const WebDavSettings: FC = () => {
} }
return ( return (
<SettingContainer> <>
<Breadcrumb <SettingTitle>{t('settings.data.webdav.title')}</SettingTitle>
items={[
{
title: t('settings.data'),
href: '#/settings/data'
},
{
title: t('settings.data.webdav.title')
}
]}
/>
<SettingTitle style={{ marginTop: 20 }}>{t('settings.data.webdav.title')}</SettingTitle>
<SettingDivider /> <SettingDivider />
<SettingRow> <SettingRow>
<SettingRowTitle>{t('settings.data.webdav.host')}</SettingRowTitle> <SettingRowTitle>{t('settings.data.webdav.host')}</SettingRowTitle>
@ -129,8 +118,7 @@ const WebDavSettings: FC = () => {
</Button> </Button>
</HStack> </HStack>
</SettingRow> </SettingRow>
<SettingDivider /> </>
</SettingContainer>
) )
} }

View File

@ -96,8 +96,13 @@ const ShortcutSettings: FC = () => {
} }
const Table = styled(AntTable)` const Table = styled(AntTable)`
.ant-table {
background: transparent;
}
.ant-table-cell { .ant-table-cell {
padding: 14px 0 !important; padding: 14px 0 !important;
background: transparent !important;
} }
` `

View File

@ -21,8 +21,9 @@ export const SettingTitle = styled.div`
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
font-weight: 900;
user-select: none; user-select: none;
font-size: 16px;
font-weight: bold;
` `
export const SettingSubtitle = styled.div` export const SettingSubtitle = styled.div`
@ -42,6 +43,7 @@ export const SettingRow = styled.div`
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
min-height: 32px;
` `
export const SettingRowTitle = styled.div` export const SettingRowTitle = styled.div`
@ -67,3 +69,10 @@ export const SettingHelpLink = styled(Link)`
font-size: 11px; font-size: 11px;
padding: 0 5px; padding: 0 5px;
` `
export const SettingGroup = styled.div`
margin-bottom: 16px;
border-radius: 8px;
border: 0.5px solid var(--color-border);
padding: 16px;
`

View File

@ -149,3 +149,12 @@ export type WebDavConfig = {
webdavPass: string webdavPass: string
webdavPath: string webdavPath: string
} }
export type AppInfo = {
version: string
isPackaged: boolean
appPath: string
appDataPath: string
filesPath: string
logsPath: string
}