mirror of
https://github.com/Eugeny/tabby.git
synced 2025-01-03 08:04:02 +03:00
.
This commit is contained in:
parent
739750e8f0
commit
384716417a
@ -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> {
|
getComponentType (): ComponentType<Tab> {
|
||||||
return null
|
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.docking.dock()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.app.restoreTabs()
|
||||||
}
|
}
|
||||||
|
|
||||||
getToolbarButtons (aboveZero: boolean): IToolbarButton[] {
|
getToolbarButtons (aboveZero: boolean): IToolbarButton[] {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Tab } from 'models/tab'
|
import { Tab } from 'api/tab'
|
||||||
|
|
||||||
export class BaseTabComponent<T extends Tab> {
|
export class BaseTabComponent<T extends Tab> {
|
||||||
protected model: T
|
protected model: T
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, ViewContainerRef, ViewChild, HostBinding, ComponentFactoryResolver, ComponentRef } from '@angular/core'
|
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'
|
import { BaseTabComponent } from 'components/baseTab'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, Output, EventEmitter, HostBinding } from '@angular/core'
|
import { Component, Input, Output, EventEmitter, HostBinding } from '@angular/core'
|
||||||
import { Tab } from 'models/tab'
|
import { Tab } from 'api/tab'
|
||||||
|
|
||||||
import './tabHeader.scss'
|
import './tabHeader.scss'
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
import { EventEmitter, Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { Tab } from 'models/tab'
|
import { Logger, LogService } from 'services/log'
|
||||||
|
import { Tab } from 'api/tab'
|
||||||
|
import { PluginsService } from 'services/plugins'
|
||||||
|
import { ITabRecoveryProvider, TabRecoveryProviderType } from 'api/tabRecovery'
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -7,14 +10,19 @@ export class AppService {
|
|||||||
tabs: Tab[] = []
|
tabs: Tab[] = []
|
||||||
activeTab: Tab
|
activeTab: Tab
|
||||||
lastTabIndex = 0
|
lastTabIndex = 0
|
||||||
|
logger: Logger
|
||||||
|
|
||||||
constructor () {
|
constructor (
|
||||||
|
private plugins: PluginsService,
|
||||||
|
log: LogService,
|
||||||
|
) {
|
||||||
|
this.logger = log.create('app')
|
||||||
}
|
}
|
||||||
|
|
||||||
openTab (tab: Tab): void {
|
openTab (tab: Tab): void {
|
||||||
this.tabs.push(tab)
|
this.tabs.push(tab)
|
||||||
this.selectTab(tab)
|
this.selectTab(tab)
|
||||||
|
this.saveTabs()
|
||||||
}
|
}
|
||||||
|
|
||||||
selectTab (tab) {
|
selectTab (tab) {
|
||||||
@ -62,5 +70,33 @@ export class AppService {
|
|||||||
if (tab == this.activeTab) {
|
if (tab == this.activeTab) {
|
||||||
this.selectTab(this.tabs[newIndex])
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,7 @@ export class Logger {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
log (level: string, ...args: any[]) {
|
log (level: string, ...args: any[]) {
|
||||||
args.splice(0, 0, this.name + ':')
|
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
|
||||||
console[level](...args)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(...args: any[]) { this.log('debug', ...args) }
|
debug(...args: any[]) { this.log('debug', ...args) }
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { IPlugin } from 'api'
|
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
|
|
||||||
|
|
||||||
interface IPluginEntry {
|
interface IPluginEntry {
|
||||||
plugin: IPlugin
|
plugin: any
|
||||||
weight: number
|
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]) {
|
if (!this.plugins[type]) {
|
||||||
this.plugins[type] = []
|
this.plugins[type] = []
|
||||||
}
|
}
|
||||||
this.plugins[type].push({ plugin, weight })
|
this.plugins[type].push({ plugin, weight })
|
||||||
}
|
}
|
||||||
|
|
||||||
getAll<T extends IPlugin> (type: string): T[] {
|
getAll<T> (type: string): T[] {
|
||||||
let plugins = this.plugins[type] || []
|
let plugins = this.plugins[type] || []
|
||||||
plugins = plugins.sort((a: IPluginEntry, b: IPluginEntry) => {
|
plugins = plugins.sort((a: IPluginEntry, b: IPluginEntry) => {
|
||||||
if (a.weight < b.weight) {
|
if (a.weight < b.weight) {
|
||||||
|
@ -9,9 +9,10 @@ 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 { PluginsService, ToolbarButtonProviderType } from 'api'
|
import { PluginsService, ToolbarButtonProviderType, TabRecoveryProviderType } from 'api'
|
||||||
|
|
||||||
import { ButtonProvider } from './buttonProvider'
|
import { ButtonProvider } from './buttonProvider'
|
||||||
|
import { RecoveryProvider } from './recoveryProvider'
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -22,6 +23,7 @@ import { ButtonProvider } from './buttonProvider'
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
ButtonProvider,
|
ButtonProvider,
|
||||||
|
RecoveryProvider,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
HotkeyInputModalComponent,
|
HotkeyInputModalComponent,
|
||||||
@ -36,8 +38,13 @@ import { ButtonProvider } from './buttonProvider'
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
class SettingsModule {
|
class SettingsModule {
|
||||||
constructor (plugins: PluginsService, buttonProvider: ButtonProvider) {
|
constructor (
|
||||||
|
plugins: PluginsService,
|
||||||
|
buttonProvider: ButtonProvider,
|
||||||
|
recoveryProvider: RecoveryProvider,
|
||||||
|
) {
|
||||||
plugins.register(ToolbarButtonProviderType, buttonProvider, 1)
|
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'
|
import { SettingsPaneComponent } from './components/settingsPane'
|
||||||
|
|
||||||
export class SettingsTab extends Tab {
|
export class SettingsTab extends Tab {
|
||||||
@ -11,4 +11,10 @@ export class SettingsTab extends Tab {
|
|||||||
getComponentType (): ComponentType<SettingsTab> {
|
getComponentType (): ComponentType<SettingsTab> {
|
||||||
return SettingsPaneComponent
|
return SettingsPaneComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getRecoveryToken (): any {
|
||||||
|
return {
|
||||||
|
type: 'app:settings',
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,12 @@ 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 { PluginsService, ToolbarButtonProviderType, TabRecoveryProviderType } from 'api'
|
||||||
|
|
||||||
import { TerminalTabComponent } from './components/terminalTab'
|
import { TerminalTabComponent } from './components/terminalTab'
|
||||||
import { SessionsService } from './services/sessions'
|
import { SessionsService } from './services/sessions'
|
||||||
import { ButtonProvider } from './buttonProvider'
|
import { ButtonProvider } from './buttonProvider'
|
||||||
|
import { RecoveryProvider } from './recoveryProvider'
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -17,6 +18,7 @@ import { ButtonProvider } from './buttonProvider'
|
|||||||
providers: [
|
providers: [
|
||||||
ButtonProvider,
|
ButtonProvider,
|
||||||
SessionsService,
|
SessionsService,
|
||||||
|
RecoveryProvider,
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
TerminalTabComponent,
|
TerminalTabComponent,
|
||||||
@ -26,8 +28,13 @@ import { ButtonProvider } from './buttonProvider'
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
class TerminalModule {
|
class TerminalModule {
|
||||||
constructor (plugins: PluginsService, buttonProvider: ButtonProvider) {
|
constructor (
|
||||||
|
plugins: PluginsService,
|
||||||
|
buttonProvider: ButtonProvider,
|
||||||
|
recoveryProvider: RecoveryProvider,
|
||||||
|
) {
|
||||||
plugins.register(ToolbarButtonProviderType, buttonProvider)
|
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 { TerminalTabComponent } from './components/terminalTab'
|
||||||
import { Session } from './services/sessions'
|
import { Session } from './services/sessions'
|
||||||
|
|
||||||
|
|
||||||
export class TerminalTab extends Tab {
|
export class TerminalTab extends Tab {
|
||||||
|
static recoveryId = 'app:terminal'
|
||||||
|
|
||||||
constructor (public session: Session) {
|
constructor (public session: Session) {
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
@ -11,4 +13,11 @@ export class TerminalTab extends Tab {
|
|||||||
getComponentType (): ComponentType<TerminalTab> {
|
getComponentType (): ComponentType<TerminalTab> {
|
||||||
return TerminalTabComponent
|
return TerminalTabComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getRecoveryToken (): any {
|
||||||
|
return {
|
||||||
|
type: 'app:terminal',
|
||||||
|
recoveryId: this.session.recoveryId,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user