fix: stop URL-encoding drag-out filenames and preserve Unicode letters
This commit is contained in:
@@ -92,9 +92,11 @@ export function useAttachmentDrag(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// `DownloadURL` format: <mime>:<filename>:<url>. Chromium reads this on
|
// `DownloadURL` format: <mime>:<filename>:<url>. The filename must be
|
||||||
// drop and writes a real file at the destination.
|
// raw - URL-encoding it lands literally on disk (`%20` instead of a
|
||||||
e.dataTransfer.setData("DownloadURL", `${type}:${encodeURIComponent(name)}:${url}`);
|
// space). Callers are expected to sanitise reserved chars (`:` etc.)
|
||||||
|
// beforehand.
|
||||||
|
e.dataTransfer.setData("DownloadURL", `${type}:${name}:${url}`);
|
||||||
e.dataTransfer.effectAllowed = "copyMove";
|
e.dataTransfer.effectAllowed = "copyMove";
|
||||||
},
|
},
|
||||||
[source.name, source.type, prefetch],
|
[source.name, source.type, prefetch],
|
||||||
|
|||||||
@@ -206,11 +206,14 @@ export function useEmailDrag({ email, sourceMailboxId, threadEmails }: UseEmailD
|
|||||||
const url = singleBlobUrlRef.current;
|
const url = singleBlobUrlRef.current;
|
||||||
if (url) {
|
if (url) {
|
||||||
const name = emailExportFilename(emailsToDrag[0], emailTemplate);
|
const name = emailExportFilename(emailsToDrag[0], emailTemplate);
|
||||||
// `DownloadURL` format: <mime>:<filename>:<url>. Chromium reads this
|
// `DownloadURL` format: <mime>:<filename>:<url>. Chromium expects
|
||||||
// on drop and writes a real file; Firefox/Safari ignore it.
|
// 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(
|
e.dataTransfer.setData(
|
||||||
"DownloadURL",
|
"DownloadURL",
|
||||||
`message/rfc822:${encodeURIComponent(name)}:${url}`,
|
`message/rfc822:${name}:${url}`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Not warmed up yet — kick off so the next attempt works. Don't
|
// 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) {
|
if (ready) {
|
||||||
e.dataTransfer.setData(
|
e.dataTransfer.setData(
|
||||||
"DownloadURL",
|
"DownloadURL",
|
||||||
`application/zip:${encodeURIComponent(ready.name)}:${ready.url}`,
|
`application/zip:${ready.name}:${ready.url}`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Kick off the bundle build for the next attempt.
|
// Kick off the bundle build for the next attempt.
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import type { Email } from "@/lib/jmap/types";
|
import type { Email } from "@/lib/jmap/types";
|
||||||
|
|
||||||
// Restrict filenames to ASCII letters/digits and a small set of safe
|
// Allow any Unicode letter or digit (so umlauts, accents, CJK survive) plus a
|
||||||
// punctuation. Everything else collapses to `_`. Keeps names predictable
|
// small set of safe punctuation. Everything else - emojis, RTL/zero-width
|
||||||
// across Windows/macOS/Linux file systems and avoids emoji/RTL/zero-width
|
// marks, control chars, and the filesystem-reserved `<>:"/\|?*` - collapses
|
||||||
// surprises in subject lines.
|
// to `_`. Keeps filenames usable across Windows/macOS/Linux without flattening
|
||||||
const SAFE_CHARS = /[^A-Za-z0-9 _\-().,!@#&+=[\]{}']/g;
|
// non-ASCII scripts.
|
||||||
|
const SAFE_CHARS = /[^\p{L}\p{N} _\-().,!@#&+=[\]{}']/gu;
|
||||||
|
|
||||||
export const DEFAULT_EMAIL_TEMPLATE = "{date} ({from}-{to}) {subject}";
|
export const DEFAULT_EMAIL_TEMPLATE = "{date} ({from}-{to}) {subject}";
|
||||||
export const DEFAULT_ATTACHMENT_TEMPLATE = "{filename}";
|
export const DEFAULT_ATTACHMENT_TEMPLATE = "{filename}";
|
||||||
|
|||||||
Reference in New Issue
Block a user