mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-13 19:46:16 +03:00
fix(app): allow removing pending attachment uploads (#55836)
This commit is contained in:
committed by
GitHub
Unverified
parent
0489de252a
commit
dd3266a14b
@@ -42,6 +42,7 @@ export function useAttachmentDestination(controls: Accessor<ComposerControls>) {
|
||||
// from disk; nothing is buffered in the renderer.
|
||||
function write(url: URL, file: File, password: string | undefined, report: (loaded: number) => void, signal: AbortSignal) {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
if (signal.aborted) return reject(new DOMException("Upload aborted", "AbortError"))
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.open("POST", url)
|
||||
xhr.responseType = "json"
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { expect, test } from "bun:test"
|
||||
import { uploads } from "./uploads"
|
||||
|
||||
test("cancelling an upload drops it even when its work never settles", async () => {
|
||||
const pending = uploads.track({ id: "stalled", filename: "image.png", mime: "image/png", size: 1024 }, () =>
|
||||
new Promise<string>(() => {}),
|
||||
)
|
||||
|
||||
expect(uploads.items().map((item) => item.id)).toEqual(["stalled"])
|
||||
uploads.items()[0]?.cancel()
|
||||
|
||||
expect(await pending).toBeUndefined()
|
||||
expect(uploads.items()).toEqual([])
|
||||
})
|
||||
@@ -25,13 +25,20 @@ export const uploads = {
|
||||
work: (report: (loaded: number) => void, signal: AbortSignal) => Promise<T>,
|
||||
): Promise<T | undefined> {
|
||||
const controller = new AbortController()
|
||||
|
||||
// The work may wait where it cannot observe the signal, such as a request queued behind
|
||||
// others, so cancelling settles without it.
|
||||
const cancelled = new Promise<undefined>((resolve) =>
|
||||
controller.signal.addEventListener("abort", () => resolve(undefined), { once: true }),
|
||||
)
|
||||
|
||||
setState("items", (items) => [...items, { ...input, loaded: 0, cancel: () => controller.abort() }])
|
||||
|
||||
try {
|
||||
return await work(
|
||||
(loaded) => setState("items", (item) => item.id === input.id, "loaded", loaded),
|
||||
controller.signal,
|
||||
)
|
||||
return await Promise.race([
|
||||
work((loaded) => setState("items", (item) => item.id === input.id, "loaded", loaded), controller.signal),
|
||||
cancelled,
|
||||
])
|
||||
} catch (error) {
|
||||
if (controller.signal.aborted) return undefined
|
||||
throw error
|
||||
|
||||
Reference in New Issue
Block a user