[evolution/gnome-3-30] I#122 - Avoid delayed message send when editing the Outbox message



commit 4bd327f09f79286680c509daa374d0b4906aa819
Author: Milan Crha <mcrha redhat com>
Date:   Mon Sep 10 17:44:17 2018 +0200

    I#122 - Avoid delayed message send when editing the Outbox message
    
    Closes https://gitlab.gnome.org/GNOME/evolution/issues/122

 src/libemail-engine/e-mail-session.c | 10 ++---
 src/libemail-engine/mail-ops.c       | 47 ++++++++++++++++++++---
 src/libemail-engine/mail-ops.h       |  3 ++
 src/mail/em-composer-utils.c         | 74 ++++++++++++++++++++++++++++++------
 4 files changed, 110 insertions(+), 24 deletions(-)
---
diff --git a/src/libemail-engine/e-mail-session.c b/src/libemail-engine/e-mail-session.c
index 65c3420b2e..9dd93cea63 100644
--- a/src/libemail-engine/e-mail-session.c
+++ b/src/libemail-engine/e-mail-session.c
@@ -2568,13 +2568,11 @@ e_mail_session_schedule_outbox_flush (EMailSession *session,
        }
 
        g_mutex_lock (&session->priv->preparing_flush_lock);
-       if (session->priv->outbox_flush_id > 0) {
-               g_source_remove (session->priv->outbox_flush_id);
-               session->priv->outbox_flush_id = 0;
+       if (!session->priv->outbox_flush_id) {
+               /* Do not reschedule the timer, it will be rescheduled
+                  when needed after the flush attempt */
+               session->priv->outbox_flush_id = e_named_timeout_add_seconds (60 * delay_minutes, 
mail_session_flush_outbox_timeout_cb, session);
        }
-
-       session->priv->outbox_flush_id = e_named_timeout_add_seconds (60 * delay_minutes, 
mail_session_flush_outbox_timeout_cb, session);
-
        g_mutex_unlock (&session->priv->preparing_flush_lock);
 }
 
diff --git a/src/libemail-engine/mail-ops.c b/src/libemail-engine/mail-ops.c
index a1716bf7c8..28101e5e85 100644
--- a/src/libemail-engine/mail-ops.c
+++ b/src/libemail-engine/mail-ops.c
@@ -908,6 +908,27 @@ exit:
 
 /* ** SEND MAIL QUEUE ***************************************************** */
 
