Feat: Update dependencies and remove unnecessary files

This commit is contained in:
anmengweilai 2024-01-10 19:03:13 +08:00 committed by lizhihong
parent 85ea19a33b
commit 148839e951
27 changed files with 1048 additions and 1497 deletions

84
webapp/.eslintrc.cjs Normal file
View File

@ -0,0 +1,84 @@
// /* eslint-env node */
// require('@rushstack/eslint-patch/modern-module-resolution');
//
// module.exports = {
// 'root': true,
// 'env': {
// 'es2021': true,
// 'node': true,
// 'browser': false,
// },
// extends: [
// 'eslint:recommended',
// /** @see https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#recommended-configs */
// // 'plugin:@typescript-eslint/recommended',
// 'prettier',
// 'plugin:prettier/recommended',
// 'plugin:vue/vue3-recommended',
// '@electron-toolkit',
// '@electron-toolkit/eslint-config-ts/eslint-recommended',
// '@vue/eslint-config-typescript/recommended',
// '@vue/eslint-config-prettier',
// ],
// rules: {
// 'vue/require-default-prop': 'off',
// 'vue/multi-word-component-names': 'off',
// },
// // 'parser': '@typescript-eslint/parser',
// 'parserOptions': {
// 'ecmaVersion': 12,
// 'sourceType': 'module',
// },
// // 'plugins': ['@typescript-eslint'],
// 'ignorePatterns': ['node_modules/**', '**/dist/**'],
// 'rules': {
// // '@typescript-eslint/no-unused-vars': [
// // 'error',
// // {
// // 'argsIgnorePattern': '^_',
// // 'varsIgnorePattern': '^_',
// // },
// // ],
// // '@typescript-eslint/no-var-requires': 'off',
// // '@typescript-eslint/consistent-type-imports': 'error',
// /**
// * Having a semicolon helps the optimizer interpret your code correctly.
// * This avoids rare errors in optimized code.
// * @see https://twitter.com/alex_kozack/status/1364210394328408066
// */
// 'semi': ['error', 'always'],
// /**
// * This will make the history of changes in the hit a little cleaner
// */
// 'comma-dangle': ['warn', 'always-multiline'],
// /**
// * Just for beauty
// */
// 'quotes': [
// 'warn',
// 'single',
// {
// 'avoidEscape': true,
// },
// ],
// // '@typescript-eslint/no-explicit-any': 'off',
// // '@typescript-eslint/ban-types': 'off',
// },
// };
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
extends: [
'eslint:recommended',
'plugin:vue/vue3-recommended',
'@electron-toolkit',
'@electron-toolkit/eslint-config-ts/eslint-recommended',
'@vue/eslint-config-typescript/recommended',
'@vue/eslint-config-prettier'
],
rules: {
'vue/require-default-prop': 'off',
'vue/multi-word-component-names': 'off'
}
}

View File

@ -1,55 +0,0 @@
{
"root": true,
"env": {
"es2021": true,
"node": true,
"browser": false
},
"extends": [
"eslint:recommended",
/** @see https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#recommended-configs */
"plugin:@typescript-eslint/recommended",
"prettier",
"plugin:prettier/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"ignorePatterns": ["node_modules/**", "**/dist/**"],
"rules": {
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
],
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/consistent-type-imports": "error",
/**
* Having a semicolon helps the optimizer interpret your code correctly.
* This avoids rare errors in optimized code.
* @see https://twitter.com/alex_kozack/status/1364210394328408066
*/
"semi": ["error", "always"],
/**
* This will make the history of changes in the hit a little cleaner
*/
"comma-dangle": ["warn", "always-multiline"],
/**
* Just for beauty
*/
"quotes": [
"warn",
"single",
{
"avoidEscape": true
}
],
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/ban-types": "off"
}
}

View File

@ -1,7 +1,5 @@
auto-install-peers=true
electron_mirror=https://npmmirror.com/mirrors/electron/
lockfile=false
resolution-mode=highest
shamefully-hoist=true
node-linker=hoisted
registry=https://registry.npmmirror.com
electron_mirror=https://npmmirror.com/mirrors/electron/
shamefully-hoist=true

View File

