pidgin/pidgin

3e818c95dfd9
Parents acae53caaff0
Children a9b5c6e0462d
facebook: mark as read only if the conversation is focused
--- 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 @@
GQueue *msgs;
GHashTable *icons;
GHashTable *icona;
- guint syncev;
+ GHashTable *unread;
+ GHashTable *evs;
};
static const gchar *fb_props_strs[] = {
@@ -54,9 +55,13 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
}
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;
--- 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 @@
#include "api.h"
#include "http.h"
+#include "id.h"
#define FB_DATA_ICON_MAX 4
@@ -79,11 +80,11 @@
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 @@
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 *
--- 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 @@
#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 @@
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 @@
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 @@
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 @@
}
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 @@
}
}
+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 @@
const gchar *user;
FbApi *api;
FbData *fata;
+ gpointer convh;
PurpleConnection *gc;
gc = purple_account_get_connection(acct);
@@ -717,6 +768,7 @@
fata = fb_data_new(gc);
api = fb_data_get_api(fata);
+ convh = purple_conversations_get_handle();
purple_connection_set_protocol_data(gc, fata);
g_signal_connect(api,
@@ -768,6 +820,12 @@
G_CALLBACK(fb_cb_api_typing),
fata);
+ purple_signal_connect(convh,
+ "conversation-updated",
+ gc,
+ G_CALLBACK(fb_cb_conv_updated),
+ fata);
+
if (!fb_data_load(fata)) {
user = purple_account_get_username(acct);
pass = purple_connection_get_password(gc);
@@ -793,7 +851,9 @@
fb_data_save(fata);
fb_api_disconnect(api);
g_object_unref(fata);
+
purple_connection_set_protocol_data(gc, NULL);
+ purple_signals_disconnect_by_handle(gc);
}
static GList *