1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-09-22 19:45:54 -04: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 *status;
char *subscription; char *subscription;
gboolean pending_out; gboolean pending_out;
GDateTime *last_activity;
}; };
PContact PContact
@ -67,36 +68,11 @@ p_contact_new(const char * const jid, const char * const name,
contact->pending_out = pending_out; contact->pending_out = pending_out;
contact->last_activity = NULL;
return contact; 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 void
p_contact_free(PContact contact) p_contact_free(PContact contact)
{ {
@ -125,6 +101,10 @@ p_contact_free(PContact contact)
contact->subscription = NULL; contact->subscription = NULL;
} }
if (contact->last_activity != NULL) {
g_date_time_unref(contact->last_activity);
}
free(contact); free(contact);
contact = NULL; contact = NULL;
} }
@ -165,6 +145,12 @@ p_contact_pending_out(const PContact contact)
return contact->pending_out; return contact->pending_out;
} }
GDateTime *
p_contact_last_activity(const PContact contact)
{
return contact->last_activity;
}
void void
p_contact_set_presence(const PContact contact, const char * const presence) 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; contact->pending_out = pending_out;
} }
int void
p_contacts_equal_deep(const PContact c1, const PContact c2) p_contact_set_last_activity(const PContact contact, GDateTime *last_activity)
{ {
int jid_eq = (g_strcmp0(c1->jid, c2->jid) == 0); if (contact->last_activity != NULL) {
int name_eq = (g_strcmp0(c1->name, c2->name) == 0); g_date_time_unref(contact->last_activity);
int presence_eq = (g_strcmp0(c1->presence, c2->presence) == 0); contact->last_activity = NULL;
int status_eq = (g_strcmp0(c1->status, c2->status) == 0); }
int subscription_eq = (g_strcmp0(c1->subscription, c2->subscription) == 0);
if (last_activity != NULL) {
return (jid_eq && name_eq && presence_eq && status_eq && subscription_eq); 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, PContact p_contact_new(const char * const jid, const char * const name,
const char * const presence, const char * const status, const char * const presence, const char * const status,
const char * const subscription, gboolean pending_out); const char * const subscription, gboolean pending_out);
PContact p_contact_copy(PContact contact);
void p_contact_free(PContact contact); void p_contact_free(PContact contact);
const char* p_contact_jid(PContact contact); const char* p_contact_jid(PContact contact);
const char* p_contact_name(PContact contact); const char* p_contact_name(PContact contact);
const char* p_contact_presence(PContact contact); const char* p_contact_presence(PContact contact);
const char* p_contact_status(PContact contact); const char* p_contact_status(PContact contact);
const char* p_contact_subscription(const 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); gboolean p_contact_pending_out(const PContact contact);
void p_contact_set_presence(const PContact contact, const char * const presence); 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_status(const PContact contact, const char * const status);
void p_contact_set_subscription(const PContact contact, const char * const subscription); void p_contact_set_subscription(const PContact contact, const char * const subscription);
void p_contact_set_pending_out(const PContact contact, gboolean pending_out); 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 #endif

View File

@ -31,6 +31,7 @@ static PAutocomplete ac;
static GHashTable *contacts; static GHashTable *contacts;
static gboolean _key_equals(void *key1, void *key2); static gboolean _key_equals(void *key1, void *key2);
static gboolean _datetimes_equal(GDateTime *dt1, GDateTime *dt2);
void void
contact_list_init(void) contact_list_init(void)
@ -80,7 +81,7 @@ contact_list_remove(const char * const jid)
gboolean gboolean
contact_list_update_contact(const char * const jid, const char * const presence, 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; gboolean changed = FALSE;
PContact contact = g_hash_table_lookup(contacts, jid); 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; changed = TRUE;
} }
if (!_datetimes_equal(p_contact_last_activity(contact), last_activity)) {
p_contact_set_last_activity(contact, last_activity);
changed = TRUE;
}
return changed; return changed;
} }
@ -173,3 +179,18 @@ gboolean _key_equals(void *key1, void *key2)
return (g_strcmp0(str1, str2) == 0); 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 presence, const char * const status,
const char * const subscription, gboolean pending_out); const char * const subscription, gboolean pending_out);
gboolean contact_list_update_contact(const char * const jid, const char * const presence, 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, void contact_list_update_subscription(const char * const jid,
const char * const subscription, gboolean pending_out); const char * const subscription, gboolean pending_out);
gboolean contact_list_has_pending_subscriptions(void); 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 *short_from = strtok(from, "/");
char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE); char *type = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_TYPE);
char *show_str, *status_str; 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); xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_STATUS);
if (status != NULL) if (status != NULL)
@ -1058,13 +1066,17 @@ _presence_handler(xmpp_conn_t * const conn,
show_str = "online"; show_str = "online";
if (strcmp(short_jid, short_from) !=0) { 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) { } else if (strcmp(type, STANZA_TYPE_UNAVAILABLE) == 0) {
if (strcmp(short_jid, short_from) !=0) { if (strcmp(short_jid, short_from) !=0) {
prof_handle_contact_offline(short_from, "offline", status_str); prof_handle_contact_offline(short_from, "offline", status_str);
} }
if (last_activity != NULL) {
g_date_time_unref(last_activity);
}
// subscriptions // subscriptions
} else if (strcmp(type, STANZA_TYPE_SUBSCRIBE) == 0) { } else if (strcmp(type, STANZA_TYPE_SUBSCRIBE) == 0) {
prof_handle_subscription(short_from, PRESENCE_SUBSCRIBE); prof_handle_subscription(short_from, PRESENCE_SUBSCRIBE);

View File

@ -321,15 +321,16 @@ prof_handle_leave_room(const char * const room)
} }
void 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) { if (updated) {
PContact result = contact_list_get_contact(contact); PContact result = contact_list_get_contact(contact);
if (p_contact_subscription(result) != NULL) { if (p_contact_subscription(result) != NULL) {
if (strcmp(p_contact_subscription(result), "none") != 0) { 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(); win_current_page_off();
} }
} }
@ -339,7 +340,7 @@ prof_handle_contact_online(char *contact, char *show, char *status)
void void
prof_handle_contact_offline(char *contact, char *show, char *status) 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) { if (updated) {
PContact result = contact_list_get_contact(contact); 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_disconnect(const char * const jid);
void prof_handle_failed_login(void); void prof_handle_failed_login(void);
void prof_handle_typing(char *from); 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_contact_offline(char *contact, char *show, char *status);
void prof_handle_incoming_message(char *from, char *message, gboolean priv); void prof_handle_incoming_message(char *from, char *message, gboolean priv);
void prof_handle_delayed_message(char *from, char *message, GTimeVal tv_stamp, 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 <string.h>
#include <glib.h> #include <glib.h>
@ -359,3 +360,34 @@ stanza_get_new_nick(xmpp_stanza_t * const stanza)
return NULL; 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); char* stanza_get_new_nick(xmpp_stanza_t * const stanza);
int stanza_get_idle_time(xmpp_stanza_t * const stanza);
#endif #endif

View File

@ -69,7 +69,7 @@ void ui_idle(void);
void ui_show_incoming_msg(const char * const from, const char * const message, void ui_show_incoming_msg(const char * const from, const char * const message,
GTimeVal *tv_stamp, gboolean priv); GTimeVal *tv_stamp, gboolean priv);
void ui_contact_online(const char * const from, const char * const show, 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, void ui_contact_offline(const char * const from, const char * const show,
const char * const status); const char * const status);
void ui_disconnected(void); 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_message(WINDOW *win, const char * const message);
static void _win_show_error_msg(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, 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); const char * const default_show);
static void _cons_show_typing(const char * const short_from); static void _cons_show_typing(const char * const short_from);
static void _cons_show_incoming_message(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 void
ui_contact_online(const char * const from, const char * const show, 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); int win_index = _find_prof_win_index(from);
if (win_index != NUM_WINS) { if (win_index != NUM_WINS) {
WINDOW *win = windows[win_index]->win; 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) if (win_index == current_index)
@ -445,12 +448,12 @@ void
ui_contact_offline(const char * const from, const char * const show, ui_contact_offline(const char * const from, const char * const show,
const char * const status) 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); int win_index = _find_prof_win_index(from);
if (win_index != NUM_WINS) { if (win_index != NUM_WINS) {
WINDOW *win = windows[win_index]->win; 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) 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) { if (strcmp(p_contact_presence(contact), "offline") == 0) {
const char const *show = p_contact_presence(contact); const char const *show = p_contact_presence(contact);
const char const *status = p_contact_status(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) { if (strcmp(p_contact_presence(contact), "offline") == 0) {
const char const *show = p_contact_presence(contact); const char const *show = p_contact_presence(contact);
const char const *status = p_contact_status(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); int win_index = _find_prof_win_index(room);
if (win_index != NUM_WINS) { if (win_index != NUM_WINS) {
WINDOW *win = windows[win_index]->win; 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) if (win_index == current_index)
@ -1882,7 +1885,8 @@ _win_resize_all(void)
static void static void
_show_status_string(WINDOW *win, const char * const from, _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) const char * const default_show)
{ {
_win_show_time(win); _win_show_time(win);
@ -1914,6 +1918,26 @@ _show_status_string(WINDOW *win, const char * const from,
else else
wprintw(win, " is %s", default_show); 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) if (status != NULL)
wprintw(win, ", \"%s\"", status); wprintw(win, ", \"%s\"", status);
@ -1965,6 +1989,7 @@ _cons_show_contact(PContact contact)
const char *name = p_contact_name(contact); const char *name = p_contact_name(contact);
const char *presence = p_contact_presence(contact); const char *presence = p_contact_presence(contact);
const char *status = p_contact_status(contact); const char *status = p_contact_status(contact);
GDateTime *last_activity = p_contact_last_activity(contact);
_win_show_time(console->win); _win_show_time(console->win);
@ -1990,6 +2015,26 @@ _cons_show_contact(PContact contact)
wprintw(console->win, " is %s", presence); 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) { if (status != NULL) {
wprintw(console->win, ", \"%s\"", p_contact_status(contact)); wprintw(console->win, ", \"%s\"", p_contact_status(contact));
} }