mirror of
https://github.com/Eugeny/tabby.git
synced 2025-07-24 04:17:59 +00:00
don't include tab state in saved layouts
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
export { BaseComponent, SubscriptionContainer } from '../components/base.component'
|
export { BaseComponent, SubscriptionContainer } from '../components/base.component'
|
||||||
export { BaseTabComponent, BaseTabProcess } from '../components/baseTab.component'
|
export { BaseTabComponent, BaseTabProcess, GetRecoveryTokenOptions } from '../components/baseTab.component'
|
||||||
export { TabHeaderComponent } from '../components/tabHeader.component'
|
export { TabHeaderComponent } from '../components/tabHeader.component'
|
||||||
export { SplitTabComponent, SplitContainer, SplitDirection, SplitOrientation } from '../components/splitTab.component'
|
export { SplitTabComponent, SplitContainer, SplitDirection, SplitOrientation } from '../components/splitTab.component'
|
||||||
export { TabRecoveryProvider, RecoveryToken } from './tabRecovery'
|
export { TabRecoveryProvider, RecoveryToken } from './tabRecovery'
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import deepClone from 'clone-deep'
|
|
||||||
import { BaseTabComponent } from '../components/baseTab.component'
|
import { BaseTabComponent } from '../components/baseTab.component'
|
||||||
import { NewTabParameters } from '../services/tabs.service'
|
import { NewTabParameters } from '../services/tabs.service'
|
||||||
|
|
||||||
@@ -38,14 +37,4 @@ export abstract class TabRecoveryProvider <T extends BaseTabComponent> {
|
|||||||
* or `null` if this token is from a different tab type or is not supported
|
* or `null` if this token is from a different tab type or is not supported
|
||||||
*/
|
*/
|
||||||
abstract recover (recoveryToken: RecoveryToken): Promise<NewTabParameters<T>>
|
abstract recover (recoveryToken: RecoveryToken): Promise<NewTabParameters<T>>
|
||||||
|
|
||||||
/**
|
|
||||||
* @param recoveryToken a recovery token found in the saved tabs list
|
|
||||||
* @returns [[RecoveryToken]] a new recovery token to create the duplicate tab from
|
|
||||||
*
|
|
||||||
* The default implementation just returns a deep copy of the original token
|
|
||||||
*/
|
|
||||||
duplicate (recoveryToken: RecoveryToken): RecoveryToken {
|
|
||||||
return deepClone(recoveryToken)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,10 @@ export interface BaseTabProcess {
|
|||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GetRecoveryTokenOptions {
|
||||||
|
includeState: boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for custom tab components
|
* Abstract base class for custom tab components
|
||||||
*/
|
*/
|
||||||
@@ -136,7 +140,7 @@ export abstract class BaseTabComponent extends BaseComponent {
|
|||||||
* @return JSON serializable tab state representation
|
* @return JSON serializable tab state representation
|
||||||
* for your [[TabRecoveryProvider]] to parse
|
* for your [[TabRecoveryProvider]] to parse
|
||||||
*/
|
*/
|
||||||
async getRecoveryToken (): Promise<RecoveryToken|null> {
|
async getRecoveryToken (options?: GetRecoveryTokenOptions): Promise<RecoveryToken|null> { // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Observable, Subject } from 'rxjs'
|
import { Observable, Subject } from 'rxjs'
|
||||||
import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, AfterViewInit, OnDestroy } from '@angular/core'
|
import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, AfterViewInit, OnDestroy } from '@angular/core'
|
||||||
import { BaseTabComponent, BaseTabProcess } from './baseTab.component'
|
import { BaseTabComponent, BaseTabProcess, GetRecoveryTokenOptions } from './baseTab.component'
|
||||||
import { TabRecoveryProvider, RecoveryToken } from '../api/tabRecovery'
|
import { TabRecoveryProvider, RecoveryToken } from '../api/tabRecovery'
|
||||||
import { TabsService, NewTabParameters } from '../services/tabs.service'
|
import { TabsService, NewTabParameters } from '../services/tabs.service'
|
||||||
import { HotkeysService } from '../services/hotkeys.service'
|
import { HotkeysService } from '../services/hotkeys.service'
|
||||||
@@ -93,13 +93,13 @@ export class SplitContainer {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
async serialize (tabsRecovery: TabRecoveryService): Promise<RecoveryToken> {
|
async serialize (tabsRecovery: TabRecoveryService, options?: GetRecoveryTokenOptions): Promise<RecoveryToken> {
|
||||||
const children: any[] = []
|
const children: any[] = []
|
||||||
for (const child of this.children) {
|
for (const child of this.children) {
|
||||||
if (child instanceof SplitContainer) {
|
if (child instanceof SplitContainer) {
|
||||||
children.push(await child.serialize(tabsRecovery))
|
children.push(await child.serialize(tabsRecovery, options))
|
||||||
} else {
|
} else {
|
||||||
children.push(await tabsRecovery.getFullRecoveryToken(child))
|
children.push(await tabsRecovery.getFullRecoveryToken(child, options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -308,7 +308,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
async ngAfterViewInit (): Promise<void> {
|
async ngAfterViewInit (): Promise<void> {
|
||||||
if (this._recoveredState) {
|
if (this._recoveredState) {
|
||||||
await this.recoverContainer(this.root, this._recoveredState, this._recoveredState.duplicate)
|
await this.recoverContainer(this.root, this._recoveredState)
|
||||||
this.updateTitle()
|
this.updateTitle()
|
||||||
this.layout()
|
this.layout()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -574,8 +574,8 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
async getRecoveryToken (): Promise<any> {
|
async getRecoveryToken (options?: GetRecoveryTokenOptions): Promise<any> {
|
||||||
return this.root.serialize(this.tabRecovery)
|
return this.root.serialize(this.tabRecovery, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
@@ -795,7 +795,7 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private async recoverContainer (root: SplitContainer, state: any, duplicate = false) {
|
private async recoverContainer (root: SplitContainer, state: any) {
|
||||||
const children: (SplitContainer | BaseTabComponent)[] = []
|
const children: (SplitContainer | BaseTabComponent)[] = []
|
||||||
root.orientation = state.orientation
|
root.orientation = state.orientation
|
||||||
root.ratios = state.ratios
|
root.ratios = state.ratios
|
||||||
@@ -806,10 +806,10 @@ export class SplitTabComponent extends BaseTabComponent implements AfterViewInit
|
|||||||
}
|
}
|
||||||
if (childState.type === 'app:split-tab') {
|
if (childState.type === 'app:split-tab') {
|
||||||
const child = new SplitContainer()
|
const child = new SplitContainer()
|
||||||
await this.recoverContainer(child, childState, duplicate)
|
await this.recoverContainer(child, childState)
|
||||||
children.push(child)
|
children.push(child)
|
||||||
} else {
|
} else {
|
||||||
const recovered = await this.tabRecovery.recoverTab(childState, duplicate)
|
const recovered = await this.tabRecovery.recoverTab(childState)
|
||||||
if (recovered) {
|
if (recovered) {
|
||||||
const tab = this.tabsService.create(recovered)
|
const tab = this.tabsService.create(recovered)
|
||||||
children.push(tab)
|
children.push(tab)
|
||||||
@@ -840,11 +840,4 @@ export class SplitTabRecoveryProvider extends TabRecoveryProvider<SplitTabCompon
|
|||||||
inputs: { _recoveredState: recoveryToken },
|
inputs: { _recoveredState: recoveryToken },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
duplicate (recoveryToken: RecoveryToken): RecoveryToken {
|
|
||||||
return {
|
|
||||||
...recoveryToken,
|
|
||||||
duplicate: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -44,7 +44,7 @@ export class SplitLayoutProfilesService extends ProfileProvider<SplitLayoutProfi
|
|||||||
}
|
}
|
||||||
|
|
||||||
async createProfile (tab: SplitTabComponent, name: string): Promise<void> {
|
async createProfile (tab: SplitTabComponent, name: string): Promise<void> {
|
||||||
const token = await tab.getRecoveryToken()
|
const token = await tab.getRecoveryToken({ includeState: false })
|
||||||
const profile: PartialProfile<SplitLayoutProfile> = {
|
const profile: PartialProfile<SplitLayoutProfile> = {
|
||||||
id: `${this.id}:custom:${slugify(name)}:${uuidv4()}`,
|
id: `${this.id}:custom:${slugify(name)}:${uuidv4()}`,
|
||||||
type: this.id,
|
type: this.id,
|
||||||
|
@@ -318,7 +318,7 @@ export class AppService {
|
|||||||
if (checkCanClose && !await tab.canClose()) {
|
if (checkCanClose && !await tab.canClose()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const token = await this.tabRecovery.getFullRecoveryToken(tab)
|
const token = await this.tabRecovery.getFullRecoveryToken(tab, { includeState: true })
|
||||||
if (token) {
|
if (token) {
|
||||||
this.closedTabsStack.push(token)
|
this.closedTabsStack.push(token)
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable, Inject } from '@angular/core'
|
import { Injectable, Inject } from '@angular/core'
|
||||||
import { TabRecoveryProvider, RecoveryToken } from '../api/tabRecovery'
|
import { TabRecoveryProvider, RecoveryToken } from '../api/tabRecovery'
|
||||||
import { BaseTabComponent } from '../components/baseTab.component'
|
import { BaseTabComponent, GetRecoveryTokenOptions } from '../components/baseTab.component'
|
||||||
import { Logger, LogService } from './log.service'
|
import { Logger, LogService } from './log.service'
|
||||||
import { ConfigService } from './config.service'
|
import { ConfigService } from './config.service'
|
||||||
import { NewTabParameters } from './tabs.service'
|
import { NewTabParameters } from './tabs.service'
|
||||||
@@ -25,13 +25,13 @@ export class TabRecoveryService {
|
|||||||
}
|
}
|
||||||
window.localStorage.tabsRecovery = JSON.stringify(
|
window.localStorage.tabsRecovery = JSON.stringify(
|
||||||
(await Promise.all(
|
(await Promise.all(
|
||||||
tabs.map(async tab => this.getFullRecoveryToken(tab))
|
tabs.map(async tab => this.getFullRecoveryToken(tab, { includeState: true }))
|
||||||
)).filter(token => !!token)
|
)).filter(token => !!token)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getFullRecoveryToken (tab: BaseTabComponent): Promise<RecoveryToken|null> {
|
async getFullRecoveryToken (tab: BaseTabComponent, options?: GetRecoveryTokenOptions): Promise<RecoveryToken|null> {
|
||||||
const token = await tab.getRecoveryToken()
|
const token = await tab.getRecoveryToken(options)
|
||||||
if (token) {
|
if (token) {
|
||||||
token.tabTitle = tab.title
|
token.tabTitle = tab.title
|
||||||
token.tabCustomTitle = tab.customTitle
|
token.tabCustomTitle = tab.customTitle
|
||||||
@@ -43,15 +43,12 @@ export class TabRecoveryService {
|
|||||||
return token
|
return token
|
||||||
}
|
}
|
||||||
|
|
||||||
async recoverTab (token: RecoveryToken, duplicate = false): Promise<NewTabParameters<BaseTabComponent>|null> {
|
async recoverTab (token: RecoveryToken): Promise<NewTabParameters<BaseTabComponent>|null> {
|
||||||
for (const provider of this.config.enabledServices(this.tabRecoveryProviders ?? [])) {
|
for (const provider of this.config.enabledServices(this.tabRecoveryProviders ?? [])) {
|
||||||
try {
|
try {
|
||||||
if (!await provider.applicableTo(token)) {
|
if (!await provider.applicableTo(token)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (duplicate) {
|
|
||||||
token = provider.duplicate(token)
|
|
||||||
}
|
|
||||||
const tab = await provider.recover(token)
|
const tab = await provider.recover(token)
|
||||||
tab.inputs = tab.inputs ?? {}
|
tab.inputs = tab.inputs ?? {}
|
||||||
tab.inputs.color = token.tabColor ?? null
|
tab.inputs.color = token.tabColor ?? null
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import deepClone from 'clone-deep'
|
||||||
import { Injectable, ComponentFactoryResolver, Injector } from '@angular/core'
|
import { Injectable, ComponentFactoryResolver, Injector } from '@angular/core'
|
||||||
import { BaseTabComponent } from '../components/baseTab.component'
|
import { BaseTabComponent } from '../components/baseTab.component'
|
||||||
import { TabRecoveryService } from './tabRecovery.service'
|
import { TabRecoveryService } from './tabRecovery.service'
|
||||||
@@ -48,7 +49,7 @@ export class TabsService {
|
|||||||
if (!token) {
|
if (!token) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const dup = await this.tabRecovery.recoverTab(token, true)
|
const dup = await this.tabRecovery.recoverTab(deepClone(token))
|
||||||
if (dup) {
|
if (dup) {
|
||||||
return this.create(dup)
|
return this.create(dup)
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { Component, Input, Injector } from '@angular/core'
|
import { Component, Input, Injector } from '@angular/core'
|
||||||
import { BaseTabProcess, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from 'tabby-core'
|
import { BaseTabProcess, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild, GetRecoveryTokenOptions } from 'tabby-core'
|
||||||
import { BaseTerminalTabComponent } from 'tabby-terminal'
|
import { BaseTerminalTabComponent } from 'tabby-terminal'
|
||||||
import { LocalProfile, SessionOptions } from '../api'
|
import { LocalProfile, SessionOptions } from '../api'
|
||||||
import { Session } from '../session'
|
import { Session } from '../session'
|
||||||
@@ -74,7 +74,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
|||||||
this.recoveryStateChangedHint.next()
|
this.recoveryStateChangedHint.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRecoveryToken (): Promise<any> {
|
async getRecoveryToken (options?: GetRecoveryTokenOptions): Promise<any> {
|
||||||
const cwd = this.session ? await this.session.getWorkingDirectory() : null
|
const cwd = this.session ? await this.session.getWorkingDirectory() : null
|
||||||
return {
|
return {
|
||||||
type: 'app:local-tab',
|
type: 'app:local-tab',
|
||||||
@@ -83,10 +83,10 @@ export class TerminalTabComponent extends BaseTerminalTabComponent {
|
|||||||
options: {
|
options: {
|
||||||
...this.profile.options,
|
...this.profile.options,
|
||||||
cwd: cwd ?? this.profile.options.cwd,
|
cwd: cwd ?? this.profile.options.cwd,
|
||||||
restoreFromPTYID: this.session?.getPTYID(),
|
restoreFromPTYID: options?.includeState && this.session?.getPTYID(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
savedState: this.frontend?.saveState(),
|
savedState: options?.includeState && this.frontend?.saveState(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,18 +19,4 @@ export class RecoveryProvider extends TabRecoveryProvider<TerminalTabComponent>
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
duplicate (recoveryToken: RecoveryToken): RecoveryToken {
|
|
||||||
return {
|
|
||||||
...recoveryToken,
|
|
||||||
profile: {
|
|
||||||
...recoveryToken.profile,
|
|
||||||
options: {
|
|
||||||
...recoveryToken.profile.options,
|
|
||||||
restoreFromPTYID: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
savedState: null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
import colors from 'ansi-colors'
|
import colors from 'ansi-colors'
|
||||||
import { Component, Injector } from '@angular/core'
|
import { Component, Injector } from '@angular/core'
|
||||||
import { first } from 'rxjs'
|
import { first } from 'rxjs'
|
||||||
import { Platform, SelectorService } from 'tabby-core'
|
import { GetRecoveryTokenOptions, Platform, SelectorService } from 'tabby-core'
|
||||||
import { BaseTerminalTabComponent } from 'tabby-terminal'
|
import { BaseTerminalTabComponent } from 'tabby-terminal'
|
||||||
import { SerialSession, BAUD_RATES, SerialProfile } from '../api'
|
import { SerialSession, BAUD_RATES, SerialProfile } from '../api'
|
||||||
|
|
||||||
@@ -98,11 +98,11 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
|||||||
super.attachSessionHandlers()
|
super.attachSessionHandlers()
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRecoveryToken (): Promise<any> {
|
async getRecoveryToken (options?: GetRecoveryTokenOptions): Promise<any> {
|
||||||
return {
|
return {
|
||||||
type: 'app:serial-tab',
|
type: 'app:serial-tab',
|
||||||
profile: this.profile,
|
profile: this.profile,
|
||||||
savedState: this.frontend?.saveState(),
|
savedState: options?.includeState && this.frontend?.saveState(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ import colors from 'ansi-colors'
|
|||||||
import { Component, Injector, HostListener } from '@angular/core'
|
import { Component, Injector, HostListener } from '@angular/core'
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { first } from 'rxjs'
|
import { first } from 'rxjs'
|
||||||
import { Platform, ProfilesService, RecoveryToken } from 'tabby-core'
|
import { GetRecoveryTokenOptions, Platform, ProfilesService, RecoveryToken } from 'tabby-core'
|
||||||
import { BaseTerminalTabComponent } from 'tabby-terminal'
|
import { BaseTerminalTabComponent } from 'tabby-terminal'
|
||||||
import { SSHService } from '../services/ssh.service'
|
import { SSHService } from '../services/ssh.service'
|
||||||
import { KeyboardInteractivePrompt, SSHSession } from '../session/ssh'
|
import { KeyboardInteractivePrompt, SSHSession } from '../session/ssh'
|
||||||
@@ -210,11 +210,11 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
this.session?.resize(this.size.columns, this.size.rows)
|
this.session?.resize(this.size.columns, this.size.rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRecoveryToken (): Promise<RecoveryToken> {
|
async getRecoveryToken (options?: GetRecoveryTokenOptions): Promise<RecoveryToken> {
|
||||||
return {
|
return {
|
||||||
type: 'app:ssh-tab',
|
type: 'app:ssh-tab',
|
||||||
profile: this.profile,
|
profile: this.profile,
|
||||||
savedState: this.frontend?.saveState(),
|
savedState: options?.includeState && this.frontend?.saveState(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,11 +19,4 @@ export class RecoveryProvider extends TabRecoveryProvider<SSHTabComponent> {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
duplicate (recoveryToken: RecoveryToken): RecoveryToken {
|
|
||||||
return {
|
|
||||||
...recoveryToken,
|
|
||||||
savedState: null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import colors from 'ansi-colors'
|
import colors from 'ansi-colors'
|
||||||
import { Component, Injector } from '@angular/core'
|
import { Component, Injector } from '@angular/core'
|
||||||
import { first } from 'rxjs'
|
import { first } from 'rxjs'
|
||||||
import { Platform, RecoveryToken } from 'tabby-core'
|
import { GetRecoveryTokenOptions, Platform, RecoveryToken } from 'tabby-core'
|
||||||
import { BaseTerminalTabComponent } from 'tabby-terminal'
|
import { BaseTerminalTabComponent } from 'tabby-terminal'
|
||||||
import { TelnetProfile, TelnetSession } from '../session'
|
import { TelnetProfile, TelnetSession } from '../session'
|
||||||
|
|
||||||
@@ -97,11 +97,11 @@ export class TelnetTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRecoveryToken (): Promise<RecoveryToken> {
|
async getRecoveryToken (options?: GetRecoveryTokenOptions): Promise<RecoveryToken> {
|
||||||
return {
|
return {
|
||||||
type: 'app:telnet-tab',
|
type: 'app:telnet-tab',
|
||||||
profile: this.profile,
|
profile: this.profile,
|
||||||
savedState: this.frontend?.saveState(),
|
savedState: options?.includeState && this.frontend?.saveState(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,11 +19,4 @@ export class RecoveryProvider extends TabRecoveryProvider<TelnetTabComponent> {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
duplicate (recoveryToken: RecoveryToken): RecoveryToken {
|
|
||||||
return {
|
|
||||||
...recoveryToken,
|
|
||||||
savedState: null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user