about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--TODO_STATES21
-rw-r--r--src/chat_session.c323
-rw-r--r--src/chat_session.h22
-rw-r--r--src/chat_state.c52
-rw-r--r--src/chat_state.h37
-rw-r--r--src/profanity.c64
-rw-r--r--src/server_events.c8
-rw-r--r--src/ui/core.c8
-rw-r--r--src/ui/inputwin.c24
-rw-r--r--src/xmpp/message.c64
10 files changed, 224 insertions, 399 deletions
diff --git a/TODO_STATES b/TODO_STATES
new file mode 100644
index 00000000..6e080b18
--- /dev/null
+++ b/TODO_STATES
@@ -0,0 +1,21 @@
+Chat sessions
+
+Start (if not already started):
+    When message received from fulljid
+    When active, composing, paused or inactive chat state received from fulljid
+End:
+    When message received from a different fulljid (start new session)
+    When active, composing, paused or inactive received from different fulljid (start new session)
+    When any presence received from any resource
+    When gone received from fulljid
+    When window closed
+    When gone sent
+
+Chat states
+
+Active - focus chat window, or message send
+Composing - typing in chat session (window)
+Paused - no typing for 30 seconds
+Inactive - unfocus chat window, or after 2 mins
+Gone - close chat window, or after 10 mins
+
diff --git a/src/chat_session.c b/src/chat_session.c
index eae3f577..0def4da2 100644
--- a/src/chat_session.c
+++ b/src/chat_session.c
@@ -43,45 +43,20 @@
 #include "log.h"
 #include "xmpp/xmpp.h"
 
-#define PAUSED_TIMOUT 10.0
-#define INACTIVE_TIMOUT 30.0
-
-typedef enum {
-    CHAT_STATE_STARTED,
-    CHAT_STATE_ACTIVE,
-    CHAT_STATE_PAUSED,
-    CHAT_STATE_COMPOSING,
-    CHAT_STATE_INACTIVE,
-    CHAT_STATE_GONE
-} chat_state_t;
-
-typedef struct chat_session_t {
-    char *barejid;
-    char *resource;
-    gboolean send_states;
-    chat_state_t state;
-    GTimer *active_timer;
-    gboolean sent;
-} ChatSession;
-
 static GHashTable *sessions;
 
-static ChatSession*
+static void
 _chat_session_new(const char * const barejid, const char * const resource, gboolean send_states)
 {
+    assert(barejid != NULL);
+    assert(resource != NULL);
+
     ChatSession *new_session = malloc(sizeof(struct chat_session_t));
     new_session->barejid = strdup(barejid);
-    if (resource) {
-        new_session->resource = strdup(resource);
-    } else {
-        new_session->resource = NULL;
-    }
+    new_session->resource = strdup(resource);
     new_session->send_states = send_states;
-    new_session->state = CHAT_STATE_STARTED;
-    new_session->active_timer = g_timer_new();
-    new_session->sent = FALSE;
 
-    return new_session;
+    g_hash_table_insert(sessions, strdup(barejid), new_session);
 }
 
 static void
@@ -90,10 +65,6 @@ _chat_session_free(ChatSession *session)
     if (session != NULL) {
         free(session->barejid);
         free(session->resource);
-        if (session->active_timer != NULL) {
-            g_timer_destroy(session->active_timer);
-            session->active_timer = NULL;
-        }
         free(session);
     }
 }
@@ -112,284 +83,34 @@ chat_sessions_clear(void)
         g_hash_table_remove_all(sessions);
 }
 
