mirror of
https://github.com/Eugeny/tabby
synced 2024-11-14 08:57:21 +00:00
.
This commit is contained in:
parent
384716417a
commit
b7bac490d2
19 changed files with 239 additions and 204 deletions
|
@ -1,6 +1,7 @@
|
|||
export { Tab } from './tab'
|
||||
export { TabRecoveryProviderType, ITabRecoveryProvider } from './tabRecovery'
|
||||
export { ToolbarButtonProviderType, IToolbarButton, IToolbarButtonProvider } from './toolbarButtonProvider'
|
||||
export { TabRecoveryProvider } from './tabRecovery'
|
||||
export { ToolbarButtonProvider, IToolbarButton } from './toolbarButtonProvider'
|
||||
|
||||
export { AppService } from 'services/app'
|
||||
export { PluginsService } from 'services/plugins'
|
||||
export { ElectronService } from 'services/electron'
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { Tab } from './tab'
|
||||
|
||||
export interface ITabRecoveryProvider {
|
||||
recover (recoveryToken: any): Tab
|
||||
export abstract class TabRecoveryProvider {
|
||||
abstract recover (recoveryToken: any): Tab
|
||||
}
|
||||
|
||||
export const TabRecoveryProviderType = 'app:TabRecoveryProviderType'
|
||||
|
|
|
@ -5,8 +5,6 @@ export interface IToolbarButton {
|
|||
click: () => void
|
||||
}
|
||||
|
||||
export interface IToolbarButtonProvider {
|
||||
provide (): IToolbarButton[]
|
||||
export abstract class ToolbarButtonProvider {
|
||||
abstract provide (): IToolbarButton[]
|
||||
}
|
||||
|
||||
export const ToolbarButtonProviderType = 'app:ToolbarButtonProviderType'
|
||||
|
|
|
@ -27,6 +27,7 @@ import { TitleBarComponent } from 'components/titleBar'
|
|||
let plugins = [
|
||||
require('./settings').default,
|
||||
require('./terminal').default,
|
||||
require('./link-highlighter').default,
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, trigger, style, animate, transition, state } from '@angular/core'
|
||||
import { Component, Inject, trigger, style, animate, transition, state } from '@angular/core'
|
||||
import { ToasterConfig } from 'angular2-toaster'
|
||||
|
||||
import { ElectronService } from 'services/electron'
|
||||
|
@ -8,9 +8,8 @@ import { LogService } from 'services/log'
|
|||
import { QuitterService } from 'services/quitter'
|
||||
import { ConfigService } from 'services/config'
|
||||
import { DockingService } from 'services/docking'
|
||||
import { PluginsService } from 'services/plugins'
|
||||
|
||||
import { AppService, IToolbarButton, IToolbarButtonProvider, ToolbarButtonProviderType } from 'api'
|
||||
import { AppService, IToolbarButton, ToolbarButtonProvider } from 'api'
|
||||
|
||||
import 'angular2-toaster/lib/toaster.css'
|
||||
import 'global.less'
|
||||
|
@ -49,8 +48,8 @@ export class AppRootComponent {
|
|||
public hostApp: HostAppService,
|
||||
public hotkeys: HotkeysService,
|
||||
public config: ConfigService,
|
||||
private plugins: PluginsService,
|
||||
public app: AppService,
|
||||
@Inject(ToolbarButtonProvider) private toolbarButtonProviders: ToolbarButtonProvider[],
|
||||
log: LogService,
|
||||
_quitter: QuitterService,
|
||||
) {
|
||||
|
@ -129,10 +128,9 @@ export class AppRootComponent {
|
|||
|
||||
getToolbarButtons (aboveZero: boolean): IToolbarButton[] {
|
||||
let buttons: IToolbarButton[] = []
|
||||
this.plugins.getAll<IToolbarButtonProvider>(ToolbarButtonProviderType)
|
||||
.forEach((provider) => {
|
||||
buttons = buttons.concat(provider.provide())
|
||||
})
|
||||
this.toolbarButtonProviders.forEach((provider) => {
|
||||
buttons = buttons.concat(provider.provide())
|
||||
})
|
||||
return buttons
|
||||
.filter((button) => (button.weight > 0) === aboveZero)
|
||||
.sort((a: IToolbarButton, b: IToolbarButton) => (a.weight || 0) - (b.weight || 0))
|
||||
|
|
6
app/src/link-highlighter/api.ts
Normal file
6
app/src/link-highlighter/api.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export abstract class LinkHandler {
|
||||
regex: string
|
||||
convert (uri: string): string { return uri }
|
||||
verify (_uri: string): boolean { return true }
|
||||
abstract handle (uri: string): void
|
||||
}
|
126
app/src/link-highlighter/decorator.ts
Normal file
126
app/src/link-highlighter/decorator.ts
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
This plugin is based on Hyperterm Hyperlinks:
|
||||
https://github.com/zeit/hyperlinks/blob/master/index.js
|
||||
*/
|
||||
|
||||
import { Inject, Injectable } from '@angular/core'
|
||||
import { LinkHandler } from './api'
|
||||
import { TerminalDecorator } from '../terminal/api'
|
||||
|
||||
const debounceDelay = 500
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class LinkHighlighterDecorator extends TerminalDecorator {
|
||||
constructor (@Inject(LinkHandler) private handlers: LinkHandler[]) {
|
||||
super()
|
||||
}
|
||||
|
||||
decorate (terminal): void {
|
||||
const Screen = terminal.screen_.constructor
|
||||
if (Screen._linkHighlighterInstalled) {
|
||||
return
|
||||
}
|
||||
Screen._linkHighlighterInstalled = true
|
||||
|
||||
const oldInsertString = Screen.prototype.insertString
|
||||
const oldDeleteChars = Screen.prototype.deleteChars
|
||||
let self = this
|
||||
Screen.prototype.insertString = function (...args) {
|
||||
let ret = oldInsertString.bind(this)(...args)
|
||||
self.debounceInsertLinks(this)
|
||||
return ret
|
||||
}
|
||||
Screen.prototype.deleteChars = function (...args) {
|
||||
let ret = oldDeleteChars.bind(this)(...args)
|
||||
self.debounceInsertLinks(this)
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
debounceInsertLinks (screen) {
|
||||
if (screen.__insertLinksTimeout) {
|
||||
screen.__insertLinksRebounce = true
|
||||
} else {
|
||||
screen.__insertLinksTimeout = window.setTimeout(() => {
|
||||
this.insertLinks(screen)
|
||||
screen.__insertLinksTimeout = null
|
||||
if (screen.__insertLinksRebounce) {
|
||||
screen.__insertLinksRebounce = false
|
||||
this.debounceInsertLinks(screen)
|
||||
}
|
||||
}, debounceDelay)
|
||||
}
|
||||
}
|
||||
|
||||
insertLinks (screen) {
|
||||
if ('#text' === screen.cursorNode_.nodeName) {
|
||||
// replace text node to element
|
||||
const cursorNode = document.createElement('span');
|
||||
cursorNode.textContent = screen.cursorNode_.textContent;
|
||||
screen.cursorRowNode_.replaceChild(cursorNode, screen.cursorNode_);
|
||||
screen.cursorNode_ = cursorNode;
|
||||
}
|
||||
|
||||
const traverse = (parentNode: Node) => {
|
||||
Array.from(parentNode.childNodes).forEach((node) => {
|
||||
if (node.nodeName == '#text') {
|
||||
parentNode.replaceChild(this.urlizeNode(node), node)
|
||||
} else if (node.nodeName != 'A') {
|
||||
traverse(node)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
screen.rowsArray.forEach((x) => traverse(x))
|
||||
}
|
||||
|
||||
urlizeNode (node) {
|
||||
let matches = []
|
||||
this.handlers.forEach((handler) => {
|
||||
let regex = new RegExp(handler.regex, 'gi')
|
||||
let match
|
||||
while (match = regex.exec(node.textContent)) {
|
||||
let uri = handler.convert(match[0])
|
||||
if (!handler.verify(uri)) {
|
||||
continue;
|
||||
}
|
||||
matches.push({
|
||||
start: regex.lastIndex - match[0].length,
|
||||
end: regex.lastIndex,
|
||||
text: match[0],
|
||||
uri,
|
||||
handler
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (matches.length == 0) {
|
||||
return node
|
||||
}
|
||||
|
||||
matches.sort((a, b) => a.start < b.start ? -1 : 1)
|
||||
|
||||
let span = document.createElement('span')
|
||||
let position = 0
|
||||
matches.forEach((match) => {
|
||||
if (match.start < position) {
|
||||
return
|
||||
}
|
||||
if (match.start > position) {
|
||||
span.appendChild(document.createTextNode(node.textContent.slice(position, match.start)))
|
||||
}
|
||||
|
||||
let a = document.createElement('a')
|
||||
a.textContent = match.text
|
||||
a.addEventListener('click', () => {
|
||||
match.handler.handle(match.uri)
|
||||
})
|
||||
span.appendChild(a)
|
||||
|
||||
position = match.end
|
||||
})
|
||||
span.appendChild(document.createTextNode(node.textContent.slice(position)))
|
||||
return span
|
||||
}
|
||||
}
|
36
app/src/link-highlighter/handlers.ts
Normal file
36
app/src/link-highlighter/handlers.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import * as fs from 'fs'
|
||||
|
||||
import { Injectable } from '@angular/core'
|
||||
import { LinkHandler } from './api'
|
||||
import { ElectronService } from 'api'
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class URLHandler extends LinkHandler {
|
||||
regex = 'http(s)?://[^\\s;\'"]+[^,;\\s]'
|
||||
|
||||
constructor (private electron: ElectronService) {
|
||||
super()
|
||||
}
|
||||
|
||||
handle (uri: string) {
|
||||
this.electron.shell.openExternal(uri)
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class FileHandler extends LinkHandler {
|
||||
regex = '/[^\\s.,;\'"]+'
|
||||
|
||||
constructor (private electron: ElectronService) {
|
||||
super()
|
||||
}
|
||||
|
||||
verify (uri: string) {
|
||||
return fs.existsSync(uri)
|
||||
}
|
||||
|
||||
handle (uri: string) {
|
||||
this.electron.shell.openExternal('file://' + uri)
|
||||
}
|
||||
}
|
20
app/src/link-highlighter/index.ts
Normal file
20
app/src/link-highlighter/index.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { NgModule } from '@angular/core'
|
||||
|
||||
import { LinkHandler } from './api'
|
||||
import { FileHandler, URLHandler } from './handlers'
|
||||
import { TerminalDecorator } from '../terminal/api'
|
||||
import { LinkHighlighterDecorator } from './decorator'
|
||||
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
{ provide: LinkHandler, useClass: FileHandler, multi: true },
|
||||
{ provide: LinkHandler, useClass: URLHandler, multi: true },
|
||||
{ provide: TerminalDecorator, useClass: LinkHighlighterDecorator, multi: true },
|
||||
],
|
||||
})
|
||||
class LinkHighlighterModule {
|
||||
}
|
||||
|
||||
|
||||
export default LinkHighlighterModule
|
|
@ -1,139 +0,0 @@
|
|||
import * as fs from 'fs'
|
||||
import { ElectronService } from 'services/electron'
|
||||
|
||||
const debounceDelay = 500
|
||||
|
||||
abstract class Handler {
|
||||
constructor (protected plugin) { }
|
||||
regex: string
|
||||
convert (uri: string): string { return uri }
|
||||
verify (_uri: string): boolean { return true }
|
||||
abstract handle (uri: string): void
|
||||
}
|
||||
|
||||
class URLHandler extends Handler {
|
||||
regex = 'http(s)?://[^\\s;\'"]+[^.,;\\s]'
|
||||
|
||||
handle (uri: string) {
|
||||
this.plugin.electron.shell.openExternal(uri)
|
||||
}
|
||||
}
|
||||
|
||||
class FileHandler extends Handler {
|
||||
regex = '/[^\\s.,;\'"]+'
|
||||
|
||||
verify (uri: string) {
|
||||
return fs.existsSync(uri)
|
||||
}
|
||||
|
||||
handle (uri: string) {
|
||||
this.plugin.electron.shell.openExternal('file://' + uri)
|
||||
}
|
||||
}
|
||||
|
||||
export default class HyperlinksPlugin {
|
||||
handlers = []
|
||||
handlerClasses = [
|
||||
URLHandler,
|
||||
FileHandler,
|
||||
]
|
||||
electron: ElectronService
|
||||
|
||||
constructor ({ electron }) {
|
||||
this.electron = electron
|
||||
this.handlers = this.handlerClasses.map((x) => new x(this))
|
||||
}
|
||||
|
||||
preTerminalInit ({ terminal }) {
|
||||
const oldInsertString = terminal.screen_.constructor.prototype.insertString
|
||||
const oldDeleteChars = terminal.screen_.constructor.prototype.deleteChars
|
||||
terminal.screen_.insertString = (...args) => {
|
||||
let ret = oldInsertString.bind(terminal.screen_)(...args)
|
||||
this.debounceInsertLinks(terminal.screen_)
|
||||
return ret
|
||||
}
|
||||
terminal.screen_.deleteChars = (...args) => {
|
||||
let ret = oldDeleteChars.bind(terminal.screen_)(...args)
|
||||
this.debounceInsertLinks(terminal.screen_)
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
debounceInsertLinks (screen) {
|
||||
if (screen.__insertLinksTimeout) {
|
||||
screen.__insertLinksRebounce = true
|
||||
} else {
|
||||
screen.__insertLinksTimeout = window.setTimeout(() => {
|
||||
this.insertLinks(screen)
|
||||
screen.__insertLinksTimeout = null
|
||||
if (screen.__insertLinksRebounce) {
|
||||
screen.__insertLinksRebounce = false
|
||||
this.debounceInsertLinks(screen)
|
||||
}
|
||||
}, debounceDelay)
|
||||
}
|
||||
}
|
||||
|
||||
insertLinks (screen) {
|
||||
const traverse = (parentNode: Node) => {
|
||||
Array.from(parentNode.childNodes).forEach((node) => {
|
||||
if (node.nodeName == '#text') {
|
||||
parentNode.replaceChild(this.urlizeNode(node), node)
|
||||
} else if (node.nodeName != 'A') {
|
||||
traverse(node)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
screen.rowsArray.forEach((x) => traverse(x))
|
||||
}
|
||||
|
||||
urlizeNode (node) {
|
||||
let matches = []
|
||||
this.handlers.forEach((handler) => {
|
||||
let regex = new RegExp(handler.regex, 'gi')
|
||||
let match
|
||||
while (match = regex.exec(node.textContent)) {
|
||||
let uri = handler.convert(match[0])
|
||||
if (!handler.verify(uri)) {
|
||||
continue;
|
||||
}
|
||||
matches.push({
|
||||
start: regex.lastIndex - match[0].length,
|
||||
end: regex.lastIndex,
|
||||
text: match[0],
|
||||
uri,
|
||||
handler
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (matches.length == 0) {
|
||||
return node
|
||||
}
|
||||
|
||||
matches.sort((a, b) => a.start < b.start ? -1 : 1)
|
||||
|
||||
let span = document.createElement('span')
|
||||
let position = 0
|
||||
matches.forEach((match) => {
|
||||
if (match.start < position) {
|
||||
return
|
||||
}
|
||||
if (match.start > position) {
|
||||
span.appendChild(document.createTextNode(node.textContent.slice(position, match.start)))
|
||||
}
|
||||
|
||||
let a = document.createElement('a')
|
||||
a.textContent = match.text
|
||||
a.addEventListener('click', () => {
|
||||
match.handler.handle(match.uri)
|
||||
})
|
||||
span.appendChild(a)
|
||||
|
||||
position = match.end
|
||||
})
|
||||
span.appendChild(document.createTextNode(node.textContent.slice(position)))
|
||||
return span
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
import { Injectable } from '@angular/core'
|
||||
import { Inject, Injectable } from '@angular/core'
|
||||
import { Logger, LogService } from 'services/log'
|
||||
import { Tab } from 'api/tab'
|
||||
import { PluginsService } from 'services/plugins'
|
||||
import { ITabRecoveryProvider, TabRecoveryProviderType } from 'api/tabRecovery'
|
||||
import { TabRecoveryProvider } from 'api/tabRecovery'
|
||||
|
||||
|
||||
@Injectable()
|
||||
|
@ -13,7 +12,7 @@ export class AppService {
|
|||
logger: Logger
|
||||
|
||||
constructor (
|
||||
private plugins: PluginsService,
|
||||
@Inject(TabRecoveryProvider) private tabRecoveryProviders: TabRecoveryProvider[],
|
||||
log: LogService,
|
||||
) {
|
||||
this.logger = log.create('app')
|
||||
|
@ -83,9 +82,8 @@ export class AppService {
|
|||
|
||||
restoreTabs () {
|
||||
if (window.localStorage.tabsRecovery) {
|
||||
let providers = this.plugins.getAll<ITabRecoveryProvider>(TabRecoveryProviderType)
|
||||
JSON.parse(window.localStorage.tabsRecovery).forEach((token) => {
|
||||
for (let provider of providers) {
|
||||
for (let provider of this.tabRecoveryProviders) {
|
||||
try {
|
||||
let tab = provider.recover(token)
|
||||
if (tab) {
|
||||
|
@ -93,8 +91,8 @@ export class AppService {
|
|||
return
|
||||
}
|
||||
} catch (_) { }
|
||||
this.logger.warn('Cannot restore tab from the token:', token)
|
||||
}
|
||||
this.logger.warn('Cannot restore tab from the token:', token)
|
||||
})
|
||||
this.saveTabs()
|
||||
}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
import { Injectable } from '@angular/core'
|
||||
import { IToolbarButtonProvider, IToolbarButton, AppService } from 'api'
|
||||
import { ToolbarButtonProvider, IToolbarButton, AppService } from 'api'
|
||||
import { SettingsTab } from './tab'
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class ButtonProvider implements IToolbarButtonProvider {
|
||||
export class ButtonProvider extends ToolbarButtonProvider {
|
||||
constructor (
|
||||
private app: AppService,
|
||||
) { }
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
provide (): IToolbarButton[] {
|
||||
return [{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import { NgModule } from '@angular/core'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
|
||||
|
@ -9,7 +9,7 @@ import { HotkeyHintComponent } from './components/hotkeyHint'
|
|||
import { HotkeyInputModalComponent } from './components/hotkeyInputModal'
|
||||
import { SettingsPaneComponent } from './components/settingsPane'
|
||||
|
||||
import { PluginsService, ToolbarButtonProviderType, TabRecoveryProviderType } from 'api'
|
||||
import { ToolbarButtonProvider, TabRecoveryProvider } from 'api'
|
||||
|
||||
import { ButtonProvider } from './buttonProvider'
|
||||
import { RecoveryProvider } from './recoveryProvider'
|
||||
|
@ -22,8 +22,8 @@ import { RecoveryProvider } from './recoveryProvider'
|
|||
NgbModule,
|
||||
],
|
||||
providers: [
|
||||
ButtonProvider,
|
||||
RecoveryProvider,
|
||||
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
|
||||
{ provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true }
|
||||
],
|
||||
entryComponents: [
|
||||
HotkeyInputModalComponent,
|
||||
|
@ -38,14 +38,6 @@ import { RecoveryProvider } from './recoveryProvider'
|
|||
],
|
||||
})
|
||||
class SettingsModule {
|
||||
constructor (
|
||||
plugins: PluginsService,
|
||||
buttonProvider: ButtonProvider,
|
||||
recoveryProvider: RecoveryProvider,
|
||||
) {
|
||||
plugins.register(ToolbarButtonProviderType, buttonProvider, 1)
|
||||
plugins.register(TabRecoveryProviderType, recoveryProvider)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Injectable } from '@angular/core'
|
||||
import { Tab, ITabRecoveryProvider } from 'api'
|
||||
import { Tab, TabRecoveryProvider } from 'api'
|
||||
import { SettingsTab } from './tab'
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class RecoveryProvider implements ITabRecoveryProvider {
|
||||
export class RecoveryProvider extends TabRecoveryProvider {
|
||||
recover (recoveryToken: any): Tab {
|
||||
if (recoveryToken.type == 'app:settings') {
|
||||
return new SettingsTab()
|
||||
|
|
3
app/src/terminal/api.ts
Normal file
3
app/src/terminal/api.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export abstract class TerminalDecorator {
|
||||
abstract decorate (terminal): void
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
import { Injectable } from '@angular/core'
|
||||
import { IToolbarButtonProvider, IToolbarButton, AppService } from 'api'
|
||||
import { ToolbarButtonProvider, IToolbarButton, AppService } from 'api'
|
||||
import { SessionsService } from './services/sessions'
|
||||
import { TerminalTab } from './tab'
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class ButtonProvider implements IToolbarButtonProvider {
|
||||
export class ButtonProvider extends ToolbarButtonProvider {
|
||||
constructor (
|
||||
private app: AppService,
|
||||
private sessions: SessionsService,
|
||||
) {
|
||||
|
||||
super()
|
||||
}
|
||||
|
||||
provide (): IToolbarButton[] {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { Subscription } from 'rxjs'
|
||||
import { Component, NgZone, Output, EventEmitter, ElementRef } from '@angular/core'
|
||||
import { Component, NgZone, Output, Inject, EventEmitter, ElementRef } from '@angular/core'
|
||||
|
||||
import { ConfigService } from 'services/config'
|
||||
import { PluginsService } from 'services/plugins'
|
||||
|
||||
import { BaseTabComponent } from 'components/baseTab'
|
||||
import { TerminalTab } from '../tab'
|
||||
import { TerminalDecorator } from '../api'
|
||||
|
||||
import { hterm, preferenceManager } from '../hterm'
|
||||
|
||||
|
@ -27,7 +27,7 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
|||
private zone: NgZone,
|
||||
private elementRef: ElementRef,
|
||||
public config: ConfigService,
|
||||
private plugins: PluginsService,
|
||||
@Inject(TerminalDecorator) private decorators: TerminalDecorator[],
|
||||
) {
|
||||
super()
|
||||
this.startupTime = performance.now()
|
||||
|
@ -42,7 +42,9 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
|||
})
|
||||
|
||||
this.terminal = new hterm.hterm.Terminal()
|
||||
//this.pluginDispatcher.emit('preTerminalInit', { terminal: this.terminal })
|
||||
this.decorators.forEach((decorator) => {
|
||||
decorator.decorate(this.terminal)
|
||||
})
|
||||
this.terminal.setWindowTitle = (title) => {
|
||||
this.zone.run(() => {
|
||||
this.title = title
|
||||
|
@ -77,7 +79,6 @@ export class TerminalTabComponent extends BaseTabComponent<TerminalTab> {
|
|||
}
|
||||
this.terminal.decorate(this.elementRef.nativeElement)
|
||||
this.configure()
|
||||
//this.pluginDispatcher.emit('postTerminalInit', { terminal: this.terminal })
|
||||
}
|
||||
|
||||
configure () {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import { NgModule } from '@angular/core'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
|
||||
import { PluginsService, ToolbarButtonProviderType, TabRecoveryProviderType } from 'api'
|
||||
import { ToolbarButtonProvider, TabRecoveryProvider } from 'api'
|
||||
|
||||
import { TerminalTabComponent } from './components/terminalTab'
|
||||
import { SessionsService } from './services/sessions'
|
||||
|
@ -16,9 +16,9 @@ import { RecoveryProvider } from './recoveryProvider'
|
|||
FormsModule,
|
||||
],
|
||||
providers: [
|
||||
ButtonProvider,
|
||||
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
|
||||
{ provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true },
|
||||
SessionsService,
|
||||
RecoveryProvider,
|
||||
],
|
||||
entryComponents: [
|
||||
TerminalTabComponent,
|
||||
|
@ -28,14 +28,6 @@ import { RecoveryProvider } from './recoveryProvider'
|
|||
],
|
||||
})
|
||||
class TerminalModule {
|
||||
constructor (
|
||||
plugins: PluginsService,
|
||||
buttonProvider: ButtonProvider,
|
||||
recoveryProvider: RecoveryProvider,
|
||||
) {
|
||||
plugins.register(ToolbarButtonProviderType, buttonProvider)
|
||||
plugins.register(TabRecoveryProviderType, recoveryProvider)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import { Injectable } from '@angular/core'
|
||||
import { Tab, ITabRecoveryProvider } from 'api'
|
||||
import { Tab, TabRecoveryProvider } from 'api'
|
||||
import { TerminalTab } from './tab'
|
||||
import { SessionsService } from './services/sessions'
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class RecoveryProvider implements ITabRecoveryProvider {
|
||||
constructor (private sessions: SessionsService) { }
|
||||
export class RecoveryProvider extends TabRecoveryProvider {
|
||||
constructor (private sessions: SessionsService) {
|
||||
super()
|
||||
}
|
||||
|
||||
recover (recoveryToken: any): Tab {
|
||||
if (recoveryToken.type == 'app:terminal') {
|
||||
|
|
Loading…
Reference in a new issue