[gnome-software/gnome-40: 1/2] gs-updates-page: Refresh "Last checked:" information periodically




commit e0b2493a2bcd09adbd240708313eb0614410c81d
Author: Milan Crha <mcrha redhat com>
Date:   Mon Jun 28 17:59:50 2021 +0200

    gs-updates-page: Refresh "Last checked:" information periodically
    
    Helps to keep the information up to date when the user lefts the window
    open at the Updates page.
    
    (Minor fixes for cherry-pick conflicts due to not using libhandy in
    gnome-40.)
    
    Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/1298

 src/gs-common.c       | 66 +++++++++++++++++++++++++++++++-----
 src/gs-common.h       |  7 ++++
 src/gs-updates-page.c | 93 ++++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 143 insertions(+), 23 deletions(-)
---
diff --git a/src/gs-common.c b/src/gs-common.c
index eea004573..54ca9eaf4 100644
--- a/src/gs-common.c
+++ b/src/gs-common.c
@@ -706,16 +706,30 @@ gs_utils_reboot_notify (GsAppList *list)
 }
 
 /**
- * gs_utils_time_to_string:
+ * gs_utils_split_time_difference:
  * @unix_time_seconds: Time since the epoch in seconds
+ * @out_minutes_ago: (out) (nullable): how many minutes elapsed
+ * @out_hours_ago: (out) (nullable): how many hours elapsed
+ * @out_days_ago: (out) (nullable): how many days elapsed
+ * @out_weeks_ago: (out) (nullable): how many weeks elapsed
+ * @out_months_ago: (out) (nullable): how many months elapsed
+ * @out_years_ago: (out) (nullable): how many years elapsed
  *
- * Converts a time to a string such as "5 minutes ago" or "2 weeks ago"
+ * Calculates the difference between the @unix_time_seconds and the current time
+ * and splits it into separate values.
  *
- * Returns: (transfer full): the time string, or %NULL if @unix_time_seconds is
- *   not valid
- */
-gchar *
-gs_utils_time_to_string (gint64 unix_time_seconds)
+ * Returns: whether the out parameters had been set
+ *
+ * Since: 41
+ **/
+gboolean
+gs_utils_split_time_difference (gint64 unix_time_seconds,
+                               gint *out_minutes_ago,
+                               gint *out_hours_ago,
+                               gint *out_days_ago,
+                               gint *out_weeks_ago,
+                               gint *out_months_ago,
+                               gint *out_years_ago)
 {
        gint minutes_ago, hours_ago, days_ago;
        gint weeks_ago, months_ago, years_ago;
@@ -724,7 +738,7 @@ gs_utils_time_to_string (gint64 unix_time_seconds)
        GTimeSpan timespan;
 
        if (unix_time_seconds <= 0)
-               return NULL;
+               return FALSE;
 
        date_time = g_date_time_new_from_unix_local (unix_time_seconds);
        now = g_date_time_new_now_local ();
@@ -737,6 +751,42 @@ gs_utils_time_to_string (gint64 unix_time_seconds)
        months_ago = days_ago / 30;
        years_ago = weeks_ago / 52;
 
+       if (out_minutes_ago)
+               *out_minutes_ago = minutes_ago;
+       if (out_hours_ago)
+               *out_hours_ago = hours_ago;
+       if (out_days_ago)
+               *out_days_ago = days_ago;
+       if (out_weeks_ago)
+               *out_weeks_ago = weeks_ago;
+       if (out_months_ago)
+               *out_months_ago = months_ago;
+       if (out_years_ago)
+               *out_years_ago = years_ago;
+
+       return TRUE;
+}
+
+/**
+ * gs_utils_time_to_string:
+ * @unix_time_seconds: Time since the epoch in seconds
+ *
+ * Converts a time to a string such as "5 minutes ago" or "2 weeks ago"
+ *
+ * Returns: (transfer full): the time string, or %NULL if @unix_time_seconds is
+ *   not valid
+ */
+gchar *
+gs_utils_time_to_string (gint64 unix_time_seconds)
+{
+       gint minutes_ago, hours_ago, days_ago;
+       gint weeks_ago, months_ago, years_ago;
+
+       if (!gs_utils_split_time_difference (unix_time_seconds,
+               &minutes_ago, &hours_ago, &days_ago,
+               &weeks_ago, &months_ago, &years_ago))
+               return NULL;
+
        if (minutes_ago < 5) {
                /* TRANSLATORS: something happened less than 5 minutes ago */
                return g_strdup (_("Just now"));
diff --git a/src/gs-common.h b/src/gs-common.h
index 068e36086..f677758e6 100644
--- a/src/gs-common.h
+++ b/src/gs-common.h
@@ -48,5 +48,12 @@ gboolean      gs_utils_list_has_component_fuzzy      (GsAppList      *list,
                                                 GsApp          *app);
 void            gs_utils_reboot_notify         (GsAppList      *list);
 gchar          *gs_utils_time_to_string        (gint64          unix_time_seconds);
+gboolean       gs_utils_split_time_difference  (gint64 unix_time_seconds,
+                                                gint *out_minutes_ago,
+                                                gint *out_hours_ago,
+                                                gint *out_days_ago,
+                                                gint *out_weeks_ago,
+                                                gint *out_months_ago,
+                                                gint *out_years_ago);
 
 G_END_DECLS
diff --git a/src/gs-updates-page.c b/src/gs-updates-page.c
index 01399820b..83165520e 100644
--- a/src/gs-updates-page.c
+++ b/src/gs-updates-page.c
@@ -84,6 +84,8 @@ struct _GsUpdatesPage
        GtkSizeGroup            *sizegroup_button;
        GtkSizeGroup            *sizegroup_header;
        GtkListBox              *sections[GS_UPDATES_SECTION_KIND_LAST];
+
+       guint                    refresh_last_checked_id;
 };
 
 enum {
@@ -172,12 +174,20 @@ _get_num_updates (GsUpdatesPage *self)
 }
 
 static gchar *
-gs_updates_page_last_checked_time_string (GsUpdatesPage *self)
+gs_updates_page_last_checked_time_string (GsUpdatesPage *self,
+                                         gint *out_hours_ago,
+                                         gint *out_days_ago)
 {
        gint64 last_checked;
+       gchar *res;
 
        g_settings_get (self->settings, "check-timestamp", "x", &last_checked);
-       return gs_utils_time_to_string (last_checked);
+       res = gs_utils_time_to_string (last_checked);
+       if (res) {
+               g_assert (gs_utils_split_time_difference (last_checked, NULL, out_hours_ago, out_days_ago, 
NULL, NULL, NULL));
+       }
+
+       return res;
 }
 
 static const gchar *
@@ -215,13 +225,66 @@ refresh_headerbar_updates_counter (GsUpdatesPage *self)
                gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "needs-attention");
 }
 
