Skip to content

Commit c9c4ae5

Browse files
authored
Merge pull request #486 from easyops-cn/steve/rename-paste-image
fix(): rename pasted images
2 parents 710a29b + 8fe4cd9 commit c9c4ae5

File tree

2 files changed

+139
-1
lines changed

2 files changed

+139
-1
lines changed

bricks/ai-portal/src/shared/useFilesUploading.spec.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,128 @@ describe("useFilesUploading", () => {
178178

179179
expect(result.current.allFilesDone).toBe(false);
180180
});
181+
182+
describe("paste", () => {
183+
const createPasteEvent = (files: File[]) => {
184+
const dataTransfer = {
185+
files: files as unknown as FileList,
186+
};
187+
return {
188+
clipboardData: dataTransfer,
189+
preventDefault: jest.fn(),
190+
stopPropagation: jest.fn(),
191+
} as unknown as React.ClipboardEvent<HTMLTextAreaElement>;
192+
};
193+
194+
it("should do nothing when not enabled", async () => {
195+
const { result } = renderHook(() =>
196+
useFilesUploading({ enabled: false })
197+
);
198+
199+
const pasteEvent = createPasteEvent([new File(["test"], "test.txt")]);
200+
201+
act(() => {
202+
result.current.paste(pasteEvent);
203+
});
204+
205+
expect(pasteEvent.preventDefault).not.toHaveBeenCalled();
206+
expect(result.current.files).toBeUndefined();
207+
});
208+
209+
it("should do nothing when no files in clipboard", async () => {
210+
const { result } = renderHook(() => useFilesUploading({ enabled: true }));
211+
212+
const pasteEvent = createPasteEvent([]);
213+
214+
act(() => {
215+
result.current.paste(pasteEvent);
216+
});
217+
218+
expect(pasteEvent.preventDefault).not.toHaveBeenCalled();
219+
expect(result.current.files).toBeUndefined();
220+
});
221+
222+
it("should handle pasted files", async () => {
223+
const { result } = renderHook(() => useFilesUploading({ enabled: true }));
224+
225+
const pasteEvent = createPasteEvent([new File(["test"], "test.txt")]);
226+
227+
act(() => {
228+
result.current.paste(pasteEvent);
229+
});
230+
231+
expect(pasteEvent.preventDefault).toHaveBeenCalled();
232+
expect(pasteEvent.stopPropagation).toHaveBeenCalled();
233+
expect(result.current.files?.length).toBe(1);
234+
expect(result.current.files?.[0].file.name).toBe("test.txt");
235+
236+
await act(async () => {
237+
await (global as any).flushPromises();
238+
});
239+
});
240+
241+
it("should rename pasted image.png to unique name", async () => {
242+
const { result } = renderHook(() => useFilesUploading({ enabled: true }));
243+
244+
const pasteEvent = createPasteEvent([
245+
new File(["image data"], "image.png", { type: "image/png" }),
246+
]);
247+
248+
act(() => {
249+
result.current.paste(pasteEvent);
250+
});
251+
252+
expect(result.current.files?.length).toBe(1);
253+
expect(result.current.files?.[0].file.name).toMatch(
254+
/^pasted-image-\d+-\d+\.png$/
255+
);
256+
expect(result.current.files?.[0].file.type).toBe("image/png");
257+
258+
await act(async () => {
259+
await (global as any).flushPromises();
260+
});
261+
});
262+
263+
it("should not rename non-image.png files", async () => {
264+
const { result } = renderHook(() => useFilesUploading({ enabled: true }));
265+
266+
const pasteEvent = createPasteEvent([
267+
new File(["image data"], "screenshot.png", { type: "image/png" }),
268+
]);
269+
270+
act(() => {
271+
result.current.paste(pasteEvent);
272+
});
273+
274+
expect(result.current.files?.length).toBe(1);
275+
expect(result.current.files?.[0].file.name).toBe("screenshot.png");
276+
277+
await act(async () => {
278+
await (global as any).flushPromises();
279+
});
280+
});
281+
282+
it("should handle multiple pasted files", async () => {
283+
const { result } = renderHook(() => useFilesUploading({ enabled: true }));
284+
285+
const pasteEvent = createPasteEvent([
286+
new File(["test1"], "file1.txt"),
287+
new File(["image data"], "image.png", { type: "image/png" }),
288+
]);
289+
290+
act(() => {
291+
result.current.paste(pasteEvent);
292+
});
293+
294+
expect(result.current.files?.length).toBe(2);
295+
expect(result.current.files?.[0].file.name).toBe("file1.txt");
296+
expect(result.current.files?.[1].file.name).toMatch(
297+
/^pasted-image-\d+-\d+\.png$/
298+
);
299+
300+
await act(async () => {
301+
await (global as any).flushPromises();
302+
});
303+
});
304+
});
181305
});

bricks/ai-portal/src/shared/useFilesUploading.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export function useFilesUploading(options?: UploadOptions) {
141141
const files = [...fileList];
142142
const allFilesAccepted = validateFiles(files, options!);
143143
if (allFilesAccepted) {
144-
appendFiles(files);
144+
appendFiles(files.map(renamePastedImage));
145145
}
146146
}
147147
},
@@ -160,3 +160,17 @@ export function useFilesUploading(options?: UploadOptions) {
160160
paste,
161161
};
162162
}
163+
164+
function renamePastedImage(originalFile: File): File {
165+
if (originalFile.name === "image.png") {
166+
return new File(
167+
[originalFile],
168+
`pasted-image-${Date.now()}-${getNextUid()}.png`,
169+
{
170+
type: originalFile.type,
171+
lastModified: originalFile.lastModified,
172+
}
173+
);
174+
}
175+
return originalFile;
176+
}

0 commit comments

Comments
 (0)