web: fix message edits silently dropped (stale editing id) (#19)
The edit send in sendMessage read the module-level `editing` variable
inside the encrypt().then() callback, but cancelEdit() runs synchronously
right after and resets `editing` to null. By the time the async callback
fired, `editing` was already null, so the frame shipped as
`message_id: null` → Go unmarshals null into int64 as 0 → the hub's
`if in.MessageID <= 0 { continue }` silently dropped it. The edit never
reached editMessage, so nothing changed and no error surfaced.
Capture the id into a local before the async hop (as the pre-#17 code
did) so the sent frame carries the real message id.
Co-authored-by: Claude <noreply@anthropic.com>
1 file changed,
+6
−2
web/static/chat.js+6 −2
diff --git a/web/static/chat.js b/web/static/chat.js| index 3b1bc11..c6717b6 100644 |
| --- a/web/static/chat.js |
| +++ b/web/static/chat.js |
| @@ -1201,10 +1201,14 @@ function sendMessage(raw) { |
| // Editing an existing message: re-encrypt the original payload with new text |
| // (preserving its name + any attachments) and send an edit. |
| if (editing != null) { |
| - const orig = msgData[editing] && msgData[editing].data; |
| + // Capture the id before cancelEdit() (below) resets `editing` to null — the |
| + // encrypt().then() send is async, so reading `editing` inside it would race |
| + // and ship message_id: null, which the server drops. |
| + const id = editing; |
| + const orig = msgData[id] && msgData[id].data; |
| if (text && orig) { |
| encrypt(threadKeys[activeId], { ...orig, text }).then((blob) => { |
| - ws.send(JSON.stringify({ type: "edit", thread_id: activeId, message_id: editing, blob })); |
| + ws.send(JSON.stringify({ type: "edit", thread_id: activeId, message_id: id, blob })); |
| }); |
| } |
| cancelEdit(); |