+static void
+gs_updates_page_remove_last_checked_timeout (GsUpdatesPage *self)
+{
+       if (self->refresh_last_checked_id) {
+               g_source_remove (self->refresh_last_checked_id);
+               self->refresh_last_checked_id = 0;
+       }
+}
+
+static void
+gs_updates_page_refresh_last_checked (GsUpdatesPage *self);
+
+static gboolean
+gs_updates_page_refresh_last_checked_cb (gpointer user_data)
+{
+       GsUpdatesPage *self = user_data;
+       gs_updates_page_refresh_last_checked (self);
+       return G_SOURCE_REMOVE;
+}
+
+static void
+gs_updates_page_refresh_last_checked (GsUpdatesPage *self)
+{
+       g_autofree gchar *checked_str = NULL;
+       gint hours_ago, days_ago;
+       checked_str = gs_updates_page_last_checked_time_string (self, &hours_ago, &days_ago);
+       if (checked_str != NULL) {
+               g_autofree gchar *last_checked = NULL;
+               guint interval;
+
+               /* TRANSLATORS: This is the time when we last checked for updates */
+               last_checked = g_strdup_printf (_("Last checked: %s"), checked_str);
+               gtk_label_set_label (GTK_LABEL (self->label_updates_last_checked),
+                                               last_checked);
+               gtk_widget_set_visible (self->label_updates_last_checked, TRUE);
+
+               if (hours_ago < 1)
+                       interval = 60;
+               else if (days_ago < 7)
+                       interval = 60 * 60;
+               else
+                       interval = 60 * 60 * 24;
+
+               gs_updates_page_remove_last_checked_timeout (self);
+
+               self->refresh_last_checked_id = g_timeout_add_seconds (interval,
+                       gs_updates_page_refresh_last_checked_cb, self);
+       } else {
+               gtk_widget_set_visible (self->label_updates_last_checked, FALSE);
+       }
+}
+
 static void
 gs_updates_page_update_ui_state (GsUpdatesPage *self)
 {
        gboolean allow_mobile_refresh = TRUE;
-       g_autofree gchar *checked_str = NULL;
        g_autofree gchar *spinner_str = NULL;
 
+       gs_updates_page_remove_last_checked_timeout (self);
+
        if (gs_shell_get_mode (self->shell) != GS_SHELL_MODE_UPDATES)
                return;
 
@@ -362,18 +425,8 @@ gs_updates_page_update_ui_state (GsUpdatesPage *self)
                                self->result_flags & GS_UPDATES_PAGE_FLAG_HAS_UPDATES);
 
        /* last checked label */
