aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2022-09-09 15:36:34 +0200
committerTheJackiMonster <thejackimonster@gmail.com>2022-09-09 15:36:34 +0200
commit2a72f770ecf2f6243fada17c6c31d4dd085eb911 (patch)
tree660d6b180b4a95f4967723cac252f8d4a1709bb9
parent04b106bf09b8ef90418811ed583d1c4ebd5fdaf5 (diff)
downloadmessenger-cli-2a72f770ecf2f6243fada17c6c31d4dd085eb911.tar.gz
messenger-cli-2a72f770ecf2f6243fada17c6c31d4dd085eb911.zip
Added lines showing dates between chat messages
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--src/ui/accounts.h3
-rw-r--r--src/ui/chats.h3
-rw-r--r--src/ui/list_input.h127
-rw-r--r--src/ui/lobby_create_dialog.h3
-rw-r--r--src/ui/members.h3
-rw-r--r--src/ui/messages.c110
-rw-r--r--src/ui/messages.h6
7 files changed, 160 insertions, 95 deletions
diff --git a/src/ui/accounts.h b/src/ui/accounts.h
index fe0e1b1..4e278d5 100644
--- a/src/ui/accounts.h
+++ b/src/ui/accounts.h
@@ -40,6 +40,9 @@ typedef struct UI_ACCOUNTS_Handle
40{ 40{
41 WINDOW *window; 41 WINDOW *window;
42 42
43 int line_prev;
44 int line_next;
45
43 int line_index; 46 int line_index;
44 int line_offset; 47 int line_offset;
45 int line_selected; 48 int line_selected;
diff --git a/src/ui/chats.h b/src/ui/chats.h
index db4e987..8e836bd 100644
--- a/src/ui/chats.h
+++ b/src/ui/chats.h
@@ -42,6 +42,9 @@ typedef struct UI_CHATS_Handle
42{ 42{
43 WINDOW *window; 43 WINDOW *window;
44 44
45 int line_prev;
46 int line_next;
47
45 int line_index; 48 int line_index;
46 int line_offset; 49 int line_offset;
47 int line_selected; 50 int line_selected;
diff --git a/src/ui/list_input.h b/src/ui/list_input.h
index 932d0fd..717e1ba 100644
--- a/src/ui/list_input.h
+++ b/src/ui/list_input.h
@@ -29,80 +29,87 @@
29#include <stdlib.h> 29#include <stdlib.h>
30 30
31#define list_input_reset(list) { \ 31#define list_input_reset(list) { \
32 (list)->line_index = 0; \ 32 (list)->line_prev = 0; \
33 (list)->selected = 0; \ 33 (list)->line_next = 0; \
34 (list)->line_index = 0; \
35 (list)->selected = 0; \
34} 36}
35 37
36#define list_input_select(list, line_width, item) { \ 38#define list_input_select(list, line_width, item) { \
37 const bool selected = ( \ 39 const bool selected = ( \
38 ((list)->line_selected >= (list)->line_index) && \ 40 ((list)->line_selected >= (list)->line_index) && \
39 ((list)->line_selected < (list)->line_index + line_width) \ 41 ((list)->line_selected < (list)->line_index + (line_width)) \
40 ); \ 42 ); \
41 \ 43 \
42 (list)->line_index += line_width; \ 44 if ((!selected) && ((list)->line_selected > (list)->line_index)) \
43 \ 45 (list)->line_prev = (list)->line_index; \
44 if (selected) \ 46 \
45 (list)->selected = item; \ 47 (list)->line_index += (line_width); \
48 \
49 if (selected) { \
50 (list)->line_next = (list)->line_index; \
51 (list)->selected = item; \
52 } \
46} 53}
47 54
48#define list_input_event(list, key) { \ 55#define list_input_event(list, key) { \
49 int count = (list)->line_index; \ 56 int count = (list)->line_index; \
50 \ 57 \
51 switch (key) \ 58 switch (key) \
52 { \ 59 { \
53 case KEY_UP: \ 60 case KEY_UP: \
54 { \ 61 { \
55 (list)->line_selected--; \ 62 (list)->line_selected = (list)->line_prev; \
56 break; \ 63 break; \
57 } \ 64 } \
58 case KEY_DOWN: \ 65 case KEY_DOWN: \
59 { \ 66 { \
60 (list)->line_selected++; \ 67 (list)->line_selected = (list)->line_next; \
61 break; \ 68 break; \
62 } \ 69 } \
63 default: \ 70 default: \
64 break; \ 71 break; \
65 } \ 72 } \
66 \ 73 \
67 if ((list)->line_selected < 0) \ 74 if ((list)->line_selected < 0) \
68 (list)->line_selected = 0; \ 75 (list)->line_selected = 0; \
69 else if ((list)->line_selected >= count) \ 76 else if ((list)->line_selected >= count) \
70 (list)->line_selected = count - 1; \ 77 (list)->line_selected = count - 1; \
71 \ 78 \
72 if ((list)->window) \ 79 if ((list)->window) \
73 { \ 80 { \
74 const int height = getmaxy((list)->window); \ 81 const int height = getmaxy((list)->window); \
75 const int y = (list)->line_selected - (list)->line_offset; \ 82 const int y = (list)->line_selected - (list)->line_offset; \
76 \ 83 \
77 if (y < 0) \ 84 if (y < 0) \
78 (list)->line_offset += y; \ 85 (list)->line_offset += y; \
79 else if (y + 1 >= height) \ 86 else if (y + 1 >= height) \
80 (list)->line_offset += y + 1 - height; \ 87 (list)->line_offset += y + 1 - height; \
81 \ 88 \
82 if ((list)->line_offset < 0) \ 89 if ((list)->line_offset < 0) \
83 (list)->line_offset = 0; \ 90 (list)->line_offset = 0; \
84 else if ((list)->line_offset >= count) \ 91 else if ((list)->line_offset >= count) \
85 (list)->line_offset = count - 1; \ 92 (list)->line_offset = count - 1; \
86 } \ 93 } \
87} 94}
88 95
89#define list_input_print_(list, line_width, yes_res, no_res) \ 96#define list_input_print_(list, line_width, yes_res, no_res) \
90 const bool selected = ( \ 97 const bool selected = ( \
91 ((list)->line_selected >= (list)->line_index) && \ 98 ((list)->line_selected >= (list)->line_index) && \
92 ((list)->line_selected < (list)->line_index + line_width) \ 99 ((list)->line_selected < (list)->line_index + (line_width)) \
93 ); \ 100 ); \
94 \ 101 \
95 const int y = (list)->line_index - (list)->line_offset; { \ 102 const int y = (list)->line_index - (list)->line_offset; { \
96 \ 103 \
97 (list)->line_index += line_width; \ 104 (list)->line_index += (line_width); \
98 \ 105 \
99 if (y + line_width < 1) \ 106 if (y + (line_width) < 1) \
100 return yes_res; \ 107 return yes_res; \
101 \ 108 \
102 const int height = getmaxy((list)->window); \ 109 const int height = getmaxy((list)->window); \
103 \ 110 \
104 if (y >= height) \ 111 if (y >= height) \
105 return no_res; \ 112 return no_res; \
106} 113}
107 114
108#define list_input_print_gnunet(list, line_width) \ 115#define list_input_print_gnunet(list, line_width) \
diff --git a/src/ui/lobby_create_dialog.h b/src/ui/lobby_create_dialog.h
index bdc34da..1497255 100644
--- 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
39 WINDOW *window; 39 WINDOW *window;
40 WINDOW **win; 40 WINDOW **win;
41 41
42 int line_prev;
43 int line_next;
44
42 int line_index; 45 int line_index;
43 int line_offset; 46 int line_offset;
44 int line_selected; 47 int line_selected;
diff --git a/src/ui/members.h b/src/ui/members.h
index 6e8711b..62c564f 100644
--- a/src/ui/members.h
+++ b/src/ui/members.h
@@ -50,6 +50,9 @@ typedef struct UI_MEMBERS_Handle
50 UI_MEMBERS_List *head; 50 UI_MEMBERS_List *head;
51 UI_MEMBERS_List *tail; 51 UI_MEMBERS_List *tail;
52 52
53 int line_prev;
54 int line_next;
55
53 int line_index; 56 int line_index;
54 int line_offset; 57 int line_offset;
55 int line_selected; 58 int line_selected;
diff --git a/src/ui/messages.c b/src/ui/messages.c
index 86df8e5..7b2d724 100644
--- a/src/ui/messages.c
+++ b/src/ui/messages.c
@@ -29,6 +29,26 @@
29#include "../application.h" 29#include "../application.h"
30#include "../util.h" 30#include "../util.h"
31 31
32struct tm*
33_messages_new_day(time_t* current_time,
34 const time_t* timestamp)
35{
36 struct tm* ts = localtime(timestamp);
37
38 ts->tm_sec = 0;
39 ts->tm_min = 0;
40 ts->tm_hour = 0;
41
42 const time_t date_time = timelocal(ts);
43
44 if (date_time <= *current_time) {
45 return NULL;
46 }
47
48 *current_time = date_time;
49 return ts;
50}
51
32void 52void
33_messages_handle_message(UI_MESSAGES_Handle *messages) 53_messages_handle_message(UI_MESSAGES_Handle *messages)
34{ 54{
@@ -65,11 +85,17 @@ messages_event(UI_MESSAGES_Handle *messages,
65 int key) 85 int key)
66{ 86{
67 list_input_reset(messages); 87 list_input_reset(messages);
88 messages->line_time = 0;
68 89
69 UI_MESSAGES_List *element = messages->head; 90 UI_MESSAGES_List *element = messages->head;
70 while (element) 91 while (element)
71 { 92 {
72 list_input_select(messages, 1, element->message); 93 struct tm *ts = _messages_new_day(
94 &(messages->line_time),
95 &(element->timestamp)
96 );
97
98 list_input_select(messages, ts? 2 : 1, element->message);
73 element = element->next; 99 element = element->next;
74 } 100 }
75 101
@@ -113,12 +139,11 @@ messages_event(UI_MESSAGES_Handle *messages,
113 139
114void 140void
115_messages_iterate_print(UI_MESSAGES_Handle *messages, 141_messages_iterate_print(UI_MESSAGES_Handle *messages,
142 const time_t* timestamp,
116 const struct GNUNET_CHAT_Message *message) 143 const struct GNUNET_CHAT_Message *message)
117{ 144{
118 enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message); 145 enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message);
119 146
120 list_input_print(messages, 1);
121
122 struct GNUNET_CHAT_Contact *sender = GNUNET_CHAT_message_get_sender(message); 147 struct GNUNET_CHAT_Contact *sender = GNUNET_CHAT_message_get_sender(message);
123 148
124 const char *name = sender? GNUNET_CHAT_contact_get_name(sender) : NULL; 149 const char *name = sender? GNUNET_CHAT_contact_get_name(sender) : NULL;
@@ -126,29 +151,35 @@ _messages_iterate_print(UI_MESSAGES_Handle *messages,
126 151
127 const struct GNUNET_CHAT_File *file = GNUNET_CHAT_message_get_file(message); 152 const struct GNUNET_CHAT_File *file = GNUNET_CHAT_message_get_file(message);
128 153
129 struct GNUNET_TIME_Absolute abs_time = GNUNET_CHAT_message_get_timestamp( 154 struct tm* ts = localtime(timestamp);
130 message 155 char time_buf [255];
131 );
132 156
133 struct GNUNET_TIME_Timestamp timestamp = GNUNET_TIME_absolute_to_timestamp( 157 strftime(time_buf, sizeof(time_buf), "%H:%M", ts);
134 abs_time
135 );
136 158
137 const time_t s_after_epoch = ( 159 ts = _messages_new_day(&(messages->line_time), timestamp);
138 GNUNET_TIME_timestamp_to_s(timestamp)
139 );
140 160
141 struct tm* ts = localtime(&s_after_epoch); 161 list_input_print(messages, ts? 2 : 1);
142 char time_buf [255]; 162 wmove(messages->window, y, 0);
143 163
144 strftime(time_buf, sizeof(time_buf), "%H:%M", ts); 164 if (ts) {
165 char date_buf [255];
166
167 strftime(date_buf, sizeof(date_buf), "%x", ts);
168
169 const int width = getmaxx(messages->window);
170
171 whline(messages->window, '-', width);
172 wmove(messages->window, y, 8);
173
174 wprintw(messages->window, " %s ", date_buf);
175 wmove(messages->window, y+1, 0);
176 }
145 177
146 const int attrs_select = A_BOLD; 178 const int attrs_select = A_BOLD;
147 179
148 if (selected) wattron(messages->window, attrs_select); 180 if (selected) wattron(messages->window, attrs_select);
149 181
150 wmove(messages->window, y, 0); 182 wprintw(messages->window, " %s | ", time_buf);
151 wprintw(messages->window, "%s | ", time_buf);
152 183
153 switch (kind) { 184 switch (kind) {
154 case GNUNET_CHAT_KIND_JOIN: 185 case GNUNET_CHAT_KIND_JOIN:
@@ -207,7 +238,6 @@ _messages_iterate_print(UI_MESSAGES_Handle *messages,
207 break; 238 break;
208 } 239 }
209 240
210
211 if (selected) wattroff(messages->window, attrs_select); 241 if (selected) wattroff(messages->window, attrs_select);
212} 242}
213 243
@@ -218,12 +248,14 @@ messages_print(UI_MESSAGES_Handle *messages)
218 return; 248 return;
219 249
220 list_input_reset(messages); 250 list_input_reset(messages);
251 messages->line_time = 0;
252
221 werase(messages->window); 253 werase(messages->window);
222 254
223 UI_MESSAGES_List *element = messages->head; 255 UI_MESSAGES_List *element = messages->head;
224 while (element) 256 while (element)
225 { 257 {
226 _messages_iterate_print(messages, element->message); 258 _messages_iterate_print(messages, &(element->timestamp), element->message);
227 element = element->next; 259 element = element->next;
228 } 260 }
229 261
@@ -278,17 +310,12 @@ _message_compare_timestamps(UNUSED void *cls,
278 UI_MESSAGES_List *list0, 310 UI_MESSAGES_List *list0,
279 UI_MESSAGES_List *list1) 311 UI_MESSAGES_List *list1)
280{ 312{
281 struct GNUNET_TIME_Absolute time0, time1;
282
283 if ((!list0) || (!list1)) 313 if ((!list0) || (!list1))
284 return 0; 314 return 0;
285 315
286 time0 = GNUNET_CHAT_message_get_timestamp(list0->message); 316 if (list0->timestamp > list1->timestamp)
287 time1 = GNUNET_CHAT_message_get_timestamp(list1->message);
288
289 if (GNUNET_TIME_absolute_cmp(time0, >, time1))
290 return -1; 317 return -1;
291 else if (GNUNET_TIME_absolute_cmp(time0, <, time1)) 318 else if (list0->timestamp < list1->timestamp)
292 return +1; 319 return +1;
293 else 320 else
294 return 0; 321 return 0;
@@ -309,19 +336,33 @@ messages_add(UI_MESSAGES_Handle *messages,
309 break; 336 break;
310 } 337 }
311 338
312 const int height = getmaxy(messages->window); 339 list_input_reset(messages);
313 const int line_height = height - 2; 340 messages->line_time = 0;
314
315 int count = 0;
316 341
317 UI_MESSAGES_List *element = messages->head; 342 UI_MESSAGES_List *element = messages->head;
318 while (element) 343 while (element)
319 { 344 {
320 count++; 345 struct tm *ts = _messages_new_day(
346 &(messages->line_time),
347 &(element->timestamp)
348 );
349
350 list_input_select(messages, ts? 2 : 1, element->message);
321 element = element->next; 351 element = element->next;
322 } 352 }
323 353
354 list_input_select(messages, 1, NULL);
355
356 const struct GNUNET_TIME_Absolute abs_time = (
357 GNUNET_CHAT_message_get_timestamp(message)
358 );
359
360 const struct GNUNET_TIME_Timestamp timestamp = (
361 GNUNET_TIME_absolute_to_timestamp(abs_time)
362 );
363
324 element = GNUNET_new(UI_MESSAGES_List); 364 element = GNUNET_new(UI_MESSAGES_List);
365 element->timestamp = GNUNET_TIME_timestamp_to_s(timestamp);
325 element->message = message; 366 element->message = message;
326 367
327 GNUNET_CONTAINER_DLL_insert_sorted( 368 GNUNET_CONTAINER_DLL_insert_sorted(
@@ -333,11 +374,10 @@ messages_add(UI_MESSAGES_Handle *messages,
333 element 374 element
334 ); 375 );
335 376
336 if (messages->line_selected >= count) 377 list_input_select(messages, 1, NULL);
337 messages->line_selected = count + 1;
338 378
339 if ((line_height > 0) && (messages->line_offset + line_height >= count)) 379 if (!(messages->selected))
340 messages->line_offset = count + 1 - line_height; 380 list_input_event(messages, KEY_DOWN);
341} 381}
342 382
343void 383void
diff --git a/src/ui/messages.h b/src/ui/messages.h
index 166941a..685cb82 100644
--- a/src/ui/messages.h
+++ b/src/ui/messages.h
@@ -36,6 +36,8 @@ struct MESSENGER_Application;
36 36
37typedef struct UI_MESSAGES_List 37typedef struct UI_MESSAGES_List
38{ 38{
39 time_t timestamp;
40
39 const struct GNUNET_CHAT_Message *message; 41 const struct GNUNET_CHAT_Message *message;
40 42
41 struct UI_MESSAGES_List *prev; 43 struct UI_MESSAGES_List *prev;
@@ -51,9 +53,13 @@ typedef struct UI_MESSAGES_Handle
51 UI_MESSAGES_List *head; 53 UI_MESSAGES_List *head;
52 UI_MESSAGES_List *tail; 54 UI_MESSAGES_List *tail;
53 55
56 int line_prev;
57 int line_next;
58
54 int line_index; 59 int line_index;
55 int line_offset; 60 int line_offset;
56 int line_selected; 61 int line_selected;
62 time_t line_time;
57 63
58 const struct GNUNET_CHAT_Message *selected; 64 const struct GNUNET_CHAT_Message *selected;
59 65