[polari] urlPreview: Promisify thumbnail lookup



commit b383bd1b79d4afa9b64a19be3c4873f5ff2903cb
Author: Florian Müllner <fmuellner gnome org>
Date:   Tue Jul 28 02:02:24 2020 +0200

    urlPreview: Promisify thumbnail lookup
    
    Switching the code from callbacks to promises not only gives us
    cleaner async code, but also gives us a standard way to propagate
    errors to the caller.
    
    https://gitlab.gnome.org/GNOME/polari/-/issues/149

 src/urlPreview.js | 68 ++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 40 insertions(+), 28 deletions(-)
---
diff --git a/src/urlPreview.js b/src/urlPreview.js
index b0bc1472..88cf9d2e 100644
--- a/src/urlPreview.js
+++ b/src/urlPreview.js
@@ -2,6 +2,7 @@
 const { Gio, GLib, GObject, Gtk, Pango } = imports.gi;
 
 Gio._promisify(Gio._LocalFilePrototype, 'query_info_async', 'query_info_finish');
+Gio._promisify(Gio.Subprocess.prototype, 'wait_async', 'wait_finish');
 
 class Thumbnailer {
     static getDefault() {
@@ -18,11 +19,13 @@ class Thumbnailer {
         GLib.mkdir_with_parents(this._thumbnailsDir, 0o755);
     }
 
-    getThumbnail(uri, callback) {
-        let filename = this._generateFilename(uri);
-        let data = { uri, filename, callback };
+    getThumbnail(uri) {
+        return new Promise((resolve, reject) => {
+            const filename = this._generateFilename(uri);
+            const data = { uri, filename, resolve, reject };
 
-        this._processData(data);
+            this._processData(data);
+        });
     }
 
     async _processData(data) {
@@ -34,28 +37,29 @@ class Thumbnailer {
             this._urlQueue.push(data);
     }
 
-    _generationDone(data) {
-        data.callback(data.filename);
+    _generationDone(data, error = null) {
+        if (error)
+            data.reject(error);
+        else
+            data.resolve(data.filename);
 
         let nextData = this._urlQueue.shift();
         if (nextData)
             this._processData(nextData);
     }
 
-    _generateThumbnail(data) {
+    async _generateThumbnail(data) {
         let { filename, uri } = data;
         this._subProc = Gio.Subprocess.new(
             ['gjs', `${pkg.pkgdatadir}/thumbnailer.js`, uri, filename],
             Gio.SubprocessFlags.NONE);
-        this._subProc.wait_async(null, (o, res) => {
-            try {
-                this._subProc.wait_finish(res);
-            } catch (e) {
-                log(`Thumbnail generation for ${uri} failed: ${e}`);
-            }
-            this._subProc = null;
+        try {
+            await this._subProc.wait_async(null);
             this._generationDone(data);
-        });
+        } catch (e) {
+            this._generationDone(data, e);
+        }
+        this._subProc = null;
     }
 
     async _thumbExists(data) {
@@ -113,24 +117,32 @@ var URLPreview = GObject.registerClass({
         this.add(this._label);
     }
 
-    vfunc_map() {
-        if (!this._imageLoaded) {
-            this._imageLoaded = true;
+    async _maybeLoadImage() {
+        if (this._imageLoaded)
+            return;
 
-            Thumbnailer.getDefault().getThumbnail(this.uri, filename => {
-                this._image.set_from_file(filename);
+        this._imageLoaded = true;
+        const thumbnailer = Thumbnailer.getDefault();
 
-                let title = null;
-                if (this._image.pixbuf)
-                    title = this._image.pixbuf.get_option('tEXt::Title');
+        try {
+            const filename = await thumbnailer.getThumbnail(this.uri);
+            this._image.set_from_file(filename);
+        } catch (e) {
+            log(`Thumbnail generation for ${this.uri} failed: ${e}`);
+        }
 
-                if (title) {
-                    this._label.set_label(title);
-                    this.tooltip_text = title;
-                }
-            });
+        let title = null;
+        if (this._image.pixbuf)
+            title = this._image.pixbuf.get_option('tEXt::Title');
+
+        if (title) {
+            this._label.set_label(title);
+            this.tooltip_text = title;
         }
+    }
 
+    vfunc_map() {
+        this._maybeLoadImage();
         super.vfunc_map();
     }
 });


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]