mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
c5501a5335
Moves the wlayout package contents to wcore to prevent import cycles. Moves the layout calls to other wcore functions instead of being handled by the services. Removes redundant CreateTab in EnsureInitialData and adds a isInitialLaunch flag to the CreateTab and CreateWorkspace functions to ensure that the initial tab is pinned and does not have the initial tab layout (since the starter layout gets applied later)
212 lines
6.4 KiB
Go
212 lines
6.4 KiB
Go
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)
|
|
}
|
|
if window.WorkspaceId == workspaceId {
|
|
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
|
|
}
|
|
}
|
|
|
|
curWs, err := GetWorkspace(ctx, window.WorkspaceId)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error getting current workspace: %w", err)
|
|
}
|
|
deleted, err := DeleteWorkspace(ctx, curWs.OID, false)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error deleting current workspace: %w", err)
|
|
}
|
|
if !deleted {
|
|
log.Printf("current workspace %s was not deleted\n", curWs.OID)
|
|
} else {
|
|
log.Printf("deleted current workspace %s\n", curWs.OID)
|
|
}
|
|
|
|
window.WorkspaceId = workspaceId
|
|
log.Printf("switching window %s to workspace %s\n", windowId, workspaceId)
|
|
return ws, wstore.DBUpdate(ctx, window)
|
|
}
|
|
|
|
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 == "" {
|
|
ws1, err := CreateWorkspace(ctx, "", "", "", false)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error creating workspace: %w", err)
|
|
}
|
|
ws = ws1
|
|
err = BootstrapNewWorkspaceLayout(ctx, ws)
|
|
if err != nil {
|
|
errStr := fmt.Errorf("error bootstrapping new workspace layout: %w", err)
|
|
_, err = DeleteWorkspace(ctx, ws.OID, true)
|
|
if err != nil {
|
|
errStr = fmt.Errorf("%s\nerror deleting workspace: %w", errStr, err)
|
|
}
|
|
return nil, errStr
|
|
}
|
|
} 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)
|
|
}
|
|
client, err := GetClientData(ctx)
|
|
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)
|
|
}
|
|
return GetWindow(ctx, windowId)
|
|
}
|
|
|
|
// 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.
|
|
func CloseWindow(ctx context.Context, windowId string, fromElectron bool) error {
|
|
log.Printf("CloseWindow %s\n", windowId)
|
|
window, err := GetWindow(ctx, windowId)
|
|
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
|
|
}
|
|
if len(ws.TabIds) == 0 {
|
|
log.Printf("fixing workspace with no tabs %q (in checkAndFixWindow)\n", ws.OID)
|
|
_, err = CreateTab(ctx, ws.OID, "", true, false, false)
|
|
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)
|
|
}
|