[gnome-software/1298-last-checked-timestamp-is-not-updated-when-you-leave-the-window-open] gs-updates-page: Refresh "Last checked:" information periodically



commit efed92459fa205caf005f85e05162856fe3fb02f
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.
    
    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 | 95 ++++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 143 insertions(+), 25 deletions(-)
---
diff --git a/src/gs-common.c b/src/gs-common.c
index cfba8208c..9c57a5573 100644
--- a/src/gs-common.c
+++ b/src/gs-common.c
@@ -735,16 +735,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;
@@ -753,7 +767,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 ();
@@ -766,6 +780,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 1e899eeb4..ef29c1b33 100644
--- a/src/gs-common.h
+++ b/src/gs-common.h
@@ -52,5 +52,12 @@ gchar                *gs_utils_time_to_string        (gint64          unix_time_seconds);
 void            gs_utils_invoke_reboot_async   (GCancellable   *cancellable,
                                                 GAsyncReadyCallback ready_callback,
                                                 gpointer        user_data);
+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 2233e22b1..c2d532472 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 {
@@ -178,12 +180,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 void
@@ -203,11 +213,64 @@ refresh_headerbar_updates_counter (GsUpdatesPage *self)
        g_object_notify (G_OBJECT (self), "counter");
 }
 
+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);
+               hdy_status_page_set_description (HDY_STATUS_PAGE (self->updates_uptodate_page),
+                                                last_checked);
+
+               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 {
+               hdy_status_page_set_description (HDY_STATUS_PAGE (self->updates_uptodate_page),
+                                                NULL);
+       }
+}
+
 static void
 gs_updates_page_update_ui_state (GsUpdatesPage *self)
 {
        gboolean allow_mobile_refresh = TRUE;
-       g_autofree gchar *checked_str = NULL;
+
+       gs_updates_page_remove_last_checked_timeout (self);
 
        if (gs_shell_get_mode (self->shell) != GS_SHELL_MODE_UPDATES)
                return;
@@ -345,20 +408,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);
-                       hdy_status_page_set_description (HDY_STATUS_PAGE (self->updates_uptodate_page),
-                                                        last_checked);
-               } else {
-                       hdy_status_page_set_description (HDY_STATUS_PAGE (self->updates_uptodate_page),
-                                                        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);
@@ -635,6 +686,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,
@@ -1311,6 +1369,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);
@@ -1349,6 +1409,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]