mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
Fix close active tab behavior (#1367)
This fixes a bug where closing the active tab would clean up the closed tab view before switching to an un-closed tab view, putting the window into an unrecoverable state. This also moves around some of the CloseTab logic so that it's more standardized and reduces unnecessary frontend-backend comms and DB writes
This commit is contained in:
parent
cdc91529b5
commit
f368a61c70
@ -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) => {
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user