-gboolean
-chat_session_exists(const char * const barejid)
-{
-    ChatSession *session = g_hash_table_lookup(sessions, barejid);
-
-    return (session != NULL);
-}
-
-char*
-chat_session_get_resource(const char * const barejid)
-{
-    ChatSession *session = g_hash_table_lookup(sessions, barejid);
-    assert(session != NULL);
-
-    return session->resource;
-}
-
-gboolean
-chat_session_send_states(const char * const barejid)
-{
-    ChatSession *session = g_hash_table_lookup(sessions, barejid);
-    assert(session != NULL);
-
-    return session->send_states;
-}
-
-void
-chat_session_on_incoming_message(const char * const barejid, const char * const resource, gboolean send_states)
-{
-    ChatSession *session = g_hash_table_lookup(sessions, barejid);
-    GString *log_msg = g_string_new("");
-
-    // no session exists, create one
-    if (!session) {
-        g_string_append(log_msg, "Creating chat session for ");
-        g_string_append(log_msg, barejid);
-        if (resource) {
-            g_string_append(log_msg, "/");
-            g_string_append(log_msg, resource);
-        }
-        session = _chat_session_new(barejid, resource, send_states);
-        g_hash_table_insert(sessions, strdup(barejid), session);
-
-    // session exists for different resource, replace session
-    } else if (g_strcmp0(session->resource, resource) != 0) {
-        g_string_append(log_msg, "Replacing chat session for ");
-        g_string_append(log_msg, barejid);
-        if (session->resource) {
-            g_string_append(log_msg, "/");
-            g_string_append(log_msg, session->resource);
-        }
-        g_string_append(log_msg, " with session for ");
-        g_string_append(log_msg, barejid);
-        if (resource) {
-            g_string_append(log_msg, "/");
-            g_string_append(log_msg, resource);
-        }
-        g_hash_table_remove(sessions, session);
-        session = _chat_session_new(barejid, resource, send_states);
-        g_hash_table_insert(sessions, strdup(barejid), session);
-
-    // session exists for resource, update state
-    } else {
-        g_string_append(log_msg, "Updating chat session for ");
-        g_string_append(log_msg, session->barejid);
-        if (session->resource) {
-            g_string_append(log_msg, "/");
-            g_string_append(log_msg, session->resource);
-        }
-        session->send_states = send_states;
-    }
-    if (send_states) {
-        g_string_append(log_msg, ", chat states supported");
-    } else {
-        g_string_append(log_msg, ", chat states not supported");
-    }
-
-    log_debug(log_msg->str);
-    g_string_free(log_msg, TRUE);
-}
-
-void
-chat_session_on_message_send(const char * const barejid)
-{
-    ChatSession *session = g_hash_table_lookup(sessions, barejid);
-
-    // if no session exists, create one with no resource, and send states
-    if (!session) {
-        log_debug("Creating chat session for %s, chat states supported", barejid);
-        session = _chat_session_new(barejid, NULL, TRUE);
-        g_hash_table_insert(sessions, strdup(barejid), session);
-    }
-
-    session->state = CHAT_STATE_ACTIVE;
-    g_timer_start(session->active_timer);
-    session->sent = TRUE;
-}
-
-void
-chat_session_on_window_close(const char * const barejid)
-{
-    ChatSession *session = g_hash_table_lookup(sessions, barejid);
-
-    if (session) {
-        if (prefs_get_boolean(PREF_STATES) && session->send_states) {
-            GString *jid = g_string_new(session->barejid);
-            if (session->resource) {
-                g_string_append(jid, "/");
-                g_string_append(jid, session->resource);
-            }
-            message_send_gone(jid->str);
-            g_string_free(jid, TRUE);
-        }
-        GString *log_msg = g_string_new("Removing chat session for ");
-        g_string_append(log_msg, barejid);
-        if (session->resource) {
-            g_string_append(log_msg, "/");
-            g_string_append(log_msg, session->resource);
-        }
-        log_debug(log_msg->str);
-        g_string_free(log_msg, TRUE);
-        g_hash_table_remove(sessions, barejid);
-    }
-}
-
-void
-chat_session_on_offline(const char * const barejid, const char * const resource)
+ChatSession*
+chat_session_get(const char * const barejid)
 {
-    if (!resource) {
-        return;
-    }
-
-    ChatSession *session = g_hash_table_lookup(sessions, barejid);
-
-    if (session && (g_strcmp0(session->resource, resource) == 0)) {
-        GString *log_msg = g_string_new("Removing chat session for ");
-        g_string_append(log_msg, barejid);
-        if (session->resource) {
-            g_string_append(log_msg, "/");
-            g_string_append(log_msg, session->resource);
-        }
-        log_debug(log_msg->str);
-        g_string_free(log_msg, TRUE);
-        g_hash_table_remove(sessions, barejid);
-    }
+    return g_hash_table_lookup(sessions, barejid);
 }
 
 void
-chat_session_on_gone(const char * const barejid)
+chat_session_on_recipient_activity(const char * const barejid, const char * const resource)
 {
     ChatSession *session = g_hash_table_lookup(sessions, barejid);
     if (session) {
-        GString *log_msg = g_string_new("Removing chat session for ");
-        g_string_append(log_msg, barejid);
-        if (session->resource) {
-            g_string_append(log_msg, "/");
-            g_string_append(log_msg, session->resource);
-        }
-        log_debug(log_msg->str);
-        g_string_free(log_msg, TRUE);
-        g_hash_table_remove(sessions, barejid);
-    }
-}
-
-void
-chat_session_on_activity(const char * const barejid)
-{
-    ChatSession *session = g_hash_table_lookup(sessions, barejid);
-
-    if (!session) {
-        log_debug("Creating chat session for %s, chat states supported", barejid);
-        session = _chat_session_new(barejid, NULL, TRUE);
-        g_hash_table_insert(sessions, strdup(barejid), session);
-    }
-
-    if (session->state != CHAT_STATE_COMPOSING) {
-        session->sent = FALSE;
-    }
-
-    session->state = CHAT_STATE_COMPOSING;
-    g_timer_start(session->active_timer);
-
-    if (!session->sent || session->state == CHAT_STATE_PAUSED) {
-        if (prefs_get_boolean(PREF_STATES) && prefs_get_boolean(PREF_OUTTYPE) && session->send_states) {
-            GString *jid = g_string_new(session->barejid);
-            if (session->resource) {
-                g_string_append(jid, "/");
-                g_string_append(jid, session->resource);
-            }
-            message_send_composing(jid->str);
-            g_string_free(jid, TRUE);
-        }
-        session->sent = TRUE;
-    }
-}
-
-void
-chat_session_on_inactivity(const char * const barejid)
-{
-    ChatSession *session = g_hash_table_lookup(sessions, barejid);
-    if (!session) {
-        return;
-    }
-
-    if (session->active_timer != NULL) {
-        gdouble elapsed = g_timer_elapsed(session->active_timer, NULL);
-
-        if ((prefs_get_gone() != 0) && (elapsed > (prefs_get_gone() * 60.0))) {
-            if (session->state != CHAT_STATE_GONE) {
-                session->sent = FALSE;
-            }
-            session->state = CHAT_STATE_GONE;
-
-        } else if (elapsed > INACTIVE_TIMOUT) {
-            if (session->state != CHAT_STATE_INACTIVE) {
-                session->sent = FALSE;
-            }
-            session->state = CHAT_STATE_INACTIVE;
-
-        } else if (elapsed > PAUSED_TIMOUT) {
-            if (session->state == CHAT_STATE_COMPOSING) {
-                session->sent = FALSE;
-                session->state = CHAT_STATE_PAUSED;
-            }
-        }
-    }
-
-    if (session->sent == FALSE) {
-        GString *jid = g_string_new(session->barejid);
-        if (session->resource) {
-            g_string_append(jid, "/");
-            g_string_append(jid, session->resource);
-        }
-        if (session->state == CHAT_STATE_GONE) {
-            if (prefs_get_boolean(PREF_STATES) && session->send_states) {
-                message_send_gone(jid->str);
-            }
-            session->sent = TRUE;
-            GString *log_msg = g_string_new("Removing chat session for ");
-            g_string_append(log_msg, barejid);
-            if (session->resource) {
-                g_string_append(log_msg, "/");
-                g_string_append(log_msg, session->resource);
-            }
-            log_debug(log_msg->str);
-            g_string_free(log_msg, TRUE);
+        // session exists with resource, do nothing
+        if (g_strcmp0(session->resource, resource) == 0) {
+            return;
+        // session exists with differet resource, replace
+        } else {
             g_hash_table_remove(sessions, barejid);
-        } else if (session->state == CHAT_STATE_INACTIVE) {
-            if (prefs_get_boolean(PREF_STATES) && session->send_states) {
-                message_send_inactive(jid->str);
-            }
-            session->sent = TRUE;
-        } else if (session->state == CHAT_STATE_PAUSED && prefs_get_boolean(PREF_OUTTYPE)) {
-            if (prefs_get_boolean(PREF_STATES) && session->send_states) {
-                message_send_paused(jid->str);
-            }
-            session->sent = TRUE;
+            _chat_session_new(barejid, resource, FALSE);
         }
-        g_string_free(jid, TRUE);
+
+    // no session, create one
+    } else {
+        _chat_session_new(barejid, resource, FALSE);
     }
 }
 
 void
-chat_session_on_cancel(const char * const jid)
+chat_session_remove(const char * const barejid)
 {
-    Jid *jidp = jid_create(jid);
-    if (jidp) {
-        ChatSession *session = g_hash_table_lookup(sessions, jidp->barejid);
-        if (session) {
-            GString *log_msg = g_string_new("Removing chat session for ");
-            g_string_append(log_msg, jidp->barejid);
-            if (session->resource) {
-                g_string_append(log_msg, "/");
-                g_string_append(log_msg, session->resource);
-            }
-            log_debug(log_msg->str);
-            g_string_free(log_msg, TRUE);
-            g_hash_table_remove(sessions, jidp->barejid);
-        }
-    }
+    g_hash_table_remove(sessions, barejid);
 }
\ No newline at end of file
diff --git a/src/chat_session.h b/src/chat_session.h
index dbffad9f..80c6d55e 100644
--- a/src/chat_session.h
+++ b/src/chat_session.h
@@ -37,21 +37,17 @@
 
 #include <glib.h>
 
+typedef struct chat_session_t {
+    char *barejid;
+    char *resource;
+    gboolean send_states;
+} ChatSession;
+
 void chat_sessions_init(void);
 void chat_sessions_clear(void);
 
-gboolean chat_session_exists(const char * const barejid);
-char* chat_session_get_resource(const char * const barejid);
-gboolean chat_session_send_states(const char * const barejid);
-
-void chat_session_on_message_send(const char * const barejid);
-void chat_session_on_window_close(const char * const barejid);
-void chat_session_on_incoming_message(const char * const barejid, const char * const resource, gboolean send_states);
-void chat_session_on_offline(const char * const barejid, const char * const resource);
-void chat_session_on_cancel(const char * const jid);
-void chat_session_on_gone(const char * const barejid);
-
-void chat_session_on_activity(const char * const barejid);
-void chat_session_on_inactivity(const char * const barejid);
+ChatSession* chat_session_get(const char * const barejid);
+void chat_session_on_recipient_activity(const char * const barejid, const char * const resourcepart);
+void chat_session_remove(const char * const barejid);
 
 #endif
diff --git a/src/chat_state.c b/src/chat_state.c
new file mode 100644
index 00000000..f8bf8a56
--- /dev/null
+++ b/src/chat_state.c
@@ -0,0 +1,52 @@
+/*
+ * chat_state.c
+ *
+ * Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+
+// TODO make preferences
+#define PAUSED_SECS 30.0
+#define INACTIVE_SECS 120.0
+
+typedef enum {
+    CHAT_STATE_ACTIVE,
+    CHAT_STATE_PAUSED,
+    CHAT_STATE_COMPOSING,
+    CHAT_STATE_INACTIVE,
+    CHAT_STATE_GONE
+} chat_state_type_t;
+
+typedef struct chat_state_t {
+    chat_state_t state;
+    GTimer *active_timer;
+    gboolean sent;
+} ChatState;
+
diff --git a/src/chat_state.h b/src/chat_state.h
new file mode 100644
index 00000000..a916b796
--- /dev/null
+++ b/src/chat_state.h
@@ -0,0 +1,37 @@
+/*
+ * chat_state.h
+ *
+ * Copyright (C) 2012 - 2014 James Booth <boothj5@gmail.com>
+ *
+ * This file is part of Profanity.
+ *
+ * Profanity is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Profanity is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Profanity.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, the copyright holders give permission to
+ * link the code of portions of this program with the OpenSSL library under
+ * certain conditions as described in each individual source file, and
+ * distribute linked combinations including the two.
+ *
+ * You must obey the GNU General Public License in all respects for all of the
+ * code used other than OpenSSL. If you modify file(s) with this exception, you
+ * may extend this exception to your version of the file(s), but you are not
+ * obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version. If you delete this exception statement from all
+ * source files in the program, then also delete it here.
+ *
+ */
+
+#ifndef CHAT_STATE_H
+#define CHAT_STATE_H
+
diff --git a/src/profanity.c b/src/profanity.c
index e53ac176..e8342b65 100644
--- a/src/profanity.c
+++ b/src/profanity.c
@@ -131,38 +131,38 @@ prof_run(const int disable_tls, char *log_level, char *account_name)
 
     g_timer_destroy(timer);
 }
