diff --git a/app/config.js b/app/config.js
deleted file mode 100644
index ab11e637..00000000
--- a/app/config.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/* global Notification */
-/* eslint no-new:0 */
-import React from 'react';
-import { ipcRenderer, remote } from 'electron';
-
-const config = remote.require('./config');
-
-export default class Config extends React.Component {
-
- constructor () {
- super();
- this.state = {
- config: config.getConfig()
- };
- this.onChange = this.onChange.bind(this);
- }
-
- onChange () {
- this.setState({ config: config.getConfig() });
- }
-
- componentDidMount () {
- ipcRenderer.on('config change', this.onChange);
- ipcRenderer.on('plugins change', this.onChange);
- }
-
- // passes `config` as props to the decorated component
- render () {
- const child = React.Children.only(this.props.children);
- const { config } = this.state;
- const decorate = remote.require('./plugins').decorateConfig;
- return React.cloneElement(child, { config: decorate(config) });
- }
-
- componentWillUnmount () {
- ipcRenderer.removeListener('config change', this.onChange);
- ipcRenderer.removeListener('plugins change', this.onChange);
- }
-
-}
diff --git a/app/css/hyperterm.css b/app/css/hyperterm.css
deleted file mode 100644
index e86db3fa..00000000
--- a/app/css/hyperterm.css
+++ /dev/null
@@ -1,105 +0,0 @@
-.main {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- border: 1px solid #333;
-}
-
-.mac.main {
- border-radius: 5px;
-}
-
-header {
- position: fixed;
- top: 1px;
- left: 1px;
- right: 1px;
- background: #000;
- z-index: 100;
-}
-
-.mac header {
- border-top-left-radius: 5px;
- border-top-right-radius: 5px;
-}
-
-.terms {
- position: absolute;
- margin-top: 28px;
- top: 0;
- right: 0;
- left: 0;
- bottom: 0;
- color: #fff;
-}
-
-.term {
- display: none;
-}
-
-.term.active {
- display: block;
-}
-
-.resize-indicator,
-.update-indicator {
- cursor: default;
- -webkit-user-select: none;
-}
-
-.resize-indicator {
- color: #fff;
- font: 11px Menlo;
- position: fixed;
- bottom: 20px;
- right: 20px;
- opacity: 0;
- transition: opacity 150ms ease-in;
- display: flex;
-}
-
-.resize-indicator > div {
- background: rgba(255, 255, 255, .2);
- padding: 6px 14px;
- margin-left: 10px;
-}
-
-.resize-indicator.showing {
- opacity: 1;
-}
-
-.update-indicator {
- background: #7ED321;
- padding: 6px 14px;
- color: #fff;
- font: 11px Menlo;
- position: fixed;
- bottom: 20px;
- right: 20px;
- opacity: 0;
- transition: opacity 150ms ease-in;
- pointer-events: none;
-}
-
-.update-indicator a {
- color: #fff;
-}
-
-.update-indicator .close {
- color: #528D11;
- cursor: pointer;
-}
-
-.update-indicator.showing {
- opacity: 1;
- pointer-events: inherit;
-}
-
-.icon {
- vertical-align: middle;
- fill: currentColor;
- width: 1em;
- height: 1em;
-}
diff --git a/app/css/tabs.css b/app/css/tabs.css
deleted file mode 100644
index 3886cbeb..00000000
--- a/app/css/tabs.css
+++ /dev/null
@@ -1,118 +0,0 @@
-nav {
- font-size: 12px;
- font-family: -apple-system, BlinkMacSystemFont,
- "Segoe UI", "Roboto", "Oxygen",
- "Ubuntu", "Cantarell", "Fira Sans",
- "Droid Sans", "Helvetica Neue", sans-serif;
- height: 34px;
- line-height: 34px;
- vertical-align: middle;
- color: #9B9B9B;
- cursor: default;
- -webkit-user-select: none;
-}
-
-.single {
- text-align: center;
- color: #fff;
-}
-
-.tabs {
- border-bottom: 1px solid #333;
- max-height: 34px;
- display: flex;
- flex-flow: row;
-}
-
-.tabs li:first-child {
- margin-left: 76px;
-}
-
-.tabs li {
- list-style-type: none;
- flex-grow: 1;
- text-align: center;
- position: relative;
-}
-
-.tabs li.is_active {
- color: #fff;
-}
-
-.tabs li span {
- transition: color .2s ease;
- display: block;
- border-left: 1px solid transparent;
- border-right: 1px solid transparent;
-}
-
-.tabs li.is_active span {
- border-left-color: #333;
- border-right-color: #333;
-}
-
-.tabs li.is_active:last-child span {
- border-right-color: transparent;
-}
-
-.tabs li.is_active::before {
- position: absolute;
- content: ' ';
- border-bottom: 1px solid #000;
- display: block;
- left: 1px;
- right: 1px;
- bottom: -1px;
-}
-
-.tabs li:not(.is_active):hover span {
- color: #ccc;
-}
-
-.tabs li.has_activity, .tabs li.has_activity:hover {
- color: #50E3C2;
-}
-
-/* The close button */
-
-.tabs li i {
- transition: opacity .2s ease,
- color .2s ease,
- transform .25s ease,
- background-color .1s ease;
- pointer-events: none;
- position: absolute;
- right: 7px;
- top: 8px;
- display: inline-block;
- width: 14px;
- height: 14px;
- border-radius: 100%;
- color: #e9e9e9;
- opacity: 0;
- transform: scale(.95);
-}
-
-.tabs li:hover i {
- opacity: 1;
- transform: none;
- pointer-events: all;
-}
-
-.tabs li i:hover {
- background-color: rgba(255,255,255, .13);
- color: #fff;
-}
-
-.tabs li i:active {
- background-color: rgba(255,255,255, .1);
- color: #909090;
-}
-
-.tabs li i .icon {
- position: absolute;
- left: 4px;
- top: 4px;
- width: 6px;
- height: 6px;
-}
diff --git a/app/hyperterm.js b/app/hyperterm.js
deleted file mode 100644
index 441e1cca..00000000
--- a/app/hyperterm.js
+++ /dev/null
@@ -1,532 +0,0 @@
-import Tabs_ from './tabs';
-import Term_ from './term';
-import RPC from './rpc';
-import Mousetrap from 'mousetrap';
-import classes from 'classnames';
-import shallowCompare from 'react-addons-shallow-compare';
-import React, { Component } from 'react';
-import decorate from './plugins';
-
-// make subcomponents reload siwth plugin changes
-const Tabs = decorate(Tabs_);
-const Term = decorate(Term_);
-
-export default class HyperTerm extends Component {
- constructor (props) {
- super();
- this.state = {
- cols: null,
- rows: null,
- hpadding: 12,
- vpadding: 12,
- sessions: [],
- titles: {},
- urls: {},
- active: null,
- activeMarkers: [],
- mac: /Mac/.test(navigator.userAgent),
- resizeIndicatorShowing: false,
- fontSizeIndicatorShowing: false,
- dismissedUpdate: false,
- updateVersion: null,
- fontSize: props.config.fontSize
- };
-
- // we set this to true when the first tab
- // has been initialized and ack'd by the
- // node server for the *first time*
- this.init = false;
-
- // we keep track of activity in tabs to avoid
- // placing an activity marker right after
- // opening
- this.tabWasActive = {};
-
- this.onResize = this.onResize.bind(this);
- this.onChange = this.onChange.bind(this);
- this.openExternal = this.openExternal.bind(this);
- this.quitAndInstall = this.quitAndInstall.bind(this);
- this.focusActive = this.focusActive.bind(this);
- this.closeBrowser = this.closeBrowser.bind(this);
- this.onHeaderMouseDown = this.onHeaderMouseDown.bind(this);
- this.closeTab = this.closeTab.bind(this);
-
- this.moveLeft = this.moveLeft.bind(this);
- this.moveRight = this.moveRight.bind(this);
- this.resetFontSize = this.resetFontSize.bind(this);
- this.increaseFontSize = this.increaseFontSize.bind(this);
- this.decreaseFontSize = this.decreaseFontSize.bind(this);
-
- this.dismissUpdate = this.dismissUpdate.bind(this);
- this.onUpdateAvailable = this.onUpdateAvailable.bind(this);
-
- document.body.style.backgroundColor = props.config.backgroundColor;
- }
-
- componentWillReceiveProps (props) {
- if (props.config.fontSize !== this.props.config.fontSize) {
- this.changeFontSize(props.config.fontSize);
- }
-
- if (props.config.backgroundColor !== this.props.config.backgroundColor) {
- document.body.style.backgroundColor = props.config.backgroundColor;
- }
- }
-
- render () {
- const { backgroundColor, borderColor, css } = this.props.config;
- return
-
-
- {
- const title = this.state.titles[uid];
- return null != title ? title : 'Shell';
- })}
- onChange={this.onChange}
- onClose={this.closeTab}
- />
-
-
-
{
- this.state.sessions.map((uid, i) => {
- const active = i === this.state.active;
- const { config } = this.props;
- return
-
-
;
- })
- }
-
-
- {this.state.fontSizeIndicatorShowing &&
{ this.state.fontSize }px
}
-
{ this.state.cols }x{ this.state.rows }
-
-
- Version
{ this.state.updateVersion } ready.
- {this.state.updateNote ? ` ${this.state.updateNote}. ` : ' '}
-
Restart
- to apply
[x]
-
-
-
;
- }
-
- dismissUpdate () {
- this.setState({ dismissedUpdate: true });
- }
-
- quitAndInstall (ev) {
- ev.preventDefault();
- this.rpc.emit('quit and install');
- }
-
- openExternal (ev) {
- ev.preventDefault();
- this.rpc.emit('open external', { url: ev.target.href });
- }
-
- requestTab () {
- // we send the hterm default size
- this.rpc.emit('new', {
- cols: this.state.cols,
- rows: this.state.rows
- });
- }
-
- closeActiveTab () {
- this.closeTab(this.state.active);
- }
-
- closeTab (id) {
- if (this.state.sessions.length) {
- const uid = this.state.sessions[id];
- this.rpc.emit('exit', { uid });
- this.onSessionExit({ uid });
- }
- }
-
- closeBrowser () {
- const uid = this.state.sessions[this.state.active];
- if (this.state.urls[uid]) {
- const urls = Object.assign({}, this.state.urls);
- delete urls[uid];
- this.setState({ urls });
- }
- }
-
- write (uid, data) {
- this.rpc.emit('data', { uid, data });
- }
-
- onURL (uid, url) {
- const urls = Object.assign({}, this.state.urls, { [uid]: url });
- this.setState({ urls });
- }
-
- onRemoteTitle ({ uid, title }) {
- this.setTitle(uid, title);
- }
-
- setTitle (uid, title) {
- const { titles: _titles } = this.state;
- const titles = Object.assign({}, _titles, { [uid]: title });
- this.setState({ titles });
- }
-
- onActive (uid) {
- const i = this.state.sessions.indexOf(uid);
-
- // we ignore activity markers all the way
- // up to the tab's been active
- const wasActive = this.tabWasActive[uid];
- if (!wasActive) {
- console.log('ignoring active, tab has not been focused', uid);
- this.tabWasActive[uid] = true;
- return;
- }
-
- if (this.state.active !== i && !~this.state.activeMarkers.indexOf(i)) {
- const activeMarkers = this.state.activeMarkers.slice();
- activeMarkers.push(i);
- this.setState({ activeMarkers });
- }
- }
-
- shouldComponentUpdate (nextProps, nextState) {
- if (this.state.active !== nextState.active) {
- const curUid = this.state.sessions[this.state.active];
- // make sure that the blurred uid has not been
- // optimistically removed
- if (curUid && ~nextState.sessions.indexOf(curUid)) {
- this.rpc.emit('blur', { uid: curUid });
- }
- const nextUid = nextState.sessions[nextState.active];
- this.rpc.emit('focus', { uid: nextUid });
- this.shouldInitKeys = true;
- } else {
- this.shouldInitKeys = false;
- }
-
- return shallowCompare(this, nextProps, nextState);
- }
-
- componentDidMount () {
- this.rpc = new RPC();
-
- // open a new tab upon mounting
- this.rpc.once('ready', () => this.requestTab());
-
- this.rpc.on('new session', ({ uid }) => {
- const { sessions: _sessions } = this.state;
- const sessions = _sessions.concat(uid);
- const state = { sessions };
- state.active = sessions.length - 1;
- this.setState(state, () => {
- if (this.state.sessions.length && !this.init) {
- this.rpc.emit('init');
- this.init = true;
- }
- });
- });
-
- this.rpc.on('clear', this.clearCurrentTerm.bind(this));
- this.rpc.on('exit', this.onSessionExit.bind(this));
-
- this.rpc.on('data', ({ uid, data }) => {
- if (this.ignoreActivity) {
- // we ignore activity for up to 300ms after triggering
- // a resize to avoid setting up markers incorrectly
- if (Date.now() - this.ignoreActivity < 300) {
- console.log('ignore activity after resizing');
- } else {
- this.ignoreActivity = null;
- this.onActive(uid);
- }
- } else {
- this.onActive(uid);
- }
- this.refs[`term-${uid}`].write(data);
- });
-
- this.rpc.on('new tab', this.requestTab.bind(this));
- this.rpc.on('close tab', this.closeActiveTab.bind(this));
- this.rpc.on('title', this.onRemoteTitle.bind(this));
-
- this.rpc.on('move left', this.moveLeft);
- this.rpc.on('move right', this.moveRight);
- this.rpc.on('increase font size', this.increaseFontSize);
- this.rpc.on('decrease font size', this.decreaseFontSize);
- this.rpc.on('reset font size', this.resetFontSize);
-
- this.rpc.on('update available', this.onUpdateAvailable);
- this.rpc.on('preferences', this.editPreferences.bind(this));
- }
-
- clearCurrentTerm () {
- const uid = this.state.sessions[this.state.active];
- const term = this.refs[`term-${uid}`];
- term.clear();
- }
-
- onUpdateAvailable ({ releaseName, releaseNotes = '' }) {
- this.setState({
- updateVersion: releaseName,
- updateNote: releaseNotes.split(/\n/)[0].trim()
- });
- }
-
- editPreferences () {
- this.requestTab();
- const onsession = ({ uid: _uid }) => {
- const ondata = ({ uid }) => {
- if (uid !== _uid) return;
- this.rpc.removeListener('data', ondata);
- this.rpc.emit('data', { uid, data: '# Attempting to open ~/.hyperterm.js with your $EDITOR\n' +
- '# If this doesn\'t work, open it manually with your favorite editor!\n' +
- '$EDITOR ~/.hyperterm.js && exit\n' });
- };
- this.rpc.on('data', ondata);
- };
- this.rpc.once('new session', onsession);
- }
-
- moveTo (n) {
- if (this.state.sessions[n]) {
- this.setActive(n);
- }
- }
-
- moveLeft () {
- const next = this.state.active - 1;
- if (this.state.sessions[next]) {
- this.setActive(next);
- } else if (this.state.sessions.length > 1) {
- // go to the end
- this.setActive(this.state.sessions.length - 1);
- }
- }
-
- moveRight () {
- const next = this.state.active + 1;
- if (this.state.sessions[next]) {
- this.setActive(next);
- } else if (this.state.sessions.length > 1) {
- // go to the beginning
- this.setActive(0);
- }
- }
-
- changeFontSize (value, { relative = false } = {}) {
- this.setState({
- fontSize: relative ? this.state.fontSize + value : value,
- fontSizeIndicatorShowing: true
- });
-
- clearTimeout(this.fontSizeIndicatorTimeout);
- this.fontSizeIndicatorTimeout = setTimeout(() => {
- this.setState({ fontSizeIndicatorShowing: false });
- }, 1500);
- }
-
- resetFontSize () {
- this.changeFontSize(this.props.config.fontSize);
- }
-
- increaseFontSize () {
- this.changeFontSize(1, { relative: true });
- }
-
- decreaseFontSize () {
- this.changeFontSize(-1, { relative: true });
- }
-
- onSessionExit ({ uid }) {
- if (!~this.state.sessions.indexOf(uid)) {
- console.log('ignore exit of', uid);
- return;
- }
-
- const {
- sessions: _sessions,
- titles: _titles,
- active: _active,
- activeMarkers
- } = this.state;
-
- const titles = Object.assign({}, _titles);
- delete titles[uid];
-
- delete this.tabWasActive[uid];
-
- const i = _sessions.indexOf(uid);
- const sessions = _sessions.slice();
- sessions.splice(i, 1);
-
- if (!sessions.length) {
- return window.close();
- }
-
- const ai = activeMarkers.indexOf(i);
- if (~ai) {
- activeMarkers.splice(ai, 1);
- }
-
- let active;
- if (i === _active) {
- if (sessions.length) {
- active = sessions[i - 1] ? i - 1 : i;
- } else {
- active = null;
- }
- } else if (i < _active) {
- active = _active - 1;
- }
-
- const ai2 = activeMarkers.indexOf(active);
- if (~ai2) {
- activeMarkers.splice(ai2, 1);
- }
-
- this.setState({
- sessions,
- titles,
- active,
- activeMarkers
- });
- }
-
- componentDidUpdate () {
- if (this.shouldInitKeys) {
- if (this.keys) {
- this.keys.reset();
- }
-
- const uid = this.state.sessions[this.state.active];
- const term = this.refs[`term-${uid}`];
- const keys = new Mousetrap(term.getTermDocument());
- keys.bind('command+1', this.moveTo.bind(this, 0));
- keys.bind('command+2', this.moveTo.bind(this, 1));
- keys.bind('command+3', this.moveTo.bind(this, 2));
- keys.bind('command+4', this.moveTo.bind(this, 3));
- keys.bind('command+5', this.moveTo.bind(this, 4));
- keys.bind('command+6', this.moveTo.bind(this, 5));
- keys.bind('command+7', this.moveTo.bind(this, 6));
- keys.bind('command+8', this.moveTo.bind(this, 7));
- keys.bind('command+9', this.moveTo.bind(this, 8));
- keys.bind('command+shift+left', this.moveLeft);
- keys.bind('command+shift+right', this.moveRight);
- keys.bind('command+shift+[', this.moveLeft);
- keys.bind('command+shift+]', this.moveRight);
- keys.bind('command+alt+left', this.moveLeft);
- keys.bind('command+alt+right', this.moveRight);
-
- this.keys = keys;
- }
-
- this.focusActive();
- }
-
- focusActive () {
- // get active uid and term
- const uid = this.state.sessions[this.state.active];
- const term = this.refs[`term-${uid}`];
- if (term) {
- term.focus();
- }
- }
-
- onResize (dim) {
- if (dim.rows !== this.state.rows || dim.cols !== this.state.cols) {
- this.ignoreActivity = Date.now();
- this.rpc.emit('resize', dim);
- const state = Object.assign({}, dim,
- // if it's the first time we hear about the resize we
- // don't show the indicator
- null === this.state.rows ? {} : { resizeIndicatorShowing: true }
- );
- this.setState(state);
- clearTimeout(this.resizeIndicatorTimeout);
- this.resizeIndicatorTimeout = setTimeout(() => {
- this.setState({ resizeIndicatorShowing: false });
- }, 1500);
- }
- }
-
- onChange (active) {
- // we ignore clicks if they're a byproduct of a drag
- // motion to move the window
- if (window.screenX !== this.headerMouseDownWindowX ||
- window.screenY !== this.headerMouseDownWindowY) {
- return;
- }
-
- this.setActive(active);
- }
-
- setActive (active) {
- if (~this.state.activeMarkers.indexOf(active)) {
- const { activeMarkers } = this.state;
- activeMarkers.splice(activeMarkers.indexOf(active), 1);
- this.setState({ active, activeMarkers });
- } else {
- this.setState({ active });
- }
- }
-
- onHeaderMouseDown () {
- this.headerMouseDownWindowX = window.screenX;
- this.headerMouseDownWindowY = window.screenY;
-
- this.clicks = this.clicks || 1;
-
- if (this.clicks++ >= 2) {
- if (this.maximized) {
- this.rpc.emit('unmaximize');
- } else {
- this.rpc.emit('maximize');
- }
- this.clicks = 0;
- this.maximized = !this.maximized;
- } else {
- // http://www.quirksmode.org/dom/events/click.html
- // https://en.wikipedia.org/wiki/Double-click
- this.clickTimer = setTimeout(() => {
- this.clicks = 0;
- }, 500);
- }
- }
-
- componentWillUnmount () {
- this.rpc.destroy();
- clearTimeout(this.resizeIndicatorTimeout);
- clearTimeout(this.fontSizeIndicatorTimeout);
- if (this.keys) this.keys.reset();
- delete this.clicks;
- clearTimeout(this.clickTimer);
- this.updateChecker.destroy();
- }
-}
diff --git a/app/index.html b/app/index.html
index 51035a82..b3e050c9 100644
--- a/app/index.html
+++ b/app/index.html
@@ -5,7 +5,6 @@