* Travis Reitter <travis.reitter@collabora.co.uk>
*/
-#include <config.h>
-
-#include <string.h>
-
-#include <telepathy-glib/telepathy-glib.h>
-#include <telepathy-glib/account-manager.h>
-#include <telepathy-glib/enums.h>
-#include <telepathy-glib/proxy-subclass.h>
-#include <telepathy-glib/util.h>
-
-#include <folks/folks.h>
-#include <folks/folks-telepathy.h>
+#include "config.h"
+#include "empathy-individual-manager.h"
-#include <extensions/extensions.h>
+#include <tp-account-widgets/tpaw-utils.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
-#include "empathy-individual-manager.h"
#include "empathy-utils.h"
#define DEBUG_FLAG EMPATHY_DEBUG_CONTACT
* changes, not when the position of every single individual is updated. */
#define TOP_INDIVIDUALS_LEN 5
+/* The constant INDIVIDUALS_COUNT_COMPRESS_FACTOR represents the number of
+ * interactions needed to be considered as 1 interaction */
+#define INTERACTION_COUNT_COMPRESS_FACTOR 50
+
+/* The constant DAY_IN_SECONDS represents the seconds in a day */
+#define DAY_IN_SECONDS 86400
+
/* This class only stores and refs Individuals who contain an EmpathyContact.
*
* This class merely forwards along signals from the aggregator and individuals
/* The TOP_INDIVIDUALS_LEN first FolksIndividual (borrowed) from
* individuals_pop */
GList *top_individuals;
+ guint global_interaction_counter;
} EmpathyIndividualManagerPriv;
enum
is_favourite);
}
+
+/* Contacts that have been interacted with within the last 30 days and have
+ * have an interaction count > INTERACTION_COUNT_COMPRESS_FACTOR have a
+ * popularity value of the count/INTERACTION_COUNT_COMPRESS_FACTOR */
static guint
compute_popularity (FolksIndividual *individual)
{
- /* TODO: we should have a better heuristic using the last time we interacted
- * with the contact as well. */
- return folks_interaction_details_get_im_interaction_count (
- FOLKS_INTERACTION_DETAILS (individual));
+ FolksInteractionDetails *details = FOLKS_INTERACTION_DETAILS (individual);
+ GDateTime *last;
+ guint current_timestamp, count;
+ float timediff;
+
+ last = folks_interaction_details_get_last_im_interaction_datetime (details);
+ if (last == NULL)
+ return 0;
+
+ /* Convert g_get_real_time () fro microseconds to seconds */
+ current_timestamp = g_get_real_time () / 1000000;
+ timediff = current_timestamp - g_date_time_to_unix (last);
+
+ if (timediff / DAY_IN_SECONDS > 30)
+ return 0;
+
+ count = folks_interaction_details_get_im_interaction_count (details);
+ count = count / INTERACTION_COUNT_COMPRESS_FACTOR;
+ if (count == 0)
+ return 0;
+
+ return count;
}
static void
* won't work as it assumes that the sequence is sorted which is no longer
* the case at this point as @individual's popularity just changed. */
g_sequence_sort (priv->individuals_pop, compare_individual_by_pop, NULL);
- check_top_individuals (self);
+
+ /* Only check for top individuals after 10 interaction events happen */
+ if (priv->global_interaction_counter % 10 == 0)
+ check_top_individuals (self);
+ priv->global_interaction_counter++;
}
static void
compare_individual_by_pop, NULL);
if (iter != NULL)
{
+ /* priv->top_individuals borrows its reference from
+ * priv->individuals_pop so we take a reference on the individual while
+ * removing it to make sure it stays alive while calling
+ * check_top_individuals(). */
+ g_object_ref (individual);
g_sequence_remove (iter);
check_top_individuals (self);
+ g_object_unref (individual);
}
g_signal_handlers_disconnect_by_func (individual,
/* Make sure we handle each added individual only once. */
if (ind == NULL || g_list_find (added_set, ind) != NULL)
- continue;
+ goto while_next;
added_set = g_list_prepend (added_set, ind);
g_signal_connect (ind, "notify::personas",
added_filtered = g_list_prepend (added_filtered, ind);
}
+while_next:
g_clear_object (&ind);
}
g_clear_object (&iter);
EmpathyIndividualManagerPriv *priv = GET_PRIV (object);
g_hash_table_unref (priv->individuals);
+
tp_clear_object (&priv->aggregator);
G_OBJECT_CLASS (empathy_individual_manager_parent_class)->dispose (object);
priv->individuals_pop = g_sequence_new (g_object_unref);
- priv->aggregator = folks_individual_aggregator_new ();
+ priv->aggregator = folks_individual_aggregator_dup ();
tp_g_signal_connect_object (priv->aggregator, "individuals-changed-detailed",
G_CALLBACK (aggregator_individuals_changed_cb), self, 0);
tp_g_signal_connect_object (priv->aggregator, "notify::is-quiescent",
tp_contact = tpf_persona_get_contact (persona);
if (tp_contact == NULL)
- continue;
+ goto while_next;
conn = tp_contact_get_connection (tp_contact);
if (!tp_proxy_has_interface_by_id (conn,
TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACT_BLOCKING))
- continue;
+ goto while_next;
if (blocked)
tp_contact_block_async (tp_contact, abusive, NULL, NULL);
else
tp_contact_unblock_async (tp_contact, NULL, NULL);
}
+
+while_next:
g_clear_object (&persona);
}
g_clear_object (&iter);
return priv->top_individuals;
}
+
+static void
+unprepare_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ GSimpleAsyncResult *my_result = user_data;
+
+ folks_individual_aggregator_unprepare_finish (
+ FOLKS_INDIVIDUAL_AGGREGATOR (source), result, &error);
+
+ if (error != NULL)
+ {
+ DEBUG ("Failed to unprepare the aggregator: %s", error->message);
+ g_simple_async_result_take_error (my_result, error);
+ }
+
+ g_simple_async_result_complete (my_result);
+ g_object_unref (my_result);
+}
+
+void
+empathy_individual_manager_unprepare_async (
+ EmpathyIndividualManager *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ EmpathyIndividualManagerPriv *priv = GET_PRIV (self);
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ empathy_individual_manager_unprepare_async);
+
+ folks_individual_aggregator_unprepare (priv->aggregator, unprepare_cb,
+ result);
+}
+
+gboolean
+empathy_individual_manager_unprepare_finish (
+ EmpathyIndividualManager *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ tpaw_implement_finish_void (self,
+ empathy_individual_manager_unprepare_async)
+}