feat: drag files between file panes (move or copy, SSH hosts too) and into a terminal of the same machine

This commit is contained in:
redtea committed 2026-10-15 21:42:21 +03:00
1 parent a30b89f1d8
commit f2740c50b4
12 files changed
+484 -32

No files matched your search

+16 -2
View File
@@ -115,6 +115,10 @@ type shipReq struct {
Move bool `json:"move"`
To string `json:"to"`
SSH *proto.SSHTarget `json:"ssh"`
// FromConn, ToConn: that side is an SSH host held by its agent for a
// file pane (its connection id); To is still the agent holding ToConn.
FromConn string `json:"from_conn"`
ToConn string `json:"to_conn"`
}
// POST /api/panel/agents/{id}/fs/ship - start sending; the answer names the
@@ -147,6 +151,9 @@ func (s *Server) handleFSShip(w http.ResponseWriter, r *http.Request) {
}
where = "ssh:" + t.User + "@" + t.Host + ":" + strconv.Itoa(t.Port)
} else {
if q.To == "" && q.ToConn != "" {
q.To = from
}
if q.To == "" {
writeJSON(w, proto.TaskResult{Error: "не выбрана машина"})
return
@@ -224,12 +231,14 @@ func (s *Server) ship1(ctx context.Context, j *shipJob, from string, q shipReq)
}()
go func() { <-ctx.Done(); x.fail("отменено") }()
args.Relay, args.Chunk = x.id, xferChunk
inArgs := args
args.Conn, inArgs.Conn = q.FromConn, q.ToConn
var in proto.TaskResult
inDone := make(chan struct{})
go func() {
defer close(inDone)
res, err := s.waitTask(ctx, q.To, proto.TaskFSShipIn, args, xferTimeout)
res, err := s.waitTask(ctx, q.To, proto.TaskFSShipIn, inArgs, xferTimeout)
if err != nil {
res = proto.TaskResult{Error: err.Error()}
}
@@ -254,7 +263,12 @@ func (s *Server) ship1(ctx context.Context, j *shipJob, from string, q shipReq)
return out
}
if q.Move {
res, err := s.waitTask(ctx, from, proto.TaskFSDelTree, proto.FSPathArgs{Path: q.Src}, fsTaskTimeout)
task, del := proto.TaskFSDelTree, any(proto.FSPathArgs{Path: q.Src})
if q.FromConn != "" {
raw, _ := json.Marshal(proto.FSPathArgs{Path: q.Src})
task, del = proto.TaskSSHFSOp, proto.SSHFSArgs{Conn: q.FromConn, Op: "deltree", Args: raw}
}
res, err := s.waitTask(ctx, from, task, del, fsTaskTimeout)
if err == nil && !res.OK {
err = errText(res.Error)
}