UNPKG

kui-shell

Version:

This is the monorepo for Kui, the hybrid command-line/GUI electron-based Kubernetes tool

328 lines 14.1 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const debug_1 = require("debug"); const debug = debug_1.default('main/spawn-electron'); debug('loading'); const defaults_1 = require("../webapp/defaults"); let nWindows = 0; let app; function createWindow(noHeadless = false, executeThisArgvPlease, subwindowPlease, subwindowPrefs) { debug('createWindow', executeThisArgvPlease); if (subwindowPrefs && subwindowPrefs.bringYourOwnWindow) { subwindowPrefs.bringYourOwnWindow(); return; } let width = (subwindowPrefs && subwindowPrefs.width) || 1280; let height = (subwindowPrefs && subwindowPrefs.height) || 960; if (process.env.WINDOW_WIDTH) { width = parseInt(process.env.WINDOW_WIDTH, 10); if (isNaN(width)) { console.error('Cannot parse WINDOW_WIDTH ' + process.env.WINDOW_WIDTH); width = 1280; } } if (process.env.WINDOW_HEIGHT) { height = parseInt(process.env.WINDOW_HEIGHT, 10); if (isNaN(height)) { console.error('Cannot parse WINDOW_HEIGHT ' + process.env.WINDOW_HEIGHT); height = 960; } } let promise = Promise.resolve(); if (!app) { debug('we need to spawn electron', subwindowPlease, subwindowPrefs); delete subwindowPrefs.synonymFor; promise = initElectron(['--'].concat(executeThisArgvPlease), {}, subwindowPlease, subwindowPrefs) .then(() => __awaiter(this, void 0, void 0, function* () { app = (yield Promise.resolve().then(() => require('electron'))).app; })) .catch((err) => { debug('not ready for graphics', err); }); } promise.then(() => __awaiter(this, void 0, void 0, function* () { const { theme, env } = yield Promise.resolve().then(() => require('@kui-shell/settings/config.json')); const Electron = yield Promise.resolve().then(() => require('electron')); const opts = Object.assign({ title: theme.productName, width, height, webPreferences: { backgroundThrottling: false, nodeIntegration: true }, show: false }, subwindowPrefs && subwindowPrefs.position); const { dirname, join } = yield Promise.resolve().then(() => require('path')); const root = dirname(require.resolve('@kui-shell/settings/package.json')); if (process.platform === 'linux') { const icon = join(root, env.imageHome, '/../..', theme.filesystemIcons.linux); opts.icon = icon; } if (process.platform === 'linux' || process.platform === 'win32') { opts.autoHideMenuBar = true; } if (subwindowPlease) { opts.useContentSize = true; } if (process.env.KUI_POSITION_X) { opts.x = parseInt(process.env.KUI_POSITION_X, 10); } if (process.env.KUI_POSITION_Y) { opts.y = parseInt(process.env.KUI_POSITION_Y, 10); } debug('createWindow::new BrowserWindow'); const mainWindow = new Electron.BrowserWindow(opts); nWindows++; debug('createWindow::new BrowserWindow success'); mainWindow.once('ready-to-show', () => { mainWindow.webContents.setZoomFactor(1); mainWindow.setVisibleOnAllWorkspaces(true); mainWindow.show(); mainWindow.setVisibleOnAllWorkspaces(false); }); const fixedWindows = {}; const openFixedWindow = (opts) => { const { type, event, url, size = mainWindow.getBounds(), position = mainWindow.getBounds() } = opts; const existing = fixedWindows[type] || {}; const { window: existingWindow, url: currentURL } = existing; if (!existingWindow || existingWindow.isDestroyed()) { const window = new Electron.BrowserWindow({ width: size.width, height: size.height, frame: true }); fixedWindows[type] = { window, url }; window.setPosition(position.x + 62, position.y + 62); window.loadURL(url); } else { if (currentURL !== url) { existingWindow.loadURL(url); existing.url = url; } existingWindow.focus(); } event.preventDefault(); }; mainWindow.webContents.on('did-finish-load', () => __awaiter(this, void 0, void 0, function* () { })); mainWindow.webContents.on('new-window', (event, url, frameName, disposition, options) => { if (url.startsWith('https://youtu.be')) { openFixedWindow({ type: 'videos', event, url, options, size: { width: 800, height: 600 } }); } else { event.preventDefault(); Electron.shell.openExternal(url); } }); let commandContext = executeThisArgvPlease && executeThisArgvPlease.find(_ => /--command-context/.test(_)); if (commandContext) { executeThisArgvPlease = executeThisArgvPlease.filter(_ => !_.match(/--command-context/)); commandContext = commandContext.replace(/^--/, ''); } if (noHeadless === true && executeThisArgvPlease) { debug('setting argv', executeThisArgvPlease); mainWindow.executeThisArgvPlease = executeThisArgvPlease; } debug('subwindowPrefs', subwindowPrefs); if (subwindowPrefs && Object.keys(subwindowPrefs).length > 0) { mainWindow.subwindow = subwindowPrefs; } const urlSpec = { pathname: join(root, '../build/index.html'), protocol: 'file:', search: commandContext ? `?${commandContext}` : '', slashes: true }; debug('mainWindow::loadURL', urlSpec); mainWindow.loadURL(require('url').format(urlSpec)); debug('install menus'); require('./menu').install(createWindow); mainWindow.once('closed', function () { nWindows--; }); const { ipcMain } = Electron; debug('ipc registration'); ipcMain.on('capture-page-to-clipboard', (event, contentsId, rect) => { try { const { clipboard, nativeImage, webContents } = Electron; webContents.fromId(parseInt(contentsId, 10)).capturePage(rect, image => { try { const buf = image.toPNG(); clipboard.writeImage(nativeImage.createFromBuffer(buf)); event.sender.send('capture-page-to-clipboard-done', buf); } catch (err) { console.log(err); event.sender.send('capture-page-to-clipboard-done'); } }); } catch (err) { console.log(err); event.sender.send('capture-page-to-clipboard-done'); } }); ipcMain.on('synchronous-message', (event, arg) => { const message = JSON.parse(arg); switch (message.operation) { case 'quit': app.quit(); break; case 'open-graphical-shell': createWindow(true); break; case 'enlarge-window': mainWindow.setContentSize(1400, 1050, true); break; case 'reduce-window': mainWindow.setContentSize(1024, 768, true); break; case 'maximize-window': mainWindow.maximize(); break; case 'unmaximize-window': mainWindow.unmaximize(); break; } event.returnValue = 'ok'; }); ipcMain.on('/exec/invoke', (event, arg) => __awaiter(this, void 0, void 0, function* () { const message = JSON.parse(arg); const channel = `/exec/response/${message.hash}`; debug('invoke', message); try { const mod = yield Promise.resolve().then(() => require(message.module)); debug('invoke got module'); const returnValue = yield mod[message.main || 'main'](message.args); debug('invoke got returnValue', returnValue); event.sender.send(channel, JSON.stringify({ success: true, returnValue })); } catch (error) { debug('error in exec', error); event.sender.send(channel, JSON.stringify({ success: false, error })); } })); debug('createWindow done'); })); } exports.createWindow = createWindow; exports.getCommand = (argv) => { debug('getCommand', argv); const dashDash = argv.lastIndexOf('--'); argv = dashDash === -1 ? argv.slice(1) : argv.slice(dashDash + 1); argv = argv.filter(_ => _ !== '--ui' && _ !== '--no-color' && !_.match(/^-psn/)); const isShell = !process.env.KUI_POPUP && (argv.length === 0 || argv.find(_ => _ === 'shell') || (process.env.RUNNING_SHELL_TEST && !process.env.KUI_TEE_TO_FILE)); debug('isShell', argv, isShell); let subwindowPlease = true; let subwindowPrefs = { fullscreen: true, width: defaults_1.default.width, height: defaults_1.default.height }; if (isShell) { argv = ['shell']; subwindowPlease = false; subwindowPrefs = {}; } else if (process.env.KUI_POPUP) { argv = JSON.parse(process.env.KUI_POPUP); } debug('using args', argv, subwindowPrefs); return { argv, subwindowPlease, subwindowPrefs }; }; function initElectron(command = [], { isRunningHeadless = false } = {}, subwindowPlease, subwindowPrefs) { return __awaiter(this, void 0, void 0, function* () { debug('initElectron', command, subwindowPlease, subwindowPrefs); if (!app) { debug('loading electron'); const Electron = yield Promise.resolve().then(() => require('electron')); app = Electron.app; if (!app) { const path = yield Promise.resolve().then(() => require('path')); const { spawn } = yield Promise.resolve().then(() => require('child_process')); const appHome = path.resolve(path.join(__dirname, 'main')); const args = [appHome, '--', ...command]; debug('spawning electron', appHome, args); const windowOptions = {}; if (subwindowPlease) { debug('passing through subwindowPlease', subwindowPlease); windowOptions['subwindowPlease'] = subwindowPlease.toString(); } if (subwindowPrefs && Object.keys(subwindowPrefs).length > 0) { debug('passing through subwindowPrefs', subwindowPrefs); windowOptions['subwindowPrefs'] = JSON.stringify(subwindowPrefs); } const env = Object.assign({}, process.env, windowOptions); delete env.KUI_HEADLESS; const child = spawn(Electron.toString(), args, { stdio: debug.enabled ? 'inherit' : 'ignore', env }); if (!debug.enabled) { child.unref(); } debug('spawning electron done, this process will soon exit'); process.exit(0); } else { debug('loading electron done'); } } if (!process.env.RUNNING_SHELL_TEST) { app.on('second-instance', (event, commandLine) => { const { argv, subwindowPlease, subwindowPrefs } = exports.getCommand(commandLine); debug('opening window for second instance', commandLine, subwindowPlease, subwindowPrefs); createWindow(true, argv, subwindowPlease, subwindowPrefs); }); if (!app.requestSingleInstanceLock()) { debug('exiting, since we are not the first instance'); return app.exit(0); } } app.once('ready', () => { debug('opening primary window', command); createWindow(true, command.length > 0 && command, subwindowPlease, subwindowPrefs); }); app.on('window-all-closed', function () { if (process.platform !== 'darwin' || isRunningHeadless) { app.quit(); } else { app.hide(); } }); app.on('activate', function () { if (nWindows === 0) { createWindow(); } }); }); } exports.initElectron = initElectron; //# sourceMappingURL=spawn-electron.js.map