mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(desktop): clean up canceled pending sends
**Category:** fix **User Impact:** Canceling a deferred attachment during send preflight no longer leaves a phantom timeline row. Expose prepared-upload cancellation state so send staging cannot begin after the task was canceled, and defensively remove any adopted row when upload start loses the cancellation race. Extend focused coverage for pre-start cancellation and navigation-bound row identity. Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> Signed-off-by: Wes <wesbillman@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import test from "node:test";
|
||||
import {
|
||||
cancelStartedMediaUploads,
|
||||
dispatchTrackedMediaUpload,
|
||||
prepareBackgroundMediaUpload,
|
||||
} from "./backgroundMediaUploadStore.ts";
|
||||
|
||||
const descriptor = {
|
||||
@@ -22,6 +23,27 @@ function deferred() {
|
||||
return { promise, resolve };
|
||||
}
|
||||
|
||||
test("reports cancellation before a prepared upload starts", () => {
|
||||
const prepared = prepareBackgroundMediaUpload([
|
||||
{
|
||||
file: new File(["video"], "large-video.mp4", { type: "video/mp4" }),
|
||||
id: 1,
|
||||
spoilered: false,
|
||||
},
|
||||
]);
|
||||
|
||||
assert.equal(prepared.isCanceled(), false);
|
||||
prepared.cancel();
|
||||
assert.equal(prepared.isCanceled(), true);
|
||||
assert.equal(
|
||||
prepared.start({
|
||||
onComplete: async () => {},
|
||||
onError: () => {},
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("cancels only uploads whose native commands were dispatched", async () => {
|
||||
const releaseUpload = deferred();
|
||||
const startedProgressIds = new Map();
|
||||
|
||||
@@ -54,6 +54,7 @@ type StartBackgroundUploadOptions = Omit<
|
||||
|
||||
export type PreparedBackgroundMediaUpload = {
|
||||
cancel: () => void;
|
||||
isCanceled: () => boolean;
|
||||
start: (options: StartBackgroundUploadOptions) => boolean;
|
||||
};
|
||||
|
||||
@@ -243,6 +244,7 @@ export function prepareBackgroundMediaUpload(
|
||||
let started = false;
|
||||
return {
|
||||
cancel: () => undefined,
|
||||
isCanceled: () => false,
|
||||
start: ({ onComplete, onError }) => {
|
||||
if (started) return false;
|
||||
started = true;
|
||||
@@ -274,6 +276,7 @@ export function prepareBackgroundMediaUpload(
|
||||
cancel: () => {
|
||||
cancelTask(task);
|
||||
},
|
||||
isCanceled: () => task.canceled,
|
||||
start: ({ onCancel, onComplete, onError }) => {
|
||||
if (started || task.canceled) return false;
|
||||
started = true;
|
||||
|
||||
@@ -572,7 +572,7 @@ export function useMentionSendFlow({
|
||||
);
|
||||
}
|
||||
};
|
||||
if (!optimisticId && sendChannelId) {
|
||||
if (!optimisticId && sendChannelId && !preparedUpload?.isCanceled()) {
|
||||
const initialMessage = buildOutgoingMessage(
|
||||
draft.trimmed,
|
||||
draft.savedImeta,
|
||||
@@ -621,9 +621,7 @@ export function useMentionSendFlow({
|
||||
restoreComposerAfterFailure();
|
||||
},
|
||||
});
|
||||
if (!uploadStarted) {
|
||||
return;
|
||||
}
|
||||
if (!uploadStarted) return removePendingSend();
|
||||
}
|
||||
if (
|
||||
draft.capturedChannelId === channelIdRef.current ||
|
||||
|
||||
@@ -265,6 +265,12 @@ test("sends immediately and keeps upload progress across channels", async ({
|
||||
await expect(queuedSpoiler).toHaveCSS("opacity", "1");
|
||||
await page.getByTestId("send-message").click();
|
||||
|
||||
const pendingRow = page.getByTestId("message-row").last();
|
||||
await expect(
|
||||
pendingRow.getByTestId("message-preparation-status"),
|
||||
).toContainText("Preparing large-video.mp4…");
|
||||
const pendingMessageId = await pendingRow.getAttribute("data-message-id");
|
||||
expect(pendingMessageId).not.toBeNull();
|
||||
await expect(page.getByTestId("message-composer")).not.toContainText(
|
||||
"large-video.mp4",
|
||||
);
|
||||
@@ -278,6 +284,9 @@ test("sends immediately and keeps upload progress across channels", async ({
|
||||
});
|
||||
|
||||
await page.getByTestId("channel-general").click();
|
||||
await expect(
|
||||
page.locator(`[data-message-id="${pendingMessageId}"]`),
|
||||
).toHaveCount(1);
|
||||
await expect(page.getByTestId("file-card").last()).toContainText(
|
||||
"quarterly-report.pdf",
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user