[gnome-software/154-gs-details-page-lack-of-information-when-flatpak-app-data-is-being-loaded: 5/5] gs-details-page: Lack of information when flatpak app data is being loaded




commit 69f74a81a19e81b1fbbf7ee489de8b54e4d9d1ce
Author: Milan Crha <mcrha redhat com>
Date:   Thu Oct 22 18:25:03 2020 +0200

    gs-details-page: Lack of information when flatpak app data is being loaded
    
    Show information from the plugin loader when populating the details page,
    thus there's a feedback about what the plugin does when it takes long time.
    
    Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/154
    Closes https://gitlab.gnome.org/GNOME/gnome-software/-/merge_requests/529

 src/gs-details-page.c  | 114 ++++++++++++++++++++++++++++++++++++++++++-------
 src/gs-details-page.ui |  22 +++++++---
 2 files changed, 115 insertions(+), 21 deletions(-)
---
diff --git a/src/gs-details-page.c b/src/gs-details-page.c
index 210724ce..aaa0ccae 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -124,8 +124,11 @@ struct _GsDetailsPage
        GtkWidget               *button_review;
        GtkWidget               *list_box_reviews;
        GtkWidget               *scrolledwindow_details;
-       GtkWidget               *spinner_details;
        GtkWidget               *spinner_remove;
+       GtkWidget               *loading_progressbar;
+       guint                    loading_progress_pulse_id;
+       gulong                   loading_status_handler_id;
+       GtkWidget               *loading_label;
        GtkWidget               *stack_details;
        GtkWidget               *grid_details_kudo;
        GtkWidget               *image_details_kudo_docs;
@@ -157,6 +160,43 @@ struct _GsDetailsPage
 
 G_DEFINE_TYPE (GsDetailsPage, gs_details_page, GS_TYPE_PAGE)
 
+static gboolean
+gs_details_page_loading_pulse_cb (gpointer user_data)
+{
+       GsDetailsPage *self = GS_DETAILS_PAGE (user_data);
+       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (self->loading_progressbar));
+       return G_SOURCE_CONTINUE;
+}
+
+static void
+gs_details_page_status_changed_cb (GsPluginLoader *plugin_loader,
+                                   GsApp *app,
+                                   GsPluginStatus status,
+                                   GsDetailsPage *self)
+{
+       const gchar *str = NULL;
+
+       if (status == GS_PLUGIN_STATUS_DOWNLOADING && app)
+               str = gs_app_get_summary_missing (app);
+
+       if (str)
+               gtk_label_set_label (GTK_LABEL (self->loading_label), str);
+
+       if (app) {
+               if (self->loading_progress_pulse_id != 0) {
+                       g_source_remove (self->loading_progress_pulse_id);
+                       self->loading_progress_pulse_id = 0;
+               }
+
+               if (gs_app_get_progress (app) == GS_APP_PROGRESS_UNKNOWN) {
+                       self->loading_progress_pulse_id = g_timeout_add (50, 
gs_details_page_loading_pulse_cb, self);
+               } else {
+                       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->loading_progressbar),
+                                                      (gdouble) gs_app_get_progress (app) / 100.0f);
+               }
+       }
+}
+
 static void
 gs_details_page_set_state (GsDetailsPage *self,
                            GsDetailsPageState state)
@@ -164,13 +204,26 @@ gs_details_page_set_state (GsDetailsPage *self,
        /* spinner */
        switch (state) {
        case GS_DETAILS_PAGE_STATE_LOADING:
-               gs_start_spinner (GTK_SPINNER (self->spinner_details));
-               gtk_widget_show (self->spinner_details);
+               gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->loading_progressbar), 0.0);
+               if (!self->loading_progress_pulse_id)
+                       self->loading_progress_pulse_id = g_timeout_add (50, 
gs_details_page_loading_pulse_cb, self);
+               gtk_label_set_label (GTK_LABEL (self->loading_label), _("Loading Application Details…"));
+               if (!self->loading_status_handler_id) {
+                       self->loading_status_handler_id =
+                               g_signal_connect (self->plugin_loader, "status-changed",
+                                                 G_CALLBACK (gs_details_page_status_changed_cb), self);
+               }
                break;
        case GS_DETAILS_PAGE_STATE_READY:
        case GS_DETAILS_PAGE_STATE_FAILED:
-               gs_stop_spinner (GTK_SPINNER (self->spinner_details));
-               gtk_widget_hide (self->spinner_details);
+               if (self->loading_status_handler_id) {
+                       g_signal_handler_disconnect (self->plugin_loader, self->loading_status_handler_id);
+                       self->loading_status_handler_id = 0;
+               }
+               if (self->loading_progress_pulse_id) {
+                       g_source_remove (self->loading_progress_pulse_id);
+                       self->loading_progress_pulse_id = 0;
+               }
                break;
        default:
                g_assert_not_reached ();
@@ -261,11 +314,21 @@ app_has_pending_action (GsApp *app)
               (gs_app_get_state (app) == AS_APP_STATE_QUEUED_FOR_INSTALL);
 }
 
