about summary refs log tree commit diff stats
path: root/src/ui
diff options
context:
space:
mode:
authorMichael Vetter <jubalh@iodoru.org>2022-10-21 13:24:46 +0200
committerMichael Vetter <jubalh@iodoru.org>2022-10-21 13:30:43 +0200
commit3bdc14dbcf1114fa1ea68cd6f455eecf90a9ac5e (patch)
tree714be508d95655b16565bc8431e44f5006c7e8c2 /src/ui
parent980fc189cd19486102e7638bb5d03bfe0dd7be62 (diff)
parentd692aec32ed22377c34efd94845b3201b5a12217 (diff)
downloadprofani-tty-3bdc14dbcf1114fa1ea68cd6f455eecf90a9ac5e.tar.gz
Merge MAM improvements from #1724
I think this PR already solves and improves the MAM situation a lot.

What's @MarcoPolo-PasTonMolo still wanted to do in this branch is:
* MAM for mucs
* Check if url and quotes autocompletion works fine
* Check if the api still works fine
* Resolve conflicts

Conflicts are solved with this commit.

MAM for mucs can be another feature PR.

The rest we can check while being on master. And more people can help
testing.
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/buffer.c36
-rw-r--r--src/ui/buffer.h2
-rw-r--r--src/ui/chatwin.c59
-rw-r--r--src/ui/ui.h1
-rw-r--r--src/ui/window.c70
-rw-r--r--src/ui/window.h3
6 files changed, 158 insertions, 13 deletions
diff --git a/src/ui/buffer.c b/src/ui/buffer.c
index e38aaaec..553dc325 100644
--- a/src/ui/buffer.c
+++ b/src/ui/buffer.c
@@ -111,6 +111,34 @@ buffer_append(ProfBuff buffer, const char* show_char, int pad_indent, GDateTime*
 }
 
 void
+buffer_prepend(ProfBuff buffer, const char* show_char, int pad_indent, GDateTime* time, int flags, theme_item_t theme_item, const char* const display_from, const char* const from_jid, const char* const message, DeliveryReceipt* receipt, const char* const id)
+{
+    ProfBuffEntry* e = malloc(sizeof(struct prof_buff_entry_t));
+    e->show_char = strdup(show_char);
+    e->pad_indent = pad_indent;
+    e->flags = flags;
+    e->theme_item = theme_item;
+    e->time = g_date_time_ref(time);
+    e->display_from = display_from ? strdup(display_from) : NULL;
+    e->from_jid = from_jid ? strdup(from_jid) : NULL;
+    e->message = strdup(message);
+    e->receipt = receipt;
+    if (id) {
+        e->id = strdup(id);
+    } else {
+        e->id = NULL;
+    }
+
+    if (g_slist_length(buffer->entries) == BUFF_SIZE) {
+        GSList* last = g_slist_last(buffer->entries);
+        _free_entry(last->data);
+        buffer->entries = g_slist_delete_link(buffer->entries, last);
+    }
+
+    buffer->entries = g_slist_prepend(buffer->entries, e);
+}
+
+void
 buffer_remove_entry_by_id(ProfBuff buffer, const char* const id)
 {
     GSList* entries = buffer->entries;
@@ -125,6 +153,14 @@ buffer_remove_entry_by_id(ProfBuff buffer, const char* const id)
     }
 }
 
