diff --git a/app/assets/javascripts/discourse.js.es6 b/app/assets/javascripts/discourse.js.es6 index f4bb1fdb02b..e8f252c5a95 100644 --- a/app/assets/javascripts/discourse.js.es6 +++ b/app/assets/javascripts/discourse.js.es6 @@ -9,6 +9,9 @@ const Discourse = Ember.Application.extend({ RAW_TEMPLATES: {}, __widget_helpers: {}, showingSignup: false, + customEvents: { + paste: 'paste' + }, getURL(url) { if (!url) return url; diff --git a/app/assets/javascripts/discourse/components/composer-editor.js.es6 b/app/assets/javascripts/discourse/components/composer-editor.js.es6 index 1d715a396de..39835269769 100644 --- a/app/assets/javascripts/discourse/components/composer-editor.js.es6 +++ b/app/assets/javascripts/discourse/components/composer-editor.js.es6 @@ -13,7 +13,8 @@ import { tinyAvatar, displayErrorForUpload, getUploadMarkdown, validateUploadedFiles, - formatUsername + formatUsername, + clipboardData } from 'discourse/lib/utilities'; import { cacheShortUploadUrl, resolveAllShortUrls } from 'pretty-text/image-short-url'; @@ -394,7 +395,14 @@ export default Ember.Component.extend({ pasteZone: $element, }); - $element.on('fileuploadpaste', () => this._pasted = true); + $element.on('fileuploadpaste', (e) => { + let {types} = clipboardData(e); + this._pasted = true; + + if (types.some(t => t === "text/plain")) { + e.preventDefault(); + } + }); $element.on('fileuploadsubmit', (e, data) => { const isPrivateMessage = this.get("composer.privateMessage"); diff --git a/app/assets/javascripts/discourse/components/d-editor.js.es6 b/app/assets/javascripts/discourse/components/d-editor.js.es6 index ee6725c9ccd..b46c934568d 100644 --- a/app/assets/javascripts/discourse/components/d-editor.js.es6 +++ b/app/assets/javascripts/discourse/components/d-editor.js.es6 @@ -8,7 +8,7 @@ import { emojiSearch, isSkinTonableEmoji } from 'pretty-text/emoji'; import { emojiUrlFor } from 'discourse/lib/text'; import { getRegister } from 'discourse-common/lib/get-owner'; import { findRawTemplate } from 'discourse/lib/raw-templates'; -import { determinePostReplaceSelection } from 'discourse/lib/utilities'; +import { determinePostReplaceSelection, clipboardData } from 'discourse/lib/utilities'; import deprecated from 'discourse-common/lib/deprecated'; // Our head can be a static string or a function that returns a string @@ -616,6 +616,14 @@ export default Ember.Component.extend({ Ember.run.scheduleOnce("afterRender", () => $textarea.focus()); }, + paste(e) { + let {types} = clipboardData(e); + + if (types.some(t => t === "Files") && !types.some(t => t === "text/plain")) { + e.preventDefault(); + } + }, + actions: { emojiSelected(code) { let selected = this._getSelected(); diff --git a/app/assets/javascripts/discourse/lib/utilities.js.es6 b/app/assets/javascripts/discourse/lib/utilities.js.es6 index 1b4cfda3492..625b68c68e7 100644 --- a/app/assets/javascripts/discourse/lib/utilities.js.es6 +++ b/app/assets/javascripts/discourse/lib/utilities.js.es6 @@ -421,5 +421,14 @@ export function isAppleDevice() { !navigator.userAgent.match(/Trident/g); } +export function clipboardData(e) { + let data = e.clipboardData || + e.originalEvent.clipboardData || + e.delegatedEvent.originalEvent.clipboardData || + event.clipboardData; + + return { items: data.items, types: data.types }; +} + // This prevents a mini racer crash export default {};