27 changed files with 867 additions and 886 deletions
@ -1,3 +1,3 @@ |
|||||
{ |
{ |
||||
"recommendations": ["dbaeumer.vscode-eslint"] |
"recommendations": ["dbaeumer.vscode-eslint"] |
||||
} |
} |
||||
|
@ -1,39 +1,39 @@ |
|||||
{ |
{ |
||||
"version": "0.2.0", |
"version": "0.2.0", |
||||
"configurations": [ |
"configurations": [ |
||||
{ |
{ |
||||
"name": "Debug Main Process", |
"name": "Debug Main Process", |
||||
"type": "node", |
"type": "node", |
||||
"request": "launch", |
"request": "launch", |
||||
"cwd": "${workspaceRoot}", |
"cwd": "${workspaceRoot}", |
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite", |
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite", |
||||
"windows": { |
"windows": { |
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd" |
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd" |
||||
}, |
}, |
||||
"runtimeArgs": ["--sourcemap"], |
"runtimeArgs": ["--sourcemap"], |
||||
"env": { |
"env": { |
||||
"REMOTE_DEBUGGING_PORT": "9222" |
"REMOTE_DEBUGGING_PORT": "9222" |
||||
} |
} |
||||
}, |
}, |
||||
{ |
{ |
||||
"name": "Debug Renderer Process", |
"name": "Debug Renderer Process", |
||||
"port": 9222, |
"port": 9222, |
||||
"request": "attach", |
"request": "attach", |
||||
"type": "chrome", |
"type": "chrome", |
||||
"webRoot": "${workspaceFolder}/src/renderer", |
"webRoot": "${workspaceFolder}/src/renderer", |
||||
"timeout": 60000, |
"timeout": 60000, |
||||
"presentation": { |
"presentation": { |
||||
"hidden": true |
"hidden": true |
||||
} |
} |
||||
} |
} |
||||
], |
], |
||||
"compounds": [ |
"compounds": [ |
||||
{ |
{ |
||||
"name": "Debug All", |
"name": "Debug All", |
||||
"configurations": ["Debug Main Process", "Debug Renderer Process"], |
"configurations": ["Debug Main Process", "Debug Renderer Process"], |
||||
"presentation": { |
"presentation": { |
||||
"order": 1 |
"order": 1 |
||||
} |
} |
||||
} |
} |
||||
] |
] |
||||
} |
} |
||||
|
@ -1,11 +1,11 @@ |
|||||
{ |
{ |
||||
"[typescript]": { |
"[typescript]": { |
||||
"editor.defaultFormatter": "vscode.typescript-language-features" |
"editor.defaultFormatter": "vscode.typescript-language-features" |
||||
}, |
}, |
||||
"[javascript]": { |
"[javascript]": { |
||||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
"editor.defaultFormatter": "esbenp.prettier-vscode" |
||||
}, |
}, |
||||
"[json]": { |
"[json]": { |
||||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
"editor.defaultFormatter": "esbenp.prettier-vscode" |
||||
} |
} |
||||
} |
} |
||||
|
@ -1,35 +1,35 @@ |
|||||
interface IConfig { |
interface IConfig { |
||||
app_title: string, |
app_title: string |
||||
default_config: { |
default_config: { |
||||
language: "zh" | "en" // i18n
|
language: "zh" | "en" // i18n
|
||||
"common.theme": "light" | "dark" | "auto" // 主题
|
"common.theme": "light" | "dark" | "auto" // 主题
|
||||
"desktop:wallpaper": string |
"desktop:wallpaper": string |
||||
"update.repo"?: string // 更新地址
|
"update.repo"?: string // 更新地址
|
||||
"update.owner"?: string // 更新通道
|
"update.owner"?: string // 更新通道
|
||||
"update.allowDowngrade": boolean, |
"update.allowDowngrade": boolean |
||||
"update.allowPrerelease": boolean |
"update.allowPrerelease": boolean |
||||
"editor.bg": string // 更新通道
|
"editor.bg": string // 更新通道
|
||||
"editor.logoType": "logo" | "bg" // 更新通道
|
"editor.logoType": "logo" | "bg" // 更新通道
|
||||
"editor.fontFamily": string // 更新通道
|
"editor.fontFamily": string // 更新通道
|
||||
// "snippet.storagePath": string // 代码片段保存位置
|
// "snippet.storagePath": string // 代码片段保存位置
|
||||
// "bookmark.storagePath": string // 书签保存位置
|
// "bookmark.storagePath": string // 书签保存位置
|
||||
// backup_rule: string // 备份规则
|
// backup_rule: string // 备份规则
|
||||
storagePath: string // 存储地址
|
storagePath: string // 存储地址
|
||||
} |
} |
||||
} |
} |
||||
export default { |
export default { |
||||
app_title: "ada", |
app_title: "ada", |
||||
default_config: { |
default_config: { |
||||
"storagePath": "$storagePath$", |
storagePath: "$storagePath$", |
||||
"language": "zh", |
language: "zh", |
||||
"common.theme": "auto", |
"common.theme": "auto", |
||||
"desktop:wallpaper": "", |
"desktop:wallpaper": "", |
||||
"editor.bg": "", |
"editor.bg": "", |
||||
"editor.logoType": "logo", |
"editor.logoType": "logo", |
||||
"editor.fontFamily": "Cascadia Mono, Consolas, 'Courier New', monospace", |
"editor.fontFamily": "Cascadia Mono, Consolas, 'Courier New', monospace", |
||||
"update.repo": "wood-desktop", |
"update.repo": "wood-desktop", |
||||
"update.owner": "npmrun", |
"update.owner": "npmrun", |
||||
"update.allowDowngrade": false, |
"update.allowDowngrade": false, |
||||
"update.allowPrerelease": false |
"update.allowPrerelease": false, |
||||
} |
}, |
||||
} as IConfig |
} as IConfig |
||||
|
@ -1,45 +1,45 @@ |
|||||
appId: com.electron.app |
appId: com.electron.app |
||||
productName: my-app |
productName: my-app |
||||
directories: |
directories: |
||||
buildResources: build |
buildResources: build |
||||
files: |
files: |
||||
- '!**/.vscode/*' |
- "!**/.vscode/*" |
||||
- '!src/*' |
- "!src/*" |
||||
- '!electron.vite.config.{js,ts,mjs,cjs}' |
- "!electron.vite.config.{js,ts,mjs,cjs}" |
||||
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' |
- "!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}" |
||||
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}' |
- "!{.env,.env.*,.npmrc,pnpm-lock.yaml}" |
||||
- '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}' |
- "!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}" |
||||
asarUnpack: |
asarUnpack: |
||||
- resources/** |
- resources/** |
||||
win: |
win: |
||||
executableName: my-app |
executableName: my-app |
||||
nsis: |
nsis: |
||||
artifactName: ${name}-${version}-setup.${ext} |
artifactName: ${name}-${version}-setup.${ext} |
||||
shortcutName: ${productName} |
shortcutName: ${productName} |
||||
uninstallDisplayName: ${productName} |
uninstallDisplayName: ${productName} |
||||
createDesktopShortcut: always |
createDesktopShortcut: always |
||||
mac: |
mac: |
||||
entitlementsInherit: build/entitlements.mac.plist |
entitlementsInherit: build/entitlements.mac.plist |
||||
extendInfo: |
extendInfo: |
||||
- NSCameraUsageDescription: Application requests access to the device's camera. |
- NSCameraUsageDescription: Application requests access to the device's camera. |
||||
- NSMicrophoneUsageDescription: Application requests access to the device's microphone. |
- NSMicrophoneUsageDescription: Application requests access to the device's microphone. |
||||
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. |
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. |
||||
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. |
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. |
||||
notarize: false |
notarize: false |
||||
dmg: |
dmg: |
||||
artifactName: ${name}-${version}.${ext} |
artifactName: ${name}-${version}.${ext} |
||||
linux: |
linux: |
||||
target: |
target: |
||||
- AppImage |
- AppImage |
||||
- snap |
- snap |
||||
- deb |
- deb |
||||
maintainer: electronjs.org |
maintainer: electronjs.org |
||||
category: Utility |
category: Utility |
||||
appImage: |
appImage: |
||||
artifactName: ${name}-${version}.${ext} |
artifactName: ${name}-${version}.${ext} |
||||
npmRebuild: false |
npmRebuild: false |
||||
publish: |
publish: |
||||
provider: generic |
provider: generic |
||||
url: https://example.com/auto-updates |
url: https://example.com/auto-updates |
||||
electronDownload: |
electronDownload: |
||||
mirror: https://npmmirror.com/mirrors/electron/ |
mirror: https://npmmirror.com/mirrors/electron/ |
||||
|
@ -1,28 +1,28 @@ |
|||||
import { resolve } from 'path' |
import { resolve } from "path" |
||||
import { defineConfig, externalizeDepsPlugin } from 'electron-vite' |
import { defineConfig, externalizeDepsPlugin } from "electron-vite" |
||||
import vue from '@vitejs/plugin-vue' |
import vue from "@vitejs/plugin-vue" |
||||
import UnoCSS from 'unocss/vite' |
import UnoCSS from "unocss/vite" |
||||
|
|
||||
export default defineConfig({ |
export default defineConfig({ |
||||
main: { |
main: { |
||||
resolve: { |
resolve: { |
||||
alias: { |
alias: { |
||||
config: resolve('config'), |
config: resolve("config"), |
||||
vc: resolve('src/main'), |
vc: resolve("src/main"), |
||||
res: resolve('resources') |
res: resolve("resources"), |
||||
} |
}, |
||||
|
}, |
||||
|
plugins: [externalizeDepsPlugin()], |
||||
}, |
}, |
||||
plugins: [externalizeDepsPlugin()] |
preload: { |
||||
}, |
plugins: [externalizeDepsPlugin()], |
||||
preload: { |
}, |
||||
plugins: [externalizeDepsPlugin()] |
renderer: { |
||||
}, |
resolve: { |
||||
renderer: { |
alias: { |
||||
resolve: { |
"@renderer": resolve("src/renderer/src"), |
||||
alias: { |
}, |
||||
'@renderer': resolve('src/renderer/src') |
}, |
||||
} |
plugins: [UnoCSS(), vue()], |
||||
}, |
}, |
||||
plugins: [UnoCSS(), vue()] |
|
||||
} |
|
||||
}) |
}) |
||||
|
@ -1,56 +1,56 @@ |
|||||
{ |
{ |
||||
"name": "my-app", |
"name": "my-app", |
||||
"type": "module", |
"type": "module", |
||||
"version": "1.0.0", |
"version": "1.0.0", |
||||
"description": "An Electron application with Vue and TypeScript", |
"description": "An Electron application with Vue and TypeScript", |
||||
"main": "./out/main/index.js", |
"main": "./out/main/index.js", |
||||
"author": "example.com", |
"author": "example.com", |
||||
"homepage": "https://electron-vite.org", |
"homepage": "https://electron-vite.org", |
||||
"scripts": { |
"scripts": { |
||||
"format": "prettier --write .", |
"format": "prettier --write .", |
||||
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix", |
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix", |
||||
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false", |
"typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false", |
||||
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false", |
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false", |
||||
"typecheck": "npm run typecheck:node && npm run typecheck:web", |
"typecheck": "npm run typecheck:node && npm run typecheck:web", |
||||
"start": "electron-vite preview", |
"start": "electron-vite preview", |
||||
"dev": "electron-vite dev", |
"dev": "electron-vite dev", |
||||
"dev:watch": "electron-vite dev --watch", |
"dev:watch": "electron-vite dev --watch", |
||||
"build": "npm run typecheck && electron-vite build", |
"build": "npm run typecheck && electron-vite build", |
||||
"postinstall": "electron-builder install-app-deps", |
"postinstall": "electron-builder install-app-deps", |
||||
"build:unpack": "npm run build && electron-builder --dir", |
"build:unpack": "npm run build && electron-builder --dir", |
||||
"build:win": "npm run build && electron-builder --win", |
"build:win": "npm run build && electron-builder --win", |
||||
"build:mac": "npm run build && electron-builder --mac", |
"build:mac": "npm run build && electron-builder --mac", |
||||
"build:linux": "npm run build && electron-builder --linux" |
"build:linux": "npm run build && electron-builder --linux" |
||||
}, |
}, |
||||
"dependencies": { |
"dependencies": { |
||||
"@electron-toolkit/preload": "^3.0.0", |
"@electron-toolkit/preload": "^3.0.0", |
||||
"@electron-toolkit/utils": "^3.0.0", |
"@electron-toolkit/utils": "^3.0.0", |
||||
"@unocss/reset": "^0.64.1", |
"@unocss/reset": "^0.64.1", |
||||
"electron-updater": "^6.1.7", |
"electron-updater": "^6.1.7", |
||||
"inversify": "^6.1.4", |
"inversify": "^6.1.4", |
||||
"lowdb": "^7.0.1", |
"lowdb": "^7.0.1", |
||||
"reflect-metadata": "^0.2.2" |
"reflect-metadata": "^0.2.2" |
||||
}, |
}, |
||||
"devDependencies": { |
"devDependencies": { |
||||
"@electron-toolkit/eslint-config": "^1.0.2", |
"@electron-toolkit/eslint-config": "^1.0.2", |
||||
"@electron-toolkit/eslint-config-ts": "^2.0.0", |
"@electron-toolkit/eslint-config-ts": "^2.0.0", |
||||
"@electron-toolkit/tsconfig": "^1.0.1", |
"@electron-toolkit/tsconfig": "^1.0.1", |
||||
"@rushstack/eslint-patch": "^1.10.3", |
"@rushstack/eslint-patch": "^1.10.3", |
||||
"@types/node": "^20.14.8", |
"@types/node": "^20.14.8", |
||||
"@unocss/preset-rem-to-px": "^0.64.1", |
"@unocss/preset-rem-to-px": "^0.64.1", |
||||
"@vitejs/plugin-vue": "^5.0.5", |
"@vitejs/plugin-vue": "^5.0.5", |
||||
"@vue/eslint-config-prettier": "^9.0.0", |
"@vue/eslint-config-prettier": "^9.0.0", |
||||
"@vue/eslint-config-typescript": "^13.0.0", |
"@vue/eslint-config-typescript": "^13.0.0", |
||||
"electron": "^31.0.2", |
"electron": "^31.0.2", |
||||
"electron-builder": "^24.13.3", |
"electron-builder": "^24.13.3", |
||||
"electron-vite": "^2.3.0", |
"electron-vite": "^2.3.0", |
||||
"eslint": "^8.57.0", |
"eslint": "^8.57.0", |
||||
"eslint-plugin-vue": "^9.26.0", |
"eslint-plugin-vue": "^9.26.0", |
||||
"prettier": "^3.3.2", |
"prettier": "^3.3.2", |
||||
"typescript": "^5.5.2", |
"typescript": "^5.5.2", |
||||
"unocss": "^0.64.1", |
"unocss": "^0.64.1", |
||||
"vite": "^5.3.1", |
"vite": "^5.3.1", |
||||
"vue": "^3.4.30", |
"vue": "^3.4.30", |
||||
"vue-tsc": "^2.0.22" |
"vue-tsc": "^2.0.22" |
||||
} |
} |
||||
} |
} |
||||
|
@ -1,3 +1,3 @@ |
|||||
abstract class Base{ |
abstract class Base { |
||||
constructor(){} |
constructor() {} |
||||
} |
} |
||||
|
@ -1,31 +1,25 @@ |
|||||
import { injectable, inject } from "inversify" |
import { injectable, inject } from "inversify" |
||||
import Setting from "./setting" |
import Setting from "./setting" |
||||
import DB from "./db" |
import DB from "./db" |
||||
|
|
||||
|
@injectable() |
||||
@injectable() |
class App { |
||||
class App { |
private _setting: Setting |
||||
private _setting: Setting |
private _db: DB |
||||
private _db: DB |
|
||||
|
constructor(@inject(Setting) setting: Setting, @inject(DB) db: DB) { |
||||
constructor( |
console.log(`App inited`) |
||||
@inject(Setting) setting: Setting, |
|
||||
@inject(DB) db: DB, |
this._setting = setting |
||||
) { |
this._db = db |
||||
console.log(`App inited`); |
} |
||||
|
|
||||
this._setting = setting |
async init() { |
||||
this._db = db |
console.log(this._setting.config()) |
||||
} |
this._db.saveData("aaa", { a: 123123 }) |
||||
|
console.log(await this._db.getData("aaa")) |
||||
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 } |
||||
} |
|
||||
|
|
||||
export default App |
|
||||
export { |
|
||||
App |
|
||||
} |
|
||||
|
@ -1,33 +1,33 @@ |
|||||
import { JSONFile } from "lowdb/node" |
import { JSONFile } from "lowdb/node" |
||||
import { Low } from 'lowdb' |
import { Low } from "lowdb" |
||||
import fs from 'fs-extra' |
import fs from "fs-extra" |
||||
|
|
||||
export class CustomAdapter<T> extends JSONFile<T> { |
export class CustomAdapter<T> extends JSONFile<T> { |
||||
constructor(filepath: string) { |
constructor(filepath: string) { |
||||
super(filepath) |
super(filepath) |
||||
this.filepath = filepath |
this.filepath = filepath |
||||
} |
} |
||||
filepath: string = '' |
filepath: string = "" |
||||
async read() { |
async read() { |
||||
if (!fs.existsSync(this.filepath)) { |
if (!fs.existsSync(this.filepath)) { |
||||
return null |
return null |
||||
} |
} |
||||
let data = fs.readJSONSync(this.filepath, { throws: false }) |
const data = fs.readJSONSync(this.filepath, { throws: false }) |
||||
if (!data) { |
if (!data) { |
||||
return null |
return null |
||||
} |
} |
||||
return data |
return data |
||||
} |
} |
||||
|
|
||||
async write(data: T) { |
async write(data: T) { |
||||
fs.ensureFileSync(this.filepath) |
fs.ensureFileSync(this.filepath) |
||||
await super.write(data) |
await super.write(data) |
||||
} |
} |
||||
} |
} |
||||
export class CustomLow<T> extends Low<T> { |
export class CustomLow<T> extends Low<T> { |
||||
constructor(adapter: CustomAdapter<T>, defaultData: T) { |
constructor(adapter: CustomAdapter<T>, defaultData: T) { |
||||
super(adapter, defaultData) |
super(adapter, defaultData) |
||||
this.filepath = adapter.filepath |
this.filepath = adapter.filepath |
||||
} |
} |
||||
filepath: string = '' |
filepath: string = "" |
||||
} |
} |
||||
|
@ -1,76 +1,74 @@ |
|||||
import { inject, injectable } from "inversify"; |
import { inject, injectable } from "inversify" |
||||
import Setting from "../setting"; |
import Setting from "../setting" |
||||
import { CustomAdapter, CustomLow } from "./custom"; |
import { CustomAdapter, CustomLow } from "./custom" |
||||
import path from "node:path"; |
import path from "node:path" |
||||
|
|
||||
@injectable() |
@injectable() |
||||
class DB { |
class DB { |
||||
private _setting: Setting |
private _setting: Setting |
||||
Modules: Record<string, CustomLow<any>> = {} |
Modules: Record<string, CustomLow<any>> = {} |
||||
|
|
||||
constructor(@inject(Setting) setting: Setting) { |
constructor(@inject(Setting) setting: Setting) { |
||||
console.log(`DB inited`); |
console.log(`DB inited`) |
||||
|
|
||||
this._setting = setting |
this._setting = setting |
||||
} |
} |
||||
|
|
||||
create(filepath) { |
create(filepath) { |
||||
let adapter = new CustomAdapter<any>(filepath) |
const adapter = new CustomAdapter<any>(filepath) |
||||
const db = new CustomLow<{}>(adapter, {}) |
const db = new CustomLow<object>(adapter, {}) |
||||
db.filepath = filepath |
db.filepath = filepath |
||||
return db |
return db |
||||
} |
} |
||||
|
|
||||
getDB(dbName: string) { |
getDB(dbName: string) { |
||||
if (this.Modules[dbName] === undefined) { |
if (this.Modules[dbName] === undefined) { |
||||
let filepath = path.resolve(this._setting.values("storagePath"), './db/' + dbName + '.json') |
const filepath = path.resolve(this._setting.values("storagePath"), "./db/" + dbName + ".json") |
||||
this.Modules[dbName] = this.create(filepath) |
this.Modules[dbName] = this.create(filepath) |
||||
return this.Modules[dbName] |
return this.Modules[dbName] |
||||
} else { |
} else { |
||||
let cur = this.Modules[dbName] |
const cur = this.Modules[dbName] |
||||
let filepath = path.resolve(this._setting.values("storagePath"), './db/' + dbName + '.json') |
const filepath = path.resolve(this._setting.values("storagePath"), "./db/" + dbName + ".json") |
||||
if (cur.filepath != filepath) { |
if (cur.filepath != filepath) { |
||||
this.Modules[dbName] = this.create(filepath) |
this.Modules[dbName] = this.create(filepath) |
||||
} |
} |
||||
return this.Modules[dbName] |
return this.Modules[dbName] |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
async saveData(data: any): Promise<any> |
async saveData(data: any): Promise<any> |
||||
async saveData(dbName: string, data: any): Promise<any> |
async saveData(dbName: string, data: any): Promise<any> |
||||
async saveData(dbName: string, data?: any): Promise<any> { |
async saveData(dbName: string, data?: any): Promise<any> { |
||||
let db, rData |
let db, rData |
||||
if (arguments.length === 2) { |
if (arguments.length === 2) { |
||||
db = this.getDB(dbName) |
db = this.getDB(dbName) |
||||
rData = data |
rData = data |
||||
} else { |
} else { |
||||
db = this.getDB('db') |
db = this.getDB("db") |
||||
rData = dbName |
rData = dbName |
||||
} |
} |
||||
if (db) { |
if (db) { |
||||
db.data = rData |
db.data = rData |
||||
await db.write() |
await db.write() |
||||
return db.data |
return db.data |
||||
} |
} |
||||
return null |
return null |
||||
} |
} |
||||
|
|
||||
async getData(dbName?: string) { |
async getData(dbName?: string) { |
||||
let db |
let db |
||||
if (dbName) { |
if (dbName) { |
||||
db = this.getDB(dbName) |
db = this.getDB(dbName) |
||||
} else { |
} else { |
||||
db = this.getDB('db') |
db = this.getDB("db") |
||||
} |
} |
||||
if (db) { |
if (db) { |
||||
await db.read() |
await db.read() |
||||
return db.data |
return db.data |
||||
} |
} |
||||
return null |
return null |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
export default DB |
export default DB |
||||
export { |
export { DB } |
||||
DB |
|
||||
} |
|
||||
|
@ -1,11 +1,9 @@ |
|||||
import { Container } from "inversify" |
import { Container } from "inversify" |
||||
import module from "./module" |
import module from "./module" |
||||
|
|
||||
const container = new Container() |
const container = new Container() |
||||
|
|
||||
container.load(module) |
container.load(module) |
||||
|
|
||||
export default container |
export default container |
||||
export { |
export { container } |
||||
container |
|
||||
} |
|
||||
|
@ -1,15 +1,13 @@ |
|||||
import { ContainerModule } from "inversify" |
import { ContainerModule } from "inversify" |
||||
import { Setting } from "./setting" |
import { Setting } from "./setting" |
||||
import { DB } from "./db" |
import { DB } from "./db" |
||||
import App from "./App" |
import App from "./App" |
||||
|
|
||||
const module = new ContainerModule((bind) => { |
const module = new ContainerModule(bind => { |
||||
bind(Setting).toConstantValue(new Setting()) |
bind(Setting).toConstantValue(new Setting()) |
||||
bind(DB).toSelf().inSingletonScope() |
bind(DB).toSelf().inSingletonScope() |
||||
bind(App).toSelf().inSingletonScope() |
bind(App).toSelf().inSingletonScope() |
||||
}) |
}) |
||||
|
|
||||
export default module |
export default module |
||||
export { |
export { module } |
||||
module |
|
||||
} |
|
||||
|
@ -1,233 +1,226 @@ |
|||||
import fs from "fs-extra" |
import fs from "fs-extra" |
||||
import { app } from "electron" |
import { app } from "electron" |
||||
import path from "path" |
import path from "path" |
||||
import { cloneDeep } from "lodash" |
import { cloneDeep } from "lodash" |
||||
import { injectable } from "inversify" |
import { injectable } from "inversify" |
||||
import Config from "config" |
import Config from "config" |
||||
|
|
||||
type IConfig = typeof Config.default_config |
type IConfig = typeof Config.default_config |
||||
|
|
||||
type IOnFunc = (n: IConfig, c: IConfig, keys?: (keyof IConfig)[]) => void |
type IOnFunc = (n: IConfig, c: IConfig, keys?: (keyof IConfig)[]) => void |
||||
type IT = (keyof IConfig)[] | keyof IConfig | "_" |
type IT = (keyof IConfig)[] | keyof IConfig | "_" |
||||
|
|
||||
let storagePath = path.join(app.getPath("documents"), Config.app_title) |
let storagePath = path.join(app.getPath("documents"), Config.app_title) |
||||
let storagePathDev = path.join(app.getPath("documents"), Config.app_title + "-dev") |
const storagePathDev = path.join(app.getPath("documents"), Config.app_title + "-dev") |
||||
|
|
||||
if (process.env.NODE_ENV === "development") { |
if (process.env.NODE_ENV === "development") { |
||||
storagePath = storagePathDev |
storagePath = storagePathDev |
||||
} |
} |
||||
|
|
||||
let _tempConfig = cloneDeep(Config.default_config as IConfig) |
const _tempConfig = cloneDeep(Config.default_config as IConfig) |
||||
Object.keys(_tempConfig).forEach(key => { |
Object.keys(_tempConfig).forEach(key => { |
||||
if (typeof _tempConfig[key] === "string" && _tempConfig[key].includes("$storagePath$")) { |
if (typeof _tempConfig[key] === "string" && _tempConfig[key].includes("$storagePath$")) { |
||||
_tempConfig[key] = _tempConfig[key].replace(/\$storagePath\$/g, storagePath) |
_tempConfig[key] = _tempConfig[key].replace(/\$storagePath\$/g, storagePath) |
||||
if (_tempConfig[key] && path.isAbsolute(_tempConfig[key])) { |
if (_tempConfig[key] && path.isAbsolute(_tempConfig[key])) { |
||||
_tempConfig[key] = path.normalize(_tempConfig[key]) |
_tempConfig[key] = path.normalize(_tempConfig[key]) |
||||
} |
} |
||||
} |
} |
||||
}) |
}) |
||||
|
|
||||
function isPath(str) { |
function isPath(str) { |
||||
// 使用正则表达式检查字符串是否以斜杠或盘符开头
|
// 使用正则表达式检查字符串是否以斜杠或盘符开头
|
||||
return /^(?:\/|[a-zA-Z]:\\)/.test(str); |
return /^(?:\/|[a-zA-Z]:\\)/.test(str) |
||||
} |
} |
||||
|
|
||||
function init(config: IConfig) { |
function init(config: IConfig) { |
||||
// 在配置初始化后执行
|
// 在配置初始化后执行
|
||||
Object.keys(config).forEach(key => { |
Object.keys(config).forEach(key => { |
||||
if (config[key] && isPath(config[key]) && path.isAbsolute(config[key])) { |
if (config[key] && isPath(config[key]) && path.isAbsolute(config[key])) { |
||||
fs.ensureDirSync(config[key]) |
fs.ensureDirSync(config[key]) |
||||
} |
} |
||||
}) |
}) |
||||
// 在配置初始化后执行
|
// 在配置初始化后执行
|
||||
// fs.ensureDirSync(config["snippet.storagePath"])
|
// fs.ensureDirSync(config["snippet.storagePath"])
|
||||
// fs.ensureDirSync(config["bookmark.storagePath"])
|
// fs.ensureDirSync(config["bookmark.storagePath"])
|
||||
} |
} |
||||
|
|
||||
// 判断是否是空文件夹
|
// 判断是否是空文件夹
|
||||
function isEmptyDir(fPath: string) { |
function isEmptyDir(fPath: string) { |
||||
var pa = fs.readdirSync(fPath) |
const pa = fs.readdirSync(fPath) |
||||
if (pa.length === 0) { |
if (pa.length === 0) { |
||||
return true |
return true |
||||
} else { |
} else { |
||||
return false |
return false |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
@injectable() |
@injectable() |
||||
class Setting { |
class Setting { |
||||
constructor() { |
constructor() { |
||||
console.log(`Setting inited`); |
console.log(`Setting inited`) |
||||
|
|
||||
this.#init() |
this.#init() |
||||
} |
} |
||||
#cb: [IT, IOnFunc][] = [] |
#cb: [IT, IOnFunc][] = [] |
||||
|
|
||||
onChange(fn: IOnFunc, that?: any) |
onChange(fn: IOnFunc, that?: any) |
||||
onChange(key: IT, fn: IOnFunc, that?: any) |
onChange(key: IT, fn: IOnFunc, that?: any) |
||||
onChange(fnOrType: IT | IOnFunc, fnOrThat: IOnFunc | any = null, that: any = null) { |
onChange(fnOrType: IT | IOnFunc, fnOrThat: IOnFunc | any = null, that: any = null) { |
||||
if (typeof fnOrType === "function") { |
if (typeof fnOrType === "function") { |
||||
this.#cb.push(["_", fnOrType.bind(fnOrThat)]) |
this.#cb.push(["_", fnOrType.bind(fnOrThat)]) |
||||
} else { |
} else { |
||||
this.#cb.push([fnOrType, fnOrThat.bind(that)]) |
this.#cb.push([fnOrType, fnOrThat.bind(that)]) |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
#runCB(n: IConfig, c: IConfig, keys: (keyof IConfig)[]) { |
#runCB(n: IConfig, c: IConfig, keys: (keyof IConfig)[]) { |
||||
for (let i = 0; i < this.#cb.length; i++) { |
for (let i = 0; i < this.#cb.length; i++) { |
||||
const temp = this.#cb[i] |
const temp = this.#cb[i] |
||||
const k = temp[0] |
const k = temp[0] |
||||
const fn = temp[1] |
const fn = temp[1] |
||||
if (k === "_") { |
if (k === "_") { |
||||
fn(n, c, keys) |
fn(n, c, keys) |
||||
} |
} |
||||
if (typeof k === "string" && keys.includes(k as keyof IConfig)) { |
if (typeof k === "string" && keys.includes(k as keyof IConfig)) { |
||||
fn(n, c) |
fn(n, c) |
||||
} |
} |
||||
if (Array.isArray(k) && k.filter(v => keys.indexOf(v) !== -1).length) { |
if (Array.isArray(k) && k.filter(v => keys.indexOf(v) !== -1).length) { |
||||
fn(n, c) |
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") |
#pathFile: string = |
||||
#config: IConfig = cloneDeep(_tempConfig) |
process.env.NODE_ENV === "development" |
||||
#configPath(storagePath?: string): string { |
? path.resolve(app.getPath("userData"), "./config_path-dev") |
||||
return path.join(storagePath || this.#config.storagePath, "./config.json") |
: 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) |
* @param confingPath 配置文件路径 |
||||
if (!fs.pathExistsSync(configFile)) { |
*/ |
||||
fs.ensureFileSync(configFile) |
#syncVar(confingPath?: string) { |
||||
fs.writeJSONSync(configFile, {}) |
const configFile = this.#configPath(confingPath) |
||||
} |
if (!fs.pathExistsSync(configFile)) { |
||||
const config = fs.readJSONSync(configFile) as IConfig |
fs.ensureFileSync(configFile) |
||||
confingPath && (config.storagePath = confingPath) |
fs.writeJSONSync(configFile, {}) |
||||
// 优先取本地的值
|
} |
||||
for (const key in config) { |
const config = fs.readJSONSync(configFile) as IConfig |
||||
// if (Object.prototype.hasOwnProperty.call(this.#config, key)) {
|
confingPath && (config.storagePath = confingPath) |
||||
// this.#config[key] = config[key] || this.#config[key]
|
// 优先取本地的值
|
||||
// }
|
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() { |
this.#config[key] = config[key] || this.#config[key] |
||||
console.log(`位置:${this.#pathFile}`) |
} |
||||
if (fs.pathExistsSync(this.#pathFile)) { |
} |
||||
const confingPath = fs.readFileSync(this.#pathFile, { encoding: "utf8" }) |
#init() { |
||||
if (confingPath && fs.pathExistsSync(this.#configPath(confingPath))) { |
console.log(`位置:${this.#pathFile}`) |
||||
this.#syncVar(confingPath) |
if (fs.pathExistsSync(this.#pathFile)) { |
||||
// 防止增加了配置本地却没变的情况
|
const confingPath = fs.readFileSync(this.#pathFile, { encoding: "utf8" }) |
||||
this.#sync(confingPath) |
if (confingPath && fs.pathExistsSync(this.#configPath(confingPath))) { |
||||
} else { |
this.#syncVar(confingPath) |
||||
this.#syncVar(confingPath) |
// 防止增加了配置本地却没变的情况
|
||||
this.#sync(confingPath) |
this.#sync(confingPath) |
||||
} |
} else { |
||||
} else { |
this.#syncVar(confingPath) |
||||
this.#syncVar() |
this.#sync(confingPath) |
||||
this.#sync() |
} |
||||
} |
} else { |
||||
init.call(this, this.#config) |
this.#syncVar() |
||||
} |
this.#sync() |
||||
config() { |
} |
||||
return this.#config |
init.call(this, this.#config) |
||||
} |
} |
||||
#sync(c?: string) { |
config() { |
||||
const config = cloneDeep(this.#config) |
return this.#config |
||||
delete config.storagePath |
} |
||||
const p = this.#configPath(c) |
#sync(c?: string) { |
||||
fs.ensureFileSync(p) |
const config = cloneDeep(this.#config) |
||||
fs.writeJSONSync(this.#configPath(c), config) |
delete config.storagePath |
||||
} |
const p = this.#configPath(c) |
||||
#change(p: string) { |
fs.ensureFileSync(p) |
||||
const storagePath = this.#config.storagePath |
fs.writeJSONSync(this.#configPath(c), config) |
||||
if (fs.existsSync(storagePath) && !fs.existsSync(p)) { |
} |
||||
fs.moveSync(storagePath, p) |
#change(p: string) { |
||||
} |
const storagePath = this.#config.storagePath |
||||
if (fs.existsSync(p) && fs.existsSync(storagePath) && isEmptyDir(p)) { |
if (fs.existsSync(storagePath) && !fs.existsSync(p)) { |
||||
console.log("文件夹为空,直接覆盖") |
fs.moveSync(storagePath, p) |
||||
fs.moveSync(storagePath, p, { overwrite: true }) |
} |
||||
} |
if (fs.existsSync(p) && fs.existsSync(storagePath) && isEmptyDir(p)) { |
||||
fs.writeFileSync(this.#pathFile, p, { encoding: "utf8" }) |
console.log("文件夹为空,直接覆盖") |
||||
} |
fs.moveSync(storagePath, p, { overwrite: true }) |
||||
reset(key: keyof IConfig) { |
} |
||||
this.set(key, cloneDeep(_tempConfig[key])) |
fs.writeFileSync(this.#pathFile, p, { encoding: "utf8" }) |
||||
} |
} |
||||
set(key: keyof IConfig | Partial<IConfig>, value?: any) { |
reset(key: keyof IConfig) { |
||||
let oldMainConfig = Object.assign({}, this.#config) |
this.set(key, cloneDeep(_tempConfig[key])) |
||||
let isChange = false |
} |
||||
let changeKeys: (keyof IConfig)[] = [] |
set(key: keyof IConfig | Partial<IConfig>, value?: any) { |
||||
let canChangeStorage = (targetPath: string) => { |
const oldMainConfig = Object.assign({}, this.#config) |
||||
if (fs.existsSync(oldMainConfig.storagePath) && fs.existsSync(targetPath) && !isEmptyDir(targetPath)) { |
let isChange = false |
||||
if (fs.existsSync(path.join(targetPath, "./config.json"))) { |
const changeKeys: (keyof IConfig)[] = [] |
||||
return true |
const canChangeStorage = (targetPath: string) => { |
||||
} |
if (fs.existsSync(oldMainConfig.storagePath) && fs.existsSync(targetPath) && !isEmptyDir(targetPath)) { |
||||
return false |
if (fs.existsSync(path.join(targetPath, "./config.json"))) { |
||||
} |
return true |
||||
return true |
} |
||||
} |
return false |
||||
if (typeof key === "string") { |
} |
||||
if (value != undefined && value !== this.#config[key]) { |
return true |
||||
if (key === "storagePath") { |
} |
||||
if (!canChangeStorage(value)) { |
if (typeof key === "string") { |
||||
throw "无法改变存储地址" |
if (value != undefined && value !== this.#config[key]) { |
||||
return |
if (key === "storagePath") { |
||||
} |
if (!canChangeStorage(value)) { |
||||
try { |
throw "无法改变存储地址" |
||||
this.#change(value) |
return |
||||
} catch (error) { |
} |
||||
throw error |
this.#change(value) |
||||
} |
changeKeys.push("storagePath") |
||||
changeKeys.push("storagePath") |
this.#config["storagePath"] = value |
||||
this.#config["storagePath"] = value |
} else { |
||||
} else { |
changeKeys.push(key) |
||||
changeKeys.push(key) |
this.#config[key as string] = value |
||||
this.#config[key as string] = value |
} |
||||
} |
isChange = true |
||||
isChange = true |
} |
||||
} |
} else { |
||||
} else { |
if (key["storagePath"] !== undefined && key["storagePath"] !== this.#config["storagePath"]) { |
||||
if (key['storagePath'] !== undefined && key['storagePath'] !== this.#config['storagePath']) { |
if (!canChangeStorage(key["storagePath"])) { |
||||
if (!canChangeStorage(key['storagePath'])) { |
throw "无法改变存储地址" |
||||
throw "无法改变存储地址" |
return |
||||
return |
} |
||||
} |
this.#change(key["storagePath"]) |
||||
try { |
this.#config["storagePath"] = key["storagePath"] |
||||
this.#change(key['storagePath']) |
changeKeys.push("storagePath") |
||||
} catch (error) { |
isChange = true |
||||
throw error |
} |
||||
} |
for (const _ in key) { |
||||
this.#config['storagePath'] = key['storagePath'] |
if (Object.prototype.hasOwnProperty.call(key, _)) { |
||||
changeKeys.push('storagePath') |
const v = key[_] |
||||
isChange = true |
if (v != undefined && _ !== "storagePath" && v !== this.#config[_]) { |
||||
} |
this.#config[_] = v |
||||
for (const _ in key as any) { |
changeKeys.push(_ as keyof IConfig) |
||||
if (Object.prototype.hasOwnProperty.call(key, _)) { |
isChange = true |
||||
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) |
||||
} |
} |
||||
} |
} |
||||
if (isChange) { |
values<T extends keyof IConfig>(key: T): IConfig[T] { |
||||
this.#sync() |
return this.#config[key] |
||||
this.#runCB(this.#config, oldMainConfig, changeKeys) |
} |
||||
} |
} |
||||
} |
|
||||
values<T extends keyof IConfig>(key: T): IConfig[T] { |
export default Setting |
||||
return this.#config[key] |
export { Setting } |
||||
} |
|
||||
} |
|
||||
|
|
||||
export default Setting |
|
||||
export { |
|
||||
Setting |
|
||||
} |
|
||||
|
@ -1,8 +1,8 @@ |
|||||
import { ElectronAPI } from '@electron-toolkit/preload' |
import { ElectronAPI } from "@electron-toolkit/preload" |
||||
|
|
||||
declare global { |
declare global { |
||||
interface Window { |
interface Window { |
||||
electron: ElectronAPI |
electron: ElectronAPI |
||||
api: unknown |
api: unknown |
||||
} |
} |
||||
} |
} |
||||
|
@ -1,17 +1,17 @@ |
|||||
<!doctype html> |
<!doctype html> |
||||
<html> |
<html> |
||||
<head> |
<head> |
||||
<meta charset="UTF-8" /> |
<meta charset="UTF-8" /> |
||||
<title>Electron</title> |
<title>Electron</title> |
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> |
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> |
||||
<meta |
<meta |
||||
http-equiv="Content-Security-Policy" |
http-equiv="Content-Security-Policy" |
||||
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:" |
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:" |
||||
/> |
/> |
||||
</head> |
</head> |
||||
|
|
||||
<body> |
<body> |
||||
<div id="app"></div> |
<div id="app"></div> |
||||
<script type="module" src="/src/main.ts"></script> |
<script type="module" src="/src/main.ts"></script> |
||||
</body> |
</body> |
||||
</html> |
</html> |
||||
|
@ -1,26 +1,30 @@ |
|||||
<script setup lang="ts"> |
<script setup lang="ts"> |
||||
import Versions from './components/Versions.vue' |
import Versions from "./components/Versions.vue" |
||||
|
|
||||
const ipcHandle = () => window.electron.ipcRenderer.send('ping') |
const ipcHandle = () => window.electron.ipcRenderer.send("ping") |
||||
</script> |
</script> |
||||
|
|
||||
<template> |
<template> |
||||
<img alt="logo" class="logo" src="./assets/electron.svg" /> |
<img alt="logo" class="logo" src="./assets/electron.svg" /> |
||||
<div class="creator">Powered by electron-vite</div> |
<div class="creator">Powered by electron-vite</div> |
||||
<div class="text"> |
<div class="text"> |
||||
Build an Electron app with |
Build an Electron app with |
||||
<span class="vue">Vue</span> |
<span class="vue">Vue</span> |
||||
and |
and |
||||
<span class="ts">TypeScript</span> |
<span class="ts">TypeScript</span> |
||||
</div> |
|
||||
<p class="tip">Please try pressing <code>F12</code> to open the devTool</p> |
|
||||
<div class="actions"> |
|
||||
<div class="action"> |
|
||||
<a href="https://electron-vite.org/" target="_blank" rel="noreferrer">Documentation</a> |
|
||||
</div> |
</div> |
||||
<div class="action"> |
<p class="tip"> |
||||
<a target="_blank" rel="noreferrer" @click="ipcHandle">Send IPC</a> |
Please try pressing |
||||
|
<code>F12</code> |
||||
|
to open the devTool |
||||
|
</p> |
||||
|
<div class="actions"> |
||||
|
<div class="action"> |
||||
|
<a href="https://electron-vite.org/" target="_blank" rel="noreferrer">Documentation</a> |
||||
|
</div> |
||||
|
<div class="action"> |
||||
|
<a target="_blank" rel="noreferrer" @click="ipcHandle">Send IPC</a> |
||||
|
</div> |
||||
</div> |
</div> |
||||
</div> |
<Versions /> |
||||
<Versions /> |
|
||||
</template> |
</template> |
||||
|
@ -1,67 +1,67 @@ |
|||||
:root { |
:root { |
||||
--ev-c-white: #ffffff; |
--ev-c-white: #ffffff; |
||||
--ev-c-white-soft: #f8f8f8; |
--ev-c-white-soft: #f8f8f8; |
||||
--ev-c-white-mute: #f2f2f2; |
--ev-c-white-mute: #f2f2f2; |
||||
|
|
||||
--ev-c-black: #1b1b1f; |
--ev-c-black: #1b1b1f; |
||||
--ev-c-black-soft: #222222; |
--ev-c-black-soft: #222222; |
||||
--ev-c-black-mute: #282828; |
--ev-c-black-mute: #282828; |
||||
|
|
||||
--ev-c-gray-1: #515c67; |
--ev-c-gray-1: #515c67; |
||||
--ev-c-gray-2: #414853; |
--ev-c-gray-2: #414853; |
||||
--ev-c-gray-3: #32363f; |
--ev-c-gray-3: #32363f; |
||||
|
|
||||
--ev-c-text-1: rgba(255, 255, 245, 0.86); |
--ev-c-text-1: rgba(255, 255, 245, 0.86); |
||||
--ev-c-text-2: rgba(235, 235, 245, 0.6); |
--ev-c-text-2: rgba(235, 235, 245, 0.6); |
||||
--ev-c-text-3: rgba(235, 235, 245, 0.38); |
--ev-c-text-3: rgba(235, 235, 245, 0.38); |
||||
|
|
||||
--ev-button-alt-border: transparent; |
--ev-button-alt-border: transparent; |
||||
--ev-button-alt-text: var(--ev-c-text-1); |
--ev-button-alt-text: var(--ev-c-text-1); |
||||
--ev-button-alt-bg: var(--ev-c-gray-3); |
--ev-button-alt-bg: var(--ev-c-gray-3); |
||||
--ev-button-alt-hover-border: transparent; |
--ev-button-alt-hover-border: transparent; |
||||
--ev-button-alt-hover-text: var(--ev-c-text-1); |
--ev-button-alt-hover-text: var(--ev-c-text-1); |
||||
--ev-button-alt-hover-bg: var(--ev-c-gray-2); |
--ev-button-alt-hover-bg: var(--ev-c-gray-2); |
||||
} |
} |
||||
|
|
||||
:root { |
:root { |
||||
--color-background: var(--ev-c-black); |
--color-background: var(--ev-c-black); |
||||
--color-background-soft: var(--ev-c-black-soft); |
--color-background-soft: var(--ev-c-black-soft); |
||||
--color-background-mute: var(--ev-c-black-mute); |
--color-background-mute: var(--ev-c-black-mute); |
||||
|
|
||||
--color-text: var(--ev-c-text-1); |
--color-text: var(--ev-c-text-1); |
||||
} |
} |
||||
|
|
||||
*, |
*, |
||||
*::before, |
*::before, |
||||
*::after { |
*::after { |
||||
box-sizing: border-box; |
box-sizing: border-box; |
||||
margin: 0; |
margin: 0; |
||||
font-weight: normal; |
font-weight: normal; |
||||
} |
} |
||||
|
|
||||
ul { |
ul { |
||||
list-style: none; |
list-style: none; |
||||
} |
} |
||||
|
|
||||
body { |
body { |
||||
min-height: 100vh; |
min-height: 100vh; |
||||
color: var(--color-text); |
color: var(--color-text); |
||||
background: var(--color-background); |
background: var(--color-background); |
||||
line-height: 1.6; |
line-height: 1.6; |
||||
font-family: |
font-family: |
||||
Inter, |
Inter, |
||||
-apple-system, |
-apple-system, |
||||
BlinkMacSystemFont, |
BlinkMacSystemFont, |
||||
'Segoe UI', |
"Segoe UI", |
||||
Roboto, |
Roboto, |
||||
Oxygen, |
Oxygen, |
||||
Ubuntu, |
Ubuntu, |
||||
Cantarell, |
Cantarell, |
||||
'Fira Sans', |
"Fira Sans", |
||||
'Droid Sans', |
"Droid Sans", |
||||
'Helvetica Neue', |
"Helvetica Neue", |
||||
sans-serif; |
sans-serif; |
||||
text-rendering: optimizeLegibility; |
text-rendering: optimizeLegibility; |
||||
-webkit-font-smoothing: antialiased; |
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
-moz-osx-font-smoothing: grayscale; |
||||
} |
} |
||||
|
@ -1,171 +1,171 @@ |
|||||
@import './base.css'; |
@import "./base.css"; |
||||
|
|
||||
body { |
body { |
||||
display: flex; |
display: flex; |
||||
align-items: center; |
align-items: center; |
||||
justify-content: center; |
justify-content: center; |
||||
overflow: hidden; |
overflow: hidden; |
||||
background-image: url('./wavy-lines.svg'); |
background-image: url("./wavy-lines.svg"); |
||||
background-size: cover; |
background-size: cover; |
||||
user-select: none; |
user-select: none; |
||||
} |
} |
||||
|
|
||||
code { |
code { |
||||
font-weight: 600; |
font-weight: 600; |
||||
padding: 3px 5px; |
padding: 3px 5px; |
||||
border-radius: 2px; |
border-radius: 2px; |
||||
background-color: var(--color-background-mute); |
background-color: var(--color-background-mute); |
||||
font-family: |
font-family: |
||||
ui-monospace, |
ui-monospace, |
||||
SFMono-Regular, |
SFMono-Regular, |
||||
SF Mono, |
SF Mono, |
||||
Menlo, |
Menlo, |
||||
Consolas, |
Consolas, |
||||
Liberation Mono, |
Liberation Mono, |
||||
monospace; |
monospace; |
||||
font-size: 85%; |
font-size: 85%; |
||||
} |
} |
||||
|
|
||||
#app { |
#app { |
||||
display: flex; |
display: flex; |
||||
align-items: center; |
align-items: center; |
||||
justify-content: center; |
justify-content: center; |
||||
flex-direction: column; |
flex-direction: column; |
||||
margin-bottom: 80px; |
margin-bottom: 80px; |
||||
} |
} |
||||
|
|
||||
.logo { |
.logo { |
||||
margin-bottom: 20px; |
margin-bottom: 20px; |
||||
-webkit-user-drag: none; |
-webkit-user-drag: none; |
||||
height: 128px; |
height: 128px; |
||||
width: 128px; |
width: 128px; |
||||
will-change: filter; |
will-change: filter; |
||||
transition: filter 300ms; |
transition: filter 300ms; |
||||
} |
} |
||||
|
|
||||
.logo:hover { |
.logo:hover { |
||||
filter: drop-shadow(0 0 1.2em #6988e6aa); |
filter: drop-shadow(0 0 1.2em #6988e6aa); |
||||
} |
} |
||||
|
|
||||
.creator { |
.creator { |
||||
font-size: 14px; |
font-size: 14px; |
||||
line-height: 16px; |
line-height: 16px; |
||||
color: var(--ev-c-text-2); |
color: var(--ev-c-text-2); |
||||
font-weight: 600; |
font-weight: 600; |
||||
margin-bottom: 10px; |
margin-bottom: 10px; |
||||
} |
} |
||||
|
|
||||
.text { |
.text { |
||||
font-size: 28px; |
font-size: 28px; |
||||
color: var(--ev-c-text-1); |
color: var(--ev-c-text-1); |
||||
font-weight: 700; |
font-weight: 700; |
||||
line-height: 32px; |
line-height: 32px; |
||||
text-align: center; |
text-align: center; |
||||
margin: 0 10px; |
margin: 0 10px; |
||||
padding: 16px 0; |
padding: 16px 0; |
||||
} |
} |
||||
|
|
||||
.tip { |
.tip { |
||||
font-size: 16px; |
font-size: 16px; |
||||
line-height: 24px; |
line-height: 24px; |
||||
color: var(--ev-c-text-2); |
color: var(--ev-c-text-2); |
||||
font-weight: 600; |
font-weight: 600; |
||||
} |
} |
||||
|
|
||||
.vue { |
.vue { |
||||
background: -webkit-linear-gradient(315deg, #42d392 25%, #647eff); |
background: -webkit-linear-gradient(315deg, #42d392 25%, #647eff); |
||||
background-clip: text; |
background-clip: text; |
||||
-webkit-background-clip: text; |
-webkit-background-clip: text; |
||||
-webkit-text-fill-color: transparent; |
-webkit-text-fill-color: transparent; |
||||
font-weight: 700; |
font-weight: 700; |
||||
} |
} |
||||
|
|
||||
.ts { |
.ts { |
||||
background: -webkit-linear-gradient(315deg, #3178c6 45%, #f0dc4e); |
background: -webkit-linear-gradient(315deg, #3178c6 45%, #f0dc4e); |
||||
background-clip: text; |
background-clip: text; |
||||
-webkit-background-clip: text; |
-webkit-background-clip: text; |
||||
-webkit-text-fill-color: transparent; |
-webkit-text-fill-color: transparent; |
||||
font-weight: 700; |
font-weight: 700; |
||||
} |
} |
||||
|
|
||||
.actions { |
.actions { |
||||
display: flex; |
display: flex; |
||||
padding-top: 32px; |
padding-top: 32px; |
||||
margin: -6px; |
margin: -6px; |
||||
flex-wrap: wrap; |
flex-wrap: wrap; |
||||
justify-content: flex-start; |
justify-content: flex-start; |
||||
} |
} |
||||
|
|
||||
.action { |
.action { |
||||
flex-shrink: 0; |
flex-shrink: 0; |
||||
padding: 6px; |
padding: 6px; |
||||
} |
} |
||||
|
|
||||
.action a { |
.action a { |
||||
cursor: pointer; |
cursor: pointer; |
||||
text-decoration: none; |
text-decoration: none; |
||||
display: inline-block; |
display: inline-block; |
||||
border: 1px solid transparent; |
border: 1px solid transparent; |
||||
text-align: center; |
text-align: center; |
||||
font-weight: 600; |
font-weight: 600; |
||||
white-space: nowrap; |
white-space: nowrap; |
||||
border-radius: 20px; |
border-radius: 20px; |
||||
padding: 0 20px; |
padding: 0 20px; |
||||
line-height: 38px; |
line-height: 38px; |
||||
font-size: 14px; |
font-size: 14px; |
||||
border-color: var(--ev-button-alt-border); |
border-color: var(--ev-button-alt-border); |
||||
color: var(--ev-button-alt-text); |
color: var(--ev-button-alt-text); |
||||
background-color: var(--ev-button-alt-bg); |
background-color: var(--ev-button-alt-bg); |
||||
} |
} |
||||
|
|
||||
.action a:hover { |
.action a:hover { |
||||
border-color: var(--ev-button-alt-hover-border); |
border-color: var(--ev-button-alt-hover-border); |
||||
color: var(--ev-button-alt-hover-text); |
color: var(--ev-button-alt-hover-text); |
||||
background-color: var(--ev-button-alt-hover-bg); |
background-color: var(--ev-button-alt-hover-bg); |
||||
} |
} |
||||
|
|
||||
.versions { |
.versions { |
||||
position: absolute; |
position: absolute; |
||||
bottom: 30px; |
bottom: 30px; |
||||
margin: 0 auto; |
margin: 0 auto; |
||||
padding: 15px 0; |
padding: 15px 0; |
||||
font-family: 'Menlo', 'Lucida Console', monospace; |
font-family: "Menlo", "Lucida Console", monospace; |
||||
display: inline-flex; |
display: inline-flex; |
||||
overflow: hidden; |
overflow: hidden; |
||||
align-items: center; |
align-items: center; |
||||
border-radius: 22px; |
border-radius: 22px; |
||||
background-color: #202127; |
background-color: #202127; |
||||
backdrop-filter: blur(24px); |
backdrop-filter: blur(24px); |
||||
} |
} |
||||
|
|
||||
.versions li { |
.versions li { |
||||
display: block; |
display: block; |
||||
float: left; |
float: left; |
||||
border-right: 1px solid var(--ev-c-gray-1); |
border-right: 1px solid var(--ev-c-gray-1); |
||||
padding: 0 20px; |
padding: 0 20px; |
||||
font-size: 14px; |
font-size: 14px; |
||||
line-height: 14px; |
line-height: 14px; |
||||
opacity: 0.8; |
opacity: 0.8; |
||||
&:last-child { |
&:last-child { |
||||
border: none; |
border: none; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
@media (max-width: 720px) { |
@media (max-width: 720px) { |
||||
.text { |
.text { |
||||
font-size: 20px; |
font-size: 20px; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
@media (max-width: 620px) { |
@media (max-width: 620px) { |
||||
.versions { |
.versions { |
||||
display: none; |
display: none; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
@media (max-width: 350px) { |
@media (max-width: 350px) { |
||||
.tip, |
.tip, |
||||
.actions { |
.actions { |
||||
display: none; |
display: none; |
||||
} |
} |
||||
} |
} |
||||
|
@ -1,13 +1,13 @@ |
|||||
<script setup lang="ts"> |
<script setup lang="ts"> |
||||
import { reactive } from 'vue' |
import { reactive } from "vue" |
||||
|
|
||||
const versions = reactive({ ...window.electron.process.versions }) |
const versions = reactive({ ...window.electron.process.versions }) |
||||
</script> |
</script> |
||||
|
|
||||
<template> |
<template> |
||||
<ul class="versions"> |
<ul class="versions"> |
||||
<li class="electron-version">Electron v{{ versions.electron }}</li> |
<li class="electron-version">Electron v{{ versions.electron }}</li> |
||||
<li class="chrome-version">Chromium v{{ versions.chrome }}</li> |
<li class="chrome-version">Chromium v{{ versions.chrome }}</li> |
||||
<li class="node-version">Node v{{ versions.node }}</li> |
<li class="node-version">Node v{{ versions.node }}</li> |
||||
</ul> |
</ul> |
||||
</template> |
</template> |
||||
|
@ -1,8 +1,8 @@ |
|||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||
|
|
||||
declare module '*.vue' { |
declare module "*.vue" { |
||||
import type { DefineComponent } from 'vue' |
import type { DefineComponent } from "vue" |
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
||||
const component: DefineComponent<{}, {}, any> |
const component: DefineComponent<{}, {}, any> |
||||
export default component |
export default component |
||||
} |
} |
||||
|
@ -1,8 +1,8 @@ |
|||||
import 'virtual:uno.css' |
import "virtual:uno.css" |
||||
import '@unocss/reset/normalize.css' |
import "@unocss/reset/normalize.css" |
||||
import './assets/main.css' |
import "./assets/main.css" |
||||
|
|
||||
import { createApp } from 'vue' |
import { createApp } from "vue" |
||||
import App from './App.vue' |
import App from "./App.vue" |
||||
|
|
||||
createApp(App).mount('#app') |
createApp(App).mount("#app") |
||||
|
@ -1,5 +1,5 @@ |
|||||
import type { AttributifyAttributes } from '@unocss/preset-attributify' |
import type { AttributifyAttributes } from "@unocss/preset-attributify" |
||||
|
|
||||
declare module '@vue/runtime-dom' { |
declare module "@vue/runtime-dom" { |
||||
interface HTMLAttributes extends AttributifyAttributes { } |
interface HTMLAttributes extends AttributifyAttributes {} |
||||
} |
} |
||||
|
@ -1,10 +1,6 @@ |
|||||
import { defineConfig, presetAttributify, presetUno } from 'unocss' |
import { defineConfig, presetAttributify, presetUno } from "unocss" |
||||
import presetRemToPx from '@unocss/preset-rem-to-px' |
import presetRemToPx from "@unocss/preset-rem-to-px" |
||||
|
|
||||
export default defineConfig({ |
export default defineConfig({ |
||||
presets: [ |
presets: [presetAttributify(), presetUno(), presetRemToPx()], |
||||
presetAttributify(), |
}) |
||||
presetUno(), |
|
||||
presetRemToPx(), |
|
||||
], |
|
||||
}) |
|
||||
|
Loading…
Reference in new issue