diff --git a/app/src/components/app.ts b/app/src/components/app.ts index 8022c3f3..ab8f8aaa 100644 --- a/app/src/components/app.ts +++ b/app/src/components/app.ts @@ -52,6 +52,7 @@ export class AppComponent { toasterConfig: ToasterConfig tabs: Tab[] = [] activeTab: Tab + lastTabIndex = 0 constructor( private modal: ModalService, @@ -78,10 +79,19 @@ export class AppComponent { if (hotkey == 'new-tab') { this.newTab() } - if (hotkey == 'close-tab') { - if (this.activeTab) { + if (this.activeTab) { + if (hotkey == 'close-tab') { this.closeTab(this.activeTab) } + if (hotkey == 'toggle-last-tab') { + this.toggleLastTab() + } + if (hotkey == 'next-tab') { + this.nextTab() + } + if (hotkey == 'previous-tab') { + this.previousTab() + } } }) @@ -118,12 +128,34 @@ export class AppComponent { } selectTab (tab) { + this.lastTabIndex = this.tabs.indexOf(this.activeTab) this.activeTab = tab setImmediate(() => { this.elementRef.nativeElement.querySelector(':scope .tab.active iframe').focus() }) } + toggleLastTab () { + if (!this.lastTabIndex || this.lastTabIndex >= this.tabs.length) { + this.lastTabIndex = 0 + } + this.selectTab(this.tabs[this.lastTabIndex]) + } + + nextTab () { + let tabIndex = this.tabs.indexOf(this.activeTab) + if (tabIndex < this.tabs.length - 1) { + this.selectTab(this.tabs[tabIndex + 1]) + } + } + + previousTab () { + let tabIndex = this.tabs.indexOf(this.activeTab) + if (tabIndex > 0) { + this.selectTab(this.tabs[tabIndex - 1]) + } + } + closeTab (tab) { tab.session.gracefullyDestroy() let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1) diff --git a/app/src/components/hotkeyDisplay.less b/app/src/components/hotkeyDisplay.less index ff8563ac..46aecc74 100644 --- a/app/src/components/hotkeyDisplay.less +++ b/app/src/components/hotkeyDisplay.less @@ -4,11 +4,13 @@ .stroke { display: inline-block; margin: 0 5px; + background: #222; + border-radius: 2px; + box-shadow: 0 1px 0 rgba(0,0,0,.5); + text-shadow: 0 1px 0 rgba(0,0,0,.5); .key-container { display: inline-block; - background: #222; - text-shadow: 0 1px 0 rgba(0,0,0,.5); .key { display: inline-block; diff --git a/app/src/components/hotkeyHint.less b/app/src/components/hotkeyHint.less index 67bdc457..f7ad1c2b 100644 --- a/app/src/components/hotkeyHint.less +++ b/app/src/components/hotkeyHint.less @@ -2,7 +2,6 @@ display: block; .line { - background: #333; padding: 3px 10px; } } diff --git a/app/src/components/hotkeyHint.pug b/app/src/components/hotkeyHint.pug index a7c8908d..a44a9fa5 100644 --- a/app/src/components/hotkeyHint.pug +++ b/app/src/components/hotkeyHint.pug @@ -1,4 +1,4 @@ .body(*ngIf='partialHotkeyMatches?.length > 0') - .line(*ngFor='let match of partialHotkeyMatches; trackBy: match?.id', @animateLine) + .line(*ngFor='let match of partialHotkeyMatches; trackBy: trackByFn', @animateLine) hotkey-display([model]='match.strokes') span {{ hotkeys.getHotkeyDescription(match.id).name }} diff --git a/app/src/components/hotkeyHint.ts b/app/src/components/hotkeyHint.ts index 3e1797f0..4f461d1b 100644 --- a/app/src/components/hotkeyHint.ts +++ b/app/src/components/hotkeyHint.ts @@ -1,4 +1,4 @@ -import { Component, ChangeDetectionStrategy, trigger, style, animate, transition, state } from '@angular/core' +import { Component, ChangeDetectionStrategy, Input, trigger, style, animate, transition, state } from '@angular/core' import { HotkeysService, PartialHotkeyMatch } from 'services/hotkeys' @@ -32,28 +32,39 @@ import { HotkeysService, PartialHotkeyMatch } from 'services/hotkeys' ] }) export class HotkeyHintComponent { - partialHotkeyMatches: PartialHotkeyMatch[] + @Input() partialHotkeyMatches: PartialHotkeyMatch[] private keyTimeoutInterval: NodeJS.Timer = null constructor ( public hotkeys: HotkeysService, ) { this.hotkeys.key.subscribe(() => { + //console.log('Keystrokes', this.hotkeys.getCurrentKeystrokes()) let partialMatches = this.hotkeys.getCurrentPartiallyMatchedHotkeys() if (partialMatches.length > 0) { - console.log('Partial matches:', partialMatches) - this.partialHotkeyMatches = partialMatches + //console.log('Partial matches:', partialMatches) + this.setMatches(partialMatches) if (this.keyTimeoutInterval == null) { this.keyTimeoutInterval = setInterval(() => { if (this.hotkeys.getCurrentPartiallyMatchedHotkeys().length == 0) { clearInterval(this.keyTimeoutInterval) this.keyTimeoutInterval = null - this.partialHotkeyMatches = null + this.setMatches(null) } }, 500) } + } else { + this.setMatches(null) } }) } + + setMatches (matches: PartialHotkeyMatch[]) { + this.partialHotkeyMatches = matches + } + + trackByFn (_, item) { + return item && item.id + } } diff --git a/app/src/services/hotkeys.ts b/app/src/services/hotkeys.ts index 7034c46d..1bd56d9c 100644 --- a/app/src/services/hotkeys.ts +++ b/app/src/services/hotkeys.ts @@ -28,6 +28,21 @@ const HOTKEYS: HotkeyDescription[] = [ name: 'Close tab', defaults: [['Ctrl+Shift+W'], ['Ctrl+A', 'K']], }, + { + id: 'toggle-last-tab', + name: 'Toggle last tab', + defaults: [['Ctrl+A', 'A'], ['Ctrl+A', 'Ctrl+A']], + }, + { + id: 'next-tab', + name: 'Next tab', + defaults: [['Ctrl+Shift-ArrowRight'], ['Ctrl+A', 'N']], + }, + { + id: 'previous-tab', + name: 'Previous tab', + defaults: [['Ctrl+Shift-ArrowLeft'], ['Ctrl+A', 'P']], + }, ] @@ -79,7 +94,7 @@ export class HotkeysService { emitNativeEvent (name, nativeEvent) { nativeEvent.event = name - console.log(nativeEvent) + //console.log(nativeEvent) this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() }) this.zone.run(() => { @@ -144,7 +159,7 @@ export class HotkeysService { let currentStrokes = this.getCurrentKeystrokes() for (let matchLength = Math.min(currentStrokes.length, sequence.length); matchLength > 0; matchLength--) { - console.log(sequence, currentStrokes.slice(currentStrokes.length - sequence.length)) + //console.log(sequence, currentStrokes.slice(currentStrokes.length - sequence.length)) if (sequence.slice(0, matchLength).every((x, index) => { return x.toLowerCase() == currentStrokes[currentStrokes.length - matchLength + index].toLowerCase() })) { diff --git a/app/src/services/hotkeys.util.ts b/app/src/services/hotkeys.util.ts index 5134cc02..9ec1cf18 100644 --- a/app/src/services/hotkeys.util.ts +++ b/app/src/services/hotkeys.util.ts @@ -46,6 +46,11 @@ export function stringifyKeySequence(events: NativeKeyEvent[]): string[] { if (lastEvent.shiftKey) { itemKeys.push('Shift') } + + if (['Control', 'Shift', 'Alt', 'Command'].includes(lastEvent.key)) { + // TODO make this optional? + continue + } itemKeys.push(lastEvent.key) items.push(itemKeys.join('+')) }