@ -21,27 +21,41 @@
"format": "npx prettier --write \"**/*.{js,mjs,cjs,ts,mts,cts,vue,json}\"",
"dev:main": "npm run start --prefix=packages/main",
"dev:renderer": "npm run start --prefix=packages/renderer",
"start": "concurrently \"npm run dev:main\" \"npm run dev:renderer\"",
"start": "concurrently \"npm run dev:renderer\" \"npm run dev:main\" ",
"electron:mac-zip": "ts-node scripts/buildMacZip.ts",
"build": "npm run build:renderer && npm run build:electron",
"build:electron": "npm run build --prefix=packages/main",
"build:renderer": "npm run build --prefix=packages/renderer"
"build:renderer": "npm run build --prefix=packages/renderer",
"clean:app": "rm -rf node_modules",
"clean:common": "npm run clean:modules --prefix=packages/common",
"clean:main": "npm run clean:modules --prefix=packages/main",
"clean:preload": "npm run clean:modules --prefix=packages/preload",
"clean:renderer": "npm run clean:modules --prefix=packages/renderer",
"clean": "npm run clean:app && npm run clean:common && npm run clean:main && npm run clean:preload && npm run clean:renderer"
},
"devDependencies": {
"@electron-toolkit/eslint-config": "^1.0.2",
"@electron-toolkit/eslint-config-ts": "^1.0.1",
"@electron-toolkit/tsconfig": "^1.0.1",
"@types/js-yaml": "^4",
"@types/fs-extra": "^11.0.1",
"@types/lodash-es": "^4.17.7",
"@types/node": "18.15.3",
"@typescript-eslint/eslint-plugin": "5.55.0",
"@typescript-eslint/parser": "^5.58.0",
"@vitejs/plugin-vue": "4.0.0",
"@rushstack/eslint-patch": "^1.6.1",
"@vue/eslint-config-prettier": "^9.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/test-utils": "2.3.1",
"consola": "^3.1.0",
"cross-env": "7.0.3",
"electron": "^24",
"electron": "^24",
"electron-builder": "^23",
"eslint": "8.36.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "9.9.0",
"eslint-plugin-vue": "^9.19.2",
"father": "^4",
"happy-dom": "8.9.0",
"nano-staged": "0.8.0",
@ -54,14 +68,14 @@
"vite": "^4.3.1",
"concurrently": "^8",
"vite-plugin-style-import": "^2.0.0",
"vitest": "0.29.3"
"vitest": "0.29.3",
"js-yaml": "^4"
},
"dependencies": {
"@electron-toolkit/preload": "^3.0.0",
"@electron-toolkit/utils": "^3.0.0",
"@vueuse/core": "^10.0.2",
"dayjs": "^1.11.7",
"electron-log": "^4.4.8",
"electron-updater": "5.3.0",
"@electron-toolkit/preload": "^1.0.0",
"fast-glob": "^3.2.12",
"fs-extra": "^11.1.1",
"lodash-es": "^4.17.21",

View File

@ -1,5 +0,0 @@
import { defineConfig } from 'father';
export default defineConfig({
cjs: { output: 'lib', platform: 'browser' },
});

View File

@ -3,11 +3,10 @@
"version": "0.4.0",
"description": "alas webapp common",
"private": true,
"main": "src/index.ts",
"main": "src/index.ts",
"scripts": {
"build": "father build",
"postinstall": "npm run build",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'"
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"clean:modules": "rm -rf node_modules"
},
"license": "ISC",
"dependencies": {

View File

@ -13,7 +13,7 @@ module.exports = {
*/
appId: 'com.azur-lane-auto-script.webapp',
productName: 'AzurLaneAutoScript',
// copyright: 'Copyright © 2021 - ALAS | All Right Reserved.',
copyright: 'Copyright © 2021 - ALAS | All Right Reserved.',
/**
* 配置 notarize dmg
@ -23,94 +23,95 @@ module.exports = {
* APPLE_ID_PASSWORD= app-specific 密码 可以在 appleid.apple.com 创建
*
*/
afterSign:
process.env.NOTARIZE === 'false'
? () => {
console.log('Skip notarize...');
}
: 'electron-builder-notarize',
// afterSign:
// process.env.NOTARIZE === 'false'
// ? () => {
// console.log('Skip notarize...');
// }
// : 'electron-builder-notarize',
/**
* win 配置项
*/
win: {
artifactName: '${name}_setup_${version}.${ext}',
target: ['nsis'],
},
nsis: {
oneClick: false,
perMachine: true,
allowToChangeInstallationDirectory: true,
license: 'build/license.txt',
},
// win: {
// artifactName: '${name}_setup_${version}.${ext}',
// target: ['nsis'],
// },
// nsis: {
// oneClick: false,
// perMachine: true,
// allowToChangeInstallationDirectory: true,
// license: 'build/license.txt',
// },
/**
* mac 配置项
*/
mac: {
category: 'public.app-category.developer-tools',
target: ['dmg'],
artifactName: '${name}_setup_${version}.${ext}',
hardenedRuntime: true,
gatekeeperAssess: false,
darkModeSupport: true,
entitlements: 'build/entitlements.mac.plist',
entitlementsInherit: 'build/entitlements.mac.plist',
},
dmg: {
// icon: 'build/volume.icns',
// background: 'build/background.png',
// title: '${productName}',
// iconSize: 80,
window: {
height: 422,
width: 600,
},
// contents: [
// {
// type: 'file',
// x: 144,
// y: 199,
// },
// {
// type: 'link',
// path: '/Applications',
// x: 451,
// y: 199,
// },
// ],
},
mas: {
hardenedRuntime: false,
darkModeSupport: true,
provisioningProfile: 'build/embedded.provisionprofile',
category: 'public.app-category.productivity',
entitlements: 'build/entitlements.mas.plist',
entitlementsInherit: 'build/entitlements.mas.inherit.plist',
asarUnpack: [],
},
// mac: {
// category: 'public.app-category.developer-tools',
// target: ['dmg'],
// artifactName: '${name}_setup_${version}.${ext}',
// hardenedRuntime: true,
// gatekeeperAssess: false,
// darkModeSupport: true,
// entitlements: 'build/entitlements.mac.plist',
// entitlementsInherit: 'build/entitlements.mac.plist',
// },
// dmg: {
// icon: 'build/volume.icns',
// background: 'build/background.png',
// title: '${productName}',
// iconSize: 80,
// window: {
// height: 422,
// width: 600,
// },
// contents: [
// {
// type: 'file',
// x: 144,
// y: 199,
// },
// {
// type: 'link',
// path: '/Applications',
// x: 451,
// y: 199,
// },
// ],
// },
// mas: {
// hardenedRuntime: false,
// darkModeSupport: true,
// provisioningProfile: 'build/embedded.provisionprofile',
// category: 'public.app-category.productivity',
// entitlements: 'build/entitlements.mas.plist',
// entitlementsInherit: 'build/entitlements.mas.inherit.plist',
// asarUnpack: [],
// },
/**
* linux 配置项
*/
linux: {
artifactName: '${name}_setup_${version}.${ext}',
icon: 'build/icon.png',
synopsis: 'azur lane auto script',
category: 'Development',
// artifactName: '${name}_setup_${version}.${ext}',
// icon: 'build/icon.png',
// synopsis: 'azur lane auto script',
// category: 'Development',
target: 'deb',
},
/**
* Publish 配置
*/
publish: ['github'],
// publish: ['github'],
/**
* 构建配置项
*/
compression: 'maximum', // 压缩比例
npmRebuild: false,
asar: {
smartUnpack: true,
},
// compression: 'maximum', // 压缩比例
// // npmRebuild: true,
// // asar: {
// // smartUnpack: true,
// // },
};

View File

@ -1,6 +1,7 @@
import {defineConfig, externalizeDepsPlugin} from 'electron-vite';
import {join} from 'node:path';
import {preload} from 'unplugin-auto-expose';
import {resolve} from 'path';
const isDev = process.env.MODE !== 'development';

View File

@ -8,22 +8,23 @@
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"postuninstall": "electron-builder install-app-deps",
"prebuild": "electron-vite build",
"build": "npm run prebuild && electron-builder build --config electron-builder.config.js",
"build": "npm run prebuild && electron-builder build --config electron-builder.config.js --dir",
"clean": "rm -rf dist release .eslintcache",
"dev": "electron-vite dev -w",
"start": "npm run dev",
"start": "electron-vite preview",
"electron:build-local": "NOTARIZE=false npm run build -- --dir --config.asar=false",
"electron:build:linux": "npm run build --linux",
"electron:build:mac": "npm run build --mac",
"electron:build:win": "npm run build --win",
"postinstall": "electron-builder install-app-deps"
"postinstall": "electron-builder install-app-deps",
"clean:modules": "rm -rf node_modules"
},
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^4",
"electron-is": "^3",
"electron-updater": "^4.6.5",
"electron-updater": "^6.1.7",
"log4js": "^6.4.1",
"os-name": "^4",
"reflect-metadata": "^0.1.13",
@ -31,16 +32,14 @@
"python-shell": "^5.0.0"
},
"devDependencies": {
"@alas/common": "^0.4.0",
"@alas/common": "0.4.0",
"@types/fs-extra": "^9",
"concurrently": "^8",
"cross-env": "^7",
"electron": "24.8.8",
"electron-builder": "^23",
"electron": "^28.1.1",
"electron-builder": "^24.9.1",
"electron-vite": "^2.0.0",
"electron-builder-notarize": "^1",
"electron-debug": "^3",
"electron-devtools-installer": "^3",
"electron-vite": "^1",
"happy-dom": "^9",
"@vue/devtools": "^7",
"vitest": "latest"

View File

@ -1,43 +0,0 @@
import type {CoreService} from '@/coreService';
import type {BrowserWindow} from 'electron';
import {app, ipcMain, nativeTheme} from 'electron';
import {ThemeObj, ELECTRON_THEME, INSTALLER_READY, PAGE_ERROR, WINDOW_READY} from '@alas/common';
import logger from '@/logger';
export const addIpcMainListener = async (mainWindow: BrowserWindow, coreService: CoreService) => {
// Minimize, maximize, close window.
ipcMain.on('window-tray', function () {
mainWindow?.hide();
});
ipcMain.on('window-minimize', function () {
mainWindow?.minimize();
});
ipcMain.on('window-maximize', function () {
mainWindow?.isMaximized() ? mainWindow?.restore() : mainWindow?.maximize();
});
ipcMain.on('window-close', function () {
coreService?.kill();
mainWindow?.close();
app.exit(0);
});
ipcMain.on(WINDOW_READY, async function (_, args) {
logger.info('-----WINDOW_READY-----');
args && (await coreService.run());
});
ipcMain.on(INSTALLER_READY, function () {
logger.info('-----INSTALLER_READY-----');
coreService.next();
});
ipcMain.on(ELECTRON_THEME, (_, args) => {
logger.info('-----ELECTRON_THEME-----');
nativeTheme.themeSource = ThemeObj[args];
});
ipcMain.on(PAGE_ERROR, (_, args) => {
logger.info('-----PAGE_ERROR-----');
logger.error(args);
});
};

View File

@ -4,7 +4,7 @@ import type {DefAlasConfig} from '@alas/common';
import {ALAS_INSTR_FILE} from '@alas/common';
import {validateConfigFile} from '@/utils/validate';
import {join} from 'path';
import logger from '@/logger';
import { logger } from "@/core/Logger/customLogger";
const yaml = require('yaml');
const fs = require('fs');

View File

@ -75,21 +75,29 @@ export default class Browser extends EventEmitter {
* @param count
*/
loadUrl = (name: BrowserWindowsIdentifier, count = 1) => {
this.app.logger.info('loadUrl');
if (count > 10) return;
if (isDev) {
// this.browserWindow.loadURL(`http://localhost:5173/${name}.html`);
this.app.logger.info('http://localhost:7777/');
this.browserWindow.loadURL('http://localhost:7777/').catch(_ => {
/**
*
*/
setTimeout(() => {
this.loadUrl(name, ++count);
}, 2000);
});
} else {
this.browserWindow.loadURL(`app://./${name}.html`);
}
this.browserWindow.loadURL('http://localhost:7777/').catch(_ => {
/**
*
*/
setTimeout(() => {
this.loadUrl(name, ++count);
}, 2000);
});
// if (isDev) {
// // this.browserWindow.loadURL(`http://localhost:5173/${name}.html`);
// this.browserWindow.loadURL('http://localhost:7777/').catch(_ => {
// /**
// * 暂时没有想到更好解决方案
// */
// setTimeout(() => {
// this.loadUrl(name, ++count);
// }, 2000);
// });
// } else {
// this.browserWindow.loadURL(`app://./${name}.html`);
// }
};
/**
*
@ -119,7 +127,6 @@ export default class Browser extends EventEmitter {
/**
* alasService
*/
app.quit();
process.exit(0);
},
@ -242,7 +249,7 @@ export default class Browser extends EventEmitter {
// https://www.electronjs.org/docs/tutorial/context-isolation
contextIsolation: true,
// devTools: isDev,
preload: join(app.getAppPath(), '../preload/dist/index.js'),
// preload: join(app.getAppPath(), '../preload/dist/index.js'),
},
});

