fix: stop URL-encoding drag-out filenames and preserve Unicode letters
This commit is contained in:
@@ -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],
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { Email } from "@/lib/jmap/types";
|
||||
|
||||
// Restrict filenames to ASCII letters/digits and a small set of safe
|
||||
// punctuation. Everything else collapses to `_`. Keeps names predictable
|
||||
// across Windows/macOS/Linux file systems and avoids emoji/RTL/zero-width
|
||||
// surprises in subject lines.
|
||||
const SAFE_CHARS = /[^A-Za-z0-9 _\-().,!@#&+=[\]{}']/g;
|
||||
// Allow any Unicode letter or digit (so umlauts, accents, CJK survive) plus a
|
||||
// small set of safe punctuation. Everything else - emojis, RTL/zero-width
|
||||
// marks, control chars, and the filesystem-reserved `<>:"/\|?*` - collapses
|
||||
// to `_`. Keeps filenames usable across Windows/macOS/Linux without flattening
|
||||
// non-ASCII scripts.
|
||||
const SAFE_CHARS = /[^\p{L}\p{N} _\-().,!@#&+=[\]{}']/gu;
|
||||
|
||||
export const DEFAULT_EMAIL_TEMPLATE = "{date} ({from}-{to}) {subject}";
|
||||
export const DEFAULT_ATTACHMENT_TEMPLATE = "{filename}";
|
||||
|
||||
Reference in New Issue
Block a user