+void
+buffer_remove_entry(ProfBuff buffer, int entry)
+{
+    GSList* node = g_slist_nth(buffer->entries, entry);
+    _free_entry(node->data);
+    buffer->entries = g_slist_delete_link(buffer->entries, node);
+}
+
 gboolean
 buffer_mark_received(ProfBuff buffer, const char* const id)
 {
diff --git a/src/ui/buffer.h b/src/ui/buffer.h
index 5d363902..535df882 100644
--- a/src/ui/buffer.h
+++ b/src/ui/buffer.h
@@ -70,7 +70,9 @@ typedef struct prof_buff_t* ProfBuff;
 ProfBuff buffer_create();
 void buffer_free(ProfBuff buffer);
 void buffer_append(ProfBuff buffer, const char* show_char, int pad_indent, GDateTime* time, int flags, theme_item_t theme_item, const char* const display_from, const char* const barejid, const char* const message, DeliveryReceipt* receipt, const char* const id);
+void buffer_prepend(ProfBuff buffer, const char* show_char, int pad_indent, GDateTime* time, int flags, theme_item_t theme_item, const char* const display_from, const char* const barejid, const char* const message, DeliveryReceipt* receipt, const char* const id);
 void buffer_remove_entry_by_id(ProfBuff buffer, const char* const id);
+void buffer_remove_entry(ProfBuff buffer, int entry);
 int buffer_size(ProfBuff buffer);
 ProfBuffEntry* buffer_get_entry(ProfBuff buffer, int entry);
 ProfBuffEntry* buffer_get_entry_by_id(ProfBuff buffer, const char* const id);
diff --git a/src/ui/chatwin.c b/src/ui/chatwin.c
index 32fd3553..93f3ce97 100644
--- a/src/ui/chatwin.c
+++ b/src/ui/chatwin.c
@@ -96,7 +96,7 @@ chatwin_new(const char* const barejid)
     ProfWin* window = wins_new_chat(barejid);
     ProfChatWin* chatwin = (ProfChatWin*)window;
 
-    if (!prefs_get_boolean(PREF_MAM) && prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY)) {
+    if (!prefs_get_boolean(PREF_MAM) && (prefs_get_boolean(PREF_CHLOG) && prefs_get_boolean(PREF_HISTORY))) {
         _chatwin_history(chatwin, barejid);
     }
 
@@ -146,7 +146,8 @@ chatwin_new(const char* const barejid)
     }
 
     if (prefs_get_boolean(PREF_MAM)) {
-        iq_mam_request(chatwin);
+        iq_mam_request(chatwin, NULL);
+        win_print_loading_history(window);
     }
 
     return chatwin;
