mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
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;
|
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) {
|
export function clipboardHelpers(e, opts) {
|
||||||
const clipboard =
|
const clipboard =
|
||||||
e.clipboardData ||
|
e.clipboardData ||
|
||||||
@ -365,7 +374,9 @@ export function clipboardHelpers(e, opts) {
|
|||||||
|
|
||||||
let canUpload = files && opts.canUpload && types.includes("Files");
|
let canUpload = files && opts.canUpload && types.includes("Files");
|
||||||
const canUploadImage =
|
const canUploadImage =
|
||||||
canUpload && files.filter((f) => f.type.match("^image/"))[0];
|
canUpload &&
|
||||||
|
files.filter((f) => f.type.match("^image/"))[0] &&
|
||||||
|
!gifInDisguise(clipboard);
|
||||||
const canPasteHtml =
|
const canPasteHtml =
|
||||||
opts.siteSettings.enable_rich_text_paste &&
|
opts.siteSettings.enable_rich_text_paste &&
|
||||||
types.includes("text/html") &&
|
types.includes("text/html") &&
|
||||||
|
@ -426,11 +426,13 @@ export default Mixin.create({
|
|||||||
|
|
||||||
@bind
|
@bind
|
||||||
paste(e) {
|
paste(e) {
|
||||||
if (!this._$textarea.is(":focus") && !isTesting()) {
|
const isComposer =
|
||||||
|
document.querySelector(this.composerFocusSelector) === e.target;
|
||||||
|
|
||||||
|
if (!isComposer && !isTesting()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isComposer = $(this.composerFocusSelector).is(":focus");
|
|
||||||
let { clipboard, canPasteHtml, canUpload } = clipboardHelpers(e, {
|
let { clipboard, canPasteHtml, canUpload } = clipboardHelpers(e, {
|
||||||
siteSettings: this.siteSettings,
|
siteSettings: this.siteSettings,
|
||||||
canUpload: isComposer,
|
canUpload: isComposer,
|
||||||
|
Loading…
Reference in New Issue
Block a user