1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-06-23 21:45:30 +00:00

Handle idle time from contacts

This commit is contained in:
James Booth 2012-12-09 03:07:33 +00:00
parent 6b99624348
commit 8e90f7a414
11 changed files with 162 additions and 61 deletions

View File

@ -34,6 +34,7 @@ struct p_contact_t {
char *status;
char *subscription;
gboolean pending_out;
GDateTime *last_activity;
};
PContact
@ -67,36 +68,11 @@ p_contact_new(const char * const jid, const char * const name,
contact->pending_out = pending_out;
contact->last_activity = NULL;
return contact;
}
PContact
p_contact_copy(PContact contact)
{
PContact copy = malloc(sizeof(struct p_contact_t));
copy->jid = strdup(contact->jid);
if (contact->name != NULL) {
copy->name = strdup(contact->name);
} else {
copy->name = NULL;
}
copy->presence = strdup(contact->presence);
if (contact->status != NULL)
copy->status = strdup(contact->status);
else
copy->status = NULL;
if (contact->subscription != NULL)
copy->subscription = strdup(contact->subscription);
else
copy->subscription = NULL;
return copy;
}
void
p_contact_free(PContact contact)
{
@ -125,6 +101,10 @@ p_contact_free(PContact contact)
contact->subscription = NULL;
}
if (contact->last_activity != NULL) {
g_date_time_unref(contact->last_activity);
}
free(contact);
contact = NULL;
}
@ -165,6 +145,12 @@ p_contact_pending_out(const PContact contact)
return contact->pending_out;
}
GDateTime *
p_contact_last_activity(const PContact contact)
{
return contact->last_activity;
}
void
p_contact_set_presence(const PContact contact, const char * const presence)
{
@ -216,14 +202,15 @@ p_contact_set_pending_out(const PContact contact, gboolean pending_out)
contact->pending_out = pending_out;
}
int
p_contacts_equal_deep(const PContact c1, const PContact c2)
void
p_contact_set_last_activity(const PContact contact, GDateTime *last_activity)
{
int jid_eq = (g_strcmp0(c1->jid, c2->jid) == 0);
int name_eq = (g_strcmp0(c1->name, c2->name) == 0);
int presence_eq = (g_strcmp0(c1->presence, c2->presence) == 0);
int status_eq = (g_strcmp0(c1->status, c2->status) == 0);
int subscription_eq = (g_strcmp0(c1->subscription, c2->subscription) == 0);
if (contact->last_activity != NULL) {
g_date_time_unref(contact->last_activity);
contact->last_activity = NULL;
}
return (jid_eq && name_eq && presence_eq && status_eq && subscription_eq);
if (last_activity != NULL) {
contact->last_activity = g_date_time_ref(last_activity);
}
}

View File

@ -28,18 +28,18 @@ typedef struct p_contact_t *PContact;
PContact p_contact_new(const char * const jid, const char * const name,
const char * const presence, const char * const status,
const char * const subscription, gboolean pending_out);
PContact p_contact_copy(PContact contact);
void p_contact_free(PContact contact);
const char * p_contact_jid(PContact contact);
const char * p_contact_name(PContact contact);
const char * p_contact_presence(PContact contact);
const char * p_contact_status(PContact contact);
const char * p_contact_subscription(const PContact contact);
const char* p_contact_jid(PContact contact);
const char* p_contact_name(PContact contact);
const char* p_contact_presence(PContact contact);
const char* p_contact_status(PContact contact);
const char* p_contact_subscription(const PContact contact);
GDateTime* p_contact_last_activity(const PContact contact);
gboolean p_contact_pending_out(const PContact contact);
void p_contact_set_presence(const PContact contact, const char * const presence);
void p_contact_set_status(const PContact contact, const char * const status);
void p_contact_set_subscription(const PContact contact, const char * const subscription);
void p_contact_set_pending_out(const PContact contact, gboolean pending_out);
int p_contacts_equal_deep(const PContact c1, const PContact c2);
void p_contact_set_last_activity(const PContact contact, GDateTime *last_activity);
#endif

