Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 52 additions & 9 deletions emain/emain-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export class WaveBrowserWindow extends BaseWindow {
waveWindowId: string;
workspaceId: string;
allLoadedTabViews: Map<string, WaveTabView>;
allTabViewsCache: Map<string, WaveTabView>; // Cache for preserving tab views across workspace switches
activeTabView: WaveTabView;
private canClose: boolean;
private deleteAllowed: boolean;
Expand Down Expand Up @@ -218,6 +219,7 @@ export class WaveBrowserWindow extends BaseWindow {
this.waveWindowId = waveWindow.oid;
this.workspaceId = waveWindow.workspaceid;
this.allLoadedTabViews = new Map<string, WaveTabView>();
this.allTabViewsCache = new Map<string, WaveTabView>();
const winBoundsPoller = setInterval(() => {
if (this.isDestroyed()) {
clearInterval(winBoundsPoller);
Expand Down Expand Up @@ -352,6 +354,11 @@ export class WaveBrowserWindow extends BaseWindow {
}
tabView?.destroy();
}
// Also destroy any cached views
for (const tabView of this.allTabViewsCache.values()) {
tabView?.destroy();
}
this.allTabViewsCache.clear();
}

async switchWorkspace(workspaceId: string) {
Expand Down Expand Up @@ -576,8 +583,27 @@ export class WaveBrowserWindow extends BaseWindow {
return;
}
console.log("processActionQueue switchworkspace newWs", newWs);
this.removeAllChildViews();
console.log("destroyed all tabs", this.waveWindowId);
// Move current tab views to cache instead of destroying them
// This preserves terminal state (including alternate screen mode) across workspace switches
for (const [tabId, tabView] of this.allLoadedTabViews.entries()) {
// Position off-screen but don't destroy
if (!this.isDestroyed()) {
const bounds = this.getContentBounds();
tabView.positionTabOffScreen(bounds);
}
// If tabId already in cache (edge case with rapid workspace switching), destroy the old cached view first
const existingCachedView = this.allTabViewsCache.get(tabId);
if (existingCachedView) {
existingCachedView.destroy();
}
this.allTabViewsCache.set(tabId, tabView);
}
console.log("cached", this.allLoadedTabViews.size, "tabs for workspace", this.workspaceId, this.waveWindowId);
// Note: Cached views are kept alive indefinitely and only destroyed when:
// 1. The tab is explicitly closed by the user
// 2. The window is closed (via removeAllChildViews)
// This matches how traditional terminal apps work and prevents terminal state loss

this.workspaceId = entry.workspaceId;
this.allLoadedTabViews = new Map();
tabId = newWs.activetabid;
Expand All @@ -586,7 +612,15 @@ export class WaveBrowserWindow extends BaseWindow {
if (tabId == null) {
return;
}
const [tabView, tabInitialized] = await getOrCreateWebViewForTab(this.waveWindowId, tabId);
// Check cache first to reuse existing tab views across workspace switches
let tabView = this.allTabViewsCache.get(tabId);
let tabInitialized = true;
if (tabView) {
console.log("reusing cached tab view", tabId, this.waveWindowId);
this.allTabViewsCache.delete(tabId);
} else {
[tabView, tabInitialized] = await getOrCreateWebViewForTab(this.waveWindowId, tabId);
}
const primaryStartupTabFlag = entry.op === "switchtab" ? (entry.primaryStartupTab ?? false) : false;
await this.setTabViewIntoWindow(tabView, tabInitialized, primaryStartupTabFlag);
} catch (e) {
Expand Down Expand Up @@ -618,14 +652,23 @@ export class WaveBrowserWindow extends BaseWindow {
console.log("cannot remove active tab", tabId, this.waveWindowId);
return;
}
const tabView = this.allLoadedTabViews.get(tabId);
let tabView = this.allLoadedTabViews.get(tabId);
if (tabView == null) {
console.log("removeTabView -- tabView not found", tabId, this.waveWindowId);
// the tab was never loaded, so just return
return;
// Check cache - tab might be from a different workspace
tabView = this.allTabViewsCache.get(tabId);
if (tabView == null) {
console.log("removeTabView -- tabView not found in loaded or cache", tabId, this.waveWindowId);
return;
}
console.log("removeTabView -- removing from cache", tabId, this.waveWindowId);
this.allTabViewsCache.delete(tabId);
} else {
this.allLoadedTabViews.delete(tabId);
}
// Remove from contentView (cached views are still children, just positioned off-screen)
if (!this.isDestroyed()) {
this.contentView.removeChildView(tabView);
}
this.contentView.removeChildView(tabView);
this.allLoadedTabViews.delete(tabId);
tabView.destroy();
}

Expand Down
Loading