[geary: 1/6] Add feedback via HUD progress pulse on slow inline image paste



commit 50a1691b2ff089ef894f8940fe88649ad93cc761
Author: Chris Heywood <15127-creywood users noreply gitlab gnome org>
Date:   Fri Dec 6 11:17:12 2019 +0100

    Add feedback via HUD progress pulse on slow inline image paste

 src/client/composer/composer-widget.vala | 78 +++++++++++++++++++++++++-------
 ui/composer-widget.ui                    | 10 ++++
 2 files changed, 71 insertions(+), 17 deletions(-)
---
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index ab6d779d..7141878f 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -28,6 +28,10 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
     private const string DEFAULT_TITLE = _("New Message");
 
 
+    /** For providing feedback on slow operation for large inline image paste. */
+    private const int SHOW_BACKGROUND_WORK_TIMEOUT_MSEC = 500;
+    private const int PULSE_TIMEOUT_MSEC = 250;
+
     public enum ComposeType {
         NEW_MESSAGE,
         REPLY,
@@ -386,6 +390,9 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
     [GtkChild]
     private Gtk.Label info_label;
 
+    [GtkChild]
+    private Gtk.ProgressBar background_progress;
+
     private GLib.SimpleActionGroup composer_actions = new GLib.SimpleActionGroup();
     private GLib.SimpleActionGroup editor_actions = new GLib.SimpleActionGroup();
 
@@ -468,6 +475,12 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
 
     private Application.Client application;
 
+    // Timeout for showing the slow image paste pulsing bar
+    private Geary.TimeoutManager show_background_work_timeout = null;
+
+    // Timer for pulsing progress bar
+    private Geary.TimeoutManager background_work_pulse;
+
 
     public Widget(Application.Client application,
                           Geary.Account initial_account,
@@ -593,6 +606,14 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
         this.editor.mouse_target_changed.connect(on_mouse_target_changed);
         this.editor.selection_changed.connect(on_selection_changed);
 
+        this.show_background_work_timeout = new Geary.TimeoutManager.milliseconds(
+            SHOW_BACKGROUND_WORK_TIMEOUT_MSEC, this.on_background_work_timeout
+        );
+        this.background_work_pulse = new Geary.TimeoutManager.milliseconds(
+            PULSE_TIMEOUT_MSEC, this.background_progress.pulse
+        );
+        this.background_work_pulse.repetition = FOREVER;
+
         load_entry_completions();
     }
 
@@ -885,6 +906,9 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
             on_account_unavailable
         );
 
+        this.show_background_work_timeout.reset();
+        this.background_work_pulse.reset();
+
         base.destroy();
     }
 
@@ -2036,30 +2060,36 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
     private void paste_image() {
         // The slow operations here are creating the PNG and, to a lesser extent,
         // requesting the image from the clipboard
-        this.container.top_window.application.mark_busy();
+        this.show_background_work_timeout.start();
 
         get_clipboard(Gdk.SELECTION_CLIPBOARD).request_image((clipboard, pixbuf) => {
             if (pixbuf != null) {
-                try {
-                    uint8[] buffer;
-                    pixbuf.save_to_buffer(out buffer, "png");
-                    Geary.Memory.ByteBuffer byte_buffer = new Geary.Memory.ByteBuffer(buffer, buffer.length);
-
-                    GLib.DateTime time_now = new GLib.DateTime.now();
-                    string filename = PASTED_IMAGE_FILENAME_TEMPLATE.printf(time_now.hash());
+                MemoryOutputStream os = new MemoryOutputStream(null);
+                pixbuf.save_to_stream_async.begin(os, "png", null, (obj, res) => {
+                    try {
+                        pixbuf.save_to_stream_async.end(res);
+                        os.close();
+
+                        Geary.Memory.ByteBuffer byte_buffer = new 
Geary.Memory.ByteBuffer.from_memory_output_stream(os);
+
+                        GLib.DateTime time_now = new GLib.DateTime.now();
+                        string filename = PASTED_IMAGE_FILENAME_TEMPLATE.printf(time_now.hash());
+
+                        string unique_filename;
+                        add_inline_part(byte_buffer, filename, out unique_filename);
+                        this.editor.insert_image(
+                            Components.WebView.INTERNAL_URL_PREFIX + unique_filename
+                        );
+                    } catch (Error err) {
+                        warning("Failed to convert pasted clipboard image to PNG");
+                    }
 
-                    string unique_filename;
-                    add_inline_part(byte_buffer, filename, out unique_filename);
-                    this.editor.insert_image(
-                        Components.WebView.INTERNAL_URL_PREFIX + unique_filename
-                    );
-                } catch (Error error) {
-                    warning("Failed to paste image %s", error.message);
-                }
+                    stop_background_work_pulse();
+                });
             } else {
                 warning("Failed to get image from clipboard");
+                stop_background_work_pulse();
             }
-            this.container.top_window.application.unmark_busy();
         });
     }
 
@@ -2807,4 +2837,18 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
             Components.WebView.INTERNAL_URL_PREFIX + unique_filename
         );
     }
+
+    /** Shows and starts pulsing the progress meter. */
+    private void on_background_work_timeout() {
+        this.background_progress.fraction = 0.0;
+        this.background_work_pulse.start();
+        this.background_progress.show();
+    }
+
+    /** Hides and stops pulsing the progress meter. */
+    private void stop_background_work_pulse() {
+        this.background_progress.hide();
+        this.background_work_pulse.reset();
+        this.show_background_work_timeout.reset();
+    }
 }
diff --git a/ui/composer-widget.ui b/ui/composer-widget.ui
index b568c422..b4821843 100644
--- a/ui/composer-widget.ui
+++ b/ui/composer-widget.ui
@@ -850,6 +850,16 @@
                             </style>
                           </object>
                         </child>
+                        <child type="overlay">
+                          <object class="GtkProgressBar" id="background_progress">
+                            <property name="can_focus">False</property>
+                            <property name="valign">start</property>
+                            <style>
+                              <class name="osd"/>
+                              <class name="top"/>
+                            </style>
+                          </object>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">True</property>


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