diff --git a/emain/emain-window.ts b/emain/emain-window.ts index 068703a70..539297cff 100644 --- a/emain/emain-window.ts +++ b/emain/emain-window.ts @@ -18,6 +18,7 @@ import { delay, ensureBoundsAreVisible, waveKeyToElectronKey } from "./emain-uti import { log } from "./log"; import { getElectronAppBasePath, unamePlatform } from "./platform"; import { updater } from "./updater"; + export type WindowOpts = { unamePlatform: string; }; @@ -303,7 +304,8 @@ export class WaveBrowserWindow extends BaseWindow { const workspaceList = await WorkspaceService.ListWorkspaces(); if (!workspaceList?.find((wse) => wse.workspaceid === workspaceId)?.windowid) { const curWorkspace = await WorkspaceService.GetWorkspace(this.workspaceId); - if (isNonEmptyUnsavedWorkspace(curWorkspace)) { + + if (curWorkspace && isNonEmptyUnsavedWorkspace(curWorkspace)) { console.log( `existing unsaved workspace ${this.workspaceId} has content, opening workspace ${workspaceId} in new window` ); @@ -693,17 +695,22 @@ ipcMain.on("delete-workspace", (event, workspaceId) => { type: "question", buttons: ["Cancel", "Delete Workspace"], title: "Confirm", - message: `Deleting workspace will also delete its contents.${workspaceHasWindow ? "\nWorkspace is open in a window, which will be closed." : ""}\n\nContinue?`, + message: `Deleting workspace will also delete its contents.\n\nContinue?`, }); if (choice === 0) { console.log("user cancelled workspace delete", workspaceId, ww?.waveWindowId); return; } - await WorkspaceService.DeleteWorkspace(workspaceId); + + const newWorkspaceId = await WorkspaceService.DeleteWorkspace(workspaceId); console.log("delete-workspace done", workspaceId, ww?.waveWindowId); if (ww?.workspaceId == workspaceId) { - console.log("delete-workspace closing window", workspaceId, ww?.waveWindowId); - ww.destroy(); + if (newWorkspaceId) { + await ww.switchWorkspace(newWorkspaceId); + } else { + console.log("delete-workspace closing window", workspaceId, ww?.waveWindowId); + ww.destroy(); + } } }); }); diff --git a/frontend/app/store/services.ts b/frontend/app/store/services.ts index 5705af21c..94f81765e 100644 --- a/frontend/app/store/services.ts +++ b/frontend/app/store/services.ts @@ -189,7 +189,7 @@ class WorkspaceServiceType { } // @returns object updates - DeleteWorkspace(workspaceId: string): Promise { + DeleteWorkspace(workspaceId: string): Promise { return WOS.callBackendService("workspace", "DeleteWorkspace", Array.from(arguments)) } diff --git a/pkg/service/workspaceservice/workspaceservice.go b/pkg/service/workspaceservice/workspaceservice.go index b6c97ac8b..0675da01e 100644 --- a/pkg/service/workspaceservice/workspaceservice.go +++ b/pkg/service/workspaceservice/workspaceservice.go @@ -54,7 +54,8 @@ func (svc *WorkspaceService) UpdateWorkspace(ctx context.Context, workspaceId st } wps.Broker.Publish(wps.WaveEvent{ - Event: wps.Event_WorkspaceUpdate}) + Event: wps.Event_WorkspaceUpdate, + }) updates := waveobj.ContextGetUpdatesRtn(ctx) go func() { @@ -87,23 +88,26 @@ func (svc *WorkspaceService) DeleteWorkspace_Meta() tsgenmeta.MethodMeta { } } -func (svc *WorkspaceService) DeleteWorkspace(workspaceId string) (waveobj.UpdatesRtnType, error) { +func (svc *WorkspaceService) DeleteWorkspace(workspaceId string) (waveobj.UpdatesRtnType, string, error) { ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout) defer cancelFn() ctx = waveobj.ContextWithUpdates(ctx) - deleted, err := wcore.DeleteWorkspace(ctx, workspaceId, true) + deleted, claimableWorkspace, err := wcore.DeleteWorkspace(ctx, workspaceId, true) + if claimableWorkspace != "" { + return nil, claimableWorkspace, nil + } if err != nil { - return nil, fmt.Errorf("error deleting workspace: %w", err) + return nil, claimableWorkspace, fmt.Errorf("error deleting workspace: %w", err) } if !deleted { - return nil, nil + return nil, claimableWorkspace, nil } updates := waveobj.ContextGetUpdatesRtn(ctx) go func() { defer panichandler.PanicHandler("WorkspaceService:DeleteWorkspace:SendUpdateEvents") wps.Broker.SendUpdateEvents(updates) }() - return updates, nil + return updates, claimableWorkspace, nil } func (svc *WorkspaceService) ListWorkspaces() (waveobj.WorkspaceList, error) { diff --git a/pkg/wcore/window.go b/pkg/wcore/window.go index 19dea5392..f44ac02f0 100644 --- a/pkg/wcore/window.go +++ b/pkg/wcore/window.go @@ -52,10 +52,13 @@ func SwitchWorkspace(ctx context.Context, windowId string, workspaceId string) ( return nil, fmt.Errorf("error updating window: %w", err) } - deleted, err := DeleteWorkspace(ctx, curWsId, false) - if err != nil { - return nil, fmt.Errorf("error deleting current workspace: %w", err) + deleted, _, err := DeleteWorkspace(ctx, curWsId, false) + if err != nil && deleted { + print(err.Error()) // @jalileh isolated the error for now, curwId/workspace was deleted when this occurs. + } else if err != nil { + return nil, fmt.Errorf("error deleting workspace: %w", err) } + if !deleted { log.Printf("current workspace %s was not deleted\n", curWsId) } else { @@ -131,7 +134,7 @@ func CloseWindow(ctx context.Context, windowId string, fromElectron bool) error window, err := GetWindow(ctx, windowId) if err == nil { log.Printf("got window %s\n", windowId) - deleted, err := DeleteWorkspace(ctx, window.WorkspaceId, false) + deleted, _, err := DeleteWorkspace(ctx, window.WorkspaceId, false) if err != nil { log.Printf("error deleting workspace: %v\n", err) } diff --git a/pkg/wcore/workspace.go b/pkg/wcore/workspace.go index 1cc8ce1cf..ef41b4645 100644 --- a/pkg/wcore/workspace.go +++ b/pkg/wcore/workspace.go @@ -66,7 +66,8 @@ func CreateWorkspace(ctx context.Context, name string, icon string, color string } wps.Broker.Publish(wps.WaveEvent{ - Event: wps.Event_WorkspaceUpdate}) + Event: wps.Event_WorkspaceUpdate, + }) ws, _, err = UpdateWorkspace(ctx, ws.OID, name, icon, color, applyDefaults) return ws, err @@ -114,15 +115,24 @@ func UpdateWorkspace(ctx context.Context, workspaceId string, name string, icon // If force is true, it will delete even if workspace is named. // If workspace is empty, it will be deleted, even if it is named. // Returns true if workspace was deleted, false if it was not deleted. -func DeleteWorkspace(ctx context.Context, workspaceId string, force bool) (bool, error) { +func DeleteWorkspace(ctx context.Context, workspaceId string, force bool) (bool, string, error) { log.Printf("DeleteWorkspace %s\n", workspaceId) workspace, err := wstore.DBMustGet[*waveobj.Workspace](ctx, workspaceId) + if err != nil && wstore.ErrNotFound == err { + return true, "", fmt.Errorf("workspace already deleted %w", err) + } + // @jalileh list needs to be saved early on i assume + workspaces, err := ListWorkspaces(ctx) if err != nil { - return false, fmt.Errorf("error getting workspace: %w", err) + return false, "", fmt.Errorf("error retrieving workspaceList: %w", err) + } + + if err != nil { + return false, "", fmt.Errorf("error getting workspace: %w", err) } if workspace.Name != "" && workspace.Icon != "" && !force && (len(workspace.TabIds) > 0 || len(workspace.PinnedTabIds) > 0) { log.Printf("Ignoring DeleteWorkspace for workspace %s as it is named\n", workspaceId) - return false, nil + return false, "", nil } // delete all pinned and unpinned tabs @@ -130,24 +140,49 @@ func DeleteWorkspace(ctx context.Context, workspaceId string, force bool) (bool, log.Printf("deleting tab %s\n", tabId) _, err := DeleteTab(ctx, workspaceId, tabId, false) if err != nil { - return false, fmt.Errorf("error closing tab: %w", err) + return false, "", fmt.Errorf("error closing tab: %w", err) } } windowId, err := wstore.DBFindWindowForWorkspaceId(ctx, workspaceId) err = wstore.DBDelete(ctx, waveobj.OType_Workspace, workspaceId) if err != nil { - return false, fmt.Errorf("error deleting workspace: %w", err) + return false, "", fmt.Errorf("error deleting workspace: %w", err) } log.Printf("deleted workspace %s\n", workspaceId) wps.Broker.Publish(wps.WaveEvent{ - Event: wps.Event_WorkspaceUpdate}) + Event: wps.Event_WorkspaceUpdate, + }) + if windowId != "" { - err = CloseWindow(ctx, windowId, false) + + UnclaimedWorkspace, findAfter := "", false + for _, ws := range workspaces { + if ws.WorkspaceId == workspaceId { + if UnclaimedWorkspace != "" { + break + } + findAfter = true + continue + } + if findAfter && ws.WindowId == "" { + UnclaimedWorkspace = ws.WorkspaceId + break + } else if ws.WindowId == "" { + UnclaimedWorkspace = ws.WorkspaceId + } + } + + if UnclaimedWorkspace != "" { + return true, UnclaimedWorkspace, nil + } else { + err = CloseWindow(ctx, windowId, false) + } + if err != nil { - return false, fmt.Errorf("error closing window: %w", err) + return false, "", fmt.Errorf("error closing window: %w", err) } } - return true, nil + return true, "", nil } func GetWorkspace(ctx context.Context, wsID string) (*waveobj.Workspace, error) {