Minor updates:
+New features:
diff --git a/src/Plug.vala b/src/Plug.vala index d4fed1d8..f86d0747 100644 --- a/src/Plug.vala +++ b/src/Plug.vala @@ -27,6 +27,7 @@ public class About.Plug : Switchboard.Plug { private OperatingSystemView operating_system_view; private Adw.ToolbarView toolbarview; private Gtk.Stack stack; + private GLib.Cancellable sponsors_goal_cancellable; public Plug () { GLib.Intl.bindtextdomain (About.GETTEXT_PACKAGE, About.LOCALEDIR); @@ -91,9 +92,15 @@ public class About.Plug : Switchboard.Plug { public override void shown () { operating_system_view.load_logo.begin (); + + sponsors_goal_cancellable = new GLib.Cancellable (); + operating_system_view.load_sponsors_goal (sponsors_goal_cancellable); } public override void hidden () { + if (sponsors_goal_cancellable != null) { + sponsors_goal_cancellable.cancel (); + } } public override void search_callback (string location) { diff --git a/src/Views/OperatingSystemView.vala b/src/Views/OperatingSystemView.vala index 783c5058..f675362b 100644 --- a/src/Views/OperatingSystemView.vala +++ b/src/Views/OperatingSystemView.vala @@ -93,6 +93,7 @@ public class About.OperatingSystemView : Gtk.Box { private Gtk.Label updates_description; private Gtk.Revealer details_button_revealer; private Gtk.Stack button_stack; + private SponsorUsRow sponsor_us_row; construct { add_css_class ("operating-system-view"); @@ -250,6 +251,21 @@ public class About.OperatingSystemView : Gtk.Box { updates_list.get_first_child ().focusable = false; updates_list.get_last_child ().focusable = false; + sponsor_us_row = new SponsorUsRow ("https://github.com/sponsors/elementary"); + + var sponsor_list = new Gtk.ListBox () { + margin_bottom = 12, + margin_top = 12, + valign = CENTER, + show_separators = true, + selection_mode = NONE, + hexpand = true + }; + sponsor_list.add_css_class ("boxed-list"); + sponsor_list.add_css_class (Granite.STYLE_CLASS_RICH_LIST); + + sponsor_list.append (sponsor_us_row); + var thebasics_link = new LinkRow ( documentation_url, _("Basics Guide"), @@ -273,9 +289,9 @@ public class About.OperatingSystemView : Gtk.Box { var getinvolved_link = new LinkRow ( "https://elementary.io/get-involved", - _("Get Involved or Sponsor Us"), - "face-heart-symbolic", - "pink" + _("Get Involved"), + "applications-development-symbolic", + "purple" ); var links_list = new Gtk.ListBox () { @@ -319,7 +335,8 @@ public class About.OperatingSystemView : Gtk.Box { software_grid.attach (kernel_version_label, 1, 2); software_grid.attach (updates_list, 1, 3); - software_grid.attach (links_list, 1, 4); + software_grid.attach (sponsor_list, 1, 4); + software_grid.attach (links_list, 1, 5); var clamp = new Adw.Clamp () { child = software_grid, @@ -357,6 +374,10 @@ public class About.OperatingSystemView : Gtk.Box { } }); + sponsor_list.row_activated.connect ((row) => { + launch_uri (((SponsorUsRow) row).uri); + }); + links_list.row_activated.connect ((row) => { launch_uri (((LinkRow) row).uri); }); @@ -417,6 +438,14 @@ public class About.OperatingSystemView : Gtk.Box { } } + public void load_sponsors_goal (GLib.Cancellable cancellable) { + if (sponsor_us_row.was_loaded) { + return; + } + + sponsor_us_row.get_goal_progress (cancellable); + } + private async void get_upstream_release () { // Upstream distro version (for "Built on" text) // FIXME: Add distro specific field to /etc/os-release and use that instead @@ -713,4 +742,119 @@ public class About.OperatingSystemView : Gtk.Box { add_css_class ("link"); } } + + private class SponsorUsRow : Gtk.ListBoxRow { + public string uri { get; construct; } + + private Gtk.Label target_label; + private Gtk.LevelBar levelbar; + private Gtk.Revealer details_revealer; + + public SponsorUsRow (string uri) { + Object ( + uri: uri + ); + } + + public bool was_loaded { + get { + return details_revealer.reveal_child; + } + } + + class construct { + set_accessible_role (LINK); + } + + construct { + var image = new Gtk.Image.from_icon_name ("face-heart-symbolic"); + image.add_css_class (Granite.STYLE_CLASS_ACCENT); + image.add_css_class ("pink"); + + var main_label = new Gtk.Label (_("Sponsor Us")) { + halign = START, + hexpand = true + }; + + target_label = new Gtk.Label (null) { + halign = START + }; + target_label.add_css_class (Granite.STYLE_CLASS_DIM_LABEL); + target_label.add_css_class (Granite.STYLE_CLASS_SMALL_LABEL); + + levelbar = new Gtk.LevelBar (); + levelbar.add_css_class (Granite.STYLE_CLASS_FLAT); + levelbar.add_css_class ("pink"); + + var details_box = new Gtk.Box (VERTICAL, 0); + details_box.append (target_label); + details_box.append (levelbar); + + details_revealer = new Gtk.Revealer () { + child = details_box, + reveal_child = false + }; + + var link_image = new Gtk.Image.from_icon_name ("adw-external-link-symbolic"); + + var grid = new Gtk.Grid () { + valign = CENTER + }; + grid.attach (image, 0, 0, 1, 2); + grid.attach (main_label, 1, 0); + grid.attach (details_revealer, 1, 1); + grid.attach (link_image, 2, 0, 2, 2); + + child = grid; + add_css_class ("link"); + } + + public void get_goal_progress (GLib.Cancellable cancellable) { + var message = new Soup.Message ("GET", "https://elementary.io/api/sponsors_goal"); + var session = new Soup.Session (); + session.send_and_read_async.begin (message, GLib.Priority.DEFAULT, cancellable , (obj, res) => { + try { + var bytes = session.send_and_read_async.end (res); + + var output = (string) bytes.get_data (); + if (output == null) { + return; + } + + var parser = new Json.Parser (); + parser.load_from_data (output); + + var root = parser.get_root (); + if (root.get_node_type () != OBJECT) { + return; + } + + int64 percent_complete = root.get_object ().get_int_member ("percent"); + double target_value = root.get_object ().get_double_member ("target"); + + var animation_target = new Adw.CallbackAnimationTarget ((val) => { + ///TRANSLATORS: first value is a percentage, second value is an amount in USD + target_label.label = _("%.0f%% towards $%'5.0f per month goal").printf ( + Math.round (val), + target_value + ); + + levelbar.value = val / 100.0; + }); + + var animation = new Adw.TimedAnimation ( + this, 0, percent_complete, 1000, + animation_target + ) { + easing = EASE_IN_OUT_QUAD + }; + + details_revealer.reveal_child = true; + animation.play (); + } catch (Error e) { + critical (e.message); + } + }); + } + } } diff --git a/src/meson.build b/src/meson.build index de2e15d2..57bd2a4a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -41,10 +41,12 @@ shared_module( dependency('gtk4'), dependency('libadwaita-1'), dependency('libgtop-2.0'), + dependency('libsoup-3.0'), dependency('packagekit-glib2'), dependency('gudev-1.0'), dependency('udisks2'), dependency('polkit-gobject-1'), + dependency('json-glib-1.0'), appstream_dep, meson.get_compiler('vala').find_library('posix'), switchboard_dep