diff --git a/app/src/overrides.scss b/app/src/overrides.scss index 610ba49c..e69de29b 100644 --- a/app/src/overrides.scss +++ b/app/src/overrides.scss @@ -1,9 +0,0 @@ -ngb-tabset.vertical { - display: flex; - - > .nav { - display: flex; - flex-direction: column; - flex: none; - } -} diff --git a/app/src/services/hotkeys.ts b/app/src/services/hotkeys.ts index a3060678..d536326e 100644 --- a/app/src/services/hotkeys.ts +++ b/app/src/services/hotkeys.ts @@ -3,7 +3,6 @@ import { ElectronService } from 'services/electron' import { ConfigService } from 'services/config' import { NativeKeyEvent, stringifyKeySequence } from './hotkeys.util' import { IHotkeyDescription, HotkeyProvider } from 'api/hotkeyProvider' -const hterm = require('hterm-commonjs') export interface PartialHotkeyMatch { @@ -34,39 +33,25 @@ export class HotkeysService { private config: ConfigService, @Inject(HotkeyProvider) hotkeyProviders: HotkeyProvider[], ) { - let events = [ - { - name: 'keydown', - htermHandler: 'onKeyDown_', - }, - { - name: 'keyup', - htermHandler: 'onKeyUp_', - }, - ] + let events = ['keydown', 'keyup'] events.forEach((event) => { - document.addEventListener(event.name, (nativeEvent) => { + document.addEventListener(event, (nativeEvent) => { if (document.querySelectorAll(':focus').length == 0) { - this.emitNativeEvent(event.name, nativeEvent) + this.pushKeystroke(event, nativeEvent) + this.processKeystrokes() + this.emitKeyEvent(nativeEvent) } }) - - let oldHandler = hterm.hterm.Keyboard.prototype[event.htermHandler] - const __this = this - hterm.hterm.Keyboard.prototype[event.htermHandler] = function (nativeEvent) { - __this.emitNativeEvent(event.name, nativeEvent) - oldHandler.bind(this)(nativeEvent) - } }) this.hotkeyDescriptions = hotkeyProviders.map(x => x.hotkeys).reduce((a, b) => a.concat(b)) } - emitNativeEvent (name, nativeEvent) { + pushKeystroke (name, nativeEvent) { nativeEvent.event = name - - //console.log(nativeEvent) this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() }) + } + processKeystrokes () { this.zone.run(() => { if (this.isEnabled()) { let matched = this.getCurrentFullyMatchedHotkey() @@ -76,6 +61,11 @@ export class HotkeysService { this.clearCurrentKeystrokes() } } + }) + } + + emitKeyEvent (nativeEvent) { + this.zone.run(() => { this.key.emit(nativeEvent) }) } diff --git a/app/src/services/hotkeys.util.ts b/app/src/services/hotkeys.util.ts index 2c958d36..dd74fba3 100644 --- a/app/src/services/hotkeys.util.ts +++ b/app/src/services/hotkeys.util.ts @@ -27,34 +27,32 @@ export interface NativeKeyEvent { export function stringifyKeySequence(events: NativeKeyEvent[]): string[] { let items: string[] = [] - let lastEvent: NativeKeyEvent events = events.slice() while (events.length > 0) { let event = events.shift() - if (event.event == 'keyup' && (lastEvent && lastEvent.event == 'keydown')) { + if (event.event == 'keydown') { let itemKeys: string[] = [] - if (lastEvent.ctrlKey) { + if (event.ctrlKey) { itemKeys.push('Ctrl') } - if (lastEvent.metaKey) { + if (event.metaKey) { itemKeys.push(metaKeyName) } - if (lastEvent.altKey) { + if (event.altKey) { itemKeys.push(altKeyName) } - if (lastEvent.shiftKey) { + if (event.shiftKey) { itemKeys.push('Shift') } - if (['Control', 'Shift', 'Alt', 'Command'].includes(lastEvent.key)) { + if (['Control', 'Shift', 'Alt', 'Command'].includes(event.key)) { // TODO make this optional? continue } - itemKeys.push(lastEvent.key) + itemKeys.push(event.key) items.push(itemKeys.join('-')) } - lastEvent = event } return items } diff --git a/app/src/settings/components/multiHotkeyInput.pug b/app/src/settings/components/multiHotkeyInput.pug index 5e848e3a..9d4af73c 100644 --- a/app/src/settings/components/multiHotkeyInput.pug +++ b/app/src/settings/components/multiHotkeyInput.pug @@ -3,4 +3,4 @@ .stroke(*ngFor='let stroke of item') {{stroke}} .remove((click)='removeItem(item)') × -.add((click)='addItem()') Add +.add((click)='addItem()') Add... diff --git a/app/src/settings/components/multiHotkeyInput.scss b/app/src/settings/components/multiHotkeyInput.scss index d38dc84a..8923c351 100644 --- a/app/src/settings/components/multiHotkeyInput.scss +++ b/app/src/settings/components/multiHotkeyInput.scss @@ -5,8 +5,6 @@ .item { display: flex; flex: none; - padding: 3px 0; - margin-right: 5px; .body { flex: none; @@ -14,7 +12,6 @@ .stroke { flex: none; - padding: 0 3px; } } diff --git a/app/src/settings/components/settingsPane.deep.css b/app/src/settings/components/settingsPane.deep.css index ecab3379..0dd03dfe 100644 --- a/app/src/settings/components/settingsPane.deep.css +++ b/app/src/settings/components/settingsPane.deep.css @@ -1,5 +1,12 @@ :host /deep/ ngb-tabset { flex: auto; + display: flex; +} + +:host /deep/ ngb-tabset > .nav { + display: flex; + flex-direction: column; + flex: none; } :host /deep/ ngb-tabset > .tab-content { diff --git a/app/src/settings/components/settingsPane.pug b/app/src/settings/components/settingsPane.pug index 90717bef..14c8adf4 100644 --- a/app/src/settings/components/settingsPane.pug +++ b/app/src/settings/components/settingsPane.pug @@ -25,7 +25,7 @@ ngb-tabset.vertical(type='tabs') type='radio', [value]='true' ) - | On top + | On the top label.btn.btn-secondary input( type='radio', diff --git a/app/src/terminal/index.ts b/app/src/terminal/index.ts index e5f24772..d9eff9bd 100644 --- a/app/src/terminal/index.ts +++ b/app/src/terminal/index.ts @@ -3,7 +3,8 @@ import { BrowserModule } from '@angular/platform-browser' import { FormsModule } from '@angular/forms' import { NgbModule } from '@ng-bootstrap/ng-bootstrap' -import { ToolbarButtonProvider, TabRecoveryProvider, ConfigProvider } from 'api' +import { ToolbarButtonProvider, TabRecoveryProvider, ConfigProvider, HotkeysService } from 'api' + import { SettingsTabProvider } from '../settings/api' import { TerminalTabComponent } from './components/terminalTab' @@ -15,6 +16,8 @@ import { RecoveryProvider } from './recoveryProvider' import { SessionPersistenceProvider } from './api' import { TerminalSettingsProvider } from './settings' import { TerminalConfigProvider } from './config' +import { hterm } from './hterm' + @NgModule({ imports: [ @@ -40,6 +43,32 @@ import { TerminalConfigProvider } from './config' ], }) class TerminalModule { + constructor (hotkeys: HotkeysService) { + let events = [ + { + name: 'keydown', + htermHandler: 'onKeyDown_', + }, + { + name: 'keyup', + htermHandler: 'onKeyUp_', + }, + ] + events.forEach((event) => { + let oldHandler = hterm.hterm.Keyboard.prototype[event.htermHandler] + hterm.hterm.Keyboard.prototype[event.htermHandler] = function (nativeEvent) { + hotkeys.pushKeystroke(event.name, nativeEvent) + if (hotkeys.getCurrentPartiallyMatchedHotkeys().length == 0) { + oldHandler.bind(this)(nativeEvent) + } else { + nativeEvent.stopPropagation() + nativeEvent.preventDefault() + } + hotkeys.processKeystrokes() + hotkeys.emitKeyEvent(nativeEvent) + } + }) + } } diff --git a/app/src/theme.scss b/app/src/theme.scss index dc2aee25..95eddb02 100644 --- a/app/src/theme.scss +++ b/app/src/theme.scss @@ -12,6 +12,8 @@ $purple: #613d7c !default; $body-bg: #1D272D; $body-bg2: #131d27; +$body-bg3: #20333e; + $body-color: #aaa; $font-family-sans-serif: "Source Sans Pro"; $font-size-base: 14rem / 16; @@ -27,9 +29,9 @@ $nav-tabs-border-color: $body-bg2; $nav-tabs-border-width: 1px; $nav-tabs-border-radius: 0; $nav-tabs-link-hover-border-color: $body-bg2; -$nav-tabs-active-link-hover-color: $body-color; -$nav-tabs-active-link-hover-bg: #424f56; -$nav-tabs-active-link-hover-border-color: $body-bg2; +$nav-tabs-active-link-hover-color: $white; +$nav-tabs-active-link-hover-bg: $blue; +$nav-tabs-active-link-hover-border-color: darken($blue, 30%); $input-bg: #111; $input-bg-disabled: #333; @@ -182,3 +184,57 @@ app-root .content { tab-body { background: $body-bg; } + +settings-pane > ngb-tabset { + border-right: 1px solid $body-bg2; + + & > .nav { + background: $body-bg3; + + & > .nav-item > .nav-link { + border-left: none; + border-right: none; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + padding: 10px 50px 10px 20px; + font-size: 14px; + + &.active { + border-top-color: $nav-tabs-active-link-hover-border-color; + border-bottom-color: $nav-tabs-active-link-hover-border-color; + } + } + } +} + +multi-hotkey-input { + .item { + background: $body-bg3; + border: 1px solid $blue; + border-radius: 3px; + margin-right: 5px; + + .body { + padding: 3px 0 2px; + + .stroke { + padding: 0 6px; + border-right: 1px solid $body-bg; + } + } + + .remove { + padding: 3px 8px 2px; + } + } + + .add { + color: #777; + padding: 4px 10px 0; + } + + .add, .item .body, .item .remove { + &:hover { background: darken($body-bg3, 5%); } + &:active { background: darken($body-bg3, 15%); } + } +}