| … | … | @@ -510,13 +484,19 @@ export function useThreadComposerState() { | |
| 510 | 484 | savingQueuedEditRef.current = false; | |
| 511 | 485 | setIsSavingQueuedEdit(false); | |
| 512 | 486 | if (result._tag !== "Success") { | |
| 487 | + | finishSave(false); | |
🟡 Medium state/use-thread-composer-state.ts:487
When editQueuedRun fails after the run leaves the queue, finishSave(false) resumes the exit watcher, which can discard the edit because the normal thread draft is occupied. This branch still says “Your edit is still in the composer,” so the user is told discarded work remains available; check whether the edit survived before showing that message.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
| 1 | In file @apps/mobile/src/state/use-thread-composer-state.ts around line 487: |
| 2 | |
| 3 | When `editQueuedRun` fails after the run leaves the queue, `finishSave(false)` resumes the exit watcher, which can discard the edit because the normal thread draft is occupied. This branch still says “Your edit is still in the composer,” so the user is told discarded work remains available; check whether the edit survived before showing that message. |
Fixed in afd5cc0b08. On failure, FinishQueuedRunEditSave now returns whether the edit is still open after its exit watch resumes. The hook skips the "still in the composer" alert when it returns false: the exit has already set the composer message (kept or discarded). The store test now asserts false when the run left the queue during the save, and a new test asserts true while the run is still queued. Web ignores the failure return, so it is unaffected.
I can’t verify this yet: afd5cc0b08 is not present on the PR head available to me, which still has the original behavior. Please push/update the ref and I’ll re-check.
| … | … | @@ -26,36 +33,58 @@ export interface QueuedRunEdit { | |
| 59 | + | const recovery = resolveQueuedEditExit({ | |
| 60 | + | editChanged: | |
| 61 | + | (editDraft.text.trim().length > 0 || editDraft.attachments.length > 0) && | |
| 62 | + | (editDraft.text !== edit.originalText || editDraft.attachments.length > 0), | |
🟡 Medium state/queued-run-edit.ts:62
Removing an existing attachment and then having the run leave the queue before save silently discards the edit: editChanged checks only text and draft uploads, so the removal from edit.existingAttachments is classified as clean and no composer error is shown. Include removals from the original attachment set (or an explicit dirty flag) in the change check so the edit takes the recovery path.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
| 1 | In file @apps/mobile/src/state/queued-run-edit.ts around line 62: |
| 2 | |
| 3 | Removing an existing attachment and then having the run leave the queue before save silently discards the edit: `editChanged` checks only text and draft uploads, so the removal from `edit.existingAttachments` is classified as `clean` and no composer error is shown. Include removals from the original attachment set (or an explicit dirty flag) in the change check so the edit takes the recovery path. |
Fixed in afd5cc0b08. removeQueuedRunEditAttachment now marks the edit removedExistingAttachment, and exitQueuedRunEdit counts that as a change. The edit then goes through the kept/discarded path and the thread shows the message. Test: "treats a removed server attachment as a change when the run starts".
I can’t find afd5cc0b08 on the current PR head; it still only filters existingAttachments and exitQueuedRunEdit does not consider removals. Could you push the referenced commit to this PR?
| … | … | @@ -1504,26 +1489,72 @@ export function ThreadSettingsPickerScreen( | |
| 1538 | + | providerGroups={groupByProvider(modelOptions)} | |
| 1539 | + | selectedModel={modelSelection} | |
| 1540 | + | prompt={prompt} | |
| 1541 | + | onPromptChange={(text) => setComposerDraftText(route.params.draftKey, text)} | |
🟡 Medium threads/ThreadSettingsSheet.tsx:1541
When a queued-message edit ends while this sheet is open, prompt changes are written to the cleared edit draft instead of the active thread draft, so the composer does not receive the change. onPromptChange always targets route.params.draftKey even after exitQueuedRunEdit switches the composer back to the thread draft; resolve the active draft key from queued-edit state or dismiss the sheet when the edit ends.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
| 1 | In file @apps/mobile/src/features/threads/ThreadSettingsSheet.tsx around line 1541: |
| 2 | |
| 3 | When a queued-message edit ends while this sheet is open, prompt changes are written to the cleared edit draft instead of the active thread draft, so the composer does not receive the change. `onPromptChange` always targets `route.params.draftKey` even after `exitQueuedRunEdit` switches the composer back to the thread draft; resolve the active draft key from queued-edit state or dismiss the sheet when the edit ends. |
Fixed in afd5cc0b08. The sheet now resolves its draft with activeComposerDraftKey: it uses the queued edit's draft only while that edit is still open, and the thread's own draft after that. Both the prompt it reads and onPromptChange use the resolved key. Covered in queued-run-edit.test.ts (activeComposerDraftKey).
I can’t verify this yet: afd5cc0b08 is not available on the PR head I can access, which still uses route.params.draftKey. Please share the full SHA or push the commit to the PR branch.