update dependencies

This commit is contained in:
codetypes committed 2025-03-02 20:36:05 +08:00
1 parent 3de6903594
commit d251c7914e
22 files changed
+3722 -395

No files matched your search

+16 -15
View File
@@ -1,23 +1,24 @@
import fs from 'node:fs' import { spawn } from "node:child_process";
import path from 'node:path' import fs from "node:fs";
import { fileURLToPath } from 'node:url' import { createRequire } from "node:module";
import { createRequire } from 'node:module' import path from "node:path";
import { spawn } from 'node:child_process' import { fileURLToPath } from "node:url";
const pkg = createRequire(import.meta.url)('../package.json') const pkg = createRequire(import.meta.url)("../package.json");
const __dirname = path.dirname(fileURLToPath(import.meta.url)) const __dirname = path.dirname(fileURLToPath(import.meta.url));
// write .debug.env // write .debug.env
const envContent = Object.entries(pkg.debug.env).map(([key, val]) => `${key}=${val}`) const envContent = Object.entries(pkg.debug.env).map(([key, val]) => `${key}=${val}`);
fs.writeFileSync(path.join(__dirname, '.debug.env'), envContent.join('\n')) fs.writeFileSync(path.join(__dirname, ".debug.env"), envContent.join("\n"));
// bootstrap // bootstrap
spawn( spawn(
// TODO: terminate `npm run dev` when Debug exits. // TODO: terminate `npm run dev` when Debug exits.
process.platform === 'win32' ? 'npm.cmd' : 'npm', process.platform === "win32" ? "npm.cmd" : "npm",
['run', 'dev'], ["run", "dev"],
{ {
stdio: 'inherit', stdio: "inherit",
env: Object.assign(process.env, { VSCODE_DEBUG: 'true' }), shell: true,
}, env: Object.assign(process.env, { VSCODE_DEBUG: "true" }),
) }
);
+10 -3
View File
@@ -7,7 +7,10 @@
{ {
"name": "Debug App", "name": "Debug App",
"preLaunchTask": "Before Debug", "preLaunchTask": "Before Debug",
"configurations": ["Debug Main Process", "Debug Renderer Process"], "configurations": [
"Debug Main Process",
"Debug Renderer Process"
],
"presentation": { "presentation": {
"hidden": false, "hidden": false,
"group": "", "group": "",
@@ -25,7 +28,11 @@
"windows": { "windows": {
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd" "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
}, },
"runtimeArgs": ["--no-sandbox", "--remote-debugging-port=9229", "."], "runtimeArgs": [
"--no-sandbox",
"--remote-debugging-port=9229",
"."
],
"envFile": "${workspaceFolder}/.vscode/.debug.env", "envFile": "${workspaceFolder}/.vscode/.debug.env",
"console": "integratedTerminal" "console": "integratedTerminal"
}, },
@@ -42,6 +49,6 @@
// Skip files in host(VITE_DEV_SERVER_URL) // Skip files in host(VITE_DEV_SERVER_URL)
"http://127.0.0.1:7777/**" "http://127.0.0.1:7777/**"
] ]
} },
] ]
} }
+34
View File
@@ -0,0 +1,34 @@
{
"$schema": "https://raw.githubusercontent.com/electron-userland/electron-builder/master/packages/app-builder-lib/scheme.json",
"appId": "behavior3editor",
"productName": "Behavior3 Editor",
"asar": true,
"directories": {
"output": "release/${version}"
},
"files": ["dist-electron", "dist"],
"mac": {
"artifactName": "behavior3editor_${version}.${ext}",
"target": ["dmg", "zip"]
},
"win": {
"target": [
{
"target": "nsis",
"arch": ["x64"]
}
],
"artifactName": "behavior3editor_${version}.${ext}"
},
"nsis": {
"oneClick": false,
"perMachine": false,
"allowToChangeInstallationDirectory": true,
"deleteAppDataOnUninstall": false
},
"publish": {
"provider": "generic",
"channel": "latest",
"url": "https://github.com/electron-vite/electron-vite-react/releases/download/v0.9.9/"
}
}
-37
View File
@@ -1,37 +0,0 @@
/**
* @see https://www.electron.build/configuration/configuration
*/
{
appId: "behavior3editor",
productName: "Behavior3 Editor",
asar: true,
directories: {
output: "release/${version}",
},
files: ["dist-electron", "dist"],
mac: {
artifactName: "behavior3editor_${version}.${ext}",
target: ["dmg", "zip"],
},
win: {
target: [
{
target: "nsis",
arch: ["x64"],
// arch: ["x64", "ia32"],
},
],
artifactName: "behavior3editor_${version}.${ext}",
},
nsis: {
oneClick: false,
perMachine: false,
allowToChangeInstallationDirectory: true,
deleteAppDataOnUninstall: false,
},
publish: {
provider: "generic",
channel: "latest",
url: "https://github.com/electron-vite/electron-vite-react/releases/download/v0.9.9/",
},
}
+15 -3
View File
@@ -3,9 +3,21 @@
declare namespace NodeJS { declare namespace NodeJS {
interface ProcessEnv { interface ProcessEnv {
VSCODE_DEBUG?: 'true' VSCODE_DEBUG?: 'true'
DIST_ELECTRON: string /**
DIST: string * The built directory structure
*
* ```tree
* ├─┬ dist-electron
* │ ├─┬ main
* │ │ └── index.js > Electron-Main
* │ └─┬ preload
* │ └── index.mjs > Preload-Scripts
* ├─┬ dist
* │ └── index.html > Electron-Renderer
* ```
*/
APP_ROOT: string
/** /dist/ or /public/ */ /** /dist/ or /public/ */
PUBLIC: string VITE_PUBLIC: string
} }
} }
+29 -26
View File
@@ -1,11 +1,16 @@
import { app, BrowserWindow, ipcMain, shell } from "electron"; import { app, BrowserWindow, ipcMain, shell } from "electron";
import * as fs from "node:fs"; import * as fs from "node:fs";
import { release } from "node:os"; import { createRequire } from "node:module";
import path, { join } from "node:path"; import os from "node:os";
import path from "node:path";
import { argv } from "node:process"; import { argv } from "node:process";
import { fileURLToPath } from "node:url";
import * as b3util from "../../src/misc/b3util"; import * as b3util from "../../src/misc/b3util";
import Path from "../../src/misc/path"; import Path from "../../src/misc/path";
const require = createRequire(import.meta.url);
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Check command line arguments // Check command line arguments
let buildProject: string | undefined; let buildProject: string | undefined;
let buildOutput: string | undefined; let buildOutput: string | undefined;
@@ -93,18 +98,22 @@ if (buildOutput || buildProject || buildHelp) {
// │ ├─┬ main // │ ├─┬ main
// │ │ └── index.js > Electron-Main // │ │ └── index.js > Electron-Main
// │ └─┬ preload // │ └─┬ preload
// │ └── index.js > Preload-Scripts // │ └── index.mjs > Preload-Scripts
// ├─┬ dist // ├─┬ dist
// │ └── index.html > Electron-Renderer // │ └── index.html > Electron-Renderer
// //
process.env.DIST_ELECTRON = join(__dirname, "../../"); process.env.APP_ROOT = path.join(__dirname, "../..");
process.env.DIST = join(process.env.DIST_ELECTRON, "../dist");
process.env.PUBLIC = process.env.VITE_DEV_SERVER_URL export const MAIN_DIST = path.join(process.env.APP_ROOT, "dist-electron");
? join(process.env.DIST_ELECTRON, "../public") export const RENDERER_DIST = path.join(process.env.APP_ROOT, "dist");
: process.env.DIST; export const VITE_DEV_SERVER_URL = process.env.VITE_DEV_SERVER_URL;
process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL
? path.join(process.env.APP_ROOT, "public")
: RENDERER_DIST;
// Disable GPU Acceleration for Windows 7 // Disable GPU Acceleration for Windows 7
if (release().startsWith("6.1")) app.disableHardwareAcceleration(); if (os.release().startsWith("6.1")) app.disableHardwareAcceleration();
// Set application name for Windows 10+ notifications // Set application name for Windows 10+ notifications
if (process.platform === "win32") app.setAppUserModelId(app.getName()); if (process.platform === "win32") app.setAppUserModelId(app.getName());
@@ -114,24 +123,19 @@ if (!app.requestSingleInstanceLock()) {
process.exit(0); process.exit(0);
} }
// Remove electron security warnings
// This warning only shows in development mode
// Read more on https://www.electronjs.org/docs/latest/tutorial/security
// process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'
interface Workspace { interface Workspace {
projectPath?: string; projectPath?: string;
window: BrowserWindow; window: BrowserWindow;
} }
const preload = "../preload/index.js"; const preload = path.join(__dirname, "../preload/index.mjs");
const url = process.env.VITE_DEV_SERVER_URL; const indexHtml = path.join(RENDERER_DIST, "index.html");
const indexHtml = join(process.env.DIST, "index.html");
const windows: Workspace[] = []; const windows: Workspace[] = [];
async function createWindow(projectPath?: string) { async function createWindow(projectPath?: string) {
const win = new BrowserWindow({ const win = new BrowserWindow({
title: "Behaviour3 Editor", title: "Behaviour3 Editor",
icon: Path.join(process.env.VITE_PUBLIC, "favicon.ico"),
frame: false, frame: false,
width: 1280, width: 1280,
height: 800, height: 800,
@@ -147,7 +151,6 @@ async function createWindow(projectPath?: string) {
: { color: "#0d1117", height: 35, symbolColor: "#7d8590" }, : { color: "#0d1117", height: 35, symbolColor: "#7d8590" },
backgroundColor: "#0d1117", backgroundColor: "#0d1117",
trafficLightPosition: { x: 10, y: 10 }, trafficLightPosition: { x: 10, y: 10 },
icon: join(process.env.PUBLIC, "favicon.ico"),
webPreferences: { webPreferences: {
preload, preload,
// Warning: Enable nodeIntegration and disable contextIsolation is not secure in production // Warning: Enable nodeIntegration and disable contextIsolation is not secure in production
@@ -164,9 +167,9 @@ async function createWindow(projectPath?: string) {
win.maximizable = true; win.maximizable = true;
if (process.env.VITE_DEV_SERVER_URL) { if (VITE_DEV_SERVER_URL) {
// electron-vite-vue#298 // #298
win.loadURL(url); win.loadURL(VITE_DEV_SERVER_URL);
// Open devTool if the app is not packaged // Open devTool if the app is not packaged
win.webContents.openDevTools(); win.webContents.openDevTools();
} else { } else {
@@ -174,6 +177,7 @@ async function createWindow(projectPath?: string) {
win.loadFile(indexHtml); win.loadFile(indexHtml);
} }
// Test actively push message to the Electron-Renderer
win.webContents.on("did-finish-load", () => { win.webContents.on("did-finish-load", () => {
win.webContents.setZoomFactor(1); win.webContents.setZoomFactor(1);
if (workspace.projectPath) { if (workspace.projectPath) {
@@ -209,7 +213,7 @@ async function createWindow(projectPath?: string) {
require("@electron/remote/main").enable(win.webContents); require("@electron/remote/main").enable(win.webContents);
// Apply electron-updater // Auto update
// update(win); // update(win);
} }
@@ -228,7 +232,6 @@ app.on("second-instance", () => {
app.on("activate", () => { app.on("activate", () => {
const allWindows = BrowserWindow.getAllWindows(); const allWindows = BrowserWindow.getAllWindows();
if (allWindows.length) { if (allWindows.length) {
allWindows[0].focus(); allWindows[0].focus();
} else { } else {
@@ -237,7 +240,7 @@ app.on("activate", () => {
}); });
// New window example arg: new windows url // New window example arg: new windows url
ipcMain.handle("open-win", (event, arg: string | undefined) => { ipcMain.handle("open-win", (event, arg) => {
if (arg) { if (arg) {
let workspace = windows.find((v) => v.projectPath === arg); let workspace = windows.find((v) => v.projectPath === arg);
if (workspace) { if (workspace) {
@@ -256,12 +259,12 @@ ipcMain.handle("open-win", (event, arg: string | undefined) => {
createWindow(arg); createWindow(arg);
}); });
ipcMain.handle("trashItem", (_, arg: string) => { ipcMain.handle("trashItem", (_, arg) => {
arg = arg.replace(/\//g, path.sep); arg = arg.replace(/\//g, path.sep);
shell.trashItem(arg).catch((e) => console.error(e)); shell.trashItem(arg).catch((e) => console.error(e));
}); });
ipcMain.handle("showItemInFolder", (_, arg: string) => { ipcMain.handle("showItemInFolder", (_, arg) => {
arg = arg.replace(/\//g, path.sep); arg = arg.replace(/\//g, path.sep);
shell.showItemInFolder(arg); shell.showItemInFolder(arg);
}); });
+41 -41
View File
@@ -1,76 +1,76 @@
import { app, ipcMain } from "electron"; import { app, ipcMain } from 'electron'
import { type ProgressInfo, type UpdateDownloadedEvent, autoUpdater } from "electron-updater"; import { createRequire } from 'node:module'
import type {
ProgressInfo,
UpdateDownloadedEvent,
UpdateInfo,
} from 'electron-updater'
const { autoUpdater } = createRequire(import.meta.url)('electron-updater');
export function update(win: Electron.BrowserWindow) { export function update(win: Electron.BrowserWindow) {
// When set to false, the update download will be triggered through the API // When set to false, the update download will be triggered through the API
autoUpdater.autoDownload = false; autoUpdater.autoDownload = false
autoUpdater.disableWebInstaller = false; autoUpdater.disableWebInstaller = false
autoUpdater.allowDowngrade = false; autoUpdater.allowDowngrade = false
// start check // start check
autoUpdater.on("checking-for-update", function () {}); autoUpdater.on('checking-for-update', function () { })
// update available // update available
autoUpdater.on("update-available", (arg) => { autoUpdater.on('update-available', (arg: UpdateInfo) => {
win.webContents.send("update-can-available", { win.webContents.send('update-can-available', { update: true, version: app.getVersion(), newVersion: arg?.version })
update: true, })
version: app.getVersion(),
newVersion: arg?.version,
});
});
// update not available // update not available
autoUpdater.on("update-not-available", (arg) => { autoUpdater.on('update-not-available', (arg: UpdateInfo) => {
win.webContents.send("update-can-available", { win.webContents.send('update-can-available', { update: false, version: app.getVersion(), newVersion: arg?.version })
update: false, })
version: app.getVersion(),
newVersion: arg?.version,
});
});
// Checking for updates // Checking for updates
ipcMain.handle("check-update", async () => { ipcMain.handle('check-update', async () => {
if (!app.isPackaged) { if (!app.isPackaged) {
const error = new Error("The update feature is only available after the package."); const error = new Error('The update feature is only available after the package.')
return { message: error.message, error }; return { message: error.message, error }
} }
try { try {
return await autoUpdater.checkForUpdatesAndNotify(); return await autoUpdater.checkForUpdatesAndNotify()
} catch (error) { } catch (error) {
return { message: "Network error", error }; return { message: 'Network error', error }
} }
}); })
// Start downloading and feedback on progress // Start downloading and feedback on progress
ipcMain.handle("start-download", (event) => { ipcMain.handle('start-download', (event: Electron.IpcMainInvokeEvent) => {
startDownload( startDownload(
(error, progressInfo) => { (error, progressInfo) => {
if (error) { if (error) {
// feedback download error message // feedback download error message
event.sender.send("update-error", { message: error.message, error }); event.sender.send('update-error', { message: error.message, error })
} else { } else {
// feedback update progress message // feedback update progress message
event.sender.send("download-progress", progressInfo); event.sender.send('download-progress', progressInfo)
} }
}, },
() => { () => {
// feedback update downloaded message // feedback update downloaded message
event.sender.send("update-downloaded"); event.sender.send('update-downloaded')
} }
); )
}); })
// Install now // Install now
ipcMain.handle("quit-and-install", () => { ipcMain.handle('quit-and-install', () => {
autoUpdater.quitAndInstall(false, true); autoUpdater.quitAndInstall(false, true)
}); })
} }
function startDownload( function startDownload(
callback: (error: Error | null, info: ProgressInfo) => void, callback: (error: Error | null, info: ProgressInfo | null) => void,
complete: (event: UpdateDownloadedEvent) => void complete: (event: UpdateDownloadedEvent) => void,
) { ) {
autoUpdater.on("download-progress", (info) => callback(null, info)); autoUpdater.on('download-progress', (info: ProgressInfo) => callback(null, info))
autoUpdater.on("error", (error) => callback(error, null!)); autoUpdater.on('error', (error: Error) => callback(error, null))
autoUpdater.on("update-downloaded", complete); autoUpdater.on('update-downloaded', complete)
autoUpdater.downloadUpdate(); autoUpdater.downloadUpdate()
} }
+27 -2
View File
@@ -1,3 +1,28 @@
// --------- Expose some API to the Renderer process ---------
// contextBridge.exposeInMainWorld("ipcRenderer", {
// on(...args: Parameters<typeof ipcRenderer.on>) {
// const [channel, listener] = args;
// return ipcRenderer.on(channel, (event, ...args) => listener(event, ...args));
// },
// off(...args: Parameters<typeof ipcRenderer.off>) {
// const [channel, ...omit] = args;
// return ipcRenderer.off(channel, ...omit);
// },
// send(...args: Parameters<typeof ipcRenderer.send>) {
// const [channel, ...omit] = args;
// return ipcRenderer.send(channel, ...omit);
// },
// invoke(...args: Parameters<typeof ipcRenderer.invoke>) {
// const [channel, ...omit] = args;
// return ipcRenderer.invoke(channel, ...omit);
// },
// // You can expose other APTs you need here.
// // ...
// });
// contextBridge.exposeInMainWorld("process", process);
// --------- Preload scripts loading ---------
function domReady(condition: DocumentReadyState[] = ["complete", "interactive"]) { function domReady(condition: DocumentReadyState[] = ["complete", "interactive"]) {
return new Promise((resolve) => { return new Promise((resolve) => {
if (condition.includes(document.readyState)) { if (condition.includes(document.readyState)) {
@@ -70,8 +95,8 @@ function useLoading() {
return { return {
appendLoading() { appendLoading() {
safeDOM.append(document.head, oStyle); // safeDOM.append(document.head, oStyle);
safeDOM.append(document.body, oDiv); // safeDOM.append(document.body, oDiv);
}, },
removeLoading() { removeLoading() {
safeDOM.remove(document.head, oStyle); safeDOM.remove(document.head, oStyle);
+3365 -153
View File
File diff suppressed because it is too large. Load diff
+36 -32
View File
@@ -1,51 +1,30 @@
{ {
"name": "behavior3editor", "name": "behavior3editor",
"version": "1.7.0", "version": "1.7.0",
"main": "dist-electron/electron/main/index.js", "main": "dist-electron/main/index.js",
"description": "行为树编辑器", "description": "行为树编辑器",
"author": "zhandouxiaojiji & codetypes", "author": "zhandouxiaojiji & codetypes",
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"type": "module",
"debug": { "debug": {
"env": { "env": {
"VITE_DEV_SERVER_URL": "http://127.0.0.1:7777/" "VITE_DEV_SERVER_URL": "http://127.0.0.1:7777/"
} }
}, },
"scripts": { "scripts": {
"tsc-check:": "tsc --noEmit",
"postinstall": "tsx pre-commit.ts",
"dev": "vite", "dev": "vite",
"build": "tsc && vite build && electron-builder", "build": "tsc && vite build && electron-builder",
"tsc-check:": "tsc --noEmit", "preview": "vite preview",
"postinstall": "copy-files-from-to" "pretest": "vite build --mode=test",
}, "test": "vitest run"
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/zhandouxiaojiji/behavior3editor.git"
}, },
"bugs": { "bugs": {
"url": "https://github.com/zhandouxiaojiji/behavior3editor/issues" "url": "https://github.com/zhandouxiaojiji/behavior3editor/issues"
}, },
"homepage": "https://github.com/zhandouxiaojiji/behavior3editor#readme", "homepage": "https://github.com/zhandouxiaojiji/behavior3editor#readme",
"devDependencies": {
"@stylistic/eslint-plugin-js": "^1.8.1",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitejs/plugin-react": "^4.3.4",
"copy-files-from-to": "^3.11.0",
"electron": "^30.3.1",
"electron-builder": "^24.13.3",
"eslint": "^8.57.0",
"eslint-plugin-react-refresh": "^0.4.9",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sass": "^1.77.8",
"typescript": "^5.5.4",
"vite": "^6.2.0",
"vite-electron-plugin": "^0.8.3",
"vite-plugin-electron": "^0.28.7",
"vite-plugin-electron-renderer": "^0.14.5"
},
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.4.0", "@ant-design/icons": "^5.4.0",
"@antv/g6": "^4.8.24", "@antv/g6": "^4.8.24",
@@ -55,7 +34,7 @@
"ahooks": "^3.8.0", "ahooks": "^3.8.0",
"antd": "^5.20.0", "antd": "^5.20.0",
"electron-localshortcut": "^3.2.1", "electron-localshortcut": "^3.2.1",
"electron-updater": "^6.3.2", "electron-updater": "^6.3.9",
"i18next": "^23.12.2", "i18next": "^23.12.2",
"i18next-browser-languagedetector": "^7.2.1", "i18next-browser-languagedetector": "^7.2.1",
"i18next-http-backend": "^2.5.2", "i18next-http-backend": "^2.5.2",
@@ -67,10 +46,35 @@
"ts-key-enum": "^2.0.12", "ts-key-enum": "^2.0.12",
"use-force-update": "^1.0.11", "use-force-update": "^1.0.11",
"usehooks-ts": "^3.1.0", "usehooks-ts": "^3.1.0",
"zustand": "^4.5.4" "zustand": "^5.0.3"
}, },
"engines": { "devDependencies": {
"node": "^14.18.0 || >=16.0.0" "@playwright/test": "^1.48.2",
"@stylistic/eslint-plugin-js": "^1.8.1",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20",
"copy-files-from-to": "^3.11.0",
"electron": "^33.2.0",
"electron-builder": "^24.13.3",
"eslint": "^8.57.0",
"eslint-plugin-react-refresh": "^0.4.9",
"postcss": "^8.4.49",
"postcss-import": "^16.1.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sass": "^1.77.8",
"tailwindcss": "^3.4.15",
"tsx": "^4.19.3",
"typescript": "^5.8.2",
"vite": "^6.2.0",
"vite-electron-plugin": "^0.8.3",
"vite-plugin-electron": "^0.29.0",
"vite-plugin-electron-renderer": "^0.14.6",
"vitest": "^2.1.5"
}, },
"copyFilesSettings": { "copyFilesSettings": {
"whenFileExists": "overwrite" "whenFileExists": "overwrite"
+8
View File
@@ -0,0 +1,8 @@
module.exports = {
plugins: {
'postcss-import': {},
'tailwindcss/nesting': {},
tailwindcss: {},
autoprefixer: {},
},
}
-18
View File
@@ -1,18 +0,0 @@
#!/bin/sh
echo -e "\nValidating Javascript:\n"
# Check for eslint
which tsc &> /dev/null
if [[ "$?" == 1 ]]; then
echo -e "\t\033[41mPlease install tsc\033[0m"
exit 1
fi
tsc --noEmit
if [[ "$?" == 0 ]]; then
echo -e "\033[42mCOMMIT SUCCEEDED\033[0m\n"
exit 0
else
echo -e "\033[41mCOMMIT FAILED:\033[0m Your commit contains files that should pass ESLint but do not. Please fix the ESLint errors and try again.\n"
exit 1
fi
+24
View File
@@ -0,0 +1,24 @@
import * as fs from "node:fs";
const hooks = `
#!/bin/sh
echo -e "\nValidating Javascript:\n"
# Check for eslint
which tsc &> /dev/null
if [[ "$?" == 1 ]]; then
echo -e "\t\x1b[41mPlease install tsc\x1b[0m"
exit 1
fi
tsc --noEmit
if [[ "$?" == 0 ]]; then
echo -e "\x1b[42mCOMMIT SUCCEEDED\x1b[0m\n"
exit 0
else
echo -e "\x1b[41mCOMMIT FAILED:\x1b[0m Your commit contains files that should pass ESLint but do not. Please fix the ESLint errors and try again.\n"
exit 1
fi
`;
fs.writeFileSync(".git/hooks/pre-commit", hooks);
fs.chmodSync(".git/hooks/pre-commit", 0o755);
+1 -1
View File
@@ -10,7 +10,7 @@
"cancel": "取消", "cancel": "取消",
"copy": "复制", "copy": "复制",
"console": "控制台", "console": "控制台",
"cut": "替换", "cut": "剪切",
"createProject": "新建项目", "createProject": "新建项目",
"delete": "删除", "delete": "删除",
"deleteNode": "删除节点", "deleteNode": "删除节点",
+2 -3
View File
@@ -35,7 +35,6 @@ import {
isNodeArgArray, isNodeArgArray,
isNodeArgOptional, isNodeArgOptional,
isValidVariableName, isValidVariableName,
nodeDefs,
} from "../misc/b3util"; } from "../misc/b3util";
import { Hotkey, isMacos } from "../misc/keys"; import { Hotkey, isMacos } from "../misc/keys";
import { mergeClassNames } from "../misc/util"; import { mergeClassNames } from "../misc/util";
@@ -121,7 +120,7 @@ const NodeInspector: FC = () => {
// set form values // set form values
useEffect(() => { useEffect(() => {
const data = workspace.editingNode.data; const data = workspace.editingNode.data;
const def = nodeDefs.get(workspace.editingNode.data.name); const def = workspace.nodeDefs.get(workspace.editingNode.data.name);
form.resetFields(); form.resetFields();
form.setFieldValue("id", data.id); form.setFieldValue("id", data.id);
form.setFieldValue("name", data.name); form.setFieldValue("name", data.name);
@@ -237,7 +236,7 @@ const NodeInspector: FC = () => {
}, [workspace.allFiles, workspace.fileTree]); }, [workspace.allFiles, workspace.fileTree]);
const editingNode = workspace.editingNode; const editingNode = workspace.editingNode;
const def = nodeDefs.get(editingNode.data.name); const def = workspace.nodeDefs.get(editingNode.data.name);
const disabled = !editingNode.editable; const disabled = !editingNode.editable;
// update value // update value
+15 -13
View File
@@ -12,7 +12,7 @@ import { useSetting } from "../contexts/setting-context";
import { useWorkspace } from "../contexts/workspace-context"; import { useWorkspace } from "../contexts/workspace-context";
import * as b3util from "../misc/b3util"; import * as b3util from "../misc/b3util";
import i18n from "../misc/i18n"; import i18n from "../misc/i18n";
import { Hotkey, isMacos, sendInputEvent } from "../misc/keys"; import { Hotkey, isMacos } from "../misc/keys";
const MenuItemLabel: FC<FlexProps> = (itemProps) => { const MenuItemLabel: FC<FlexProps> = (itemProps) => {
return ( return (
@@ -175,9 +175,9 @@ export const Menu: FC<LayoutProps> = () => {
id: "menu.edit.undo", id: "menu.edit.undo",
label: t("undo"), label: t("undo"),
enabled: enabled, enabled: enabled,
accelerator: Hotkey.Undo, accelerator: Hotkey.Undo.replaceAll(".", "+"),
click: () => { click: () => {
sendInputEvent(Hotkey.Undo); // sendInputEvent(Hotkey.Undo);
getFocusedWebContents()?.undo(); getFocusedWebContents()?.undo();
}, },
}, },
@@ -185,9 +185,9 @@ export const Menu: FC<LayoutProps> = () => {
id: "menu.edit.redo", id: "menu.edit.redo",
label: t("redo"), label: t("redo"),
enabled: enabled, enabled: enabled,
accelerator: Hotkey.Redo, accelerator: Hotkey.Redo.replaceAll(".", "+"),
click: () => { click: () => {
sendInputEvent(Hotkey.Redo); // sendInputEvent(Hotkey.Redo);
getFocusedWebContents()?.redo(); getFocusedWebContents()?.redo();
}, },
}, },
@@ -196,9 +196,9 @@ export const Menu: FC<LayoutProps> = () => {
id: "menu.edit.copy", id: "menu.edit.copy",
label: t("copy"), label: t("copy"),
enabled: enabled, enabled: enabled,
accelerator: Hotkey.Copy, accelerator: Hotkey.Copy.replaceAll(".", "+"),
click: () => { click: () => {
sendInputEvent(Hotkey.Copy); // sendInputEvent(Hotkey.Copy);
getFocusedWebContents()?.copy(); getFocusedWebContents()?.copy();
}, },
}, },
@@ -206,9 +206,9 @@ export const Menu: FC<LayoutProps> = () => {
id: "menu.edit.paste", id: "menu.edit.paste",
label: t("paste"), label: t("paste"),
enabled: enabled, enabled: enabled,
accelerator: Hotkey.Paste, accelerator: Hotkey.Paste.replaceAll(".", "+"),
click: () => { click: () => {
sendInputEvent(Hotkey.Paste); // sendInputEvent(Hotkey.Paste);
getFocusedWebContents()?.paste(); getFocusedWebContents()?.paste();
}, },
}, },
@@ -216,7 +216,7 @@ export const Menu: FC<LayoutProps> = () => {
id: "menu.edit.cut", id: "menu.edit.cut",
label: t("cut"), label: t("cut"),
enabled: enabled, enabled: enabled,
accelerator: Hotkey.Cut, accelerator: Hotkey.Cut.replaceAll(".", "+"),
click: () => { click: () => {
getFocusedWebContents()?.cut(); getFocusedWebContents()?.cut();
}, },
@@ -225,7 +225,7 @@ export const Menu: FC<LayoutProps> = () => {
id: "menu.edit.selectAll", id: "menu.edit.selectAll",
label: t("selectAll"), label: t("selectAll"),
enabled: enabled, enabled: enabled,
accelerator: Hotkey.SelectAll, accelerator: Hotkey.SelectAll.replaceAll(".", "+"),
click: () => { click: () => {
getFocusedWebContents()?.selectAll(); getFocusedWebContents()?.selectAll();
}, },
@@ -235,16 +235,18 @@ export const Menu: FC<LayoutProps> = () => {
id: "menu.edit.insertNode", id: "menu.edit.insertNode",
label: t("insertNode"), label: t("insertNode"),
enabled: enabled, enabled: enabled,
accelerator: Hotkey.Enter.replaceAll(".", "+"),
click: () => { click: () => {
workspace.editing?.dispatch("insert"); // workspace.editing?.dispatch("insert");
}, },
}, },
{ {
id: "menu.edit.deleteNode", id: "menu.edit.deleteNode",
label: t("deleteNode"), label: t("deleteNode"),
enabled: enabled, enabled: enabled,
accelerator: Hotkey.Backspace.replaceAll(".", "+"),
click: () => { click: () => {
workspace.editing?.dispatch("delete"); // workspace.editing?.dispatch("delete");
}, },
}, },
], ],
+6 -2
View File
@@ -1,6 +1,7 @@
import G6 from "@antv/g6"; import G6 from "@antv/g6";
import { useWorkspace } from "../contexts/workspace-context";
import { TreeGraphData, getNodeType } from "../misc/b3type"; import { TreeGraphData, getNodeType } from "../misc/b3type";
import { checkTreeData, nodeDefs, workdir } from "../misc/b3util"; import { checkTreeData, getNodeDefs } from "../misc/b3util";
import i18n from "../misc/i18n"; import i18n from "../misc/i18n";
import { isMacos } from "../misc/keys"; import { isMacos } from "../misc/keys";
@@ -141,6 +142,7 @@ G6.registerNode(
}, },
draw(cfg, group) { draw(cfg, group) {
const data = cfg as TreeGraphData; const data = cfg as TreeGraphData;
const nodeDefs = getNodeDefs();
const nodeDef = nodeDefs.get(data.name); const nodeDef = nodeDefs.get(data.name);
let classify = getNodeType(nodeDef); let classify = getNodeType(nodeDef);
let color = nodeDef.color || NODE_COLORS[classify] || NODE_COLORS["Other"]; let color = nodeDef.color || NODE_COLORS[classify] || NODE_COLORS["Other"];
@@ -257,7 +259,9 @@ G6.registerNode(
}); });
// icon // icon
const img = nodeDef.icon ? `file:///${workdir}/${nodeDef.icon}` : `./icons/${classify}.svg`; const img = nodeDef.icon
? `file:///${useWorkspace.getState().workdir}/${nodeDef.icon}`
: `./icons/${classify}.svg`;
addShape("image", { addShape("image", {
attrs: { attrs: {
x: 5, x: 5,
+3 -3
View File
@@ -155,7 +155,7 @@ export type WorkspaceStore = {
loadTrees: () => void; loadTrees: () => void;
loadNodeDefs: () => void; loadNodeDefs: () => void;
nodeDefs: Map<string, NodeDef>; nodeDefs: b3util.NodeDefs;
// edit node // edit node
editingNode?: EditNode | null; editingNode?: EditNode | null;
@@ -609,11 +609,11 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ({
} }
}, },
nodeDefs: new Map(), nodeDefs: new b3util.NodeDefs(),
loadNodeDefs: () => { loadNodeDefs: () => {
const workspace = get(); const workspace = get();
b3util.initWorkdir(workspace.workdir, message.error.bind(message)); b3util.initWorkdir(workspace.workdir, message.error.bind(message));
set({ nodeDefs: b3util.nodeDefs }); set({ nodeDefs: b3util.getNodeDefs() });
workspace.editing?.dispatch("refresh"); workspace.editing?.dispatch("refresh");
}, },
+12 -6
View File
@@ -16,8 +16,15 @@ import {
import Path from "./path"; import Path from "./path";
import { readJson } from "./util"; import { readJson } from "./util";
export let workdir: string = ""; export class NodeDefs extends Map<string, NodeDef> {
get(key: string): NodeDef {
return super.get(key) ?? unknownNodeDef;
}
}
let workdir: string = "";
let alertError: (msg: string, duration?: number) => void = () => {}; let alertError: (msg: string, duration?: number) => void = () => {};
let nodeDefs: NodeDefs = new NodeDefs();
const unknownNodeDef: NodeDef = { const unknownNodeDef: NodeDef = {
name: "unknown", name: "unknown",
@@ -25,16 +32,15 @@ const unknownNodeDef: NodeDef = {
type: "Action", type: "Action",
}; };
export const nodeDefs = new (class extends Map<string, NodeDef> { export const getNodeDefs = () => {
get(key: string): NodeDef { return nodeDefs;
return super.get(key) ?? unknownNodeDef; };
}
})();
export const initWorkdir = (path: string, handler: typeof alertError) => { export const initWorkdir = (path: string, handler: typeof alertError) => {
workdir = path; workdir = path;
alertError = handler; alertError = handler;
const nodeDefData = readJson(`${workdir}/node-config.b3-setting`) as NodeDef[]; const nodeDefData = readJson(`${workdir}/node-config.b3-setting`) as NodeDef[];
nodeDefs = new NodeDefs();
for (const v of nodeDefData) { for (const v of nodeDefData) {
nodeDefs.set(v.name, v); nodeDefs.set(v.name, v);
} }
+5
View File
@@ -1 +1,6 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
interface Window {
// expose in the `electron/preload/index.ts`
ipcRenderer: import("electron").IpcRenderer;
}
+14
View File
@@ -0,0 +1,14 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
'./index.html',
'./src/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {},
},
corePlugins: {
preflight: false,
},
plugins: [],
}
+59 -37
View File
@@ -1,59 +1,81 @@
import react from "@vitejs/plugin-react"; import react from "@vitejs/plugin-react";
import { rmSync } from "node:fs"; import { rmSync } from "node:fs";
import path from "node:path";
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import electron from "vite-electron-plugin"; import electron from "vite-plugin-electron/simple";
import { customStart, loadViteEnv } from "vite-electron-plugin/plugin";
import renderer from "vite-plugin-electron-renderer";
import pkg from "./package.json"; import pkg from "./package.json";
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig(({ command }) => { export default defineConfig(({ command }) => {
rmSync("dist-electron", { recursive: true, force: true }); rmSync("dist-electron", { recursive: true, force: true });
const sourcemap = true; //command === "serve" || !!process.env.VSCODE_DEBUG; const isServe = command === "serve";
const isBuild = false; //command === "build";
const sourcemap = true; //isServe || !!process.env.VSCODE_DEBUG;
return { return {
resolve: {
alias: {
"@": path.join(__dirname, "src"),
},
},
build: { build: {
sourcemap: true, sourcemap,
}, },
plugins: [ plugins: [
react(), react(),
electron({ electron({
include: [ main: {
"electron", // Shortcut of `build.lib.entry`
"src/misc/b3type.ts", entry: "electron/main/index.ts",
"src/misc/b3util.ts", onstart(args) {
"src/misc/path.ts", if (process.env.VSCODE_DEBUG) {
"src/misc/util.ts", console.log(/* For `.vscode/.debug.script.mjs` */ "[startup] Electron App");
], } else {
transformOptions: { args.startup();
sourcemap, }
},
vite: {
build: {
sourcemap,
minify: isBuild,
outDir: "dist-electron/main",
rollupOptions: {
external: Object.keys("dependencies" in pkg ? pkg.dependencies : {}),
},
},
},
}, },
plugins: [ preload: {
...(!!process.env.VSCODE_DEBUG // Shortcut of `build.rollupOptions.input`.
? [ // Preload scripts may contain Web assets, so use the `build.rollupOptions.input` instead `build.lib.entry`.
// Will start Electron via VSCode Debug input: "electron/preload/index.ts",
customStart(() => vite: {
console.log(/* For `.vscode/.debug.script.mjs` */ "[startup] Electron App") build: {
), sourcemap: sourcemap ? "inline" : undefined, // #332
] minify: isBuild,
: []), outDir: "dist-electron/preload",
// Allow use `import.meta.env.VITE_SOME_KEY` in Electron-Main rollupOptions: {
loadViteEnv(), external: Object.keys("dependencies" in pkg ? pkg.dependencies : {}),
], },
},
},
},
// Ployfill the Electron and Node.js API for Renderer process.
// If you want use Node.js in Renderer process, the `nodeIntegration` needs to be enabled in the Main process.
// See 👉 https://github.com/electron-vite/vite-plugin-electron-renderer
renderer: {},
}), }),
// Use Node.js API in the Renderer-process
renderer(),
], ],
server: !!process.env.VSCODE_DEBUG server:
? (() => { process.env.VSCODE_DEBUG &&
const url = new URL(pkg.debug.env.VITE_DEV_SERVER_URL); (() => {
return { const url = new URL(pkg.debug.env.VITE_DEV_SERVER_URL);
host: url.hostname, return {
port: +url.port, host: url.hostname,
}; port: +url.port,
})() };
: undefined, })(),
clearScreen: false, clearScreen: false,
}; };
}); });