Files
YukiHookAPI-ProjectBuilder/src/app-space.js
2022-07-23 20:50:11 +08:00

384 lines
14 KiB
JavaScript

/*
* YukiHookAPI Project Builder - A Xposed Project Builder by YukiHookAPI.
* Copyright (C) 2019-2022 HighCapable
* https://github.com/fankes/YukiHookAPI-ProjectBuilder
*
* This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/7/21.
*/
const {app, ipcMain, dialog, BrowserWindow, Menu, MenuItem} = require('electron');
const {locale} = require('./libs/locale');
const {fileSystem} = require('./libs/file-system');
const {store} = require('./libs/store');
const {system} = require("./libs/system");
/** 主窗口 */
let mainWindow = null;
/**
* 应用程序初始化命名空间
*/
const appSpace = {
/** 开始装载窗口 */
loadFrame: () => {
appSpace.createWindow();
appSpace.createMenu();
},
/** 创建窗口 */
createWindow: () => {
mainWindow = new BrowserWindow({
title: locale.i18n.windowTitle,
width: 1000,
height: 1050,
resizable: false,
maximizable: false,
show: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
mainWindow.loadFile('src/content/index.html').then(() => {
appWindow.webContents.methods.page.init(localeConfig.currentLocale(), app.getVersion());
});
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
},
/** 创建菜单 */
createMenu: () => {
const menu = new Menu();
const separatorItem = new MenuItem({type: 'separator'});
const aboutChildItem = new MenuItem({
label: locale.i18n.about,
accelerator: system.isMacOS ? 'command+a' : 'ctrl+a',
click: () => {
appWindow.webContents.methods.page.showAbout(app.getName(), app.getVersion());
}
});
const checkUpdateChildItem = new MenuItem({
label: locale.i18n.checkUpdate,
click: () => {
appWindow.webContents.methods.page.checkForUpdates();
}
});
const projectAddressChildItem = new MenuItem({
label: locale.i18n.projectAddress,
accelerator: system.isMacOS ? 'command+w' : 'ctrl+w',
click: () => {
system.openBrowser('https://github.com/fankes/YukiHookAPI');
}
});
const helpDocumentationChildItem = new MenuItem({
label: locale.i18n.helpDocumentation,
accelerator: system.isMacOS ? 'command+h' : 'ctrl+h',
click: () => {
system.openBrowser('https://fankes.github.io/YukiHookAPI');
}
});
const openSourceChildItem = new MenuItem({
label: locale.i18n.openSource,
accelerator: system.isMacOS ? 'command+o' : 'ctrl+o',
click: () => {
appWindow.webContents.methods.page.showOpenSource();
}
});
const laguageSubChildItems = [];
laguageSubChildItems.push(new MenuItem({
type: 'radio',
label: locale.i18n.followSystem,
checked: localeConfig.isFollowSystem,
click: () => {
localeConfig.changeLocale();
}
}));
for (const la in locale.languageSupports)
laguageSubChildItems.push(new MenuItem({
type: 'radio',
label: locale.languageSupports[la],
checked: la === locale.name && !localeConfig.isFollowSystem,
click: () => {
localeConfig.changeLocale(la);
}
}));
const languageChildItem = new MenuItem({
label: locale.i18n.language + ' (Language)',
submenu: laguageSubChildItems
});
const quitChildItem = new MenuItem({
label: locale.i18n.quit,
accelerator: system.isMacOS ? 'command+q' : 'ctrl+q',
click: () => {
app.quit();
}
});
const runBuildChildItem = new MenuItem({
label: locale.i18n.runBuild,
accelerator: system.isMacOS ? 'command+b' : 'ctrl+b',
click: () => {
appWindow.webContents.methods.build.checking();
}
});
const newTemplateChildItem = new MenuItem({
label: locale.i18n.newTemplate,
accelerator: system.isMacOS ? 'command+n' : 'ctrl+n',
click: () => {
appWindow.webContents.methods.configTemplate.createNew();
}
});
const templateSubChildItems = [];
const clearAllTemplateChildItem = new MenuItem({
label: locale.i18n.clearAllTemplate,
accelerator: system.isMacOS ? 'command+d' : 'ctrl+d',
click: () => {
appWindow.webContents.methods.configTemplate.clearAll();
}
});
const templates = store.get('config-templates', []);
if (templates.length > 0) {
templates.forEach((value) => {
templateSubChildItems.push(new MenuItem({
label: value.name,
click: () => {
appWindow.webContents.methods.configTemplate.load(value);
}
}));
});
templateSubChildItems.push(separatorItem);
templateSubChildItems.push(clearAllTemplateChildItem);
} else templateSubChildItems.push(new MenuItem({
label: locale.i18n.nothing,
enabled: false
}));
const savedTemplateChildItem = new MenuItem({
label: locale.i18n.savedTemplate,
submenu: templateSubChildItems
});
const configTemplateChildItem = new MenuItem({
label: locale.i18n.configTemplate,
submenu: [newTemplateChildItem, savedTemplateChildItem]
});
const resetCurrentConfigChildItem = new MenuItem({
label: locale.i18n.resetCurrentConfig,
accelerator: system.isMacOS ? 'command+r' : 'ctrl+r',
click: () => {
appWindow.webContents.methods.page.restore();
}
});
const fileMainItem = new MenuItem({
label: system.isMacOS ? app.name : locale.i18n.file,
submenu: system.isMacOS ? [aboutChildItem, separatorItem, checkUpdateChildItem, separatorItem,
projectAddressChildItem, helpDocumentationChildItem, separatorItem, openSourceChildItem, separatorItem,
languageChildItem, separatorItem, quitChildItem] : [languageChildItem, separatorItem, quitChildItem]
});
const projectMainItem = new MenuItem({
label: locale.i18n.project,
submenu: [runBuildChildItem, separatorItem, configTemplateChildItem, resetCurrentConfigChildItem]
});
const helpMainItem = new MenuItem({
label: (locale.i18n.help),
submenu: [aboutChildItem, separatorItem, checkUpdateChildItem, separatorItem,
projectAddressChildItem, helpDocumentationChildItem, separatorItem, openSourceChildItem]
});
menu.append(fileMainItem);
menu.append(projectMainItem);
if (!system.isMacOS) menu.append(helpMainItem);
Menu.setApplicationMenu(menu);
},
/**
* 注册 ipc 监听
* @param option 回调选项
*/
registerIpcListener: (option) => {
ipcMain.on('run-packaging-project', (_, configs) => {
option['run-packaging-project'](configs);
});
ipcMain.on('open-complete-project', () => {
option['open-complete-project']();
});
ipcMain.on('save-config-template', (_, configs) => {
const templates = store.get('config-templates', []);
templates.push(configs);
store.set('config-templates', templates);
appSpace.createMenu();
});
ipcMain.on('clear-all-config-template', () => {
store.set('config-templates', []);
appSpace.createMenu();
});
ipcMain.on('reload-current-page', () => {
setTimeout(() => {
mainWindow.reload();
appWindow.webContents.methods.page.init(localeConfig.currentLocale(), app.getVersion());
}, 150);
});
ipcMain.on('relaunch-app', () => {
mainWindow.close();
app.relaunch();
});
ipcMain.on('open-system-browser', (_, url) => {
system.openBrowser(url);
});
}
};
/**
* 应用程序配置命名空间
*/
const appConfig = {
/**
* 项目根路径
* @return string
*/
sourcePath: app.isPackaged ? app.getAppPath() : '.',
/**
* 项目外部路径
* @return string
*/
dataPath: fileSystem.path(app.getPath('appData'), 'YukiHookAPI'),
/** 创建应用数据目录 */
createDataDir: () => {
const dataPath = appConfig.dataPath;
if (!fileSystem.exists(dataPath)) fileSystem.mkdir(dataPath);
}
};
/**
* 语言区域配置命名空间
*/
const localeConfig = {
/**
* 语言是否跟随系统
* @return boolean
*/
isFollowSystem: store.get('locale-follow-system', true),
/**
* 当前存储的语言名称
* @return string
*/
storeLocaleName: store.get('store-locale-name', locale.default),
/**
* 获取当前语言区域名称
* @return string
*/
currentLocale: () => {
return localeConfig.isFollowSystem ? app.getLocale() : localeConfig.storeLocaleName;
},
/**
* 修改语言
* @param name 语言名称
*/
changeLocale: (name = 'default') => {
if (name === 'default') {
store.set('locale-follow-system', true);
store.set('store-locale-name', locale.default);
} else {
store.set('locale-follow-system', false);
store.set('store-locale-name', name);
}
appWindow.webContents.methods.page.relaunch();
}
};
/**
* 应用程序窗口命名空间
*/
const appWindow = {
/**
* 打开目录
* @param option 选项
* @param callback 回调结果
* @param onError 回调错误
*/
showOpenDirectory: (option, callback, onError) => {
dialog.showOpenDialog(mainWindow, {
properties: ['openDirectory'],
title: option['title'],
message: option['message'],
buttonLabel: option['buttonLabel']
}).then(result => {
callback(result);
}).catch((e) => {
onError(e);
});
},
/** 窗口内网页交互调用桥 */
webContents: {
/**
* 执行内部 JS
* @param code 执行代码
*/
execJs: (code) => {
mainWindow.webContents.executeJavaScript(code).then(() => null);
},
methods: {
configTemplate: {
load: (configs) => {
appWindow.webContents.execJs('configTemplate.load(\'' + encodeURI(JSON.stringify(configs)) + '\')');
},
createNew: () => {
appWindow.webContents.execJs('configTemplate.createNew()');
},
clearAll: () => {
appWindow.webContents.execJs('configTemplate.clearAll()');
}
},
page: {
init: (localeName, appVersion) => {
appWindow.webContents.execJs('page.init(\'' + localeName + '\',\'' + appVersion + '\')');
},
snack: (message) => {
appWindow.webContents.execJs('page.snack(\'' + message + '\')');
},
showAbout: (name, version) => {
appWindow.webContents.execJs('page.showAbout(\'' + name + '\',\'' + version + '\')');
},
showOpenSource: () => {
appWindow.webContents.execJs('page.showOpenSource()');
},
checkForUpdates: () => {
appWindow.webContents.execJs('page.checkForUpdates()');
},
restore: () => {
appWindow.webContents.execJs('page.restore()');
},
relaunch: () => {
appWindow.webContents.execJs('page.relaunch()');
}
},
build: {
checking: () => {
appWindow.webContents.execJs('build.checking()');
},
changeStatus: (msg) => {
appWindow.webContents.execJs('build.changeStatus(\'' + msg + '\')');
},
complete: (msg) => {
appWindow.webContents.execJs('build.complete(\'' + msg + '\')');
},
failure: (msg) => {
appWindow.webContents.execJs('build.failure(\'' + msg + '\')');
},
cancel: () => {
appWindow.webContents.execJs('build.cancel()');
}
}
}
}
};
module.exports = {appSpace, appWindow, appConfig, localeConfig};