/soc/2015/jgeboski/facebook: 3e818c95dfd9: facebook: mark as rea...

James Geboski jgeboski at gmail.com
Thu Aug 13 06:22:19 EDT 2015


Changeset: 3e818c95dfd9b0e8ec7a63feeaccbe29055f5c13
Author:	 James Geboski <jgeboski at gmail.com>
Date:	 2015-08-13 06:22 -0400
Branch:	 facebook
URL: https://hg.pidgin.im/soc/2015/jgeboski/facebook/rev/3e818c95dfd9

Description:

facebook: mark as read only if the conversation is focused

diffstat:

 libpurple/protocols/facebook/data.c     |  80 ++++++++++++++++++++++++++------
 libpurple/protocols/facebook/data.h     |  13 ++++-
 libpurple/protocols/facebook/facebook.c |  68 ++++++++++++++++++++++++++-
 3 files changed, 139 insertions(+), 22 deletions(-)

diffs (truncated from 338 to 300 lines):

diff --git a/libpurple/protocols/facebook/data.c b/libpurple/protocols/facebook/data.c
--- a/libpurple/protocols/facebook/data.c
+++ b/libpurple/protocols/facebook/data.c
@@ -35,7 +35,8 @@ struct _FbDataPrivate
 	GQueue *msgs;
 	GHashTable *icons;
 	GHashTable *icona;
-	guint syncev;
+	GHashTable *unread;
+	GHashTable *evs;
 };
 
 static const gchar *fb_props_strs[] = {
@@ -54,9 +55,13 @@ static void
 fb_data_dispose(GObject *obj)
 {
 	FbDataPrivate *priv = FB_DATA(obj)->priv;
+	GHashTableIter iter;
+	gpointer ptr;
 
-	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 @@ fb_data_dispose(GObject *obj)
 	}
 
 	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);
 }
 
 static void
@@ -92,6 +100,10 @@ fb_data_init(FbData *fata)
 	priv->icona = g_hash_table_new_full(g_direct_hash, g_direct_equal,
 	                                    (GDestroyNotify) fb_data_icon_free,
 					    NULL);
+	priv->unread = g_hash_table_new_full(fb_id_hash, fb_id_equal, g_free,
+	                                     NULL);
+	priv->evs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+	                                  NULL);
 }
 
 FbData *
@@ -211,36 +223,41 @@ fb_data_save(FbData *fata)
 }
 
 void
-fb_data_add_sync_timeout(FbData *fata, guint minutes, GSourceFunc func,
-                         gpointer data)
+fb_data_add_timeout(FbData *fata, const gchar *name, guint interval,
+                    GSourceFunc func, gpointer data)
 {
 	FbDataPrivate *priv;
+	gchar *key;
+	guint id;
 
 	g_return_if_fail(FB_IS_DATA(fata));
 	priv = fata->priv;
 
-	if (priv->syncev > 0) {
-		purple_timeout_remove(priv->syncev);
-	}
+	fb_data_clear_timeout(fata, name, TRUE);
 
-	minutes *= 60;
-	priv->syncev = purple_timeout_add_seconds(minutes, func, data);
+	key = g_strdup(name);
+	id = purple_timeout_add_seconds(interval, func, data);
+	g_hash_table_replace(priv->evs, key, GUINT_TO_POINTER(id));
 }
 
 void
-fb_data_clear_sync_timeout(FbData *fata, gboolean remove)
+fb_data_clear_timeout(FbData *fata, const gchar *name, gboolean remove)
 {
 	FbDataPrivate *priv;
+	gpointer ptr;
+	guint id;
 
 	g_return_if_fail(FB_IS_DATA(fata));
 	priv = fata->priv;
-	g_return_if_fail(priv->syncev > 0);
 
-	if (remove) {
-		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);
 	}
 
-	priv->syncev = 0;
+	g_hash_table_remove(priv->evs, name);
 }
 
 FbApi *
@@ -276,6 +293,20 @@ fb_data_get_roomlist(FbData *fata)
 	return priv->roomlist;
 }
 
