This commit is contained in:
Eugene Pankov 2016-12-26 00:04:56 +01:00
parent 8a02fd1708
commit 4e451d0598
8 changed files with 160 additions and 120 deletions

View file

@ -9,5 +9,5 @@ html
window.nodeRequire = require
script(src='./preload.js')
script(src='./bundle.js', defer)
body(style='background-image: radial-gradient(circle, #2b3840 0%, #1D272D 100%); min-height: 100vh')
body(style='background: ; min-height: 100vh')
app

View file

@ -75,10 +75,10 @@ start = () => {
let options = {
width: 800,
height: 400,
icon: `${app.getAppPath()}/assets/img/icon.png`,
//icon: `${app.getAppPath()}/assets/img/icon.png`,
title: 'ELEMENTS Benchmark',
minWidth: 800,
minHeight: 400,
minWidth: 300,
minHeight: 100,
'web-preferences': {'web-security': false},
//- background to avoid the flash of unstyled window
backgroundColor: '#1D272D',

View file

@ -12,121 +12,123 @@
background: @body-bg;
}
@tabs-height: 40px;
.navbar {
.tabs {
flex: none;
border-left: none;
border-right: none;
border-top: none;
-webkit-app-region: drag;
margin: 0;
height: @tabs-height;
background: @navbar-default-bg;
:host.platform-darwin & {
background: fade(@navbar-default-bg, 50%);
display: flex;
flex-direction: row;
.btn-new-tab, .tab {
line-height: @tabs-height - 2px;
cursor: pointer;
}
.navbar-btn-big {
margin: 0;
padding: 15px 20px 15px;
background-color: #333;
text-align: left;
.btn-new-tab {
padding: 0 15px;
flex: none;
flex-grow: 0;
border-bottom: 2px solid transparent;
transition: 0.25s all;
background: transparent;
box-shadow: none;
text-transform: uppercase;
font-weight: bold;
color: #888;
&.btn-profile {
padding: 7px 14px 7px;
display: flex;
flex-direction: row;
max-width: 150px;
:host.platform-darwin & {
max-width: 120px;
}
>img {
flex: none;
float: left;
margin: 2px 10px 4px 0;
width: 30px;
height: 30px;
:host.platform-darwin & {
margin-right: 0;
}
}
>div {
flex: auto;
:host.platform-darwin & {
display: none;
}
.username {
}
.settings {
font-size: 10px;
}
}
i {
margin-right: 10px;
}
&.btn-close {
font-size: 38px;
padding: 1px 13px 2px;
line-height: 47px;
&:hover {
background: rgba(255, 255, 255, .1);
}
:host.platform-darwin & {
display: none;
}
&:active {
background: rgba(0, 0, 0, .1);
}
}
button.navbar-btn-big:hover {
background-color: #222;
}
.tab {
flex: auto;
flex-basis: 0;
flex-grow: 1;
button.navbar-btn-big:active {
background-color: #111;
}
display: flex;
flex-direction: row;
div {
flex: auto;
padding: 0 15px;
}
.navbar-brand {
padding: 11px 15px;
width: 150px;
border-bottom: 2px solid transparent;
transition: 0.25s all;
&:hover:not(.active) {
background: rgba(255, 255, 255, .05);
}
&:active {
background: rgba(0, 0, 0, .1);
}
&.active {
background: #141c23;
border-bottom: 2px solid #69bbea;
}
button {
flex: none;
border: none;
background: transparent;
opacity: 0;
transition: 0.25s all;
@button-size: @tabs-height * 0.6;
width: @button-size;
height: @button-size;
border-radius: @button-size / 2;
line-height: @button-size * 0.8;
margin-top: (@tabs-height - @button-size) * 0.4;
margin-right: 10px;
:host.platform-darwin & {
display: block;
margin: auto;
float: none;
text-align: center;
font-size: 20px;
&:hover {
background: rgba(255, 255, 255, .05);
}
&:active {
background: rgba(0, 0, 0, .1);
}
}
img {
height: 28px;
&:hover button {
opacity: 1;
}
}
}
[scrollable] {
width: 100vw;
.tabs-content {
flex: auto;
display: flex;
.nano {
.tab {
display: none;
flex: auto;
height: auto;
position: relative;
&.active {
display: flex;
>* {
flex: auto;
}
}
}
}
footer {
display: block;
flex: none;
height: 1px;
}
perfect-scrollbar {
flex: auto;
min-height: 0;
}

View file

@ -1,19 +1,14 @@
div.navbar.navbar-default.draggable
button.btn.btn-default.navbar-btn.navbar-btn-big.btn-close.pull-right((click)='hide()', title='Hide')
| ×
button.btn.btn-default.navbar-btn.navbar-btn-big.pull-right((click)='showSettings()', title='Settings')
i.fa.fa-cog
.tabs
.tab(*ngFor='let tab of tabs; trackBy: tab?.id', (click)='selectTab(tab)', [class.active]='tab == activeTab')
div {{tab.name}}
button((click)='closeTab(tab)') ×
.btn-new-tab((click)='newTab()')
i.fa.fa-plus
span Tab
ngb-tabset
ngb-tab(*ngFor='let tab of tabs; trackBy: tab?.name')
template(ngbTabTitle)
span {{tab.name}}
button.btn.btn-default((click)='closeTab(tab)') ×
template(ngbTabContent)
terminal([session]='tab', style='width: 300px; height: 300px;')
button.btn.btn-default((click)='newTab()') New tab
footer
.tabs-content
.tab(*ngFor='let tab of tabs; trackBy: tab?.id', [class.active]='tab == activeTab')
terminal([session]='tab.session', '[(title)]'='tab.name')
toaster-container([toasterconfig]="toasterconfig")
template(ngbModalContainer)

View file

@ -1,4 +1,4 @@
import { Component, ElementRef } from '@angular/core'
import { Component } from '@angular/core'
import { ModalService } from 'services/modal'
import { ElectronService } from 'services/electron'
import { HostAppService } from 'services/hostApp'
@ -13,6 +13,17 @@ import 'angular2-toaster/lib/toaster.css'
import 'global.less'
class Tab {
id: number
name: string
static lastTabID = 0
constructor (public session: Session) {
this.id = Tab.lastTabID++
}
}
@Component({
selector: 'app',
template: require('./app.pug'),
@ -24,7 +35,6 @@ export class AppComponent {
private modal: ModalService,
private electron: ElectronService,
private sessions: SessionsService,
element: ElementRef,
log: LogService,
_quitter: QuitterService,
) {
@ -41,17 +51,27 @@ export class AppComponent {
}
toasterConfig: ToasterConfig
tabs: Session[] = []
tabs: Tab[] = []
activeTab: Tab
newTab () {
this.tabs.push(this.sessions.createSession({command: 'zsh'}))
const tab = new Tab(this.sessions.createSession({command: 'bash'}))
this.tabs.push(tab)
this.selectTab(tab)
}
closeTab (session) {
session.destroy()
selectTab (tab) {
this.activeTab = tab
}
closeTab (tab) {
tab.session.destroy()
this.tabs = this.tabs.filter((x) => x != tab)
this.selectTab(this.tabs[0])
}
ngOnInit () {
this.newTab()
}
ngOnDestroy () {

View file

@ -1,4 +1,4 @@
import { Component, Input, ElementRef } from '@angular/core'
import { Component, NgZone, Input, Output, EventEmitter, ElementRef } from '@angular/core'
import { ElectronService } from 'services/electron'
import { ConfigService } from 'services/config'
@ -7,6 +7,19 @@ import { Session } from 'services/sessions'
const hterm = require('hterm-commonjs')
hterm.hterm.VT.ESC['k'] = function(parseState) {
parseState.resetArguments();
function parseOSC(parseState) {
if (!this.parseUntilStringTerminator_(parseState) || parseState.func == parseOSC) {
return
}
this.terminal.setWindowTitle(parseState.args[0])
}
parseState.func = parseOSC
}
@Component({
selector: 'terminal',
template: '',
@ -14,9 +27,12 @@ const hterm = require('hterm-commonjs')
})
export class TerminalComponent {
@Input() session: Session
title: string
@Output() titleChange = new EventEmitter()
private terminal: any
constructor(
private zone: NgZone,
private electron: ElectronService,
private elementRef: ElementRef,
public config: ConfigService,
@ -27,23 +43,28 @@ export class TerminalComponent {
let io
hterm.hterm.defaultStorage = new hterm.lib.Storage.Memory()
this.terminal = new hterm.hterm.Terminal()
this.terminal.setWindowTitle = (title) => {
this.zone.run(() => {
this.title = title
this.titleChange.emit(title)
})
}
this.terminal.onTerminalReady = () => {
this.terminal.installKeyboard()
io = this.terminal.io.push()
const dataSubscription = this.session.dataAvailable.subscribe((data) => {
io.writeUTF8(data)
io.writeUTF16(data)
})
const closedSubscription = this.session.closed.subscribe(() => {
dataSubscription.unsubscribe()
closedSubscription.unsubscribe()
})
io.onVTKeystroke = (str) => {
this.session.write(str)
}
io.sendString = (str) => {
io.onVTKeystroke = io.sendString = (str) => {
this.session.write(str)
}
io.onTerminalResize = (columns, rows) => {
console.log(`Resizing to ${columns}x${rows}`)
this.session.resize(columns, rows)
}
}

View file

@ -22,6 +22,7 @@ export class Session {
this.name = options.name
this.pty = ptyjs.spawn('sh', ['-c', options.command], {
name: 'xterm-color',
//name: 'screen-256color',
cols: 80,
rows: 30,
cwd: options.cwd || process.env.HOME,

View file

@ -15,7 +15,8 @@
},
"compileOnSave": false,
"exclude": [
"node_modules"
"node_modules",
"platforms",
],
"files": [
"app/src/app.d.ts",