/
githubmirror
/
edex-ui
Обзор
Документация
Войти
/
githubmirror
/
edex-ui
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
v2.2.7
src/_boot.js
369 строк
13 KB
Gabriel Saillard
upgrade to Electron 11, attempt apple silicon build #907
26 ноя 2020, 16:35
Не верифицирован
26 ноя 2020, 16:35
ae5a420
Код
Авторство
О чём код?
const signale = require("signale"); const {app, BrowserWindow, dialog, shell} = require("electron"); process.on("uncaughtException", e => { signale.fatal(e); dialog.showErrorBox("eDEX-UI crashed", e.message || "Cannot retrieve error message."); if (tty) { tty.close(); } if (extraTtys) { Object.keys(extraTtys).forEach(key => { if (extraTtys[key] !== null) { extraTtys[key].close(); } }); } process.exit(1); }); signale.start(`Starting eDEX-UI v${app.getVersion()}`); signale.info(`With Node ${process.versions.node} and Electron ${process.versions.electron}`); signale.info(`Renderer is Chrome ${process.versions.chrome}`); const gotLock = app.requestSingleInstanceLock(); if (!gotLock) { signale.fatal("Error: Another instance of eDEX is already running. Cannot proceed."); app.exit(1); } signale.time("Startup"); const electron = require("electron"); const ipc = electron.ipcMain; const path = require("path"); const url = require("url"); const fs = require("fs"); const which = require("which"); const Terminal = require("./classes/terminal.class.js").Terminal; ipc.on("log", (e, type, content) => { signale[type](content); }); var win, tty, extraTtys; const settingsFile = path.join(electron.app.getPath("userData"), "settings.json"); const shortcutsFile = path.join(electron.app.getPath("userData"), "shortcuts.json"); const lastWindowStateFile = path.join(electron.app.getPath("userData"), "lastWindowState.json"); const themesDir = path.join(electron.app.getPath("userData"), "themes"); const innerThemesDir = path.join(__dirname, "assets/themes"); const kblayoutsDir = path.join(electron.app.getPath("userData"), "keyboards"); const innerKblayoutsDir = path.join(__dirname, "assets/kb_layouts"); const fontsDir = path.join(electron.app.getPath("userData"), "fonts"); const innerFontsDir = path.join(__dirname, "assets/fonts"); // Unset proxy env variables to avoid connection problems on the internal websockets // See #222 if (process.env.http_proxy) delete process.env.http_proxy; if (process.env.https_proxy) delete process.env.https_proxy; // Fix userData folder not setup on Windows try { fs.mkdirSync(electron.app.getPath("userData")); signale.info(`Created config dir at ${electron.app.getPath("userData")}`); } catch(e) { signale.info(`Base config dir is ${electron.app.getPath("userData")}`); } // Create default settings file if (!fs.existsSync(settingsFile)) { fs.writeFileSync(settingsFile, JSON.stringify({ shell: (process.platform === "win32") ? "powershell.exe" : "bash", shellArgs: '', cwd: electron.app.getPath("userData"), keyboard: "en-US", theme: "tron", termFontSize: 15, audio: true, audioVolume: 1.0, disableFeedbackAudio: false, clockHours: 24, pingAddr: "1.1.1.1", port: 3000, nointro: false, nocursor: false, forceFullscreen: true, allowWindowed: false, excludeThreadsFromToplist: true, hideDotfiles: false, fsListView: false, experimentalGlobeFeatures: false, experimentalFeatures: false }, "", 4)); signale.info(`Default settings written to ${settingsFile}`); } // Create default shortcuts file if (!fs.existsSync(shortcutsFile)) { fs.writeFileSync(shortcutsFile, JSON.stringify([ { type: "app", trigger: "Ctrl+Shift+C", action: "COPY", enabled: true }, { type: "app", trigger: "Ctrl+Shift+V", action: "PASTE", enabled: true }, { type: "app", trigger: "Ctrl+Tab", action: "NEXT_TAB", enabled: true }, { type: "app", trigger: "Ctrl+Shift+Tab", action: "PREVIOUS_TAB", enabled: true }, { type: "app", trigger: "Ctrl+X", action: "TAB_X", enabled: true }, { type: "app", trigger: "Ctrl+Shift+S", action: "SETTINGS", enabled: true }, { type: "app", trigger: "Ctrl+Shift+K", action: "SHORTCUTS", enabled: true }, { type: "app", trigger: "Ctrl+Shift+F", action: "FUZZY_SEARCH", enabled: true }, { type: "app", trigger: "Ctrl+Shift+L", action: "FS_LIST_VIEW", enabled: true }, { type: "app", trigger: "Ctrl+Shift+H", action: "FS_DOTFILES", enabled: true }, { type: "app", trigger: "Ctrl+Shift+P", action: "KB_PASSMODE", enabled: true }, { type: "app", trigger: "Ctrl+Shift+I", action: "DEV_DEBUG", enabled: false }, { type: "app", trigger: "Ctrl+Shift+F5", action: "DEV_RELOAD", enabled: true }, { type: "shell", trigger: "Ctrl+Shift+Alt+Space", action: "neofetch", linebreak: true, enabled: false } ], "", 4)); signale.info(`Default keymap written to ${shortcutsFile}`); } //Create default window state file if(!fs.existsSync(lastWindowStateFile)) { fs.writeFileSync(lastWindowStateFile, JSON.stringify({ useFullscreen: true }, "", 4)); signale.info(`Default last window state written to ${lastWindowStateFile}`); } // Copy default themes & keyboard layouts & fonts signale.pending("Mirroring internal assets..."); try { fs.mkdirSync(themesDir); } catch(e) { // Folder already exists } fs.readdirSync(innerThemesDir).forEach(e => { fs.writeFileSync(path.join(themesDir, e), fs.readFileSync(path.join(innerThemesDir, e), {encoding:"utf-8"})); }); try { fs.mkdirSync(kblayoutsDir); } catch(e) { // Folder already exists } fs.readdirSync(innerKblayoutsDir).forEach(e => { fs.writeFileSync(path.join(kblayoutsDir, e), fs.readFileSync(path.join(innerKblayoutsDir, e), {encoding:"utf-8"})); }); try { fs.mkdirSync(fontsDir); } catch(e) { // Folder already exists } fs.readdirSync(innerFontsDir).forEach(e => { fs.writeFileSync(path.join(fontsDir, e), fs.readFileSync(path.join(innerFontsDir, e))); }); // Version history logging const versionHistoryPath = path.join(electron.app.getPath("userData"), "versions_log.json"); var versionHistory = fs.existsSync(versionHistoryPath) ? require(versionHistoryPath) : {}; var version = app.getVersion(); if (typeof versionHistory[version] === "undefined") { versionHistory[version] = { firstSeen: Date.now(), lastSeen: Date.now() }; } else { versionHistory[version].lastSeen = Date.now(); } fs.writeFileSync(versionHistoryPath, JSON.stringify(versionHistory, 0, 2), {encoding:"utf-8"}); function createWindow(settings) { signale.info("Creating window..."); let display; if (!isNaN(settings.monitor)) { display = electron.screen.getAllDisplays()[settings.monitor] || electron.screen.getPrimaryDisplay(); } else { display = electron.screen.getPrimaryDisplay(); } let {x, y, width, height} = display.bounds; width++; height++; win = new BrowserWindow({ title: "eDEX-UI", x, y, width, height, show: false, resizable: true, movable: settings.allowWindowed || false, fullscreen: settings.forceFullscreen || false, autoHideMenuBar: true, frame: settings.allowWindowed || false, backgroundColor: '#000000', webPreferences: { devTools: true, enableRemoteModule: true, contextIsolation: false, backgroundThrottling: false, webSecurity: true, nodeIntegration: true, nodeIntegrationInSubFrames: false, allowRunningInsecureContent: false, experimentalFeatures: settings.experimentalFeatures || false } }); win.loadURL(url.format({ pathname: path.join(__dirname, 'ui.html'), protocol: 'file:', slashes: true })); signale.complete("Frontend window created!"); win.show(); if (!settings.allowWindowed) { win.setResizable(false); } else if (!require(lastWindowStateFile)["useFullscreen"]) { win.setFullScreen(false); } signale.watch("Waiting for frontend connection..."); } app.on('ready', async () => { signale.pending(`Loading settings file...`); let settings = require(settingsFile); signale.pending(`Resolving shell path...`); settings.shell = await which(settings.shell).catch(e => { throw(e) }); signale.info(`Shell found at ${settings.shell}`); signale.success(`Settings loaded!`); if (!require("fs").existsSync(settings.cwd)) throw new Error("Configured cwd path does not exist."); // See #366 let cleanEnv = await require("shell-env")(settings.shell).catch(e => { throw e; }); Object.assign(cleanEnv, process.env, { TERM: "xterm-256color", COLORTERM: "truecolor", TERM_PROGRAM: "eDEX-UI", TERM_PROGRAM_VERSION: app.getVersion() }, settings.env); signale.pending(`Creating new terminal process on port ${settings.port || '3000'}`); tty = new Terminal({ role: "server", shell: settings.shell, params: settings.shellArgs || '', cwd: settings.cwd, env: cleanEnv, port: settings.port || 3000 }); signale.success(`Terminal back-end initialized!`); tty.onclosed = (code, signal) => { tty.ondisconnected = () => {}; signale.complete("Terminal exited", code, signal); app.quit(); }; tty.onopened = () => { signale.success("Connected to frontend!"); signale.timeEnd("Startup"); }; tty.onresized = (cols, rows) => { signale.info("Resized TTY to ", cols, rows); }; tty.ondisconnected = () => { signale.error("Lost connection to frontend"); signale.watch("Waiting for frontend connection..."); }; // Support for multithreaded systeminformation calls signale.pending("Starting multithreaded calls controller..."); require("./_multithread.js"); createWindow(settings); // Support for more terminals, used for creating tabs (currently limited to 4 extra terms) extraTtys = {}; let basePort = settings.port || 3000; basePort = Number(basePort) + 2; for (let i = 0; i < 4; i++) { extraTtys[basePort+i] = null; } ipc.on("ttyspawn", (e, arg) => { let port = null; Object.keys(extraTtys).forEach(key => { if (extraTtys[key] === null && port === null) { extraTtys[key] = {}; port = key; } }); if (port === null) { signale.error("TTY spawn denied (Reason: exceeded max TTYs number)"); e.sender.send("ttyspawn-reply", "ERROR: max number of ttys reached"); } else { signale.pending(`Creating new TTY process on port ${port}`); let term = new Terminal({ role: "server", shell: settings.shell, params: settings.shellArgs || '', cwd: tty.tty._cwd || settings.cwd, env: cleanEnv, port: port }); signale.success(`New terminal back-end initialized at ${port}`); term.onclosed = (code, signal) => { term.ondisconnected = () => {}; term.wss.close(); signale.complete(`TTY exited at ${port}`, code, signal); extraTtys[term.port] = null; term = null; }; term.onopened = pid => { signale.success(`TTY ${port} connected to frontend (process PID ${pid})`); }; term.onresized = () => {}; term.ondisconnected = () => { term.onclosed = () => {}; term.close(); term.wss.close(); extraTtys[term.port] = null; term = null; }; extraTtys[port] = term; e.sender.send("ttyspawn-reply", "SUCCESS: "+port); } }); // Backend support for theme and keyboard hotswitch let themeOverride = null; let kbOverride = null; ipc.on("getThemeOverride", (e, arg) => { e.sender.send("getThemeOverride", themeOverride); }); ipc.on("getKbOverride", (e, arg) => { e.sender.send("getKbOverride", kbOverride); }); ipc.on("setThemeOverride", (e, arg) => { themeOverride = arg; }); ipc.on("setKbOverride", (e, arg) => { kbOverride = arg; }); }); app.on('web-contents-created', (e, contents) => { // Prevent creating more than one window contents.on('new-window', (e, url) => { e.preventDefault(); shell.openExternal(url); }); // Prevent loading something else than the UI contents.on('will-navigate', (e, url) => { if (url !== contents.getURL()) e.preventDefault(); }); }); app.on('window-all-closed', () => { signale.info("All windows closed"); app.quit(); }); app.on('before-quit', () => { tty.close(); Object.keys(extraTtys).forEach(key => { if (extraTtys[key] !== null) { extraTtys[key].close(); } }); signale.complete("Shutting down..."); });