mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-28 21:24:38 +00:00
.
This commit is contained in:
@@ -52,6 +52,7 @@ export class AppComponent {
|
|||||||
toasterConfig: ToasterConfig
|
toasterConfig: ToasterConfig
|
||||||
tabs: Tab[] = []
|
tabs: Tab[] = []
|
||||||
activeTab: Tab
|
activeTab: Tab
|
||||||
|
lastTabIndex = 0
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private modal: ModalService,
|
private modal: ModalService,
|
||||||
@@ -78,10 +79,19 @@ export class AppComponent {
|
|||||||
if (hotkey == 'new-tab') {
|
if (hotkey == 'new-tab') {
|
||||||
this.newTab()
|
this.newTab()
|
||||||
}
|
}
|
||||||
if (hotkey == 'close-tab') {
|
if (this.activeTab) {
|
||||||
if (this.activeTab) {
|
if (hotkey == 'close-tab') {
|
||||||
this.closeTab(this.activeTab)
|
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) {
|
selectTab (tab) {
|
||||||
|
this.lastTabIndex = this.tabs.indexOf(this.activeTab)
|
||||||
this.activeTab = tab
|
this.activeTab = tab
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this.elementRef.nativeElement.querySelector(':scope .tab.active iframe').focus()
|
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) {
|
closeTab (tab) {
|
||||||
tab.session.gracefullyDestroy()
|
tab.session.gracefullyDestroy()
|
||||||
let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
|
let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
|
||||||
|
@@ -4,11 +4,13 @@
|
|||||||
.stroke {
|
.stroke {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0 5px;
|
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 {
|
.key-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background: #222;
|
|
||||||
text-shadow: 0 1px 0 rgba(0,0,0,.5);
|
|
||||||
|
|
||||||
.key {
|
.key {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
.line {
|
.line {
|
||||||
background: #333;
|
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
.body(*ngIf='partialHotkeyMatches?.length > 0')
|
.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')
|
hotkey-display([model]='match.strokes')
|
||||||
span {{ hotkeys.getHotkeyDescription(match.id).name }}
|
span {{ hotkeys.getHotkeyDescription(match.id).name }}
|
||||||
|
@@ -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'
|
import { HotkeysService, PartialHotkeyMatch } from 'services/hotkeys'
|
||||||
|
|
||||||
|
|
||||||
@@ -32,28 +32,39 @@ import { HotkeysService, PartialHotkeyMatch } from 'services/hotkeys'
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class HotkeyHintComponent {
|
export class HotkeyHintComponent {
|
||||||
partialHotkeyMatches: PartialHotkeyMatch[]
|
@Input() partialHotkeyMatches: PartialHotkeyMatch[]
|
||||||
private keyTimeoutInterval: NodeJS.Timer = null
|
private keyTimeoutInterval: NodeJS.Timer = null
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
public hotkeys: HotkeysService,
|
public hotkeys: HotkeysService,
|
||||||
) {
|
) {
|
||||||
this.hotkeys.key.subscribe(() => {
|
this.hotkeys.key.subscribe(() => {
|
||||||
|
//console.log('Keystrokes', this.hotkeys.getCurrentKeystrokes())
|
||||||
let partialMatches = this.hotkeys.getCurrentPartiallyMatchedHotkeys()
|
let partialMatches = this.hotkeys.getCurrentPartiallyMatchedHotkeys()
|
||||||
if (partialMatches.length > 0) {
|
if (partialMatches.length > 0) {
|
||||||
console.log('Partial matches:', partialMatches)
|
//console.log('Partial matches:', partialMatches)
|
||||||
this.partialHotkeyMatches = partialMatches
|
this.setMatches(partialMatches)
|
||||||
|
|
||||||
if (this.keyTimeoutInterval == null) {
|
if (this.keyTimeoutInterval == null) {
|
||||||
this.keyTimeoutInterval = setInterval(() => {
|
this.keyTimeoutInterval = setInterval(() => {
|
||||||
if (this.hotkeys.getCurrentPartiallyMatchedHotkeys().length == 0) {
|
if (this.hotkeys.getCurrentPartiallyMatchedHotkeys().length == 0) {
|
||||||
clearInterval(this.keyTimeoutInterval)
|
clearInterval(this.keyTimeoutInterval)
|
||||||
this.keyTimeoutInterval = null
|
this.keyTimeoutInterval = null
|
||||||
this.partialHotkeyMatches = null
|
this.setMatches(null)
|
||||||
}
|
}
|
||||||
}, 500)
|
}, 500)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this.setMatches(null)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setMatches (matches: PartialHotkeyMatch[]) {
|
||||||
|
this.partialHotkeyMatches = matches
|
||||||
|
}
|
||||||
|
|
||||||
|
trackByFn (_, item) {
|
||||||
|
return item && item.id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,21 @@ const HOTKEYS: HotkeyDescription[] = [
|
|||||||
name: 'Close tab',
|
name: 'Close tab',
|
||||||
defaults: [['Ctrl+Shift+W'], ['Ctrl+A', 'K']],
|
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) {
|
emitNativeEvent (name, nativeEvent) {
|
||||||
nativeEvent.event = name
|
nativeEvent.event = name
|
||||||
|
|
||||||
console.log(nativeEvent)
|
//console.log(nativeEvent)
|
||||||
this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() })
|
this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() })
|
||||||
|
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
@@ -144,7 +159,7 @@ export class HotkeysService {
|
|||||||
let currentStrokes = this.getCurrentKeystrokes()
|
let currentStrokes = this.getCurrentKeystrokes()
|
||||||
|
|
||||||
for (let matchLength = Math.min(currentStrokes.length, sequence.length); matchLength > 0; matchLength--) {
|
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) => {
|
if (sequence.slice(0, matchLength).every((x, index) => {
|
||||||
return x.toLowerCase() == currentStrokes[currentStrokes.length - matchLength + index].toLowerCase()
|
return x.toLowerCase() == currentStrokes[currentStrokes.length - matchLength + index].toLowerCase()
|
||||||
})) {
|
})) {
|
||||||
|
@@ -46,6 +46,11 @@ export function stringifyKeySequence(events: NativeKeyEvent[]): string[] {
|
|||||||
if (lastEvent.shiftKey) {
|
if (lastEvent.shiftKey) {
|
||||||
itemKeys.push('Shift')
|
itemKeys.push('Shift')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (['Control', 'Shift', 'Alt', 'Command'].includes(lastEvent.key)) {
|
||||||
|
// TODO make this optional?
|
||||||
|
continue
|
||||||
|
}
|
||||||
itemKeys.push(lastEvent.key)
|
itemKeys.push(lastEvent.key)
|
||||||
items.push(itemKeys.join('+'))
|
items.push(itemKeys.join('+'))
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user