DEV: Refactor uppy plugin interfaces (#14275)

DEV: Refactor uppy plugin interfaces (#14275)

This abstracts interaction with uppy for uppy plugin classes into base classes for Preprocessor plugins, so anyone making these uppy plugins doesn’t have to think as much about uppy underneath the hood. This also makes the logging and validation nicer, and provides a more consistent way to emit progress and completion events.

In a future commit, we will introduce another base class for UploadUploaderPlugin which will be used to be able to hijack the upload process to go to a different provider (e.g. for discourse-video)

diff --git a/app/assets/javascripts/discourse/app/lib/uppy-checksum-plugin.js b/app/assets/javascripts/discourse/app/lib/uppy-checksum-plugin.js
index 3e74b36..ec73104 100644
--- a/app/assets/javascripts/discourse/app/lib/uppy-checksum-plugin.js
+++ b/app/assets/javascripts/discourse/app/lib/uppy-checksum-plugin.js
@@ -1,39 +1,31 @@
-import { BasePlugin } from "@uppy/core";
-import { warn } from "@ember/debug";
+import { UploadPreProcessorPlugin } from "discourse/lib/uppy-plugin-base";
 import { Promise } from "rsvp";
 
-export default class UppyChecksum extends BasePlugin {
+export default class UppyChecksum extends UploadPreProcessorPlugin {
+  static pluginId = "uppy-checksum";
+
   constructor(uppy, opts) {
     super(uppy, opts);
-    this.id = opts.id || "uppy-checksum";
-    this.pluginClass = this.constructor.name;
     this.capabilities = opts.capabilities;
-    this.type = "preprocessor";
   }
 
   _canUseSubtleCrypto() {
     if (!this._secureContext()) {
-      warn(
-        "Cannot generate cryptographic digests in an insecure context (not HTTPS).",
-        {
-          id: "discourse.uppy-media-optimization",
-        }
+      this._consoleWarn(
+        "Cannot generate cryptographic digests in an insecure context (not HTTPS)."
       );
       return false;
     }
     if (this.capabilities.isIE11) {
-      warn(
-        "The required cipher suite is unavailable in Internet Explorer 11.",
-        {
-          id: "discourse.uppy-media-optimization",
-        }
+      this._consoleWarn(
+        "The required cipher suite is unavailable in Internet Explorer 11."
       );
       return false;
     }
     if (!this._hasCryptoCipher()) {
-      warn("The required cipher suite is unavailable in this browser.", {
-        id: "discourse.uppy-media-optimization",
-      });
+      this._consoleWarn(
+        "The required cipher suite is unavailable in this browser."
+      );
       return false;
     }
 
@@ -46,9 +38,9 @@ export default class UppyChecksum extends BasePlugin {
     }
 
     let promises = fileIds.map((fileId) => {
-      let file = this.uppy.getFile(fileId);
+      let file = this._getFile(fileId);
 
-      this.uppy.emit("preprocess-progress", this.pluginClass, file);
+      this._emitProgress(file);
 
       return file.data.arrayBuffer().then((arrayBuffer) => {
         return window.crypto.subtle
@@ -58,22 +50,22 @@ export default class UppyChecksum extends BasePlugin {
             const hashHex = hashArray
               .map((b) => b.toString(16).padStart(2, "0"))
               .join("");
-            this.uppy.setFileMeta(fileId, { sha1_checksum: hashHex });
-            this.uppy.emit("preprocess-complete", this.pluginClass, file);
+            this._setFileMeta(fileId, { sha1_checksum: hashHex });
+            this._emitComplete(file);
           })
           .catch((err) => {
             if (
               err.message.toString().includes("Algorithm: Unrecognized name")
             ) {
-              warn("SHA-1 algorithm is unsupported in this browser.", {
-                id: "discourse.uppy-media-optimization",
-              });
+              this._consoleWarn(
+                "SHA-1 algorithm is unsupported in this browser."
+              );
             } else {
-              warn(`Error encountered when generating digest: ${err.message}`, {
-                id: "discourse.uppy-media-optimization",
-              });
+              this._consoleWarn(
+                `Error encountered when generating digest: ${err.message}`
+              );
             }
-            this.uppy.emit("preprocess-complete", this.pluginClass, file);
+            this._emitComplete(file);
           });
       });
     });
@@ -90,10 +82,10 @@ export default class UppyChecksum extends BasePlugin {
   }
 
   install() {
-    this.uppy.addPreProcessor(this._generateChecksum.bind(this));
+    this._install(this._generateChecksum.bind(this));
   }
 
   uninstall() {
-    this.uppy.removePreProcessor(this._generateChecksum.bind(this));
+    this._uninstall(this._generateChecksum.bind(this));
   }
 }
diff --git a/app/assets/javascripts/discourse/app/lib/uppy-media-optimization-plugin.js b/app/assets/javascripts/discourse/app/lib/uppy-media-optimization-plugin.js
index dcf3c31..4a00374 100644
--- a/app/assets/javascripts/discourse/app/lib/uppy-media-optimization-plugin.js
+++ b/app/assets/javascripts/discourse/app/lib/uppy-media-optimization-plugin.js
@@ -1,15 +1,12 @@
-import { BasePlugin } from "@uppy/core";
-import { warn } from "@ember/debug";
+import { UploadPreProcessorPlugin } from "discourse/lib/uppy-plugin-base";
 import { Promise } from "rsvp";
 
-export default class UppyMediaOptimization extends BasePlugin {
+export default class UppyMediaOptimization extends UploadPreProcessorPlugin {
+  static pluginId = "uppy-media-optimization";
+
   constructor(uppy, opts) {
     super(uppy, opts);
-    this.id = opts.id || "uppy-media-optimization";
-
-    this.type = "preprocessor";
     this.optimizeFn = opts.optimizeFn;
-    this.pluginClass = this.constructor.name;
 
     // mobile devices have limited processing power, so we only enable
     // running media optimization in parallel when we are sure the user
@@ -19,27 +16,27 @@ export default class UppyMediaOptimization extends BasePlugin {
   }
 
   _optimizeFile(fileId) {
-    let file = this.uppy.getFile(fileId);
+    let file = this._getFile(fileId);
 
-    this.uppy.emit("preprocess-progress", this.pluginClass, file);
+    this._emitProgress(file);
 
     return this.optimizeFn(file, { stopWorkerOnError: !this.runParallel })
       .then((optimizedFile) => {
         if (!optimizedFile) {
-          warn("Nothing happened, possible error or other restriction.", {
-            id: "discourse.uppy-media-optimization",
-          });
+          this._consoleWarn(
+            "Nothing happened, possible error or other restriction."
+          );
         } else {
-          this.uppy.setFileState(fileId, {
+          this._setFileState(fileId, {
             data: optimizedFile,
             size: optimizedFile.size,
           });
         }
-        this.uppy.emit("preprocess-complete", this.pluginClass, file);
+        this._emitComplete(file);
       })
       .catch((err) => {
-        warn(err, { id: "discourse.uppy-media-optimization" });
-        this.uppy.emit("preprocess-complete", this.pluginClass, file);
+        this._consoleWarn(err);
+        this._emitComplete(file);
       });
   }
 
@@ -59,17 +56,17 @@ export default class UppyMediaOptimization extends BasePlugin {
 
   install() {
     if (this.runParallel) {
-      this.uppy.addPreProcessor(this._optimizeParallel.bind(this));
+      this._install(this._optimizeParallel.bind(this));
     } else {
-      this.uppy.addPreProcessor(this._optimizeSerial.bind(this));
+      this._install(this._optimizeSerial.bind(this));
     }
   }
 
   uninstall() {
     if (this.runParallel) {
-      this.uppy.removePreProcessor(this._optimizeParallel.bind(this));
+      this._uninstall(this._optimizeParallel.bind(this));
     } else {
-      this.uppy.removePreProcessor(this._optimizeSerial.bind(this));
+      this._uninstall(this._optimizeSerial.bind(this));
     }
   }
 }
diff --git a/app/assets/javascripts/discourse/app/lib/uppy-plugin-base.js b/app/assets/javascripts/discourse/app/lib/uppy-plugin-base.js
new file mode 100644
index 0000000..34eddeb
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/lib/uppy-plugin-base.js
@@ -0,0 +1,50 @@
+import { BasePlugin } from "@uppy/core";
+import { warn } from "@ember/debug";
+
+export class UppyPluginBase extends BasePlugin {
+  constructor(uppy, opts) {
+    super(uppy, opts);
+    this.id = this.constructor.pluginId;
+  }
+
+  _consoleWarn(msg) {
+    warn(msg, { id: `discourse.${this.id}` });
+  }
+
+  _getFile(fileId) {
+    return this.uppy.getFile(fileId);
+  }
+
+  _setFileMeta(fileId, meta) {
+    this.uppy.setFileMeta(fileId, meta);
+  }
+

[... diff too long, it was truncated ...]

GitHub sha: 2215cc2547ae965f3039f0d5857766c2d0c8d9d0

This commit appears in #14275 which was approved by pmusaraj. It was merged by martin.