messenger-cli

Command-line user interface for GNUnet Messenger
Log | Files | Refs | README | LICENSE

commit 2a72f770ecf2f6243fada17c6c31d4dd085eb911
parent 04b106bf09b8ef90418811ed583d1c4ebd5fdaf5
Author: TheJackiMonster <thejackimonster@gmail.com>
Date:   Fri,  9 Sep 2022 15:36:34 +0200

Added lines showing dates between chat messages

Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>

Diffstat:
Msrc/ui/accounts.h | 3+++
Msrc/ui/chats.h | 3+++
Msrc/ui/list_input.h | 127++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/ui/lobby_create_dialog.h | 3+++
Msrc/ui/members.h | 3+++
Msrc/ui/messages.c | 110++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/ui/messages.h | 6++++++
7 files changed, 160 insertions(+), 95 deletions(-)

diff --git a/src/ui/accounts.h b/src/ui/accounts.h @@ -40,6 +40,9 @@ typedef struct UI_ACCOUNTS_Handle { WINDOW *window; + int line_prev; + int line_next; + int line_index; int line_offset; int line_selected; diff --git a/src/ui/chats.h b/src/ui/chats.h @@ -42,6 +42,9 @@ typedef struct UI_CHATS_Handle { WINDOW *window; + int line_prev; + int line_next; + int line_index; int line_offset; int line_selected; diff --git a/src/ui/list_input.h b/src/ui/list_input.h @@ -29,80 +29,87 @@ #include <stdlib.h> #define list_input_reset(list) { \ - (list)->line_index = 0; \ - (list)->selected = 0; \ + (list)->line_prev = 0; \ + (list)->line_next = 0; \ + (list)->line_index = 0; \ + (list)->selected = 0; \ } -#define list_input_select(list, line_width, item) { \ - const bool selected = ( \ - ((list)->line_selected >= (list)->line_index) && \ - ((list)->line_selected < (list)->line_index + line_width) \ - ); \ - \ - (list)->line_index += line_width; \ - \ - if (selected) \ - (list)->selected = item; \ +#define list_input_select(list, line_width, item) { \ + const bool selected = ( \ + ((list)->line_selected >= (list)->line_index) && \ + ((list)->line_selected < (list)->line_index + (line_width)) \ + ); \ + \ + if ((!selected) && ((list)->line_selected > (list)->line_index)) \ + (list)->line_prev = (list)->line_index; \ + \ + (list)->line_index += (line_width); \ + \ + if (selected) { \ + (list)->line_next = (list)->line_index; \ + (list)->selected = item; \ + } \ } #define list_input_event(list, key) { \ - int count = (list)->line_index; \ - \ - switch (key) \ - { \ - case KEY_UP: \ - { \ - (list)->line_selected--; \ - break; \ - } \ - case KEY_DOWN: \ - { \ - (list)->line_selected++; \ - break; \ - } \ - default: \ - break; \ - } \ - \ - if ((list)->line_selected < 0) \ - (list)->line_selected = 0; \ - else if ((list)->line_selected >= count) \ - (list)->line_selected = count - 1; \ - \ - if ((list)->window) \ - { \ - const int height = getmaxy((list)->window); \ + int count = (list)->line_index; \ + \ + switch (key) \ + { \ + case KEY_UP: \ + { \ + (list)->line_selected = (list)->line_prev; \ + break; \ + } \ + case KEY_DOWN: \ + { \ + (list)->line_selected = (list)->line_next; \ + break; \ + } \ + default: \ + break; \ + } \ + \ + if ((list)->line_selected < 0) \ + (list)->line_selected = 0; \ + else if ((list)->line_selected >= count) \ + (list)->line_selected = count - 1; \ + \ + if ((list)->window) \ + { \ + const int height = getmaxy((list)->window); \ const int y = (list)->line_selected - (list)->line_offset; \ - \ - if (y < 0) \ + \ + if (y < 0) \ (list)->line_offset += y; \ - else if (y + 1 >= height) \ + else if (y + 1 >= height) \ (list)->line_offset += y + 1 - height; \ - \ + \ if ((list)->line_offset < 0) \ (list)->line_offset = 0; \ else if ((list)->line_offset >= count) \ (list)->line_offset = count - 1; \ - } \ + } \ } -#define list_input_print_(list, line_width, yes_res, no_res) \ - const bool selected = ( \ - ((list)->line_selected >= (list)->line_index) && \ - ((list)->line_selected < (list)->line_index + line_width) \ - ); \ - \ - const int y = (list)->line_index - (list)->line_offset; { \ - \ - (list)->line_index += line_width; \ - \ - if (y + line_width < 1) \ - return yes_res; \ - \ - const int height = getmaxy((list)->window); \ - \ - if (y >= height) \ - return no_res; \ +#define list_input_print_(list, line_width, yes_res, no_res) \ + const bool selected = ( \ + ((list)->line_selected >= (list)->line_index) && \ + ((list)->line_selected < (list)->line_index + (line_width)) \ + ); \ + \ + const int y = (list)->line_index - (list)->line_offset; { \ + \ + (list)->line_index += (line_width); \ + \ + if (y + (line_width) < 1) \ + return yes_res; \ + \ + const int height = getmaxy((list)->window); \ + \ + if (y >= height) \ + return no_res; \ } #define list_input_print_gnunet(list, line_width) \ diff --git a/src/ui/lobby_create_dialog.h b/src/ui/lobby_create_dialog.h @@ -39,6 +39,9 @@ typedef struct UI_LOBBY_CREATE_DIALOG_Handle WINDOW *window; WINDOW **win; + int line_prev; + int line_next; + int line_index; int line_offset; int line_selected; diff --git a/src/ui/members.h b/src/ui/members.h @@ -50,6 +50,9 @@ typedef struct UI_MEMBERS_Handle UI_MEMBERS_List *head; UI_MEMBERS_List *tail; + int line_prev; + int line_next; + int line_index; int line_offset; int line_selected; diff --git a/src/ui/messages.c b/src/ui/messages.c @@ -29,6 +29,26 @@ #include "../application.h" #include "../util.h" +struct tm* +_messages_new_day(time_t* current_time, + const time_t* timestamp) +{ + struct tm* ts = localtime(timestamp); + + ts->tm_sec = 0; + ts->tm_min = 0; + ts->tm_hour = 0; + + const time_t date_time = timelocal(ts); + + if (date_time <= *current_time) { + return NULL; + } + + *current_time = date_time; + return ts; +} + void _messages_handle_message(UI_MESSAGES_Handle *messages) { @@ -65,11 +85,17 @@ messages_event(UI_MESSAGES_Handle *messages, int key) { list_input_reset(messages); + messages->line_time = 0; UI_MESSAGES_List *element = messages->head; while (element) { - list_input_select(messages, 1, element->message); + struct tm *ts = _messages_new_day( + &(messages->line_time), + &(element->timestamp) + ); + + list_input_select(messages, ts? 2 : 1, element->message); element = element->next; } @@ -113,12 +139,11 @@ messages_event(UI_MESSAGES_Handle *messages, void _messages_iterate_print(UI_MESSAGES_Handle *messages, + const time_t* timestamp, const struct GNUNET_CHAT_Message *message) { enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message); - list_input_print(messages, 1); - struct GNUNET_CHAT_Contact *sender = GNUNET_CHAT_message_get_sender(message); const char *name = sender? GNUNET_CHAT_contact_get_name(sender) : NULL; @@ -126,29 +151,35 @@ _messages_iterate_print(UI_MESSAGES_Handle *messages, const struct GNUNET_CHAT_File *file = GNUNET_CHAT_message_get_file(message); - struct GNUNET_TIME_Absolute abs_time = GNUNET_CHAT_message_get_timestamp( - message - ); + struct tm* ts = localtime(timestamp); + char time_buf [255]; - struct GNUNET_TIME_Timestamp timestamp = GNUNET_TIME_absolute_to_timestamp( - abs_time - ); + strftime(time_buf, sizeof(time_buf), "%H:%M", ts); - const time_t s_after_epoch = ( - GNUNET_TIME_timestamp_to_s(timestamp) - ); + ts = _messages_new_day(&(messages->line_time), timestamp); - struct tm* ts = localtime(&s_after_epoch); - char time_buf [255]; + list_input_print(messages, ts? 2 : 1); + wmove(messages->window, y, 0); - strftime(time_buf, sizeof(time_buf), "%H:%M", ts); + if (ts) { + char date_buf [255]; + + strftime(date_buf, sizeof(date_buf), "%x", ts); + + const int width = getmaxx(messages->window); + + whline(messages->window, '-', width); + wmove(messages->window, y, 8); + + wprintw(messages->window, " %s ", date_buf); + wmove(messages->window, y+1, 0); + } const int attrs_select = A_BOLD; if (selected) wattron(messages->window, attrs_select); - wmove(messages->window, y, 0); - wprintw(messages->window, "%s | ", time_buf); + wprintw(messages->window, " %s | ", time_buf); switch (kind) { case GNUNET_CHAT_KIND_JOIN: @@ -207,7 +238,6 @@ _messages_iterate_print(UI_MESSAGES_Handle *messages, break; } - if (selected) wattroff(messages->window, attrs_select); } @@ -218,12 +248,14 @@ messages_print(UI_MESSAGES_Handle *messages) return; list_input_reset(messages); + messages->line_time = 0; + werase(messages->window); UI_MESSAGES_List *element = messages->head; while (element) { - _messages_iterate_print(messages, element->message); + _messages_iterate_print(messages, &(element->timestamp), element->message); element = element->next; } @@ -278,17 +310,12 @@ _message_compare_timestamps(UNUSED void *cls, UI_MESSAGES_List *list0, UI_MESSAGES_List *list1) { - struct GNUNET_TIME_Absolute time0, time1; - if ((!list0) || (!list1)) return 0; - time0 = GNUNET_CHAT_message_get_timestamp(list0->message); - time1 = GNUNET_CHAT_message_get_timestamp(list1->message); - - if (GNUNET_TIME_absolute_cmp(time0, >, time1)) + if (list0->timestamp > list1->timestamp) return -1; - else if (GNUNET_TIME_absolute_cmp(time0, <, time1)) + else if (list0->timestamp < list1->timestamp) return +1; else return 0; @@ -309,19 +336,33 @@ messages_add(UI_MESSAGES_Handle *messages, break; } - const int height = getmaxy(messages->window); - const int line_height = height - 2; - - int count = 0; + list_input_reset(messages); + messages->line_time = 0; UI_MESSAGES_List *element = messages->head; while (element) { - count++; + struct tm *ts = _messages_new_day( + &(messages->line_time), + &(element->timestamp) + ); + + list_input_select(messages, ts? 2 : 1, element->message); element = element->next; } + list_input_select(messages, 1, NULL); + + const struct GNUNET_TIME_Absolute abs_time = ( + GNUNET_CHAT_message_get_timestamp(message) + ); + + const struct GNUNET_TIME_Timestamp timestamp = ( + GNUNET_TIME_absolute_to_timestamp(abs_time) + ); + element = GNUNET_new(UI_MESSAGES_List); + element->timestamp = GNUNET_TIME_timestamp_to_s(timestamp); element->message = message; GNUNET_CONTAINER_DLL_insert_sorted( @@ -333,11 +374,10 @@ messages_add(UI_MESSAGES_Handle *messages, element ); - if (messages->line_selected >= count) - messages->line_selected = count + 1; + list_input_select(messages, 1, NULL); - if ((line_height > 0) && (messages->line_offset + line_height >= count)) - messages->line_offset = count + 1 - line_height; + if (!(messages->selected)) + list_input_event(messages, KEY_DOWN); } void diff --git a/src/ui/messages.h b/src/ui/messages.h @@ -36,6 +36,8 @@ struct MESSENGER_Application; typedef struct UI_MESSAGES_List { + time_t timestamp; + const struct GNUNET_CHAT_Message *message; struct UI_MESSAGES_List *prev; @@ -51,9 +53,13 @@ typedef struct UI_MESSAGES_Handle UI_MESSAGES_List *head; UI_MESSAGES_List *tail; + int line_prev; + int line_next; + int line_index; int line_offset; int line_selected; + time_t line_time; const struct GNUNET_CHAT_Message *selected;