-
-void
-prof_handle_idle(void)
-{
-    jabber_conn_status_t status = jabber_get_connection_status();
-    if (status == JABBER_CONNECTED) {
-        GSList *recipients = ui_get_chat_recipients();
-        GSList *curr = recipients;
-
-        while (curr != NULL) {
-            char *barejid = curr->data;
-            chat_session_on_inactivity(barejid);
-            curr = g_slist_next(curr);
-        }
-
-        if (recipients != NULL) {
-            g_slist_free(recipients);
-        }
-    }
-}
-
-void
-prof_handle_activity(void)
-{
-    win_type_t win_type = ui_current_win_type();
-    jabber_conn_status_t status = jabber_get_connection_status();
-
-    if ((status == JABBER_CONNECTED) && (win_type == WIN_CHAT)) {
-        ProfChatWin *chatwin = wins_get_current_chat();
-        chat_session_on_activity(chatwin->barejid);
-    }
-}
+//
+//void
+//prof_handle_idle(void)
+//{
+//    jabber_conn_status_t status = jabber_get_connection_status();
+//    if (status == JABBER_CONNECTED) {
+//        GSList *recipients = ui_get_chat_recipients();
+//        GSList *curr = recipients;
+//
+//        while (curr != NULL) {
+//            char *barejid = curr->data;
+//            chat_session_on_inactivity(barejid);
+//            curr = g_slist_next(curr);
+//        }
+//
+//        if (recipients != NULL) {
+//            g_slist_free(recipients);
+//        }
+//    }
+//}
+//
+//void
+//prof_handle_activity(void)
+//{
+//    win_type_t win_type = ui_current_win_type();
+//    jabber_conn_status_t status = jabber_get_connection_status();
+//
+//    if ((status == JABBER_CONNECTED) && (win_type == WIN_CHAT)) {
+//        ProfChatWin *chatwin = wins_get_current_chat();
+//        chat_session_on_activity(chatwin->barejid);
+//    }
+//}
 
 /*
  * Take a line of input and process it, return TRUE if profanity is to
diff --git a/src/server_events.c b/src/server_events.c
index edd58724..34185ed5 100644
--- a/src/server_events.c
+++ b/src/server_events.c
@@ -87,7 +87,8 @@ handle_message_error(const char * const jid, const char * const type,
     // handle recipient not found ('from' contains a value and type is 'cancel')
     } else if (type != NULL && (strcmp(type, "cancel") == 0)) {
         log_info("Recipient %s not found: %s", jid, err_msg);
-        chat_session_on_cancel(jid);
+        Jid *jidp = jid_create(jid);
+        chat_session_remove(jidp->barejid);
 
     // handle any other error from recipient
     } else {
@@ -393,7 +394,7 @@ handle_typing(char *from)
 void
 handle_gone(const char * const from)
 {
-    chat_session_on_gone(from);
+    chat_session_remove(from);
     ui_recipient_gone(from);
 }
 
@@ -464,7 +465,7 @@ handle_contact_offline(char *barejid, char *resource, char *status)
     }
 
     rosterwin_roster();
-    chat_session_on_offline(barejid, resource);
+    chat_session_remove(barejid);
 }
 
 void
@@ -507,6 +508,7 @@ handle_contact_online(char *barejid, Resource *resource,
     }
 
     rosterwin_roster();
+    chat_session_remove(barejid);
 }
 
 void
diff --git a/src/ui/core.c b/src/ui/core.c
index fafa4377..8eb9025b 100644
--- a/src/ui/core.c
+++ b/src/ui/core.c
@@ -686,9 +686,7 @@ ui_close_connected_win(int index)
                 otr_end_session(chatwin->barejid);
             }
 #endif
-            if (chat_session_exists(chatwin->barejid)) {
-                chat_session_on_window_close(chatwin->barejid);
-            }
+            chat_session_remove(chatwin->barejid);
         }
     }
 }
@@ -1145,9 +1143,7 @@ ui_prune_wins(void)
         if (window->type == WIN_CHAT) {
             if (conn_status == JABBER_CONNECTED) {
                 ProfChatWin *chatwin = (ProfChatWin*)window;
-                if (chat_session_exists(chatwin->barejid)) {
-                    chat_session_on_window_close(chatwin->barejid);
-                }
+                chat_session_remove(chatwin->barejid);
             }
         }
 
diff --git a/src/ui/inputwin.c b/src/ui/inputwin.c
index 19318745..57634385 100644
--- a/src/ui/inputwin.c
+++ b/src/ui/inputwin.c
@@ -145,18 +145,18 @@ inp_get_char(char *input, int *size, int *result)
     noecho();
     *result = wget_wch(inp_win, &ch);
 
-    gboolean in_command = FALSE;
-    if ((display_size > 0 && input[0] == '/') ||
-            (display_size == 0 && ch == '/')) {
-        in_command = TRUE;
-    }
-
-    if (*result == ERR) {
-        prof_handle_idle();
-    }
-    if ((*result != ERR) && (*result != KEY_CODE_YES) && !in_command && _printable(ch)) {
-        prof_handle_activity();
-    }
+//    gboolean in_command = FALSE;
+//    if ((display_size > 0 && input[0] == '/') ||
+//            (display_size == 0 && ch == '/')) {
+//        in_command = TRUE;
+//    }
+
+//    if (*result == ERR) {
+//        prof_handle_idle();
+//    }
+//    if ((*result != ERR) && (*result != KEY_CODE_YES) && !in_command && _printable(ch)) {
+//        prof_handle_activity();
+//    }
 
     // if it wasn't an arrow key etc
     if (!_handle_edit(*result, ch, input, size)) {
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index b104bdb3..4474c7ad 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -86,25 +86,17 @@ message_send_chat(const char * const barejid, const char * const msg)
     xmpp_conn_t * const conn = connection_get_conn();
     xmpp_ctx_t * const ctx = connection_get_ctx();
 
-    chat_session_on_message_send(barejid);
-    char *resource = chat_session_get_resource(barejid);
-    gboolean send_state = chat_session_send_states(barejid);
-
-    GString *jid = g_string_new(barejid);
-    if (resource) {
-        g_string_append(jid, "/");
-        g_string_append(jid, resource);
-    }
-
-    if (prefs_get_boolean(PREF_STATES) && send_state) {
-        message = stanza_create_message(ctx, jid->str, STANZA_TYPE_CHAT, msg, STANZA_NAME_ACTIVE);
+    ChatSession *session = chat_session_get(barejid);
+    if (session) {
+        Jid *jidp = jid_create_from_bare_and_resource(session->barejid, session->resource);
+        message = stanza_create_message(ctx, jidp->fulljid, STANZA_TYPE_CHAT, msg, NULL);
+        jid_destroy(jidp);
     } else {
-        message = stanza_create_message(ctx, jid->str, STANZA_TYPE_CHAT, msg, NULL);
+        message = stanza_create_message(ctx, barejid, STANZA_TYPE_CHAT, msg, NULL);
     }
 
     xmpp_send(conn, message);
     xmpp_stanza_release(message);
-    g_string_free(jid, TRUE);
 }
 
 void
@@ -469,28 +461,36 @@ _chat_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
         GTimeVal tv_stamp;
         gboolean delayed = stanza_get_delay(stanza, &tv_stamp);
 
-        // deal with chat states if recipient supports them
-        if (!delayed) {
-            // determine chatstate support of recipient
-            if (stanza_contains_chat_state(stanza)) {
-                chat_session_on_incoming_message(jid->barejid, jid->resourcepart, TRUE);
+        // handle chat sessions
+        if (!delayed && jid->resourcepart) {
+            gboolean recipient_gone = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL;
+            if (recipient_gone) {
+                chat_session_remove(jid->barejid);
             } else {
-                chat_session_on_incoming_message(jid->barejid, jid->resourcepart, FALSE);
-            }
-
-            if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL) {
-                handle_typing(jid->barejid);
-            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL) {
-                handle_gone(jid->barejid);
-            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL) {
-                // do something
-            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_INACTIVE) != NULL) {
-                // do something
-            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ACTIVE) != NULL) {
-                // do something
+                chat_session_on_recipient_activity(jid->barejid, jid->resourcepart);
             }
         }
 
+//            // determine chatstate support of recipient
+//            if (stanza_contains_chat_state(stanza)) {
+//                chat_session_on_incoming_message(jid->barejid, jid->resourcepart, TRUE);
+//            } else {
+//                chat_session_on_incoming_message(jid->barejid, jid->resourcepart, FALSE);
+//            }
+//
+//            if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_COMPOSING) != NULL) {
+//                handle_typing(jid->barejid);
+//            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_GONE) != NULL) {
+//                handle_gone(jid->barejid);
+//            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_PAUSED) != NULL) {
+//                // do something
+//            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_INACTIVE) != NULL) {
+//                // do something
+//            } else if (xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ACTIVE) != NULL) {
+//                // do something
+//            }
+//        }
+
         // check for and deal with message
         xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_BODY);
         if (body != NULL) {