+static void
+gs_details_page_set_header_label (GsDetailsPage *self,
+                                 const gchar *text)
+{
+       GtkWidget *widget;
+
+       widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "application_details_header"));
+       gtk_label_set_label (GTK_LABEL (widget), text ? text : "");
+       gtk_widget_set_visible (widget, text != NULL);
+}
+
 static void
 gs_details_page_switch_to (GsPage *page, gboolean scroll_up)
 {
        GsDetailsPage *self = GS_DETAILS_PAGE (page);
-       GtkWidget *widget;
        GtkAdjustment *adj;
 
        if (gs_shell_get_mode (self->shell) != GS_SHELL_MODE_DETAILS) {
@@ -274,14 +337,12 @@ gs_details_page_switch_to (GsPage *page, gboolean scroll_up)
                return;
        }
 
-       widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "application_details_header"));
-       gtk_label_set_label (GTK_LABEL (widget), "");
-       gtk_widget_show (widget);
-
        /* not set, perhaps file-to-app */
        if (self->app == NULL)
                return;
 
+       gs_details_page_set_header_label (self, gs_app_get_name (self->app));
+
        adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->scrolledwindow_details));
        gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj));
 
@@ -1127,7 +1188,6 @@ gs_details_page_refresh_all (GsDetailsPage *self)
        GsAppList *history;
        GdkPixbuf *pixbuf = NULL;
        GList *addons;
-       GtkWidget *widget;
        const gchar *tmp;
        gboolean ret;
        gchar **menu_path;
@@ -1139,14 +1199,12 @@ gs_details_page_refresh_all (GsDetailsPage *self)
 
        /* change widgets */
        tmp = gs_app_get_name (self->app);
-       widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "application_details_header"));
+       gs_details_page_set_header_label (self, tmp);
        if (tmp != NULL && tmp[0] != '\0') {
                gtk_label_set_label (GTK_LABEL (self->application_details_title), tmp);
-               gtk_label_set_label (GTK_LABEL (widget), tmp);
                gtk_widget_set_visible (self->application_details_title, TRUE);
        } else {
                gtk_widget_set_visible (self->application_details_title, FALSE);
-               gtk_label_set_label (GTK_LABEL (widget), "");
        }
        tmp = gs_app_get_summary (self->app);
        if (tmp != NULL && tmp[0] != '\0') {
@@ -1966,8 +2024,17 @@ void
 gs_details_page_set_local_file (GsDetailsPage *self, GFile *file)
 {
        g_autoptr(GsPluginJob) plugin_job = NULL;
+       g_autoptr(GFileInfo) file_info = NULL;
+       const gchar *display_name = NULL;
        gs_details_page_set_state (self, GS_DETAILS_PAGE_STATE_LOADING);
        g_clear_object (&self->app_local_file);
+       g_clear_object (&self->app);
+
+       file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, 
NULL, NULL);
+       if (file_info)
+               display_name = g_file_info_get_attribute_string (file_info, 
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
+       gs_details_page_set_header_label (self, display_name);
+
        plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_FILE_TO_APP,
                                         "file", file,
                                         "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON |
@@ -1999,8 +2066,16 @@ void
 gs_details_page_set_url (GsDetailsPage *self, const gchar *url)
 {
        g_autoptr(GsPluginJob) plugin_job = NULL;
+       const gchar *dash;
        gs_details_page_set_state (self, GS_DETAILS_PAGE_STATE_LOADING);
        g_clear_object (&self->app_local_file);
+       g_clear_object (&self->app);
+
+       dash = strrchr (url, '/');
+       if (dash)
+               dash++;
+       gs_details_page_set_header_label (self, dash);
+
        plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_URL_TO_APP,
                                         "search", url,
                                         "refine-flags", GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON |
@@ -2726,6 +2801,14 @@ gs_details_page_dispose (GObject *object)
                g_signal_handlers_disconnect_by_func (self->app, gs_details_page_progress_changed_cb, self);
                g_clear_object (&self->app);
        }
+       if (self->plugin_loader && self->loading_status_handler_id) {
+               g_signal_handler_disconnect (self->plugin_loader, self->loading_status_handler_id);
+               self->loading_status_handler_id = 0;
+       }
+       if (self->loading_progress_pulse_id != 0) {
+               g_source_remove (self->loading_progress_pulse_id);
+               self->loading_progress_pulse_id = 0;
+       }
        g_clear_object (&self->app_local_file);
        g_clear_object (&self->builder);
        g_clear_object (&self->plugin_loader);
@@ -2820,8 +2903,9 @@ gs_details_page_class_init (GsDetailsPageClass *klass)
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, button_review);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, list_box_reviews);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, scrolledwindow_details);
-       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, spinner_details);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, spinner_remove);
+       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, loading_progressbar);
+       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, loading_label);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, stack_details);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, grid_details_kudo);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, image_details_kudo_docs);
diff --git a/src/gs-details-page.ui b/src/gs-details-page.ui
index f86674fe..b006fb31 100644
--- a/src/gs-details-page.ui
+++ b/src/gs-details-page.ui
@@ -23,14 +23,24 @@
               <class name="dim-label"/>
             </style>
             <child>
-              <object class="GtkSpinner" id="spinner_details">
+              <object class="GtkProgressBar" id="loading_progressbar">
                 <property name="visible">True</property>
-                <property name="width_request">32</property>
-                <property name="height_request">32</property>
+                <property name="width_request">480</property>
                 <property name="halign">center</property>
-                <property name="valign">center</property>
-                <property name="hexpand">True</property>
-                <property name="vexpand">True</property>
+                <property name="fraction">0.0</property>
+                <property name="margin_top">8</property>
+                <style>
+                  <class name="upgrade-progressbar"/>
+                </style>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="loading_label">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Loading Application Details…</property>
+                <attributes>
+                  <attribute name="scale" value="1.4"/>
+                </attributes>
               </object>
             </child>
           </object>


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