From 7023810b2a52dcd1018eb8662b59fce4c4fc6632 Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Sat, 16 Nov 2024 02:24:13 +0800 Subject: [PATCH] =?UTF-8?q?style:=20=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/extensions.json | 2 +- .vscode/launch.json | 74 ++--- .vscode/settings.json | 18 +- README.md | 2 +- config/index.ts | 70 ++--- electron-builder.yml | 62 ++--- electron.vite.config.ts | 46 ++-- package.json | 108 ++++---- src/main/base/base.ts | 6 +- src/main/index.ts | 106 +++---- src/main/modules/App.ts | 56 ++-- src/main/modules/db/custom.ts | 66 ++--- src/main/modules/db/index.ts | 150 +++++----- src/main/modules/index.ts | 20 +- src/main/modules/module.ts | 28 +- src/main/modules/setting/index.ts | 459 +++++++++++++++---------------- src/preload/index.d.ts | 10 +- src/preload/index.ts | 24 +- src/renderer/index.html | 26 +- src/renderer/src/App.vue | 40 +-- src/renderer/src/assets/base.css | 92 +++---- src/renderer/src/assets/main.css | 228 +++++++-------- src/renderer/src/components/Versions.vue | 12 +- src/renderer/src/env.d.ts | 10 +- src/renderer/src/main.ts | 12 +- src/renderer/src/shims.d.ts | 10 +- uno.config.ts | 16 +- 27 files changed, 867 insertions(+), 886 deletions(-) diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 940260d..8ccf0e7 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,3 @@ { - "recommendations": ["dbaeumer.vscode-eslint"] + "recommendations": ["dbaeumer.vscode-eslint"] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 0b6b9a6..344cf45 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,39 +1,39 @@ { - "version": "0.2.0", - "configurations": [ - { - "name": "Debug Main Process", - "type": "node", - "request": "launch", - "cwd": "${workspaceRoot}", - "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite", - "windows": { - "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd" - }, - "runtimeArgs": ["--sourcemap"], - "env": { - "REMOTE_DEBUGGING_PORT": "9222" - } - }, - { - "name": "Debug Renderer Process", - "port": 9222, - "request": "attach", - "type": "chrome", - "webRoot": "${workspaceFolder}/src/renderer", - "timeout": 60000, - "presentation": { - "hidden": true - } - } - ], - "compounds": [ - { - "name": "Debug All", - "configurations": ["Debug Main Process", "Debug Renderer Process"], - "presentation": { - "order": 1 - } - } - ] + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Main Process", + "type": "node", + "request": "launch", + "cwd": "${workspaceRoot}", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite", + "windows": { + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd" + }, + "runtimeArgs": ["--sourcemap"], + "env": { + "REMOTE_DEBUGGING_PORT": "9222" + } + }, + { + "name": "Debug Renderer Process", + "port": 9222, + "request": "attach", + "type": "chrome", + "webRoot": "${workspaceFolder}/src/renderer", + "timeout": 60000, + "presentation": { + "hidden": true + } + } + ], + "compounds": [ + { + "name": "Debug All", + "configurations": ["Debug Main Process", "Debug Renderer Process"], + "presentation": { + "order": 1 + } + } + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 20951e4..7e74831 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,11 @@ { - "[typescript]": { - "editor.defaultFormatter": "vscode.typescript-language-features" - }, - "[javascript]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, - "[json]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" - } + "[typescript]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } } diff --git a/README.md b/README.md index a89e70b..eb68cfd 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ An Electron application with Vue and TypeScript ## Recommended IDE Setup -- [VSCode](https://code.visualstudio.com/) + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) + [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) +- [VSCode](https://code.visualstudio.com/) + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) + [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) ## Project Setup diff --git a/config/index.ts b/config/index.ts index 74f2c72..c191c59 100644 --- a/config/index.ts +++ b/config/index.ts @@ -1,35 +1,35 @@ -interface IConfig { - app_title: string, - default_config: { - language: "zh" | "en" // i18n - "common.theme": "light" | "dark" | "auto" // 主题 - "desktop:wallpaper": string - "update.repo"?: string // 更新地址 - "update.owner"?: string // 更新通道 - "update.allowDowngrade": boolean, - "update.allowPrerelease": boolean - "editor.bg": string // 更新通道 - "editor.logoType": "logo" | "bg" // 更新通道 - "editor.fontFamily": string // 更新通道 - // "snippet.storagePath": string // 代码片段保存位置 - // "bookmark.storagePath": string // 书签保存位置 - // backup_rule: string // 备份规则 - storagePath: string // 存储地址 - } -} -export default { - app_title: "ada", - default_config: { - "storagePath": "$storagePath$", - "language": "zh", - "common.theme": "auto", - "desktop:wallpaper": "", - "editor.bg": "", - "editor.logoType": "logo", - "editor.fontFamily": "Cascadia Mono, Consolas, 'Courier New', monospace", - "update.repo": "wood-desktop", - "update.owner": "npmrun", - "update.allowDowngrade": false, - "update.allowPrerelease": false - } -} as IConfig \ No newline at end of file +interface IConfig { + app_title: string + default_config: { + language: "zh" | "en" // i18n + "common.theme": "light" | "dark" | "auto" // 主题 + "desktop:wallpaper": string + "update.repo"?: string // 更新地址 + "update.owner"?: string // 更新通道 + "update.allowDowngrade": boolean + "update.allowPrerelease": boolean + "editor.bg": string // 更新通道 + "editor.logoType": "logo" | "bg" // 更新通道 + "editor.fontFamily": string // 更新通道 + // "snippet.storagePath": string // 代码片段保存位置 + // "bookmark.storagePath": string // 书签保存位置 + // backup_rule: string // 备份规则 + storagePath: string // 存储地址 + } +} +export default { + app_title: "ada", + default_config: { + storagePath: "$storagePath$", + language: "zh", + "common.theme": "auto", + "desktop:wallpaper": "", + "editor.bg": "", + "editor.logoType": "logo", + "editor.fontFamily": "Cascadia Mono, Consolas, 'Courier New', monospace", + "update.repo": "wood-desktop", + "update.owner": "npmrun", + "update.allowDowngrade": false, + "update.allowPrerelease": false, + }, +} as IConfig diff --git a/electron-builder.yml b/electron-builder.yml index 97d7126..a3235c8 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -1,45 +1,45 @@ appId: com.electron.app productName: my-app directories: - buildResources: build + buildResources: build files: - - '!**/.vscode/*' - - '!src/*' - - '!electron.vite.config.{js,ts,mjs,cjs}' - - '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' - - '!{.env,.env.*,.npmrc,pnpm-lock.yaml}' - - '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}' + - "!**/.vscode/*" + - "!src/*" + - "!electron.vite.config.{js,ts,mjs,cjs}" + - "!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}" + - "!{.env,.env.*,.npmrc,pnpm-lock.yaml}" + - "!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}" asarUnpack: - - resources/** + - resources/** win: - executableName: my-app + executableName: my-app nsis: - artifactName: ${name}-${version}-setup.${ext} - shortcutName: ${productName} - uninstallDisplayName: ${productName} - createDesktopShortcut: always + artifactName: ${name}-${version}-setup.${ext} + shortcutName: ${productName} + uninstallDisplayName: ${productName} + createDesktopShortcut: always mac: - entitlementsInherit: build/entitlements.mac.plist - extendInfo: - - NSCameraUsageDescription: Application requests access to the device's camera. - - NSMicrophoneUsageDescription: Application requests access to the device's microphone. - - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. - - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. - notarize: false + entitlementsInherit: build/entitlements.mac.plist + extendInfo: + - NSCameraUsageDescription: Application requests access to the device's camera. + - NSMicrophoneUsageDescription: Application requests access to the device's microphone. + - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. + - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. + notarize: false dmg: - artifactName: ${name}-${version}.${ext} + artifactName: ${name}-${version}.${ext} linux: - target: - - AppImage - - snap - - deb - maintainer: electronjs.org - category: Utility + target: + - AppImage + - snap + - deb + maintainer: electronjs.org + category: Utility appImage: - artifactName: ${name}-${version}.${ext} + artifactName: ${name}-${version}.${ext} npmRebuild: false publish: - provider: generic - url: https://example.com/auto-updates + provider: generic + url: https://example.com/auto-updates electronDownload: - mirror: https://npmmirror.com/mirrors/electron/ + mirror: https://npmmirror.com/mirrors/electron/ diff --git a/electron.vite.config.ts b/electron.vite.config.ts index b662fe9..1870ac4 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -1,28 +1,28 @@ -import { resolve } from 'path' -import { defineConfig, externalizeDepsPlugin } from 'electron-vite' -import vue from '@vitejs/plugin-vue' -import UnoCSS from 'unocss/vite' +import { resolve } from "path" +import { defineConfig, externalizeDepsPlugin } from "electron-vite" +import vue from "@vitejs/plugin-vue" +import UnoCSS from "unocss/vite" export default defineConfig({ - main: { - resolve: { - alias: { - config: resolve('config'), - vc: resolve('src/main'), - res: resolve('resources') - } + main: { + resolve: { + alias: { + config: resolve("config"), + vc: resolve("src/main"), + res: resolve("resources"), + }, + }, + plugins: [externalizeDepsPlugin()], }, - plugins: [externalizeDepsPlugin()] - }, - preload: { - plugins: [externalizeDepsPlugin()] - }, - renderer: { - resolve: { - alias: { - '@renderer': resolve('src/renderer/src') - } + preload: { + plugins: [externalizeDepsPlugin()], + }, + renderer: { + resolve: { + alias: { + "@renderer": resolve("src/renderer/src"), + }, + }, + plugins: [UnoCSS(), vue()], }, - plugins: [UnoCSS(), vue()] - } }) diff --git a/package.json b/package.json index 4d8523d..dfd8e39 100644 --- a/package.json +++ b/package.json @@ -1,56 +1,56 @@ { - "name": "my-app", - "type": "module", - "version": "1.0.0", - "description": "An Electron application with Vue and TypeScript", - "main": "./out/main/index.js", - "author": "example.com", - "homepage": "https://electron-vite.org", - "scripts": { - "format": "prettier --write .", - "lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix", - "typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false", - "typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false", - "typecheck": "npm run typecheck:node && npm run typecheck:web", - "start": "electron-vite preview", - "dev": "electron-vite dev", - "dev:watch": "electron-vite dev --watch", - "build": "npm run typecheck && electron-vite build", - "postinstall": "electron-builder install-app-deps", - "build:unpack": "npm run build && electron-builder --dir", - "build:win": "npm run build && electron-builder --win", - "build:mac": "npm run build && electron-builder --mac", - "build:linux": "npm run build && electron-builder --linux" - }, - "dependencies": { - "@electron-toolkit/preload": "^3.0.0", - "@electron-toolkit/utils": "^3.0.0", - "@unocss/reset": "^0.64.1", - "electron-updater": "^6.1.7", - "inversify": "^6.1.4", - "lowdb": "^7.0.1", - "reflect-metadata": "^0.2.2" - }, - "devDependencies": { - "@electron-toolkit/eslint-config": "^1.0.2", - "@electron-toolkit/eslint-config-ts": "^2.0.0", - "@electron-toolkit/tsconfig": "^1.0.1", - "@rushstack/eslint-patch": "^1.10.3", - "@types/node": "^20.14.8", - "@unocss/preset-rem-to-px": "^0.64.1", - "@vitejs/plugin-vue": "^5.0.5", - "@vue/eslint-config-prettier": "^9.0.0", - "@vue/eslint-config-typescript": "^13.0.0", - "electron": "^31.0.2", - "electron-builder": "^24.13.3", - "electron-vite": "^2.3.0", - "eslint": "^8.57.0", - "eslint-plugin-vue": "^9.26.0", - "prettier": "^3.3.2", - "typescript": "^5.5.2", - "unocss": "^0.64.1", - "vite": "^5.3.1", - "vue": "^3.4.30", - "vue-tsc": "^2.0.22" - } + "name": "my-app", + "type": "module", + "version": "1.0.0", + "description": "An Electron application with Vue and TypeScript", + "main": "./out/main/index.js", + "author": "example.com", + "homepage": "https://electron-vite.org", + "scripts": { + "format": "prettier --write .", + "lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix", + "typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false", + "typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false", + "typecheck": "npm run typecheck:node && npm run typecheck:web", + "start": "electron-vite preview", + "dev": "electron-vite dev", + "dev:watch": "electron-vite dev --watch", + "build": "npm run typecheck && electron-vite build", + "postinstall": "electron-builder install-app-deps", + "build:unpack": "npm run build && electron-builder --dir", + "build:win": "npm run build && electron-builder --win", + "build:mac": "npm run build && electron-builder --mac", + "build:linux": "npm run build && electron-builder --linux" + }, + "dependencies": { + "@electron-toolkit/preload": "^3.0.0", + "@electron-toolkit/utils": "^3.0.0", + "@unocss/reset": "^0.64.1", + "electron-updater": "^6.1.7", + "inversify": "^6.1.4", + "lowdb": "^7.0.1", + "reflect-metadata": "^0.2.2" + }, + "devDependencies": { + "@electron-toolkit/eslint-config": "^1.0.2", + "@electron-toolkit/eslint-config-ts": "^2.0.0", + "@electron-toolkit/tsconfig": "^1.0.1", + "@rushstack/eslint-patch": "^1.10.3", + "@types/node": "^20.14.8", + "@unocss/preset-rem-to-px": "^0.64.1", + "@vitejs/plugin-vue": "^5.0.5", + "@vue/eslint-config-prettier": "^9.0.0", + "@vue/eslint-config-typescript": "^13.0.0", + "electron": "^31.0.2", + "electron-builder": "^24.13.3", + "electron-vite": "^2.3.0", + "eslint": "^8.57.0", + "eslint-plugin-vue": "^9.26.0", + "prettier": "^3.3.2", + "typescript": "^5.5.2", + "unocss": "^0.64.1", + "vite": "^5.3.1", + "vue": "^3.4.30", + "vue-tsc": "^2.0.22" + } } diff --git a/src/main/base/base.ts b/src/main/base/base.ts index 222ba99..44849ab 100644 --- a/src/main/base/base.ts +++ b/src/main/base/base.ts @@ -1,3 +1,3 @@ -abstract class Base{ - constructor(){} -} \ No newline at end of file +abstract class Base { + constructor() {} +} diff --git a/src/main/index.ts b/src/main/index.ts index 66650e8..00dc8e4 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,78 +1,78 @@ -import "reflect-metadata"; -import { app, shell, BrowserWindow, ipcMain } from 'electron' -import { join } from 'path' -import { electronApp, optimizer, is } from '@electron-toolkit/utils' -import icon from 'res/icon.png?asset' -import { container } from 'vc/modules' -import { App } from 'vc/modules/App' +import "reflect-metadata" +import { app, shell, BrowserWindow, ipcMain } from "electron" +import { join } from "path" +import { electronApp, optimizer, is } from "@electron-toolkit/utils" +import icon from "res/icon.png?asset" +import { container } from "vc/modules" +import { App } from "vc/modules/App" container.get(App).init() function createWindow(): void { - // Create the browser window. - const mainWindow = new BrowserWindow({ - width: 900, - height: 670, - show: false, - autoHideMenuBar: true, - ...(process.platform === 'linux' ? { icon } : {}), - webPreferences: { - preload: join(__dirname, '../preload/index.mjs'), - sandbox: false - } - }) + // Create the browser window. + const mainWindow = new BrowserWindow({ + width: 900, + height: 670, + show: false, + autoHideMenuBar: true, + ...(process.platform === "linux" ? { icon } : {}), + webPreferences: { + preload: join(__dirname, "../preload/index.mjs"), + sandbox: false, + }, + }) - mainWindow.on('ready-to-show', () => { - mainWindow.show() - }) + mainWindow.on("ready-to-show", () => { + mainWindow.show() + }) - mainWindow.webContents.setWindowOpenHandler((details) => { - shell.openExternal(details.url) - return { action: 'deny' } - }) + mainWindow.webContents.setWindowOpenHandler(details => { + shell.openExternal(details.url) + return { action: "deny" } + }) - // HMR for renderer base on electron-vite cli. - // Load the remote URL for development or the local html file for production. - if (is.dev && process.env['ELECTRON_RENDERER_URL']) { - mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) - } else { - mainWindow.loadFile(join(__dirname, '../renderer/index.html')) - } + // HMR for renderer base on electron-vite cli. + // Load the remote URL for development or the local html file for production. + if (is.dev && process.env["ELECTRON_RENDERER_URL"]) { + mainWindow.loadURL(process.env["ELECTRON_RENDERER_URL"]) + } else { + mainWindow.loadFile(join(__dirname, "../renderer/index.html")) + } } // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.whenReady().then(() => { - // Set app user model id for windows - electronApp.setAppUserModelId('com.electron') + // Set app user model id for windows + electronApp.setAppUserModelId("com.electron") - // Default open or close DevTools by F12 in development - // and ignore CommandOrControl + R in production. - // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils - app.on('browser-window-created', (_, window) => { - optimizer.watchWindowShortcuts(window) - }) + // Default open or close DevTools by F12 in development + // and ignore CommandOrControl + R in production. + // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils + app.on("browser-window-created", (_, window) => { + optimizer.watchWindowShortcuts(window) + }) - // IPC test - ipcMain.on('ping', () => console.log(icon)) + // IPC test + ipcMain.on("ping", () => console.log(icon)) - createWindow() + createWindow() - app.on('activate', function () { - // On macOS it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (BrowserWindow.getAllWindows().length === 0) createWindow() - }) + app.on("activate", function () { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (BrowserWindow.getAllWindows().length === 0) createWindow() + }) }) // Quit when all windows are closed, except on macOS. There, it's common // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') { - app.quit() - } +app.on("window-all-closed", () => { + if (process.platform !== "darwin") { + app.quit() + } }) // In this file you can include the rest of your app"s specific main process diff --git a/src/main/modules/App.ts b/src/main/modules/App.ts index fb20760..ff870ba 100644 --- a/src/main/modules/App.ts +++ b/src/main/modules/App.ts @@ -1,31 +1,25 @@ -import { injectable, inject } from "inversify" -import Setting from "./setting" -import DB from "./db" - - -@injectable() -class App { - private _setting: Setting - private _db: DB - - constructor( - @inject(Setting) setting: Setting, - @inject(DB) db: DB, - ) { - console.log(`App inited`); - - this._setting = setting - this._db = db - } - - async init() { - console.log(this._setting.config()); - this._db.saveData("aaa", { a: 123123 }) - console.log(await this._db.getData("aaa")); - } -} - -export default App -export { - App -} \ No newline at end of file +import { injectable, inject } from "inversify" +import Setting from "./setting" +import DB from "./db" + +@injectable() +class App { + private _setting: Setting + private _db: DB + + constructor(@inject(Setting) setting: Setting, @inject(DB) db: DB) { + console.log(`App inited`) + + this._setting = setting + this._db = db + } + + async init() { + console.log(this._setting.config()) + this._db.saveData("aaa", { a: 123123 }) + console.log(await this._db.getData("aaa")) + } +} + +export default App +export { App } diff --git a/src/main/modules/db/custom.ts b/src/main/modules/db/custom.ts index 8737440..14c5f23 100644 --- a/src/main/modules/db/custom.ts +++ b/src/main/modules/db/custom.ts @@ -1,33 +1,33 @@ -import { JSONFile } from "lowdb/node" -import { Low } from 'lowdb' -import fs from 'fs-extra' - -export class CustomAdapter extends JSONFile { - constructor(filepath: string) { - super(filepath) - this.filepath = filepath - } - filepath: string = '' - async read() { - if (!fs.existsSync(this.filepath)) { - return null - } - let data = fs.readJSONSync(this.filepath, { throws: false }) - if (!data) { - return null - } - return data - } - - async write(data: T) { - fs.ensureFileSync(this.filepath) - await super.write(data) - } -} -export class CustomLow extends Low { - constructor(adapter: CustomAdapter, defaultData: T) { - super(adapter, defaultData) - this.filepath = adapter.filepath - } - filepath: string = '' -} \ No newline at end of file +import { JSONFile } from "lowdb/node" +import { Low } from "lowdb" +import fs from "fs-extra" + +export class CustomAdapter extends JSONFile { + constructor(filepath: string) { + super(filepath) + this.filepath = filepath + } + filepath: string = "" + async read() { + if (!fs.existsSync(this.filepath)) { + return null + } + const data = fs.readJSONSync(this.filepath, { throws: false }) + if (!data) { + return null + } + return data + } + + async write(data: T) { + fs.ensureFileSync(this.filepath) + await super.write(data) + } +} +export class CustomLow extends Low { + constructor(adapter: CustomAdapter, defaultData: T) { + super(adapter, defaultData) + this.filepath = adapter.filepath + } + filepath: string = "" +} diff --git a/src/main/modules/db/index.ts b/src/main/modules/db/index.ts index e1f10e5..f764847 100644 --- a/src/main/modules/db/index.ts +++ b/src/main/modules/db/index.ts @@ -1,76 +1,74 @@ -import { inject, injectable } from "inversify"; -import Setting from "../setting"; -import { CustomAdapter, CustomLow } from "./custom"; -import path from "node:path"; - -@injectable() -class DB { - private _setting: Setting - Modules: Record> = {} - - constructor(@inject(Setting) setting: Setting) { - console.log(`DB inited`); - - this._setting = setting - } - - create(filepath) { - let adapter = new CustomAdapter(filepath) - const db = new CustomLow<{}>(adapter, {}) - db.filepath = filepath - return db - } - - getDB(dbName: string) { - if (this.Modules[dbName] === undefined) { - let filepath = path.resolve(this._setting.values("storagePath"), './db/' + dbName + '.json') - this.Modules[dbName] = this.create(filepath) - return this.Modules[dbName] - } else { - let cur = this.Modules[dbName] - let filepath = path.resolve(this._setting.values("storagePath"), './db/' + dbName + '.json') - if (cur.filepath != filepath) { - this.Modules[dbName] = this.create(filepath) - } - return this.Modules[dbName] - } - } - - async saveData(data: any): Promise - async saveData(dbName: string, data: any): Promise - async saveData(dbName: string, data?: any): Promise { - let db, rData - if (arguments.length === 2) { - db = this.getDB(dbName) - rData = data - } else { - db = this.getDB('db') - rData = dbName - } - if (db) { - db.data = rData - await db.write() - return db.data - } - return null - } - - async getData(dbName?: string) { - let db - if (dbName) { - db = this.getDB(dbName) - } else { - db = this.getDB('db') - } - if (db) { - await db.read() - return db.data - } - return null - } -} - -export default DB -export { - DB -} \ No newline at end of file +import { inject, injectable } from "inversify" +import Setting from "../setting" +import { CustomAdapter, CustomLow } from "./custom" +import path from "node:path" + +@injectable() +class DB { + private _setting: Setting + Modules: Record> = {} + + constructor(@inject(Setting) setting: Setting) { + console.log(`DB inited`) + + this._setting = setting + } + + create(filepath) { + const adapter = new CustomAdapter(filepath) + const db = new CustomLow(adapter, {}) + db.filepath = filepath + return db + } + + getDB(dbName: string) { + if (this.Modules[dbName] === undefined) { + const filepath = path.resolve(this._setting.values("storagePath"), "./db/" + dbName + ".json") + this.Modules[dbName] = this.create(filepath) + return this.Modules[dbName] + } else { + const cur = this.Modules[dbName] + const filepath = path.resolve(this._setting.values("storagePath"), "./db/" + dbName + ".json") + if (cur.filepath != filepath) { + this.Modules[dbName] = this.create(filepath) + } + return this.Modules[dbName] + } + } + + async saveData(data: any): Promise + async saveData(dbName: string, data: any): Promise + async saveData(dbName: string, data?: any): Promise { + let db, rData + if (arguments.length === 2) { + db = this.getDB(dbName) + rData = data + } else { + db = this.getDB("db") + rData = dbName + } + if (db) { + db.data = rData + await db.write() + return db.data + } + return null + } + + async getData(dbName?: string) { + let db + if (dbName) { + db = this.getDB(dbName) + } else { + db = this.getDB("db") + } + if (db) { + await db.read() + return db.data + } + return null + } +} + +export default DB +export { DB } diff --git a/src/main/modules/index.ts b/src/main/modules/index.ts index 1d3d7d5..19c142e 100644 --- a/src/main/modules/index.ts +++ b/src/main/modules/index.ts @@ -1,11 +1,9 @@ -import { Container } from "inversify" -import module from "./module" - -const container = new Container() - -container.load(module) - -export default container -export { - container -} \ No newline at end of file +import { Container } from "inversify" +import module from "./module" + +const container = new Container() + +container.load(module) + +export default container +export { container } diff --git a/src/main/modules/module.ts b/src/main/modules/module.ts index 2e74a13..da41a5f 100644 --- a/src/main/modules/module.ts +++ b/src/main/modules/module.ts @@ -1,15 +1,13 @@ -import { ContainerModule } from "inversify" -import { Setting } from "./setting" -import { DB } from "./db" -import App from "./App" - -const module = new ContainerModule((bind) => { - bind(Setting).toConstantValue(new Setting()) - bind(DB).toSelf().inSingletonScope() - bind(App).toSelf().inSingletonScope() -}) - -export default module -export { - module -} \ No newline at end of file +import { ContainerModule } from "inversify" +import { Setting } from "./setting" +import { DB } from "./db" +import App from "./App" + +const module = new ContainerModule(bind => { + bind(Setting).toConstantValue(new Setting()) + bind(DB).toSelf().inSingletonScope() + bind(App).toSelf().inSingletonScope() +}) + +export default module +export { module } diff --git a/src/main/modules/setting/index.ts b/src/main/modules/setting/index.ts index 9a34c94..9b0d92c 100644 --- a/src/main/modules/setting/index.ts +++ b/src/main/modules/setting/index.ts @@ -1,233 +1,226 @@ -import fs from "fs-extra" -import { app } from "electron" -import path from "path" -import { cloneDeep } from "lodash" -import { injectable } from "inversify" -import Config from "config" - -type IConfig = typeof Config.default_config - -type IOnFunc = (n: IConfig, c: IConfig, keys?: (keyof IConfig)[]) => void -type IT = (keyof IConfig)[] | keyof IConfig | "_" - -let storagePath = path.join(app.getPath("documents"), Config.app_title) -let storagePathDev = path.join(app.getPath("documents"), Config.app_title + "-dev") - -if (process.env.NODE_ENV === "development") { - storagePath = storagePathDev -} - -let _tempConfig = cloneDeep(Config.default_config as IConfig) -Object.keys(_tempConfig).forEach(key => { - if (typeof _tempConfig[key] === "string" && _tempConfig[key].includes("$storagePath$")) { - _tempConfig[key] = _tempConfig[key].replace(/\$storagePath\$/g, storagePath) - if (_tempConfig[key] && path.isAbsolute(_tempConfig[key])) { - _tempConfig[key] = path.normalize(_tempConfig[key]) - } - } -}) - -function isPath(str) { - // 使用正则表达式检查字符串是否以斜杠或盘符开头 - return /^(?:\/|[a-zA-Z]:\\)/.test(str); -} - -function init(config: IConfig) { - // 在配置初始化后执行 - Object.keys(config).forEach(key => { - if (config[key] && isPath(config[key]) && path.isAbsolute(config[key])) { - fs.ensureDirSync(config[key]) - } - }) - // 在配置初始化后执行 - // fs.ensureDirSync(config["snippet.storagePath"]) - // fs.ensureDirSync(config["bookmark.storagePath"]) -} - -// 判断是否是空文件夹 -function isEmptyDir(fPath: string) { - var pa = fs.readdirSync(fPath) - if (pa.length === 0) { - return true - } else { - return false - } -} - -@injectable() -class Setting { - constructor() { - console.log(`Setting inited`); - - this.#init() - } - #cb: [IT, IOnFunc][] = [] - - onChange(fn: IOnFunc, that?: any) - onChange(key: IT, fn: IOnFunc, that?: any) - onChange(fnOrType: IT | IOnFunc, fnOrThat: IOnFunc | any = null, that: any = null) { - if (typeof fnOrType === "function") { - this.#cb.push(["_", fnOrType.bind(fnOrThat)]) - } else { - this.#cb.push([fnOrType, fnOrThat.bind(that)]) - } - } - - #runCB(n: IConfig, c: IConfig, keys: (keyof IConfig)[]) { - for (let i = 0; i < this.#cb.length; i++) { - const temp = this.#cb[i] - const k = temp[0] - const fn = temp[1] - if (k === "_") { - fn(n, c, keys) - } - if (typeof k === "string" && keys.includes(k as keyof IConfig)) { - fn(n, c) - } - if (Array.isArray(k) && k.filter(v => keys.indexOf(v) !== -1).length) { - fn(n, c) - } - } - } - - #pathFile: string = process.env.NODE_ENV === "development" ? path.resolve(app.getPath("userData"), "./config_path-dev") : path.resolve(app.getPath("userData"), "./config_path") - #config: IConfig = cloneDeep(_tempConfig) - #configPath(storagePath?: string): string { - return path.join(storagePath || this.#config.storagePath, "./config.json") - } - /** - * 读取配置文件变量同步 - * @param confingPath 配置文件路径 - */ - #syncVar(confingPath?: string) { - const configFile = this.#configPath(confingPath) - if (!fs.pathExistsSync(configFile)) { - fs.ensureFileSync(configFile) - fs.writeJSONSync(configFile, {}) - } - const config = fs.readJSONSync(configFile) as IConfig - confingPath && (config.storagePath = confingPath) - // 优先取本地的值 - for (const key in config) { - // if (Object.prototype.hasOwnProperty.call(this.#config, key)) { - // this.#config[key] = config[key] || this.#config[key] - // } - // 删除配置时本地的配置不会改变,想一下哪种方式更好 - this.#config[key] = config[key] || this.#config[key] - } - } - #init() { - console.log(`位置:${this.#pathFile}`) - if (fs.pathExistsSync(this.#pathFile)) { - const confingPath = fs.readFileSync(this.#pathFile, { encoding: "utf8" }) - if (confingPath && fs.pathExistsSync(this.#configPath(confingPath))) { - this.#syncVar(confingPath) - // 防止增加了配置本地却没变的情况 - this.#sync(confingPath) - } else { - this.#syncVar(confingPath) - this.#sync(confingPath) - } - } else { - this.#syncVar() - this.#sync() - } - init.call(this, this.#config) - } - config() { - return this.#config - } - #sync(c?: string) { - const config = cloneDeep(this.#config) - delete config.storagePath - const p = this.#configPath(c) - fs.ensureFileSync(p) - fs.writeJSONSync(this.#configPath(c), config) - } - #change(p: string) { - const storagePath = this.#config.storagePath - if (fs.existsSync(storagePath) && !fs.existsSync(p)) { - fs.moveSync(storagePath, p) - } - if (fs.existsSync(p) && fs.existsSync(storagePath) && isEmptyDir(p)) { - console.log("文件夹为空,直接覆盖") - fs.moveSync(storagePath, p, { overwrite: true }) - } - fs.writeFileSync(this.#pathFile, p, { encoding: "utf8" }) - } - reset(key: keyof IConfig) { - this.set(key, cloneDeep(_tempConfig[key])) - } - set(key: keyof IConfig | Partial, value?: any) { - let oldMainConfig = Object.assign({}, this.#config) - let isChange = false - let changeKeys: (keyof IConfig)[] = [] - let canChangeStorage = (targetPath: string) => { - if (fs.existsSync(oldMainConfig.storagePath) && fs.existsSync(targetPath) && !isEmptyDir(targetPath)) { - if (fs.existsSync(path.join(targetPath, "./config.json"))) { - return true - } - return false - } - return true - } - if (typeof key === "string") { - if (value != undefined && value !== this.#config[key]) { - if (key === "storagePath") { - if (!canChangeStorage(value)) { - throw "无法改变存储地址" - return - } - try { - this.#change(value) - } catch (error) { - throw error - } - changeKeys.push("storagePath") - this.#config["storagePath"] = value - } else { - changeKeys.push(key) - this.#config[key as string] = value - } - isChange = true - } - } else { - if (key['storagePath'] !== undefined && key['storagePath'] !== this.#config['storagePath']) { - if (!canChangeStorage(key['storagePath'])) { - throw "无法改变存储地址" - return - } - try { - this.#change(key['storagePath']) - } catch (error) { - throw error - } - this.#config['storagePath'] = key['storagePath'] - changeKeys.push('storagePath') - isChange = true - } - for (const _ in key as any) { - if (Object.prototype.hasOwnProperty.call(key, _)) { - const v = key[_] - if (v != undefined && _ !== "storagePath" && v !== this.#config[_]) { - this.#config[_] = v - changeKeys.push(_ as keyof IConfig) - isChange = true - } - } - } - } - if (isChange) { - this.#sync() - this.#runCB(this.#config, oldMainConfig, changeKeys) - } - } - values(key: T): IConfig[T] { - return this.#config[key] - } -} - -export default Setting -export { - Setting -} \ No newline at end of file +import fs from "fs-extra" +import { app } from "electron" +import path from "path" +import { cloneDeep } from "lodash" +import { injectable } from "inversify" +import Config from "config" + +type IConfig = typeof Config.default_config + +type IOnFunc = (n: IConfig, c: IConfig, keys?: (keyof IConfig)[]) => void +type IT = (keyof IConfig)[] | keyof IConfig | "_" + +let storagePath = path.join(app.getPath("documents"), Config.app_title) +const storagePathDev = path.join(app.getPath("documents"), Config.app_title + "-dev") + +if (process.env.NODE_ENV === "development") { + storagePath = storagePathDev +} + +const _tempConfig = cloneDeep(Config.default_config as IConfig) +Object.keys(_tempConfig).forEach(key => { + if (typeof _tempConfig[key] === "string" && _tempConfig[key].includes("$storagePath$")) { + _tempConfig[key] = _tempConfig[key].replace(/\$storagePath\$/g, storagePath) + if (_tempConfig[key] && path.isAbsolute(_tempConfig[key])) { + _tempConfig[key] = path.normalize(_tempConfig[key]) + } + } +}) + +function isPath(str) { + // 使用正则表达式检查字符串是否以斜杠或盘符开头 + return /^(?:\/|[a-zA-Z]:\\)/.test(str) +} + +function init(config: IConfig) { + // 在配置初始化后执行 + Object.keys(config).forEach(key => { + if (config[key] && isPath(config[key]) && path.isAbsolute(config[key])) { + fs.ensureDirSync(config[key]) + } + }) + // 在配置初始化后执行 + // fs.ensureDirSync(config["snippet.storagePath"]) + // fs.ensureDirSync(config["bookmark.storagePath"]) +} + +// 判断是否是空文件夹 +function isEmptyDir(fPath: string) { + const pa = fs.readdirSync(fPath) + if (pa.length === 0) { + return true + } else { + return false + } +} + +@injectable() +class Setting { + constructor() { + console.log(`Setting inited`) + + this.#init() + } + #cb: [IT, IOnFunc][] = [] + + onChange(fn: IOnFunc, that?: any) + onChange(key: IT, fn: IOnFunc, that?: any) + onChange(fnOrType: IT | IOnFunc, fnOrThat: IOnFunc | any = null, that: any = null) { + if (typeof fnOrType === "function") { + this.#cb.push(["_", fnOrType.bind(fnOrThat)]) + } else { + this.#cb.push([fnOrType, fnOrThat.bind(that)]) + } + } + + #runCB(n: IConfig, c: IConfig, keys: (keyof IConfig)[]) { + for (let i = 0; i < this.#cb.length; i++) { + const temp = this.#cb[i] + const k = temp[0] + const fn = temp[1] + if (k === "_") { + fn(n, c, keys) + } + if (typeof k === "string" && keys.includes(k as keyof IConfig)) { + fn(n, c) + } + if (Array.isArray(k) && k.filter(v => keys.indexOf(v) !== -1).length) { + fn(n, c) + } + } + } + + #pathFile: string = + process.env.NODE_ENV === "development" + ? path.resolve(app.getPath("userData"), "./config_path-dev") + : path.resolve(app.getPath("userData"), "./config_path") + #config: IConfig = cloneDeep(_tempConfig) + #configPath(storagePath?: string): string { + return path.join(storagePath || this.#config.storagePath, "./config.json") + } + /** + * 读取配置文件变量同步 + * @param confingPath 配置文件路径 + */ + #syncVar(confingPath?: string) { + const configFile = this.#configPath(confingPath) + if (!fs.pathExistsSync(configFile)) { + fs.ensureFileSync(configFile) + fs.writeJSONSync(configFile, {}) + } + const config = fs.readJSONSync(configFile) as IConfig + confingPath && (config.storagePath = confingPath) + // 优先取本地的值 + for (const key in config) { + // if (Object.prototype.hasOwnProperty.call(this.#config, key)) { + // this.#config[key] = config[key] || this.#config[key] + // } + // 删除配置时本地的配置不会改变,想一下哪种方式更好 + this.#config[key] = config[key] || this.#config[key] + } + } + #init() { + console.log(`位置:${this.#pathFile}`) + if (fs.pathExistsSync(this.#pathFile)) { + const confingPath = fs.readFileSync(this.#pathFile, { encoding: "utf8" }) + if (confingPath && fs.pathExistsSync(this.#configPath(confingPath))) { + this.#syncVar(confingPath) + // 防止增加了配置本地却没变的情况 + this.#sync(confingPath) + } else { + this.#syncVar(confingPath) + this.#sync(confingPath) + } + } else { + this.#syncVar() + this.#sync() + } + init.call(this, this.#config) + } + config() { + return this.#config + } + #sync(c?: string) { + const config = cloneDeep(this.#config) + delete config.storagePath + const p = this.#configPath(c) + fs.ensureFileSync(p) + fs.writeJSONSync(this.#configPath(c), config) + } + #change(p: string) { + const storagePath = this.#config.storagePath + if (fs.existsSync(storagePath) && !fs.existsSync(p)) { + fs.moveSync(storagePath, p) + } + if (fs.existsSync(p) && fs.existsSync(storagePath) && isEmptyDir(p)) { + console.log("文件夹为空,直接覆盖") + fs.moveSync(storagePath, p, { overwrite: true }) + } + fs.writeFileSync(this.#pathFile, p, { encoding: "utf8" }) + } + reset(key: keyof IConfig) { + this.set(key, cloneDeep(_tempConfig[key])) + } + set(key: keyof IConfig | Partial, value?: any) { + const oldMainConfig = Object.assign({}, this.#config) + let isChange = false + const changeKeys: (keyof IConfig)[] = [] + const canChangeStorage = (targetPath: string) => { + if (fs.existsSync(oldMainConfig.storagePath) && fs.existsSync(targetPath) && !isEmptyDir(targetPath)) { + if (fs.existsSync(path.join(targetPath, "./config.json"))) { + return true + } + return false + } + return true + } + if (typeof key === "string") { + if (value != undefined && value !== this.#config[key]) { + if (key === "storagePath") { + if (!canChangeStorage(value)) { + throw "无法改变存储地址" + return + } + this.#change(value) + changeKeys.push("storagePath") + this.#config["storagePath"] = value + } else { + changeKeys.push(key) + this.#config[key as string] = value + } + isChange = true + } + } else { + if (key["storagePath"] !== undefined && key["storagePath"] !== this.#config["storagePath"]) { + if (!canChangeStorage(key["storagePath"])) { + throw "无法改变存储地址" + return + } + this.#change(key["storagePath"]) + this.#config["storagePath"] = key["storagePath"] + changeKeys.push("storagePath") + isChange = true + } + for (const _ in key) { + if (Object.prototype.hasOwnProperty.call(key, _)) { + const v = key[_] + if (v != undefined && _ !== "storagePath" && v !== this.#config[_]) { + this.#config[_] = v + changeKeys.push(_ as keyof IConfig) + isChange = true + } + } + } + } + if (isChange) { + this.#sync() + this.#runCB(this.#config, oldMainConfig, changeKeys) + } + } + values(key: T): IConfig[T] { + return this.#config[key] + } +} + +export default Setting +export { Setting } diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts index a153669..2d45fc3 100644 --- a/src/preload/index.d.ts +++ b/src/preload/index.d.ts @@ -1,8 +1,8 @@ -import { ElectronAPI } from '@electron-toolkit/preload' +import { ElectronAPI } from "@electron-toolkit/preload" declare global { - interface Window { - electron: ElectronAPI - api: unknown - } + interface Window { + electron: ElectronAPI + api: unknown + } } diff --git a/src/preload/index.ts b/src/preload/index.ts index 2d18524..9cf45a0 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -1,5 +1,5 @@ -import { contextBridge } from 'electron' -import { electronAPI } from '@electron-toolkit/preload' +import { contextBridge } from "electron" +import { electronAPI } from "@electron-toolkit/preload" // Custom APIs for renderer const api = {} @@ -8,15 +8,15 @@ const api = {} // renderer only if context isolation is enabled, otherwise // just add to the DOM global. if (process.contextIsolated) { - try { - contextBridge.exposeInMainWorld('electron', electronAPI) - contextBridge.exposeInMainWorld('api', api) - } catch (error) { - console.error(error) - } + try { + contextBridge.exposeInMainWorld("electron", electronAPI) + contextBridge.exposeInMainWorld("api", api) + } catch (error) { + console.error(error) + } } else { - // @ts-ignore (define in dts) - window.electron = electronAPI - // @ts-ignore (define in dts) - window.api = api + // @ts-ignore (define in dts) + window.electron = electronAPI + // @ts-ignore (define in dts) + window.api = api } diff --git a/src/renderer/index.html b/src/renderer/index.html index e3b0ca1..9777bba 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -1,17 +1,17 @@ - - - Electron - - - + + + Electron + + + - -
- - + +
+ + diff --git a/src/renderer/src/App.vue b/src/renderer/src/App.vue index f38fbaa..c3a5ac7 100644 --- a/src/renderer/src/App.vue +++ b/src/renderer/src/App.vue @@ -1,26 +1,30 @@ diff --git a/src/renderer/src/assets/base.css b/src/renderer/src/assets/base.css index 5ed6406..c8dbd6b 100644 --- a/src/renderer/src/assets/base.css +++ b/src/renderer/src/assets/base.css @@ -1,67 +1,67 @@ :root { - --ev-c-white: #ffffff; - --ev-c-white-soft: #f8f8f8; - --ev-c-white-mute: #f2f2f2; + --ev-c-white: #ffffff; + --ev-c-white-soft: #f8f8f8; + --ev-c-white-mute: #f2f2f2; - --ev-c-black: #1b1b1f; - --ev-c-black-soft: #222222; - --ev-c-black-mute: #282828; + --ev-c-black: #1b1b1f; + --ev-c-black-soft: #222222; + --ev-c-black-mute: #282828; - --ev-c-gray-1: #515c67; - --ev-c-gray-2: #414853; - --ev-c-gray-3: #32363f; + --ev-c-gray-1: #515c67; + --ev-c-gray-2: #414853; + --ev-c-gray-3: #32363f; - --ev-c-text-1: rgba(255, 255, 245, 0.86); - --ev-c-text-2: rgba(235, 235, 245, 0.6); - --ev-c-text-3: rgba(235, 235, 245, 0.38); + --ev-c-text-1: rgba(255, 255, 245, 0.86); + --ev-c-text-2: rgba(235, 235, 245, 0.6); + --ev-c-text-3: rgba(235, 235, 245, 0.38); - --ev-button-alt-border: transparent; - --ev-button-alt-text: var(--ev-c-text-1); - --ev-button-alt-bg: var(--ev-c-gray-3); - --ev-button-alt-hover-border: transparent; - --ev-button-alt-hover-text: var(--ev-c-text-1); - --ev-button-alt-hover-bg: var(--ev-c-gray-2); + --ev-button-alt-border: transparent; + --ev-button-alt-text: var(--ev-c-text-1); + --ev-button-alt-bg: var(--ev-c-gray-3); + --ev-button-alt-hover-border: transparent; + --ev-button-alt-hover-text: var(--ev-c-text-1); + --ev-button-alt-hover-bg: var(--ev-c-gray-2); } :root { - --color-background: var(--ev-c-black); - --color-background-soft: var(--ev-c-black-soft); - --color-background-mute: var(--ev-c-black-mute); + --color-background: var(--ev-c-black); + --color-background-soft: var(--ev-c-black-soft); + --color-background-mute: var(--ev-c-black-mute); - --color-text: var(--ev-c-text-1); + --color-text: var(--ev-c-text-1); } *, *::before, *::after { - box-sizing: border-box; - margin: 0; - font-weight: normal; + box-sizing: border-box; + margin: 0; + font-weight: normal; } ul { - list-style: none; + list-style: none; } body { - min-height: 100vh; - color: var(--color-text); - background: var(--color-background); - line-height: 1.6; - font-family: - Inter, - -apple-system, - BlinkMacSystemFont, - 'Segoe UI', - Roboto, - Oxygen, - Ubuntu, - Cantarell, - 'Fira Sans', - 'Droid Sans', - 'Helvetica Neue', - sans-serif; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + line-height: 1.6; + font-family: + Inter, + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + Roboto, + Oxygen, + Ubuntu, + Cantarell, + "Fira Sans", + "Droid Sans", + "Helvetica Neue", + sans-serif; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } diff --git a/src/renderer/src/assets/main.css b/src/renderer/src/assets/main.css index 495aa99..d6907ce 100644 --- a/src/renderer/src/assets/main.css +++ b/src/renderer/src/assets/main.css @@ -1,171 +1,171 @@ -@import './base.css'; +@import "./base.css"; body { - display: flex; - align-items: center; - justify-content: center; - overflow: hidden; - background-image: url('./wavy-lines.svg'); - background-size: cover; - user-select: none; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + background-image: url("./wavy-lines.svg"); + background-size: cover; + user-select: none; } code { - font-weight: 600; - padding: 3px 5px; - border-radius: 2px; - background-color: var(--color-background-mute); - font-family: - ui-monospace, - SFMono-Regular, - SF Mono, - Menlo, - Consolas, - Liberation Mono, - monospace; - font-size: 85%; + font-weight: 600; + padding: 3px 5px; + border-radius: 2px; + background-color: var(--color-background-mute); + font-family: + ui-monospace, + SFMono-Regular, + SF Mono, + Menlo, + Consolas, + Liberation Mono, + monospace; + font-size: 85%; } #app { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - margin-bottom: 80px; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + margin-bottom: 80px; } .logo { - margin-bottom: 20px; - -webkit-user-drag: none; - height: 128px; - width: 128px; - will-change: filter; - transition: filter 300ms; + margin-bottom: 20px; + -webkit-user-drag: none; + height: 128px; + width: 128px; + will-change: filter; + transition: filter 300ms; } .logo:hover { - filter: drop-shadow(0 0 1.2em #6988e6aa); + filter: drop-shadow(0 0 1.2em #6988e6aa); } .creator { - font-size: 14px; - line-height: 16px; - color: var(--ev-c-text-2); - font-weight: 600; - margin-bottom: 10px; + font-size: 14px; + line-height: 16px; + color: var(--ev-c-text-2); + font-weight: 600; + margin-bottom: 10px; } .text { - font-size: 28px; - color: var(--ev-c-text-1); - font-weight: 700; - line-height: 32px; - text-align: center; - margin: 0 10px; - padding: 16px 0; + font-size: 28px; + color: var(--ev-c-text-1); + font-weight: 700; + line-height: 32px; + text-align: center; + margin: 0 10px; + padding: 16px 0; } .tip { - font-size: 16px; - line-height: 24px; - color: var(--ev-c-text-2); - font-weight: 600; + font-size: 16px; + line-height: 24px; + color: var(--ev-c-text-2); + font-weight: 600; } .vue { - background: -webkit-linear-gradient(315deg, #42d392 25%, #647eff); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - font-weight: 700; + background: -webkit-linear-gradient(315deg, #42d392 25%, #647eff); + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-weight: 700; } .ts { - background: -webkit-linear-gradient(315deg, #3178c6 45%, #f0dc4e); - background-clip: text; - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - font-weight: 700; + background: -webkit-linear-gradient(315deg, #3178c6 45%, #f0dc4e); + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-weight: 700; } .actions { - display: flex; - padding-top: 32px; - margin: -6px; - flex-wrap: wrap; - justify-content: flex-start; + display: flex; + padding-top: 32px; + margin: -6px; + flex-wrap: wrap; + justify-content: flex-start; } .action { - flex-shrink: 0; - padding: 6px; + flex-shrink: 0; + padding: 6px; } .action a { - cursor: pointer; - text-decoration: none; - display: inline-block; - border: 1px solid transparent; - text-align: center; - font-weight: 600; - white-space: nowrap; - border-radius: 20px; - padding: 0 20px; - line-height: 38px; - font-size: 14px; - border-color: var(--ev-button-alt-border); - color: var(--ev-button-alt-text); - background-color: var(--ev-button-alt-bg); + cursor: pointer; + text-decoration: none; + display: inline-block; + border: 1px solid transparent; + text-align: center; + font-weight: 600; + white-space: nowrap; + border-radius: 20px; + padding: 0 20px; + line-height: 38px; + font-size: 14px; + border-color: var(--ev-button-alt-border); + color: var(--ev-button-alt-text); + background-color: var(--ev-button-alt-bg); } .action a:hover { - border-color: var(--ev-button-alt-hover-border); - color: var(--ev-button-alt-hover-text); - background-color: var(--ev-button-alt-hover-bg); + border-color: var(--ev-button-alt-hover-border); + color: var(--ev-button-alt-hover-text); + background-color: var(--ev-button-alt-hover-bg); } .versions { - position: absolute; - bottom: 30px; - margin: 0 auto; - padding: 15px 0; - font-family: 'Menlo', 'Lucida Console', monospace; - display: inline-flex; - overflow: hidden; - align-items: center; - border-radius: 22px; - background-color: #202127; - backdrop-filter: blur(24px); + position: absolute; + bottom: 30px; + margin: 0 auto; + padding: 15px 0; + font-family: "Menlo", "Lucida Console", monospace; + display: inline-flex; + overflow: hidden; + align-items: center; + border-radius: 22px; + background-color: #202127; + backdrop-filter: blur(24px); } .versions li { - display: block; - float: left; - border-right: 1px solid var(--ev-c-gray-1); - padding: 0 20px; - font-size: 14px; - line-height: 14px; - opacity: 0.8; - &:last-child { - border: none; - } + display: block; + float: left; + border-right: 1px solid var(--ev-c-gray-1); + padding: 0 20px; + font-size: 14px; + line-height: 14px; + opacity: 0.8; + &:last-child { + border: none; + } } @media (max-width: 720px) { - .text { - font-size: 20px; - } + .text { + font-size: 20px; + } } @media (max-width: 620px) { - .versions { - display: none; - } + .versions { + display: none; + } } @media (max-width: 350px) { - .tip, - .actions { - display: none; - } + .tip, + .actions { + display: none; + } } diff --git a/src/renderer/src/components/Versions.vue b/src/renderer/src/components/Versions.vue index c72967a..73e5785 100644 --- a/src/renderer/src/components/Versions.vue +++ b/src/renderer/src/components/Versions.vue @@ -1,13 +1,13 @@ diff --git a/src/renderer/src/env.d.ts b/src/renderer/src/env.d.ts index aafef95..6e57274 100644 --- a/src/renderer/src/env.d.ts +++ b/src/renderer/src/env.d.ts @@ -1,8 +1,8 @@ /// -declare module '*.vue' { - import type { DefineComponent } from 'vue' - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types - const component: DefineComponent<{}, {}, any> - export default component +declare module "*.vue" { + import type { DefineComponent } from "vue" + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types + const component: DefineComponent<{}, {}, any> + export default component } diff --git a/src/renderer/src/main.ts b/src/renderer/src/main.ts index a08846f..1ecb799 100644 --- a/src/renderer/src/main.ts +++ b/src/renderer/src/main.ts @@ -1,8 +1,8 @@ -import 'virtual:uno.css' -import '@unocss/reset/normalize.css' -import './assets/main.css' +import "virtual:uno.css" +import "@unocss/reset/normalize.css" +import "./assets/main.css" -import { createApp } from 'vue' -import App from './App.vue' +import { createApp } from "vue" +import App from "./App.vue" -createApp(App).mount('#app') +createApp(App).mount("#app") diff --git a/src/renderer/src/shims.d.ts b/src/renderer/src/shims.d.ts index 6b91b5b..53b5860 100644 --- a/src/renderer/src/shims.d.ts +++ b/src/renderer/src/shims.d.ts @@ -1,5 +1,5 @@ -import type { AttributifyAttributes } from '@unocss/preset-attributify' - -declare module '@vue/runtime-dom' { - interface HTMLAttributes extends AttributifyAttributes { } -} \ No newline at end of file +import type { AttributifyAttributes } from "@unocss/preset-attributify" + +declare module "@vue/runtime-dom" { + interface HTMLAttributes extends AttributifyAttributes {} +} diff --git a/uno.config.ts b/uno.config.ts index 9049819..b2036fa 100644 --- a/uno.config.ts +++ b/uno.config.ts @@ -1,10 +1,6 @@ -import { defineConfig, presetAttributify, presetUno } from 'unocss' -import presetRemToPx from '@unocss/preset-rem-to-px' - -export default defineConfig({ - presets: [ - presetAttributify(), - presetUno(), - presetRemToPx(), - ], -}) \ No newline at end of file +import { defineConfig, presetAttributify, presetUno } from "unocss" +import presetRemToPx from "@unocss/preset-rem-to-px" + +export default defineConfig({ + presets: [presetAttributify(), presetUno(), presetRemToPx()], +})