refactor: main code

This commit is contained in:
kangfenmao 2024-11-02 23:29:16 +08:00
parent 04af940144
commit 9468f3b511
13 changed files with 81 additions and 63 deletions

View File

@ -1,25 +1,15 @@
import fs from 'node:fs'
import { app } from 'electron'
import Store from 'electron-store'
import path from 'path'
import { getDataPath } from './utils'
const isDev = process.env.NODE_ENV === 'development'
isDev && app.setPath('userData', app.getPath('userData') + 'Dev')
const getDataPath = () => {
const dataPath = path.join(app.getPath('userData'), 'Data')
if (!fs.existsSync(dataPath)) {
fs.mkdirSync(dataPath, { recursive: true })
}
return dataPath
if (isDev) {
app.setPath('userData', app.getPath('userData') + 'Dev')
}
export const DATA_PATH = getDataPath()
export const appConfig = new Store()
export const titleBarOverlayDark = {
height: 40,
color: '#00000000',

View File

@ -3,7 +3,7 @@ import { app, BrowserWindow } from 'electron'
import installExtension, { REDUX_DEVTOOLS } from 'electron-devtools-installer'
import { registerIpc } from './ipc'
import { registerZoomShortcut } from './shortcut'
import { registerZoomShortcut } from './services/ShortcutService'
import { updateUserDataPath } from './utils/upgrade'
import { createMainWindow } from './window'

View File

@ -2,15 +2,16 @@ import path from 'node:path'
import { BrowserWindow, ipcMain, session, shell } from 'electron'
import { appConfig, titleBarOverlayDark, titleBarOverlayLight } from './config'
import { titleBarOverlayDark, titleBarOverlayLight } from './config'
import AppUpdater from './services/AppUpdater'
import BackupManager from './services/BackupManager'
import { configManager } from './services/ConfigManager'
import { ExportService } from './services/ExportService'
import FileManager from './services/FileManager'
import FileStorage from './services/FileStorage'
import { compress, decompress } from './utils/zip'
import { createMinappWindow } from './window'
const fileManager = new FileManager()
const fileManager = new FileStorage()
const backupManager = new BackupManager()
const exportService = new ExportService(fileManager)
@ -24,16 +25,25 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
filesPath: path.join(app.getPath('userData'), 'Data', 'Files')
}))
ipcMain.handle('open-website', (_, url: string) => {
shell.openExternal(url)
ipcMain.handle('app:proxy', (_, proxy: string) => session.defaultSession.setProxy(proxy ? { proxyRules: proxy } : {}))
ipcMain.handle('app:reload', () => mainWindow.reload())
ipcMain.handle('open:website', (_, url: string) => shell.openExternal(url))
// theme
ipcMain.handle('app:set-theme', (_, theme: 'light' | 'dark') => {
configManager.setTheme(theme)
mainWindow?.setTitleBarOverlay &&
mainWindow.setTitleBarOverlay(theme === 'dark' ? titleBarOverlayDark : titleBarOverlayLight)
})
ipcMain.handle('set-proxy', (_, proxy: string) => {
session.defaultSession.setProxy(proxy ? { proxyRules: proxy } : {})
// check for update
ipcMain.handle('app:check-for-update', async () => {
return {
currentVersion: autoUpdater.currentVersion,
update: await autoUpdater.checkForUpdates()
}
})
ipcMain.handle('reload', () => mainWindow.reload())
// zip
ipcMain.handle('zip:compress', (_, text: string) => compress(text))
ipcMain.handle('zip:decompress', (_, text: Buffer) => decompress(text))
@ -73,20 +83,6 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
})
})
// theme
ipcMain.handle('set-theme', (_, theme: 'light' | 'dark') => {
appConfig.set('theme', theme)
mainWindow?.setTitleBarOverlay &&
mainWindow.setTitleBarOverlay(theme === 'dark' ? titleBarOverlayDark : titleBarOverlayLight)
})
// 触发检查更新(此方法用于被渲染线程调用,例如页面点击检查更新按钮来调用此方法)
ipcMain.handle('check-for-update', async () => {
return {
currentVersion: autoUpdater.currentVersion,
update: await autoUpdater.checkForUpdates()
}
})
// export
ipcMain.handle('export:word', exportService.exportToWord)
}

View File

@ -0,0 +1,19 @@
import Store from 'electron-store'
export class ConfigManager {
private store: Store
constructor() {
this.store = new Store()
}
getTheme(): 'light' | 'dark' {
return this.store.get('theme', 'light') as 'light' | 'dark'
}
setTheme(theme: 'light' | 'dark') {
this.store.set('theme', theme)
}
}
export const configManager = new ConfigManager()

View File

