[gnome-software: 6/18] gs-details-page: Add community-built tile




commit 1da32151731a7e1da4926fd4b23275ab7ec8b40b
Author: Philip Withnall <pwithnall endlessos org>
Date:   Mon Jul 26 15:32:22 2021 +0100

    gs-details-page: Add community-built tile
    
    This is shown to highlight FOSS applications.
    
    Designs: 
https://gitlab.gnome.org/Teams/Design/software-mockups/-/raw/master/adaptive/app-page-adaptive.png
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Helps: #1111, #1285

 po/POTFILES.in                   |   2 +
 src/gnome-software.gresource.xml |   1 +
 src/gs-details-page.c            |  12 ++
 src/gs-details-page.ui           |  10 ++
 src/gs-license-tile.c            | 313 +++++++++++++++++++++++++++++++++++++++
 src/gs-license-tile.h            |  31 ++++
 src/gs-license-tile.ui           | 148 ++++++++++++++++++
 src/gtk-style-hc.css             |   2 +
 src/meson.build                  |   1 +
 9 files changed, 520 insertions(+)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ece3e1ea9..49bf95f56 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -43,6 +43,8 @@ src/gs-history-dialog.c
 src/gs-history-dialog.ui
 src/gs-installed-page.c
 src/gs-installed-page.ui
+src/gs-license-tile.c
+src/gs-license-tile.ui
 src/gs-loading-page.c
 src/gs-loading-page.ui
 src/gs-main.c
diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index 436b1d2ef..8a090a3c3 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -20,6 +20,7 @@
   <file preprocess="xml-stripblanks">gs-history-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-info-bar.ui</file>
   <file preprocess="xml-stripblanks">gs-installed-page.ui</file>
+  <file preprocess="xml-stripblanks">gs-license-tile.ui</file>
   <file preprocess="xml-stripblanks">gs-loading-page.ui</file>
   <file preprocess="xml-stripblanks">gs-metered-data-dialog.ui</file>
   <file preprocess="xml-stripblanks">gs-moderate-page.ui</file>
diff --git a/src/gs-details-page.c b/src/gs-details-page.c
index 656b00f44..b68326125 100644
--- a/src/gs-details-page.c
+++ b/src/gs-details-page.c
@@ -24,6 +24,7 @@
 #include "gs-app-version-history-dialog.h"
 #include "gs-description-box.h"
 #include "gs-history-dialog.h"
+#include "gs-license-tile.h"
 #include "gs-origin-popover-row.h"
 #include "gs-screenshot-carousel.h"
 #include "gs-star-widget.h"
@@ -157,6 +158,7 @@ struct _GsDetailsPage
        GtkWidget               *origin_popover_list_box;
        GtkWidget               *origin_box;
        GtkWidget               *origin_button_label;
+       GsLicenseTile           *license_tile;
 };
 
 G_DEFINE_TYPE (GsDetailsPage, gs_details_page, GS_TYPE_PAGE)
@@ -566,6 +568,13 @@ gs_details_page_link_row_activated_cb (HdyActionRow *row, GsDetailsPage *self)
        gs_shell_show_uri (self->shell, hdy_action_row_get_subtitle (row));
 }
 
+static void
+gs_details_page_license_tile_get_involved_activated_cb (GsLicenseTile *license_tile,
+                                                       GsDetailsPage *self)
+{
+       gs_shell_show_uri (self->shell, gs_app_get_url (self->app, AS_URL_KIND_HOMEPAGE));
+}
+
 static void
 gs_details_page_set_description (GsDetailsPage *self, const gchar *tmp)
 {
@@ -1594,6 +1603,7 @@ _set_app (GsDetailsPage *self, GsApp *app)
        g_set_object (&self->app, app);
 
        gs_app_context_bar_set_app (self->context_bar, app);
+       gs_license_tile_set_app (self->license_tile, app);
 
        /* title/app name will have changed */
        g_object_notify (G_OBJECT (self), "title");
@@ -2482,8 +2492,10 @@ gs_details_page_class_init (GsDetailsPageClass *klass)
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, origin_popover_list_box);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, origin_box);
        gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, origin_button_label);
+       gtk_widget_class_bind_template_child (widget_class, GsDetailsPage, license_tile);
 
        gtk_widget_class_bind_template_callback (widget_class, gs_details_page_link_row_activated_cb);
