From 33c26ec3109ca210953cf08dd9ea0e939ae2c737 Mon Sep 17 00:00:00 2001 From: Jamie Banks Date: Tue, 9 Jun 2026 15:22:41 +0100 Subject: [PATCH 1/4] fix: improve private key parsing by handling escaped newlines and whitespace in credentials --- internal/protocols/sftp/sftp.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/internal/protocols/sftp/sftp.go b/internal/protocols/sftp/sftp.go index 4e37775..df1eadc 100644 --- a/internal/protocols/sftp/sftp.go +++ b/internal/protocols/sftp/sftp.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "path/filepath" + "strings" "time" "github.com/pkg/sftp" @@ -32,8 +33,16 @@ func (e *SFTPExplorer) Connect() error { } var authMethod ssh.AuthMethod - signer, err := ssh.ParsePrivateKey([]byte(e.secret)) - if err == nil { + + secretStr := strings.TrimSpace(e.secret) + // Handle case where newlines might be escaped by mistake + secretStr = strings.ReplaceAll(secretStr, "\\n", "\n") + + if strings.Contains(secretStr, "-----BEGIN") { + signer, err := ssh.ParsePrivateKey([]byte(secretStr)) + if err != nil { + return fmt.Errorf("failed to parse private key: %w", err) + } authMethod = ssh.PublicKeys(signer) } else { authMethod = ssh.Password(e.secret) -- 2.47.3 From e6b806d2c1398efe640485883252c91ff02cbe72 Mon Sep 17 00:00:00 2001 From: Jamie Banks Date: Tue, 9 Jun 2026 15:26:05 +0100 Subject: [PATCH 2/4] feat: implement drag-and-drop connection reordering --- app.go | 28 +++++++++++++++++++ frontend/src/main.js | 39 ++++++++++++++++++++++++++- frontend/wailsjs/go/main/App.d.ts | 6 +++-- frontend/wailsjs/go/main/App.js | 12 ++++++--- frontend/wailsjs/go/models.ts | 6 +++++ frontend/wailsjs/runtime/package.json | 0 frontend/wailsjs/runtime/runtime.d.ts | 0 frontend/wailsjs/runtime/runtime.js | 0 8 files changed, 84 insertions(+), 7 deletions(-) mode change 100644 => 100755 frontend/wailsjs/runtime/package.json mode change 100644 => 100755 frontend/wailsjs/runtime/runtime.d.ts mode change 100644 => 100755 frontend/wailsjs/runtime/runtime.js diff --git a/app.go b/app.go index 6a03dfa..eb8b2a0 100644 --- a/app.go +++ b/app.go @@ -95,6 +95,34 @@ func (a *App) DeleteConnection(id string) error { return config.SaveConfig(a.cfg) } +func (a *App) ReorderConnections(ids []string) error { + var newConns []config.ConnectionConfig + connMap := make(map[string]config.ConnectionConfig) + for _, c := range a.cfg.Connections { + connMap[c.ID] = c + } + + for _, id := range ids { + if c, ok := connMap[id]; ok { + newConns = append(newConns, c) + } + } + + // Add any connections that might have been missed + added := make(map[string]bool) + for _, c := range newConns { + added[c.ID] = true + } + for _, c := range a.cfg.Connections { + if !added[c.ID] { + newConns = append(newConns, c) + } + } + + a.cfg.Connections = newConns + return config.SaveConfig(a.cfg) +} + func (a *App) getExplorerForConnection(id string) (explorer.Explorer, error) { if id == "local" { return local.New(), nil diff --git a/frontend/src/main.js b/frontend/src/main.js index 50b03d1..a6d943f 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -1,4 +1,4 @@ -import { GetVersion, ListDir, GetConnections, SaveConnection, DeleteConnection, Delete, Rename, PromptUploadFiles, PromptUploadDirectory, PromptDownload, TransferItems, GetTransfers, ClearTransfers } from '../wailsjs/go/main/App.js'; +import { GetVersion, ListDir, GetConnections, SaveConnection, DeleteConnection, Delete, Rename, PromptUploadFiles, PromptUploadDirectory, PromptDownload, TransferItems, GetTransfers, ClearTransfers, ReorderConnections } from '../wailsjs/go/main/App.js'; let currentConn = 'local'; let currentPath = ''; @@ -8,6 +8,7 @@ let lastSelectedPath = null; let showHiddenFiles = false; let sortField = 'name'; let sortAsc = true; +let draggedConnId = null; function uuidv4() { return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => @@ -79,6 +80,42 @@ async function loadConnections() { el.className = `conn-item ${currentConn === c.id ? 'active' : ''}`; el.innerHTML = `${c.protocol} ${c.name} `; el.onclick = () => switchConn(c.id); + + el.draggable = true; + el.addEventListener('dragstart', (e) => { + draggedConnId = c.id; + e.dataTransfer.effectAllowed = 'move'; + el.style.opacity = '0.5'; + }); + el.addEventListener('dragend', () => { + draggedConnId = null; + el.style.opacity = '1'; + }); + el.addEventListener('dragover', (e) => { + e.preventDefault(); + e.dataTransfer.dropEffect = 'move'; + }); + el.addEventListener('drop', async (e) => { + e.preventDefault(); + if (!draggedConnId || draggedConnId === c.id) return; + + const ids = connectionsCache.map(conn => conn.id); + const draggedIdx = ids.indexOf(draggedConnId); + const targetIdx = ids.indexOf(c.id); + + if (draggedIdx !== -1 && targetIdx !== -1) { + ids.splice(draggedIdx, 1); + ids.splice(targetIdx, 0, draggedConnId); + + try { + await ReorderConnections(ids); + await loadConnections(); + } catch (err) { + console.error("Failed to reorder connections:", err); + } + } + }); + list.appendChild(el); }); } diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index c3f43c3..8aca504 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -27,10 +27,12 @@ export function PromptUploadDirectory(arg1:string,arg2:string):Promise; export function PromptUploadFiles(arg1:string,arg2:string):Promise; -export function QueueTransfer(arg1:string,arg2:string,arg3:string,arg4:string,arg5:string,arg6:string,arg7:number):Promise; +export function QueueTransfer(arg1:string,arg2:string,arg3:string,arg4:string,arg5:string,arg6:string,arg7:number,arg8:boolean,arg9:number):Promise; export function Rename(arg1:string,arg2:string,arg3:string):Promise; +export function ReorderConnections(arg1:Array):Promise; + export function SaveConnection(arg1:config.ConnectionConfig,arg2:string):Promise; -export function TransferItems(arg1:string,arg2:string,arg3:string,arg4:Array):Promise; +export function TransferItems(arg1:string,arg2:string,arg3:string,arg4:Array,arg5:boolean,arg6:number):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index 1e0950e..9b0e0d1 100755 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -46,18 +46,22 @@ export function PromptUploadFiles(arg1, arg2) { return window['go']['main']['App']['PromptUploadFiles'](arg1, arg2); } -export function QueueTransfer(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { - return window['go']['main']['App']['QueueTransfer'](arg1, arg2, arg3, arg4, arg5, arg6, arg7); +export function QueueTransfer(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) { + return window['go']['main']['App']['QueueTransfer'](arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } export function Rename(arg1, arg2, arg3) { return window['go']['main']['App']['Rename'](arg1, arg2, arg3); } +export function ReorderConnections(arg1) { + return window['go']['main']['App']['ReorderConnections'](arg1); +} + export function SaveConnection(arg1, arg2) { return window['go']['main']['App']['SaveConnection'](arg1, arg2); } -export function TransferItems(arg1, arg2, arg3, arg4) { - return window['go']['main']['App']['TransferItems'](arg1, arg2, arg3, arg4); +export function TransferItems(arg1, arg2, arg3, arg4, arg5, arg6) { + return window['go']['main']['App']['TransferItems'](arg1, arg2, arg3, arg4, arg5, arg6); } diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index c32dbbd..61fed85 100755 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -9,6 +9,7 @@ export namespace config { bucket?: string; region?: string; path_style?: boolean; + secure?: boolean; username?: string; keychain_key?: string; @@ -26,6 +27,7 @@ export namespace config { this.bucket = source["bucket"]; this.region = source["region"]; this.path_style = source["path_style"]; + this.secure = source["secure"]; this.username = source["username"]; this.keychain_key = source["keychain_key"]; } @@ -96,6 +98,8 @@ export namespace transfer { eta_seconds: number; status: string; error?: string; + verify: boolean; + limit_mbps: number; static createFrom(source: any = {}) { return new Transfer(source); @@ -113,6 +117,8 @@ export namespace transfer { this.eta_seconds = source["eta_seconds"]; this.status = source["status"]; this.error = source["error"]; + this.verify = source["verify"]; + this.limit_mbps = source["limit_mbps"]; } } diff --git a/frontend/wailsjs/runtime/package.json b/frontend/wailsjs/runtime/package.json old mode 100644 new mode 100755 diff --git a/frontend/wailsjs/runtime/runtime.d.ts b/frontend/wailsjs/runtime/runtime.d.ts old mode 100644 new mode 100755 diff --git a/frontend/wailsjs/runtime/runtime.js b/frontend/wailsjs/runtime/runtime.js old mode 100644 new mode 100755 -- 2.47.3 From d34e919f4004b26c906fbefc923282ad61e34913 Mon Sep 17 00:00:00 2001 From: Jamie Banks Date: Tue, 9 Jun 2026 15:28:27 +0100 Subject: [PATCH 3/4] feat: add support for NFS protocol with dynamic UI field updates and visibility toggles --- frontend/index.html | 6 +++--- frontend/src/main.js | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index fd034e3..a00285e 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -95,7 +95,7 @@ -
+
@@ -104,7 +104,7 @@