mirror of
https://github.com/Eugeny/tabby
synced 2024-11-14 08:57:21 +00:00
.
This commit is contained in:
parent
739750e8f0
commit
384716417a
18 changed files with 148 additions and 40 deletions
|
@ -1,20 +0,0 @@
|
|||
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'
|
6
app/src/api/index.ts
Normal file
6
app/src/api/index.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export { Tab } from './tab'
|
||||
export { TabRecoveryProviderType, ITabRecoveryProvider } from './tabRecovery'
|
||||
export { ToolbarButtonProviderType, IToolbarButton, IToolbarButtonProvider } from './toolbarButtonProvider'
|
||||
|
||||
export { AppService } from 'services/app'
|
||||
export { PluginsService } from 'services/plugins'
|
|
@ -23,4 +23,8 @@ export class Tab {
|
|||
getComponentType (): ComponentType<Tab> {
|
||||
return null
|
||||
}
|
||||
|
||||
getRecoveryToken (): any {
|
||||
return null
|
||||
}
|
||||
}
|
7
app/src/api/tabRecovery.ts
Normal file
7
app/src/api/tabRecovery.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { Tab } from './tab'
|
||||
|
||||
export interface ITabRecoveryProvider {
|
||||
recover (recoveryToken: any): Tab
|
||||
}
|
||||
|
||||
export const TabRecoveryProviderType = 'app:TabRecoveryProviderType'
|
12
app/src/api/toolbarButtonProvider.ts
Normal file
12
app/src/api/toolbarButtonProvider.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
export interface IToolbarButton {
|
||||
icon: string
|
||||
title: string
|
||||
weight?: number
|
||||
click: () => void
|
||||
}
|
||||
|
||||
export interface IToolbarButtonProvider {
|
||||
provide (): IToolbarButton[]
|
||||
}
|
||||
|
||||
export const ToolbarButtonProviderType = 'app:ToolbarButtonProviderType'
|
|
@ -123,6 +123,8 @@ export class AppRootComponent {
|
|||
}
|
||||
this.docking.dock()
|
||||
})
|
||||
|
||||
this.app.restoreTabs()
|
||||
}
|
||||
|
||||
getToolbarButtons (aboveZero: boolean): IToolbarButton[] {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Tab } from 'models/tab'
|
||||
import { Tab } from 'api/tab'
|
||||
|
||||
export class BaseTabComponent<T extends Tab> {
|
||||
protected model: T
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Component, Input, ViewContainerRef, ViewChild, HostBinding, ComponentFactoryResolver, ComponentRef } from '@angular/core'
|
||||
import { Tab } from 'models/tab'
|
||||
import { Tab } from 'api/tab'
|
||||
import { BaseTabComponent } from 'components/baseTab'
|
||||
|
||||
@Component({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Component, Input, Output, EventEmitter, HostBinding } from '@angular/core'
|
||||
import { Tab } from 'models/tab'
|
||||
import { Tab } from 'api/tab'
|
||||
|
||||
import './tabHeader.scss'
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import { EventEmitter, Injectable } from '@angular/core'
|
||||
import { Tab } from 'models/tab'
|
||||
import { 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'
|
||||
|
||||
|
||||
@Injectable()
|
||||
|
@ -7,14 +10,19 @@ export class AppService {
|
|||
tabs: Tab[] = []
|
||||
activeTab: Tab
|
||||
lastTabIndex = 0
|
||||
logger: Logger
|
||||
|
||||
constructor () {
|
||||
|
||||
constructor (
|
||||
private plugins: PluginsService,
|
||||
log: LogService,
|
||||
) {
|
||||
this.logger = log.create('app')
|
||||
}
|
||||
|
||||
openTab (tab: Tab): void {
|
||||
this.tabs.push(tab)
|
||||
this.selectTab(tab)
|
||||
this.saveTabs()
|
||||
}
|
||||
|
||||
selectTab (tab) {
|
||||
|
@ -62,5 +70,33 @@ export class AppService {
|
|||
if (tab == this.activeTab) {
|
||||
this.selectTab(this.tabs[newIndex])
|
||||
}
|
||||
this.saveTabs()
|
||||
}
|
||||
|
||||
saveTabs () {
|
||||
window.localStorage.tabsRecovery = JSON.stringify(
|
||||
this.tabs
|
||||
.map((tab) => tab.getRecoveryToken())
|
||||
.filter((token) => !!token)
|
||||
)
|
||||
}
|
||||
|
||||
restoreTabs () {
|
||||
if (window.localStorage.tabsRecovery) {
|
||||
let providers = this.plugins.getAll<ITabRecoveryProvider>(TabRecoveryProviderType)
|
||||
JSON.parse(window.localStorage.tabsRecovery).forEach((token) => {
|
||||
for (let provider of providers) {
|
||||
try {
|
||||
let tab = provider.recover(token)
|
||||
if (tab) {
|
||||
this.openTab(tab)
|
||||
return
|
||||
}
|
||||
} catch (_) { }
|
||||
this.logger.warn('Cannot restore tab from the token:', token)
|
||||
}
|
||||
})
|
||||
this.saveTabs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,8 @@ export class Logger {
|
|||
private name: string,
|
||||
) {}
|
||||
|
||||
log(level: string, ...args: any[]) {
|
||||
args.splice(0, 0, this.name + ':')
|
||||
console[level](...args)
|
||||
log (level: string, ...args: any[]) {
|
||||
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
|
||||
}
|
||||
|
||||
debug(...args: any[]) { this.log('debug', ...args) }
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { IPlugin } from 'api'
|
||||
import { Injectable } from '@angular/core'
|
||||
|
||||
|
||||
interface IPluginEntry {
|
||||
plugin: IPlugin
|
||||
plugin: any
|
||||
weight: number
|
||||
}
|
||||
|
||||
|
@ -15,14 +14,14 @@ export class PluginsService {
|
|||
) {
|
||||
}
|
||||
|
||||
register (type: string, plugin: IPlugin, weight = 0): void {
|
||||
register (type: string, plugin: any, weight = 0): void {
|
||||
if (!this.plugins[type]) {
|
||||
this.plugins[type] = []
|
||||
}
|
||||
this.plugins[type].push({ plugin, weight })
|
||||
}
|
||||
|
||||
getAll<T extends IPlugin> (type: string): T[] {
|
||||
getAll<T> (type: string): T[] {
|
||||
let plugins = this.plugins[type] || []
|
||||
plugins = plugins.sort((a: IPluginEntry, b: IPluginEntry) => {
|
||||
if (a.weight < b.weight) {
|
||||
|
|
|
@ -9,9 +9,10 @@ import { HotkeyHintComponent } from './components/hotkeyHint'
|
|||
import { HotkeyInputModalComponent } from './components/hotkeyInputModal'
|
||||
import { SettingsPaneComponent } from './components/settingsPane'
|
||||
|
||||
import { PluginsService, ToolbarButtonProviderType } from 'api'
|
||||
import { PluginsService, ToolbarButtonProviderType, TabRecoveryProviderType } from 'api'
|
||||
|
||||
import { ButtonProvider } from './buttonProvider'
|
||||
import { RecoveryProvider } from './recoveryProvider'
|
||||
|
||||
|
||||
@NgModule({
|
||||
|
@ -22,6 +23,7 @@ import { ButtonProvider } from './buttonProvider'
|
|||
],
|
||||
providers: [
|
||||
ButtonProvider,
|
||||
RecoveryProvider,
|
||||
],
|
||||
entryComponents: [
|
||||
HotkeyInputModalComponent,
|
||||
|
@ -36,8 +38,13 @@ import { ButtonProvider } from './buttonProvider'
|
|||
],
|
||||
})
|
||||
class SettingsModule {
|
||||
constructor (plugins: PluginsService, buttonProvider: ButtonProvider) {
|
||||
constructor (
|
||||
plugins: PluginsService,
|
||||
buttonProvider: ButtonProvider,
|
||||
recoveryProvider: RecoveryProvider,
|
||||
) {
|
||||
plugins.register(ToolbarButtonProviderType, buttonProvider, 1)
|
||||
plugins.register(TabRecoveryProviderType, recoveryProvider)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
14
app/src/settings/recoveryProvider.ts
Normal file
14
app/src/settings/recoveryProvider.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { Injectable } from '@angular/core'
|
||||
import { Tab, ITabRecoveryProvider } from 'api'
|
||||
import { SettingsTab } from './tab'
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class RecoveryProvider implements ITabRecoveryProvider {
|
||||
recover (recoveryToken: any): Tab {
|
||||
if (recoveryToken.type == 'app:settings') {
|
||||
return new SettingsTab()
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { Tab, ComponentType } from '../models/tab'
|
||||
import { Tab, ComponentType } from 'api/tab'
|
||||
import { SettingsPaneComponent } from './components/settingsPane'
|
||||
|
||||
export class SettingsTab extends Tab {
|
||||
|
@ -11,4 +11,10 @@ export class SettingsTab extends Tab {
|
|||
getComponentType (): ComponentType<SettingsTab> {
|
||||
return SettingsPaneComponent
|
||||
}
|
||||
|
||||
getRecoveryToken (): any {
|
||||
return {
|
||||
type: 'app:settings',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,12 @@ import { BrowserModule } from '@angular/platform-browser'
|
|||
import { NgModule } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
|
||||
import { PluginsService, ToolbarButtonProviderType } from 'api'
|
||||
import { PluginsService, ToolbarButtonProviderType, TabRecoveryProviderType } from 'api'
|
||||
|
||||
import { TerminalTabComponent } from './components/terminalTab'
|
||||
import { SessionsService } from './services/sessions'
|
||||
import { ButtonProvider } from './buttonProvider'
|
||||
import { RecoveryProvider } from './recoveryProvider'
|
||||
|
||||
|
||||
@NgModule({
|
||||
|
@ -17,6 +18,7 @@ import { ButtonProvider } from './buttonProvider'
|
|||
providers: [
|
||||
ButtonProvider,
|
||||
SessionsService,
|
||||
RecoveryProvider,
|
||||
],
|
||||
entryComponents: [
|
||||
TerminalTabComponent,
|
||||
|
@ -26,8 +28,13 @@ import { ButtonProvider } from './buttonProvider'
|
|||
],
|
||||
})
|
||||
class TerminalModule {
|
||||
constructor (plugins: PluginsService, buttonProvider: ButtonProvider) {
|
||||
constructor (
|
||||
plugins: PluginsService,
|
||||
buttonProvider: ButtonProvider,
|
||||
recoveryProvider: RecoveryProvider,
|
||||
) {
|
||||
plugins.register(ToolbarButtonProviderType, buttonProvider)
|
||||
plugins.register(TabRecoveryProviderType, recoveryProvider)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
20
app/src/terminal/recoveryProvider.ts
Normal file
20
app/src/terminal/recoveryProvider.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { Injectable } from '@angular/core'
|
||||
import { Tab, ITabRecoveryProvider } from 'api'
|
||||
import { TerminalTab } from './tab'
|
||||
import { SessionsService } from './services/sessions'
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class RecoveryProvider implements ITabRecoveryProvider {
|
||||
constructor (private sessions: SessionsService) { }
|
||||
|
||||
recover (recoveryToken: any): Tab {
|
||||
if (recoveryToken.type == 'app:terminal') {
|
||||
const options = this.sessions.recoveryProvider.getRecoverySession(recoveryToken.recoveryId)
|
||||
let session = this.sessions.createSession(options)
|
||||
session.recoveryId = recoveryToken.recoveryId
|
||||
return new TerminalTab(session)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
import { Tab, ComponentType } from '../models/tab'
|
||||
import { Tab, ComponentType } from 'api/tab'
|
||||
import { TerminalTabComponent } from './components/terminalTab'
|
||||
import { Session } from './services/sessions'
|
||||
|
||||
|
||||
export class TerminalTab extends Tab {
|
||||
static recoveryId = 'app:terminal'
|
||||
|
||||
constructor (public session: Session) {
|
||||
super()
|
||||
}
|
||||
|
@ -11,4 +13,11 @@ export class TerminalTab extends Tab {
|
|||
getComponentType (): ComponentType<TerminalTab> {
|
||||
return TerminalTabComponent
|
||||
}
|
||||
|
||||
getRecoveryToken (): any {
|
||||
return {
|
||||
type: 'app:terminal',
|
||||
recoveryId: this.session.recoveryId,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue