2024-12-11 00:18:14 +01:00
|
|
|
// Copyright 2024, Command Line Inc.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2024-12-02 19:56:56 +01:00
|
|
|
package wcore
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/wavetermdev/waveterm/pkg/eventbus"
|
|
|
|
"github.com/wavetermdev/waveterm/pkg/util/utilfn"
|
|
|
|
"github.com/wavetermdev/waveterm/pkg/waveobj"
|
|
|
|
"github.com/wavetermdev/waveterm/pkg/wshrpc"
|
|
|
|
"github.com/wavetermdev/waveterm/pkg/wshrpc/wshclient"
|
|
|
|
"github.com/wavetermdev/waveterm/pkg/wshutil"
|
|
|
|
"github.com/wavetermdev/waveterm/pkg/wstore"
|
|
|
|
)
|
|
|
|
|
|
|
|
func SwitchWorkspace(ctx context.Context, windowId string, workspaceId string) (*waveobj.Workspace, error) {
|
|
|
|
log.Printf("SwitchWorkspace %s %s\n", windowId, workspaceId)
|
|
|
|
ws, err := GetWorkspace(ctx, workspaceId)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error getting new workspace: %w", err)
|
|
|
|
}
|
|
|
|
window, err := GetWindow(ctx, windowId)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error getting window: %w", err)
|
|
|
|
}
|
2024-12-17 06:54:13 +01:00
|
|
|
curWsId := window.WorkspaceId
|
|
|
|
if curWsId == workspaceId {
|
2024-12-02 19:56:56 +01:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
allWindows, err := wstore.DBGetAllObjsByType[*waveobj.Window](ctx, waveobj.OType_Window)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error getting all windows: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, w := range allWindows {
|
|
|
|
if w.WorkspaceId == workspaceId {
|
|
|
|
log.Printf("workspace %s already has a window %s, focusing that window\n", workspaceId, w.OID)
|
|
|
|
client := wshclient.GetBareRpcClient()
|
|
|
|
err = wshclient.FocusWindowCommand(client, w.OID, &wshrpc.RpcOpts{Route: wshutil.ElectronRoute})
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2024-12-17 06:54:13 +01:00
|
|
|
window.WorkspaceId = workspaceId
|
|
|
|
err = wstore.DBUpdate(ctx, window)
|
2024-12-02 19:56:56 +01:00
|
|
|
if err != nil {
|
2024-12-17 06:54:13 +01:00
|
|
|
return nil, fmt.Errorf("error updating window: %w", err)
|
2024-12-02 19:56:56 +01:00
|
|
|
}
|
2024-12-17 06:54:13 +01:00
|
|
|
|
|
|
|
deleted, err := DeleteWorkspace(ctx, curWsId, false)
|
2024-12-02 19:56:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error deleting current workspace: %w", err)
|
|
|
|
}
|
|
|
|
if !deleted {
|
2024-12-17 06:54:13 +01:00
|
|
|
log.Printf("current workspace %s was not deleted\n", curWsId)
|
2024-12-02 19:56:56 +01:00
|
|
|
} else {
|
2024-12-17 06:54:13 +01:00
|
|
|
log.Printf("deleted current workspace %s\n", curWsId)
|
2024-12-02 19:56:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("switching window %s to workspace %s\n", windowId, workspaceId)
|
2024-12-17 06:54:13 +01:00
|
|
|
return ws, nil
|
2024-12-02 19:56:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func GetWindow(ctx context.Context, windowId string) (*waveobj.Window, error) {
|
|
|
|
window, err := wstore.DBMustGet[*waveobj.Window](ctx, windowId)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("error getting window %q: %v\n", windowId, err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return window, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func CreateWindow(ctx context.Context, winSize *waveobj.WinSize, workspaceId string) (*waveobj.Window, error) {
|
|
|
|
log.Printf("CreateWindow %v %v\n", winSize, workspaceId)
|
|
|
|
var ws *waveobj.Workspace
|
|
|
|
if workspaceId == "" {
|
2024-12-13 02:21:09 +01:00
|
|
|
ws1, err := CreateWorkspace(ctx, "", "", "", false, false)
|
2024-12-02 19:56:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error creating workspace: %w", err)
|
|
|
|
}
|
|
|
|
ws = ws1
|
|
|
|
} else {
|
|
|
|
ws1, err := GetWorkspace(ctx, workspaceId)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error getting workspace: %w", err)
|
|
|
|
}
|
|
|
|
ws = ws1
|
|
|
|
}
|
|
|
|
windowId := uuid.NewString()
|
|
|
|
if winSize == nil {
|
|
|
|
winSize = &waveobj.WinSize{
|
|
|
|
Width: 0,
|
|
|
|
Height: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
window := &waveobj.Window{
|
|
|
|
OID: windowId,
|
|
|
|
WorkspaceId: ws.OID,
|
|
|
|
IsNew: true,
|
|
|
|
Pos: waveobj.Point{
|
|
|
|
X: 0,
|
|
|
|
Y: 0,
|
|
|
|
},
|
|
|
|
WinSize: *winSize,
|
|
|
|
}
|
|
|
|
err := wstore.DBInsert(ctx, window)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error inserting window: %w", err)
|
|
|
|
}
|
2024-12-02 21:59:03 +01:00
|
|
|
client, err := GetClientData(ctx)
|
2024-12-02 19:56:56 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error getting client: %w", err)
|
|
|
|
}
|
|
|
|
client.WindowIds = append(client.WindowIds, windowId)
|
|
|
|
err = wstore.DBUpdate(ctx, client)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("error updating client: %w", err)
|
|
|
|
}
|
2024-12-02 21:59:03 +01:00
|
|
|
return GetWindow(ctx, windowId)
|
2024-12-02 19:56:56 +01:00
|
|
|
}
|
|
|
|
|
2024-12-04 03:39:06 +01:00
|
|
|
// CloseWindow closes a window and deletes its workspace if it is empty and not named.
|
|
|
|
// If fromElectron is true, it does not send an event to Electron.
|
2024-12-02 19:56:56 +01:00
|
|
|
func CloseWindow(ctx context.Context, windowId string, fromElectron bool) error {
|
|
|
|
log.Printf("CloseWindow %s\n", windowId)
|
2024-12-02 21:59:03 +01:00
|
|
|
window, err := GetWindow(ctx, windowId)
|
2024-12-02 19:56:56 +01:00
|
|
|
if err == nil {
|
|
|
|
log.Printf("got window %s\n", windowId)
|
|
|
|
deleted, err := DeleteWorkspace(ctx, window.WorkspaceId, false)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("error deleting workspace: %v\n", err)
|
|
|
|
}
|
|
|
|
if deleted {
|
|
|
|
log.Printf("deleted workspace %s\n", window.WorkspaceId)
|
|
|
|
}
|
|
|
|
err = wstore.DBDelete(ctx, waveobj.OType_Window, windowId)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error deleting window: %w", err)
|
|
|
|
}
|
|
|
|
log.Printf("deleted window %s\n", windowId)
|
|
|
|
} else {
|
|
|
|
log.Printf("error getting window %s: %v\n", windowId, err)
|
|
|
|
}
|
|
|
|
client, err := wstore.DBGetSingleton[*waveobj.Client](ctx)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error getting client: %w", err)
|
|
|
|
}
|
|
|
|
client.WindowIds = utilfn.RemoveElemFromSlice(client.WindowIds, windowId)
|
|
|
|
err = wstore.DBUpdate(ctx, client)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error updating client: %w", err)
|
|
|
|
}
|
|
|
|
log.Printf("updated client\n")
|
|
|
|
if !fromElectron {
|
|
|
|
eventbus.SendEventToElectron(eventbus.WSEventType{
|
|
|
|
EventType: eventbus.WSEvent_ElectronCloseWindow,
|
|
|
|
Data: windowId,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func CheckAndFixWindow(ctx context.Context, windowId string) *waveobj.Window {
|
|
|
|
log.Printf("CheckAndFixWindow %s\n", windowId)
|
|
|
|
window, err := GetWindow(ctx, windowId)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("error getting window %q (in checkAndFixWindow): %v\n", windowId, err)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
ws, err := GetWorkspace(ctx, window.WorkspaceId)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("error getting workspace %q (in checkAndFixWindow): %v\n", window.WorkspaceId, err)
|
|
|
|
CloseWindow(ctx, windowId, false)
|
|
|
|
return nil
|
|
|
|
}
|
2024-12-11 21:52:15 +01:00
|
|
|
if len(ws.TabIds) == 0 && len(ws.PinnedTabIds) == 0 {
|
2024-12-02 19:56:56 +01:00
|
|
|
log.Printf("fixing workspace with no tabs %q (in checkAndFixWindow)\n", ws.OID)
|
2024-12-09 23:24:02 +01:00
|
|
|
_, err = CreateTab(ctx, ws.OID, "", true, false, false)
|
2024-12-02 19:56:56 +01:00
|
|
|
if err != nil {
|
|
|
|
log.Printf("error creating tab (in checkAndFixWindow): %v\n", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return window
|
|
|
|
}
|
|
|
|
|
|
|
|
func FocusWindow(ctx context.Context, windowId string) error {
|
|
|
|
log.Printf("FocusWindow %s\n", windowId)
|
|
|
|
client, err := GetClientData(ctx)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("error getting client data: %v\n", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
winIdx := utilfn.SliceIdx(client.WindowIds, windowId)
|
|
|
|
if winIdx == -1 {
|
|
|
|
log.Printf("window %s not found in client data\n", windowId)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
client.WindowIds = utilfn.MoveSliceIdxToFront(client.WindowIds, winIdx)
|
|
|
|
log.Printf("client.WindowIds: %v\n", client.WindowIds)
|
|
|
|
return wstore.DBUpdate(ctx, client)
|
|
|
|
}
|