From 1803da85c1f385ac6d68ea3b48078bca7a838ad1 Mon Sep 17 00:00:00 2001 From: jfreegman Date: Fri, 19 Nov 2021 22:54:35 -0500 Subject: [PATCH] Refactor unread message flagging This fixes an issue where the interface wasn't able to update when the unread message flag changed. It also cleans up some ugly code --- src/line_info.c | 36 +++++++++++++++++------------ src/line_info.h | 5 +++++ src/message_queue.c | 55 +++++++++++++++++++++++++++++++++------------ src/message_queue.h | 8 +++++++ src/toxic.c | 9 +++++--- src/windows.c | 3 +++ 6 files changed, 85 insertions(+), 31 deletions(-) diff --git a/src/line_info.c b/src/line_info.c index e169d50..dc4d59c 100644 --- a/src/line_info.c +++ b/src/line_info.c @@ -440,6 +440,10 @@ int line_info_add(ToxWindow *self, bool show_timestamp, const char *name1, const new_line->noread_flag = false; new_line->timestamp = get_unix_time(); + if (type == OUT_MSG || type == OUT_ACTION) { + new_line->noread_flag = self->stb->connection == TOX_CONNECTION_NONE; + } + line_info_init_line(self, new_line); hst->queue[hst->queue_size++] = new_line; @@ -475,8 +479,6 @@ static void line_info_check_queue(ToxWindow *self) flag_interface_refresh(); } -#define NOREAD_FLAG_TIMEOUT 5 /* seconds before a sent message with no read receipt is flagged as unread */ - void line_info_print(ToxWindow *self) { ChatContext *ctx = self->chatwin; @@ -577,12 +579,6 @@ void line_info_print(ToxWindow *self) wattroff(win, COLOR_PAIR(RED)); } - if (type == OUT_MSG && !line->read_flag) { - if (timed_out(line->timestamp, NOREAD_FLAG_TIMEOUT)) { - line->noread_flag = true; - } - } - waddch(win, '\n'); break; @@ -602,12 +598,6 @@ void line_info_print(ToxWindow *self) print_ret = print_wrap(win, line, max_x, max_y); wattroff(win, COLOR_PAIR(YELLOW)); - if (type == OUT_ACTION && !line->read_flag) { - if (timed_out(line->timestamp, NOREAD_FLAG_TIMEOUT)) { - line->noread_flag = true; - } - } - waddch(win, '\n'); break; @@ -771,6 +761,24 @@ void line_info_set(ToxWindow *self, uint32_t id, char *msg) } } +/* Return the line_info object associated with `id`. + * Return NULL if id cannot be found + */ +struct line_info *line_info_get(ToxWindow *self, uint32_t id) +{ + struct line_info *line = self->chatwin->hst->line_end; + + while (line) { + if (line->id == id) { + return line; + } + + line = line->prev; + } + + return NULL; +} + static void line_info_scroll_up(ToxWindow *self, struct history *hst) { if (hst->line_start->prev) { diff --git a/src/line_info.h b/src/line_info.h index 409f5de..8fc757e 100644 --- a/src/line_info.h +++ b/src/line_info.h @@ -96,6 +96,11 @@ void line_info_clear(struct history *hst); /* puts msg in specified line_info msg buffer */ void line_info_set(ToxWindow *self, uint32_t id, char *msg); +/* Return the line_info object associated with `id`. + * Return NULL if id cannot be found + */ +struct line_info *line_info_get(ToxWindow *self, uint32_t id); + /* resets line_start (moves to end of chat history) */ void line_info_reset_start(ToxWindow *self, struct history *hst); diff --git a/src/message_queue.c b/src/message_queue.c index 81b8fce..dee3ef5 100644 --- a/src/message_queue.c +++ b/src/message_queue.c @@ -59,6 +59,7 @@ void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type, new_m->type = type; new_m->line_id = line_id; new_m->last_send_try = 0; + new_m->time_added = get_unix_time(); new_m->receipt = -1; new_m->next = NULL; @@ -76,23 +77,19 @@ void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type, /* update line to show receipt was received after queue removal */ static void cqueue_mark_read(ToxWindow *self, struct cqueue_msg *msg) { - struct line_info *line = self->chatwin->hst->line_end; - - while (line) { - if (line->id != msg->line_id) { - line = line->prev; - continue; - } - - line->type = msg->type == OUT_ACTION ? OUT_ACTION_READ : OUT_MSG_READ; - - if (line->noread_flag) { - line->noread_flag = false; - line->read_flag = true; - } + struct line_info *line = line_info_get(self, msg->line_id); + if (line == NULL) { return; } + + line->type = msg->type == OUT_ACTION ? OUT_ACTION_READ : OUT_MSG_READ; + + if (line->noread_flag) { + line->noread_flag = false; + line->read_flag = true; + flag_interface_refresh(); + } } /* removes message with matching receipt from queue, writes to log and updates line to show the message was received. */ @@ -158,6 +155,36 @@ static void cqueue_check_timeouts(struct cqueue_msg *msg) } } +/* + * Sets the noread flag for messages sent to the peer associated with `self` which have not + * received a receipt after a period of time. + */ +#define NOREAD_TIMEOUT 5 +void cqueue_check_unread(ToxWindow *self) +{ + struct chat_queue *q = self->chatwin->cqueue; + struct cqueue_msg *msg = q->root; + + while (msg) { + if (msg->noread_flag) { + msg = msg->next; + continue; + } + + struct line_info *line = line_info_get(self, msg->line_id); + + if (line != NULL) { + if (timed_out(msg->time_added, NOREAD_TIMEOUT)) { + line->noread_flag = true; + msg->noread_flag = true; + flag_interface_refresh(); + } + } + + msg = msg->next; + } +} + /* * Tries to send all messages in the send queue in sequential order. * If a message fails to send the function will immediately return. diff --git a/src/message_queue.h b/src/message_queue.h index 460c334..2e00c32 100644 --- a/src/message_queue.h +++ b/src/message_queue.h @@ -28,8 +28,10 @@ struct cqueue_msg { size_t len; int line_id; time_t last_send_try; + time_t time_added; uint8_t type; int64_t receipt; + bool noread_flag; struct cqueue_msg *next; struct cqueue_msg *prev; }; @@ -48,6 +50,12 @@ void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type, */ void cqueue_try_send(ToxWindow *self, Tox *m); +/* + * Sets the noread flag for messages sent to the peer associated with `self` which have not + * received a receipt after a period of time. + */ +void cqueue_check_unread(ToxWindow *self); + /* removes message with matching receipt from queue, writes to log and updates line to show the message was received. */ void cqueue_remove(ToxWindow *self, Tox *m, uint32_t receipt); diff --git a/src/toxic.c b/src/toxic.c index ff9a6c8..fd572b4 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -1144,9 +1144,12 @@ void *thread_cqueue(void *data) for (size_t i = 2; i < MAX_WINDOWS_NUM; ++i) { ToxWindow *toxwin = get_window_ptr(i); - if ((toxwin != NULL) && (toxwin->type == WINDOW_TYPE_CHAT) - && (get_friend_connection_status(toxwin->num) != TOX_CONNECTION_NONE)) { - cqueue_try_send(toxwin, m); + if ((toxwin != NULL) && (toxwin->type == WINDOW_TYPE_CHAT)) { + cqueue_check_unread(toxwin); + + if (get_friend_connection_status(toxwin->num) != TOX_CONNECTION_NONE) { + cqueue_try_send(toxwin, m); + } } } diff --git a/src/windows.c b/src/windows.c index 1e96226..ee2f0ca 100644 --- a/src/windows.c +++ b/src/windows.c @@ -808,15 +808,18 @@ void draw_active_window(Tox *m) a->onDraw(a, m); wrefresh(a->window); } + #ifdef AUDIO else if (a->is_call && timed_out(a->chatwin->infobox.lastupdate, 1)) { touchwin(a->window); a->onDraw(a, m); wrefresh(a->window); } + #endif #ifdef GAMES + if (a->type == WINDOW_TYPE_GAME) { if (!flag_refresh) { // we always want to be continously refreshing game windows touchwin(a->window);