mirror of
https://github.com/Eugeny/tabby.git
synced 2025-06-27 06:49:53 +00:00
.
This commit is contained in:
parent
f08bf49b62
commit
b7745bdd5b
@ -22,7 +22,7 @@ import { HotkeyInputComponent } from 'components/hotkeyInput'
|
|||||||
import { HotkeyDisplayComponent } from 'components/hotkeyDisplay'
|
import { HotkeyDisplayComponent } from 'components/hotkeyDisplay'
|
||||||
import { HotkeyHintComponent } from 'components/hotkeyHint'
|
import { HotkeyHintComponent } from 'components/hotkeyHint'
|
||||||
import { HotkeyInputModalComponent } from 'components/hotkeyInputModal'
|
import { HotkeyInputModalComponent } from 'components/hotkeyInputModal'
|
||||||
import { SettingsModalComponent } from 'components/settingsModal'
|
import { SettingsPaneComponent } from 'components/settingsPane'
|
||||||
import { TerminalComponent } from 'components/terminal'
|
import { TerminalComponent } from 'components/terminal'
|
||||||
|
|
||||||
|
|
||||||
@ -48,7 +48,6 @@ import { TerminalComponent } from 'components/terminal'
|
|||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
HotkeyInputModalComponent,
|
HotkeyInputModalComponent,
|
||||||
SettingsModalComponent,
|
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
@ -57,7 +56,7 @@ import { TerminalComponent } from 'components/terminal'
|
|||||||
HotkeyHintComponent,
|
HotkeyHintComponent,
|
||||||
HotkeyInputComponent,
|
HotkeyInputComponent,
|
||||||
HotkeyInputModalComponent,
|
HotkeyInputModalComponent,
|
||||||
SettingsModalComponent,
|
SettingsPaneComponent,
|
||||||
TerminalComponent,
|
TerminalComponent,
|
||||||
],
|
],
|
||||||
bootstrap: [
|
bootstrap: [
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
.button-states() {
|
.button-states() {
|
||||||
transition: 0.125s all;
|
transition: 0.125s all;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
&:hover:not(.active) {
|
&:hover:not(.active) {
|
||||||
background: rgba(255, 255, 255, .033);
|
background: rgba(255, 255, 255, .033);
|
||||||
@ -43,7 +45,7 @@
|
|||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-minimize, .btn-maximize, .btn-close {
|
button {
|
||||||
flex: none;
|
flex: none;
|
||||||
line-height: @titlebar-height - 2px;
|
line-height: @titlebar-height - 2px;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
@ -62,32 +64,36 @@
|
|||||||
flex: none;
|
flex: none;
|
||||||
height: @tabs-height;
|
height: @tabs-height;
|
||||||
background: @body-bg;
|
background: @body-bg;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
.btn-settings, .btn-new-tab, .tab {
|
&>button, .tab {
|
||||||
line-height: @tabs-height - 2px;
|
line-height: @tabs-height - 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-new-tab, .btn-settings {
|
&>button {
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
flex: none;
|
flex: none;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
border-bottom: 2px solid transparent;
|
border-bottom: 2px solid transparent;
|
||||||
transition: 0.25s all;
|
transition: 0.25s all;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
.button-states();
|
||||||
|
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #888;
|
color: #888;
|
||||||
background: #141c23;
|
background: #141c23;
|
||||||
|
}
|
||||||
|
|
||||||
i {
|
&.active-tab-0 .btn-new-tab {
|
||||||
margin-right: 10px;
|
border-bottom-right-radius: @tab-border-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-states();
|
.tab.active + button {
|
||||||
|
border-bottom-left-radius: @tab-border-radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
@ -99,6 +105,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
background: @body-bg;
|
background: @body-bg;
|
||||||
|
transition: 0.25s all;
|
||||||
|
|
||||||
.button-states();
|
.button-states();
|
||||||
|
|
||||||
@ -108,6 +115,7 @@
|
|||||||
flex: auto;
|
flex: auto;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
background: #141c23;
|
background: #141c23;
|
||||||
|
transition: 0.25s all;
|
||||||
|
|
||||||
div.index {
|
div.index {
|
||||||
flex: none;
|
flex: none;
|
||||||
@ -162,7 +170,7 @@
|
|||||||
//border-bottom: 2px solid transparent;
|
//border-bottom: 2px solid transparent;
|
||||||
transition: 0.25s all;
|
transition: 0.25s all;
|
||||||
|
|
||||||
&.pre-selected, &:nth-last-child(2) {
|
&.pre-selected, &:nth-last-child(1) {
|
||||||
.content-wrapper {
|
.content-wrapper {
|
||||||
border-bottom-right-radius: @tab-border-radius;
|
border-bottom-right-radius: @tab-border-radius;
|
||||||
}
|
}
|
||||||
@ -195,7 +203,7 @@
|
|||||||
display: none;
|
display: none;
|
||||||
flex: auto;
|
flex: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 10px 15px;
|
padding: 15px;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
.titlebar
|
.titlebar
|
||||||
.title((dblclick)='hostApp.maximizeWindow()') Term
|
.title((dblclick)='hostApp.maximizeWindow()') Term
|
||||||
.btn-minimize((click)='hostApp.minimizeWindow()')
|
button.btn-minimize((click)='hostApp.minimizeWindow()')
|
||||||
i.fa.fa-window-minimize
|
i.fa.fa-window-minimize
|
||||||
.btn-maximize((click)='hostApp.maximizeWindow()')
|
button.btn-maximize((click)='hostApp.maximizeWindow()')
|
||||||
i.fa.fa-window-maximize
|
i.fa.fa-window-maximize
|
||||||
.btn-close((click)='hostApp.quit()')
|
button.btn-close((click)='hostApp.quit()')
|
||||||
i.fa.fa-close
|
i.fa.fa-close
|
||||||
|
|
||||||
.tabs
|
.tabs(class='active-tab-{{tabs.indexOf(activeTab)}}')
|
||||||
|
button.btn-new-tab((click)='newTab()')
|
||||||
|
i.fa.fa-plus
|
||||||
.tab(
|
.tab(
|
||||||
*ngFor='let tab of tabs; let idx = index; trackBy: tab?.id',
|
*ngFor='let tab of tabs; let idx = index; trackBy: tab?.id',
|
||||||
(click)='selectTab(tab)',
|
(click)='selectTab(tab)',
|
||||||
@ -20,15 +22,13 @@
|
|||||||
div.index {{idx + 1}}
|
div.index {{idx + 1}}
|
||||||
div.name {{tab.name || 'Terminal'}}
|
div.name {{tab.name || 'Terminal'}}
|
||||||
button((click)='closeTab(tab)') ×
|
button((click)='closeTab(tab)') ×
|
||||||
.btn-new-tab((click)='newTab()')
|
button.btn-settings((click)='showSettings()')
|
||||||
i.fa.fa-plus
|
|
||||||
span Tab
|
|
||||||
.btn-settings((click)='showSettings()')
|
|
||||||
i.fa.fa-cog
|
i.fa.fa-cog
|
||||||
|
|
||||||
.tabs-content
|
.tabs-content
|
||||||
.tab(*ngFor='let tab of tabs; trackBy: tab?.id', [class.active]='tab == activeTab')
|
.tab(*ngFor='let tab of tabs; trackBy: tab?.id', [class.active]='tab == activeTab')
|
||||||
terminal([session]='tab.session', '[(title)]'='tab.name')
|
terminal(*ngIf='tab.type == "terminal"', [session]='tab.session', '[(title)]'='tab.name')
|
||||||
|
settings-pane(*ngIf='tab.type == "settings"')
|
||||||
|
|
||||||
hotkey-hint
|
hotkey-hint
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Component, ElementRef, trigger, style, animate, transition, state } from '@angular/core'
|
import { Component, ElementRef, trigger, style, animate, transition, state } from '@angular/core'
|
||||||
import { ModalService } from 'services/modal'
|
|
||||||
import { ElectronService } from 'services/electron'
|
import { ElectronService } from 'services/electron'
|
||||||
import { HostAppService } from 'services/hostApp'
|
import { HostAppService } from 'services/hostApp'
|
||||||
import { HotkeysService } from 'services/hotkeys'
|
import { HotkeysService } from 'services/hotkeys'
|
||||||
@ -8,19 +7,23 @@ import { QuitterService } from 'services/quitter'
|
|||||||
import { ToasterConfig } from 'angular2-toaster'
|
import { ToasterConfig } from 'angular2-toaster'
|
||||||
import { Session, SessionsService } from 'services/sessions'
|
import { Session, SessionsService } from 'services/sessions'
|
||||||
|
|
||||||
import { SettingsModalComponent } from 'components/settingsModal'
|
|
||||||
|
|
||||||
import 'angular2-toaster/lib/toaster.css'
|
import 'angular2-toaster/lib/toaster.css'
|
||||||
import 'global.less'
|
import 'global.less'
|
||||||
|
|
||||||
|
|
||||||
|
const TYPE_TERMINAL = 'terminal'
|
||||||
|
const TYPE_SETTINGS = 'settings'
|
||||||
|
|
||||||
class Tab {
|
class Tab {
|
||||||
id: number
|
id: number
|
||||||
name: string
|
name: string
|
||||||
static lastTabID = 0
|
static lastTabID = 0
|
||||||
|
|
||||||
constructor (public session: Session) {
|
constructor (public type: string, public session: Session) {
|
||||||
this.id = Tab.lastTabID++
|
this.id = Tab.lastTabID++
|
||||||
|
if (type == TYPE_SETTINGS) {
|
||||||
|
this.name = 'Settings'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,7 +58,6 @@ export class AppComponent {
|
|||||||
lastTabIndex = 0
|
lastTabIndex = 0
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private modal: ModalService,
|
|
||||||
private elementRef: ElementRef,
|
private elementRef: ElementRef,
|
||||||
private sessions: SessionsService,
|
private sessions: SessionsService,
|
||||||
public hostApp: HostAppService,
|
public hostApp: HostAppService,
|
||||||
@ -118,11 +120,11 @@ export class AppComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newTab () {
|
newTab () {
|
||||||
this.addSessionTab(this.sessions.createNewSession({command: 'bash'}))
|
this.addTerminalTab(this.sessions.createNewSession({command: 'bash'}))
|
||||||
}
|
}
|
||||||
|
|
||||||
addSessionTab (session) {
|
addTerminalTab (session) {
|
||||||
let tab = new Tab(session)
|
let tab = new Tab(TYPE_TERMINAL, session)
|
||||||
this.tabs.push(tab)
|
this.tabs.push(tab)
|
||||||
this.selectTab(tab)
|
this.selectTab(tab)
|
||||||
}
|
}
|
||||||
@ -161,7 +163,9 @@ export class AppComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
closeTab (tab) {
|
closeTab (tab) {
|
||||||
tab.session.gracefullyDestroy()
|
if (tab.session) {
|
||||||
|
tab.session.gracefullyDestroy()
|
||||||
|
}
|
||||||
let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
|
let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
|
||||||
this.tabs = this.tabs.filter((x) => x != tab)
|
this.tabs = this.tabs.filter((x) => x != tab)
|
||||||
if (tab == this.activeTab) {
|
if (tab == this.activeTab) {
|
||||||
@ -173,7 +177,7 @@ export class AppComponent {
|
|||||||
this.sessions.recoverAll().then((recoveredSessions) => {
|
this.sessions.recoverAll().then((recoveredSessions) => {
|
||||||
if (recoveredSessions.length > 0) {
|
if (recoveredSessions.length > 0) {
|
||||||
recoveredSessions.forEach((session) => {
|
recoveredSessions.forEach((session) => {
|
||||||
this.addSessionTab(session)
|
this.addTerminalTab(session)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.newTab()
|
this.newTab()
|
||||||
@ -185,6 +189,11 @@ export class AppComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showSettings() {
|
showSettings() {
|
||||||
this.modal.open(SettingsModalComponent)
|
let settingsTab = this.tabs.find((x) => x.type == TYPE_SETTINGS)
|
||||||
|
if (!settingsTab) {
|
||||||
|
settingsTab = new Tab(TYPE_SETTINGS, null)
|
||||||
|
this.tabs.push(settingsTab)
|
||||||
|
}
|
||||||
|
this.selectTab(settingsTab)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
div.modal-body
|
|
||||||
ngb-tabset(type='tabs nav-justified')
|
|
||||||
ngb-tab
|
|
||||||
template(ngbTabTitle)
|
|
||||||
i.fa.fa-keyboard-o
|
|
||||||
| Hotkeys
|
|
||||||
template(ngbTabContent)
|
|
||||||
.form-group
|
|
||||||
table.table
|
|
||||||
tr
|
|
||||||
th Toggle terminal window
|
|
||||||
td
|
|
||||||
hotkey-input('[(model)]'='globalHotkey')
|
|
||||||
|
|
||||||
div.modal-footer
|
|
||||||
div.btn-group.btn-group-justified
|
|
||||||
a.btn.btn-default((click)='close()')
|
|
||||||
i.fa.fa-fw.fa-check
|
|
||||||
br
|
|
||||||
| Done
|
|
12
app/src/components/settingsPane.pug
Normal file
12
app/src/components/settingsPane.pug
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
ngb-tabset(type='tabs nav-justified')
|
||||||
|
ngb-tab
|
||||||
|
template(ngbTabTitle)
|
||||||
|
i.fa.fa-keyboard-o
|
||||||
|
| Hotkeys
|
||||||
|
template(ngbTabContent)
|
||||||
|
.form-group
|
||||||
|
table.table
|
||||||
|
tr
|
||||||
|
th Toggle terminal window
|
||||||
|
td
|
||||||
|
hotkey-input('[(model)]'='globalHotkey')
|
@ -2,17 +2,15 @@ import { Component } from '@angular/core'
|
|||||||
import { ElectronService } from 'services/electron'
|
import { ElectronService } from 'services/electron'
|
||||||
import { HostAppService, PLATFORM_WINDOWS, PLATFORM_LINUX, PLATFORM_MAC } from 'services/hostApp'
|
import { HostAppService, PLATFORM_WINDOWS, PLATFORM_LINUX, PLATFORM_MAC } from 'services/hostApp'
|
||||||
import { ConfigService } from 'services/config'
|
import { ConfigService } from 'services/config'
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'settings-modal',
|
selector: 'settings-pane',
|
||||||
template: require('./settingsModal.pug'),
|
template: require('./settingsPane.pug'),
|
||||||
styles: [require('./settingsModal.less')],
|
styles: [require('./settingsPane.less')],
|
||||||
})
|
})
|
||||||
export class SettingsModalComponent {
|
export class SettingsPaneComponent {
|
||||||
constructor(
|
constructor(
|
||||||
private modalInstance: NgbActiveModal,
|
|
||||||
public config: ConfigService,
|
public config: ConfigService,
|
||||||
hostApp: HostAppService,
|
hostApp: HostAppService,
|
||||||
electron: ElectronService,
|
electron: ElectronService,
|
||||||
@ -35,8 +33,4 @@ export class SettingsModalComponent {
|
|||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.config.save()
|
this.config.save()
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
|
||||||
this.modalInstance.close()
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -22,6 +22,7 @@ hterm.hterm.VT.ESC['k'] = function(parseState) {
|
|||||||
hterm.hterm.defaultStorage = new hterm.lib.Storage.Memory()
|
hterm.hterm.defaultStorage = new hterm.lib.Storage.Memory()
|
||||||
const pmgr = new hterm.hterm.PreferenceManager('default')
|
const pmgr = new hterm.hterm.PreferenceManager('default')
|
||||||
pmgr.set('user-css', ``)
|
pmgr.set('user-css', ``)
|
||||||
|
pmgr.set('font-size', 12)
|
||||||
pmgr.set('background-color', '#1D272D')
|
pmgr.set('background-color', '#1D272D')
|
||||||
pmgr.set('color-palette-overrides', {
|
pmgr.set('color-palette-overrides', {
|
||||||
0: '#1D272D',
|
0: '#1D272D',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user