+static void
+maybe_schedule_next_flush (EMailSession *session,
+                          time_t nearest_next_flush)
+{
+       gint delay_seconds, delay_minutes;
+
+       if (!session || nearest_next_flush <= 0)
+               return;
+
+       delay_seconds = nearest_next_flush - time (NULL);
+       if (delay_seconds <= 0)
+               delay_seconds = 1;
+
+       delay_minutes = delay_seconds / 60 + ((delay_seconds % 60) > 0 ? 1 : 0);
+
+       if (!delay_minutes)
+               delay_minutes = 1;
+
+       e_mail_session_schedule_outbox_flush (session, delay_minutes);
+}
+
 static void
 report_status (struct _send_queue_msg *m,
                enum camel_filter_status_t status,
@@ -934,8 +955,8 @@ send_queue_exec (struct _send_queue_msg *m,
 {
        CamelFolder *sent_folder;
        GPtrArray *uids, *send_uids = NULL;
-       gint i, j;
-       time_t delay_send = 0;
+       gint i, j, delay_flush = 0;
+       time_t delay_send = 0, nearest_next_flush = 0;
        GError *local_error = NULL;
 
        d (printf ("sending queue\n"));
@@ -945,7 +966,7 @@ send_queue_exec (struct _send_queue_msg *m,
 
                settings = e_util_ref_settings ("org.gnome.evolution.mail");
                if (g_settings_get_boolean (settings, "composer-use-outbox")) {
-                       gint delay_flush = g_settings_get_int (settings, "composer-delay-outbox-flush");
+                       delay_flush = g_settings_get_int (settings, "composer-delay-outbox-flush");
 
                        if (delay_flush > 0)
                                delay_send = time (NULL) - (60 * delay_flush);
@@ -966,15 +987,27 @@ send_queue_exec (struct _send_queue_msg *m,
 
                info = camel_folder_get_message_info (m->queue, uids->pdata[i]);
                if (info) {
-                       if ((camel_message_info_get_flags (info) & CAMEL_MESSAGE_DELETED) == 0 &&
-                           (!delay_send || camel_message_info_get_date_sent (info) <= delay_send))
-                               send_uids->pdata[j++] = uids->pdata[i];
+                       if (!(camel_message_info_get_flags (info) & CAMEL_MESSAGE_DELETED)) {
+                               gboolean is_editing = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info), 
MAIL_USER_KEY_EDITING)) != 0;
+
+                               if (!delay_send || (!is_editing && camel_message_info_get_date_sent (info) <= 
delay_send)) {
+                                       send_uids->pdata[j++] = uids->pdata[i];
+                               } else if (!is_editing && (!nearest_next_flush || nearest_next_flush > 
camel_message_info_get_date_sent (info))) {
+                                       nearest_next_flush = camel_message_info_get_date_sent (info);
+                               }
+                       }
+
                        g_clear_object (&info);
                }
        }
 
+       if (nearest_next_flush > 0)
+               nearest_next_flush += (delay_flush * 60);
+
        send_uids->len = j;
        if (send_uids->len == 0) {
+               maybe_schedule_next_flush (m->session, nearest_next_flush);
+
                /* nothing to send */
                camel_folder_free_uids (m->queue, uids);
                g_ptr_array_free (send_uids, TRUE);
@@ -1077,6 +1110,8 @@ send_queue_exec (struct _send_queue_msg *m,
                camel_folder_synchronize_sync (sent_folder, FALSE, NULL, NULL);
 
        camel_operation_pop_message (cancellable);
+
+       maybe_schedule_next_flush (m->session, nearest_next_flush);
 }
 
 static void
diff --git a/src/libemail-engine/mail-ops.h b/src/libemail-engine/mail-ops.h
index 7d7c744d5c..eafa8899e3 100644
--- a/src/libemail-engine/mail-ops.h
+++ b/src/libemail-engine/mail-ops.h
@@ -33,6 +33,9 @@ G_BEGIN_DECLS
 #include <libemail-engine/e-mail-session.h>
 #include <libemail-engine/mail-mt.h>
 
+/* Used to "tag" messages as being edited */
+#define MAIL_USER_KEY_EDITING  "mail-user-key-editing"
+
 void           mail_transfer_messages          (EMailSession *session,
                                                 CamelFolder *source,
                                                 GPtrArray *uids,
diff --git a/src/mail/em-composer-utils.c b/src/mail/em-composer-utils.c
index 7ffd82125b..19318299db 100644
--- a/src/mail/em-composer-utils.c
+++ b/src/mail/em-composer-utils.c
@@ -1173,6 +1173,26 @@ em_utils_composer_save_to_drafts_cb (EMsgComposer *composer,
        g_free (identity_uid);
 }
 
+static void
+emcu_manage_flush_outbox (EMailSession *session)
+{
+       GSettings *settings;
+
+       g_return_if_fail (E_IS_MAIL_SESSION (session));
+
+       settings = e_util_ref_settings ("org.gnome.evolution.mail");
+       if (g_settings_get_boolean (settings, "composer-use-outbox")) {
+               gint delay_flush = g_settings_get_int (settings, "composer-delay-outbox-flush");
+
+               if (delay_flush == 0) {
+                       e_mail_session_flush_outbox (session);
+               } else if (delay_flush > 0) {
+                       e_mail_session_schedule_outbox_flush (session, delay_flush);
+               }
+       }
+       g_object_unref (settings);
+}
+
 static void
 composer_save_to_outbox_completed (GObject *source_object,
                                    GAsyncResult *result,
@@ -1183,7 +1203,6 @@ composer_save_to_outbox_completed (GObject *source_object,
        EAlertSink *alert_sink;
        GCancellable *cancellable;
        AsyncContext *async_context;
-       GSettings *settings;
        GError *local_error = NULL;
 
        session = E_MAIL_SESSION (source_object);
@@ -1224,17 +1243,7 @@ composer_save_to_outbox_completed (GObject *source_object,
                G_OBJECT (activity), (GWeakNotify)
                gtk_widget_destroy, async_context->composer);
 
-       settings = e_util_ref_settings ("org.gnome.evolution.mail");
-       if (g_settings_get_boolean (settings, "composer-use-outbox")) {
-               gint delay_flush = g_settings_get_int (settings, "composer-delay-outbox-flush");
-
-               if (delay_flush == 0) {
-                       e_mail_session_flush_outbox (session);
-               } else if (delay_flush > 0) {
-                       e_mail_session_schedule_outbox_flush (session, delay_flush);
-               }
-       }
-       g_object_unref (settings);
+       emcu_manage_flush_outbox (session);
 
 exit:
        async_context_free (async_context);
@@ -2108,6 +2117,31 @@ emcu_message_references_existing_account (CamelMimeMessage *message,
        return res;
 }
 
+typedef struct _OutboxData {
+       CamelSession *session;
+       CamelMessageInfo *info;
+} OutboxData;
+
+static void
+outbox_data_free (gpointer ptr)
+{
+       OutboxData *od = ptr;
+
+       if (od) {
+               if (od->info) {
+                       g_object_set_data (G_OBJECT (od->info), MAIL_USER_KEY_EDITING, NULL);
+
+                       if (od->session && !(camel_message_info_get_flags (od->info) & 
CAMEL_MESSAGE_DELETED)) {
+                               emcu_manage_flush_outbox (E_MAIL_SESSION (od->session));
+                       }
+               }
+
+               g_clear_object (&od->session);
+               g_clear_object (&od->info);
+               g_free (od);
+       }
+}
+
 /**
  * em_utils_edit_message:
  * @composer: an #EMsgComposer
@@ -2237,9 +2271,25 @@ em_utils_edit_message (EMsgComposer *composer,
                g_free (folder_uri);
 
        } else if (message_uid != NULL && folder_is_outbox) {
+               CamelMessageInfo *info;
+
                e_msg_composer_set_header (
                        composer, "X-Evolution-Replace-Outbox-UID",
                        message_uid);
+
+               info = camel_folder_get_message_info (folder, message_uid);
+               if (info) {
+                       OutboxData *od;
+
+                       /* This makes the message not to send it while it's being edited */
+                       g_object_set_data (G_OBJECT (info), MAIL_USER_KEY_EDITING, GINT_TO_POINTER (1));
+
+                       od = g_new0 (OutboxData, 1);
+                       od->session = e_msg_composer_ref_session (composer);
+                       od->info = info; /* takes ownership of it */
+
+                       g_object_set_data_full (G_OBJECT (composer), MAIL_USER_KEY_EDITING, od, 
outbox_data_free);
+               }
        }
 
        composer_set_no_change (composer);


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