View File

@ -31,6 +31,7 @@ static PAutocomplete ac;
static GHashTable *contacts;
static gboolean _key_equals(void *key1, void *key2);
static gboolean _datetimes_equal(GDateTime *dt1, GDateTime *dt2);
void
contact_list_init(void)
@ -80,7 +81,7 @@ contact_list_remove(const char * const jid)
gboolean
contact_list_update_contact(const char * const jid, const char * const presence,
const char * const status)
const char * const status, GDateTime *last_activity)
{
gboolean changed = FALSE;
PContact contact = g_hash_table_lookup(contacts, jid);
@ -99,6 +100,11 @@ contact_list_update_contact(const char * const jid, const char * const presence,
changed = TRUE;
}
if (!_datetimes_equal(p_contact_last_activity(contact), last_activity)) {
p_contact_set_last_activity(contact, last_activity);
changed = TRUE;
}
return changed;
}
@ -173,3 +179,18 @@ gboolean _key_equals(void *key1, void *key2)
return (g_strcmp0(str1, str2) == 0);
}
static gboolean
_datetimes_equal(GDateTime *dt1, GDateTime *dt2)
{
if ((dt1 == NULL) && (dt2 == NULL)) {
return TRUE;
} else if ((dt1 == NULL) && (dt2 != NULL)) {
return FALSE;
} else if ((dt1 != NULL) && (dt2 == NULL)) {
return FALSE;
} else {
return g_date_time_equal(dt1, dt2);
}
}

View File

@ -35,7 +35,7 @@ gboolean contact_list_add(const char * const jid, const char * const name,
const char * const presence, const char * const status,
const char * const subscription, gboolean pending_out);
gboolean contact_list_update_contact(const char * const jid, const char * const presence,
const char * const status);
const char * const status, GDateTime *last_activity);
void contact_list_update_subscription(const char * const jid,
const char * const subscription, gboolean pending_out);
gboolean contact_list_has_pending_subscriptions(void);

View File

