From 1849f6660c09b5e4e7b1b22ee22bb327e58a8ba4 Mon Sep 17 00:00:00 2001 From: Alexander Vanhee <160625516+AlexanderVanhee@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:07:48 +0200 Subject: [PATCH 1/2] Make other apps by developer not use Flathub API This makes the time until result shown way shorter, saves an API call and makes it work for apps across all remotes. --- src/bz-entry.c | 50 +--------------------- src/bz-full-view.blp | 7 ++- src/bz-full-view.c | 100 ++++++++++++++++++++++++++++++++----------- 3 files changed, 82 insertions(+), 75 deletions(-) diff --git a/src/bz-entry.c b/src/bz-entry.c index 809d851f..5dd63836 100644 --- a/src/bz-entry.c +++ b/src/bz-entry.c @@ -99,7 +99,6 @@ typedef struct char *project_group; char *developer; char *developer_id; - GListModel *developer_apps; GListModel *screenshot_paintables; GListModel *screenshot_captions; GdkPaintable *thumbnail_paintable; @@ -167,7 +166,6 @@ enum PROP_PROJECT_GROUP, PROP_DEVELOPER, PROP_DEVELOPER_ID, - PROP_DEVELOPER_APPS, PROP_SCREENSHOT_PAINTABLES, PROP_SCREENSHOT_CAPTIONS, PROP_THUMBNAIL_PAINTABLE, @@ -206,11 +204,9 @@ BZ_DEFINE_DATA ( GWeakRef self; int prop; char *id; - char *developer; }, g_weak_ref_clear (&self->self); - BZ_RELEASE_DATA (id, g_free); - BZ_RELEASE_DATA (developer, g_free)); + BZ_RELEASE_DATA (id, g_free);); static DexFuture * query_flathub_fiber (QueryFlathubData *data); static DexFuture * @@ -350,10 +346,6 @@ bz_entry_get_property (GObject *object, case PROP_DEVELOPER_ID: g_value_set_string (value, priv->developer_id); break; - case PROP_DEVELOPER_APPS: - query_flathub (self, PROP_DEVELOPER_APPS); - g_value_set_object (value, priv->developer_apps); - break; case PROP_SCREENSHOT_PAINTABLES: g_value_set_object (value, priv->screenshot_paintables); break; @@ -557,10 +549,6 @@ bz_entry_set_property (GObject *object, g_clear_pointer (&priv->developer_id, g_free); priv->developer_id = g_value_dup_string (value); break; - case PROP_DEVELOPER_APPS: - g_clear_object (&priv->developer_apps); - priv->developer_apps = g_value_dup_object (value); - break; case PROP_SCREENSHOT_PAINTABLES: g_clear_object (&priv->screenshot_paintables); priv->screenshot_paintables = g_value_dup_object (value); @@ -850,13 +838,6 @@ bz_entry_class_init (BzEntryClass *klass) NULL, NULL, NULL, G_PARAM_READWRITE); - props[PROP_DEVELOPER_APPS] = - g_param_spec_object ( - "developer-apps", - NULL, NULL, - G_TYPE_LIST_MODEL, - G_PARAM_READWRITE); - props[PROP_SCREENSHOT_PAINTABLES] = g_param_spec_object ( "screenshot-paintables", @@ -2381,7 +2362,6 @@ query_flathub (BzEntry *self, g_weak_ref_init (&data->self, self); data->prop = prop; data->id = g_strdup (priv->id); - data->developer = g_strdup (priv->developer); future = dex_scheduler_spawn ( bz_get_io_scheduler (), @@ -2412,7 +2392,6 @@ query_flathub_fiber (QueryFlathubData *data) { int prop = data->prop; char *id = data->id; - char *developer = data->developer; g_autoptr (GError) local_error = NULL; g_autofree char *request = NULL; g_autoptr (JsonNode) node = NULL; @@ -2425,9 +2404,6 @@ query_flathub_fiber (QueryFlathubData *data) case PROP_TOTAL_DOWNLOADS: request = g_strdup_printf ("/stats/%s?all=false&days=175", id); break; - case PROP_DEVELOPER_APPS: - request = g_strdup_printf ("/collection/developer/%s", developer); - break; case PROP_FAVORITES_COUNT: request = g_strdup_printf ("/favorites/%s/count", id); break; @@ -2517,29 +2493,6 @@ query_flathub_fiber (QueryFlathubData *data) return dex_future_new_for_int (total_downloads); } break; - - case PROP_DEVELOPER_APPS: - { - JsonObject *response_obj = NULL; - JsonArray *apps_array = NULL; - g_autoptr (GtkStringList) app_ids = NULL; - - response_obj = json_node_get_object (node); - apps_array = json_object_get_array_member (response_obj, "hits"); - - app_ids = gtk_string_list_new (NULL); - for (guint i = 0; i < json_array_get_length (apps_array); i++) - { - JsonObject *app_obj = json_array_get_object_element (apps_array, i); - const char *app_id = json_object_get_string_member (app_obj, "app_id"); - - if (app_id != NULL) - gtk_string_list_append (app_ids, app_id); - } - - return dex_future_new_for_object (app_ids); - } - break; case PROP_FAVORITES_COUNT: { int favorites_count = 0; @@ -2815,7 +2768,6 @@ clear_entry (BzEntry *self) g_clear_pointer (&priv->project_group, g_free); g_clear_pointer (&priv->developer, g_free); g_clear_pointer (&priv->developer_id, g_free); - g_clear_object (&priv->developer_apps); g_clear_object (&priv->screenshot_paintables); g_clear_object (&priv->screenshot_captions); g_clear_object (&priv->thumbnail_paintable); diff --git a/src/bz-full-view.blp b/src/bz-full-view.blp index 13dc1ba6..a307fcc9 100644 --- a/src/bz-full-view.blp +++ b/src/bz-full-view.blp @@ -670,12 +670,15 @@ template $BzFullView: Adw.Bin { model: SliceListModel other_apps_model { offset: 0; size: 6; - model: bind $get_developer_apps_entries(template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.developer-apps, template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>) as ; + model: FilterListModel { + model: bind template.developer-apps-model as ; + filter: CustomFilter is_equal_filter {}; + }; }; } Button { - visible: bind $is_longer(template.entry-group as <$BzEntryGroup>.ui-entry as <$BzResult>.object as <$BzEntry>.developer-apps, 6) as ; + visible: bind $is_longer(template.developer-apps-model, 6) as ; clicked => $more_apps_button_clicked_cb(template); halign: center; margin-top: 11; diff --git a/src/bz-full-view.c b/src/bz-full-view.c index ee00663f..b41169b1 100644 --- a/src/bz-full-view.c +++ b/src/bz-full-view.c @@ -66,6 +66,7 @@ struct _BzFullView BzResult *runtime; BzResult *group_model; gboolean show_sidebar; + GListModel *developer_apps_model; GMenuModel *main_menu; @@ -74,6 +75,7 @@ struct _BzFullView AdwViewStack *stack; GtkWidget *shadow_overlay; GtkToggleButton *description_toggle; + GtkCustomFilter *is_group_equal_filter; }; G_DEFINE_FINAL_TYPE (BzFullView, bz_full_view, ADW_TYPE_BIN) @@ -86,6 +88,7 @@ enum PROP_ENTRY_GROUP, PROP_UI_ENTRY, PROP_MAIN_MENU, + PROP_DEVELOPER_APPS_MODEL, LAST_PROP }; @@ -138,6 +141,9 @@ bz_full_view_get_property (GObject *object, case PROP_MAIN_MENU: g_value_set_object (value, self->main_menu); break; + case PROP_DEVELOPER_APPS_MODEL: + g_value_set_object (value, self->developer_apps_model); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -670,40 +676,29 @@ static void more_apps_button_clicked_cb (BzFullView *self, GtkButton *button) { - g_autoptr (GListModel) model = NULL; - guint n_items; - g_autofree char *title = NULL; - g_autofree char *subtitle = NULL; - AdwNavigationPage *apps_page = NULL; - GtkWidget *nav_view = NULL; - g_autoptr (GListModel) app_ids = NULL; - BzEntry *entry = NULL; - const char *developer = NULL; + guint n_items = 0; + g_autofree char *title = NULL; + g_autofree char *subtitle = NULL; + AdwNavigationPage *apps_page = NULL; + GtkWidget *nav_view = NULL; + const char *developer = NULL; g_return_if_fail (BZ_IS_FULL_VIEW (self)); g_return_if_fail (GTK_IS_BUTTON (button)); - entry = bz_result_get_object (self->ui_entry); - if (entry == NULL) + if (self->developer_apps_model == NULL) return; - g_object_get (entry, "developer-apps", &app_ids, NULL); + developer = bz_entry_group_get_developer (self->group); + n_items = g_list_model_get_n_items (self->developer_apps_model); - model = bz_application_map_factory_generate ( - bz_state_info_get_application_factory (self->state), - app_ids); - - n_items = g_list_model_get_n_items (model); - - developer = bz_entry_get_developer (entry); if (developer != NULL && *developer != '\0') - title = g_strdup_printf (_ ("Other Apps by %s"), developer); + title = g_strdup_printf (_ ("All Apps by %s"), developer); else - title = g_strdup (_ ("Other Apps")); - - subtitle = g_strdup_printf (ngettext ("%d Application", "%d Applications", n_items), n_items); + title = g_strdup (_ ("All Apps by developer")); - apps_page = bz_apps_page_new (title, model); + subtitle = g_strdup_printf (ngettext ("%d Application", "%d Applications", n_items), n_items); + apps_page = bz_apps_page_new (title, self->developer_apps_model); bz_apps_page_set_subtitle (BZ_APPS_PAGE (apps_page), subtitle); nav_view = gtk_widget_get_ancestor (GTK_WIDGET (self), ADW_TYPE_NAVIGATION_VIEW); @@ -948,6 +943,13 @@ get_description_toggle_text (gpointer object, return g_strdup (active ? _ ("Show Less") : _ ("Show More")); } +static gboolean +filter_own_group (BzEntryGroup *group, + BzFullView *self) +{ + return g_strcmp0 (bz_entry_group_get_id (group), bz_entry_group_get_id (self->group)) != 0; +} + static void copy_id_cb (BzFullView *self, GtkButton *button) @@ -1027,6 +1029,13 @@ bz_full_view_class_init (BzFullViewClass *klass) G_TYPE_MENU_MODEL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + props[PROP_DEVELOPER_APPS_MODEL] = + g_param_spec_object ( + "developer-apps-model", + NULL, NULL, + G_TYPE_LIST_MODEL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + g_object_class_install_properties (object_class, LAST_PROP, props); signals[SIGNAL_UPDATE] = @@ -1068,6 +1077,7 @@ bz_full_view_class_init (BzFullViewClass *klass) gtk_widget_class_bind_template_child (widget_class, BzFullView, main_scroll); gtk_widget_class_bind_template_child (widget_class, BzFullView, shadow_overlay); gtk_widget_class_bind_template_child (widget_class, BzFullView, description_toggle); + gtk_widget_class_bind_template_child (widget_class, BzFullView, is_group_equal_filter); gtk_widget_class_bind_template_callback (widget_class, is_scrolled_down); gtk_widget_class_bind_template_callback (widget_class, format_favorites_count); gtk_widget_class_bind_template_callback (widget_class, format_recent_downloads); @@ -1093,6 +1103,7 @@ bz_full_view_class_init (BzFullViewClass *klass) gtk_widget_class_bind_template_callback (widget_class, format_leftover_label); gtk_widget_class_bind_template_callback (widget_class, format_other_apps_label); gtk_widget_class_bind_template_callback (widget_class, format_more_other_apps_label); + gtk_widget_class_bind_template_callback (widget_class, filter_own_group); gtk_widget_class_bind_template_callback (widget_class, get_developer_apps_entries); gtk_widget_class_bind_template_callback (widget_class, get_dev_apps_max_children_per_line); gtk_widget_class_bind_template_callback (widget_class, more_apps_button_clicked_cb); @@ -1117,10 +1128,21 @@ bz_full_view_class_init (BzFullViewClass *klass) gtk_widget_class_bind_template_callback (widget_class, debug_id_inspect_cb); } +static gboolean +is_group_equal_filter (BzEntryGroup *group, + BzFullView *self) +{ + return g_strcmp0 (bz_entry_group_get_id (group), bz_entry_group_get_id (self->group)) != 0; +} + static void bz_full_view_init (BzFullView *self) { gtk_widget_init_template (GTK_WIDGET (self)); + + gtk_custom_filter_set_filter_func ( + self->is_group_equal_filter, (GtkCustomFilterFunc) is_group_equal_filter, + self, NULL); } GtkWidget * @@ -1152,6 +1174,13 @@ on_ui_entry_resolved (DexFuture *future, return dex_future_new_for_boolean (TRUE); } +static gboolean +filter_by_developer (BzEntryGroup *group, + const char *developer) +{ + return g_strcmp0 (bz_entry_group_get_developer (group), developer) == 0; +} + void bz_full_view_set_entry_group (BzFullView *self, BzEntryGroup *group) @@ -1168,6 +1197,7 @@ bz_full_view_set_entry_group (BzFullView *self, g_clear_object (&self->ui_entry); g_clear_object (&self->runtime); g_clear_object (&self->group_model); + g_clear_object (&self->developer_apps_model); gtk_toggle_button_set_active (self->description_toggle, FALSE); if (group != NULL) @@ -1216,6 +1246,27 @@ bz_full_view_set_entry_group (BzFullView *self, } } + { + const char *developer = NULL; + GListModel *all_groups = NULL; + + developer = bz_entry_group_get_developer (group); + if (developer != NULL && *developer != '\0') + { + all_groups = bz_state_info_get_filtered_entry_groups ( + self->state); + + if (all_groups != NULL) + self->developer_apps_model = G_LIST_MODEL ( + gtk_filter_list_model_new ( + g_object_ref (all_groups), + GTK_FILTER (gtk_custom_filter_new ( + (GtkCustomFilterFunc) filter_by_developer, + g_strdup (developer), + g_free)))); + } + } + adw_view_stack_set_visible_child_name (self->stack, "content"); } else @@ -1225,6 +1276,7 @@ bz_full_view_set_entry_group (BzFullView *self, g_object_notify_by_pspec (G_OBJECT (self), props[PROP_ENTRY_GROUP]); g_object_notify_by_pspec (G_OBJECT (self), props[PROP_UI_ENTRY]); + g_object_notify_by_pspec (G_OBJECT (self), props[PROP_DEVELOPER_APPS_MODEL]); } BzEntryGroup * From bfcf761c546d665aa057753dc700595de42cd72a Mon Sep 17 00:00:00 2001 From: Alexander Vanhee <160625516+AlexanderVanhee@users.noreply.github.com> Date: Tue, 7 Apr 2026 19:32:15 +0200 Subject: [PATCH 2/2] Update bz-full-view.blp --- src/bz-full-view.blp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bz-full-view.blp b/src/bz-full-view.blp index a307fcc9..c0fd9d9d 100644 --- a/src/bz-full-view.blp +++ b/src/bz-full-view.blp @@ -672,7 +672,7 @@ template $BzFullView: Adw.Bin { size: 6; model: FilterListModel { model: bind template.developer-apps-model as ; - filter: CustomFilter is_equal_filter {}; + filter: CustomFilter is_group_equal_filter {}; }; }; }