Skip to content

Commit 2137541

Browse files
fix(mobile): a context paste cancelled as its last copy finishes releases its files
Co-Authored-By: Claude Opus 5.5 <[email protected]>
1 parent b24344d commit 2137541

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

‎apps/mobile/src/lib/composerContextClipboard.test.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,24 @@ describe("mobile context clipboard imports", () => {
169169
expect(mocks.dispose).toHaveBeenCalledOnce();
170170
});
171171

172+
it("releases its files if cancelled after the last copy finishes", async () => {
173+
const controller = new AbortController();
174+
mocks.dispose.mockImplementationOnce(() => controller.abort());
175+
const imageOnly = {
176+
text: "![Checkout](t3-context://v1/image/image-source)",
177+
fragment: encodeComposerContextFragment({
178+
version: 1,
179+
source: { environmentId: EnvironmentId.make("source") },
180+
records: [image],
181+
})!,
182+
html: "",
183+
};
184+
await expect(importComposerContextClipboard(imageOnly, 0, controller.signal)).rejects.toThrow(
185+
"cancelled",
186+
);
187+
expect(mocks.remove).toHaveBeenCalledWith("file:///owned.png");
188+
});
189+
172190
it("can copy an image before its source upload completes", async () => {
173191
mocks.local.mockReturnValue({
174192
id: "source-file",

‎apps/mobile/src/lib/composerContextClipboard.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ export async function importComposerContextClipboard(
106106
failures.push(record.name);
107107
}
108108
}
109+
// The last copy can be cancelled after its own check; a cancelled import must not return files nobody will release.
110+
checkAborted(signal);
109111
return {
110112
text: imported.text,
111113
context: { version: 1 as const, records },

0 commit comments

Comments
 (0)