diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 3d7efd1b..27e2b573 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -2,6 +2,7 @@ import path from 'node:path' import { ThemeMode } from '@types' import { BrowserWindow, ipcMain, session, shell } from 'electron' +import log from 'electron-log' import { titleBarOverlayDark, titleBarOverlayLight } from './config' import AppUpdater from './services/AppUpdater' @@ -23,7 +24,9 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { version: app.getVersion(), isPackaged: app.isPackaged, 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) => { @@ -110,4 +113,9 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) { // export ipcMain.handle('export:word', exportService.exportToWord) + + // open path + ipcMain.handle('open:path', async (_, path: string) => { + await shell.openPath(path) + }) } diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts index f0e01c46..dcfc76df 100644 --- a/src/preload/index.d.ts +++ b/src/preload/index.d.ts @@ -1,7 +1,7 @@ import { ElectronAPI } from '@electron-toolkit/preload' import { FileType } 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 { Readable } from 'stream' @@ -9,12 +9,7 @@ declare global { interface Window { electron: ElectronAPI api: { - getAppInfo: () => Promise<{ - version: string - isPackaged: boolean - appPath: string - filesPath: string - }> + getAppInfo: () => Promise checkForUpdate: () => void openWebsite: (url: string) => void setProxy: (proxy: string | undefined) => void @@ -57,6 +52,7 @@ declare global { export: { toWord: (markdown: string, fileName: string) => Promise } + openPath: (path: string) => Promise } } } diff --git a/src/preload/index.ts b/src/preload/index.ts index 39be2265..4a8612c5 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -45,7 +45,8 @@ const api = { }, export: { 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 diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 2ae39696..9c335bc9 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -348,6 +348,9 @@ "topic.position.right": "Right", "topic.show.time": "Show Topic Time", "display.title": "Display Settings", + "data.title": "Data Directory", + "data.app_data": "App Data", + "data.app_logs": "App Logs", "shortcuts": { "title": "Keyboard Shortcuts", "action": "Action", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index c8175c84..e453a314 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -348,6 +348,9 @@ "topic.position.right": "Справа", "topic.show.time": "Показывать время топика", "display.title": "Настройки отображения", + "data.title": "Каталог данных", + "data.app_data": "Данные приложения", + "data.app_logs": "Логи приложения", "shortcuts": { "title": "Горячие клавиши", "action": "Действие", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 8883d9c0..6fcf318d 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -336,6 +336,9 @@ "topic.position.right": "右侧", "topic.show.time": "显示话题时间", "display.title": "显示设置", + "data.title": "数据目录", + "data.app_data": "应用数据", + "data.app_logs": "应用日志", "shortcuts": { "title": "快捷方式", "action": "操作", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 62252b4d..b740a90f 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -336,6 +336,9 @@ "topic.position.right": "右側", "topic.show.time": "顯示話題時間", "display.title": "顯示設定", + "data.title": "數據目錄", + "data.app_data": "應用數據", + "data.app_logs": "應用日誌", "shortcuts": { "title": "快速方式", "action": "操作", diff --git a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx index 0b2fcd6c..09792801 100644 --- a/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/DataSettings.tsx @@ -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 { backup, reset, restore } from '@renderer/services/BackupService' -import { Button } from 'antd' -import { FC } from 'react' +import { AppInfo } from '@renderer/types' +import { Button, Typography } from 'antd' +import { FC, useEffect, useState } from 'react' 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' const DataSettings: FC = () => { const { t } = useTranslation() + const [appInfo, setAppInfo] = useState() + + 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 ( - - - {t('settings.data')} - - - {t('settings.data.webdav.title')} - - - - - - - - - {t('settings.general.backup.title')} - - - - - - - - {t('settings.general.reset.title')} - - - - - - - } - /> - } /> - + + + {t('settings.data')} + + + {t('settings.data.webdav.title')} + + + + + + + + + {t('settings.general.backup.title')} + + + + + + + + {t('settings.general.reset.title')} + + + + + + + + + + {t('settings.data.title')} + + + {t('settings.data.app_data')} + + {appInfo?.appDataPath} + handleOpenPath(appInfo?.appDataPath)} /> + + + + + {t('settings.data.app_logs')} + + {appInfo?.logsPath} + handleOpenPath(appInfo?.logsPath)} /> + + + + ) } +const StyledIcon = styled(FileSearchOutlined)` + color: var(--color-text-2); + cursor: pointer; + transition: color 0.3s; + + &:hover { + color: var(--color-text-1); + } +` + export default DataSettings diff --git a/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx b/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx index 4204b338..e0fbad4e 100644 --- a/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx +++ b/src/renderer/src/pages/settings/DataSettings/WebDavSettings.tsx @@ -9,11 +9,11 @@ import { setWebdavPath as _setWebdavPath, setWebdavUser as _setWebdavUser } from '@renderer/store/settings' -import { Breadcrumb, Button, Input } from 'antd' +import { Button, Input } from 'antd' import { FC, useState } from 'react' import { useTranslation } from 'react-i18next' -import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from '..' +import { SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from '..' const WebDavSettings: FC = () => { const { @@ -58,19 +58,8 @@ const WebDavSettings: FC = () => { } return ( - - - {t('settings.data.webdav.title')} + <> + {t('settings.data.webdav.title')} {t('settings.data.webdav.host')} @@ -129,8 +118,7 @@ const WebDavSettings: FC = () => { - - + ) } diff --git a/src/renderer/src/pages/settings/ShortcutSettings.tsx b/src/renderer/src/pages/settings/ShortcutSettings.tsx index c3c4d55e..44727eab 100644 --- a/src/renderer/src/pages/settings/ShortcutSettings.tsx +++ b/src/renderer/src/pages/settings/ShortcutSettings.tsx @@ -96,8 +96,13 @@ const ShortcutSettings: FC = () => { } const Table = styled(AntTable)` + .ant-table { + background: transparent; + } + .ant-table-cell { padding: 14px 0 !important; + background: transparent !important; } ` diff --git a/src/renderer/src/pages/settings/index.tsx b/src/renderer/src/pages/settings/index.tsx index fe0bc754..9c5de650 100644 --- a/src/renderer/src/pages/settings/index.tsx +++ b/src/renderer/src/pages/settings/index.tsx @@ -21,8 +21,9 @@ export const SettingTitle = styled.div` flex-direction: row; justify-content: space-between; align-items: center; - font-weight: 900; user-select: none; + font-size: 16px; + font-weight: bold; ` export const SettingSubtitle = styled.div` @@ -42,6 +43,7 @@ export const SettingRow = styled.div` flex-direction: row; justify-content: space-between; align-items: center; + min-height: 32px; ` export const SettingRowTitle = styled.div` @@ -67,3 +69,10 @@ export const SettingHelpLink = styled(Link)` font-size: 11px; padding: 0 5px; ` + +export const SettingGroup = styled.div` + margin-bottom: 16px; + border-radius: 8px; + border: 0.5px solid var(--color-border); + padding: 16px; +` diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts index 62a60ad8..ce69b2fc 100644 --- a/src/renderer/src/types/index.ts +++ b/src/renderer/src/types/index.ts @@ -149,3 +149,12 @@ export type WebDavConfig = { webdavPass: string webdavPath: string } + +export type AppInfo = { + version: string + isPackaged: boolean + appPath: string + appDataPath: string + filesPath: string + logsPath: string +}