This commit is contained in:
Eugene Pankov 2016-12-27 22:21:02 +01:00
parent d7bae654eb
commit f7af82902f
9 changed files with 92 additions and 12 deletions

View file

@ -27,10 +27,21 @@ setupWindowManagement = () => {
})
electron.ipcMain.on('window-focus', () => {
app.window.show()
app.window.focus()
})
electron.ipcMain.on('window-focus', () => {
app.window.focus()
})
electron.ipcMain.on('window-toggle-focus', () => {
if (app.window.isFocused()) {
app.window.minimize()
} else {
app.window.focus()
}
})
electron.ipcMain.on('window-maximize', () => {
if (app.window.isMaximized()) {
app.window.unmaximize()

View file

@ -92,7 +92,7 @@
.tab {
flex: auto;
flex-basis: 0;
flex-grow: 1;
flex-grow: 1000;
background: @body-bg;
@ -178,6 +178,7 @@
display: none;
flex: auto;
position: relative;
padding: 10px 15px;
&.active {
display: flex;

View file

@ -14,6 +14,7 @@
[class.active]='tab == activeTab',
[class.pre-selected]='tabs[idx + 1] == activeTab',
[class.post-selected]='tabs[idx - 1] == activeTab',
@animateTab,
)
div.index {{idx + 1}}
div.name {{tab.name || 'Terminal'}}

View file

@ -1,4 +1,4 @@
import { Component, ElementRef } from '@angular/core'
import { Component, ElementRef, trigger, style, animate, transition, state } from '@angular/core'
import { ModalService } from 'services/modal'
import { ElectronService } from 'services/electron'
import { HostAppService } from 'services/hostApp'
@ -29,6 +29,24 @@ class Tab {
selector: 'app',
template: require('./app.pug'),
styles: [require('./app.less')],
animations: [
trigger('animateTab', [
state('in', style({
'flex-grow': '1000',
})),
transition(':enter', [
style({
'flex-grow': '1',
}),
animate('250ms ease-in-out')
]),
transition(':leave', [
animate('250ms ease-in-out', style({
'flex-grow': '1',
}))
])
])
]
})
export class AppComponent {
constructor(
@ -65,8 +83,19 @@ export class AppComponent {
this.selectTab(this.tabs[9])
}
}
if (key.ctrl && key.shift && key.key == 'W' && this.activeTab) {
this.closeTab(this.activeTab)
}
if (key.ctrl && key.shift && key.key == 'T' && this.activeTab) {
this.newTab()
}
}
})
this.hotkeys.registerHotkeys()
this.hotkeys.globalHotkey.subscribe(() => {
this.hostApp.toggleWindow()
})
}
toasterConfig: ToasterConfig
@ -92,9 +121,10 @@ export class AppComponent {
closeTab (tab) {
tab.session.gracefullyDestroy()
let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
this.tabs = this.tabs.filter((x) => x != tab)
if (tab == this.activeTab) {
this.selectTab(this.tabs[0])
this.selectTab(this.tabs[newIndex])
}
}

View file

@ -20,7 +20,12 @@ hterm.hterm.VT.ESC['k'] = function(parseState) {
}
hterm.hterm.defaultStorage = new hterm.lib.Storage.Memory()
hterm.hterm.PreferenceManager.defaultPreferences['user-css'] = ``
const pmgr = new hterm.hterm.PreferenceManager('default')
pmgr.set('user-css', ``)
pmgr.set('background-color', '#1D272D')
pmgr.set('color-palette-overrides', {
0: '#1D272D',
})
const oldDecorate = hterm.hterm.ScrollPort.prototype.decorate
hterm.hterm.ScrollPort.prototype.decorate = function (...args) {
oldDecorate.bind(this)(...args)
@ -73,6 +78,8 @@ export class TerminalComponent {
console.log(`Resizing to ${columns}x${rows}`)
this.session.resize(columns, rows)
}
this.session.releaseInitialDataBuffer()
}
this.terminal.decorate(this.elementRef.nativeElement)
}

View file

@ -19,6 +19,7 @@ export class ElectronService {
this.shell = this.electron.shell
this.clipboard = this.electron.clipboard
this.ipcRenderer = this.electron.ipcRenderer
this.globalShortcut = this.remoteElectron.globalShortcut
}
initTest() {
@ -34,6 +35,7 @@ export class ElectronService {
shell: any
dialog: any
clipboard: any
globalShortcut: any
private electron: any
private remoteElectron: any
}

View file

@ -62,6 +62,10 @@ export class HostAppService {
this.electron.ipcRenderer.send('window-focus')
}
toggleWindow() {
this.electron.ipcRenderer.send('window-toggle-focus')
}
minimizeWindow () {
this.electron.ipcRenderer.send('window-minimize')
}

View file

@ -1,4 +1,5 @@
import { Injectable, NgZone, EventEmitter } from '@angular/core'
import { ElectronService } from 'services/electron'
const hterm = require('hterm-commonjs')
@ -14,8 +15,12 @@ export interface Key {
@Injectable()
export class HotkeysService {
key = new EventEmitter<Key>()
globalHotkey = new EventEmitter()
constructor(private zone: NgZone) {
constructor(
private zone: NgZone,
private electron: ElectronService,
) {
let events = [
{
name: 'keydown',
@ -45,7 +50,6 @@ export class HotkeysService {
}
emitNativeEvent (name, nativeEvent) {
console.debug('Key', nativeEvent)
this.zone.run(() => {
this.key.emit({
event: name,
@ -57,4 +61,11 @@ export class HotkeysService {
})
})
}
registerHotkeys () {
this.electron.globalShortcut.unregisterAll()
this.electron.globalShortcut.register('`', () => {
this.globalHotkey.emit()
})
}
}

View file

@ -57,17 +57,20 @@ export interface SessionOptions {
export class Session {
open: boolean
name: string
pty: any
dataAvailable = new EventEmitter()
closed = new EventEmitter()
destroyed = new EventEmitter()
private pty: any
private initialDataBuffer = ''
private initialDataBufferReleased = false
constructor (options: SessionOptions) {
this.name = options.name
console.log('Spawning', options.command)
this.pty = ptyjs.spawn('sh', ['-c', options.command], {
name: 'screen-256color',
//name: 'xterm-256color',
//name: 'xterm-color',
name: 'xterm-256color',
cols: 80,
rows: 30,
cwd: options.cwd || process.env.HOME,
@ -77,7 +80,11 @@ export class Session {
this.open = true
this.pty.on('data', (data) => {
this.dataAvailable.emit(data)
if (!this.initialDataBufferReleased) {
this.initialDataBuffer += data
} else {
this.dataAvailable.emit(data)
}
})
this.pty.on('close', () => {
@ -86,6 +93,12 @@ export class Session {
})
}
releaseInitialDataBuffer () {
this.initialDataBufferReleased = true
this.dataAvailable.emit(this.initialDataBuffer)
this.initialDataBuffer = null
}
resize (columns, rows) {
this.pty.resize(columns, rows)
}
@ -143,8 +156,8 @@ export class SessionsService {
log: LogService,
) {
this.logger = log.create('sessions')
this.recoveryProvider = new ScreenSessionRecoveryProvider()
//this.recoveryProvider = new NullSessionRecoveryProvider()
//this.recoveryProvider = new ScreenSessionRecoveryProvider()
this.recoveryProvider = new NullSessionRecoveryProvider()
}
createNewSession (options: SessionOptions) : Session {