-       if (g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (self->stack_updates)), "uptodate") == 0) {
-               checked_str = gs_updates_page_last_checked_time_string (self);
-               if (checked_str != NULL) {
-                       g_autofree gchar *last_checked = NULL;
-
-                       /* TRANSLATORS: This is the time when we last checked for updates */
-                       last_checked = g_strdup_printf (_("Last checked: %s"), checked_str);
-                       gtk_label_set_label (GTK_LABEL (self->label_updates_last_checked),
-                                            last_checked);
-               }
-               gtk_widget_set_visible (self->label_updates_last_checked, checked_str != NULL);
-       }
+       if (g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (self->stack_updates)), "uptodate") == 0)
+               gs_updates_page_refresh_last_checked (self);
 
        /* update the counter in headerbar */
        refresh_headerbar_updates_counter (self);
@@ -666,6 +719,13 @@ gs_updates_page_switch_to (GsPage *page,
        gs_updates_page_load (self);
 }
 
+static void
+gs_updates_page_switch_from (GsPage *page)
+{
+       GsUpdatesPage *self = GS_UPDATES_PAGE (page);
+       gs_updates_page_remove_last_checked_timeout (self);
+}
+
 static void
 gs_updates_page_refresh_cb (GsPluginLoader *plugin_loader,
                             GAsyncResult *res,
@@ -1299,6 +1359,8 @@ gs_updates_page_dispose (GObject *object)
 {
        GsUpdatesPage *self = GS_UPDATES_PAGE (object);
 
+       gs_updates_page_remove_last_checked_timeout (self);
+
        g_cancellable_cancel (self->cancellable_refresh);
        g_clear_object (&self->cancellable_refresh);
        g_cancellable_cancel (self->cancellable_upgrade_download);
@@ -1335,6 +1397,7 @@ gs_updates_page_class_init (GsUpdatesPageClass *klass)
 
        object_class->dispose = gs_updates_page_dispose;
        page_class->switch_to = gs_updates_page_switch_to;
+       page_class->switch_from = gs_updates_page_switch_from;
        page_class->reload = gs_updates_page_reload;
        page_class->setup = gs_updates_page_setup;
 


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