mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-13 04:28:41 -09:00
This reverts commit 9e3fe9228d.
@freebroccolo while great in theory, this breaks uglifyjs.
minification provides an important advantage in interpretation
time (and therefore reduced bootup time)
255 lines
5.8 KiB
JavaScript
255 lines
5.8 KiB
JavaScript
const { app, BrowserWindow, shell, Menu } = require('electron');
|
|
const createRPC = require('./rpc');
|
|
const createMenu = require('./menu');
|
|
const Session = require('./session');
|
|
const genUid = require('uid2');
|
|
const { resolve } = require('path');
|
|
const isDev = require('electron-is-dev');
|
|
const AutoUpdater = require('./auto-updater');
|
|
const toHex = require('convert-css-color-name-to-hex');
|
|
|
|
// set up config
|
|
const config = require('./config');
|
|
config.init();
|
|
const plugins = require('./plugins');
|
|
|
|
const windowSet = new Set([]);
|
|
|
|
// expose to plugins
|
|
app.config = config;
|
|
app.plugins = plugins;
|
|
app.getWindows = () => new Set([...windowSet]); // return a clone
|
|
|
|
if (isDev) {
|
|
console.log('running in dev mode');
|
|
} else {
|
|
console.log('running in prod mode');
|
|
}
|
|
|
|
const url = 'file://' + resolve(
|
|
isDev ? __dirname : app.getAppPath(),
|
|
// in prod version, we copy over index.html and dist from 'app'
|
|
// into one dist folder to avoid unwanted files in package
|
|
isDev ? 'app' : 'build',
|
|
'index.html'
|
|
);
|
|
|
|
console.log('electron will open', url);
|
|
|
|
app.on('window-all-closed', () => {
|
|
if (process.platform !== 'darwin') {
|
|
app.quit();
|
|
}
|
|
});
|
|
|
|
app.on('ready', () => {
|
|
function createWindow (fn) {
|
|
const cfg = plugins.getDecoratedConfig();
|
|
const [width, height] = cfg.windowSize || [540, 380];
|
|
|
|
const browserDefaults = {
|
|
width,
|
|
height,
|
|
minHeight: 190,
|
|
minWidth: 370,
|
|
titleBarStyle: 'hidden-inset',
|
|
title: 'HyperTerm',
|
|
backgroundColor: toHex(cfg.backgroundColor || '#000'),
|
|
transparent: true,
|
|
icon: resolve(__dirname, 'static/icon.png'),
|
|
// we only want to show when the prompt
|
|
// is ready for user input
|
|
show: process.env.HYPERTERM_DEBUG || isDev
|
|
};
|
|
const browserOptions = plugins.getDecoratedBrowserOptions(browserDefaults);
|
|
|
|
const win = new BrowserWindow(browserOptions);
|
|
|
|
windowSet.add(win);
|
|
win.loadURL(url);
|
|
|
|
const rpc = createRPC(win);
|
|
const sessions = new Map();
|
|
|
|
// config changes
|
|
const cfgUnsubscribe = config.subscribe(() => {
|
|
win.webContents.send('config change');
|
|
});
|
|
|
|
rpc.on('init', () => {
|
|
win.show();
|
|
if (fn) fn(win);
|
|
|
|
// auto updates
|
|
if (!isDev && process.platform !== 'linux') {
|
|
AutoUpdater(win);
|
|
} else {
|
|
console.log('ignoring auto updates during dev');
|
|
}
|
|
});
|
|
|
|
rpc.on('new', ({ rows = 40, cols = 100, cwd = process.env.HOME }) => {
|
|
const shell = cfg.shell;
|
|
|
|
initSession({ rows, cols, cwd, shell }, (uid, session) => {
|
|
sessions.set(uid, session);
|
|
rpc.emit('session add', {
|
|
uid,
|
|
shell: session.shell,
|
|
pid: session.pty.pid
|
|
});
|
|
|
|
session.on('data', (data) => {
|
|
rpc.emit('session data', { uid, data });
|
|
});
|
|
|
|
session.on('title', (title) => {
|
|
rpc.emit('session title', { uid, title });
|
|
});
|
|
|
|
session.on('exit', () => {
|
|
rpc.emit('session exit', { uid });
|
|
sessions.delete(uid);
|
|
});
|
|
});
|
|
});
|
|
|
|
// TODO: this goes away when we are able to poll
|
|
// for the title ourseleves, instead of relying
|
|
// on Session and focus/blur to subscribe
|
|
rpc.on('focus', ({ uid }) => {
|
|
const session = sessions.get(uid);
|
|
|
|
if (session) {
|
|
session.focus();
|
|
} else {
|
|
console.log('session not found by', uid);
|
|
}
|
|
});
|
|
|
|
rpc.on('blur', ({ uid }) => {
|
|
const session = sessions.get(uid);
|
|
|
|
if (session) {
|
|
session.blur();
|
|
} else {
|
|
console.log('session not found by', uid);
|
|
}
|
|
});
|
|
|
|
rpc.on('exit', ({ uid }) => {
|
|
sessions.get(uid).exit();
|
|
});
|
|
|
|
rpc.on('unmaximize', () => {
|
|
win.unmaximize();
|
|
});
|
|
|
|
rpc.on('maximize', () => {
|
|
win.maximize();
|
|
});
|
|
|
|
rpc.on('resize', ({ cols, rows }) => {
|
|
sessions.forEach((session) => {
|
|
session.resize({ cols, rows });
|
|
});
|
|
});
|
|
|
|
rpc.on('data', ({ uid, data }) => {
|
|
sessions.get(uid).write(data);
|
|
});
|
|
|
|
rpc.on('open external', ({ url }) => {
|
|
shell.openExternal(url);
|
|
});
|
|
|
|
rpc.win.on('move', () => {
|
|
rpc.emit('move');
|
|
});
|
|
|
|
const deleteSessions = () => {
|
|
sessions.forEach((session, key) => {
|
|
session.removeAllListeners();
|
|
session.destroy();
|
|
sessions.delete(key);
|
|
});
|
|
};
|
|
|
|
// we reset the rpc channel only upon
|
|
// subsequent refreshes (ie: F5)
|
|
let i = 0;
|
|
win.webContents.on('did-navigate', () => {
|
|
if (i++) {
|
|
deleteSessions();
|
|
}
|
|
});
|
|
|
|
// expose internals to extension authors
|
|
win.rpc = rpc;
|
|
win.sessions = sessions;
|
|
|
|
const load = () => {
|
|
plugins.onWindow(win);
|
|
};
|
|
|
|
// load plugins
|
|
load();
|
|
|
|
const pluginsUnsubscribe = plugins.subscribe((err) => {
|
|
if (!err) {
|
|
load();
|
|
win.webContents.send('plugins change');
|
|
}
|
|
});
|
|
|
|
// the window can be closed by the browser process itself
|
|
win.on('close', () => {
|
|
windowSet.delete(win);
|
|
rpc.destroy();
|
|
deleteSessions();
|
|
cfgUnsubscribe();
|
|
pluginsUnsubscribe();
|
|
});
|
|
}
|
|
|
|
// when opening create a new window
|
|
createWindow();
|
|
|
|
// expose to plugins
|
|
app.createWindow = createWindow;
|
|
|
|
// mac only. when the dock icon is clicked
|
|
// and we don't have any active windows open,
|
|
// we open one
|
|
app.on('activate', () => {
|
|
if (!windowSet.size) {
|
|
createWindow();
|
|
}
|
|
});
|
|
|
|
const setupMenu = () => {
|
|
const tpl = plugins.decorateMenu(createMenu({
|
|
createWindow,
|
|
updatePlugins: () => {
|
|
plugins.updatePlugins({ force: true });
|
|
}
|
|
}));
|
|
|
|
Menu.setApplicationMenu(Menu.buildFromTemplate(tpl));
|
|
};
|
|
|
|
const load = () => {
|
|
plugins.onApp(app);
|
|
setupMenu();
|
|
};
|
|
|
|
load();
|
|
plugins.subscribe(load);
|
|
});
|
|
|
|
function initSession (opts, fn) {
|
|
genUid(20, (err, uid) => {
|
|
if (err) throw err;
|
|
fn(uid, new Session(opts));
|
|
});
|
|
}
|