@ -6,13 +6,13 @@ import { dialog } from 'electron'
import Logger from 'electron-log'
import MarkdownIt from 'markdown-it'
import FileManager from './FileManager'
import FileStorage from './FileStorage'
export class ExportService {
private fileManager: FileManager
private fileManager: FileStorage
private md: MarkdownIt
constructor(fileManager: FileManager) {
constructor(fileManager: FileStorage) {
this.fileManager = fileManager
this.md = new MarkdownIt()
}

View File

@ -20,7 +20,7 @@ import { chdir } from 'process'
import sharp from 'sharp'
import { v4 as uuidv4 } from 'uuid'
class FileManager {
class FileStorage {
private storageDir = path.join(app.getPath('userData'), 'Data', 'Files')
private tempDir = path.join(app.getPath('temp'), 'CherryStudio')
@ -135,13 +135,13 @@ class FileManager {
.jpeg({ quality: 80 })
.toFile(destPath)
logger.info('[FileManager] Image compressed successfully:', sourcePath)
logger.info('[FileStorage] Image compressed successfully:', sourcePath)
} else {
// 小图片直接复制
await fs.promises.copyFile(sourcePath, destPath)
}
} catch (error) {
logger.error('[FileManager] Image compression failed:', error)
logger.error('[FileStorage] Image compression failed:', error)
// 压缩失败时直接复制原文件
await fs.promises.copyFile(sourcePath, destPath)
}
@ -159,7 +159,7 @@ class FileManager {
const ext = path.extname(origin_name).toLowerCase()
const destPath = path.join(this.storageDir, uuid + ext)
logger.info('[FileManager] Uploading file:', file.path)
logger.info('[FileStorage] Uploading file:', file.path)
// 根据文件类型选择处理方式
if (imageExts.includes(ext)) {
@ -411,7 +411,7 @@ class FileManager {
return fileMetadata
} catch (error) {
logger.error('[FileManager] Download file error:', error)
logger.error('[FileStorage] Download file error:', error)
throw error
}
}
@ -447,12 +447,12 @@ class FileManager {
// 复制文件
await fs.promises.copyFile(sourcePath, destPath)
logger.info('[FileManager] File copied successfully:', { from: sourcePath, to: destPath })
logger.info('[FileStorage] File copied successfully:', { from: sourcePath, to: destPath })
} catch (error) {
logger.error('[FileManager] Copy file failed:', error)
logger.error('[FileStorage] Copy file failed:', error)
throw error
}
}
}
export default FileManager
export default FileStorage

View File

@ -1,3 +1,4 @@
import fs from 'node:fs'
import path from 'node:path'
import { app } from 'electron'
@ -5,3 +6,11 @@ import { app } from 'electron'
export function getResourcePath() {
return path.join(app.getAppPath(), 'resources')
}
export function getDataPath() {
const dataPath = path.join(app.getPath('userData'), 'Data')
if (!fs.existsSync(dataPath)) {
fs.mkdirSync(dataPath, { recursive: true })
}
return dataPath
}

View File

@ -4,7 +4,8 @@ import windowStateKeeper from 'electron-window-state'
import { join } from 'path'
import icon from '../../build/icon.png?asset'
import { appConfig, titleBarOverlayDark, titleBarOverlayLight } from './config'
import { titleBarOverlayDark, titleBarOverlayLight } from './config'
import { configManager } from './services/ConfigManager'
export function createMainWindow() {
// Load the previous state with fallback to defaults
@ -13,7 +14,7 @@ export function createMainWindow() {
defaultHeight: 670
})
const theme = appConfig.get('theme') || 'light'
const theme = configManager.getTheme()
// Create the browser window.
const isMac = process.platform === 'darwin'

View File

@ -20,8 +20,10 @@ declare global {
setTheme: (theme: 'light' | 'dark') => void
minApp: (options: { url: string; windowOptions?: Electron.BrowserWindowConstructorOptions }) => void
reload: () => void
compress: (text: string) => Promise<Buffer>
decompress: (text: Buffer) => Promise<string>
zip: {
compress: (text: string) => Promise<Buffer>
decompress: (text: Buffer) => Promise<string>
}
backup: {
backup: (fileName: string, data: string, destinationPath?: string) => Promise<Readable>
restore: (backupPath: string) => Promise<string>

View File

@ -5,14 +5,16 @@ import { contextBridge, ipcRenderer, OpenDialogOptions } from 'electron'
// Custom APIs for renderer
const api = {
getAppInfo: () => ipcRenderer.invoke('app:info'),
checkForUpdate: () => ipcRenderer.invoke('check-for-update'),
openWebsite: (url: string) => ipcRenderer.invoke('open-website', url),
setProxy: (proxy: string) => ipcRenderer.invoke('set-proxy', proxy),
setTheme: (theme: 'light' | 'dark') => ipcRenderer.invoke('set-theme', theme),
reload: () => ipcRenderer.invoke('app:reload'),
setProxy: (proxy: string) => ipcRenderer.invoke('app:proxy', proxy),
checkForUpdate: () => ipcRenderer.invoke('app:check-for-update'),
setTheme: (theme: 'light' | 'dark') => ipcRenderer.invoke('app:set-theme', theme),
openWebsite: (url: string) => ipcRenderer.invoke('open:website', url),
minApp: (url: string) => ipcRenderer.invoke('minapp', url),
reload: () => ipcRenderer.invoke('reload'),
compress: (text: string) => ipcRenderer.invoke('zip:compress', text),
decompress: (text: Buffer) => ipcRenderer.invoke('zip:decompress', text),
zip: {
compress: (text: string) => ipcRenderer.invoke('zip:compress', text),
decompress: (text: Buffer) => ipcRenderer.invoke('zip:decompress', text)
},
backup: {
backup: (fileName: string, data: string, destinationPath?: string) =>
ipcRenderer.invoke('backup:backup', fileName, data, destinationPath),

View File

@ -168,7 +168,6 @@ body,
body[os='mac'] {
#content-container {
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
border-left: 0.5px solid var(--color-border);
box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.05);
}

View File

@ -26,7 +26,7 @@ export async function restore() {
const restoreData = await window.api.backup.restore(file.filePath)
data = JSON.parse(restoreData)
} else {
data = JSON.parse(await window.api.decompress(file.content))
data = JSON.parse(await window.api.zip.decompress(file.content))
}
await handleData(data)