From b0aaacf05d0b46ca53f3b6b9f2dd0565cea0f5d0 Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Thu, 21 Apr 2011 15:03:52 +1000 Subject: Use dbus-error from delivery report for better errors --- libempathy-gtk/empathy-chat.c | 52 ++++++++++++++++++++++++++----------------- libempathy/empathy-tp-chat.c | 12 ++++++---- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c index 5c8bbce3b..d4e025f8d 100644 --- a/libempathy-gtk/empathy-chat.c +++ b/libempathy-gtk/empathy-chat.c @@ -1282,31 +1282,41 @@ static void chat_send_error_cb (EmpathyTpChat *tp_chat, const gchar *message_body, TpChannelTextSendError error_code, + const gchar *dbus_error, EmpathyChat *chat) { - const gchar *error; + const gchar *error = NULL; gchar *str; - switch (error_code) { - case TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE: - error = _("offline"); - break; - case TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT: - error = _("invalid contact"); - break; - case TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED: - error = _("permission denied"); - break; - case TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG: - error = _("too long message"); - break; - case TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED: - error = _("not implemented"); - break; - case TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN: - default: - error = _("unknown"); - break; + if (!tp_strdiff (dbus_error, TP_ERROR_STR_INSUFFICIENT_BALANCE)) { + error = _("insufficient balance to send message"); + } else if (!tp_strdiff (dbus_error, TP_ERROR_STR_NOT_CAPABLE)) { + error = _("not capable"); + } + + if (error == NULL) { + /* if we didn't find a dbus-error, try the old error */ + switch (error_code) { + case TP_CHANNEL_TEXT_SEND_ERROR_OFFLINE: + error = _("offline"); + break; + case TP_CHANNEL_TEXT_SEND_ERROR_INVALID_CONTACT: + error = _("invalid contact"); + break; + case TP_CHANNEL_TEXT_SEND_ERROR_PERMISSION_DENIED: + error = _("permission denied"); + break; + case TP_CHANNEL_TEXT_SEND_ERROR_TOO_LONG: + error = _("too long message"); + break; + case TP_CHANNEL_TEXT_SEND_ERROR_NOT_IMPLEMENTED: + error = _("not implemented"); + break; + case TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN: + default: + error = _("unknown"); + break; + } } if (message_body != NULL) { diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c index b8e4cdf0c..4b3bca4df 100644 --- a/libempathy/empathy-tp-chat.c +++ b/libempathy/empathy-tp-chat.c @@ -322,6 +322,7 @@ handle_delivery_report (EmpathyTpChat *self, gboolean valid; GPtrArray *echo; const gchar *message_body = NULL; + const gchar *delivery_dbus_error; header = tp_message_peek (message, 0); if (header == NULL) @@ -335,6 +336,8 @@ handle_delivery_report (EmpathyTpChat *self, if (!valid) delivery_error = TP_CHANNEL_TEXT_SEND_ERROR_UNKNOWN; + delivery_dbus_error = tp_asv_get_string (header, "delivery-dbus-error"); + /* TODO: ideally we should use tp-glib API giving us the echoed message as a * TpMessage. (fdo #35884) */ echo = tp_asv_get_boxed (header, "delivery-echo", @@ -347,7 +350,8 @@ handle_delivery_report (EmpathyTpChat *self, message_body = tp_asv_get_string (echo_body, "content"); } - g_signal_emit (self, signals[SEND_ERROR], 0, message_body, delivery_error); + g_signal_emit (self, signals[SEND_ERROR], 0, message_body, + delivery_error, delivery_dbus_error); out: tp_text_channel_ack_message_async (TP_TEXT_CHANNEL (priv->channel), @@ -449,7 +453,7 @@ message_send_cb (GObject *source, * we'll have rebased EmpathyTpChat on top of TpTextChannel we'll be able * to use the user_data pointer to pass the message and fix this. */ g_signal_emit (chat, signals[SEND_ERROR], 0, - NULL, error_to_text_send_error (error)); + NULL, error_to_text_send_error (error), NULL); g_error_free (error); } @@ -1521,9 +1525,9 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass) G_SIGNAL_RUN_LAST, 0, NULL, NULL, - _empathy_marshal_VOID__STRING_UINT, + _empathy_marshal_VOID__STRING_UINT_STRING, G_TYPE_NONE, - 2, G_TYPE_STRING, G_TYPE_UINT); + 3, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING); signals[CHAT_STATE_CHANGED] = g_signal_new ("chat-state-changed", -- cgit v1.2.3 From 1f46d6c5aa319ea7b81c29dcd08a0c7eb40d5789 Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Wed, 27 Apr 2011 14:10:50 +1000 Subject: [tp-chat] add a counter for the number of pending messages Requires delivery reports to include delivery-token. --- libempathy/empathy-tp-chat.c | 81 ++++++++++++++++++++++++++++++++++++++++++-- libempathy/empathy-tp-chat.h | 6 ++++ 2 files changed, 84 insertions(+), 3 deletions(-) diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c index 4b3bca4df..18087580b 100644 --- a/libempathy/empathy-tp-chat.c +++ b/libempathy/empathy-tp-chat.c @@ -61,6 +61,8 @@ typedef struct { gboolean can_upgrade_to_muc; gboolean got_sms_channel; gboolean sms_channel; + + GHashTable *messages_being_sent; } EmpathyTpChatPriv; static void tp_chat_iface_init (EmpathyContactListIface *iface); @@ -73,6 +75,7 @@ enum { PROP_PASSWORD_NEEDED, PROP_READY, PROP_SMS_CHANNEL, + PROP_N_MESSAGES_SENDING, }; enum { @@ -92,6 +95,39 @@ G_DEFINE_TYPE_WITH_CODE (EmpathyTpChat, empathy_tp_chat, G_TYPE_OBJECT, static void acknowledge_messages (EmpathyTpChat *chat, GArray *ids); +static void +tp_chat_set_delivery_status (EmpathyTpChat *self, + const gchar *token, + EmpathyDeliveryStatus delivery_status) +{ + EmpathyTpChatPriv *priv = GET_PRIV (self); + + /* channel must support receiving failures and successes */ + if (!tp_str_empty (token) && + tp_text_channel_get_delivery_reporting_support ( + TP_TEXT_CHANNEL (priv->channel)) & + (TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES | + TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_SUCCESSES)) { + + DEBUG ("Delivery status (%s) = %u", token, delivery_status); + + switch (delivery_status) { + case EMPATHY_DELIVERY_STATUS_NONE: + g_hash_table_remove (priv->messages_being_sent, + token); + break; + + default: + g_hash_table_insert (priv->messages_being_sent, + g_strdup (token), + GUINT_TO_POINTER (delivery_status)); + break; + } + + g_object_notify (G_OBJECT (self), "n-messages-sending"); + } +} + static void tp_chat_invalidated_cb (TpProxy *proxy, guint domain, @@ -323,14 +359,30 @@ handle_delivery_report (EmpathyTpChat *self, GPtrArray *echo; const gchar *message_body = NULL; const gchar *delivery_dbus_error; + const gchar *delivery_token = NULL; header = tp_message_peek (message, 0); if (header == NULL) goto out; + delivery_token = tp_asv_get_string (header, "delivery-token"); delivery_status = tp_asv_get_uint32 (header, "delivery-status", &valid); - if (!valid || delivery_status != TP_DELIVERY_STATUS_PERMANENTLY_FAILED) + + if (!valid) { + goto out; + } else if (delivery_status == TP_DELIVERY_STATUS_ACCEPTED) { + DEBUG ("Accepted %s", delivery_token); + tp_chat_set_delivery_status (self, delivery_token, + EMPATHY_DELIVERY_STATUS_ACCEPTED); + goto out; + } else if (delivery_status == TP_DELIVERY_STATUS_DELIVERED) { + DEBUG ("Delivered %s", delivery_token); + tp_chat_set_delivery_status (self, delivery_token, + EMPATHY_DELIVERY_STATUS_NONE); goto out; + } else if (delivery_status != TP_DELIVERY_STATUS_PERMANENTLY_FAILED) { + goto out; + } delivery_error = tp_asv_get_uint32 (header, "delivery-error", &valid); if (!valid) @@ -350,6 +402,8 @@ handle_delivery_report (EmpathyTpChat *self, message_body = tp_asv_get_string (echo_body, "content"); } + tp_chat_set_delivery_status (self, delivery_token, + EMPATHY_DELIVERY_STATUS_NONE); g_signal_emit (self, signals[SEND_ERROR], 0, message_body, delivery_error, delivery_dbus_error); @@ -443,9 +497,10 @@ message_send_cb (GObject *source, { EmpathyTpChat *chat = user_data; TpTextChannel *channel = (TpTextChannel *) source; + gchar *token = NULL; GError *error = NULL; - if (!tp_text_channel_send_message_finish (channel, result, NULL, &error)) { + if (!tp_text_channel_send_message_finish (channel, result, &token, &error)) { DEBUG ("Error: %s", error->message); /* FIXME: we should use the body of the message as first argument of the @@ -457,6 +512,10 @@ message_send_cb (GObject *source, g_error_free (error); } + + tp_chat_set_delivery_status (chat, token, + EMPATHY_DELIVERY_STATUS_SENDING); + g_free (token); } typedef struct { @@ -816,6 +875,7 @@ tp_chat_finalize (GObject *object) g_queue_free (priv->messages_queue); g_queue_free (priv->pending_messages_queue); + g_hash_table_destroy (priv->messages_being_sent); G_OBJECT_CLASS (empathy_tp_chat_parent_class)->finalize (object); } @@ -1419,6 +1479,10 @@ tp_chat_get_property (GObject *object, case PROP_SMS_CHANNEL: g_value_set_boolean (value, priv->sms_channel); break; + case PROP_N_MESSAGES_SENDING: + g_value_set_uint (value, + g_hash_table_size (priv->messages_being_sent)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -1508,6 +1572,14 @@ empathy_tp_chat_class_init (EmpathyTpChatClass *klass) FALSE, G_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_N_MESSAGES_SENDING, + g_param_spec_uint ("n-messages-sending", + "Num Messages Sending", + "The number of messages being sent", + 0, G_MAXUINT, 0, + G_PARAM_READABLE)); + /* Signals */ signals[MESSAGE_RECEIVED] = g_signal_new ("message-received", @@ -1571,6 +1643,8 @@ empathy_tp_chat_init (EmpathyTpChat *chat) chat->priv = priv; priv->messages_queue = g_queue_new (); priv->pending_messages_queue = g_queue_new (); + priv->messages_being_sent = g_hash_table_new_full ( + g_str_hash, g_str_equal, g_free, NULL); } static void @@ -1679,7 +1753,8 @@ empathy_tp_chat_send (EmpathyTpChat *chat, DEBUG ("Sending message: %s", message_body); tp_text_channel_send_message_async (TP_TEXT_CHANNEL (priv->channel), - message, 0, message_send_cb, chat); + message, TP_MESSAGE_SENDING_FLAG_REPORT_DELIVERY, + message_send_cb, chat); g_free (message_body); } diff --git a/libempathy/empathy-tp-chat.h b/libempathy/empathy-tp-chat.h index 7ac1296e0..83c7fe7d1 100644 --- a/libempathy/empathy-tp-chat.h +++ b/libempathy/empathy-tp-chat.h @@ -59,6 +59,12 @@ typedef struct { GValue *value; } EmpathyTpChatProperty; +typedef enum { + EMPATHY_DELIVERY_STATUS_NONE, + EMPATHY_DELIVERY_STATUS_SENDING, + EMPATHY_DELIVERY_STATUS_ACCEPTED +} EmpathyDeliveryStatus; + GType empathy_tp_chat_get_type (void) G_GNUC_CONST; EmpathyTpChat *empathy_tp_chat_new (TpAccount *account, TpChannel *channel); -- cgit v1.2.3 From 4f37d474725cd006eb627e10349e0361ce9a7b29 Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Thu, 28 Apr 2011 15:28:08 +1000 Subject: [chat] expose this property in EmpathyChat --- libempathy-gtk/empathy-chat.c | 44 +++++++++++++++++++++++++++++++++++++++++++ libempathy-gtk/empathy-chat.h | 2 ++ 2 files changed, 46 insertions(+) diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c index d4e025f8d..3e8a9c70b 100644 --- a/libempathy-gtk/empathy-chat.c +++ b/libempathy-gtk/empathy-chat.c @@ -172,6 +172,7 @@ enum { PROP_REMOTE_CONTACT, PROP_SHOW_CONTACTS, PROP_SMS_CHANNEL, + PROP_N_MESSAGES_SENDING, }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -214,6 +215,10 @@ chat_get_property (GObject *object, case PROP_SMS_CHANNEL: g_value_set_boolean (value, priv->sms_channel); break; + case PROP_N_MESSAGES_SENDING: + g_value_set_uint (value, + empathy_chat_get_n_messages_sending (chat)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -2992,6 +2997,14 @@ empathy_chat_class_init (EmpathyChatClass *klass) FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_N_MESSAGES_SENDING, + g_param_spec_uint ("n-messages-sending", + "Num Messages Sending", + "The number of messages being sent", + 0, G_MAXUINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + signals[COMPOSING] = g_signal_new ("composing", G_OBJECT_CLASS_TYPE (object_class), @@ -3497,6 +3510,12 @@ chat_sms_channel_changed_cb (EmpathyChat *self) g_object_notify (G_OBJECT (self), "sms-channel"); } +static void +chat_n_messages_sending_changed_cb (EmpathyChat *self) +{ + g_object_notify (G_OBJECT (self), "n-messages-sending"); +} + void empathy_chat_set_tp_chat (EmpathyChat *chat, EmpathyTpChat *tp_chat) @@ -3549,6 +3568,9 @@ empathy_chat_set_tp_chat (EmpathyChat *chat, g_signal_connect_swapped (tp_chat, "notify::sms-channel", G_CALLBACK (chat_sms_channel_changed_cb), chat); + g_signal_connect_swapped (tp_chat, "notify::n-messages-sending", + G_CALLBACK (chat_n_messages_sending_changed_cb), + chat); /* Get initial value of properties */ properties = empathy_tp_chat_get_properties (priv->tp_chat); @@ -3873,3 +3895,25 @@ empathy_chat_is_sms_channel (EmpathyChat *self) return priv->sms_channel; } + +guint +empathy_chat_get_n_messages_sending (EmpathyChat *self) +{ + EmpathyChatPriv *priv; + + g_return_val_if_fail (EMPATHY_IS_CHAT (self), 0); + + priv = GET_PRIV (self); + + if (priv->tp_chat == NULL) { + return 0; + } else { + guint n_messages; + + g_object_get (priv->tp_chat, + "n-messages-sending", &n_messages, + NULL); + + return n_messages; + } +} diff --git a/libempathy-gtk/empathy-chat.h b/libempathy-gtk/empathy-chat.h index 8da8004ec..a5c0148a1 100644 --- a/libempathy-gtk/empathy-chat.h +++ b/libempathy-gtk/empathy-chat.h @@ -96,6 +96,8 @@ void empathy_chat_messages_read (EmpathyChat *self); gboolean empathy_chat_is_composing (EmpathyChat *chat); gboolean empathy_chat_is_sms_channel (EmpathyChat *self); +guint empathy_chat_get_n_messages_sending (EmpathyChat *self); + G_END_DECLS #endif /* __EMPATHY_CHAT_H__ */ -- cgit v1.2.3 From 3e22736f0211a0bb668218243bc4764435f62a58 Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Thu, 28 Apr 2011 15:28:35 +1000 Subject: [chat-window] add a spinner to the window tab for when messages are being sent --- src/empathy-chat-window.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c index ac97601ce..1012e4e90 100644 --- a/src/empathy-chat-window.c +++ b/src/empathy-chat-window.c @@ -314,6 +314,15 @@ chat_window_create_label (EmpathyChatWindow *window, if (is_tab_label) { GtkWidget *close_button; + GtkWidget *sending_spinner; + + sending_spinner = gtk_spinner_new (); + + gtk_box_pack_start (GTK_BOX (hbox), sending_spinner, + FALSE, FALSE, 0); + g_object_set_data (G_OBJECT (chat), + "chat-window-tab-sending-spinner", + sending_spinner); close_button = gedit_close_button_new (); g_object_set_data (G_OBJECT (chat), "chat-window-tab-close-button", close_button); @@ -652,6 +661,8 @@ chat_window_update_chat_tab_full (EmpathyChat *chat, const gchar *icon_name; GtkWidget *tab_image; GtkWidget *menu_image; + GtkWidget *sending_spinner; + guint nb_sending; window = chat_window_find_chat (chat); if (!window) { @@ -700,6 +711,16 @@ chat_window_update_chat_tab_full (EmpathyChat *chat, gtk_widget_hide (menu_image); } + /* Update the sending spinner */ + nb_sending = empathy_chat_get_n_messages_sending (chat); + sending_spinner = g_object_get_data (G_OBJECT (chat), + "chat-window-tab-sending-spinner"); + + g_object_set (sending_spinner, + "active", nb_sending > 0, + "visible", nb_sending > 0, + NULL); + /* Update tab tooltip */ tooltip = g_string_new (NULL); @@ -719,6 +740,15 @@ chat_window_update_chat_tab_full (EmpathyChat *chat, id, tp_account_get_display_name (account)); + if (nb_sending > 0) { + append_markup_printf (tooltip, "\n"); + append_markup_printf (tooltip, + ngettext ("Sending %d message", + "Sending %d messages", + nb_sending), + nb_sending); + } + if (!EMP_STR_EMPTY (status)) { append_markup_printf (tooltip, "\n%s", status); } @@ -2251,6 +2281,9 @@ empathy_chat_window_add_chat (EmpathyChatWindow *window, g_signal_connect (chat, "notify::sms-channel", G_CALLBACK (chat_window_chat_notify_cb), NULL); + g_signal_connect (chat, "notify::n-messages-sending", + G_CALLBACK (chat_window_chat_notify_cb), + NULL); chat_window_chat_notify_cb (chat); gtk_notebook_append_page_menu (GTK_NOTEBOOK (priv->notebook), child, label, popup_label); -- cgit v1.2.3 From 24e6b10a9c1795964f0e6e80e074eff24344f64b Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Wed, 4 May 2011 09:58:18 +1000 Subject: Fix broken logic that caused delivery report spinner to spin forever --- libempathy/empathy-tp-chat.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libempathy/empathy-tp-chat.c b/libempathy/empathy-tp-chat.c index 18087580b..72c6bebf0 100644 --- a/libempathy/empathy-tp-chat.c +++ b/libempathy/empathy-tp-chat.c @@ -101,13 +101,14 @@ tp_chat_set_delivery_status (EmpathyTpChat *self, EmpathyDeliveryStatus delivery_status) { EmpathyTpChatPriv *priv = GET_PRIV (self); + TpDeliveryReportingSupportFlags flags = + tp_text_channel_get_delivery_reporting_support ( + TP_TEXT_CHANNEL (priv->channel)); /* channel must support receiving failures and successes */ if (!tp_str_empty (token) && - tp_text_channel_get_delivery_reporting_support ( - TP_TEXT_CHANNEL (priv->channel)) & - (TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES | - TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_SUCCESSES)) { + flags & TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES && + flags & TP_DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_SUCCESSES) { DEBUG ("Delivery status (%s) = %u", token, delivery_status); -- cgit v1.2.3 From 0d44943efc4f3f727861387ba89f57238aa92577 Mon Sep 17 00:00:00 2001 From: Danielle Madeley Date: Wed, 4 May 2011 10:05:16 +1000 Subject: Add a tooltip to the sending message spinner --- src/empathy-chat-window.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/empathy-chat-window.c b/src/empathy-chat-window.c index 1012e4e90..841005c93 100644 --- a/src/empathy-chat-window.c +++ b/src/empathy-chat-window.c @@ -741,12 +741,17 @@ chat_window_update_chat_tab_full (EmpathyChat *chat, tp_account_get_display_name (account)); if (nb_sending > 0) { - append_markup_printf (tooltip, "\n"); - append_markup_printf (tooltip, - ngettext ("Sending %d message", - "Sending %d messages", - nb_sending), - nb_sending); + char *tmp = g_strdup_printf ( + ngettext ("Sending %d message", + "Sending %d messages", + nb_sending), + nb_sending); + + g_string_append (tooltip, "\n"); + g_string_append (tooltip, tmp); + + gtk_widget_set_tooltip_text (sending_spinner, tmp); + g_free (tmp); } if (!EMP_STR_EMPTY (status)) { -- cgit v1.2.3