diff --git a/emain/emain-window.ts b/emain/emain-window.ts index 96af4aca2..76b928765 100644 --- a/emain/emain-window.ts +++ b/emain/emain-window.ts @@ -282,10 +282,11 @@ export class WaveBrowserWindow extends BaseWindow { await this.queueTabSwitch(tabView, tabInitialized); } - async setActiveTab(tabId: string) { - console.log("setActiveTab", this); - const workspace = await WorkspaceService.GetWorkspace(this.workspaceId); - await WorkspaceService.SetActiveTab(workspace.oid, tabId); + async setActiveTab(tabId: string, setInBackend: boolean) { + console.log("setActiveTab", tabId, this.waveWindowId, this.workspaceId, setInBackend); + if (setInBackend) { + await WorkspaceService.SetActiveTab(this.workspaceId, tabId); + } const fullConfig = await FileService.GetFullConfig(); const [tabView, tabInitialized] = getOrCreateWebViewForTab(fullConfig, tabId); await this.queueTabSwitch(tabView, tabInitialized); @@ -293,19 +294,20 @@ export class WaveBrowserWindow extends BaseWindow { async createTab() { const tabId = await WorkspaceService.CreateTab(this.workspaceId, null, true); - this.setActiveTab(tabId); + await this.setActiveTab(tabId, false); } async closeTab(tabId: string) { + console.log("closeTab", tabId, this.waveWindowId, this.workspaceId); const tabView = this.allTabViews.get(tabId); if (tabView) { const rtn = await WorkspaceService.CloseTab(this.workspaceId, tabId, true); - this.allTabViews.delete(tabId); if (rtn?.closewindow) { this.close(); } else if (rtn?.newactivetabid) { - this.setActiveTab(rtn.newactivetabid); + await this.setActiveTab(rtn.newactivetabid, false); } + this.allTabViews.delete(tabId); } } @@ -519,7 +521,7 @@ export async function createBrowserWindow( console.log("createBrowserWindow", waveWindow.oid, workspace.oid, workspace); const bwin = new WaveBrowserWindow(waveWindow, fullConfig, opts); if (workspace.activetabid) { - await bwin.setActiveTab(workspace.activetabid); + await bwin.setActiveTab(workspace.activetabid, false); } return bwin; } @@ -527,7 +529,7 @@ export async function createBrowserWindow( ipcMain.on("set-active-tab", async (event, tabId) => { const ww = getWaveWindowByWebContentsId(event.sender.id); console.log("set-active-tab", tabId, ww?.waveWindowId); - await ww?.setActiveTab(tabId); + await ww?.setActiveTab(tabId, true); }); ipcMain.on("create-tab", async (event, opts) => { diff --git a/pkg/service/workspaceservice/workspaceservice.go b/pkg/service/workspaceservice/workspaceservice.go index 7f4a6120e..1c4f55b59 100644 --- a/pkg/service/workspaceservice/workspaceservice.go +++ b/pkg/service/workspaceservice/workspaceservice.go @@ -164,54 +164,28 @@ func (svc *WorkspaceService) CloseTab(ctx context.Context, workspaceId string, t if err != nil { return nil, nil, fmt.Errorf("error getting tab: %w", err) } - ws, err := wstore.DBMustGet[*waveobj.Workspace](ctx, workspaceId) - if err != nil { - return nil, nil, fmt.Errorf("error getting workspace: %w", err) - } - tabIndex := -1 - for i, id := range ws.TabIds { - if id == tabId { - tabIndex = i - break - } - } go func() { for _, blockId := range tab.BlockIds { blockcontroller.StopBlockController(blockId) } }() - if err := wcore.DeleteTab(ctx, workspaceId, tabId); err != nil { + newActiveTabId, err := wcore.DeleteTab(ctx, workspaceId, tabId) + if err != nil { return nil, nil, fmt.Errorf("error closing tab: %w", err) } rtn := &CloseTabRtnType{} - if ws.ActiveTabId == tabId && tabIndex != -1 { - if len(ws.TabIds) == 1 { - windowId, err := wstore.DBFindWindowForWorkspaceId(ctx, workspaceId) - if err != nil { - return rtn, nil, fmt.Errorf("unable to find window for workspace id %v: %w", workspaceId, err) - } - rtn.CloseWindow = true - err = wcore.CloseWindow(ctx, windowId, fromElectron) - if err != nil { - return rtn, nil, err - } - } else { - if tabIndex < len(ws.TabIds)-1 { - newActiveTabId := ws.TabIds[tabIndex+1] - err := wcore.SetActiveTab(ctx, ws.OID, newActiveTabId) - if err != nil { - return rtn, nil, err - } - rtn.NewActiveTabId = newActiveTabId - } else { - newActiveTabId := ws.TabIds[tabIndex-1] - err := wcore.SetActiveTab(ctx, ws.OID, newActiveTabId) - if err != nil { - return rtn, nil, err - } - rtn.NewActiveTabId = newActiveTabId - } + if newActiveTabId == "" { + windowId, err := wstore.DBFindWindowForWorkspaceId(ctx, workspaceId) + if err != nil { + return rtn, nil, fmt.Errorf("unable to find window for workspace id %v: %w", workspaceId, err) } + rtn.CloseWindow = true + err = wcore.CloseWindow(ctx, windowId, fromElectron) + if err != nil { + return rtn, nil, err + } + } else { + rtn.NewActiveTabId = newActiveTabId } updates := waveobj.ContextGetUpdatesRtn(ctx) go func() { diff --git a/pkg/wcore/window.go b/pkg/wcore/window.go index 644f011b8..08ec9d8dd 100644 --- a/pkg/wcore/window.go +++ b/pkg/wcore/window.go @@ -108,7 +108,7 @@ func CreateWindow(ctx context.Context, winSize *waveobj.WinSize, workspaceId str if err != nil { return nil, fmt.Errorf("error inserting window: %w", err) } - client, err := wstore.DBGetSingleton[*waveobj.Client](ctx) + client, err := GetClientData(ctx) if err != nil { return nil, fmt.Errorf("error getting client: %w", err) } @@ -117,12 +117,12 @@ func CreateWindow(ctx context.Context, winSize *waveobj.WinSize, workspaceId str if err != nil { return nil, fmt.Errorf("error updating client: %w", err) } - return wstore.DBMustGet[*waveobj.Window](ctx, windowId) + return GetWindow(ctx, windowId) } func CloseWindow(ctx context.Context, windowId string, fromElectron bool) error { log.Printf("CloseWindow %s\n", windowId) - window, err := wstore.DBMustGet[*waveobj.Window](ctx, windowId) + window, err := GetWindow(ctx, windowId) if err == nil { log.Printf("got window %s\n", windowId) deleted, err := DeleteWorkspace(ctx, window.WorkspaceId, false) diff --git a/pkg/wcore/workspace.go b/pkg/wcore/workspace.go index ec3fd68e9..2402512a8 100644 --- a/pkg/wcore/workspace.go +++ b/pkg/wcore/workspace.go @@ -39,7 +39,7 @@ func DeleteWorkspace(ctx context.Context, workspaceId string, force bool) (bool, } for _, tabId := range workspace.TabIds { log.Printf("deleting tab %s\n", tabId) - err := DeleteTab(ctx, workspaceId, tabId) + _, err := DeleteTab(ctx, workspaceId, tabId) if err != nil { return false, fmt.Errorf("error closing tab: %w", err) } @@ -57,9 +57,9 @@ func GetWorkspace(ctx context.Context, wsID string) (*waveobj.Workspace, error) } func createTabObj(ctx context.Context, workspaceId string, name string) (*waveobj.Tab, error) { - ws, _ := wstore.DBGet[*waveobj.Workspace](ctx, workspaceId) - if ws == nil { - return nil, fmt.Errorf("workspace not found: %q", workspaceId) + ws, err := GetWorkspace(ctx, workspaceId) + if err != nil { + return nil, fmt.Errorf("workspace %s not found: %w", workspaceId, err) } layoutStateId := uuid.NewString() tab := &waveobj.Tab{ @@ -81,19 +81,11 @@ func createTabObj(ctx context.Context, workspaceId string, name string) (*waveob // returns tabid func CreateTab(ctx context.Context, workspaceId string, tabName string, activateTab bool) (string, error) { if tabName == "" { - client, err := wstore.DBGetSingleton[*waveobj.Client](ctx) + ws, err := GetWorkspace(ctx, workspaceId) if err != nil { - return "", fmt.Errorf("error getting client: %w", err) - } - ws, _ := wstore.DBGet[*waveobj.Workspace](ctx, workspaceId) - if ws == nil { - return "", fmt.Errorf("workspace not found: %q", workspaceId) + return "", fmt.Errorf("workspace %s not found: %w", workspaceId, err) } tabName = "T" + fmt.Sprint(len(ws.TabIds)+1) - err = wstore.DBUpdate(ctx, client) - if err != nil { - return "", fmt.Errorf("error updating client: %w", err) - } } tab, err := createTabObj(ctx, workspaceId, tabName) if err != nil { @@ -109,49 +101,60 @@ func CreateTab(ctx context.Context, workspaceId string, tabName string, activate return tab.OID, nil } -// must delete all blocks individually first -// also deletes LayoutState -func DeleteTab(ctx context.Context, workspaceId string, tabId string) error { +// Must delete all blocks individually first. +// Also deletes LayoutState. +// Returns new active tab id, error. +func DeleteTab(ctx context.Context, workspaceId string, tabId string) (string, error) { ws, _ := wstore.DBGet[*waveobj.Workspace](ctx, workspaceId) if ws == nil { - return fmt.Errorf("workspace not found: %q", workspaceId) + return "", fmt.Errorf("workspace not found: %q", workspaceId) } tab, _ := wstore.DBGet[*waveobj.Tab](ctx, tabId) if tab == nil { - return fmt.Errorf("tab not found: %q", tabId) + return "", fmt.Errorf("tab not found: %q", tabId) } // close blocks (sends events + stops block controllers) for _, blockId := range tab.BlockIds { err := DeleteBlock(ctx, blockId) if err != nil { - return fmt.Errorf("error deleting block %s: %w", blockId, err) + return "", fmt.Errorf("error deleting block %s: %w", blockId, err) } } tabIdx := utilfn.FindStringInSlice(ws.TabIds, tabId) if tabIdx == -1 { - return nil + return "", nil } ws.TabIds = append(ws.TabIds[:tabIdx], ws.TabIds[tabIdx+1:]...) + newActiveTabId := ws.ActiveTabId + if len(ws.TabIds) > 0 { + if ws.ActiveTabId == tabId { + newActiveTabId = ws.TabIds[max(0, min(tabIdx-1, len(ws.TabIds)-1))] + } + } else { + newActiveTabId = "" + } + ws.ActiveTabId = newActiveTabId + wstore.DBUpdate(ctx, ws) wstore.DBDelete(ctx, waveobj.OType_Tab, tabId) wstore.DBDelete(ctx, waveobj.OType_LayoutState, tab.LayoutState) - return nil + return newActiveTabId, nil } func SetActiveTab(ctx context.Context, workspaceId string, tabId string) error { - workspace, _ := wstore.DBGet[*waveobj.Workspace](ctx, workspaceId) - if workspace == nil { - return fmt.Errorf("workspace not found: %q", workspaceId) - } if tabId != "" { + workspace, err := GetWorkspace(ctx, workspaceId) + if err != nil { + return fmt.Errorf("workspace %s not found: %w", workspaceId, err) + } tab, _ := wstore.DBGet[*waveobj.Tab](ctx, tabId) if tab == nil { return fmt.Errorf("tab not found: %q", tabId) } + workspace.ActiveTabId = tabId + wstore.DBUpdate(ctx, workspace) } - workspace.ActiveTabId = tabId - wstore.DBUpdate(ctx, workspace) return nil }