From ff5dd8c0069475026cf167f0a29c297b8e9a99d7 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Thu, 5 Mar 2026 16:58:04 -0800 Subject: [PATCH] fix: await saveDraft/saveToAutomerge in all image and share handlers All callers of saveDraft() and saveToAutomerge() in generateImage, uploadImage, uploadTweetImage, generateTweetImage, removeTweetImage, and share handler now properly await these async methods. Without await, runtime.change() fires before the Automerge doc subscription resolves, causing "Document not open" errors. Co-Authored-By: Claude Opus 4.6 --- .../components/folk-thread-builder.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/rsocials/components/folk-thread-builder.ts b/modules/rsocials/components/folk-thread-builder.ts index 4aa9b55..f7cf162 100644 --- a/modules/rsocials/components/folk-thread-builder.ts +++ b/modules/rsocials/components/folk-thread-builder.ts @@ -405,7 +405,7 @@ export class FolkThreadBuilder extends HTMLElement { // ── Draft management (Automerge) ── - private saveDraft() { + private async saveDraft() { const sr = this.shadowRoot; if (!sr) return; const textarea = sr.getElementById('thread-input') as HTMLTextAreaElement; @@ -435,8 +435,8 @@ export class FolkThreadBuilder extends HTMLElement { this._thread = thread; - // Save via Automerge - this.saveToAutomerge(thread); + // Save via Automerge (await ensures doc is open first) + await this.saveToAutomerge(thread); // Update URL history.replaceState(null, '', this.basePath + 'thread/' + this._threadId + '/edit'); @@ -562,7 +562,7 @@ export class FolkThreadBuilder extends HTMLElement { private async generateImage() { if (!this._threadId) { - this.saveDraft(); + await this.saveDraft(); if (!this._threadId) return; } @@ -588,7 +588,7 @@ export class FolkThreadBuilder extends HTMLElement { // Update Automerge with new image URL if (this._thread) { this._thread.imageUrl = data.imageUrl; - this.saveToAutomerge(this._thread); + await this.saveToAutomerge(this._thread); } } else { genBtn.textContent = 'Generation Failed'; @@ -604,7 +604,7 @@ export class FolkThreadBuilder extends HTMLElement { private async uploadImage(file: File) { if (!this._threadId) { - this.saveDraft(); + await this.saveDraft(); if (!this._threadId) return; } @@ -631,7 +631,7 @@ export class FolkThreadBuilder extends HTMLElement { genBtn.textContent = 'Replace with AI'; if (this._thread) { this._thread.imageUrl = data.imageUrl; - this.saveToAutomerge(this._thread); + await this.saveToAutomerge(this._thread); } } else { uploadBtn.textContent = data.error || 'Upload Failed'; @@ -647,7 +647,7 @@ export class FolkThreadBuilder extends HTMLElement { private async uploadTweetImage(index: string, file: File) { if (!this._threadId) { - this.saveDraft(); + await this.saveDraft(); if (!this._threadId) return; } @@ -660,7 +660,7 @@ export class FolkThreadBuilder extends HTMLElement { this._tweetImages[index] = data.imageUrl; if (this._thread) { this._thread.tweetImages = { ...this._tweetImages }; - this.saveToAutomerge(this._thread); + await this.saveToAutomerge(this._thread); } this.renderPreview(); } @@ -669,7 +669,7 @@ export class FolkThreadBuilder extends HTMLElement { private async generateTweetImage(index: string) { if (!this._threadId) { - this.saveDraft(); + await this.saveDraft(); if (!this._threadId) return; } @@ -684,7 +684,7 @@ export class FolkThreadBuilder extends HTMLElement { this._tweetImages[index] = data.imageUrl; if (this._thread) { this._thread.tweetImages = { ...this._tweetImages }; - this.saveToAutomerge(this._thread); + await this.saveToAutomerge(this._thread); } this.renderPreview(); } else if (btn) { @@ -703,7 +703,7 @@ export class FolkThreadBuilder extends HTMLElement { delete this._tweetImages[index]; if (this._thread) { this._thread.tweetImages = Object.keys(this._tweetImages).length ? { ...this._tweetImages } : undefined; - this.saveToAutomerge(this._thread); + await this.saveToAutomerge(this._thread); } this.renderPreview(); } catch (e) { console.error('Tweet image removal failed:', e); } @@ -919,7 +919,7 @@ export class FolkThreadBuilder extends HTMLElement { shareBtn.disabled = true; try { - this.saveDraft(); + await this.saveDraft(); if (!this._threadId) { shareBtn.textContent = 'Share'; shareBtn.disabled = false; return; } if (imagePreview?.hidden) {