mirror of
https://github.com/Eugeny/tabby.git
synced 2025-09-18 22:26:05 +00:00
.
This commit is contained in:
4
app/src/api/configProvider.ts
Normal file
4
app/src/api/configProvider.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export abstract class ConfigProvider {
|
||||
configStructure: any = {}
|
||||
defaultConfigValues: any = {}
|
||||
}
|
8
app/src/api/hotkeyProvider.ts
Normal file
8
app/src/api/hotkeyProvider.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export interface IHotkeyDescription {
|
||||
id: string,
|
||||
name: string,
|
||||
}
|
||||
|
||||
export abstract class HotkeyProvider {
|
||||
hotkeys: IHotkeyDescription[] = []
|
||||
}
|
@@ -1,7 +1,10 @@
|
||||
export { Tab } from './tab'
|
||||
export { TabRecoveryProvider } from './tabRecovery'
|
||||
export { ToolbarButtonProvider, IToolbarButton } from './toolbarButtonProvider'
|
||||
export { ConfigProvider } from './configProvider'
|
||||
export { HotkeyProvider, IHotkeyDescription } from './hotkeyProvider'
|
||||
|
||||
export { AppService } from 'services/app'
|
||||
export { PluginsService } from 'services/plugins'
|
||||
export { ElectronService } from 'services/electron'
|
||||
export { HotkeysService } from 'services/hotkeys'
|
||||
|
@@ -10,7 +10,7 @@ import { ConfigService } from 'services/config'
|
||||
import { ElectronService } from 'services/electron'
|
||||
import { HostAppService } from 'services/hostApp'
|
||||
import { LogService } from 'services/log'
|
||||
import { HotkeysService } from 'services/hotkeys'
|
||||
import { HotkeysService, AppHotkeyProvider } from 'services/hotkeys'
|
||||
import { ModalService } from 'services/modal'
|
||||
import { NotifyService } from 'services/notify'
|
||||
import { PluginsService } from 'services/plugins'
|
||||
@@ -23,6 +23,8 @@ import { TabBodyComponent } from 'components/tabBody'
|
||||
import { TabHeaderComponent } from 'components/tabHeader'
|
||||
import { TitleBarComponent } from 'components/titleBar'
|
||||
|
||||
import { HotkeyProvider } from 'api/hotkeyProvider'
|
||||
|
||||
|
||||
let plugins = [
|
||||
require('./settings').default,
|
||||
@@ -50,6 +52,7 @@ let plugins = [
|
||||
NotifyService,
|
||||
PluginsService,
|
||||
QuitterService,
|
||||
{ provide: HotkeyProvider, useClass: AppHotkeyProvider, multi: true },
|
||||
],
|
||||
entryComponents: [
|
||||
],
|
||||
@@ -65,7 +68,4 @@ let plugins = [
|
||||
]
|
||||
})
|
||||
export class AppModule {
|
||||
constructor () {
|
||||
//pluginDispatcher.register(require('./plugin.hyperlinks').default)
|
||||
}
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@ import { DockingService } from 'services/docking'
|
||||
import { AppService, IToolbarButton, ToolbarButtonProvider } from 'api'
|
||||
|
||||
import 'angular2-toaster/lib/toaster.css'
|
||||
import 'overrides.scss'
|
||||
import 'global.less'
|
||||
import 'theme.scss'
|
||||
|
||||
@@ -65,9 +66,6 @@ export class AppRootComponent {
|
||||
})
|
||||
|
||||
this.hotkeys.matchedHotkey.subscribe((hotkey) => {
|
||||
if (hotkey == 'new-tab') {
|
||||
// TODO this.newTab()
|
||||
}
|
||||
if (hotkey.startsWith('tab-')) {
|
||||
let index = parseInt(hotkey.split('-')[1])
|
||||
if (index <= this.app.tabs.length) {
|
||||
|
@@ -66,24 +66,6 @@ body {
|
||||
}
|
||||
|
||||
|
||||
|
||||
ngb-modal-backdrop {
|
||||
// ngbmodalwindow has its own, properly animated backdrop
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
ngb-modal-window.fade.in {
|
||||
&.out {
|
||||
opacity: 0;
|
||||
|
||||
.modal-dialog {
|
||||
transform: translate(0, -25%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.btn {
|
||||
i + * {
|
||||
margin-left: 5px;
|
||||
|
9
app/src/overrides.scss
Normal file
9
app/src/overrides.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
ngb-tabset.vertical {
|
||||
display: flex;
|
||||
|
||||
> .nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: none;
|
||||
}
|
||||
}
|
@@ -1,69 +1,54 @@
|
||||
import * as yaml from 'js-yaml'
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
import { EventEmitter, Injectable } from '@angular/core'
|
||||
import { EventEmitter, Injectable, Inject } from '@angular/core'
|
||||
import { ElectronService } from 'services/electron'
|
||||
import { ConfigProvider } from 'api/configProvider'
|
||||
|
||||
const configMerge = (a, b) => require('deepmerge')(a, b, { arrayMerge: (_d, s) => s })
|
||||
const defaultConfigValues : IConfigData = require('../../defaultConfigValues.yaml')
|
||||
const defaultConfigStructure : IConfigData = require('../../defaultConfigStructure.yaml')
|
||||
|
||||
export interface IAppearanceData {
|
||||
useNativeFrame: boolean
|
||||
font: string
|
||||
fontSize: number
|
||||
dock: string
|
||||
dockScreen: string
|
||||
dockFill: number
|
||||
tabsOnTop: boolean
|
||||
}
|
||||
|
||||
export interface ITerminalData {
|
||||
bell: string|boolean
|
||||
}
|
||||
|
||||
export interface IConfigData {
|
||||
appearance?: IAppearanceData
|
||||
hotkeys?: any
|
||||
terminal?: ITerminalData
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ConfigService {
|
||||
store: IConfigData
|
||||
store: any
|
||||
change = new EventEmitter()
|
||||
restartRequested: boolean
|
||||
private path: string
|
||||
private configStructure: any = require('../../defaultConfigStructure.yaml')
|
||||
private defaultConfigValues: any = require('../../defaultConfigValues.yaml')
|
||||
|
||||
constructor (
|
||||
electron: ElectronService
|
||||
electron: ElectronService,
|
||||
@Inject(ConfigProvider) configProviders: ConfigProvider[],
|
||||
) {
|
||||
this.path = path.join(electron.app.getPath('userData'), 'config.yaml')
|
||||
this.configStructure = configProviders.map(x => x.configStructure).reduce(configMerge, this.configStructure)
|
||||
this.defaultConfigValues = configProviders.map(x => x.defaultConfigValues).reduce(configMerge, this.defaultConfigValues)
|
||||
this.load()
|
||||
}
|
||||
|
||||
load () {
|
||||
load (): void {
|
||||
if (fs.existsSync(this.path)) {
|
||||
this.store = configMerge(defaultConfigStructure, yaml.safeLoad(fs.readFileSync(this.path, 'utf8')))
|
||||
this.store = configMerge(this.configStructure, yaml.safeLoad(fs.readFileSync(this.path, 'utf8')))
|
||||
} else {
|
||||
this.store = Object.assign({}, defaultConfigStructure)
|
||||
this.store = Object.assign({}, this.configStructure)
|
||||
}
|
||||
}
|
||||
|
||||
save () {
|
||||
save (): void {
|
||||
fs.writeFileSync(this.path, yaml.safeDump(this.store), 'utf8')
|
||||
this.emitChange()
|
||||
}
|
||||
|
||||
full () : IConfigData {
|
||||
return configMerge(defaultConfigValues, this.store)
|
||||
full (): any {
|
||||
return configMerge(this.defaultConfigValues, this.store)
|
||||
}
|
||||
|
||||
emitChange () {
|
||||
emitChange (): void {
|
||||
this.change.emit()
|
||||
}
|
||||
|
||||
requestRestart () {
|
||||
requestRestart (): void {
|
||||
this.restartRequested = true
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,10 @@
|
||||
import { Injectable, NgZone, EventEmitter } from '@angular/core'
|
||||
import { Injectable, Inject, NgZone, EventEmitter } from '@angular/core'
|
||||
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 HotkeyDescription {
|
||||
id: string,
|
||||
name: string,
|
||||
}
|
||||
|
||||
export interface PartialHotkeyMatch {
|
||||
id: string,
|
||||
@@ -16,69 +13,6 @@ export interface PartialHotkeyMatch {
|
||||
}
|
||||
|
||||
const KEY_TIMEOUT = 2000
|
||||
const HOTKEYS: HotkeyDescription[] = [
|
||||
{
|
||||
id: 'new-tab',
|
||||
name: 'New tab',
|
||||
},
|
||||
{
|
||||
id: 'close-tab',
|
||||
name: 'Close tab',
|
||||
},
|
||||
{
|
||||
id: 'toggle-last-tab',
|
||||
name: 'Toggle last tab',
|
||||
},
|
||||
{
|
||||
id: 'next-tab',
|
||||
name: 'Next tab',
|
||||
},
|
||||
{
|
||||
id: 'previous-tab',
|
||||
name: 'Previous tab',
|
||||
},
|
||||
{
|
||||
id: 'tab-1',
|
||||
name: 'Tab 1',
|
||||
},
|
||||
{
|
||||
id: 'tab-2',
|
||||
name: 'Tab 2',
|
||||
},
|
||||
{
|
||||
id: 'tab-3',
|
||||
name: 'Tab 3',
|
||||
},
|
||||
{
|
||||
id: 'tab-4',
|
||||
name: 'Tab 4',
|
||||
},
|
||||
{
|
||||
id: 'tab-5',
|
||||
name: 'Tab 5',
|
||||
},
|
||||
{
|
||||
id: 'tab-6',
|
||||
name: 'Tab 6',
|
||||
},
|
||||
{
|
||||
id: 'tab-7',
|
||||
name: 'Tab 7',
|
||||
},
|
||||
{
|
||||
id: 'tab-8',
|
||||
name: 'Tab 8',
|
||||
},
|
||||
{
|
||||
id: 'tab-9',
|
||||
name: 'Tab 9',
|
||||
},
|
||||
{
|
||||
id: 'tab-10',
|
||||
name: 'Tab 10',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
interface EventBufferEntry {
|
||||
event: NativeKeyEvent,
|
||||
@@ -92,11 +26,13 @@ export class HotkeysService {
|
||||
globalHotkey = new EventEmitter()
|
||||
private currentKeystrokes: EventBufferEntry[] = []
|
||||
private disabledLevel = 0
|
||||
private hotkeyDescriptions: IHotkeyDescription[]
|
||||
|
||||
constructor(
|
||||
private zone: NgZone,
|
||||
private electron: ElectronService,
|
||||
private config: ConfigService,
|
||||
@Inject(HotkeyProvider) hotkeyProviders: HotkeyProvider[],
|
||||
) {
|
||||
let events = [
|
||||
{
|
||||
@@ -122,6 +58,7 @@ export class HotkeysService {
|
||||
oldHandler.bind(this)(nativeEvent)
|
||||
}
|
||||
})
|
||||
this.hotkeyDescriptions = hotkeyProviders.map(x => x.hotkeys).reduce((a, b) => a.concat(b))
|
||||
}
|
||||
|
||||
emitNativeEvent (name, nativeEvent) {
|
||||
@@ -214,8 +151,8 @@ export class HotkeysService {
|
||||
return result
|
||||
}
|
||||
|
||||
getHotkeyDescription (id: string) : HotkeyDescription {
|
||||
return HOTKEYS.filter((x) => x.id == id)[0]
|
||||
getHotkeyDescription (id: string) : IHotkeyDescription {
|
||||
return this.hotkeyDescriptions.filter((x) => x.id == id)[0]
|
||||
}
|
||||
|
||||
enable () {
|
||||
@@ -231,3 +168,70 @@ export class HotkeysService {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class AppHotkeyProvider extends HotkeyProvider {
|
||||
hotkeys: IHotkeyDescription[] = [
|
||||
{
|
||||
id: 'new-tab',
|
||||
name: 'New tab',
|
||||
},
|
||||
{
|
||||
id: 'close-tab',
|
||||
name: 'Close tab',
|
||||
},
|
||||
{
|
||||
id: 'toggle-last-tab',
|
||||
name: 'Toggle last tab',
|
||||
},
|
||||
{
|
||||
id: 'next-tab',
|
||||
name: 'Next tab',
|
||||
},
|
||||
{
|
||||
id: 'previous-tab',
|
||||
name: 'Previous tab',
|
||||
},
|
||||
{
|
||||
id: 'tab-1',
|
||||
name: 'Tab 1',
|
||||
},
|
||||
{
|
||||
id: 'tab-2',
|
||||
name: 'Tab 2',
|
||||
},
|
||||
{
|
||||
id: 'tab-3',
|
||||
name: 'Tab 3',
|
||||
},
|
||||
{
|
||||
id: 'tab-4',
|
||||
name: 'Tab 4',
|
||||
},
|
||||
{
|
||||
id: 'tab-5',
|
||||
name: 'Tab 5',
|
||||
},
|
||||
{
|
||||
id: 'tab-6',
|
||||
name: 'Tab 6',
|
||||
},
|
||||
{
|
||||
id: 'tab-7',
|
||||
name: 'Tab 7',
|
||||
},
|
||||
{
|
||||
id: 'tab-8',
|
||||
name: 'Tab 8',
|
||||
},
|
||||
{
|
||||
id: 'tab-9',
|
||||
name: 'Tab 9',
|
||||
},
|
||||
{
|
||||
id: 'tab-10',
|
||||
name: 'Tab 10',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ import { Component } from '@angular/core'
|
||||
|
||||
export declare type ComponentType = new (...args: any[]) => Component
|
||||
|
||||
export abstract class SettingsProvider {
|
||||
export abstract class SettingsTabProvider {
|
||||
title: string
|
||||
|
||||
getComponentType (): ComponentType {
|
||||
|
6
app/src/settings/components/multiHotkeyInput.pug
Normal file
6
app/src/settings/components/multiHotkeyInput.pug
Normal file
@@ -0,0 +1,6 @@
|
||||
.item(*ngFor='let item of model')
|
||||
.body((click)='editItem(item)')
|
||||
.stroke(*ngFor='let stroke of item') {{stroke}}
|
||||
.remove((click)='removeItem(item)') ×
|
||||
|
||||
.add((click)='addItem()') Add
|
28
app/src/settings/components/multiHotkeyInput.scss
Normal file
28
app/src/settings/components/multiHotkeyInput.scss
Normal file
@@ -0,0 +1,28 @@
|
||||
:host {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
flex: none;
|
||||
padding: 3px 0;
|
||||
margin-right: 5px;
|
||||
|
||||
.body {
|
||||
flex: none;
|
||||
display: flex;
|
||||
|
||||
.stroke {
|
||||
flex: none;
|
||||
padding: 0 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.remove {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
|
||||
.add {
|
||||
flex: auto;
|
||||
}
|
48
app/src/settings/components/multiHotkeyInput.ts
Normal file
48
app/src/settings/components/multiHotkeyInput.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core'
|
||||
import { ModalService } from 'services/modal'
|
||||
import { HotkeyInputModalComponent } from './hotkeyInputModal'
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'multi-hotkey-input',
|
||||
template: require('./multiHotkeyInput.pug'),
|
||||
styles: [require('./multiHotkeyInput.scss')],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class MultiHotkeyInputComponent {
|
||||
constructor (
|
||||
private modal: ModalService,
|
||||
) { }
|
||||
|
||||
ngOnInit () {
|
||||
if (!this.model) {
|
||||
this.model = []
|
||||
}
|
||||
if (typeof this.model == 'string') {
|
||||
this.model = [this.model]
|
||||
}
|
||||
this.model = this.model.map(item => (typeof item == 'string') ? [item] : item)
|
||||
}
|
||||
|
||||
editItem (item) {
|
||||
this.modal.open(HotkeyInputModalComponent).result.then((value: string[]) => {
|
||||
Object.assign(item, value)
|
||||
this.modelChange.emit(this.model)
|
||||
})
|
||||
}
|
||||
|
||||
addItem () {
|
||||
this.modal.open(HotkeyInputModalComponent).result.then((value: string[]) => {
|
||||
this.model.push(value)
|
||||
this.modelChange.emit(this.model)
|
||||
})
|
||||
}
|
||||
|
||||
removeItem (item) {
|
||||
this.model = this.model.filter(x => x !== item)
|
||||
this.modelChange.emit(this.model)
|
||||
}
|
||||
|
||||
@Input() model: string[][]
|
||||
@Output() modelChange = new EventEmitter()
|
||||
}
|
10
app/src/settings/components/settingsPane.deep.css
Normal file
10
app/src/settings/components/settingsPane.deep.css
Normal file
@@ -0,0 +1,10 @@
|
||||
:host /deep/ ngb-tabset {
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
:host /deep/ ngb-tabset > .tab-content {
|
||||
padding: 15px 30px;
|
||||
margin: 0;
|
||||
flex: auto;
|
||||
overflow-y: auto;
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
button.btn.btn-outline-warning.btn-block(*ngIf='config.restartRequested', '(click)'='restartApp()') Restart the app to apply changes
|
||||
|
||||
ngb-tabset(type='tabs')
|
||||
ngb-tabset.vertical(type='tabs')
|
||||
ngb-tab(*ngFor='let provider of settingsProviders')
|
||||
template(ngbTabTitle)
|
||||
| {{provider.title}}
|
||||
@@ -134,10 +134,13 @@ ngb-tabset(type='tabs')
|
||||
| Hotkeys
|
||||
template(ngbTabContent)
|
||||
.form-group
|
||||
table.table
|
||||
table
|
||||
tr
|
||||
th Toggle terminal window
|
||||
td
|
||||
hotkey-input('[(model)]'='globalHotkey')
|
||||
|
||||
|
||||
hotkey-input('[(model)]'='globalHotkey')
|
||||
tr(*ngFor='let hotkey of hotkeyDescriptions')
|
||||
th {{hotkey.name}}
|
||||
td
|
||||
multi-hotkey-input('[(model)]'='config.store.hotkeys[hotkey.id]')
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex: auto;
|
||||
margin: 15px;
|
||||
|
||||
>.btn-block {
|
||||
margin-bottom: 20px;
|
@@ -2,27 +2,34 @@ import { Component, Inject } from '@angular/core'
|
||||
import { ElectronService } from 'services/electron'
|
||||
import { ConfigService } from 'services/config'
|
||||
import { DockingService } from 'services/docking'
|
||||
import { IHotkeyDescription, HotkeyProvider } from 'api/hotkeyProvider'
|
||||
|
||||
import { BaseTabComponent } from 'components/baseTab'
|
||||
import { SettingsTab } from '../tab'
|
||||
import { SettingsProvider } from '../api'
|
||||
import { SettingsTabProvider } from '../api'
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'settings-pane',
|
||||
template: require('./settingsPane.pug'),
|
||||
styles: [require('./settingsPane.less')],
|
||||
styles: [
|
||||
require('./settingsPane.scss'),
|
||||
require('./settingsPane.deep.css'),
|
||||
],
|
||||
})
|
||||
export class SettingsPaneComponent extends BaseTabComponent<SettingsTab> {
|
||||
globalHotkey = ['Ctrl+Shift+G']
|
||||
private hotkeyDescriptions: IHotkeyDescription[]
|
||||
|
||||
constructor(
|
||||
public config: ConfigService,
|
||||
private electron: ElectronService,
|
||||
public docking: DockingService,
|
||||
@Inject(SettingsProvider) public settingsProviders: SettingsProvider[]
|
||||
@Inject(HotkeyProvider) hotkeyProviders: HotkeyProvider[],
|
||||
@Inject(SettingsTabProvider) public settingsProviders: SettingsTabProvider[]
|
||||
) {
|
||||
super()
|
||||
this.hotkeyDescriptions = hotkeyProviders.map(x => x.hotkeys).reduce((a, b) => a.concat(b))
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import { Component, Input, ViewContainerRef, ViewChild, ComponentFactoryResolver, ComponentRef } from '@angular/core'
|
||||
import { SettingsProvider } from '../api'
|
||||
import { SettingsTabProvider } from '../api'
|
||||
|
||||
@Component({
|
||||
selector: 'settings-tab-body',
|
||||
template: '<template #placeholder></template>',
|
||||
})
|
||||
export class SettingsTabBodyComponent {
|
||||
@Input() provider: SettingsProvider
|
||||
@Input() provider: SettingsTabProvider
|
||||
@ViewChild('placeholder', {read: ViewContainerRef}) placeholder: ViewContainerRef
|
||||
private component: ComponentRef<Component>
|
||||
|
||||
|
@@ -7,6 +7,7 @@ import { HotkeyInputComponent } from './components/hotkeyInput'
|
||||
import { HotkeyDisplayComponent } from './components/hotkeyDisplay'
|
||||
import { HotkeyHintComponent } from './components/hotkeyHint'
|
||||
import { HotkeyInputModalComponent } from './components/hotkeyInputModal'
|
||||
import { MultiHotkeyInputComponent } from './components/multiHotkeyInput'
|
||||
import { SettingsPaneComponent } from './components/settingsPane'
|
||||
import { SettingsTabBodyComponent } from './components/settingsTabBody'
|
||||
|
||||
@@ -35,6 +36,7 @@ import { RecoveryProvider } from './recoveryProvider'
|
||||
HotkeyHintComponent,
|
||||
HotkeyInputComponent,
|
||||
HotkeyInputModalComponent,
|
||||
MultiHotkeyInputComponent,
|
||||
SettingsPaneComponent,
|
||||
SettingsTabBodyComponent,
|
||||
],
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ToolbarButtonProvider, IToolbarButton, AppService } from 'api'
|
||||
import { HotkeysService, ToolbarButtonProvider, IToolbarButton, AppService } from 'api'
|
||||
import { SessionsService } from './services/sessions'
|
||||
import { TerminalTab } from './tab'
|
||||
|
||||
@@ -9,8 +9,18 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
||||
constructor (
|
||||
private app: AppService,
|
||||
private sessions: SessionsService,
|
||||
hotkeys: HotkeysService,
|
||||
) {
|
||||
super()
|
||||
hotkeys.matchedHotkey.subscribe(async (hotkey) => {
|
||||
if (hotkey == 'new-tab') {
|
||||
this.app.openTab(await this.getNewTab())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async getNewTab (): Promise<TerminalTab> {
|
||||
return new TerminalTab(await this.sessions.createNewSession({ command: 'zsh' }))
|
||||
}
|
||||
|
||||
provide (): IToolbarButton[] {
|
||||
@@ -18,8 +28,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
||||
icon: 'plus',
|
||||
title: 'New terminal',
|
||||
click: async () => {
|
||||
let session = await this.sessions.createNewSession({ command: 'zsh' })
|
||||
this.app.openTab(new TerminalTab(session))
|
||||
this.app.openTab(await this.getNewTab())
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
@@ -3,8 +3,8 @@
|
||||
.form-group
|
||||
label Preview
|
||||
.appearance-preview(
|
||||
[style.font-family]='config.full().appearance.font',
|
||||
[style.font-size]='config.full().appearance.fontSize + "px"',
|
||||
[style.font-family]='config.full().terminal.font',
|
||||
[style.font-size]='config.full().terminal.fontSize + "px"',
|
||||
)
|
||||
.text john@doe-pc$ ls
|
||||
.text foo bar
|
||||
@@ -14,7 +14,7 @@
|
||||
input.form-control(
|
||||
type='text',
|
||||
[ngbTypeahead]='fontAutocomplete',
|
||||
'[(ngModel)]'='config.store.appearance.font',
|
||||
'[(ngModel)]'='config.store.terminal.font',
|
||||
(ngModelChange)='config.save()',
|
||||
)
|
||||
small.form-text.text-muted Font to be used in the terminal
|
||||
@@ -23,7 +23,7 @@
|
||||
label Font size
|
||||
input.form-control(
|
||||
type='number',
|
||||
'[(ngModel)]'='config.store.appearance.fontSize',
|
||||
'[(ngModel)]'='config.store.terminal.fontSize',
|
||||
(ngModelChange)='config.save()',
|
||||
)
|
||||
small.form-text.text-muted Text size to be used in the terminal
|
||||
|
@@ -83,8 +83,8 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
||||
|
||||
configure () {
|
||||
let config = this.config.full()
|
||||
preferenceManager.set('font-family', config.appearance.font)
|
||||
preferenceManager.set('font-size', config.appearance.fontSize)
|
||||
preferenceManager.set('font-family', config.terminal.font)
|
||||
preferenceManager.set('font-size', config.terminal.fontSize)
|
||||
preferenceManager.set('audible-bell-sound', '')
|
||||
preferenceManager.set('desktop-notification-bell', config.terminal.bell == 'notification')
|
||||
preferenceManager.set('enable-clipboard-notice', false)
|
||||
|
24
app/src/terminal/config.ts
Normal file
24
app/src/terminal/config.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { ConfigProvider } from 'api'
|
||||
|
||||
|
||||
export class TerminalConfigProvider extends ConfigProvider {
|
||||
defaultConfigValues: any = {
|
||||
terminal: {
|
||||
font: 'monospace',
|
||||
fontSize: 14,
|
||||
bell: 'off',
|
||||
},
|
||||
hotkeys: {
|
||||
'new-tab': [
|
||||
['Ctrl-A', 'C'],
|
||||
['Ctrl-A', 'Ctrl-C'],
|
||||
'Ctrl-Shift-T',
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
configStructure: any = {
|
||||
terminal: {},
|
||||
hotkeys: {},
|
||||
}
|
||||
}
|
@@ -3,8 +3,8 @@ import { BrowserModule } from '@angular/platform-browser'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
|
||||
import { ToolbarButtonProvider, TabRecoveryProvider } from 'api'
|
||||
import { SettingsProvider } from '../settings/api'
|
||||
import { ToolbarButtonProvider, TabRecoveryProvider, ConfigProvider } from 'api'
|
||||
import { SettingsTabProvider } from '../settings/api'
|
||||
|
||||
import { TerminalTabComponent } from './components/terminalTab'
|
||||
import { SettingsComponent } from './components/settings'
|
||||
@@ -14,6 +14,7 @@ import { ButtonProvider } from './buttonProvider'
|
||||
import { RecoveryProvider } from './recoveryProvider'
|
||||
import { SessionPersistenceProvider } from './api'
|
||||
import { TerminalSettingsProvider } from './settings'
|
||||
import { TerminalConfigProvider } from './config'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -26,7 +27,8 @@ import { TerminalSettingsProvider } from './settings'
|
||||
{ provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true },
|
||||
SessionsService,
|
||||
{ provide: SessionPersistenceProvider, useClass: ScreenPersistenceProvider },
|
||||
{ provide: SettingsProvider, useClass: TerminalSettingsProvider, multi: true },
|
||||
{ provide: SettingsTabProvider, useClass: TerminalSettingsProvider, multi: true },
|
||||
{ provide: ConfigProvider, useClass: TerminalConfigProvider, multi: true },
|
||||
],
|
||||
entryComponents: [
|
||||
TerminalTabComponent,
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { SettingsProvider, ComponentType } from '../settings/api'
|
||||
import { SettingsTabProvider, ComponentType } from '../settings/api'
|
||||
import { SettingsComponent } from './components/settings'
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class TerminalSettingsProvider extends SettingsProvider {
|
||||
export class TerminalSettingsProvider extends SettingsTabProvider {
|
||||
title = 'Terminal'
|
||||
|
||||
getComponentType (): ComponentType {
|
||||
|
Reference in New Issue
Block a user