--- a/libpurple/protocols/facebook/data.c Wed Aug 12 18:55:37 2015 -0400
+++ b/libpurple/protocols/facebook/data.c Thu Aug 13 06:22:01 2015 -0400
@@ -35,7 +35,8 @@
static const gchar *fb_props_strs[] = {
@@ -54,9 +55,13 @@
fb_data_dispose(GObject *obj)
FbDataPrivate *priv = FB_DATA(obj)->priv;
- if (priv->syncev > 0) {
- purple_timeout_remove(priv->syncev);
+ g_hash_table_iter_init(&iter, priv->evs); + while (g_hash_table_iter_next(&iter, NULL, &ptr)) { + purple_timeout_remove(GPOINTER_TO_UINT(ptr)); if (G_LIKELY(priv->api != NULL)) {
@@ -64,8 +69,11 @@
g_queue_free_full(priv->msgs, (GDestroyNotify) fb_api_message_free);
g_hash_table_destroy(priv->icons);
g_hash_table_destroy(priv->icona);
+ g_hash_table_destroy(priv->unread); + g_hash_table_destroy(priv->evs); @@ -92,6 +100,10 @@
priv->icona = g_hash_table_new_full(g_direct_hash, g_direct_equal,
(GDestroyNotify) fb_data_icon_free,
+ priv->unread = g_hash_table_new_full(fb_id_hash, fb_id_equal, g_free, + priv->evs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, @@ -211,36 +223,41 @@
-fb_data_add_sync_timeout(FbData *fata, guint minutes, GSourceFunc func,
+fb_data_add_timeout(FbData *fata, const gchar *name, guint interval, + GSourceFunc func, gpointer data) g_return_if_fail(FB_IS_DATA(fata));
- if (priv->syncev > 0) {
- purple_timeout_remove(priv->syncev);
+ fb_data_clear_timeout(fata, name, TRUE);
- priv->syncev = purple_timeout_add_seconds(minutes, func, data);
+ id = purple_timeout_add_seconds(interval, func, data); + g_hash_table_replace(priv->evs, key, GUINT_TO_POINTER(id)); -fb_data_clear_sync_timeout(FbData *fata, gboolean remove)
+fb_data_clear_timeout(FbData *fata, const gchar *name, gboolean remove) g_return_if_fail(FB_IS_DATA(fata));
- g_return_if_fail(priv->syncev > 0);
- purple_timeout_remove(priv->syncev);
+ ptr = g_hash_table_lookup(priv->evs, name); + id = GPOINTER_TO_UINT(ptr); + if ((id > 0) && remove) { + purple_timeout_remove(id);
+ g_hash_table_remove(priv->evs, name); @@ -276,6 +293,20 @@
+fb_data_get_unread(FbData *fata, FbId id) + g_return_val_if_fail(FB_IS_DATA(fata), FALSE); + g_return_val_if_fail(id != 0, FALSE); + ptr = g_hash_table_lookup(priv->unread, &id); + return GPOINTER_TO_INT(ptr); fb_data_set_roomlist(FbData *fata, PurpleRoomlist *list)
@@ -288,6 +319,25 @@
+fb_data_set_unread(FbData *fata, FbId id, gboolean unread) + g_return_if_fail(FB_IS_DATA(fata)); + g_return_if_fail(id != 0); + g_hash_table_remove(priv->unread, &id); + key = g_memdup(&id, sizeof id); + g_hash_table_replace(priv->unread, key, GINT_TO_POINTER(unread)); fb_data_add_message(FbData *fata, FbApiMessage *msg)
--- a/libpurple/protocols/facebook/data.h Wed Aug 12 18:55:37 2015 -0400
+++ b/libpurple/protocols/facebook/data.h Thu Aug 13 06:22:01 2015 -0400
@@ -30,6 +30,7 @@
#define FB_DATA_ICON_MAX 4
@@ -79,11 +80,11 @@
fb_data_save(FbData *fata);
-fb_data_add_sync_timeout(FbData *fata, guint minutes, GSourceFunc func,
+fb_data_add_timeout(FbData *fata, const gchar *name, guint interval, + GSourceFunc func, gpointer data); -fb_data_clear_sync_timeout(FbData *fata, gboolean remove);
+fb_data_clear_timeout(FbData *fata, const gchar *name, gboolean remove); fb_data_get_api(FbData *fata);
@@ -94,10 +95,16 @@
fb_data_get_roomlist(FbData *fata);
+fb_data_get_unread(FbData *fata, FbId id); fb_data_set_roomlist(FbData *fata, PurpleRoomlist *list);
+fb_data_set_unread(FbData *fata, FbId id, gboolean unread); fb_data_add_message(FbData *fata, FbApiMessage *msg);
--- a/libpurple/protocols/facebook/facebook.c Wed Aug 12 18:55:37 2015 -0400
+++ b/libpurple/protocols/facebook/facebook.c Thu Aug 13 06:22:01 2015 -0400
@@ -42,6 +42,7 @@
@@ -208,7 +209,7 @@
api = fb_data_get_api(fata);
- fb_data_clear_sync_timeout(fata, FALSE);
+ fb_data_clear_timeout(fata, "sync-contacts", FALSE); @@ -320,7 +321,9 @@
- fb_data_add_sync_timeout(fata, sync, fb_cb_sync_contacts, fata);
+ fb_data_add_timeout(fata, "sync-contacts", sync, fb_cb_sync_contacts, @@ -447,7 +450,7 @@
if (mark && !msg->isself) {
- fb_api_read(api, msg->uid, FALSE);
+ fb_data_set_unread(fata, msg->uid, TRUE); fb_util_serv_got_im(gc, uid, html, flags, time(NULL));
@@ -472,7 +475,7 @@
if (mark && !msg->isself) {
- fb_api_read(api, msg->tid, TRUE);
+ fb_data_set_unread(fata, msg->tid, TRUE); fb_util_serv_got_chat_in(gc, id, uid, html, flags, time(NULL));
@@ -634,6 +637,53 @@
+fb_cb_conv_read(gpointer data) + PurpleConversation *conv = data; + gc = purple_conversation_get_connection(conv); + fata = purple_connection_get_protocol_data(gc); + name = purple_conversation_get_name(conv); + id = FB_ID_FROM_STR(name); + fb_data_clear_timeout(fata, "conv-read", FALSE); + if (!purple_conversation_has_focus(conv) || + !fb_data_get_unread(fata, id)) + api = fb_data_get_api(fata); + fb_data_set_unread(fata, id, FALSE); + fb_api_read(api, id, PURPLE_IS_CHAT_CONVERSATION(conv)); +fb_cb_conv_updated(PurpleConversation *conv, PurpleConversationUpdateType type, + acct = purple_conversation_get_account(conv); + if ((type == PURPLE_CONVERSATION_UPDATE_UNSEEN) && + purple_account_get_bool(acct, "mark-read", TRUE)) + /* Use event loop for purple_conversation_has_focus() */ + fb_data_add_timeout(fata, "conv-read", 1, fb_cb_conv_read, fb_blist_chat_create(GSList *buddies, gpointer data)
@@ -703,6 +753,7 @@
gc = purple_account_get_connection(acct);
@@ -717,6 +768,7 @@
api = fb_data_get_api(fata);
+ convh = purple_conversations_get_handle(); purple_connection_set_protocol_data(gc, fata);
@@ -768,6 +820,12 @@
G_CALLBACK(fb_cb_api_typing),
+ purple_signal_connect(convh, + "conversation-updated", + G_CALLBACK(fb_cb_conv_updated), if (!fb_data_load(fata)) {
user = purple_account_get_username(acct);
pass = purple_connection_get_password(gc);
@@ -793,7 +851,9 @@
purple_connection_set_protocol_data(gc, NULL);
+ purple_signals_disconnect_by_handle(gc);