+       gtk_widget_class_bind_template_callback (widget_class, 
gs_details_page_license_tile_get_involved_activated_cb);
 }
 
 static void
diff --git a/src/gs-details-page.ui b/src/gs-details-page.ui
index ee9f7886c..1b78c4671 100644
--- a/src/gs-details-page.ui
+++ b/src/gs-details-page.ui
@@ -547,9 +547,19 @@
                         <child>
                           <object class="GtkBox">
                             <property name="visible">True</property>
+                            <property name="homogeneous">True</property>
                             <property name="orientation">horizontal</property>
                             <property name="spacing">12</property>
 
+                            <child>
+                              <object class="GsLicenseTile" id="license_tile">
+                                <property name="visible">True</property>
+                                <property name="halign">fill</property>
+                                <property name="valign">start</property>
+                                <signal name="get-involved-activated" 
handler="gs_details_page_license_tile_get_involved_activated_cb"/>
+                              </object>
+                            </child>
+
                             <child>
                               <object class="GtkStack" id="links_stack">
                                 <property name="visible">True</property>
diff --git a/src/gs-license-tile.c b/src/gs-license-tile.c
new file mode 100644
index 000000000..0150b806b
--- /dev/null
+++ b/src/gs-license-tile.c
@@ -0,0 +1,313 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Endless OS Foundation LLC
+ *
+ * Author: Philip Withnall <pwithnall endlessos org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/**
+ * SECTION:gs-license-tile
+ * @short_description: A tile for displaying license information about an app
+ *
+ * #GsLicenseTile is a tile which displays high-level license information about
+ * an app. Broadly, whether it is FOSS or proprietary.
+ *
+ * It checks the license information in the provided #GsApp. If
+ * #GsLicenseTile:app is %NULL, the behaviour of the widget is undefined.
+ *
+ * Since: 41
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gs-common.h"
+#include "gs-license-tile.h"
+
+struct _GsLicenseTile
+{
+       GtkListBox       parent_instance;
+
+       GsApp           *app;  /* (nullable) (owned) */
+       gulong           notify_license_handler;
+       gulong           notify_urls_handler;
+
+       GtkWidget       *lozenges[3];
+       GtkImage        *lozenge_images[3];
+       GtkLabel        *title_label;
+       GtkLabel        *description_label;
+       GtkListBoxRow   *get_involved_row;
+};
+
+G_DEFINE_TYPE (GsLicenseTile, gs_license_tile, GTK_TYPE_LIST_BOX)
+
+typedef enum {
+       PROP_APP = 1,
+} GsLicenseTileProperty;
+
+static GParamSpec *obj_props[PROP_APP + 1] = { NULL, };
+
+typedef enum {
+       SIGNAL_GET_INVOLVED_ACTIVATED,
+} GsFeaturedCarouselSignal;
+
+static guint obj_signals[SIGNAL_GET_INVOLVED_ACTIVATED + 1] = { 0, };
+
+static void
+gs_license_tile_init (GsLicenseTile *self)
+{
+       gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+static void
+gs_license_tile_row_activated_cb (GtkListBox    *box,
+                                  GtkListBoxRow *row,
+                                  gpointer       user_data)
+{
+       GsLicenseTile *self = GS_LICENSE_TILE (user_data);
+
+       /* The ‘Get Involved’ row is the only activatable one */
+       g_signal_emit (self, obj_signals[SIGNAL_GET_INVOLVED_ACTIVATED], 0);
+}
+
+static void
+gs_license_tile_refresh (GsLicenseTile *self)
+{
+       const gchar *title, *css_class;
+       const gchar *lozenge_icon_names[3];
+       g_autofree gchar *description = NULL;
+       gboolean get_involved_visible;
+
+       /* Widget behaviour is undefined if the app is unspecified. */
+       if (self->app == NULL)
+               return;
+
+       if (gs_app_get_license_is_free (self->app)) {
+               title = _("Community Built");
+               css_class = "green";
+               lozenge_icon_names[0] = "heart-filled-symbolic";
+               lozenge_icon_names[1] = "system-users-symbolic";
+               lozenge_icon_names[2] = "sign-language-symbolic";
+               get_involved_visible = (gs_app_get_url (self->app, AS_URL_KIND_HOMEPAGE) != NULL);
+
+               /* Translators: The placeholder here is the name of a software license. */
+               description = g_strdup_printf (_("This app is developed in the open by a community of 
volunteers, and released under the %s license."
+                                                "\n\n"
+                                                "You can contribute and help make it even better."),
+                                                gs_app_get_license (self->app));
+       } else {
+               title = _("Proprietary");
+               css_class = "red";
+               lozenge_icon_names[0] = "dialog-warning-symbolic";
+               lozenge_icon_names[1] = "face-sad-symbolic";
+               lozenge_icon_names[2] = "padlock-open-symbolic";
+               get_involved_visible = FALSE;
+
+               description = g_strdup (_("This app is not developed in the open, so only its developers know 
how it works. It could be insecure, or actively do nefarious things that are hard to detect or prevent."
+                                         "\n\n"
+                                         "By installing this app you are putting a high amount of trust in 
the developers."));
+       }
+
+       for (gsize i = 0; i < G_N_ELEMENTS (self->lozenges); i++) {
+               GtkStyleContext *context = gtk_widget_get_style_context (self->lozenges[i]);
+               gtk_style_context_remove_class (context, "green");
+               gtk_style_context_remove_class (context, "red");
+               gtk_style_context_add_class (context, css_class);
+       }
+
+       for (gsize i = 0; i < G_N_ELEMENTS (self->lozenge_images); i++)
+               gtk_image_set_from_icon_name (self->lozenge_images[i], lozenge_icon_names[i], 
GTK_ICON_SIZE_BUTTON);
+
+       gtk_label_set_label (self->title_label, title);
+       gtk_label_set_label (self->description_label, description);
+       gtk_widget_set_visible (GTK_WIDGET (self->get_involved_row), get_involved_visible);
+}
+
+static void
+notify_license_or_urls_cb (GObject    *object,
+                           GParamSpec *pspec,
+                           gpointer    user_data)
+{
+       gs_license_tile_refresh (GS_LICENSE_TILE (user_data));
+}
+
+static void
+gs_license_tile_get_property (GObject    *object,
+                              guint       prop_id,
+                              GValue     *value,
+                              GParamSpec *pspec)
+{
+       GsLicenseTile *self = GS_LICENSE_TILE (object);
+
+       switch ((GsLicenseTileProperty) prop_id) {
+       case PROP_APP:
+               g_value_set_object (value, gs_license_tile_get_app (self));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+gs_license_tile_set_property (GObject      *object,
+                              guint         prop_id,
+                              const GValue *value,
+                              GParamSpec   *pspec)
+{
+       GsLicenseTile *self = GS_LICENSE_TILE (object);
+
+       switch ((GsLicenseTileProperty) prop_id) {
+       case PROP_APP:
+               gs_license_tile_set_app (self, g_value_get_object (value));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+gs_license_tile_dispose (GObject *object)
+{
+       GsLicenseTile *self = GS_LICENSE_TILE (object);
+
+       gs_license_tile_set_app (self, NULL);
+
+       G_OBJECT_CLASS (gs_license_tile_parent_class)->dispose (object);
+}
+
+static void
+gs_license_tile_class_init (GsLicenseTileClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       object_class->get_property = gs_license_tile_get_property;
+       object_class->set_property = gs_license_tile_set_property;
+       object_class->dispose = gs_license_tile_dispose;
+
+       /**
+        * GsLicenseTile:app: (nullable)
+        *
+        * Application to display license information for.
+        *
+        * If this is %NULL, the state of the widget is undefined.
+        *
+        * Since: 41
+        */
+       obj_props[PROP_APP] =
+               g_param_spec_object ("app", NULL, NULL,
+                                    GS_TYPE_APP,
+                                    G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+       g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_props), obj_props);
+
+       /**
+        * GsLicenseTile::get-involved-activated:
+        *
+        * Emitted when the ‘Get Involved’ button is clicked, for a #GsApp which
+        * is FOSS licensed.
+        *
+        * Typically the caller should open the app’s ‘get involved’ link or
+        * homepage when this signal is emitted.
+        *
+        * Since: 41
+        */
+       obj_signals[SIGNAL_GET_INVOLVED_ACTIVATED] =
+               g_signal_new ("get-involved-activated",
+                             G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+                             0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+
+       gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-license-tile.ui");
+
+       gtk_widget_class_bind_template_child_full (widget_class, "lozenge0", FALSE, G_STRUCT_OFFSET 
(GsLicenseTile, lozenges[0]));
+       gtk_widget_class_bind_template_child_full (widget_class, "lozenge0_image", FALSE, G_STRUCT_OFFSET 
(GsLicenseTile, lozenge_images[0]));
+       gtk_widget_class_bind_template_child_full (widget_class, "lozenge1", FALSE, G_STRUCT_OFFSET 
(GsLicenseTile, lozenges[1]));
+       gtk_widget_class_bind_template_child_full (widget_class, "lozenge1_image", FALSE, G_STRUCT_OFFSET 
(GsLicenseTile, lozenge_images[1]));
+       gtk_widget_class_bind_template_child_full (widget_class, "lozenge2", FALSE, G_STRUCT_OFFSET 
(GsLicenseTile, lozenges[2]));
+       gtk_widget_class_bind_template_child_full (widget_class, "lozenge2_image", FALSE, G_STRUCT_OFFSET 
(GsLicenseTile, lozenge_images[2]));
+       gtk_widget_class_bind_template_child (widget_class, GsLicenseTile, title_label);
+       gtk_widget_class_bind_template_child (widget_class, GsLicenseTile, description_label);
+       gtk_widget_class_bind_template_child (widget_class, GsLicenseTile, get_involved_row);
+
+       gtk_widget_class_bind_template_callback (widget_class, gs_license_tile_row_activated_cb);
+}
+
+/**
+ * gs_license_tile_new:
+ * @app: (nullable) (transfer none): app to display the license information for
+ *
+ * Create a new #GsLicenseTile.
+ *
+ * Returns: (transfer full) (type GsLicenseTile): a new #GsLicenseTile
+ * Since: 41
+ */
+GtkWidget *
+gs_license_tile_new (GsApp *app)
+{
+       g_return_val_if_fail (app == NULL || GS_IS_APP (app), NULL);
+
+       return g_object_new (GS_TYPE_LICENSE_TILE,
+                            "app", app,
+                            NULL);
+}
+
+/**
+ * gs_license_tile_get_app:
+ * @self: a #GsLicenseTile
+ *
+ * Get the value of #GsLicenseTile:app.
+ *
+ * Returns: (transfer none) (nullable): the app being displayed in the tile
+ * Since: 41
+ */
+GsApp *
+gs_license_tile_get_app (GsLicenseTile *self)
+{
+       g_return_val_if_fail (GS_IS_LICENSE_TILE (self), NULL);
+
+       return self->app;
+}
+
+/**
+ * gs_license_tile_set_app:
+ * @self: a #GsLicenseTile
+ * @app: (nullable) (transfer none): new app to display in the tile
+ *
+ * Set the value of #GsLicenseTile:app to @app.
+ *
+ * Since: 41
+ */
+void
+gs_license_tile_set_app (GsLicenseTile *self,
+                         GsApp         *app)
+{
+       g_return_if_fail (GS_IS_LICENSE_TILE (self));
+       g_return_if_fail (app == NULL || GS_IS_APP (app));
+
+       if (self->app == app)
+               return;
+
+       g_clear_signal_handler (&self->notify_license_handler, self->app);
+       g_clear_signal_handler (&self->notify_urls_handler, self->app);
+
+       g_set_object (&self->app, app);
+
+       if (self->app != NULL) {
+               self->notify_license_handler = g_signal_connect (self->app, "notify::license", G_CALLBACK 
(notify_license_or_urls_cb), self);
+               self->notify_urls_handler = g_signal_connect (self->app, "notify::urls", G_CALLBACK 
(notify_license_or_urls_cb), self);
+       }
+
+       gs_license_tile_refresh (self);
+
+       g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_APP]);
+}
diff --git a/src/gs-license-tile.h b/src/gs-license-tile.h
new file mode 100644
index 000000000..b8d82a71d
--- /dev/null
+++ b/src/gs-license-tile.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Endless OS Foundation LLC
+ *
+ * Author: Philip Withnall <pwithnall endlessos org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#pragma once
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "gs-app.h"
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_LICENSE_TILE (gs_license_tile_get_type ())
+
+G_DECLARE_FINAL_TYPE (GsLicenseTile, gs_license_tile, GS, LICENSE_TILE, GtkListBox)
+
+GtkWidget      *gs_license_tile_new            (GsApp *app);
+
+GsApp          *gs_license_tile_get_app        (GsLicenseTile *self);
+void            gs_license_tile_set_app        (GsLicenseTile *self,
+                                                GsApp         *app);
+
+G_END_DECLS
diff --git a/src/gs-license-tile.ui b/src/gs-license-tile.ui
new file mode 100644
index 000000000..e6289d765
--- /dev/null
+++ b/src/gs-license-tile.ui
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.10"/>
+  <template class="GsLicenseTile" parent="GtkListBox">
+    <property name="selection_mode">none</property>
+    <signal name="row-activated" handler="gs_license_tile_row_activated_cb"/>
+    <style>
+      <class name="content"/>
+    </style>
+
+    <child>
+      <object class="GtkListBoxRow">
+        <property name="activatable">False</property>
+        <property name="visible">True</property>
+        <property name="can-focus">True</property>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">8</property>
+            <property name="margin">14</property>
+
+            <child>
+              <object class="GtkBox">
+                <property name="halign">center</property>
+                <property name="visible">True</property>
+                <property name="orientation">horizontal</property>
+                <property name="spacing">8</property>
+
+                <child>
+                  <object class="GtkBox" id="lozenge0">
+                    <property name="halign">center</property>
+                    <property name="visible">True</property>
+                    <style>
+                      <class name="context-tile-lozenge"/>
+                      <class name="green"/>
+                    </style>
+                    <child>
+                      <object class="GtkImage" id="lozenge0_image">
+                        <property name="halign">center</property>
+                        <property name="icon-name">heart-filled-symbolic</property>
+                        <property name="visible">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox" id="lozenge1">
+                    <property name="halign">center</property>
+                    <property name="visible">True</property>
+                    <style>
+                      <class name="context-tile-lozenge"/>
+                      <class name="green"/>
+                    </style>
+                    <child>
+                      <object class="GtkImage" id="lozenge1_image">
+                        <property name="halign">center</property>
+                        <property name="icon-name">system-users-symbolic</property>
+                        <property name="visible">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox" id="lozenge2">
+                    <property name="halign">center</property>
+                    <property name="visible">True</property>
+                    <style>
+                      <class name="context-tile-lozenge"/>
+                      <class name="green"/>
+                    </style>
+                    <child>
+                      <object class="GtkImage" id="lozenge2_image">
+                        <property name="halign">center</property>
+                        <property name="icon-name">sign-language-symbolic</property>
+                        <property name="visible">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="title_label">
+                <property name="visible">True</property>
+                <!-- This text is a placeholder and will be set dynamically -->
+                <property name="label">Community Built</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+            </child>
+            <child>
+              <object class="GtkLabel" id="description_label">
+                <property name="visible">True</property>
+                <!-- This text is a placeholder and will be set dynamically -->
+                <property name="label">This app is developed in the open by a community of volunteers, and 
released under the GNU GPL v3 license.\n\nYou can contribute and help make it even better.</property>
+                <property name="wrap">True</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+
+    <child>
+      <object class="GtkListBoxRow" id="get_involved_row">
+        <property name="activatable">True</property>
+        <property name="visible">True</property>
+        <property name="can-focus">True</property>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="orientation">horizontal</property>
+            <property name="halign">center</property>
+            <property name="margin-top">12</property>
+            <property name="margin-bottom">12</property>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="xalign">0</property>
+                <property name="yalign">0.5</property>
+                <property name="label" translatable="yes">Get _Involved</property>
+                <property name="use-underline">True</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="icon-name">external-link-symbolic</property>
+                <property name="margin-start">6</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/gtk-style-hc.css b/src/gtk-style-hc.css
index 73977fc12..447be699f 100644
--- a/src/gtk-style-hc.css
+++ b/src/gtk-style-hc.css
@@ -71,3 +71,5 @@ app-context-bar .context-tile {
 .context-tile-lozenge.details-rating-15 { background-color: #ffd7a5; color: @theme_fg_color }
 .context-tile-lozenge.yellow, .context-tile-lozenge.details-rating-12 { background-color: #f7eb9f; color: 
@theme_fg_color }
 .context-tile-lozenge.details-rating-5 { background-color: #d1e4fb; color: @theme_fg_color }
+
+.community-built { color: @theme_fg_color }
diff --git a/src/meson.build b/src/meson.build
index b7783c40a..7fcfa14c1 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -50,6 +50,7 @@ gnome_software_sources = [
   'gs-info-bar.c',
   'gs-installed-page.c',
   'gs-language.c',
+  'gs-license-tile.c',
   'gs-loading-page.c',
   'gs-main.c',
   'gs-metered-data-dialog.c',


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