]> git.0d.be Git - empathy.git/commitdiff
Queue received messages until the sender got his alias.
authorXavier Claessens <xclaesse@src.gnome.org>
Sat, 8 Mar 2008 20:36:41 +0000 (20:36 +0000)
committerXavier Claessens <xclaesse@src.gnome.org>
Sat, 8 Mar 2008 20:36:41 +0000 (20:36 +0000)
svn path=/trunk/; revision=713

libempathy-gtk/empathy-chat.c
libempathy-gtk/empathy-status-icon.c
libempathy/empathy-message.h
libempathy/empathy-tp-chat.c
libempathy/empathy-tp-contact-factory.c

index f6e7a2c2a58ecdf1f1003bc51a53f3077a9cf64d..8af3d573c9f80a9e88911a77e80d67f545bb3649 100644 (file)
@@ -1504,7 +1504,6 @@ empathy_chat_set_tp_chat (EmpathyChat   *chat,
                          EmpathyTpChat *tp_chat)
 {
        EmpathyChatPriv *priv;
-       GList           *messages;
 
        g_return_if_fail (EMPATHY_IS_CHAT (chat));
        g_return_if_fail (EMPATHY_IS_TP_CHAT (tp_chat));
@@ -1544,6 +1543,7 @@ empathy_chat_set_tp_chat (EmpathyChat   *chat,
        priv->tp_chat = g_object_ref (tp_chat);
        priv->id = g_strdup (empathy_tp_chat_get_id (tp_chat));
        priv->account = g_object_ref (empathy_tp_chat_get_account (tp_chat));
+       empathy_tp_chat_set_acknowledge (tp_chat, TRUE);
 
        if (priv->first_tp_chat) {
                chat_add_logs (chat);
@@ -1563,12 +1563,6 @@ empathy_chat_set_tp_chat (EmpathyChat   *chat,
                          G_CALLBACK (chat_destroy_cb),
                          chat);
 
-       /* Get pending messages, wait until block_events cb before displaying
-        * them to have to chance to get alias/avatar of sender. */
-       empathy_tp_chat_set_acknowledge (tp_chat, TRUE);
-       messages = empathy_tp_chat_get_pendings (tp_chat);
-       priv->pending_messages = g_list_concat (priv->pending_messages, messages);
-
        if (!priv->sensitive) {
                gtk_widget_set_sensitive (chat->input_text_view, TRUE);
                empathy_chat_view_append_event (chat->view, _("Connected"));
index 78c8b47e0d11914358cfcfa91a5447654be4d12f..9f10bd37eb7665996c6e8d1f1ab7390e5157bad7 100644 (file)
@@ -322,7 +322,6 @@ status_icon_text_filter_new_channel (EmpathyFilter     *filter,
        EmpathyStatusIconPriv *priv;
        McAccount             *account;
        EmpathyTpChat         *tp_chat;
-       GList                 *messages;
 
        priv = GET_PRIV (icon);
 
@@ -335,19 +334,9 @@ status_icon_text_filter_new_channel (EmpathyFilter     *filter,
        g_object_set_data (G_OBJECT (tp_chat), "filter", filter);
        g_object_unref (account);
 
-       messages = empathy_tp_chat_get_pendings (tp_chat);
-       if (!messages) {
-               empathy_debug (DEBUG_DOMAIN, "No pending msg, waiting...");
-               g_signal_connect (tp_chat, "message-received",
-                                 G_CALLBACK (status_icon_message_received_cb),
-                                 icon);
-               return;
-       }
-
-       status_icon_message_received_cb (tp_chat, messages->data, icon);
-
-       g_list_foreach (messages, (GFunc) g_object_unref, NULL);
-       g_list_free (messages);
+       g_signal_connect (tp_chat, "message-received",
+                         G_CALLBACK (status_icon_message_received_cb),
+                         icon);
 }
 
 static void
@@ -783,6 +772,7 @@ status_icon_event_msg_cb (StatusIconEvent *event)
        empathy_filter_process (filter,
                                empathy_tp_chat_get_channel (tp_chat),
                                TRUE);
+
        g_object_unref (tp_chat);
 }
 
index 668b33311f942745eb0a72f88e2494c4dceb99ca..d1c995fe44b5b6197bb04fbfb864a4217be41886 100644 (file)
@@ -76,7 +76,7 @@ time_t             empathy_message_get_timestamp (EmpathyMessage     *message);
 void               empathy_message_set_timestamp (EmpathyMessage     *message,
                                                  time_t              timestamp);
 GDate *            empathy_message_get_date_and_time (EmpathyMessage *message,
-                                 time_t             *timestamp);
+                                                     time_t         *timestamp);
 EmpathyMessageType empathy_message_type_from_str (const gchar        *type_str);
 const gchar *      empathy_message_type_to_str   (EmpathyMessageType  type);
 
index 8e39442983bb584c7296a3af8c7da48216a07bed..b96ba48a31d7c4369b63d9e23f6251f9943d83b0 100644 (file)
@@ -28,6 +28,7 @@
 #include <libtelepathy/tp-conn.h>
 #include <libtelepathy/tp-helpers.h>
 #include <libtelepathy/tp-props-iface.h>
+#include <telepathy-glib/util.h>
 
 #include "empathy-tp-chat.h"
 #include "empathy-contact-factory.h"
@@ -48,7 +49,8 @@ struct _EmpathyTpChatPriv {
        gchar                 *id;
        MissionControl        *mc;
        gboolean               acknowledge;
-
+       gboolean               had_pending_messages;
+       GSList                *message_queue;
        TpChan                *tp_chan;
        DBusGProxy            *props_iface;
        DBusGProxy            *text_iface;
@@ -158,6 +160,84 @@ tp_chat_build_message (EmpathyTpChat *chat,
        return message;
 }
 
+static void
+tp_chat_sender_ready_notify_cb (EmpathyContact *contact,
+                               GParamSpec     *param_spec,
+                               EmpathyTpChat  *chat)
+{
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
+       EmpathyMessage    *message;
+       EmpathyContact    *sender;
+       gboolean           removed = FALSE;
+       const gchar       *name, *id;
+
+       /* Emit all messages queued until we find a message with not
+        * ready sender. When leaving this loop, sender is the first not ready
+        * contact queued and removed tells if at least one message got removed
+        * from the queue. */
+       while (priv->message_queue) {
+               message = priv->message_queue->data;
+               sender = empathy_message_get_sender (message);
+               name = empathy_contact_get_name (sender);
+               id = empathy_contact_get_id (sender);
+
+               if (!tp_strdiff (name, id)) {
+                       break;
+               }
+
+               empathy_debug (DEBUG_DOMAIN, "Queued message ready");
+               g_signal_emit (chat, signals[MESSAGE_RECEIVED], 0, message);
+               priv->message_queue = g_slist_remove (priv->message_queue,
+                                                     message);
+               g_object_unref (message);
+               removed = TRUE;
+       }
+
+       if (removed) {
+               g_signal_handlers_disconnect_by_func (contact,
+                                                     tp_chat_sender_ready_notify_cb,
+                                                     chat);
+
+               if (priv->message_queue) {
+                       g_signal_connect (sender, "notify::name",
+                                         G_CALLBACK (tp_chat_sender_ready_notify_cb),
+                                         chat);
+               }
+       }
+}
+
+static void
+tp_chat_emit_or_queue_message (EmpathyTpChat  *chat,
+                              EmpathyMessage *message)
+{
+       EmpathyTpChatPriv   *priv = GET_PRIV (chat);
+       EmpathyContact      *sender;
+       const gchar         *name, *id;
+
+       if (priv->message_queue != NULL) {
+               empathy_debug (DEBUG_DOMAIN, "Message queue not empty");
+               priv->message_queue = g_slist_append (priv->message_queue,
+                                                     g_object_ref (message));
+               return;
+       }
+
+       sender = empathy_message_get_sender (message);
+       name = empathy_contact_get_name (sender);
+       id = empathy_contact_get_id (sender);
+       if (tp_strdiff (name, id)) {
+               empathy_debug (DEBUG_DOMAIN, "Message queue empty and sender ready");
+               g_signal_emit (chat, signals[MESSAGE_RECEIVED], 0, message);
+               return;
+       }
+
+       empathy_debug (DEBUG_DOMAIN, "Sender not ready");
+       priv->message_queue = g_slist_append (priv->message_queue, 
+                                             g_object_ref (message));
+       g_signal_connect (sender, "notify::name",
+                         G_CALLBACK (tp_chat_sender_ready_notify_cb),
+                         chat);
+}
+
 static void
 tp_chat_received_cb (DBusGProxy    *text_iface,
                     guint          message_id,
@@ -173,7 +253,11 @@ tp_chat_received_cb (DBusGProxy    *text_iface,
 
        priv = GET_PRIV (chat);
 
-       empathy_debug (DEBUG_DOMAIN, "Message received: %s", message_body);
+       if (!priv->had_pending_messages) {
+               return;
+       }
+       empathy_debug (DEBUG_DOMAIN, "Message received: %s", message_body);
 
        message = tp_chat_build_message (chat,
                                         message_type,
@@ -181,7 +265,7 @@ tp_chat_received_cb (DBusGProxy    *text_iface,
                                         from_handle,
                                         message_body);
 
-       g_signal_emit (chat, signals[MESSAGE_RECEIVED], 0, message);
+       tp_chat_emit_or_queue_message (EMPATHY_TP_CHAT (chat), message);
        g_object_unref (message);
 
        if (priv->acknowledge) {
@@ -212,7 +296,7 @@ tp_chat_sent_cb (DBusGProxy    *text_iface,
                                         0,
                                         message_body);
 
-       g_signal_emit (chat, signals[MESSAGE_RECEIVED], 0, message);
+       tp_chat_emit_or_queue_message (EMPATHY_TP_CHAT (chat), message);
        g_object_unref (message);
 }
 
@@ -263,6 +347,53 @@ tp_chat_state_changed_cb (DBusGProxy         *chat_state_iface,
        g_object_unref (contact);
 }
 
+static void
+tp_chat_list_pending_messages_cb (DBusGProxy *proxy,
+                                 GPtrArray *messages_list,
+                                 GError *error,
+                                 gpointer chat)
+{
+       EmpathyTpChatPriv *priv = GET_PRIV (chat);
+       guint              i;
+
+       priv->had_pending_messages = TRUE;
+
+       for (i = 0; i < messages_list->len; i++) {
+               EmpathyMessage *message;
+               GValueArray    *message_struct;
+               const gchar    *message_body;
+               guint           message_id;
+               guint           timestamp;
+               guint           from_handle;
+               guint           message_type;
+               guint           message_flags;
+
+               message_struct = g_ptr_array_index (messages_list, i);
+
+               message_id = g_value_get_uint (g_value_array_get_nth (message_struct, 0));
+               timestamp = g_value_get_uint (g_value_array_get_nth (message_struct, 1));
+               from_handle = g_value_get_uint (g_value_array_get_nth (message_struct, 2));
+               message_type = g_value_get_uint (g_value_array_get_nth (message_struct, 3));
+               message_flags = g_value_get_uint (g_value_array_get_nth (message_struct, 4));
+               message_body = g_value_get_string (g_value_array_get_nth (message_struct, 5));
+
+               empathy_debug (DEBUG_DOMAIN, "Message pending: %s", message_body);
+
+               message = tp_chat_build_message (chat,
+                                                message_type,
+                                                timestamp,
+                                                from_handle,
+                                                message_body);
+
+               tp_chat_emit_or_queue_message (chat, message);
+               g_object_unref (message);
+
+               g_value_array_free (message_struct);
+       }
+
+       g_ptr_array_free (messages_list, TRUE);
+}
+
 static void
 tp_chat_properties_ready_cb (TpPropsIface  *props_iface,
                             EmpathyTpChat *chat)
@@ -382,18 +513,10 @@ tp_chat_finalize (GObject *object)
                g_object_unref (priv->tp_chan);
        }
 
-       if (priv->factory) {
-               g_object_unref (priv->factory);
-       }
-       if (priv->user) {
-               g_object_unref (priv->user);
-       }
-       if (priv->account) {
-               g_object_unref (priv->account);
-       }
-       if (priv->mc) {
-               g_object_unref (priv->mc);
-       }
+       g_object_unref (priv->factory);
+       g_object_unref (priv->user);
+       g_object_unref (priv->account);
+       g_object_unref (priv->mc);
        g_free (priv->id);
 
        G_OBJECT_CLASS (empathy_tp_chat_parent_class)->finalize (object);
@@ -469,6 +592,10 @@ tp_chat_constructor (GType                  type,
                                  chat);
        }
 
+       /* FIXME: We do that in a cb to let time to set the acknowledge
+        * property, this property should be required for construct. */
+       g_idle_add ((GSourceFunc) empathy_tp_chat_get_pendings, chat);
+
        return chat;
 }
 
@@ -851,64 +978,17 @@ GList *
 empathy_tp_chat_get_pendings (EmpathyTpChat *chat)
 {
        EmpathyTpChatPriv *priv;
-       GPtrArray         *messages_list;
-       guint              i;
-       GList             *messages = NULL;
-       GError            *error = NULL;
 
        g_return_val_if_fail (EMPATHY_IS_TP_CHAT (chat), NULL);
 
        priv = GET_PRIV (chat);
 
-       /* If we do this call async, don't forget to ignore Received signal
-        * until we get the answer */
-       if (!tp_chan_type_text_list_pending_messages (priv->text_iface,
-                                                     priv->acknowledge,
-                                                     &messages_list,
-                                                     &error)) {
-               empathy_debug (DEBUG_DOMAIN, 
-                             "Error retrieving pending messages: %s",
-                             error ? error->message : "No error given");
-               g_clear_error (&error);
-               return NULL;
-       }
-
-       for (i = 0; i < messages_list->len; i++) {
-               EmpathyMessage *message;
-               GValueArray    *message_struct;
-               const gchar    *message_body;
-               guint           message_id;
-               guint           timestamp;
-               guint           from_handle;
-               guint           message_type;
-               guint           message_flags;
-
-               message_struct = g_ptr_array_index (messages_list, i);
-
-               message_id = g_value_get_uint (g_value_array_get_nth (message_struct, 0));
-               timestamp = g_value_get_uint (g_value_array_get_nth (message_struct, 1));
-               from_handle = g_value_get_uint (g_value_array_get_nth (message_struct, 2));
-               message_type = g_value_get_uint (g_value_array_get_nth (message_struct, 3));
-               message_flags = g_value_get_uint (g_value_array_get_nth (message_struct, 4));
-               message_body = g_value_get_string (g_value_array_get_nth (message_struct, 5));
-
-               empathy_debug (DEBUG_DOMAIN, "Message pending: %s", message_body);
-
-               message = tp_chat_build_message (chat,
-                                                message_type,
-                                                timestamp,
-                                                from_handle,
-                                                message_body);
-
-               messages = g_list_prepend (messages, message);
-
-               g_value_array_free (message_struct);
-       }
-       messages = g_list_reverse (messages);
-
-       g_ptr_array_free (messages_list, TRUE);
+       tp_chan_type_text_list_pending_messages_async (priv->text_iface,
+                                                      priv->acknowledge,
+                                                      tp_chat_list_pending_messages_cb,
+                                                      chat);
 
-       return messages;
+       return NULL;
 }
 
 void
index 4621ba3940779176a9756edc48d4d95b5a9e56a0..4e50f6fa876f910553f44cabf354734b66c5fdaf 100644 (file)
@@ -271,10 +271,6 @@ tp_contact_factory_aliases_changed_cb (DBusGProxy *proxy,
                        continue;
                }
 
-               if (G_STR_EMPTY (alias)) {
-                       alias = NULL;
-               }
-
                empathy_debug (DEBUG_DOMAIN, "Renaming contact %s (%d) to %s (changed cb)",
                               empathy_contact_get_id (contact),
                               handle, alias);