View File

@ -1,91 +0,0 @@
import type {PyShell} from '@/pyshell';
import {createAlas, createInstaller} from '@/serviceLogic';
import {ALAS_LOG} from '@alas/common';
import {BrowserWindow} from 'electron';
import logger from '@/logger';
export interface CoreServiceOption {
appABSPath?: string;
isFirstRun?: boolean;
theme?: 'light' | 'dark';
mainWindow: Electron.BrowserWindow | null;
}
const defOptions = {
appABSPath: '',
theme: 'light',
isFirstRun: false,
mainWindow: BrowserWindow.getAllWindows()[0] || null,
};
export type CallbackFun<T = any> = (
coreService: CoreService,
next: (...args: any[]) => Promise<PyShell | null>,
...args1: (any | T)[]
) => Promise<PyShell | null>;
export class CoreService {
public appABSPath: string;
public theme = 'light';
public mainWindow: Electron.BrowserWindow | null = null;
private currentService: PyShell | null = null;
private eventQueue: Array<CallbackFun> = [createInstaller, createAlas];
private stepIndex = 0;
constructor(options?: CoreServiceOption) {
const {appABSPath, theme, mainWindow} = Object.assign(defOptions, options || {});
this.appABSPath = appABSPath;
this.theme = theme;
this.mainWindow = mainWindow;
}
async run(...rags: any[]) {
logger.info('---------------run---------------');
logger.info('stepIndex:' + this.stepIndex);
const cb = this.eventQueue[this.stepIndex++];
const next = (...rags1: any[]) => {
return this.run(...rags1);
};
try {
cb && (this.currentService = await cb(this, next, ...rags));
} catch (e) {
/**
* 1.
*/
logger.error('currentService:' + (e as unknown as any).toString());
}
return this.curService;
}
async next(...rags: any[]) {
return this.run(...rags);
}
get curService() {
return this.currentService;
}
onError(e: Error | any) {
logger.error(`currentServiceIndex:${this.stepIndex}` + (e as unknown as any).toString());
}
reset() {
this.stepIndex = 0;
}
sendLaunchLog(message: string) {
if (!this.mainWindow || this.mainWindow.isDestroyed()) return;
logger.info(`pyShellLaunch: ${message}`);
this.mainWindow?.webContents.send(ALAS_LOG, message);
}
kill(callback?: () => void) {
this.curService?.kill(callback || this.cb);
}
cb() {
/**
*
*/
}
}

