From 14f25992c39cc5e3ec04f3a053f38bee9c77cf4e Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Fri, 13 Dec 2019 12:05:24 +0100 Subject: [PATCH 1/4] Initial work on last-read-position feature Print dashes on the position we last left off in a chat window. So far the number of dashes is hardcoded, and the feature only works in chat windows. Regards https://github.com/profanity-im/profanity/issues/1238 --- src/ui/buffer.c | 13 +++++++++++++ src/ui/buffer.h | 1 + src/ui/chatwin.c | 1 + src/ui/core.c | 8 ++++++++ src/ui/window.c | 33 +++++++++++++++++++++++++++++++++ src/ui/window.h | 3 +++ 6 files changed, 59 insertions(+) diff --git a/src/ui/buffer.c b/src/ui/buffer.c index a4ae41da..916aba1a 100644 --- a/src/ui/buffer.c +++ b/src/ui/buffer.c @@ -106,6 +106,19 @@ buffer_append(ProfBuff buffer, const char show_char, int pad_indent, GDateTime * buffer->entries = g_slist_append(buffer->entries, e); } +void +buffer_remove_entry_by_id(ProfBuff buffer, const char *const id) +{ + GSList *entries = buffer->entries; + while (entries) { + ProfBuffEntry *entry = entries->data; + if (entry->id && (g_strcmp0(entry->id, id) == 0)) { + buffer->entries = g_slist_delete_link(buffer->entries, entries); + } + entries = g_slist_next(entries); + } +} + gboolean buffer_mark_received(ProfBuff buffer, const char *const id) { diff --git a/src/ui/buffer.h b/src/ui/buffer.h index 67cd6d5b..10151d17 100644 --- a/src/ui/buffer.h +++ b/src/ui/buffer.h @@ -64,6 +64,7 @@ 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 from, const char *const message, DeliveryReceipt *receipt, const char *const id); +void buffer_remove_entry_by_id(ProfBuff buffer, const char *const id); 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 d92f0de4..8faf4934 100644 --- a/src/ui/chatwin.c +++ b/src/ui/chatwin.c @@ -286,6 +286,7 @@ chatwin_incoming_msg(ProfChatWin *chatwin, ProfMessage *message, gboolean win_cr } } + win_insert_last_read_position_marker((ProfWin*)chatwin, chatwin->barejid); win_print_incoming(window, display_name, message); } diff --git a/src/ui/core.c b/src/ui/core.c index 8c7eca2e..6bf43d94 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -656,6 +656,14 @@ ui_focus_win(ProfWin *window) cmd_ac_remove_form_fields(confwin->form); } + // TODO: if old win is chatwin; and has lastreadline; then remove that line + if (old_current->type == WIN_CHAT) { + ProfChatWin *chatwin = (ProfChatWin*)old_current; + assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); + //win_update_entry_message_real(old_current, chatwin->barejid, "$$$"); + win_remove_entry_message(old_current, chatwin->barejid); + } + if (window->type == WIN_CONFIG) { ProfConfWin *confwin = (ProfConfWin*)window; cmd_ac_add_form_fields(confwin->form); diff --git a/src/ui/window.c b/src/ui/window.c index 2a76496c..e592aa2e 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -1354,6 +1354,13 @@ win_update_entry_message(ProfWin *window, const char *const id, const char *cons } } +void +win_remove_entry_message(ProfWin *window, const char *const id) +{ + buffer_remove_entry_by_id(window->layout->buffer, id); + win_redraw(window); +} + void win_newline(ProfWin *window) { @@ -1809,3 +1816,29 @@ win_handle_command_exec_result_note(ProfWin *window, const char *const type, con assert(window != NULL); win_println(window, THEME_DEFAULT, '!', value); } + +void +win_print_separator(ProfWin *window) +{ + int cols = getmaxx(window->layout->win); + + int i; + for (i=1; ilayout->win, "-"); + } +} + +void +win_insert_last_read_position_marker(ProfWin *window, char* id) +{ + GDateTime *time = g_date_time_new_now_local(); + + buffer_append(window->layout->buffer, ' ', 0, time, 0, THEME_TEXT, NULL, "-----", NULL, id); + // can we leave this? TODO + // win_print_separator(window); + //_win_print(window, '-', 0, time, 0, THEME_TEXT, NULL, "---", NULL); + win_redraw(window); + + g_date_time_unref(time); +} + diff --git a/src/ui/window.h b/src/ui/window.h index 79def390..b1f9a4af 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -90,4 +90,7 @@ void win_page_down(ProfWin *window); void win_sub_page_down(ProfWin *window); void win_sub_page_up(ProfWin *window); +void win_insert_last_read_position_marker(ProfWin *window, char* id); +void win_remove_entry_message(ProfWin *window, const char *const id); + #endif From a1ed37953cfcfb81533f90e68e0c388ff2def788 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Fri, 13 Dec 2019 12:19:07 +0100 Subject: [PATCH 2/4] separator: print trackbar across the whole line Use the whole line. We do this in win_redraw() so upon terminal size change it still matches. Regards https://github.com/profanity-im/profanity/issues/1238 --- src/ui/window.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/ui/window.c b/src/ui/window.c index e592aa2e..28c76348 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -1650,6 +1650,18 @@ _win_print_wrapped(WINDOW *win, const char *const message, size_t indent, int pa free(word); } +void +win_print_separator(ProfWin *window) +{ + int cols = getmaxx(window->layout->win); + + int i; + for (i=1; ilayout->win, "-"); + } + wprintw(window->layout->win, "\n"); +} + void win_redraw(ProfWin *window) { @@ -1659,7 +1671,12 @@ win_redraw(ProfWin *window) for (i = 0; i < size; i++) { ProfBuffEntry *e = buffer_get_entry(window->layout->buffer, i); - _win_print(window, e->show_char, e->pad_indent, e->time, e->flags, e->theme_item, e->from, e->message, e->receipt); + + if (e->from == NULL && e->message && e->message[0] == '-') { + win_print_separator(window); + } else { + _win_print(window, e->show_char, e->pad_indent, e->time, e->flags, e->theme_item, e->from, e->message, e->receipt); + } } } @@ -1817,23 +1834,12 @@ win_handle_command_exec_result_note(ProfWin *window, const char *const type, con win_println(window, THEME_DEFAULT, '!', value); } -void -win_print_separator(ProfWin *window) -{ - int cols = getmaxx(window->layout->win); - - int i; - for (i=1; ilayout->win, "-"); - } -} - void win_insert_last_read_position_marker(ProfWin *window, char* id) { GDateTime *time = g_date_time_new_now_local(); - buffer_append(window->layout->buffer, ' ', 0, time, 0, THEME_TEXT, NULL, "-----", NULL, id); + buffer_append(window->layout->buffer, ' ', 0, time, 0, THEME_TEXT, NULL, "-", NULL, id); // can we leave this? TODO // win_print_separator(window); //_win_print(window, '-', 0, time, 0, THEME_TEXT, NULL, "---", NULL); From e2b44a69bd445e375664c6a3e85146b81fc088ab Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Fri, 13 Dec 2019 12:47:27 +0100 Subject: [PATCH 3/4] separator: Print only one for each chat window So far we printed one after the last received message, which doesn't make much sense of course. Now only print one if there is not already one present. --- src/ui/window.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/ui/window.c b/src/ui/window.c index 28c76348..c062e694 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -1673,8 +1673,10 @@ win_redraw(ProfWin *window) ProfBuffEntry *e = buffer_get_entry(window->layout->buffer, i); if (e->from == NULL && e->message && e->message[0] == '-') { + // just an indicator to print the separator not the actual message win_print_separator(window); } else { + // regular thing to print _win_print(window, e->show_char, e->pad_indent, e->time, e->flags, e->theme_item, e->from, e->message, e->receipt); } } @@ -1837,12 +1839,26 @@ win_handle_command_exec_result_note(ProfWin *window, const char *const type, con void win_insert_last_read_position_marker(ProfWin *window, char* id) { + int i, size; + size = buffer_size(window->layout->buffer); + + // TODO: this is somewhat costly. We should improve this later. + // check if we already have a separator present + for (i = 0; i < size; i++) { + ProfBuffEntry *e = buffer_get_entry(window->layout->buffer, i); + + // if yes, don't print a new one + if (e->id && (g_strcmp0(e->id, id) == 0)) { + return; + } + } + GDateTime *time = g_date_time_new_now_local(); + // the separator will actually be print in win_redraw(). + // this only puts it in the buffer and win_redraw() will interpret it. + // so that we have the correct length even when resizing. buffer_append(window->layout->buffer, ' ', 0, time, 0, THEME_TEXT, NULL, "-", NULL, id); - // can we leave this? TODO - // win_print_separator(window); - //_win_print(window, '-', 0, time, 0, THEME_TEXT, NULL, "---", NULL); win_redraw(window); g_date_time_unref(time); From 3036834ec83d2433bf5b1b4408776d771554878c Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Fri, 13 Dec 2019 13:13:02 +0100 Subject: [PATCH 4/4] separator: Enable for MUC and PRIVWIN too Fix https://github.com/profanity-im/profanity/issues/1238 --- src/ui/core.c | 35 ++++++++++++++++++++++++++--------- src/ui/mucwin.c | 2 ++ src/ui/privwin.c | 1 + 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/ui/core.c b/src/ui/core.c index 6bf43d94..545c508f 100644 --- a/src/ui/core.c +++ b/src/ui/core.c @@ -651,24 +651,41 @@ ui_focus_win(ProfWin *window) } ProfWin *old_current = wins_get_current(); + if (old_current->type == WIN_CONFIG) { ProfConfWin *confwin = (ProfConfWin*)old_current; cmd_ac_remove_form_fields(confwin->form); } - - // TODO: if old win is chatwin; and has lastreadline; then remove that line - if (old_current->type == WIN_CHAT) { - ProfChatWin *chatwin = (ProfChatWin*)old_current; - assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK); - //win_update_entry_message_real(old_current, chatwin->barejid, "$$$"); - win_remove_entry_message(old_current, chatwin->barejid); - } - if (window->type == WIN_CONFIG) { ProfConfWin *confwin = (ProfConfWin*)window; cmd_ac_add_form_fields(confwin->form); } + // check for trackbar last position separator + switch (old_current->type) + { + case WIN_CHAT: + { + ProfChatWin *chatwin = (ProfChatWin*)old_current; + win_remove_entry_message(old_current, chatwin->barejid); + break; + } + case WIN_MUC: + { + ProfMucWin *mucwin = (ProfMucWin*)old_current; + win_remove_entry_message(old_current, mucwin->roomjid); + break; + } + case WIN_PRIVATE: + { + ProfPrivateWin *privwin = (ProfPrivateWin*)old_current; + win_remove_entry_message(old_current, privwin->fulljid); + break; + } + default: + break; + } + int i = wins_get_num(window); wins_set_current_by_num(i); diff --git a/src/ui/mucwin.c b/src/ui/mucwin.c index f2d1a946..66de0dba 100644 --- a/src/ui/mucwin.c +++ b/src/ui/mucwin.c @@ -551,6 +551,8 @@ mucwin_incoming_msg(ProfMucWin *mucwin, ProfMessage *message, GSList *mentions, ch = prefs_get_omemo_char(); } + win_insert_last_read_position_marker((ProfWin*)mucwin, mucwin->roomjid); + if (g_slist_length(mentions) > 0) { _mucwin_print_mention(window, message->plain, message->jid->resourcepart, mynick, mentions, &ch, flags); } else if (triggers) { diff --git a/src/ui/privwin.c b/src/ui/privwin.c index b888041a..4befc325 100644 --- a/src/ui/privwin.c +++ b/src/ui/privwin.c @@ -69,6 +69,7 @@ privwin_incoming_msg(ProfPrivateWin *privatewin, ProfMessage *message) } else { status_bar_new(num, WIN_PRIVATE, privatewin->fulljid); cons_show_incoming_private_message(jidp->resourcepart, jidp->barejid, num, privatewin->unread); + win_insert_last_read_position_marker((ProfWin*)privatewin, privatewin->fulljid); win_print_incoming(window, jidp->resourcepart, message); privatewin->unread++;