From c7828e55f29351e90a4c0f217e90c607c0783a08 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Fri, 28 Apr 2017 21:37:39 +0200 Subject: [PATCH 1/2] . --- .../src/components/appRoot.component.pug | 54 ++++++++++--------- .../src/components/appRoot.component.scss | 9 +++- terminus-core/src/theme.scss | 20 ++++++- webpack.config.js | 2 +- 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/terminus-core/src/components/appRoot.component.pug b/terminus-core/src/components/appRoot.component.pug index b12dabe4..587c375d 100644 --- a/terminus-core/src/components/appRoot.component.pug +++ b/terminus-core/src/components/appRoot.component.pug @@ -16,37 +16,39 @@ title-bar(*ngIf='config.store.appearance.frame == "full" && config.store.appeara (closeClicked)='app.closeTab(tab)', ) - button.btn.btn-secondary( - *ngFor='let button of getLeftToolbarButtons()', - [title]='button.title', - (click)='button.click()', - ) - i.fa([class]='"fa fa-" + button.icon') + .btn-group + button.btn.btn-secondary.btn-tab-bar( + *ngFor='let button of getLeftToolbarButtons()', + [title]='button.title', + (click)='button.click()', + ) + i.fa([class]='"fa fa-" + button.icon') .drag-space + + .btn-group + button.btn.btn-secondary.btn-tab-bar( + *ngFor='let button of getRightToolbarButtons()', + [title]='button.title', + (click)='button.click()', + ) + i.fa([class]='"fa fa-" + button.icon') - button.btn.btn-secondary( - *ngFor='let button of getRightToolbarButtons()', - [title]='button.title', - (click)='button.click()', - ) - i.fa([class]='"fa fa-" + button.icon') - - button.btn.btn-secondary.btn-minimize( + .btn-group.window-controls( *ngIf='config.store.appearance.frame == "thin"', - (click)='hostApp.minimize()', ) - i.fa.fa-window-minimize - button.btn.btn-secondary.btn-maximize( - *ngIf='config.store.appearance.frame == "thin"', - (click)='hostApp.toggleMaximize()', - ) - i.fa.fa-window-maximize - button.btn.btn-secondary.btn-close( - *ngIf='config.store.appearance.frame == "thin"', - (click)='hostApp.quit()', - ) - i.fa.fa-close + button.btn.btn-secondary.btn-minimize.btn-tab-bar( + (click)='hostApp.minimize()', + ) + i.fa.fa-window-minimize + button.btn.btn-secondary.btn-maximize.btn-tab-bar( + (click)='hostApp.toggleMaximize()', + ) + i.fa.fa-window-maximize + button.btn.btn-secondary.btn-close.btn-tab-bar( + (click)='hostApp.quit()', + ) + i.fa.fa-close start-page(*ngIf='app.tabs.length == 0') diff --git a/terminus-core/src/components/appRoot.component.scss b/terminus-core/src/components/appRoot.component.scss index 40bc2d33..7ce9492f 100644 --- a/terminus-core/src/components/appRoot.component.scss +++ b/terminus-core/src/components/appRoot.component.scss @@ -5,6 +5,7 @@ flex-direction: column; overflow: hidden; -webkit-user-select: none; + -webkit-user-drag: none; -webkit-font-smoothing: antialiased; cursor: default; animation: 0.5s ease-out fadeIn; @@ -29,7 +30,7 @@ $tab-border-radius: 4px; height: $tabs-height; display: flex; - &>button { + .btn-tab-bar { line-height: $tabs-height + 2px; cursor: pointer; @@ -48,7 +49,7 @@ $tab-border-radius: 4px; &.btn-minimize { margin-left: 10px; } - + &.btn-minimize, &.btn-maximize { font-size: 8px; } @@ -69,6 +70,10 @@ $tab-border-radius: 4px; flex: 1 0 25%; -webkit-app-region: drag; } + + &.window-controls { + flex: 0 0 none; + } } .tabs-content { diff --git a/terminus-core/src/theme.scss b/terminus-core/src/theme.scss index 9724fd00..04535ae1 100644 --- a/terminus-core/src/theme.scss +++ b/terminus-core/src/theme.scss @@ -82,13 +82,14 @@ title-bar { } } +$border-color: #141414; app-root { &> .content { background: $body-bg2; .tab-bar { - &>button { + .btn-tab-bar { &:not(:hover):not(:active) { background: $body-bg2; } @@ -105,6 +106,9 @@ app-root { tab-header { background: $body-bg2; + border-left: 1px solid transparent; + border-right: 1px solid transparent; + margin-bottom: -1px; .index { color: #555; @@ -121,6 +125,8 @@ app-root { &.active { background: $body-bg; + border-left: 1px solid $border-color; + border-right: 1px solid $border-color; } } } @@ -129,15 +135,21 @@ app-root { &.tabs-on-top .tab-bar { tab-header { border-top: 1px solid transparent; + border-bottom: 1px solid $border-color; &.active { border-top: 1px solid $teal; + border-bottom: 1px solid transparent; } &.has-activity:not(.active) { border-top: 1px solid $green; } } + + &>.btn-group, .drag-space { + border-bottom: 1px solid $border-color; + } } &:not(.tabs-on-top) .tab-bar { @@ -145,15 +157,21 @@ app-root { tab-header { border-bottom: 1px solid transparent; + border-top: 1px solid $border-color; &.active { border-bottom: 1px solid $teal; + border-top: 1px solid transparent; } &.has-activity:not(.active) { border-bottom: 1px solid $green; } } + + &>.btn-group, .drag-space { + border-top: 1px solid $border-color; + } } } } diff --git a/webpack.config.js b/webpack.config.js index d566f6aa..3c98e18a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -5,6 +5,6 @@ module.exports = [ require('./terminus-terminal/webpack.config.js'), require('./terminus-clickable-links/webpack.config.js'), require('./terminus-community-color-schemes/webpack.config.js'), - require('./terminus-plugin-manager/webpack.config.js'), + //require('./terminus-plugin-manager/webpack.config.js'), require('./terminus-theme-hype/webpack.config.js'), ] From 94d8886d5a9d147d17b7cd65a2191ab7a9df3ec6 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Fri, 28 Apr 2017 22:40:58 +0200 Subject: [PATCH 2/2] . --- app/index.pug | 2 +- app/src/entry.ts | 2 +- app/src/plugins.ts | 9 ++-- .../src/components/appRoot.component.pug | 14 ++++-- .../src/components/appRoot.component.scss | 6 ++- .../src/components/appRoot.component.ts | 3 +- .../src/components/tabHeader.component.scss | 4 ++ .../src/components/titleBar.component.scss | 2 +- .../src/components/titleBar.component.ts | 8 +--- terminus-core/src/configDefaults.yaml | 10 ++--- terminus-core/src/theme.scss | 19 +++----- .../src/components/settingsTab.component.pug | 6 +-- terminus-terminal/src/api.ts | 3 +- terminus-terminal/src/persistenceProviders.ts | 45 ++++++++++++------- .../src/services/sessions.service.ts | 8 +++- 15 files changed, 82 insertions(+), 59 deletions(-) diff --git a/app/index.pug b/app/index.pug index 9913d713..445e857e 100644 --- a/app/index.pug +++ b/app/index.pug @@ -29,6 +29,6 @@ html div h1.terminus-title Terminus .progress - .bar(style='width: 50%') + .bar(style='width: 0%') diff --git a/app/src/entry.ts b/app/src/entry.ts index b633d484..3ba065b1 100644 --- a/app/src/entry.ts +++ b/app/src/entry.ts @@ -21,7 +21,7 @@ if ((global).require('electron-is-dev')) { } findPlugins().then(async plugins => { - let pluginsModules = loadPlugins(plugins, (current, total) => { + let pluginsModules = await loadPlugins(plugins, (current, total) => { (document.querySelector('.progress .bar')).style.width = 100 * current / total + '%' }) let module = await getRootModule(pluginsModules) diff --git a/app/src/plugins.ts b/app/src/plugins.ts index c0ff98ff..d95e716b 100644 --- a/app/src/plugins.ts +++ b/app/src/plugins.ts @@ -56,10 +56,11 @@ export async function findPlugins (): Promise { return foundPlugins } -export function loadPlugins (foundPlugins: IPluginEntry[], progress: ProgressCallback): any[] { +export async function loadPlugins (foundPlugins: IPluginEntry[], progress: ProgressCallback): Promise { let plugins: any[] = [] progress(0, 1) - foundPlugins.forEach((foundPlugin, index) => { + let index = 0 + for (let foundPlugin of foundPlugins) { console.info(`Loading ${foundPlugin.name}: ${(global).require.resolve(foundPlugin.path)}`) progress(index, foundPlugins.length) try { @@ -68,7 +69,9 @@ export function loadPlugins (foundPlugins: IPluginEntry[], progress: ProgressCal } catch (error) { console.error(`Could not load ${foundPlugin.name}:`, error) } - }) + await delay(1) + index++ + } progress(1, 1) return plugins } diff --git a/terminus-core/src/components/appRoot.component.pug b/terminus-core/src/components/appRoot.component.pug index 587c375d..553767a1 100644 --- a/terminus-core/src/components/appRoot.component.pug +++ b/terminus-core/src/components/appRoot.component.pug @@ -1,9 +1,14 @@ -title-bar(*ngIf='config.store.appearance.frame == "full" && config.store.appearance.dock == "off"') +title-bar( + *ngIf='config.store.appearance.frame == "full" && config.store.appearance.dock == "off"', + [class.inset]='hostApp.platform == Platform.macOS' +) .content( - [class.tabs-on-top]='config.store.appearance.tabsOnTop' + [class.tabs-on-top]='config.store.appearance.tabsLocation == "top"' ) - .tab-bar + .tab-bar( + [class.inset]='hostApp.platform == Platform.macOS && config.store.appearance.frame == "thin" && config.store.appearance.tabsLocation == "top"' + ) .tabs tab-header( *ngFor='let tab of app.tabs; let idx = index', @@ -11,6 +16,7 @@ title-bar(*ngIf='config.store.appearance.frame == "full" && config.store.appeara [tab]='tab', [active]='tab == app.activeTab', [hasActivity]='tab.hasActivity', + [class.drag-region]='hostApp.platform == Platform.macOS', @animateTab, (click)='app.selectTab(tab)', (closeClicked)='app.closeTab(tab)', @@ -35,7 +41,7 @@ title-bar(*ngIf='config.store.appearance.frame == "full" && config.store.appeara i.fa([class]='"fa fa-" + button.icon') .btn-group.window-controls( - *ngIf='config.store.appearance.frame == "thin"', + *ngIf='config.store.appearance.frame == "thin" && (hostApp.platform == Platform.Windows || hostApp.platform == Platform.Linux)', ) button.btn.btn-secondary.btn-minimize.btn-tab-bar( (click)='hostApp.minimize()', diff --git a/terminus-core/src/components/appRoot.component.scss b/terminus-core/src/components/appRoot.component.scss index 7ce9492f..4bb951ff 100644 --- a/terminus-core/src/components/appRoot.component.scss +++ b/terminus-core/src/components/appRoot.component.scss @@ -71,9 +71,13 @@ $tab-border-radius: 4px; -webkit-app-region: drag; } - &.window-controls { + .window-controls { flex: 0 0 none; } + + &.inset { + padding-left: 85px; + } } .tabs-content { diff --git a/terminus-core/src/components/appRoot.component.ts b/terminus-core/src/components/appRoot.component.ts index 6e10c77c..3f59711d 100644 --- a/terminus-core/src/components/appRoot.component.ts +++ b/terminus-core/src/components/appRoot.component.ts @@ -3,7 +3,7 @@ import { trigger, style, animate, transition, state } from '@angular/animations' import { ToasterConfig } from 'angular2-toaster' import { ElectronService } from '../services/electron.service' -import { HostAppService } from '../services/hostApp.service' +import { HostAppService, Platform } from '../services/hostApp.service' import { HotkeysService } from '../services/hotkeys.service' import { Logger, LogService } from '../services/log.service' import { QuitterService } from '../services/quitter.service' @@ -43,6 +43,7 @@ import { AppService, IToolbarButton, ToolbarButtonProvider } from '../api' }) export class AppRootComponent { toasterConfig: ToasterConfig + Platform = Platform private logger: Logger constructor( diff --git a/terminus-core/src/components/tabHeader.component.scss b/terminus-core/src/components/tabHeader.component.scss index 1728795d..b33d3f7f 100644 --- a/terminus-core/src/components/tabHeader.component.scss +++ b/terminus-core/src/components/tabHeader.component.scss @@ -61,4 +61,8 @@ $tabs-height: 40px; display: block; opacity: 1; } + + &.drag-region { + -webkit-app-region: drag; + } } diff --git a/terminus-core/src/components/titleBar.component.scss b/terminus-core/src/components/titleBar.component.scss index ef3ac7ac..e9dd1153 100644 --- a/terminus-core/src/components/titleBar.component.scss +++ b/terminus-core/src/components/titleBar.component.scss @@ -31,7 +31,7 @@ $titlebar-height: 30px; font-size: 12px; } - &.inset-titlebar { + &.inset { flex-basis: 36px; .title { diff --git a/terminus-core/src/components/titleBar.component.ts b/terminus-core/src/components/titleBar.component.ts index 3bb32706..aefa88b5 100644 --- a/terminus-core/src/components/titleBar.component.ts +++ b/terminus-core/src/components/titleBar.component.ts @@ -1,5 +1,4 @@ -import { Component, HostBinding } from '@angular/core' -import { HostAppService, Platform } from '../services/hostApp.service' +import { Component } from '@angular/core' @Component({ selector: 'title-bar', @@ -7,9 +6,4 @@ import { HostAppService, Platform } from '../services/hostApp.service' styles: [require('./titleBar.component.scss')], }) export class TitleBarComponent { - @HostBinding('class.inset-titlebar') insetTitlebar = false - - constructor (public hostApp: HostAppService) { - this.insetTitlebar = hostApp.platform == Platform.macOS - } } diff --git a/terminus-core/src/configDefaults.yaml b/terminus-core/src/configDefaults.yaml index bad01a1f..408946a5 100644 --- a/terminus-core/src/configDefaults.yaml +++ b/terminus-core/src/configDefaults.yaml @@ -1,7 +1,7 @@ appearance: - dock: 'off' - dockScreen: 'current' + dock: off + dockScreen: current dockFill: 50 - tabsOnTop: true - theme: 'Standard' - frame: 'thin' + tabsLocation: top + theme: Standard + frame: thin diff --git a/terminus-core/src/theme.scss b/terminus-core/src/theme.scss index 04535ae1..6cd41162 100644 --- a/terminus-core/src/theme.scss +++ b/terminus-core/src/theme.scss @@ -108,7 +108,6 @@ app-root { background: $body-bg2; border-left: 1px solid transparent; border-right: 1px solid transparent; - margin-bottom: -1px; .index { color: #555; @@ -133,45 +132,37 @@ app-root { } &.tabs-on-top .tab-bar { + border-bottom: 1px solid $border-color; + tab-header { border-top: 1px solid transparent; - border-bottom: 1px solid $border-color; &.active { border-top: 1px solid $teal; - border-bottom: 1px solid transparent; + margin-bottom: -1px; } &.has-activity:not(.active) { border-top: 1px solid $green; } } - - &>.btn-group, .drag-space { - border-bottom: 1px solid $border-color; - } } &:not(.tabs-on-top) .tab-bar { - margin-bottom: 3px; + border-top: 1px solid $border-color; tab-header { border-bottom: 1px solid transparent; - border-top: 1px solid $border-color; &.active { border-bottom: 1px solid $teal; - border-top: 1px solid transparent; + margin-top: -1px; } &.has-activity:not(.active) { border-bottom: 1px solid $green; } } - - &>.btn-group, .drag-space { - border-top: 1px solid $border-color; - } } } } diff --git a/terminus-settings/src/components/settingsTab.component.pug b/terminus-settings/src/components/settingsTab.component.pug index acc5d22a..32c3fe3f 100644 --- a/terminus-settings/src/components/settingsTab.component.pug +++ b/terminus-settings/src/components/settingsTab.component.pug @@ -19,20 +19,20 @@ ngb-tabset.vertical(type='tabs') label Show tabs br div( - '[(ngModel)]'='config.store.appearance.tabsOnTop', + '[(ngModel)]'='config.store.appearance.tabsLocation', (ngModelChange)='config.save()', ngbRadioGroup ) label.btn.btn-secondary input( type='radio', - [value]='true' + [value]='"top"' ) | On the top label.btn.btn-secondary input( type='radio', - [value]='false' + [value]='"bottom"' ) | At the bottom .col.col-lg-6 diff --git a/terminus-terminal/src/api.ts b/terminus-terminal/src/api.ts index c6af1cfe..5e3d5f09 100644 --- a/terminus-terminal/src/api.ts +++ b/terminus-terminal/src/api.ts @@ -1,3 +1,4 @@ +import { Observable } from 'rxjs' import { TerminalTabComponent } from './components/terminalTab.component' export { TerminalTabComponent } @@ -18,7 +19,7 @@ export interface SessionOptions { cwd?: string env?: any recoveryId?: string - recoveredTruePID?: number + recoveredTruePID$?: Observable } export abstract class SessionPersistenceProvider { diff --git a/terminus-terminal/src/persistenceProviders.ts b/terminus-terminal/src/persistenceProviders.ts index d7ddef50..32a8e880 100644 --- a/terminus-terminal/src/persistenceProviders.ts +++ b/terminus-terminal/src/persistenceProviders.ts @@ -1,6 +1,8 @@ import * as fs from 'fs-promise' import { exec, spawn } from 'mz/child_process' +import { exec as execCallback } from 'child_process' +import { AsyncSubject } from 'rxjs' import { Injectable } from '@angular/core' import { Logger, LogService } from 'terminus-core' import { SessionOptions, SessionPersistenceProvider } from './api' @@ -36,12 +38,12 @@ export class ScreenPersistenceProvider extends SessionPersistenceProvider { } async attachSession (recoveryId: any): Promise { - let lines: string[] - try { - lines = (await exec('screen -list'))[0].toString().split('\n') - } catch (result) { - lines = result.stdout.split('\n') - } + let lines = await new Promise(resolve => { + execCallback('screen -list', (_err, stdout) => { + // returns an error code on macOS + resolve(stdout.split('\n')) + }) + }) let screenPID = lines .filter(line => line.indexOf('.' + recoveryId) !== -1) .map(line => parseInt(line.trim().split('.')[0]))[0] @@ -50,25 +52,36 @@ export class ScreenPersistenceProvider extends SessionPersistenceProvider { return null } - let child = (await listProcesses()).find(x => x.ppid === screenPID) + let truePID_ = new AsyncSubject() - if (!child) { - this.logger.error(`Could not find any children of the screen process (PID ${screenPID})!`) - } - if (child.command == 'login') { - child = (await listProcesses()).find(x => x.ppid === child.pid) - } - - let recoveredTruePID = child.pid + this.extractShellPID(screenPID).then(pid => { + truePID_.next(pid) + truePID_.complete() + }) return { recoveryId, - recoveredTruePID, + recoveredTruePID$: truePID_.asObservable(), command: 'screen', args: ['-r', recoveryId], } } + async extractShellPID (screenPID: number): Promise { + let child = (await listProcesses()).find(x => x.ppid === screenPID) + + if (!child) { + throw new Error(`Could not find any children of the screen process (PID ${screenPID})!`) + } + + if (child.command == 'login') { + await delay(1000) + child = (await listProcesses()).find(x => x.ppid === child.pid) + } + + return child.pid + } + async startSession (options: SessionOptions): Promise { let configPath = '/tmp/.termScreenConfig' await fs.writeFile(configPath, ` diff --git a/terminus-terminal/src/services/sessions.service.ts b/terminus-terminal/src/services/sessions.service.ts index 3aadd5fa..b2f4431b 100644 --- a/terminus-terminal/src/services/sessions.service.ts +++ b/terminus-terminal/src/services/sessions.service.ts @@ -43,7 +43,13 @@ export class Session { env: env, }) - this.truePID = options.recoveredTruePID || (this.pty).pid + if (options.recoveredTruePID$) { + options.recoveredTruePID$.subscribe(pid => { + this.truePID = pid + }) + } else { + this.truePID = (this.pty).pid + } this.open = true