@@ -333,7 +334,7 @@ chatwin_incoming_msg(ProfChatWin* chatwin, ProfMessage* message, gboolean win_cr
     free(mybarejid);
 
     gboolean is_current = wins_is_current(window);
-    gboolean notify = prefs_do_chat_notify(is_current);
+    gboolean notify = prefs_do_chat_notify(is_current) && !message->is_mam;
 
     // currently viewing chat window with sender
     if (wins_is_current(window)) {
@@ -344,13 +345,16 @@ chatwin_incoming_msg(ProfChatWin* chatwin, ProfMessage* message, gboolean win_cr
         // not currently viewing chat window with sender
     } else {
         status_bar_new(num, WIN_CHAT, chatwin->barejid);
-        cons_show_incoming_message(display_name, num, chatwin->unread, window);
 
-        if (prefs_get_boolean(PREF_FLASH)) {
-            flash();
-        }
+        if (!message->is_mam) {
+            cons_show_incoming_message(display_name, num, chatwin->unread, window);
+
+            if (prefs_get_boolean(PREF_FLASH)) {
+                flash();
+            }
 
-        chatwin->unread++;
+            chatwin->unread++;
+        }
 
         // TODO: so far we don't ask for MAM when incoming message occurs.
         // Need to figure out:
@@ -379,7 +383,7 @@ chatwin_incoming_msg(ProfChatWin* chatwin, ProfMessage* message, gboolean win_cr
     wins_add_urls_ac(window, message);
     wins_add_quotes_ac(window, message->plain);
 
-    if (prefs_get_boolean(PREF_BEEP)) {
+    if (prefs_get_boolean(PREF_BEEP) && !message->is_mam) {
         beep();
     }
 
@@ -572,7 +576,7 @@ static void
 _chatwin_history(ProfChatWin* chatwin, const char* const contact_barejid)
 {
     if (!chatwin->history_shown) {
-        GSList* history = log_database_get_previous_chat(contact_barejid);
+        GSList* history = log_database_get_previous_chat(contact_barejid, NULL, NULL, FALSE, FALSE);
         GSList* curr = history;
 
         while (curr) {
@@ -591,6 +595,41 @@ _chatwin_history(ProfChatWin* chatwin, const char* const contact_barejid)
     }
 }
 
+// Print history starting from start_time to end_time if end_time is null the
+// first entry's timestamp in the buffer is used. Flip true to prepend to buffer.
+// Timestamps should be in iso8601
+gboolean
+chatwin_db_history(ProfChatWin* chatwin, char* start_time, char* end_time, gboolean flip)
+{
+    if (!end_time) {
+        end_time = buffer_size(((ProfWin*)chatwin)->layout->buffer) == 0 ? NULL : g_date_time_format_iso8601(buffer_get_entry(((ProfWin*)chatwin)->layout->buffer, 0)->time);
+    }
+
+    GSList* history = log_database_get_previous_chat(chatwin->barejid, start_time, end_time, !flip, flip);
+    gboolean has_items = g_slist_length(history) != 0;
+    GSList* curr = history;
+
+    while (curr) {
+        ProfMessage* msg = curr->data;
+        char* msg_plain = msg->plain;
+        msg->plain = plugins_pre_chat_message_display(msg->from_jid->barejid, msg->from_jid->resourcepart, msg->plain);
+        // This is dirty workaround for memory leak. We reassign msg->plain above so have to free previous object
+        // TODO: Make a better solution, for example, pass msg object to the function and it will replace msg->plain properly if needed.
+        free(msg_plain);
+        if (flip) {
+            win_print_old_history((ProfWin*)chatwin, msg);
+        } else {
+            win_print_history((ProfWin*)chatwin, msg);
+        }
+        curr = g_slist_next(curr);
+    }
+
+    g_slist_free_full(history, (GDestroyNotify)message_free);
+    win_redraw((ProfWin*)chatwin);
+
+    return has_items;
+}
+
 static void
 _chatwin_set_last_message(ProfChatWin* chatwin, const char* const id, const char* const message)
 {
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 78632aa0..92a40843 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -145,6 +145,7 @@ void chatwin_set_incoming_char(ProfChatWin* chatwin, const char* const ch);
 void chatwin_unset_incoming_char(ProfChatWin* chatwin);
 void chatwin_set_outgoing_char(ProfChatWin* chatwin, const char* const ch);
 void chatwin_unset_outgoing_char(ProfChatWin* chatwin);
+gboolean chatwin_db_history(ProfChatWin* chatwin, char* start_time, char* end_time, gboolean flip);
 
 // MUC window
 ProfMucWin* mucwin_new(const char* const barejid);
diff --git a/src/ui/window.c b/src/ui/window.c
index fbff3374..269affbd 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -61,6 +61,7 @@
 #include "xmpp/xmpp.h"
 #include "xmpp/roster_list.h"
 #include "xmpp/connection.h"
+#include "database.h"
 
 #define CONS_WIN_TITLE "Profanity. Type /help for help information."
 #define XML_WIN_TITLE  "XML Console"
@@ -637,6 +638,19 @@ win_page_up(ProfWin* window)
 
     *page_start -= page_space;
 
+    if (*page_start == -page_space && window->type == WIN_CHAT) {
+        ProfChatWin* chatwin = (ProfChatWin*) window;
+        ProfBuffEntry* first_entry = buffer_size(window->layout->buffer) != 0 ? buffer_get_entry(window->layout->buffer, 0) : NULL;
+
+        // Don't do anything if still fetching mam messages
+        if (first_entry && !(first_entry->theme_item == THEME_ROOMINFO && g_strcmp0(first_entry->message, LOADING_MESSAGE) == 0)) {
+            if (!chatwin_db_history(chatwin, NULL, NULL, TRUE) && prefs_get_boolean(PREF_MAM)) {
+                win_print_loading_history(window);
+                iq_mam_request_older(chatwin);
+            }
+        }
+    }
+
     // went past beginning, show first page
     if (*page_start < 0)
         *page_start = 0;
@@ -660,6 +674,20 @@ win_page_down(ProfWin* window)
 
     *page_start += page_space;
 
+    // Scrolled down after reaching the bottom of the page
+    if ((*page_start == y || (*page_start == page_space && *page_start >= y)) && window->type == WIN_CHAT) {
+        int bf_size = buffer_size(window->layout->buffer);
+        if (bf_size > 0) {
+            char* start = g_date_time_format_iso8601(buffer_get_entry(window->layout->buffer, bf_size - 1)->time);
+            GDateTime* now = g_date_time_new_now_local();
+            char* end = g_date_time_format_iso8601(now);
+            chatwin_db_history((ProfChatWin*)window, start, end, FALSE);
+
+            g_free(start);
+            g_date_time_unref(now);
+        }
+    }
+
     // only got half a screen, show full screen
     if ((y - (*page_start)) < page_space)
         *page_start = y - page_space;
@@ -1386,8 +1414,8 @@ win_print_incoming(ProfWin* window, const char* const display_name_from, ProfMes
         if (prefs_get_boolean(PREF_CORRECTION_ALLOW) && message->replace_id) {
             _win_correct(window, message->plain, message->id, message->replace_id, message->from_jid->barejid);
         } else {
-            // Prevent duplicate messages when current client is sending a message
-            if (g_strcmp0(message->from_jid->fulljid, connection_get_fulljid()) != 0) {
+            // Prevent duplicate messages when current client is sending a message or if it's mam
+            if (g_strcmp0(message->from_jid->fulljid, connection_get_fulljid()) != 0 && !message->is_mam) {
                 _win_printf(window, enc_char, 0, message->timestamp, flags, THEME_TEXT_THEM, display_name_from, message->from_jid->barejid, message->id, "%s", message->plain);
             }
         }
@@ -1483,6 +1511,34 @@ win_print_history(ProfWin* window, const ProfMessage* const message)
 }
 
 void
+win_print_old_history(ProfWin* window, const ProfMessage* const message)
+{
+    g_date_time_ref(message->timestamp);
+
+    char* display_name;
+    int flags = 0;
+    const char* jid = connection_get_fulljid();
+    Jid* jidp = jid_create(jid);
+
+    if (g_strcmp0(jidp->barejid, message->from_jid->barejid) == 0) {
+        display_name = strdup("me");
+    } else {
+        display_name = roster_get_msg_display_name(message->from_jid->barejid, message->from_jid->resourcepart);
+        flags = NO_ME;
+    }
+
+    jid_destroy(jidp);
+
+    buffer_prepend(window->layout->buffer, "-", 0, message->timestamp, flags, THEME_TEXT_HISTORY, display_name, NULL, message->plain, NULL, NULL);
+    _win_print_internal(window, "-", 0, message->timestamp, flags, THEME_TEXT_HISTORY, display_name, message->plain, NULL);
+
+    free(display_name);
+
+    inp_nonblocking(TRUE);
+    g_date_time_unref(message->timestamp);
+}
+
+void
 win_print(ProfWin* window, theme_item_t theme_item, const char* show_char, const char* const message, ...)
 {
     GDateTime* timestamp = g_date_time_new_now_local();
@@ -1698,7 +1754,6 @@ _win_printf(ProfWin* window, const char* show_char, int pad_indent, GDateTime* t
     g_string_vprintf(fmt_msg, message, arg);
 
     buffer_append(window->layout->buffer, show_char, pad_indent, timestamp, flags, theme_item, display_from, from_jid, fmt_msg->str, NULL, message_id);
-
     _win_print_internal(window, show_char, pad_indent, timestamp, flags, theme_item, display_from, fmt_msg->str, NULL);
 
     inp_nonblocking(TRUE);
@@ -2002,6 +2057,15 @@ win_redraw(ProfWin* window)
     }
 }
 
+void
+win_print_loading_history(ProfWin* window)
+{
+    GDateTime* timestamp = buffer_size(window->layout->buffer) != 0 ? buffer_get_entry(window->layout->buffer, 0)->time : g_date_time_new_now_local();
+    buffer_prepend(window->layout->buffer, "-", 0, timestamp, NO_DATE, THEME_ROOMINFO, NULL, NULL, LOADING_MESSAGE, NULL, NULL);
+    g_date_time_unref(timestamp);
+    win_redraw(window);
+}
+
 gboolean
 win_has_active_subwin(ProfWin* window)
 {
diff --git a/src/ui/window.h b/src/ui/window.h
index 669734ff..c8a5e03a 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -57,6 +57,7 @@
 #include "xmpp/muc.h"
 
 #define PAD_SIZE 1000
+#define LOADING_MESSAGE "Loading older messages ..."
 
 void win_move_to_end(ProfWin* window);
 void win_show_status_string(ProfWin* window, const char* const from,
@@ -71,11 +72,13 @@ void win_print_outgoing_with_receipt(ProfWin* window, const char* show_char, con
 void win_println_incoming_muc_msg(ProfWin* window, char* show_char, int flags, const ProfMessage* const message);
 void win_print_outgoing_muc_msg(ProfWin* window, char* show_char, const char* const me, const char* const id, const char* const replace_id, const char* const message);
 void win_print_history(ProfWin* window, const ProfMessage* const message);
+void win_print_old_history(ProfWin* window, const ProfMessage* const message);
 
 void win_print_http_transfer(ProfWin* window, const char* const message, char* url);
 
 void win_newline(ProfWin* window);
 void win_redraw(ProfWin* window);
+void win_print_loading_history(ProfWin* window);
 int win_roster_cols(void);
 int win_occpuants_cols(void);
 void win_sub_print(WINDOW* win, char* msg, gboolean newline, gboolean wrap, int indent);