[gnome-software] Fix a race with displaying results from shell search provider



commit a69e779204348fc264185388d1a40f3bf602445e
Author: Kalev Lember <kalevlember gmail com>
Date:   Sun Oct 5 22:12:24 2014 +0200

    Fix a race with displaying results from shell search provider
    
    Clicking on an app in gnome-shell search results is supposed to bring up
    the details page for that app, with the back button leading to the
    search page, pre-populated with the same search that was done in
    gnome-shell.
    
    The code for this was all there, but it rarely worked properly because
    we'd spawn two parallel async processes, one to switch to the search
    page, and another one to switch to the details page. Whichever finished
    last was the one that the user actually saw.
    
    Fix this by properly chaining the async operations so that we'd always
    end up on the details page.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=735798

 src/gs-shell-search.c |   65 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/gs-shell-search.h |    2 +
 src/gs-shell.c        |   44 +--------------------------------
 3 files changed, 68 insertions(+), 43 deletions(-)
---
diff --git a/src/gs-shell-search.c b/src/gs-shell-search.c
index 2828e34..21d8cd2 100644
--- a/src/gs-shell-search.c
+++ b/src/gs-shell-search.c
@@ -41,6 +41,7 @@ struct GsShellSearchPrivate
        GtkSizeGroup            *sizegroup_image;
        GtkSizeGroup            *sizegroup_name;
        GsShell                 *shell;
+       gchar                   *appid_to_show;
        gchar                   *value;
 
        GtkWidget               *list_box_search;
@@ -234,6 +235,36 @@ gs_shell_search_app_row_clicked_cb (GsAppRow *app_row,
                gs_shell_search_show_missing_url (app);
 }
 
+typedef struct {
+       GsShellSearch *shell_search;
+       GsApp *app;
+} RefineData;
+
+static void
+refine_cb (GObject *source,
+           GAsyncResult *res,
+           gpointer data)
+{
+       RefineData *refine = data;
+       GsShellSearchPrivate *priv = refine->shell_search->priv;
+       GError *error = NULL;
+
+       if (!gs_plugin_loader_app_refine_finish (priv->plugin_loader,
+                                                res,
+                                                &error)) {
+               g_warning ("%s", error->message);
+               g_error_free (error);
+               goto out;
+       }
+
+       refine->app = gs_plugin_loader_dedupe (priv->plugin_loader, refine->app);
+       gs_shell_show_app (priv->shell, refine->app);
+
+out:
+       g_object_unref (refine->app);
+       g_free (refine);
+}
+
 /**
  * gs_shell_search_get_search_cb:
  **/
@@ -291,6 +322,24 @@ gs_shell_search_get_search_cb (GObject *source_object,
                gtk_widget_show (app_row);
        }
 
+       if (priv->appid_to_show != NULL) {
+               RefineData *refine;
+
+               refine = g_new0 (RefineData, 1);
+               refine->shell_search = shell_search;
+               refine->app = gs_app_new (priv->appid_to_show);
+               gs_plugin_loader_app_refine_async (priv->plugin_loader,
+                                                  refine->app,
+                                                  GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE |
+                                                  GS_PLUGIN_REFINE_FLAGS_REQUIRE_SIZE |
+                                                  GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL,
+                                                  priv->cancellable,
+                                                  refine_cb,
+                                                  refine);
+
+               g_clear_pointer (&priv->appid_to_show, g_free);
+       }
+
 out: ;
 }
 
@@ -340,6 +389,21 @@ gs_shell_search_reload (GsShellSearch *shell_search)
                gs_shell_search_load (shell_search);
 }
 
+
+/**
+ * gs_shell_search_set_appid_to_show:
+ *
+ * Switch to the specified app id after loading the search results.
+ **/
+void
+gs_shell_search_set_appid_to_show (GsShellSearch *shell_search, const gchar *appid)
+{
+       GsShellSearchPrivate *priv = shell_search->priv;
+
+       g_free (priv->appid_to_show);
+       priv->appid_to_show = g_strdup (appid);
+}
+
 /**
  * gs_shell_search_switch_to:
  **/
@@ -585,6 +649,7 @@ gs_shell_search_finalize (GObject *object)
        if (priv->search_cancellable != NULL)
                g_object_unref (priv->search_cancellable);
 
+       g_free (priv->appid_to_show);
        g_free (priv->value);
 
        G_OBJECT_CLASS (gs_shell_search_parent_class)->finalize (object);
diff --git a/src/gs-shell-search.h b/src/gs-shell-search.h
index 9538020..49678a3 100644
--- a/src/gs-shell-search.h
+++ b/src/gs-shell-search.h
@@ -53,6 +53,8 @@ typedef struct
 GType           gs_shell_search_get_type       (void);
 
 GsShellSearch  *gs_shell_search_new            (void);
+void            gs_shell_search_set_appid_to_show (GsShellSearch       *shell_search,
+                                                const gchar            *appid);
 void            gs_shell_search_switch_to      (GsShellSearch          *shell_search,
                                                 const gchar            *text,
                                                 gboolean                scroll_up);
diff --git a/src/gs-shell.c b/src/gs-shell.c
index 43f87e9..db953fc 100644
--- a/src/gs-shell.c
+++ b/src/gs-shell.c
@@ -747,62 +747,20 @@ gs_shell_show_filename (GsShell *shell, const gchar *filename)
        gs_shell_activate (shell);
 }
 
-typedef struct {
-       GsShell *shell;
-       GsApp *app;
-} RefineData;
-
-static void
-refine_cb (GObject *source,
-          GAsyncResult *res,
-          gpointer data)
-{
-       RefineData *refine = data;
-       GsShellPrivate *priv = refine->shell->priv;
-       GError *error = NULL;
-
-        if (!gs_plugin_loader_app_refine_finish (priv->plugin_loader,
-                                                 res,
-                                                 &error)) {
-                g_warning ("%s", error->message);
-                g_error_free (error);
-               goto out;
-        }
-
-        refine->app = gs_plugin_loader_dedupe (priv->plugin_loader, refine->app);
-        gs_shell_show_app (refine->shell, refine->app);
-
-out:
-        g_object_unref (refine->app);
-       g_free (refine);
-}
-
 void
 gs_shell_show_search_result (GsShell *shell, const gchar *id, const gchar *search)
 {
        GsShellPrivate *priv = shell->priv;
        GtkWidget *widget;
-       RefineData *refine;
 
        if (search != NULL && search[0] != '\0') {
                widget = GTK_WIDGET (gtk_builder_get_object (priv->builder, "entry_search"));
                gtk_entry_set_text (GTK_ENTRY (widget), search);
+               gs_shell_search_set_appid_to_show (priv->shell_search, id);
                gs_shell_search_switch_to (priv->shell_search, search, TRUE);
 
                gs_shell_change_mode (shell, GS_SHELL_MODE_SEARCH, NULL, NULL, TRUE);
        }
-
-       refine = g_new0 (RefineData, 1);
-       refine->shell = shell;
-       refine->app = gs_app_new (id);
-       gs_plugin_loader_app_refine_async (priv->plugin_loader,
-                                          refine->app,
-                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENCE |
-                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_SIZE |
-                                          GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL,
-                                          priv->cancellable,
-                                          refine_cb,
-                                          refine);
 }
 
 


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