[gnome-software/91-clicking-screenshots-doesn-t-switch-between-them] gs-screenshot-image: Show spinner when load of image takes long time
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/91-clicking-screenshots-doesn-t-switch-between-them] gs-screenshot-image: Show spinner when load of image takes long time
- Date: Wed, 14 Oct 2020 15:20:46 +0000 (UTC)
commit e64e8581eede0be98cb222ed90deece79ebfdd26
Author: Milan Crha <mcrha redhat com>
Date: Wed Oct 14 17:18:30 2020 +0200
gs-screenshot-image: Show spinner when load of image takes long time
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/91
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/merge_requests/524
src/gs-screenshot-image.c | 43 ++++++++++++++++++++-
src/gs-screenshot-image.ui | 93 ++++++++++++++++++++++++++++------------------
2 files changed, 98 insertions(+), 38 deletions(-)
---
diff --git a/src/gs-screenshot-image.c b/src/gs-screenshot-image.c
index 0ecba076..86528782 100644
--- a/src/gs-screenshot-image.c
+++ b/src/gs-screenshot-image.c
@@ -15,11 +15,14 @@
#include "gs-screenshot-image.h"
#include "gs-common.h"
+#define SPINNER_TIMEOUT_SECS 2
+
struct _GsScreenshotImage
{
GtkBin parent_instance;
AsScreenshot *screenshot;
+ GtkWidget *spinner;
GtkWidget *stack;
GtkWidget *box_error;
GtkWidget *image1;
@@ -33,6 +36,7 @@ struct _GsScreenshotImage
guint width;
guint height;
guint scale;
+ guint load_timeout_id;
gboolean showing_image;
};
@@ -58,6 +62,7 @@ gs_screenshot_image_set_error (GsScreenshotImage *ssimg, const gchar *message)
else
gtk_widget_show (ssimg->label_error);
ssimg->showing_image = FALSE;
+ gtk_widget_hide (ssimg->spinner);
}
static void
@@ -95,6 +100,8 @@ as_screenshot_show_image (GsScreenshotImage *ssimg)
gtk_widget_show (GTK_WIDGET (ssimg));
ssimg->showing_image = TRUE;
+
+ gtk_widget_hide (ssimg->spinner);
}
static void
@@ -214,6 +221,11 @@ gs_screenshot_image_complete_cb (SoupSession *session,
g_autoptr(GdkPixbuf) pixbuf = NULL;
g_autoptr(GInputStream) stream = NULL;
+ if (ssimg->load_timeout_id) {
+ g_source_remove (ssimg->load_timeout_id);
+ ssimg->load_timeout_id = 0;
+ }
+
/* return immediately if the message was cancelled or if we're in destruction */
if (msg->status_code == SOUP_STATUS_CANCELLED || ssimg->session == NULL)
return;
@@ -221,12 +233,14 @@ gs_screenshot_image_complete_cb (SoupSession *session,
if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
g_debug ("screenshot has not been modified");
as_screenshot_show_image (ssimg);
+ gtk_widget_hide (ssimg->spinner);
return;
}
if (msg->status_code != SOUP_STATUS_OK) {
g_warning ("Result of screenshot downloading attempt with "
"status code '%u': %s", msg->status_code,
msg->reason_phrase);
+ gtk_widget_hide (ssimg->spinner);
/* if we're already showing an image, then don't set the error
* as having an image (even if outdated) is better */
if (ssimg->showing_image)
@@ -241,8 +255,10 @@ gs_screenshot_image_complete_cb (SoupSession *session,
stream = g_memory_input_stream_new_from_data (msg->response_body->data,
msg->response_body->length,
NULL);
- if (stream == NULL)
+ if (stream == NULL) {
+ gtk_widget_hide (ssimg->spinner);
return;
+ }
/* load the image */
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL);
@@ -345,6 +361,17 @@ gs_screenshot_soup_msg_set_modified_request (SoupMessage *msg, GFile *file)
mod_date);
}
+static gboolean
+gs_screenshot_show_spinner_cb (gpointer user_data)
+{
+ GsScreenshotImage *ssimg = user_data;
+
+ ssimg->load_timeout_id = 0;
+ gtk_widget_show (ssimg->spinner);
+
+ return FALSE;
+}
+
void
gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
GCancellable *cancellable)
@@ -473,6 +500,11 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
return;
}
+ if (ssimg->load_timeout_id) {
+ g_source_remove (ssimg->load_timeout_id);
+ ssimg->load_timeout_id = 0;
+ }
+
/* cancel any previous messages */
if (ssimg->message != NULL) {
soup_session_cancel_message (ssimg->session,
@@ -495,6 +527,9 @@ gs_screenshot_image_load_async (GsScreenshotImage *ssimg,
gs_screenshot_soup_msg_set_modified_request (ssimg->message, file);
}
+ ssimg->load_timeout_id = g_timeout_add_seconds (SPINNER_TIMEOUT_SECS,
+ gs_screenshot_show_spinner_cb, ssimg);
+
/* send async */
soup_session_queue_message (ssimg->session,
g_object_ref (ssimg->message) /* transfer full */,
@@ -513,6 +548,11 @@ gs_screenshot_image_destroy (GtkWidget *widget)
{
GsScreenshotImage *ssimg = GS_SCREENSHOT_IMAGE (widget);
+ if (ssimg->load_timeout_id) {
+ g_source_remove (ssimg->load_timeout_id);
+ ssimg->load_timeout_id = 0;
+ }
+
if (ssimg->message != NULL) {
soup_session_cancel_message (ssimg->session,
ssimg->message,
@@ -575,6 +615,7 @@ gs_screenshot_image_class_init (GsScreenshotImageClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/Software/gs-screenshot-image.ui");
+ gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, spinner);
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, stack);
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, image1);
gtk_widget_class_bind_template_child (widget_class, GsScreenshotImage, image2);
diff --git a/src/gs-screenshot-image.ui b/src/gs-screenshot-image.ui
index 0dae6e86..94704890 100644
--- a/src/gs-screenshot-image.ui
+++ b/src/gs-screenshot-image.ui
@@ -7,62 +7,81 @@
<class name="screenshot-image"/>
</style>
<child>
- <object class="GtkStack" id="stack">
+ <object class="GtkOverlay" id="overlay">
<property name="visible">True</property>
- <property name="transition-type">crossfade</property>
- <child>
- <object class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <style>
- <class name="image1"/>
- </style>
- </object>
- <packing>
- <property name="name">image1</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="image2">
+ <property name="halign">fill</property>
+ <property name="valign">fill</property>
+ <child type="overlay">
+ <object class="GtkSpinner" id="spinner">
+ <property name="active">True</property>
<property name="visible">True</property>
+ <property name="width_request">32</property>
+ <property name="height_request">32</property>
<property name="halign">center</property>
<property name="valign">center</property>
- <style>
- <class name="image2"/>
- </style>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
</object>
- <packing>
- <property name="name">image2</property>
- </packing>
</child>
<child>
- <object class="GtkBox" id="box_error">
+ <object class="GtkStack" id="stack">
<property name="visible">True</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="orientation">vertical</property>
- <property name="spacing">4</property>
+ <property name="transition-type">crossfade</property>
<child>
- <object class="GtkImage" id="image_error">
+ <object class="GtkImage" id="image1">
<property name="visible">True</property>
- <property name="icon-name">dialog-error-symbolic</property>
- <property name="icon-size">6</property>
- <property name="pixel-size">48</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="image1"/>
+ </style>
</object>
+ <packing>
+ <property name="name">image1</property>
+ </packing>
</child>
<child>
- <object class="GtkLabel" id="label_error">
+ <object class="GtkImage" id="image2">
<property name="visible">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
<style>
- <class name="error-label"/>
+ <class name="image2"/>
</style>
</object>
+ <packing>
+ <property name="name">image2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box_error">
+ <property name="visible">True</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">4</property>
+ <child>
+ <object class="GtkImage" id="image_error">
+ <property name="visible">True</property>
+ <property name="icon-name">dialog-error-symbolic</property>
+ <property name="icon-size">6</property>
+ <property name="pixel-size">48</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_error">
+ <property name="visible">True</property>
+ <style>
+ <class name="error-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="name">error</property>
+ </packing>
</child>
</object>
- <packing>
- <property name="name">error</property>
- </packing>
</child>
</object>
</child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]