mirror of
https://github.com/profanity-im/profanity.git
synced 2024-12-04 14:46:46 -05:00
Handle idle time from contacts
This commit is contained in:
parent
6b99624348
commit
8e90f7a414
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
14
src/jabber.c
14
src/jabber.c
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
32
src/stanza.c
32
src/stanza.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
2
src/ui.h
2
src/ui.h
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user