From 43c847312af6185b41cda3162c7bf07f23008adf Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Mon, 22 Aug 2022 16:51:15 +0200 Subject: [PATCH 1/4] gs-category-page: Ignore content load when the page is not active No need to load content of the category page when the page is not active. --- src/gs-category-page.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gs-category-page.c b/src/gs-category-page.c index ba57ed2c8..a254452bc 100644 --- a/src/gs-category-page.c +++ b/src/gs-category-page.c @@ -376,6 +376,9 @@ gs_category_page_load_category (GsCategoryPage *self) g_assert (self->subcategory != NULL); + if (!gs_page_is_active (GS_PAGE (self))) + return; + featured_subcat = gs_category_find_child (self->category, "featured"); g_cancellable_cancel (self->cancellable); -- GitLab From 34df903c95781ec976deb03b7ac2ec38804c3cad Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Mon, 22 Aug 2022 16:53:36 +0200 Subject: [PATCH 2/4] gs-category-page: Check whether app list was returned, before using it When the load of the category apps had been cancelled or finished with an error, the data->app is NULL, which produces a runtime warning when passing it to gs_app_list_length(). --- src/gs-category-page.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gs-category-page.c b/src/gs-category-page.c index a254452bc..70364c763 100644 --- a/src/gs-category-page.c +++ b/src/gs-category-page.c @@ -221,7 +221,7 @@ choose_top_carousel_apps (LoadCategoryData *data, top_carousel_rand = g_rand_new_with_seed (top_carousel_seed); g_debug ("Top carousel seed: %u", top_carousel_seed); - for (guint i = 0; i < gs_app_list_length (data->apps); i++) { + for (guint i = 0; data->apps != NULL && i < gs_app_list_length (data->apps); i++) { GsApp *app = gs_app_list_index (data->apps, i); gboolean is_featured, is_recently_updated, is_hi_res; @@ -299,7 +299,7 @@ load_category_finish (LoadCategoryData *data) /* Apps to go in the top carousel */ top_carousel_apps = choose_top_carousel_apps (data, recently_updated_cutoff_secs); - for (guint i = 0; i < gs_app_list_length (data->apps); i++) { + for (guint i = 0; data->apps != NULL && i < gs_app_list_length (data->apps); i++) { GsApp *app = gs_app_list_index (data->apps, i); gboolean is_featured, is_recently_updated; guint64 release_date; -- GitLab From 0bf949bd600da068872c1527365a80a177f221f5 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Mon, 22 Aug 2022 16:57:31 +0200 Subject: [PATCH 3/4] gs-category-page: Ignore result of cancelled operation The result is not valid when the operation had been cancelled, thus do not modify the GUI in such case. --- src/gs-category-page.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/gs-category-page.c b/src/gs-category-page.c index 70364c763..0df2efcef 100644 --- a/src/gs-category-page.c +++ b/src/gs-category-page.c @@ -109,6 +109,7 @@ typedef struct { gboolean get_featured_apps_finished; GsAppList *apps; /* (owned) (nullable) */ gboolean get_main_apps_finished; + gboolean cancelled; } LoadCategoryData; static void @@ -140,6 +141,8 @@ gs_category_page_get_featured_apps_cb (GObject *source_object, if (!g_error_matches (local_error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED) && !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("failed to get featured apps for category apps: %s", local_error->message); + else + data->cancelled = TRUE; data->get_featured_apps_finished = TRUE; load_category_finish (data); return; @@ -175,6 +178,8 @@ gs_category_page_get_apps_cb (GObject *source_object, if (!g_error_matches (local_error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_CANCELLED) && !g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("failed to get apps for category apps: %s", local_error->message); + else + data->cancelled = TRUE; data->get_main_apps_finished = TRUE; load_category_finish (data); return; @@ -287,6 +292,11 @@ load_category_finish (LoadCategoryData *data) !data->get_main_apps_finished) return; + if (data->cancelled) { + load_category_data_free (data); + return; + } + /* Remove the loading tiles. */ gs_widget_remove_all (self->featured_flow_box, (GsRemoveFunc) gtk_flow_box_remove); gs_widget_remove_all (self->recently_updated_flow_box, (GsRemoveFunc) gtk_flow_box_remove); -- GitLab From 9dd99d089c59101e8a7684d5276bc86ee1419365 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Mon, 22 Aug 2022 16:59:18 +0200 Subject: [PATCH 4/4] gs-category-page: Refresh content from scratch only when the content is invalid Track when the content is valid and when not and refresh the content with complete removal of the previous data only if the content is invalid. It helps to not lost scroll position when any of the plugins request the page reload. Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1688 --- src/gs-category-page.c | 60 +++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/src/gs-category-page.c b/src/gs-category-page.c index 0df2efcef..a5377b631 100644 --- a/src/gs-category-page.c +++ b/src/gs-category-page.c @@ -28,6 +28,7 @@ struct _GsCategoryPage GCancellable *cancellable; GsCategory *category; GsCategory *subcategory; + gboolean content_valid; GtkWidget *top_carousel; GtkWidget *category_detail_box; @@ -371,6 +372,8 @@ load_category_finish (LoadCategoryData *data) gtk_widget_set_visible (self->web_apps_flow_box, gtk_flow_box_get_child_at_index (GTK_FLOW_BOX (self->web_apps_flow_box), 0) != NULL); gtk_widget_set_visible (self->category_detail_box, gtk_flow_box_get_child_at_index (GTK_FLOW_BOX (self->category_detail_box), 0) != NULL); + self->content_valid = data->apps != NULL; + load_category_data_free (data); } @@ -378,7 +381,6 @@ static void gs_category_page_load_category (GsCategoryPage *self) { GsCategory *featured_subcat = NULL; - GtkAdjustment *adj = NULL; g_autoptr(GsPluginJob) featured_plugin_job = NULL; g_autoptr(GsAppQuery) main_query = NULL; g_autoptr(GsPluginJob) main_plugin_job = NULL; @@ -399,24 +401,29 @@ gs_category_page_load_category (GsCategoryPage *self) gs_category_get_id (self->category), gs_category_get_id (self->subcategory)); - gs_featured_carousel_set_apps (GS_FEATURED_CAROUSEL (self->top_carousel), NULL); - gtk_widget_show (self->top_carousel); - gs_category_page_add_placeholders (self, GTK_FLOW_BOX (self->category_detail_box), - MIN (30, gs_category_get_size (self->subcategory))); - gs_category_page_add_placeholders (self, GTK_FLOW_BOX (self->recently_updated_flow_box), MAX_RECENTLY_UPDATED_APPS); - - if (gs_plugin_loader_get_enabled (self->plugin_loader, "epiphany")) - gs_category_page_add_placeholders (self, GTK_FLOW_BOX (self->web_apps_flow_box), 12); - - if (featured_subcat != NULL) { - /* set up the placeholders as having the featured category is a good - * indicator that there will be featured apps */ - gs_category_page_add_placeholders (self, GTK_FLOW_BOX (self->featured_flow_box), 6); + /* Add placeholders only when the content is not valid */ + if (!self->content_valid) { + gs_featured_carousel_set_apps (GS_FEATURED_CAROUSEL (self->top_carousel), NULL); + gs_category_page_add_placeholders (self, GTK_FLOW_BOX (self->category_detail_box), + MIN (30, gs_category_get_size (self->subcategory))); + gs_category_page_add_placeholders (self, GTK_FLOW_BOX (self->recently_updated_flow_box), MAX_RECENTLY_UPDATED_APPS); gtk_widget_show (self->top_carousel); - } else { - gs_widget_remove_all (self->featured_flow_box, (GsRemoveFunc) gtk_flow_box_remove); - gtk_widget_hide (self->featured_flow_box); - gtk_widget_hide (self->top_carousel); + gtk_widget_show (self->category_detail_box); + gtk_widget_show (self->recently_updated_flow_box); + + if (gs_plugin_loader_get_enabled (self->plugin_loader, "epiphany")) + gs_category_page_add_placeholders (self, GTK_FLOW_BOX (self->web_apps_flow_box), 12); + + if (featured_subcat != NULL) { + /* set up the placeholders as having the featured category is a good + * indicator that there will be featured apps */ + gs_category_page_add_placeholders (self, GTK_FLOW_BOX (self->featured_flow_box), 6); + gtk_widget_show (self->featured_flow_box); + } else { + gs_widget_remove_all (self->featured_flow_box, (GsRemoveFunc) gtk_flow_box_remove); + gtk_widget_hide (self->featured_flow_box); + gtk_widget_hide (self->top_carousel); + } } /* Load the list of apps in the category, and also the list of all @@ -475,11 +482,6 @@ gs_category_page_load_category (GsCategoryPage *self) self->cancellable, gs_category_page_get_apps_cb, load_data); - - /* scroll the list of apps to the beginning, otherwise it will show - * with the previous scroll value */ - adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->scrolledwindow_category)); - gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj)); } static void @@ -509,8 +511,18 @@ gs_category_page_set_category (GsCategoryPage *self, GsCategory *category) g_set_object (&self->subcategory, all_subcat); /* load the apps from it */ - if (all_subcat != NULL) + if (all_subcat != NULL) { + GtkAdjustment *adj = NULL; + + /* scroll the list of apps to the beginning, otherwise it will show + * with the previous scroll value, for the previous category */ + adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->scrolledwindow_category)); + gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj)); + + self->content_valid = FALSE; + gs_category_page_load_category (self); + } /* notify of the updates — the category’s title will have changed too */ g_object_notify (G_OBJECT (self), "category"); -- GitLab