kui-shell
Version:
This is the monorepo for Kui, the hybrid command-line/GUI electron-based Kubernetes tool
328 lines • 14.1 kB
JavaScript
;
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