View File

@ -1,67 +0,0 @@
import {createMainWindow} from '@/createMainWindow';
import {addIpcMainListener} from '@/addIpcMainListener';
import {CoreService} from '@/coreService';
import logger from '@/logger';
import {app, nativeImage, Tray} from 'electron';
import {join} from 'node:path';
import {isMacOS} from '@alas/common';
export const createApp = async () => {
logger.info('-----createApp-----');
logger.info('-----createMainWindow-----');
const mainWindow = await createMainWindow();
const coreService = new CoreService({mainWindow});
// Hide menu
const {Menu} = require('electron');
Menu.setApplicationMenu(null);
const icon = nativeImage.createFromPath(join(__dirname, './icon.png'));
const dockerIcon = icon.resize({width: 16, height: 16});
// Tray
const tray = new Tray(isMacOS ? dockerIcon : icon);
const contextMenu = Menu.buildFromTemplate([
{
label: 'Show',
click: function () {
mainWindow?.show();
},
},
{
label: 'Hide',
click: function () {
mainWindow?.hide();
},
},
{
label: 'Exit',
click: function () {
coreService.curService?.kill(() => {
logger.info('kill coreService');
});
app.quit();
process.exit(0);
},
},
]);
tray.setToolTip('Alas');
tray.setContextMenu(contextMenu);
tray.on('click', () => {
if (mainWindow?.isVisible()) {
if (mainWindow?.isMinimized()) {
mainWindow?.show();
} else {
mainWindow?.hide();
}
} else {
mainWindow?.show();
}
});
tray.on('right-click', () => {
tray.popUpContextMenu(contextMenu);
});
await addIpcMainListener(mainWindow, coreService);
return {
mainWindow,
coreService,
};
};

View File

