From 68ecc4b033082dea93f76edc273521e5244e741c Mon Sep 17 00:00:00 2001 From: Codinget Date: Tue, 14 Apr 2026 22:58:13 +0000 Subject: [PATCH] feat(tsconnect): add notifyFilesWaiting and notifyIncomingFiles callbacks Wire two new callbacks into the IPN notify stream: - notifyFilesWaiting: fires when a completed inbound transfer is staged and ready to retrieve via waitingFiles(). Triggered by n.FilesWaiting in the notify stream. - notifyIncomingFiles: fires with a JSON snapshot of in-progress inbound transfers whenever progress changes (roughly once per second while active, plus once at completion). The jsIncomingFile struct carries name, started (Unix ms), declaredSize, and received bytes. An empty array indicates all active transfers have finished. Co-Authored-By: Claude Sonnet 4.6 --- cmd/tsconnect/wasm/wasm_js.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index 3834b255c..f3296346c 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -394,6 +394,25 @@ func (i *jsIPN) run(jsCallbacks js.Value) { if n.BrowseToURL != nil { jsCallbacks.Call("notifyBrowseToURL", *n.BrowseToURL) } + if n.FilesWaiting != nil { + jsCallbacks.Call("notifyFilesWaiting") + } + if n.IncomingFiles != nil { + files := make([]jsIncomingFile, len(n.IncomingFiles)) + for i, f := range n.IncomingFiles { + files[i] = jsIncomingFile{ + Name: f.Name, + Started: f.Started.UnixMilli(), + DeclaredSize: f.DeclaredSize, + Received: f.Received, + } + } + if b, err := json.Marshal(files); err == nil { + jsCallbacks.Call("notifyIncomingFiles", string(b)) + } else { + log.Printf("could not marshal IncomingFiles: %v", err) + } + } }) go func() { @@ -921,6 +940,15 @@ func (w termWriter) Write(p []byte) (n int, err error) { return len(p), nil } +// jsIncomingFile is the JSON representation of an in-progress inbound file +// transfer sent to the notifyIncomingFiles callback. +type jsIncomingFile struct { + Name string `json:"name"` + Started int64 `json:"started"` // Unix milliseconds; use new Date(started) in JS + DeclaredSize int64 `json:"declaredSize"` // -1 if unknown + Received int64 `json:"received"` // bytes received so far +} + type jsNetMap struct { Self jsNetMapSelfNode `json:"self"` Peers []jsNetMapPeerNode `json:"peers"`