mirror of
https://github.com/Eugeny/tabby.git
synced 2024-12-22 18:11:43 +03:00
.
This commit is contained in:
parent
3b47047052
commit
739750e8f0
@ -9,4 +9,4 @@ html
|
|||||||
script(src='./preload.js')
|
script(src='./preload.js')
|
||||||
script(src='./bundle.js', defer)
|
script(src='./bundle.js', defer)
|
||||||
body(style='background: ; min-height: 100vh')
|
body(style='background: ; min-height: 100vh')
|
||||||
app
|
app-root
|
||||||
|
20
app/src/api.ts
Normal file
20
app/src/api.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
export { AppService } from 'services/app'
|
||||||
|
export { PluginsService } from 'services/plugins'
|
||||||
|
export { Tab } from 'models/tab'
|
||||||
|
|
||||||
|
export interface IPlugin {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IToolbarButton {
|
||||||
|
icon: string
|
||||||
|
title: string
|
||||||
|
weight?: number
|
||||||
|
click: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IToolbarButtonProvider {
|
||||||
|
provide (): IToolbarButton[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ToolbarButtonProviderType = 'app:toolbar-button-provider'
|
@ -5,6 +5,7 @@ import { FormsModule } from '@angular/forms'
|
|||||||
import { ToasterModule } from 'angular2-toaster'
|
import { ToasterModule } from 'angular2-toaster'
|
||||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||||
|
|
||||||
|
import { AppService } from 'services/app'
|
||||||
import { ConfigService } from 'services/config'
|
import { ConfigService } from 'services/config'
|
||||||
import { ElectronService } from 'services/electron'
|
import { ElectronService } from 'services/electron'
|
||||||
import { HostAppService } from 'services/hostApp'
|
import { HostAppService } from 'services/hostApp'
|
||||||
@ -12,11 +13,11 @@ import { LogService } from 'services/log'
|
|||||||
import { HotkeysService } from 'services/hotkeys'
|
import { HotkeysService } from 'services/hotkeys'
|
||||||
import { ModalService } from 'services/modal'
|
import { ModalService } from 'services/modal'
|
||||||
import { NotifyService } from 'services/notify'
|
import { NotifyService } from 'services/notify'
|
||||||
import { PluginDispatcherService } from 'services/pluginDispatcher'
|
import { PluginsService } from 'services/plugins'
|
||||||
import { QuitterService } from 'services/quitter'
|
import { QuitterService } from 'services/quitter'
|
||||||
import { DockingService } from 'services/docking'
|
import { DockingService } from 'services/docking'
|
||||||
|
|
||||||
import { AppComponent } from 'components/app'
|
import { AppRootComponent } from 'components/appRoot'
|
||||||
import { CheckboxComponent } from 'components/checkbox'
|
import { CheckboxComponent } from 'components/checkbox'
|
||||||
import { TabBodyComponent } from 'components/tabBody'
|
import { TabBodyComponent } from 'components/tabBody'
|
||||||
import { TabHeaderComponent } from 'components/tabHeader'
|
import { TabHeaderComponent } from 'components/tabHeader'
|
||||||
@ -37,6 +38,7 @@ let plugins = [
|
|||||||
NgbModule.forRoot(),
|
NgbModule.forRoot(),
|
||||||
].concat(plugins),
|
].concat(plugins),
|
||||||
providers: [
|
providers: [
|
||||||
|
AppService,
|
||||||
ConfigService,
|
ConfigService,
|
||||||
DockingService,
|
DockingService,
|
||||||
ElectronService,
|
ElectronService,
|
||||||
@ -45,24 +47,24 @@ let plugins = [
|
|||||||
LogService,
|
LogService,
|
||||||
ModalService,
|
ModalService,
|
||||||
NotifyService,
|
NotifyService,
|
||||||
PluginDispatcherService,
|
PluginsService,
|
||||||
QuitterService,
|
QuitterService,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppRootComponent,
|
||||||
CheckboxComponent,
|
CheckboxComponent,
|
||||||
TabBodyComponent,
|
TabBodyComponent,
|
||||||
TabHeaderComponent,
|
TabHeaderComponent,
|
||||||
TitleBarComponent,
|
TitleBarComponent,
|
||||||
],
|
],
|
||||||
bootstrap: [
|
bootstrap: [
|
||||||
AppComponent,
|
AppRootComponent,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
constructor (pluginDispatcher: PluginDispatcherService) {
|
constructor () {
|
||||||
pluginDispatcher.register(require('./plugin.hyperlinks').default)
|
//pluginDispatcher.register(require('./plugin.hyperlinks').default)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
title-bar(*ngIf='!config.store.appearance.useNativeFrame && config.store.appearance.dock == "off"')
|
|
||||||
|
|
||||||
.spacer
|
|
||||||
|
|
||||||
.tabs(class='active-tab-{{tabs.indexOf(activeTab)}}')
|
|
||||||
button.btn.btn-secondary.btn-new-tab((click)='newTab()')
|
|
||||||
i.fa.fa-plus
|
|
||||||
tab-header(
|
|
||||||
*ngFor='let tab of tabs; let idx = index; trackBy: tab?.id',
|
|
||||||
[index]='idx',
|
|
||||||
[model]='tab',
|
|
||||||
[active]='tab == activeTab',
|
|
||||||
[hasActivity]='tab.hasActivity',
|
|
||||||
@animateTab,
|
|
||||||
(click)='selectTab(tab)',
|
|
||||||
(closeClicked)='closeTab(tab)',
|
|
||||||
)
|
|
||||||
button.btn.btn-secondary.btn-settings((click)='showSettings()')
|
|
||||||
i.fa.fa-cog
|
|
||||||
|
|
||||||
.tabs-content
|
|
||||||
tab-body(
|
|
||||||
*ngFor='let tab of tabs; trackBy: tab?.id',
|
|
||||||
[active]='tab == activeTab',
|
|
||||||
[model]='tab',
|
|
||||||
[class.scrollable]='tab.scrollable',
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
//hotkey-hint
|
|
||||||
|
|
||||||
toaster-container([toasterconfig]="toasterconfig")
|
|
||||||
template(ngbModalContainer)
|
|
||||||
|
|
||||||
div.window-resizer.window-resizer-tl
|
|
43
app/src/components/appRoot.pug
Normal file
43
app/src/components/appRoot.pug
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
title-bar(*ngIf='!config.store.appearance.useNativeFrame && config.store.appearance.dock == "off"')
|
||||||
|
|
||||||
|
.spacer
|
||||||
|
|
||||||
|
.tabs(class='active-tab-{{app.tabs.indexOf(app.activeTab)}}')
|
||||||
|
button.btn.btn-secondary(
|
||||||
|
*ngFor='let button of getToolbarButtons(false)',
|
||||||
|
[title]='button.title',
|
||||||
|
(click)='button.click()',
|
||||||
|
)
|
||||||
|
i.fa([class]='"fa fa-" + button.icon')
|
||||||
|
tab-header(
|
||||||
|
*ngFor='let tab of app.tabs; let idx = index; trackBy: tab?.id',
|
||||||
|
[index]='idx',
|
||||||
|
[model]='tab',
|
||||||
|
[active]='tab == app.activeTab',
|
||||||
|
[hasActivity]='tab.hasActivity',
|
||||||
|
@animateTab,
|
||||||
|
(click)='app.selectTab(tab)',
|
||||||
|
(closeClicked)='app.closeTab(tab)',
|
||||||
|
)
|
||||||
|
button.btn.btn-secondary(
|
||||||
|
*ngFor='let button of getToolbarButtons(true)',
|
||||||
|
[title]='button.title',
|
||||||
|
(click)='button.click()',
|
||||||
|
)
|
||||||
|
i.fa([class]='"fa fa-" + button.icon')
|
||||||
|
|
||||||
|
.tabs-content
|
||||||
|
tab-body(
|
||||||
|
*ngFor='let tab of app.tabs; trackBy: tab?.id',
|
||||||
|
[active]='tab == app.activeTab',
|
||||||
|
[model]='tab',
|
||||||
|
[class.scrollable]='tab.scrollable',
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
//hotkey-hint
|
||||||
|
|
||||||
|
toaster-container([toasterconfig]="toasterconfig")
|
||||||
|
template(ngbModalContainer)
|
||||||
|
|
||||||
|
div.window-resizer.window-resizer-tl
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, trigger, style, animate, transition, state } from '@angular/core'
|
import { Component, trigger, style, animate, transition, state } from '@angular/core'
|
||||||
import { ToasterConfig } from 'angular2-toaster'
|
import { ToasterConfig } from 'angular2-toaster'
|
||||||
|
|
||||||
import { ElectronService } from 'services/electron'
|
import { ElectronService } from 'services/electron'
|
||||||
@ -8,10 +8,9 @@ import { LogService } from 'services/log'
|
|||||||
import { QuitterService } from 'services/quitter'
|
import { QuitterService } from 'services/quitter'
|
||||||
import { ConfigService } from 'services/config'
|
import { ConfigService } from 'services/config'
|
||||||
import { DockingService } from 'services/docking'
|
import { DockingService } from 'services/docking'
|
||||||
// import { SessionsService } from 'services/sessions'
|
import { PluginsService } from 'services/plugins'
|
||||||
import { PluginDispatcherService } from 'services/pluginDispatcher'
|
|
||||||
|
|
||||||
import { Tab } from 'models/tab'
|
import { AppService, IToolbarButton, IToolbarButtonProvider, ToolbarButtonProviderType } from 'api'
|
||||||
|
|
||||||
import 'angular2-toaster/lib/toaster.css'
|
import 'angular2-toaster/lib/toaster.css'
|
||||||
import 'global.less'
|
import 'global.less'
|
||||||
@ -19,9 +18,9 @@ import 'theme.scss'
|
|||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app',
|
selector: 'app-root',
|
||||||
template: require('./app.pug'),
|
template: require('./appRoot.pug'),
|
||||||
styles: [require('./app.less')],
|
styles: [require('./appRoot.less')],
|
||||||
animations: [
|
animations: [
|
||||||
trigger('animateTab', [
|
trigger('animateTab', [
|
||||||
state('in', style({
|
state('in', style({
|
||||||
@ -41,27 +40,24 @@ import 'theme.scss'
|
|||||||
])
|
])
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppRootComponent {
|
||||||
toasterConfig: ToasterConfig
|
toasterConfig: ToasterConfig
|
||||||
@Input() tabs: Tab[] = []
|
|
||||||
@Input() activeTab: Tab
|
|
||||||
lastTabIndex = 0
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
// private sessions: SessionsService,
|
|
||||||
private docking: DockingService,
|
private docking: DockingService,
|
||||||
private electron: ElectronService,
|
private electron: ElectronService,
|
||||||
public hostApp: HostAppService,
|
public hostApp: HostAppService,
|
||||||
public hotkeys: HotkeysService,
|
public hotkeys: HotkeysService,
|
||||||
public config: ConfigService,
|
public config: ConfigService,
|
||||||
private pluginDispatcher: PluginDispatcherService,
|
private plugins: PluginsService,
|
||||||
|
public app: AppService,
|
||||||
log: LogService,
|
log: LogService,
|
||||||
_quitter: QuitterService,
|
_quitter: QuitterService,
|
||||||
) {
|
) {
|
||||||
console.timeStamp('AppComponent ctor')
|
console.timeStamp('AppComponent ctor')
|
||||||
|
|
||||||
let logger = log.create('main')
|
let logger = log.create('main')
|
||||||
logger.info('ELEMENTS client', electron.app.getVersion())
|
logger.info('v', electron.app.getVersion())
|
||||||
|
|
||||||
this.toasterConfig = new ToasterConfig({
|
this.toasterConfig = new ToasterConfig({
|
||||||
mouseoverTimerStop: true,
|
mouseoverTimerStop: true,
|
||||||
@ -71,42 +67,26 @@ export class AppComponent {
|
|||||||
|
|
||||||
this.hotkeys.matchedHotkey.subscribe((hotkey) => {
|
this.hotkeys.matchedHotkey.subscribe((hotkey) => {
|
||||||
if (hotkey == 'new-tab') {
|
if (hotkey == 'new-tab') {
|
||||||
this.newTab()
|
// TODO this.newTab()
|
||||||
}
|
}
|
||||||
if (hotkey.startsWith('tab-')) {
|
if (hotkey.startsWith('tab-')) {
|
||||||
let index = parseInt(hotkey.split('-')[1])
|
let index = parseInt(hotkey.split('-')[1])
|
||||||
if (index <= this.tabs.length) {
|
if (index <= this.app.tabs.length) {
|
||||||
this.selectTab(this.tabs[index - 1])
|
this.app.selectTab(this.app.tabs[index - 1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.activeTab) {
|
if (this.app.activeTab) {
|
||||||
if (hotkey == 'close-tab') {
|
if (hotkey == 'close-tab') {
|
||||||
this.closeTab(this.activeTab)
|
this.app.closeTab(this.app.activeTab)
|
||||||
}
|
}
|
||||||
if (hotkey == 'toggle-last-tab') {
|
if (hotkey == 'toggle-last-tab') {
|
||||||
this.toggleLastTab()
|
this.app.toggleLastTab()
|
||||||
}
|
}
|
||||||
if (hotkey == 'next-tab') {
|
if (hotkey == 'next-tab') {
|
||||||
this.nextTab()
|
this.app.nextTab()
|
||||||
}
|
}
|
||||||
if (hotkey == 'previous-tab') {
|
if (hotkey == 'previous-tab') {
|
||||||
this.previousTab()
|
this.app.previousTab()
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.hotkeys.key.subscribe((key) => {
|
|
||||||
if (key.event == 'keydown') {
|
|
||||||
if (key.alt && key.key >= '1' && key.key <= '9') {
|
|
||||||
let index = key.key.charCodeAt(0) - '0'.charCodeAt(0) - 1
|
|
||||||
if (index < this.tabs.length) {
|
|
||||||
this.selectTab(this.tabs[index])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (key.alt && key.key == '0') {
|
|
||||||
if (this.tabs.length >= 10) {
|
|
||||||
this.selectTab(this.tabs[9])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -145,57 +125,15 @@ export class AppComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
newTab () {
|
getToolbarButtons (aboveZero: boolean): IToolbarButton[] {
|
||||||
const tab = this.pluginDispatcher.temp2('zsh')
|
let buttons: IToolbarButton[] = []
|
||||||
this.tabs.push(tab)
|
this.plugins.getAll<IToolbarButtonProvider>(ToolbarButtonProviderType)
|
||||||
this.selectTab(tab)
|
.forEach((provider) => {
|
||||||
}
|
buttons = buttons.concat(provider.provide())
|
||||||
|
})
|
||||||
selectTab (tab) {
|
return buttons
|
||||||
if (this.tabs.includes(this.activeTab)) {
|
.filter((button) => (button.weight > 0) === aboveZero)
|
||||||
this.lastTabIndex = this.tabs.indexOf(this.activeTab)
|
.sort((a: IToolbarButton, b: IToolbarButton) => (a.weight || 0) - (b.weight || 0))
|
||||||
} else {
|
|
||||||
this.lastTabIndex = null
|
|
||||||
}
|
|
||||||
if (this.activeTab) {
|
|
||||||
this.activeTab.hasActivity = false
|
|
||||||
this.activeTab.blurred.emit()
|
|
||||||
}
|
|
||||||
this.activeTab = tab
|
|
||||||
this.activeTab.focused.emit()
|
|
||||||
}
|
|
||||||
|
|
||||||
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.destroy()
|
|
||||||
/* if (tab.session) {
|
|
||||||
this.sessions.destroySession(tab.session)
|
|
||||||
} */
|
|
||||||
let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
|
|
||||||
this.tabs = this.tabs.filter((x) => x != tab)
|
|
||||||
if (tab == this.activeTab) {
|
|
||||||
this.selectTab(this.tabs[newIndex])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
@ -212,14 +150,4 @@ export class AppComponent {
|
|||||||
})
|
})
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
showSettings() {
|
|
||||||
const SettingsTab = this.pluginDispatcher.temp
|
|
||||||
let settingsTab = this.tabs.find((x) => x instanceof SettingsTab)
|
|
||||||
if (!settingsTab) {
|
|
||||||
settingsTab = new SettingsTab()
|
|
||||||
this.tabs.push(settingsTab)
|
|
||||||
}
|
|
||||||
this.selectTab(settingsTab)
|
|
||||||
}
|
|
||||||
}
|
}
|
66
app/src/services/app.ts
Normal file
66
app/src/services/app.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { EventEmitter, Injectable } from '@angular/core'
|
||||||
|
import { Tab } from 'models/tab'
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppService {
|
||||||
|
tabs: Tab[] = []
|
||||||
|
activeTab: Tab
|
||||||
|
lastTabIndex = 0
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
openTab (tab: Tab): void {
|
||||||
|
this.tabs.push(tab)
|
||||||
|
this.selectTab(tab)
|
||||||
|
}
|
||||||
|
|
||||||
|
selectTab (tab) {
|
||||||
|
if (this.tabs.includes(this.activeTab)) {
|
||||||
|
this.lastTabIndex = this.tabs.indexOf(this.activeTab)
|
||||||
|
} else {
|
||||||
|
this.lastTabIndex = null
|
||||||
|
}
|
||||||
|
if (this.activeTab) {
|
||||||
|
this.activeTab.hasActivity = false
|
||||||
|
this.activeTab.blurred.emit()
|
||||||
|
}
|
||||||
|
this.activeTab = tab
|
||||||
|
this.activeTab.focused.emit()
|
||||||
|
}
|
||||||
|
|
||||||
|
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.destroy()
|
||||||
|
/* if (tab.session) {
|
||||||
|
this.sessions.destroySession(tab.session)
|
||||||
|
} */
|
||||||
|
let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
|
||||||
|
this.tabs = this.tabs.filter((x) => x != tab)
|
||||||
|
if (tab == this.activeTab) {
|
||||||
|
this.selectTab(this.tabs[newIndex])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,34 +0,0 @@
|
|||||||
import { Injectable } from '@angular/core'
|
|
||||||
import { ConfigService } from 'services/config'
|
|
||||||
import { ElectronService } from 'services/electron'
|
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class PluginDispatcherService {
|
|
||||||
plugins = []
|
|
||||||
temp: any
|
|
||||||
temp2: any
|
|
||||||
|
|
||||||
constructor (
|
|
||||||
private config: ConfigService,
|
|
||||||
private electron: ElectronService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
register (plugin) {
|
|
||||||
if (!this.plugins.includes(plugin)) {
|
|
||||||
this.plugins.push(new plugin({
|
|
||||||
config: this.config,
|
|
||||||
electron: this.electron,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit (event: string, parameters: any) {
|
|
||||||
this.plugins.forEach((plugin) => {
|
|
||||||
if (plugin[event]) {
|
|
||||||
plugin[event].bind(plugin)(parameters)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
45
app/src/services/plugins.ts
Normal file
45
app/src/services/plugins.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { IPlugin } from 'api'
|
||||||
|
import { Injectable } from '@angular/core'
|
||||||
|
|
||||||
|
|
||||||
|
interface IPluginEntry {
|
||||||
|
plugin: IPlugin
|
||||||
|
weight: number
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PluginsService {
|
||||||
|
plugins: {[type: string]: IPluginEntry[]} = {}
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
register (type: string, plugin: IPlugin, weight = 0): void {
|
||||||
|
if (!this.plugins[type]) {
|
||||||
|
this.plugins[type] = []
|
||||||
|
}
|
||||||
|
this.plugins[type].push({ plugin, weight })
|
||||||
|
}
|
||||||
|
|
||||||
|
getAll<T extends IPlugin> (type: string): T[] {
|
||||||
|
let plugins = this.plugins[type] || []
|
||||||
|
plugins = plugins.sort((a: IPluginEntry, b: IPluginEntry) => {
|
||||||
|
if (a.weight < b.weight) {
|
||||||
|
return -1
|
||||||
|
} else if (a.weight > b.weight) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
return plugins.map((x) => <T>(x.plugin))
|
||||||
|
}
|
||||||
|
|
||||||
|
emit (type: string, event: string, parameters: any[]) {
|
||||||
|
(this.plugins[type] || []).forEach((entry) => {
|
||||||
|
if (entry.plugin[event]) {
|
||||||
|
entry.plugin[event].bind(entry.plugin)(parameters)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
27
app/src/settings/buttonProvider.ts
Normal file
27
app/src/settings/buttonProvider.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { Injectable } from '@angular/core'
|
||||||
|
import { IToolbarButtonProvider, IToolbarButton, AppService } from 'api'
|
||||||
|
import { SettingsTab } from './tab'
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ButtonProvider implements IToolbarButtonProvider {
|
||||||
|
constructor (
|
||||||
|
private app: AppService,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
provide (): IToolbarButton[] {
|
||||||
|
return [{
|
||||||
|
icon: 'cog',
|
||||||
|
title: 'Settings',
|
||||||
|
weight: 10,
|
||||||
|
click: () => {
|
||||||
|
let settingsTab = this.app.tabs.find((tab) => tab instanceof SettingsTab)
|
||||||
|
if (settingsTab) {
|
||||||
|
this.app.selectTab(settingsTab)
|
||||||
|
} else {
|
||||||
|
this.app.openTab(new SettingsTab())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
@ -8,9 +8,11 @@ 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 { SettingsPaneComponent } from './components/settingsPane'
|
import { SettingsPaneComponent } from './components/settingsPane'
|
||||||
import { PluginDispatcherService } from 'services/pluginDispatcher'
|
|
||||||
|
|
||||||
import { SettingsTab } from './tab'
|
import { PluginsService, ToolbarButtonProviderType } from 'api'
|
||||||
|
|
||||||
|
import { ButtonProvider } from './buttonProvider'
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -19,6 +21,7 @@ import { SettingsTab } from './tab'
|
|||||||
NgbModule,
|
NgbModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
ButtonProvider,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
HotkeyInputModalComponent,
|
HotkeyInputModalComponent,
|
||||||
@ -33,8 +36,8 @@ import { SettingsTab } from './tab'
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
class SettingsModule {
|
class SettingsModule {
|
||||||
constructor (pluginDispatcher: PluginDispatcherService) {
|
constructor (plugins: PluginsService, buttonProvider: ButtonProvider) {
|
||||||
pluginDispatcher.temp = SettingsTab
|
plugins.register(ToolbarButtonProviderType, buttonProvider, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
app/src/terminal/buttonProvider.ts
Normal file
26
app/src/terminal/buttonProvider.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { Injectable } from '@angular/core'
|
||||||
|
import { IToolbarButtonProvider, IToolbarButton, AppService } from 'api'
|
||||||
|
import { SessionsService } from './services/sessions'
|
||||||
|
import { TerminalTab } from './tab'
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ButtonProvider implements IToolbarButtonProvider {
|
||||||
|
constructor (
|
||||||
|
private app: AppService,
|
||||||
|
private sessions: SessionsService,
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
provide (): IToolbarButton[] {
|
||||||
|
return [{
|
||||||
|
icon: 'plus',
|
||||||
|
title: 'New terminal',
|
||||||
|
click: () => {
|
||||||
|
let session = this.sessions.createNewSession({ command: 'zsh' })
|
||||||
|
this.app.openTab(new TerminalTab(session))
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@ import { Subscription } from 'rxjs'
|
|||||||
import { Component, NgZone, Output, EventEmitter, ElementRef } from '@angular/core'
|
import { Component, NgZone, Output, EventEmitter, ElementRef } from '@angular/core'
|
||||||
|
|
||||||
import { ConfigService } from 'services/config'
|
import { ConfigService } from 'services/config'
|
||||||
import { PluginDispatcherService } from 'services/pluginDispatcher'
|
import { PluginsService } from 'services/plugins'
|
||||||
|
|
||||||
import { BaseTabComponent } from 'components/baseTab'
|
import { BaseTabComponent } from 'components/baseTab'
|
||||||
import { TerminalTab } from '../tab'
|
import { TerminalTab } from '../tab'
|
||||||
@ -27,7 +27,7 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
|||||||
private zone: NgZone,
|
private zone: NgZone,
|
||||||
private elementRef: ElementRef,
|
private elementRef: ElementRef,
|
||||||
public config: ConfigService,
|
public config: ConfigService,
|
||||||
private pluginDispatcher: PluginDispatcherService,
|
private plugins: PluginsService,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
this.startupTime = performance.now()
|
this.startupTime = performance.now()
|
||||||
@ -42,7 +42,7 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.terminal = new hterm.hterm.Terminal()
|
this.terminal = new hterm.hterm.Terminal()
|
||||||
this.pluginDispatcher.emit('preTerminalInit', { terminal: this.terminal })
|
//this.pluginDispatcher.emit('preTerminalInit', { terminal: this.terminal })
|
||||||
this.terminal.setWindowTitle = (title) => {
|
this.terminal.setWindowTitle = (title) => {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
this.title = title
|
this.title = title
|
||||||
@ -77,7 +77,7 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
|||||||
}
|
}
|
||||||
this.terminal.decorate(this.elementRef.nativeElement)
|
this.terminal.decorate(this.elementRef.nativeElement)
|
||||||
this.configure()
|
this.configure()
|
||||||
this.pluginDispatcher.emit('postTerminalInit', { terminal: this.terminal })
|
//this.pluginDispatcher.emit('postTerminalInit', { terminal: this.terminal })
|
||||||
}
|
}
|
||||||
|
|
||||||
configure () {
|
configure () {
|
||||||
|
@ -2,11 +2,11 @@ import { BrowserModule } from '@angular/platform-browser'
|
|||||||
import { NgModule } from '@angular/core'
|
import { NgModule } from '@angular/core'
|
||||||
import { FormsModule } from '@angular/forms'
|
import { FormsModule } from '@angular/forms'
|
||||||
|
|
||||||
|
import { PluginsService, ToolbarButtonProviderType } from 'api'
|
||||||
|
|
||||||
import { TerminalTabComponent } from './components/terminalTab'
|
import { TerminalTabComponent } from './components/terminalTab'
|
||||||
import { SessionsService } from './services/sessions'
|
import { SessionsService } from './services/sessions'
|
||||||
import { TerminalTab } from './tab'
|
import { ButtonProvider } from './buttonProvider'
|
||||||
|
|
||||||
import { PluginDispatcherService } from 'services/pluginDispatcher'
|
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -15,6 +15,7 @@ import { PluginDispatcherService } from 'services/pluginDispatcher'
|
|||||||
FormsModule,
|
FormsModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
ButtonProvider,
|
||||||
SessionsService,
|
SessionsService,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
@ -25,11 +26,8 @@ import { PluginDispatcherService } from 'services/pluginDispatcher'
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
class TerminalModule {
|
class TerminalModule {
|
||||||
constructor (pluginDispatcher: PluginDispatcherService, sessions: SessionsService) {
|
constructor (plugins: PluginsService, buttonProvider: ButtonProvider) {
|
||||||
pluginDispatcher.temp2 = (command) => {
|
plugins.register(ToolbarButtonProviderType, buttonProvider)
|
||||||
let session = sessions.createNewSession({ command }))
|
|
||||||
return new TerminalTab(session)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user