@ -1,94 +0,0 @@
import {app, BrowserWindow, globalShortcut, nativeTheme} from 'electron';
import {join} from 'node:path';
import {URL} from 'node:url';
import {ThemeObj} from '@alas/common';
import logger from '@/logger';
export const createMainWindow = async () => {
nativeTheme.themeSource = ThemeObj['light'];
const browserWindow = new BrowserWindow({
width: 1280,
height: 880,
show: false, // Use 'ready-to-show' event to show window
frame: false,
icon: join(__dirname, './icon.png'),
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
sandbox: false, // Sandbox disabled because the demo of preload script depend on the Node.js api
webviewTag: false, // The webview tag is not recommended. Consider alternatives like an iframe or Electron's BrowserView. @see https://www.electronjs.org/docs/latest/api/webview-tag#warning
preload: join(app.getAppPath(), 'packages/preload/dist/index.cjs'),
},
});
browserWindow.setMinimumSize(576, 396);
browserWindow.webContents.on('preload-error', (event, preloadPath, error) => {
logger.error('------------preload-error------------');
logger.error(`preloadPath:${preloadPath}`);
logger.error(`error:${error}`);
});
browserWindow.webContents.on('console-message', (event, level, message, line, sourceId) => {
if (level === 2) {
logger.warn(`console-message:${message} line:${line} sourceId:${sourceId}`);
return;
}
if (level === 3) {
logger.info('------------console-message------------');
logger.error(`console-message:${message} \n line:${line} \n sourceId:${sourceId}`);
return;
}
});
/**
* If the 'show' property of the BrowserWindow's constructor is omitted from the initialization options,
* it then defaults to 'true'. This can cause flickering as the window loads the html content,
* and it also has show problematic behaviour with the closing of the window.
* Use `show: false` and listen to the `ready-to-show` event to show the window.
*
* @see https://github.com/electron/electron/issues/25012 for the afford mentioned issue.
*/
browserWindow.on('ready-to-show', () => {
logger.info('-----ready-to-show-----');
browserWindow?.show();
if (import.meta.env.DEV) {
browserWindow?.webContents.openDevTools();
}
});
browserWindow.on('focus', function () {
// Dev tools
globalShortcut.register('Ctrl+Shift+I', function () {
if (browserWindow?.webContents.isDevToolsOpened()) {
browserWindow?.webContents.closeDevTools();
} else {
browserWindow?.webContents.openDevTools();
}
});
// Refresh
globalShortcut.register('Ctrl+R', function () {
browserWindow?.reload();
});
globalShortcut.register('Ctrl+Shift+R', function () {
browserWindow?.reload();
});
});
browserWindow.on('blur', function () {
globalShortcut.unregisterAll();
});
/**
* URL for main window.
* Vite dev server for development.
* `file://../renderer/index.html` for production and test
*/
const pageUrl =
import.meta.env.DEV && import.meta.env.VITE_DEV_SERVER_URL !== undefined
? import.meta.env.VITE_DEV_SERVER_URL
: new URL('../renderer/dist/index.html', 'file://' + __dirname).toString();
await browserWindow.loadURL(pageUrl);
return browserWindow;
};

View File

