From 91d28b844dff25f3e5b8cc6b458f14b3401d3c34 Mon Sep 17 00:00:00 2001 From: Jamie Banks Date: Tue, 9 Jun 2026 16:01:02 +0100 Subject: [PATCH 1/2] fix: reordering connections --- frontend/src/main.js | 7 ++++--- frontend/wailsjs/runtime/package.json | 0 frontend/wailsjs/runtime/runtime.d.ts | 0 frontend/wailsjs/runtime/runtime.js | 0 go.mod | 4 ++-- 5 files changed, 6 insertions(+), 5 deletions(-) mode change 100755 => 100644 frontend/wailsjs/runtime/package.json mode change 100755 => 100644 frontend/wailsjs/runtime/runtime.d.ts mode change 100755 => 100644 frontend/wailsjs/runtime/runtime.js diff --git a/frontend/src/main.js b/frontend/src/main.js index ea53af4..9dfee25 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -85,6 +85,7 @@ async function loadConnections() { el.addEventListener('dragstart', (e) => { draggedConnId = c.id; e.dataTransfer.effectAllowed = 'move'; + e.dataTransfer.setData('text/plain', c.id); el.style.opacity = '0.5'; }); el.addEventListener('dragend', () => { @@ -94,11 +95,11 @@ async function loadConnections() { el.addEventListener('dragenter', (e) => { e.preventDefault(); if (draggedConnId && draggedConnId !== c.id) { - el.style.borderTop = '2px solid var(--accent)'; + el.style.boxShadow = 'inset 0 2px 0 var(--accent)'; } }); el.addEventListener('dragleave', (e) => { - el.style.borderTop = ''; + el.style.boxShadow = ''; }); el.addEventListener('dragover', (e) => { e.preventDefault(); @@ -106,7 +107,7 @@ async function loadConnections() { }); el.addEventListener('drop', async (e) => { e.preventDefault(); - el.style.borderTop = ''; + el.style.boxShadow = ''; if (!draggedConnId || draggedConnId === c.id) return; const ids = connectionsCache.map(conn => conn.id); diff --git a/frontend/wailsjs/runtime/package.json b/frontend/wailsjs/runtime/package.json old mode 100755 new mode 100644 diff --git a/frontend/wailsjs/runtime/runtime.d.ts b/frontend/wailsjs/runtime/runtime.d.ts old mode 100755 new mode 100644 diff --git a/frontend/wailsjs/runtime/runtime.js b/frontend/wailsjs/runtime/runtime.js old mode 100755 new mode 100644 diff --git a/go.mod b/go.mod index 0cd290c..f685caa 100644 --- a/go.mod +++ b/go.mod @@ -9,12 +9,14 @@ require ( github.com/aws/aws-sdk-go-v2/service/s3 v1.103.3 github.com/google/uuid v1.6.0 github.com/hirochachacha/go-smb2 v1.1.0 + github.com/jlaffaye/ftp v0.2.1 github.com/pkg/sftp v1.13.10 github.com/studio-b12/gowebdav v0.12.0 github.com/vmware/go-nfs-client v0.0.0-20190605212624-d43b92724c1b github.com/wailsapp/wails/v2 v2.12.0 github.com/zalando/go-keyring v0.2.8 golang.org/x/crypto v0.53.0 + golang.org/x/time v0.15.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -41,7 +43,6 @@ require ( github.com/godbus/dbus/v5 v5.2.2 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect - github.com/jlaffaye/ftp v0.2.1 // indirect github.com/kr/fs v0.1.0 // indirect github.com/labstack/echo/v4 v4.13.3 // indirect github.com/labstack/gommon v0.4.2 // indirect @@ -64,7 +65,6 @@ require ( golang.org/x/net v0.55.0 // indirect golang.org/x/sys v0.46.0 // indirect golang.org/x/text v0.38.0 // indirect - golang.org/x/time v0.15.0 // indirect ) // replace github.com/wailsapp/wails/v2 v2.12.0 => /home/jamie/go/pkg/mod -- 2.47.3 From 5f7c977f779be758db914b0d932adc54baeb2127 Mon Sep 17 00:00:00 2001 From: Jamie Banks Date: Tue, 9 Jun 2026 16:24:11 +0100 Subject: [PATCH 2/2] refactor: implement connection pooling and state management for remote explorers --- app.go | 63 +++++++++++++++++++++---------- frontend/wailsjs/go/main/App.d.ts | 2 + frontend/wailsjs/go/main/App.js | 4 ++ internal/protocols/sftp/sftp.go | 23 +++++++---- main.go | 6 +++ 5 files changed, 71 insertions(+), 27 deletions(-) diff --git a/app.go b/app.go index eb8b2a0..aa6df03 100644 --- a/app.go +++ b/app.go @@ -16,6 +16,7 @@ import ( "goexplore/internal/transfer" "os" "path/filepath" + "sync" "github.com/google/uuid" "github.com/wailsapp/wails/v2/pkg/runtime" @@ -25,6 +26,8 @@ type App struct { ctx context.Context cfg *config.Config transferManager *transfer.Manager + explorers map[string]explorer.Explorer + explorersMu sync.Mutex } func NewApp() *App { @@ -38,6 +41,7 @@ func NewApp() *App { return &App{ cfg: cfg, transferManager: transfer.NewManager(3), + explorers: make(map[string]explorer.Explorer), } } @@ -123,6 +127,41 @@ func (a *App) ReorderConnections(ids []string) error { return config.SaveConfig(a.cfg) } +func (a *App) getConnection(id string) (explorer.Explorer, error) { + if id == "local" { + return local.New(), nil + } + + a.explorersMu.Lock() + defer a.explorersMu.Unlock() + + if exp, ok := a.explorers[id]; ok { + return exp, nil + } + + exp, err := a.getExplorerForConnection(id) + if err != nil { + return nil, err + } + + if err := exp.Connect(); err != nil { + return nil, err + } + + a.explorers[id] = exp + return exp, nil +} + +func (a *App) DisconnectConnection(id string) { + a.explorersMu.Lock() + defer a.explorersMu.Unlock() + + if exp, ok := a.explorers[id]; ok { + exp.Disconnect() + delete(a.explorers, id) + } +} + func (a *App) getExplorerForConnection(id string) (explorer.Explorer, error) { if id == "local" { return local.New(), nil @@ -160,38 +199,26 @@ func (a *App) getExplorerForConnection(id string) (explorer.Explorer, error) { } func (a *App) ListDir(connId, path string) ([]explorer.FileEntry, error) { - exp, err := a.getExplorerForConnection(connId) + exp, err := a.getConnection(connId) if err != nil { return nil, err } - if err := exp.Connect(); err != nil { - return nil, err - } - defer exp.Disconnect() return exp.ListDir(path) } func (a *App) MkDir(connId, path string) error { - exp, err := a.getExplorerForConnection(connId) + exp, err := a.getConnection(connId) if err != nil { return err } - if err := exp.Connect(); err != nil { - return err - } - defer exp.Disconnect() return exp.MkDir(path) } func (a *App) Delete(connId, path string) error { - exp, err := a.getExplorerForConnection(connId) + exp, err := a.getConnection(connId) if err != nil { return err } - if err := exp.Connect(); err != nil { - return err - } - defer exp.Disconnect() return exp.Delete(path) } @@ -225,14 +252,10 @@ func (a *App) ClearTransfers() { } func (a *App) Rename(connId, src, dst string) error { - exp, err := a.getExplorerForConnection(connId) + exp, err := a.getConnection(connId) if err != nil { return err } - if err := exp.Connect(); err != nil { - return err - } - defer exp.Disconnect() return exp.Rename(src, dst) } diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 8aca504..5f3c85a 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -11,6 +11,8 @@ export function Delete(arg1:string,arg2:string):Promise; export function DeleteConnection(arg1:string):Promise; +export function DisconnectConnection(arg1:string):Promise; + export function GetConnections():Promise>; export function GetTransfers():Promise>; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index 9b0e0d1..b5c6640 100755 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -14,6 +14,10 @@ export function DeleteConnection(arg1) { return window['go']['main']['App']['DeleteConnection'](arg1); } +export function DisconnectConnection(arg1) { + return window['go']['main']['App']['DisconnectConnection'](arg1); +} + export function GetConnections() { return window['go']['main']['App']['GetConnections'](); } diff --git a/internal/protocols/sftp/sftp.go b/internal/protocols/sftp/sftp.go index 4d04d71..c3b0cd1 100644 --- a/internal/protocols/sftp/sftp.go +++ b/internal/protocols/sftp/sftp.go @@ -9,10 +9,11 @@ import ( "strings" "time" - "github.com/pkg/sftp" - "golang.org/x/crypto/ssh" "goexplore/internal/config" "goexplore/internal/explorer" + + "github.com/pkg/sftp" + "golang.org/x/crypto/ssh" ) type SFTPExplorer struct { @@ -31,9 +32,9 @@ func (e *SFTPExplorer) Connect() error { if port == 0 { port = 22 } - + var authMethods []ssh.AuthMethod - + secretStr := strings.TrimSpace(e.secret) // Handle case where newlines might be escaped by mistake secretStr = strings.ReplaceAll(secretStr, "\\n", "\n") @@ -70,8 +71,8 @@ func (e *SFTPExplorer) Connect() error { })) config := &ssh.ClientConfig{ - User: e.cfg.Username, - Auth: authMethods, + User: e.cfg.Username, + Auth: authMethods, HostKeyCallback: ssh.InsecureIgnoreHostKey(), } @@ -102,9 +103,17 @@ func (e *SFTPExplorer) Disconnect() error { func (e *SFTPExplorer) ListDir(path string) ([]explorer.FileEntry, error) { if path == "" { - path = "." + if e.cfg.Bucket != "" { + path = e.cfg.Bucket + } else { + path = "/" + } + } else if path == "." { + path = "/" } + files, err := e.client.ReadDir(path) + if err != nil { return nil, err } diff --git a/main.go b/main.go index 7d90f1d..a7aee3e 100644 --- a/main.go +++ b/main.go @@ -27,6 +27,12 @@ func installLinux() { return } + for _, arg := range os.Args { + if arg == "--debug" { + return + } + } + exe, err := os.Executable() if err != nil { return -- 2.47.3