FIX: always try to convert PNG to JPG when pasting an image

FIX: always try to convert PNG to JPG when pasting an image

diff --git a/app/assets/javascripts/discourse/components/composer-editor.js.es6 b/app/assets/javascripts/discourse/components/composer-editor.js.es6
index 9a92e7e..e32c2f5 100644
--- a/app/assets/javascripts/discourse/components/composer-editor.js.es6
+++ b/app/assets/javascripts/discourse/components/composer-editor.js.es6
@@ -228,6 +228,8 @@ export default Ember.Component.extend({
   _bindUploadTarget() {
     this._unbindUploadTarget(); // in case it's still bound, let's clean it up first
 
+    let pasted = false;
+
     const $element = this.$();
     const csrf = this.session.get('csrfToken');
     const uploadPlaceholder = this.get('uploadPlaceholder');
@@ -238,15 +240,24 @@ export default Ember.Component.extend({
       pasteZone: $element,
     });
 
+    $element.on('fileuploadpaste', () => this.pasted = true);
+
     $element.on('fileuploadsubmit', (e, data) => {
       const isPrivateMessage = this.get("composer.privateMessage");
+
+      data.formData = { type: "composer" }
+      if (isPrivateMessage) data.formData.for_private_message = true;
+      if (this.pasted) data.formData.pasted = true;
+
       const opts = {
         isPrivateMessage,
         allowStaffToUploadAnyFileInPm: this.siteSettings.allow_staff_to_upload_any_file_in_pm,
       };
+
       const isUploading = validateUploadedFiles(data.files, opts);
-      data.formData = { type: "composer", for_private_message: isPrivateMessage };
+
       this.setProperties({ uploadProgress: 0, isUploading });
+
       return isUploading;
     });
 
@@ -255,6 +266,7 @@ export default Ember.Component.extend({
     });
 
     $element.on("fileuploadsend", (e, data) => {
+      this.pasted = false;
       this._validUploads++;
       this.appEvents.trigger('composer:insert-text', uploadPlaceholder);
 
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
index 295671c..c19fa69 100644
--- a/app/controllers/uploads_controller.rb
+++ b/app/controllers/uploads_controller.rb
@@ -13,17 +13,18 @@ class UploadsController < ApplicationController
       return render json: failed_json, status: 422
     end
 
-    url  = params[:url]
-    file = params[:file] || params[:files]&.first
-    for_private_message = params[:for_private_message]
+    url    = params[:url]
+    file   = params[:file] || params[:files]&.first
+    pasted = params[:pasted] == "true"
+    for_private_message = params[:for_private_message] == "true"
 
     if params[:synchronous] && (current_user.staff? || is_api?)
-      data = create_upload(file, url, type, for_private_message)
+      data = create_upload(file, url, type, for_private_message, pasted)
       render json: data.as_json
     else
       Scheduler::Defer.later("Create Upload") do
         begin
-          data = create_upload(file, url, type, for_private_message)
+          data = create_upload(file, url, type, for_private_message, pasted)
         ensure
           MessageBus.publish("/uploads/#{type}", (data || {}).as_json, client_ids: [params[:client_id]])
         end
@@ -60,7 +61,7 @@ class UploadsController < ApplicationController
     raise Discourse::NotFound
   end
 
-  def create_upload(file, url, type, for_private_message = false)
+  def create_upload(file, url, type, for_private_message, pasted)
     if file.nil?
       if url.present? && is_api?
         maximum_upload_size = [SiteSetting.max_image_size_kb, SiteSetting.max_attachment_size_kb].max.kilobytes
@@ -79,8 +80,12 @@ class UploadsController < ApplicationController
 
     return { errors: [I18n.t("upload.file_missing")] } if tempfile.nil?
 
-    opts = { type: type, content_type: content_type }
-    opts[:for_private_message] = true if for_private_message
+    opts = {
+      type: type,
+      content_type: content_type,
+      for_private_message: for_private_message,
+      pasted: pasted,
+    }
 
     upload = UploadCreator.new(tempfile, filename, opts).create_for(current_user.id)
 
diff --git a/lib/upload_creator.rb b/lib/upload_creator.rb
index 2e33e05..ddf703f 100644
--- a/lib/upload_creator.rb
+++ b/lib/upload_creator.rb
@@ -19,6 +19,7 @@ class UploadCreator
   #  - for_group_message (boolean)
   #  - for_theme (boolean)
   #  - for_private_message (boolean)
+  #  - pasted (boolean)
   def initialize(file, filename, opts = {})
     @upload = Upload.new
     @file = file
@@ -121,9 +122,10 @@ class UploadCreator
   MIN_PIXELS_TO_CONVERT_TO_JPEG ||= 1280 * 720
 
   def should_convert_to_jpeg?
-    TYPES_CONVERTED_TO_JPEG.include?(@image_info.type) &&
-    pixels > MIN_PIXELS_TO_CONVERT_TO_JPEG &&
-    SiteSetting.png_to_jpg_quality < 100
+    return false if !TYPES_CONVERTED_TO_JPEG.include?(@image_info.type)
+    return true  if @opts[:pasted]
+    return false if SiteSetting.png_to_jpg_quality < 100
+    pixels > MIN_PIXELS_TO_CONVERT_TO_JPEG
   end
 
   def convert_to_jpeg!
diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb
index b44436d..63255e4 100644
--- a/spec/controllers/uploads_controller_spec.rb
+++ b/spec/controllers/uploads_controller_spec.rb
@@ -38,7 +38,7 @@ describe UploadsController do
       end
 
       it 'parameterize the type' do
-        subject.expects(:create_upload).with(logo, nil, "super_long_type_with_charssuper_long_type_with_char", nil)
+        subject.expects(:create_upload).with(logo, nil, "super_long_type_with_charssuper_long_type_with_char", false, false)
         xhr :post, :create, file: logo, type: "super \# long \//\\ type with \\. $%^&*( chars" * 5
       end
 
@@ -140,7 +140,7 @@ describe UploadsController do
         @user.update_columns(moderator: true)
 
         message = MessageBus.track_publish do
-          xhr :post, :create, file: text_file, type: "composer", for_private_message: true
+          xhr :post, :create, file: text_file, type: "composer", for_private_message: "true"
         end.first
 
         expect(response).to be_success

GitHub sha: a9c0df0b

@ZogStriP what if the pasted image has an alpha layer? Wouldn’t that lose transparency when there is some?

This commit has been mentioned on Discourse Meta. There might be relevant details there:

https://meta.discourse.org/t/why-do-pasted-png-get-converted-to-jpg/152403/1

Did you mean this.pasted here?

1 Like

Good point :+1: I guess I did…

Wow, that flashback… That’s from 2017 :open_mouth:

And is already fixed :wink:

1 Like

Haha I did not notice! It was pending in review.

2 Likes