@ -1,143 +1,3 @@
// import {app, BrowserWindow} from 'electron';
// import './security-restrictions';
// import {createApp} from '@/createApp';
// import logger from '@/logger';
// import {dpiScaling} from '@/config';
//
// /**
// * Prevent electron from running multiple instances.
// */
// const isSingleInstance = app.requestSingleInstanceLock();
// logger.info(`isSingleInstance:${isSingleInstance}`);
// if (!isSingleInstance) {
// app.quit();
// } else {
// app.on('second-instance', async () => {
// logger.info('second-instance');
// const [curWindow] = BrowserWindow.getAllWindows();
// if (!curWindow) {
// logger.info('------createApp------');
// await createApp();
// } else {
// logger.info('------curWindow.restore------');
// if (curWindow.isMinimized?.()) curWindow.restore?.();
// logger.info('------curWindow.show------');
// if (!curWindow.isVisible?.()) curWindow.show?.();
// logger.info('------curWindow.focus------');
// curWindow.focus?.();
// }
// });
// }
//
// /**
// * Disable Hardware Acceleration to save more system resources.
// * Also `in-process-gpu` to avoid creating a gpu process which may `exited unexpectedly`
// * See https://github.com/electron/electron/issues/30966
// */
// app.disableHardwareAcceleration();
// app.commandLine.appendSwitch('disable-gpu');
// app.commandLine.appendSwitch('disable-software-rasterizer');
// app.commandLine.appendSwitch('disable-gpu-compositing');
// app.commandLine.appendSwitch('disable-gpu-rasterization');
// app.commandLine.appendSwitch('disable-gpu-sandbox');
// app.commandLine.appendSwitch('in-process-gpu');
// app.commandLine.appendSwitch('no-sandbox');
//
// // No DPI scaling
// if (!dpiScaling) {
// app.commandLine.appendSwitch('high-dpi-support', '1');
// app.commandLine.appendSwitch('force-device-scale-factor', '1');
// }
//
// /**
// *Set App Error Log Path
// */
// // app.setAppLogsPath(join(app.getAppPath(), '/AlasAppError'));
//
// /**
// * Shout down background process if all windows was closed
// */
// app.on('window-all-closed', () => {
// app.quit();
// });
//
// /**
// * @see https://www.electronjs.org/docs/latest/api/app#event-activate-macos Event: 'activate'.
// */
// // app.on('activate', createWindow);
// /**
// * Create the application window when the background process is ready.
// */
// // app
// // .whenReady()
// // .then(createWindow)
// // .then(loadURL)
// // .catch(e => console.error('Failed create window:', e));
//
// /**
// * Install Vue.js or any other extension in development mode only.
// * Note: You must install `electron-devtools-installer` manually
// */
// // if (import.meta.env.DEV) {
// // app
// // .whenReady()
// // .then(() => import('electron-devtools-installer'))
// // .then(module => {
// // const {default: installExtension, VUEJS3_DEVTOOLS} =
// // // @ts-expect-error Hotfix for https://github.com/cawa-93/vite-electron-builder/issues/915
// // typeof module.default === 'function' ? module : (module.default as typeof module);
// //
// // return installExtension(VUEJS3_DEVTOOLS, {
// // loadExtensionOptions: {
// // allowFileAccess: true,
// // },
// // });
// // })
// // .catch(e => console.error('Failed install extension:', e));
// // }
//
// /**
// * Check for app updates, install it in background and notify user that new version was installed.
// * No reason run this in non-production build.
// * @see https://www.electron.build/auto-update.html#quick-setup-guide
// *
// * Note: It may throw "ENOENT: no such file app-update.yml"
// * if you compile production app without publishing it to distribution server.
// * Like `npm run compile` does. It's ok 😅
// */
// // if (import.meta.env.PROD) {
// // app
// // .whenReady()
// // .then(() => import('electron-updater'))
// // .then(module => {
// // const autoUpdater =
// // module.autoUpdater ||
// // // @ts-expect-error Hotfix for https://github.com/electron-userland/electron-builder/issues/7338
// // (module.default.autoUpdater as (typeof module)['autoUpdater']);
// // return autoUpdater.checkForUpdatesAndNotify();
// // })
// // .catch(e => console.error('Failed check and install updates:', e));
// // }
//
// app
// .whenReady()
// .then(createApp)
// .catch(e => {
// logger.error('Failed create window:' + e);
// });
//
// app.on('activate', async () => {
// logger.info('------app activate------');
// const [curWindow] = BrowserWindow.getAllWindows();
// if (!curWindow) {
// logger.info('------createApp------');
// await createApp();
// } else {
// logger.info('------curWindow.focus------');
// curWindow.focus();
// }
// });
import {App} from './core/App';
new App().bootstrap().catch(e => {
console.error(e);

View File

@ -1,31 +0,0 @@
import logger from 'electron-log';
import {join} from 'node:path';
import getAlasABSPath from '@/utils/getAlasABSPath';
import dayjs from 'dayjs';
logger.transports.file.level = 'info';
logger.transports.file.maxSize = 1024 * 1024;
logger.transports.file.format = '[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}]{scope} {text}';
const dateStr = dayjs(new Date()).format('YYYY-MM-DD');
const logPath = join(getAlasABSPath(), `./log/${dateStr}_webapp.txt`);
logger.transports.file.resolvePath = () => logPath;
export default {
info(params: string) {
logger.info(params);
},
warn(params: string) {
logger.warn(params);
},
error(params: string) {
logger.error(params);
},
debug(params: string) {
logger.debug(params);
},
verbose(params: string) {
logger.verbose(params);
},
silly(params: string) {
logger.silly(params);
},
};

View File

@ -1,263 +0,0 @@
import {
app,
BrowserWindow,
globalShortcut,
ipcMain,
Menu,
nativeTheme,
Tray,
nativeImage,
} from 'electron';
import {URL} from 'node:url';
import {PyShell} from '@/pyshell';
import {dpiScaling, webuiTheme, webuiArgs, webuiPath, installerPath, installerArgs} from '@/config';
import {isMacOS} from '@alas/common';
import relaunchApp from '@/relaunchApp';
import {ALAS_LOG, UPDATE_APP} from '@alas/common';
const path = require('path');
/**
* Load deploy settings and start Alas web server.
*/
let installer: PyShell | null = null;
let alas: PyShell | null = null;
let browserWindow: BrowserWindow | null = null;
nativeTheme.themeSource = webuiTheme;
export async function createWindow() {
browserWindow = new BrowserWindow({
width: 1280,
height: 880,
show: false, // Use 'ready-to-show' event to show window
frame: false,
icon: path.join(__dirname, './icon.png'),
webPreferences: {
nodeIntegration: true,
contextIsolation: true,
sandbox: false, // Sandbox disabled because the demo of preload script depend on the Node.js api
webviewTag: false, // The webview tag is not recommended. Consider alternatives like an iframe or Electron's BrowserView. @see https://www.electronjs.org/docs/latest/api/webview-tag#warning
preload: path.join(app.getAppPath(), 'packages/preload/dist/index.cjs'),
},
});
/**
* If the 'show' property of the BrowserWindow's constructor is omitted from the initialization options,
* it then defaults to 'true'. This can cause flickering as the window loads the html content,
* and it also has show problematic behaviour with the closing of the window.
* Use `show: false` and listen to the `ready-to-show` event to show the window.
*
* @see https://github.com/electron/electron/issues/25012 for the afford mentioned issue.
*/
browserWindow.on('ready-to-show', () => {
browserWindow?.show();
// Hide menu
const {Menu} = require('electron');
Menu.setApplicationMenu(null);
if (import.meta.env.DEV) {
browserWindow?.webContents.openDevTools();
}
});
browserWindow.on('focus', function () {
// Dev tools
globalShortcut.register('Ctrl+Shift+I', function () {
if (browserWindow?.webContents.isDevToolsOpened()) {
browserWindow?.webContents.closeDevTools();
} else {
browserWindow?.webContents.openDevTools();
}
});
// Refresh
globalShortcut.register('Ctrl+R', function () {
browserWindow?.reload();
});
globalShortcut.register('Ctrl+Shift+R', function () {
browserWindow?.reload();
});
});
browserWindow.on('blur', function () {
globalShortcut.unregisterAll();
});
ipcMain.on('window-ready', async function (_, args) {
args && (await initWindowEvents());
});
/*
* Fix oversize icon on bar in macOS
*/
const icon = nativeImage.createFromPath(path.join(__dirname, './icon.png'));
const dockerIcon = icon.resize({width: 16, height: 16});
// Tray
const tray = new Tray(isMacOS ? dockerIcon : icon);
const contextMenu = Menu.buildFromTemplate([
{
label: 'Show',
click: function () {
browserWindow?.show();
},
},
{
label: 'Hide',
click: function () {
browserWindow?.hide();
},
},
{
label: 'Exit',
click: function () {
alas?.kill(function () {
browserWindow?.close();
});
},
},
]);
tray.setToolTip('Alas');
tray.setContextMenu(contextMenu);
tray.on('click', () => {
if (browserWindow?.isVisible()) {
if (browserWindow?.isMinimized()) {
browserWindow?.show();
} else {
browserWindow?.hide();
}
} else {
browserWindow?.show();
}
});
tray.on('right-click', () => {
tray.popUpContextMenu(contextMenu);
});
return browserWindow;
}
// No DPI scaling
if (!dpiScaling) {
app.commandLine.appendSwitch('high-dpi-support', '1');
app.commandLine.appendSwitch('force-device-scale-factor', '1');
}
export function loadURL() {
/**
* URL for main window.
* Vite dev server for development.
* `file://../renderer/index.html` for production and test
*/
const pageUrl =
import.meta.env.DEV && import.meta.env.VITE_DEV_SERVER_URL !== undefined
? import.meta.env.VITE_DEV_SERVER_URL
: new URL('../renderer/dist/index.html', 'file://' + __dirname).toString();
browserWindow?.loadURL(pageUrl);
}
// Minimize, maximize, close window.
ipcMain.on('window-tray', function () {
browserWindow?.hide();
});
ipcMain.on('window-min', function () {
browserWindow?.minimize();
});
ipcMain.on('window-max', function () {
browserWindow?.isMaximized() ? browserWindow?.restore() : browserWindow?.maximize();
});
ipcMain.on('window-close', function () {
if (installer) {
installer?.removeAllListeners('stderr');
installer?.removeAllListeners('message');
installer?.removeAllListeners('stdout');
installer?.kill(function () {
browserWindow?.close();
browserWindow = null;
installer = null;
});
return;
}
alas?.removeAllListeners('stderr');
alas?.removeAllListeners('message');
alas?.removeAllListeners('stdout');
alas?.kill(function () {
browserWindow?.close();
browserWindow = null;
});
browserWindow?.close();
});
async function initWindowEvents() {
// Start installer and wait for it to finish.
await runInstaller();
ipcMain.on('install-success', async function () {
installer = null;
// Start Alas web server.
runAlas();
});
}
async function runInstaller() {
installer = new PyShell(installerPath, installerArgs);
installer?.end(function (err: string) {
sendLaunchLog(err);
if (err) throw err;
});
installer?.on('stdout', function (message) {
sendLaunchLog(message);
});
installer?.on('message', function (message) {
sendLaunchLog(message);
});
installer?.on('stderr', function (message: string) {
sendLaunchLog(message);
});
}
function runAlas() {
alas = new PyShell(webuiPath, webuiArgs);
alas?.end(function (err: string) {
sendLaunchLog(err);
if (err) throw err;
});
alas?.on('stdout', function (message) {
sendLaunchLog(message);
});
alas?.on('message', function (message) {
sendLaunchLog(message);
});
alas?.on('stderr', function (message: string) {
sendLaunchLog(message);
/**
* Receive logs, judge if Alas is ready
* For starlette backend, there will have:
* `INFO: Uvicorn running on http://0.0.0.0:22267 (Press CTRL+C to quit)`
* Or backend has started already
* `[Errno 10048] error while attempting to bind on address ('0.0.0.0', 22267): `
*/
if (message.includes('Application startup complete') || message.includes('bind on address')) {
alas?.removeAllListeners('stderr');
alas?.removeAllListeners('message');
alas?.removeAllListeners('stdout');
// loadURL();
}
});
}
function sendLaunchLog(message: string) {
message?.includes(UPDATE_APP) && relaunchApp();
browserWindow?.webContents.send(ALAS_LOG, message);
}
export async function restoreWindow() {
// Someone tried to run a second instance, we should focus our window.
if (browserWindow) {
if (browserWindow.isMinimized()) browserWindow.restore();
if (!browserWindow.isVisible()) browserWindow.show();
browserWindow.focus();
}
}

View File

@ -1,5 +1,5 @@
import {alasPath, pythonPath} from '@/config';
import logger from '@/logger';
import { logger } from "@/core/Logger/customLogger";
const {PythonShell} = require('python-shell');
const treeKill = require('tree-kill');

View File

@ -1,52 +0,0 @@
import {webuiArgs, webuiPath} from '@/config';
import {PyShell} from '@/pyshell';
import type {CallbackFun} from '@/coreService';
import logger from '@/logger';
export const createAlas: CallbackFun = async ctx => {
let alas: PyShell | null = null;
try {
alas = new PyShell(webuiPath, webuiArgs);
} catch (e) {
ctx.onError(e);
}
alas?.on('error', function (err: string) {
if (!err) return;
logger.error('alas.error:' + err);
ctx.sendLaunchLog(err);
});
alas?.end(function (err: string) {
if (!err) return;
logger.info('alas.end:' + err);
ctx.sendLaunchLog(err);
throw err;
});
alas?.on('stdout', function (message) {
ctx.sendLaunchLog(message);
});
alas?.on('message', function (message) {
ctx.sendLaunchLog(message);
});
alas?.on('stderr', function (message: string) {
ctx.sendLaunchLog(message);
/**
* Receive logs, judge if Alas is ready
* For starlette backend, there will have:
* `INFO: Uvicorn running on http://0.0.0.0:22267 (Press CTRL+C to quit)`
* Or backend has started already
* `[Errno 10048] error while attempting to bind on address ('0.0.0.0', 22267): `
*/
if (message.includes('Application startup complete') || message.includes('bind on address')) {
alas?.removeAllListeners('stderr');
alas?.removeAllListeners('message');
alas?.removeAllListeners('stdout');
}
});
alas?.on('pythonError', err => {
ctx.onError('alas pythonError:' + err);
});
return alas;
};

View File

@ -1,43 +0,0 @@
import type {CallbackFun} from '@/coreService';
import {PyShell} from '@/pyshell';
import {installerArgs, installerPath} from '@/config';
import {ALAS_RELAUNCH_ARGV} from '@alas/common';
import logger from '@/logger';
export const createInstaller: CallbackFun = async (ctx, next) => {
if (process.argv.includes(ALAS_RELAUNCH_ARGV)) {
return next();
}
let installer: PyShell | null = null;
try {
installer = new PyShell(installerPath, installerArgs);
} catch (err) {
ctx.onError(err);
}
installer?.on('error', function (err: string) {
if (!err) return;
logger.error('installer.error:' + err);
ctx.sendLaunchLog(err);
});
installer?.end(function (err: string) {
if (!err) return;
logger.info('installer.end:' + err);
ctx.sendLaunchLog(err);
// throw err;
});
installer?.on('stdout', function (message) {
ctx.sendLaunchLog(message);
});
installer?.on('message', function (message) {
ctx.sendLaunchLog(message);
});
installer?.on('stderr', function (message: string) {
ctx.sendLaunchLog(message);
});
installer?.on('pythonError', err => {
ctx.onError('alas pythonError :' + err);
});
return installer;
};

View File

@ -1,4 +0,0 @@
import {createInstaller} from './createInstaller';
import {createAlas} from './createAlas';
export {createInstaller, createAlas};

View File

@ -1,5 +0,0 @@
import { defineConfig } from 'father';
export default defineConfig({
cjs: { output: 'dist', platform: 'browser' },
});

View File

@ -2,12 +2,11 @@
"name": "@alas/preload",
"version": "0.4.0",
"description": "alas webapp preload",
"main": "src/index.ts",
"private": "true",
"main": "src/index.ts",
"scripts": {
"build": "father build",
"postinstall": "npm run build",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'"
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"clean:modules": "rm -rf node_modules"
},
"author": "",
"license": "ISC",

View File

@ -7,7 +7,8 @@
"build": "vite build",
"dev": "vite dev",
"start": "npm run dev",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'"
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"clean:modules": "rm -rf node_modules"
},
"author": "",
"license": "ISC",
@ -23,7 +24,7 @@
"vue-router": "^4.1.6"
},
"devDependencies": {
"@alas/common": "^0.4.0",
"@alas/common": "0.4.0",
"autoprefixer": "^10.4.14",
"less": "^4.1.3",
"unocss": "^0.51.8",

1257
webapp/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
import {execSync} from 'child_process';
import fs from 'fs';
import yaml from 'js-yaml';
import {join} from 'path';
import {name as appName, version} from '../package.json';
// @ts-ignore
import options from '../packages/main/electron-builder.config';
const dir = join(__dirname, '../release');
const appPath = `${dir}/mac/${options.productName}.app`;
const zipFileName = `${appName}_setup_${version}_mac.zip`;
const zipFilePath = `${dir}/${zipFileName}`;
const appBuilder = join(__dirname, '../node_modules/app-builder-bin/mac/app-builder');
console.log('Zipping...');
execSync(`ditto -c -k --sequesterRsrc --keepParent "${appPath}" "${zipFilePath}"`);
console.log('Finished zipping!');
console.log('Collect data...');
const blockmap = JSON.parse(
execSync(`${appBuilder} blockmap -i ${zipFilePath} -o ${dir}/th.zip`).toString(),
);
console.log(blockmap);
// eslint-disable-next-line radix
blockmap.blockMapSize = parseInt(
execSync(`ls -l ${dir}/th.zip | awk '{print $5}' && rm ${dir}/th.zip`).toString(),
);
const doc = yaml.load(fs.readFileSync(`${dir}/latest-mac.yml`, 'utf8')) as any;
doc.files.unshift({
url: zipFileName,
...blockmap,
});
doc.path = zipFileName;
doc.sha512 = blockmap.sha512;
fs.writeFileSync(`${dir}/latest-mac.yml`, yaml.dump(doc, {lineWidth: 65535}), 'utf8');