+gboolean
+fb_data_get_unread(FbData *fata, FbId id)
+{
+	FbDataPrivate *priv;
+	gpointer *ptr;
+
+	g_return_val_if_fail(FB_IS_DATA(fata), FALSE);
+	g_return_val_if_fail(id != 0, FALSE);
+	priv = fata->priv;
+
+	ptr = g_hash_table_lookup(priv->unread, &id);
+	return GPOINTER_TO_INT(ptr);
+}
+
 void
 fb_data_set_roomlist(FbData *fata, PurpleRoomlist *list)
 {
@@ -288,6 +319,25 @@ fb_data_set_roomlist(FbData *fata, Purpl
 }
 
 void
+fb_data_set_unread(FbData *fata, FbId id, gboolean unread)
+{
+	FbDataPrivate *priv;
+	gpointer key;
+
+	g_return_if_fail(FB_IS_DATA(fata));
+	g_return_if_fail(id != 0);
+	priv = fata->priv;
+
+	if (!unread) {
+		g_hash_table_remove(priv->unread, &id);
+		return;
+	}
+
+	key = g_memdup(&id, sizeof id);
+	g_hash_table_replace(priv->unread, key, GINT_TO_POINTER(unread));
+}
+
+void
 fb_data_add_message(FbData *fata, FbApiMessage *msg)
 {
 	FbDataPrivate *priv;
diff --git a/libpurple/protocols/facebook/data.h b/libpurple/protocols/facebook/data.h
--- a/libpurple/protocols/facebook/data.h
+++ b/libpurple/protocols/facebook/data.h
@@ -30,6 +30,7 @@
 
 #include "api.h"
 #include "http.h"
+#include "id.h"
 
 #define FB_DATA_ICON_MAX 4
 
@@ -79,11 +80,11 @@ void
 fb_data_save(FbData *fata);
 
 void
-fb_data_add_sync_timeout(FbData *fata, guint minutes, GSourceFunc func,
-                         gpointer data);
+fb_data_add_timeout(FbData *fata, const gchar *name, guint interval,
+                    GSourceFunc func, gpointer data);
 
 void
-fb_data_clear_sync_timeout(FbData *fata, gboolean remove);
+fb_data_clear_timeout(FbData *fata, const gchar *name, gboolean remove);
 
 FbApi *
 fb_data_get_api(FbData *fata);
@@ -94,10 +95,16 @@ fb_data_get_connection(FbData *fata);
 PurpleRoomlist *
 fb_data_get_roomlist(FbData *fata);
 
+gboolean
+fb_data_get_unread(FbData *fata, FbId id);
+
 void
 fb_data_set_roomlist(FbData *fata, PurpleRoomlist *list);
 
 void
+fb_data_set_unread(FbData *fata, FbId id, gboolean unread);
+
+void
 fb_data_add_message(FbData *fata, FbApiMessage *msg);
 
 GSList *
diff --git a/libpurple/protocols/facebook/facebook.c b/libpurple/protocols/facebook/facebook.c
--- a/libpurple/protocols/facebook/facebook.c
+++ b/libpurple/protocols/facebook/facebook.c
@@ -42,6 +42,7 @@
 #include "request.h"
 #include "roomlist.h"
 #include "server.h"
+#include "signals.h"
 #include "sslconn.h"
 #include "status.h"
 #include "util.h"
@@ -208,7 +209,7 @@ fb_cb_sync_contacts(gpointer data)
 	FbData *fata = data;
 
 	api = fb_data_get_api(fata);
-	fb_data_clear_sync_timeout(fata, FALSE);
+	fb_data_clear_timeout(fata, "sync-contacts", FALSE);
 	fb_api_contacts(api);
 	return FALSE;
 }
@@ -320,7 +321,9 @@ fb_cb_api_contacts(FbApi *api, GSList *u
 		sync = 5;
 	}
 
-	fb_data_add_sync_timeout(fata, sync, fb_cb_sync_contacts, fata);
+	sync *= 60 * 1000;
+	fb_data_add_timeout(fata, "sync-contacts", sync, fb_cb_sync_contacts,
+	                    fata);
 }
 
 static void
@@ -447,7 +450,7 @@ fb_cb_api_messages(FbApi *api, GSList *m
 
 		if (msg->tid == 0) {
 			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 @@ fb_cb_api_messages(FbApi *api, GSList *m
 		}
 
 		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_api_typing(FbApi *api, FbApiTyping
 	}
 }
 
+static gboolean
+fb_cb_conv_read(gpointer data)
+{
+	const gchar *name;
+	FbApi *api;
+	FbData *fata;
+	FbId id;
+	PurpleConnection *gc;
+	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))
+	{
+		return FALSE;
+	}
+
+	api = fb_data_get_api(fata);
+	fb_data_set_unread(fata, id, FALSE);
+	fb_api_read(api, id, PURPLE_IS_CHAT_CONVERSATION(conv));
+	return FALSE;
+}
+
+static void
+fb_cb_conv_updated(PurpleConversation *conv, PurpleConversationUpdateType type,
+                   gpointer data)
+{
+	FbData *fata = data;
+	PurpleAccount *acct;
+
+	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,
+		                    conv);
+	}
+}
+
 static void
 fb_blist_chat_create(GSList *buddies, gpointer data)
 {
@@ -703,6 +753,7 @@ fb_login(PurpleAccount *acct)



More information about the Commits mailing list