@ -1043,6 +1043,14 @@ _presence_handler(xmpp_conn_t * const conn,
char *short_from = strtok(from, "/");
char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE);
char *show_str, *status_str;
int idle_seconds = stanza_get_idle_time(stanza);
GDateTime *last_activity = NULL;
if (idle_seconds > 0) {
GDateTime *now = g_date_time_new_now_local();
last_activity = g_date_time_add_seconds(now, 0 - idle_seconds);
g_date_time_unref(now);
}
xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_STATUS);
if (status != NULL)
@ -1058,13 +1066,17 @@ _presence_handler(xmpp_conn_t * const conn,
show_str = "online";
if (strcmp(short_jid, short_from) !=0) {
prof_handle_contact_online(short_from, show_str, status_str);
prof_handle_contact_online(short_from, show_str, status_str, last_activity);
}
} else if (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0) {
if (strcmp(short_jid, short_from) !=0) {
prof_handle_contact_offline(short_from, "offline", status_str);
}
if (last_activity != NULL) {
g_date_time_unref(last_activity);
}
// subscriptions
} else if (strcmp(type, STANZA_TYPE_SUBSCRIBE) == 0) {
prof_handle_subscription(short_from, PRESENCE_SUBSCRIBE);

View File

@ -321,15 +321,16 @@ prof_handle_leave_room(const char * const room)
}
void
prof_handle_contact_online(char *contact, char *show, char *status)
prof_handle_contact_online(char *contact, char *show, char *status,
GDateTime *last_activity)
{
gboolean updated = contact_list_update_contact(contact, show, status);
gboolean updated = contact_list_update_contact(contact, show, status, last_activity);
if (updated) {
PContact result = contact_list_get_contact(contact);
if (p_contact_subscription(result) != NULL) {
if (strcmp(p_contact_subscription(result), "none") != 0) {
ui_contact_online(contact, show, status);
ui_contact_online(contact, show, status, last_activity);
win_current_page_off();
}
}
@ -339,7 +340,7 @@ prof_handle_contact_online(char *contact, char *show, char *status)
void
prof_handle_contact_offline(char *contact, char *show, char *status)
{
gboolean updated = contact_list_update_contact(contact, "offline", status);
gboolean updated = contact_list_update_contact(contact, "offline", status, NULL);
if (updated) {
PContact result = contact_list_get_contact(contact);

View File

@ -32,7 +32,8 @@ void prof_handle_lost_connection(void);
void prof_handle_disconnect(const char * const jid);
void prof_handle_failed_login(void);
void prof_handle_typing(char *from);
void prof_handle_contact_online(char *contact, char *show, char *status);
void prof_handle_contact_online(char *contact, char *show, char *status,
GDateTime *last_activity);
void prof_handle_contact_offline(char *contact, char *show, char *status);
void prof_handle_incoming_message(char *from, char *message, gboolean priv);
void prof_handle_delayed_message(char *from, char *message, GTimeVal tv_stamp,

View File

@ -20,6 +20,7 @@
*
*/
#include <stdlib.h>
#include <string.h>
#include <glib.h>
@ -359,3 +360,34 @@ stanza_get_new_nick(xmpp_stanza_t * const stanza)
return NULL;
}
}
int
stanza_get_idle_time(xmpp_stanza_t * const stanza)
{
xmpp_stanza_t *query = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
if (query == NULL) {
return 0;
}
char *ns = xmpp_stanza_get_ns(query);
if (ns == NULL) {
return 0;
}
if (strcmp(ns, STANZA_NS_LASTACTIVITY) != 0) {
return 0;
}
char *seconds_str = xmpp_stanza_get_attribute(query, STANZA_ATTR_SECONDS);
if (seconds_str == NULL) {
return 0;
}
int result = atoi(seconds_str);
if (result < 1) {
return 0;
} else {
return result;
}
}

View File

@ -117,4 +117,6 @@ gboolean stanza_is_room_nick_change(xmpp_stanza_t * const stanza);
char* stanza_get_new_nick(xmpp_stanza_t * const stanza);
int stanza_get_idle_time(xmpp_stanza_t * const stanza);
#endif

View File

@ -69,7 +69,7 @@ void ui_idle(void);
void ui_show_incoming_msg(const char * const from, const char * const message,
GTimeVal *tv_stamp, gboolean priv);
void ui_contact_online(const char * const from, const char * const show,
const char * const status);
const char * const status, GDateTime *last_activity);
void ui_contact_offline(const char * const from, const char * const show,
const char * const status);
void ui_disconnected(void);

View File

@ -89,7 +89,8 @@ static void _win_show_user(WINDOW *win, const char * const user, const int colou
static void _win_show_message(WINDOW *win, const char * const message);
static void _win_show_error_msg(WINDOW *win, const char * const message);
static void _show_status_string(WINDOW *win, const char * const from,
const char * const show, const char * const status, const char * const pre,
const char * const show, const char * const status,
GDateTime *last_activity, const char * const pre,
const char * const default_show);
static void _cons_show_typing(const char * const short_from);
static void _cons_show_incoming_message(const char * const short_from,
@ -427,14 +428,16 @@ ui_show_incoming_msg(const char * const from, const char * const message,
void
ui_contact_online(const char * const from, const char * const show,
const char * const status)
const char * const status, GDateTime *last_activity)
{
_show_status_string(console->win, from, show, status, "++", "online");
_show_status_string(console->win, from, show, status, last_activity, "++",
"online");
int win_index = _find_prof_win_index(from);
if (win_index != NUM_WINS) {
WINDOW *win = windows[win_index]->win;
_show_status_string(win, from, show, status, "++", "online");
_show_status_string(win, from, show, status, last_activity, "++",
"online");
}
if (win_index == current_index)
@ -445,12 +448,12 @@ void
ui_contact_offline(const char * const from, const char * const show,
const char * const status)
{
_show_status_string(console->win, from, show, status, "--", "offline");
_show_status_string(console->win, from, show, status, NULL, "--", "offline");
int win_index = _find_prof_win_index(from);
if (win_index != NUM_WINS) {
WINDOW *win = windows[win_index]->win;
_show_status_string(win, from, show, status, "--", "offline");
_show_status_string(win, from, show, status, NULL, "--", "offline");
}
if (win_index == current_index)
@ -694,7 +697,7 @@ win_new_chat_win(const char * const to)
if (strcmp(p_contact_presence(contact), "offline") == 0) {
const char const *show = p_contact_presence(contact);
const char const *status = p_contact_status(contact);
_show_status_string(win, to, show, status, "--", "offline");
_show_status_string(win, to, show, status, NULL, "--", "offline");
}
}
@ -734,7 +737,7 @@ win_show_outgoing_msg(const char * const from, const char * const to,
if (strcmp(p_contact_presence(contact), "offline") == 0) {
const char const *show = p_contact_presence(contact);
const char const *status = p_contact_status(contact);
_show_status_string(win, to, show, status, "--", "offline");
_show_status_string(win, to, show, status, NULL, "--", "offline");
}
}
@ -876,7 +879,7 @@ win_show_room_member_presence(const char * const room, const char * const nick,
int win_index = _find_prof_win_index(room);
if (win_index != NUM_WINS) {
WINDOW *win = windows[win_index]->win;
_show_status_string(win, nick, show, status, "++", "online");
_show_status_string(win, nick, show, status, NULL, "++", "online");
}
if (win_index == current_index)
@ -1882,7 +1885,8 @@ _win_resize_all(void)
static void
_show_status_string(WINDOW *win, const char * const from,
const char * const show, const char * const status, const char * const pre,
const char * const show, const char * const status,
GDateTime *last_activity, const char * const pre,
const char * const default_show)
{
_win_show_time(win);
@ -1914,6 +1918,26 @@ _show_status_string(WINDOW *win, const char * const from,
else
wprintw(win, " is %s", default_show);
if (last_activity != NULL) {
GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity);
wprintw(win, ", idle ");
int hours = span / G_TIME_SPAN_HOUR;
span = span - hours * G_TIME_SPAN_HOUR;
if (hours > 0) {
wprintw(win, "%dh", hours);
}
int minutes = span / G_TIME_SPAN_MINUTE;
span = span - minutes * G_TIME_SPAN_MINUTE;
wprintw(win, "%dm", minutes);
int seconds = span / G_TIME_SPAN_SECOND;
wprintw(win, "%ds", seconds);
}
if (status != NULL)
wprintw(win, ", \"%s\"", status);
@ -1965,6 +1989,7 @@ _cons_show_contact(PContact contact)
const char *name = p_contact_name(contact);
const char *presence = p_contact_presence(contact);
const char *status = p_contact_status(contact);
GDateTime *last_activity = p_contact_last_activity(contact);
_win_show_time(console->win);
@ -1990,6 +2015,26 @@ _cons_show_contact(PContact contact)
wprintw(console->win, " is %s", presence);
if (last_activity != NULL) {
GDateTime *now = g_date_time_new_now_local();
GTimeSpan span = g_date_time_difference(now, last_activity);
wprintw(console->win, ", idle ");
int hours = span / G_TIME_SPAN_HOUR;
span = span - hours * G_TIME_SPAN_HOUR;
if (hours > 0) {
wprintw(console->win, "%dh", hours);
}
int minutes = span / G_TIME_SPAN_MINUTE;
span = span - minutes * G_TIME_SPAN_MINUTE;
wprintw(console->win, "%dm", minutes);
int seconds = span / G_TIME_SPAN_SECOND;
wprintw(console->win, "%ds", seconds);
}
if (status != NULL) {
wprintw(console->win, ", \"%s\"", p_contact_status(contact));
}