fix(chat): a file-manager copy pasted on a local browser attaches by its own path
Chrome gives a PASTE of a file manager's copy (Ctrl+C in Nautilus, Ctrl+V in the chat) the files and their paths as plain text, but no text/uri-list — only a drag carries that — so localCandidates found no path and every such file was uploaded, and refused past the upload limit. Plain-text paths (or file:// lines) whose names match the pasted files one for one are now candidates too; sameFilesHere still has the server confirm each is the same file (size) on this machine, so server mode and remote browsers upload as before. The prompt box also attaches a file:// text paste with no file by path, as the terminal already did (copiedFilePaths moved to promptAttach).
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
||||
*/
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { claudePastes } from "../promptAttach";
|
||||
import { claudePastes, copiedFilePaths, localCandidates } from "../promptAttach";
|
||||
|
||||
describe("claudePastes", () => {
|
||||
it("pastes each image as its bare path and the other files as one @ mention paste", () => {
|
||||
@@ -18,3 +18,46 @@ describe("claudePastes", () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
/** A clipboard as the browser hands it to a paste handler. */
|
||||
const clip = (data: Record<string, string>) =>
|
||||
({ getData: (t: string) => data[t] ?? "" }) as unknown as DataTransfer;
|
||||
const file = (name: string) => new File(["x"], name);
|
||||
|
||||
describe("localCandidates (a file manager's copy, pasted)", () => {
|
||||
it("takes the plain-text paths when their names match the pasted files", () => {
|
||||
expect(window.location.hostname).toBe("localhost");
|
||||
const dt = clip({ "text/plain": "/home/u/Videos/big.mp4\n/home/u/b c.pdf\n" });
|
||||
expect(localCandidates(dt, [file("b c.pdf"), file("big.mp4")])).toEqual([
|
||||
"/home/u/Videos/big.mp4",
|
||||
"/home/u/b c.pdf",
|
||||
]);
|
||||
});
|
||||
|
||||
it("takes file:// lines too, decoded", () => {
|
||||
const dt = clip({ "text/plain": "file:///home/u/a%20b.zip" });
|
||||
expect(localCandidates(dt, [file("a b.zip")])).toEqual(["/home/u/a b.zip"]);
|
||||
});
|
||||
|
||||
it("refuses text that does not name exactly the pasted files", () => {
|
||||
expect(localCandidates(clip({ "text/plain": "/etc/passwd" }), [file("big.mp4")])).toBeNull();
|
||||
expect(localCandidates(clip({ "text/plain": "hello" }), [file("hello")])).toBeNull();
|
||||
expect(
|
||||
localCandidates(clip({ "text/plain": "/a/x.txt" }), [file("x.txt"), file("y.txt")])
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("prefers a uri-list (a drag) as before", () => {
|
||||
const dt = clip({ "text/uri-list": "file:///tmp/z.bin", "text/plain": "/other/z.bin" });
|
||||
expect(localCandidates(dt, [file("z.bin")])).toEqual(["/tmp/z.bin"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("copiedFilePaths (no file beside the text)", () => {
|
||||
it("takes file:// text, never bare absolute paths, which stay text to paste", () => {
|
||||
expect(copiedFilePaths(clip({ "text/plain": "file:///home/u/a.txt" }))).toEqual([
|
||||
"/home/u/a.txt",
|
||||
]);
|
||||
expect(copiedFilePaths(clip({ "text/plain": "/home/u/a.txt" }))).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user