feat: add SFTP drag-and-drop file handling and upload functionality

- Implemented drag-and-drop support for file uploads in the terminal.
- Added a modal for users to choose between uploading files or pasting contents.
- Enhanced SFTP browser with a directory picker for selecting upload destinations.
- Introduced methods for handling file uploads and reading file contents from the local system.
- Added a new API endpoint for uploading raw file data to the server.
- Implemented session management improvements to retrieve the current working directory for SSH sessions.
- Updated documentation to include an overview and quick start guide for Nexus Terminal.
This commit is contained in:
Andy Dixon
2026-04-21 13:20:03 +01:00
parent 7146063da2
commit 2ce145ba0f
13 changed files with 1349 additions and 560 deletions
+43
View File
@@ -8,6 +8,7 @@ import (
"encoding/json"
"fmt"
"net"
"path"
"path/filepath"
"runtime"
"strings"
@@ -1044,6 +1045,22 @@ func (s *Service) SFTPMkdir(sessionID string, remotePath string) error {
return s.sessions.SFTPMkdir(sessionID, remotePath)
}
// SFTPStat returns information about a remote path.
func (s *Service) SFTPStat(sessionID string, remotePath string) (map[string]interface{}, error) {
entry, err := s.sessions.SFTPStat(sessionID, remotePath)
if err != nil {
return nil, err
}
return map[string]interface{}{
"name": entry.Name,
"path": entry.Path,
"size": entry.Size,
"isDir": entry.IsDir,
"mode": entry.Mode,
"modifiedAt": entry.ModifiedAt,
}, nil
}
// SFTPRemove deletes a remote file or empty directory.
func (s *Service) SFTPRemove(sessionID string, remotePath string) error {
return s.sessions.SFTPRemove(sessionID, remotePath)
@@ -1096,11 +1113,37 @@ func (s *Service) SFTPUpload(sessionID string, remotePath string) error {
return s.sessions.SFTPUpload(sessionID, localPath, destPath)
}
// SFTPUploadData uploads raw file data to a remote directory.
// Data is expected as base64-encoded bytes from the frontend.
func (s *Service) SFTPUploadData(sessionID string, remoteDir string, fileName string, base64Data string) error {
if base64Data == "" {
return fmt.Errorf("empty upload payload")
}
data, err := base64.StdEncoding.DecodeString(base64Data)
if err != nil {
return fmt.Errorf("failed to decode upload data: %w", err)
}
safeName := filepath.Base(fileName)
if safeName == "" || safeName == "." || safeName == "/" {
return fmt.Errorf("invalid file name")
}
destPath := path.Join(remoteDir, safeName)
return s.sessions.SFTPUploadBytes(sessionID, destPath, data)
}
// SFTPPwd returns the current working directory on the remote host.
func (s *Service) SFTPPwd(sessionID string) (string, error) {
return s.sessions.SFTPPwd(sessionID)
}
// GetSessionCwd returns a best-effort working directory for SSH sessions.
func (s *Service) GetSessionCwd(sessionID string) (string, error) {
return s.sessions.GetSessionCwd(sessionID)
}
// ---------------------------------------------------------------------------
// OpenSSH config import
// ---------------------------------------------------------------------------