FEATURE: Allow users to paste animated gifs into composer (#16204)
If a user copies a gif from a website into their clipboard and then tries to paste it into the Discourse composer, we would only paste a static single frame of the original gif. This happens because the browser doesn't store the original image in the clipboard, but two entries: 1. image/png with the frame of the copy moment 2. text/html with the markup of the gif img element This commit adds an heuristic that detects this and makes us pick the clipboard content of text/html instead of the image/png when this happens. From there our existing HTML paste logic handles and converts the HTML img tag into markdown, preserving even the alt text. See https://meta.discourse.org/t/-/218720 for context.
This commit is contained in:
parent
3b8ff1184f
commit
d678ba1103
|
@ -349,6 +349,15 @@ const toArray = (items) => {
|
|||
return items;
|
||||
};
|
||||
|
||||
const gifInDisguise = (clipboard) => {
|
||||
return (
|
||||
clipboard.files.length === 1 &&
|
||||
clipboard.files[0].type === "image/png" &&
|
||||
clipboard.types.every((e) => ["text/html", "Files"].includes(e)) &&
|
||||
/<img.*src=.*\.gif/.test(clipboard.getData("text/html"))
|
||||
);
|
||||
};
|
||||
|
||||
export function clipboardHelpers(e, opts) {
|
||||
const clipboard =
|
||||
e.clipboardData ||
|
||||
|
@ -365,7 +374,9 @@ export function clipboardHelpers(e, opts) {
|
|||
|
||||
let canUpload = files && opts.canUpload && types.includes("Files");
|
||||
const canUploadImage =
|
||||
canUpload && files.filter((f) => f.type.match("^image/"))[0];
|
||||
canUpload &&
|
||||
files.filter((f) => f.type.match("^image/"))[0] &&
|
||||
!gifInDisguise(clipboard);
|
||||
const canPasteHtml =
|
||||
opts.siteSettings.enable_rich_text_paste &&
|
||||
types.includes("text/html") &&
|
||||
|
|
|
@ -426,11 +426,13 @@ export default Mixin.create({
|
|||
|
||||
@bind
|
||||
paste(e) {
|
||||
if (!this._$textarea.is(":focus") && !isTesting()) {
|
||||
const isComposer =
|
||||
document.querySelector(this.composerFocusSelector) === e.target;
|
||||
|
||||
if (!isComposer && !isTesting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isComposer = $(this.composerFocusSelector).is(":focus");
|
||||
let { clipboard, canPasteHtml, canUpload } = clipboardHelpers(e, {
|
||||
siteSettings: this.siteSettings,
|
||||
canUpload: isComposer,
|
||||
|
|
Loading…
Reference in New Issue