[polari] urlPreview: Load actual thumbnails



commit 711ffd3bdc9f115ec6797ae0928488cbe2b70743
Author: daronion <stefanosdimos 98 gmail com>
Date:   Mon Aug 26 17:58:17 2019 +0300

    urlPreview: Load actual thumbnails
    
    We potentially want to load a lot of previews at a time. Depending on
    the web page this can be a quite expensive operation, so we only want
    to create one thumbnail at a time.
    
    To ensure that, delegate the loading and creation to a singleton that
    runs the previously added helper script on each URL one by one and cache
    the result.
    
    https://gitlab.gnome.org/GNOME/polari/issues/58

 src/urlPreview.js | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)
---
diff --git a/src/urlPreview.js b/src/urlPreview.js
index cc32e08..cf7e814 100644
--- a/src/urlPreview.js
+++ b/src/urlPreview.js
@@ -1,5 +1,69 @@
 /* exported URLPreview */
-const { GObject, Gtk } = imports.gi;
+const { Gio, GLib, GObject, Gtk } = imports.gi;
+
+class Thumbnailer {
+    static getDefault() {
+        if (!this._singleton)
+            this._singleton = new Thumbnailer();
+        return this._singleton;
+    }
+
+    constructor() {
+        this._urlQueue = [];
+        this._subProc = null;
+        this._thumbnailsDir = `${GLib.get_user_cache_dir()}/polari/thumbnails/`;
+
+        GLib.mkdir_with_parents(this._thumbnailsDir, 0o755);
+    }
+
+    getThumbnail(uri, callback) {
+        let filename = this._generateFilename(uri);
+        let data = { uri, filename, callback };
+
+        this._processData(data);
+    }
+
+    _processData(data) {
+        let check = GLib.file_test(`${data.filename}`, GLib.FileTest.EXISTS);
+        if (check)
+            this._generationDone(data);
+        else if (!this._subProc)
+            this._generateThumbnail(data);
+        else
+            this._urlQueue.push(data);
+    }
+
+    _generationDone(data) {
+        data.callback(data.filename);
+
+        let nextData = this._urlQueue.shift();
+        if (nextData)
+            this._processData(nextData);
+    }
+
+    _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;
+            this._generationDone(data);
+        });
+    }
+
+    _generateFilename(url) {
+        let checksum = GLib.Checksum.new(GLib.ChecksumType.MD5);
+        checksum.update(url);
+
+        return `${this._thumbnailsDir}${checksum.get_string()}.png`;
+    }
+}
 
 let URLPreview = GObject.registerClass({
     Properties: {
@@ -26,5 +90,9 @@ let URLPreview = GObject.registerClass({
             visible: true,
         });
         this.add(this._image);
+
+        Thumbnailer.getDefault().getThumbnail(this.uri, filename => {
+            this._image.set_from_file(filename);
+        });
     }
 });


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