From 2f60309b13c5808ee5d8389eaf7e2d9aeb191dcf Mon Sep 17 00:00:00 2001
From: Rafael dos Santos Silva <xfalcox@gmail.com>
Date: Tue, 11 May 2021 12:20:28 -0300
Subject: [PATCH] FEATURE: New API hook to allow for client side upload
 transforms (#12990)

---
 .../app/components/composer-editor.js         | 29 +++++++++++++++++++
 .../discourse/app/lib/plugin-api.js           | 28 +++++++++++++++++-
 config/locales/client.en.yml                  |  1 +
 3 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/app/assets/javascripts/discourse/app/components/composer-editor.js b/app/assets/javascripts/discourse/app/components/composer-editor.js
index d110191c24c..84b6c137194 100644
--- a/app/assets/javascripts/discourse/app/components/composer-editor.js
+++ b/app/assets/javascripts/discourse/app/components/composer-editor.js
@@ -53,6 +53,13 @@ export function addComposerUploadHandler(extensions, method) {
   });
 }
 
+const uploadProcessorQueue = [];
+const uploadProcessorActions = {};
+export function addComposerUploadProcessor(queueItem, actionItem) {
+  uploadProcessorQueue.push(queueItem);
+  Object.assign(uploadProcessorActions, actionItem);
+}
+
 const uploadMarkdownResolvers = [];
 export function addComposerUploadMarkdownResolver(resolver) {
   uploadMarkdownResolvers.push(resolver);
@@ -634,12 +641,34 @@ export default Component.extend({
 
     const $element = $(this.element);
 
+    $.blueimp.fileupload.prototype.processActions = uploadProcessorActions;
+
     $element.fileupload({
       url: getURL(`/uploads.json?client_id=${this.messageBus.clientId}`),
       dataType: "json",
       pasteZone: $element,
+      processQueue: uploadProcessorQueue,
     });
 
+    $element
+      .on("fileuploadprocess", (e, data) => {
+        this.appEvents.trigger(
+          "composer:insert-text",
+          `[${I18n.t("processing_filename", {
+            filename: data.files[data.index].name,
+          })}]()\n`
+        );
+      })
+      .on("fileuploadprocessalways", (e, data) => {
+        this.appEvents.trigger(
+          "composer:replace-text",
+          `[${I18n.t("processing_filename", {
+            filename: data.files[data.index].name,
+          })}]()\n`,
+          ""
+        );
+      });
+
     $element.on("fileuploadpaste", (e) => {
       this._pasted = true;
 
diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.js b/app/assets/javascripts/discourse/app/lib/plugin-api.js
index 4d00f3a9e2f..21c71426379 100644
--- a/app/assets/javascripts/discourse/app/lib/plugin-api.js
+++ b/app/assets/javascripts/discourse/app/lib/plugin-api.js
@@ -1,6 +1,7 @@
 import ComposerEditor, {
   addComposerUploadHandler,
   addComposerUploadMarkdownResolver,
+  addComposerUploadProcessor,
 } from "discourse/components/composer-editor";
 import { addButton, removeButton } from "discourse/widgets/post-menu";
 import {
@@ -72,7 +73,7 @@ import { replaceTagRenderer } from "discourse/lib/render-tag";
 import { setNewCategoryDefaultColors } from "discourse/routes/new-category";
 
 // If you add any methods to the API ensure you bump up this number
-const PLUGIN_API_VERSION = "0.11.2";
+const PLUGIN_API_VERSION = "0.11.3";
 
 class PluginApi {
   constructor(version, container) {
@@ -933,6 +934,31 @@ class PluginApi {
     addComposerUploadHandler(extensions, method);
   }
 
+  /**
+   * Registers a pre-processor for file uploads
+   * See https://github.com/blueimp/jQuery-File-Upload/wiki/Options#file-processing-options
+   * Your theme/plugin will also need to load https://github.com/blueimp/jQuery-File-Upload/blob/v10.13.0/js/jquery.fileupload-process.js
+   * for this hook to work.
+   *
+   * Useful for transforming to-be uploaded files client-side
+   *
+   * Example:
+   *
+   * api.addComposerUploadProcessor({action: 'myFileTransformation'}, {
+   *    myFileTransformation: function (data, options) {
+   *      let p = new Promise((resolve, reject) => {
+   *        let file = data.files[data.index];
+   *        console.log(`Transforming ${file.name}`);
+   *        // do work...
+   *        resolve(data);
+   *      });
+   *      return p;
+   * });
+   */
+  addComposerUploadProcessor(queueItem, actionItem) {
+    addComposerUploadProcessor(queueItem, actionItem);
+  }
+
   /**
    * Registers a function to generate Markdown after a file has been uploaded.
    *
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 3ee96c7bfb7..5308b7038b4 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -368,6 +368,7 @@ en:
     upload: "Upload"
     uploading: "Uploading..."
     uploading_filename: "Uploading: %{filename}..."
+    processing_filename: "Processing: %{filename}..."
     clipboard: "clipboard"
     uploaded: "Uploaded!"