fix: stop URL-encoding drag-out filenames and preserve Unicode letters

This commit is contained in:
Linus Rath
2026-05-22 14:49:17 +02:00
parent ca0d6805cf
commit 0dca019fe5
3 changed files with 18 additions and 12 deletions
+5 -3
View File
@@ -92,9 +92,11 @@ export function useAttachmentDrag(
return;
}
// `DownloadURL` format: <mime>:<filename>:<url>. Chromium reads this on
// drop and writes a real file at the destination.
e.dataTransfer.setData("DownloadURL", `${type}:${encodeURIComponent(name)}:${url}`);
// `DownloadURL` format: <mime>:<filename>:<url>. The filename must be
// raw - URL-encoding it lands literally on disk (`%20` instead of a
// space). Callers are expected to sanitise reserved chars (`:` etc.)
// beforehand.
e.dataTransfer.setData("DownloadURL", `${type}:${name}:${url}`);
e.dataTransfer.effectAllowed = "copyMove";
},
[source.name, source.type, prefetch],
+7 -4
View File
@@ -206,11 +206,14 @@ export function useEmailDrag({ email, sourceMailboxId, threadEmails }: UseEmailD
const url = singleBlobUrlRef.current;
if (url) {
const name = emailExportFilename(emailsToDrag[0], emailTemplate);
// `DownloadURL` format: <mime>:<filename>:<url>. Chromium reads this
// on drop and writes a real file; Firefox/Safari ignore it.
// `DownloadURL` format: <mime>:<filename>:<url>. Chromium expects
// the filename raw - URL-encoding it ends up literally on disk
// (e.g. `%20` instead of a space). The sanitiser already removed
// `:` and other reserved chars, so embedding the name as-is is
// safe. Firefox/Safari ignore this entry entirely.
e.dataTransfer.setData(
"DownloadURL",
`message/rfc822:${encodeURIComponent(name)}:${url}`,
`message/rfc822:${name}:${url}`,
);
} else {
// Not warmed up yet — kick off so the next attempt works. Don't
@@ -222,7 +225,7 @@ export function useEmailDrag({ email, sourceMailboxId, threadEmails }: UseEmailD
if (ready) {
e.dataTransfer.setData(
"DownloadURL",
`application/zip:${encodeURIComponent(ready.name)}:${ready.url}`,
`application/zip:${ready.name}:${ready.url}`,
);
} else {
// Kick off the bundle build for the next attempt.