aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2022-07-02 18:45:40 +0200
committerTheJackiMonster <thejackimonster@gmail.com>2022-07-02 18:45:40 +0200
commit131b5671c30636ec2ebcd847ca5dc09113b70b89 (patch)
treed5acac602ce38d1e6a31ddf2604f52a8b45b9bd8
parentb258c174a4e826c151adb216553628987e50f7c8 (diff)
downloadmessenger-cli-131b5671c30636ec2ebcd847ca5dc09113b70b89.tar.gz
messenger-cli-131b5671c30636ec2ebcd847ca5dc09113b70b89.zip
Added list of members in a chat
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r--Makefile3
-rw-r--r--src/application.c5
-rw-r--r--src/application.h4
-rw-r--r--src/chat.c68
-rw-r--r--src/chat.h6
-rw-r--r--src/ui/chat.h37
-rw-r--r--src/ui/chats.c19
-rw-r--r--src/ui/members.c217
-rw-r--r--src/ui/members.h78
-rw-r--r--src/ui/messages.c19
-rw-r--r--src/ui/messages.h2
11 files changed, 409 insertions, 49 deletions
diff --git a/Makefile b/Makefile
index c836442..d3ebae0 100644
--- a/Makefile
+++ b/Makefile
@@ -10,13 +10,16 @@ SOURCES = messenger_cli.c\
10 ui/accounts.c\ 10 ui/accounts.c\
11 ui/chat_open_dialog.c\ 11 ui/chat_open_dialog.c\
12 ui/chats.c\ 12 ui/chats.c\
13 ui/members.c\
13 ui/messages.c 14 ui/messages.c
14HEADERS = application.h\ 15HEADERS = application.h\
15 chat.h\ 16 chat.h\
16 ui/account_create_dialog.h\ 17 ui/account_create_dialog.h\
17 ui/accounts.h\ 18 ui/accounts.h\
19 ui/chat.h\
18 ui/chat_open_dialog.h\ 20 ui/chat_open_dialog.h\
19 ui/chats.h\ 21 ui/chats.h\
22 ui/members.h\
20 ui/messages.h 23 ui/messages.h
21 24
22LIBRARIES = gnunetchat gnunetutil ncurses 25LIBRARIES = gnunetchat gnunetutil ncurses
diff --git a/src/application.c b/src/application.c
index 74641c5..f3b99c5 100644
--- a/src/application.c
+++ b/src/application.c
@@ -45,7 +45,7 @@ application_init(MESSENGER_Application *app,
45 noecho(); 45 noecho();
46 46
47 keypad(app->window, TRUE); 47 keypad(app->window, TRUE);
48 timeout(100); 48 timeout(10);
49} 49}
50 50
51static void 51static void
@@ -79,7 +79,8 @@ application_run(MESSENGER_Application *app)
79 app 79 app
80 ); 80 );
81 81
82 messages_clear(&(app->messages)); 82 members_clear(&(app->current.members));
83 messages_clear(&(app->current.messages));
83 84
84 if (app->window) 85 if (app->window)
85 delwin(app->window); 86 delwin(app->window);
diff --git a/src/application.h b/src/application.h
index 63e1689..ad8a7f5 100644
--- a/src/application.h
+++ b/src/application.h
@@ -32,8 +32,8 @@
32#include "util.h" 32#include "util.h"
33 33
34#include "ui/accounts.h" 34#include "ui/accounts.h"
35#include "ui/chat.h"
35#include "ui/chats.h" 36#include "ui/chats.h"
36#include "ui/messages.h"
37 37
38typedef struct MESSENGER_Application 38typedef struct MESSENGER_Application
39{ 39{
@@ -47,7 +47,7 @@ typedef struct MESSENGER_Application
47 47
48 UI_ACCOUNTS_Handle accounts; 48 UI_ACCOUNTS_Handle accounts;
49 UI_CHATS_Handle chats; 49 UI_CHATS_Handle chats;
50 UI_MESSAGES_Handle messages; 50 UI_CHAT_Handle current;
51} MESSENGER_Application; 51} MESSENGER_Application;
52 52
53void 53void
diff --git a/src/chat.c b/src/chat.c
index 8ad21e5..4bf7972 100644
--- a/src/chat.c
+++ b/src/chat.c
@@ -35,18 +35,25 @@ _chat_refresh(MESSENGER_Application *app)
35 35
36 app->accounts.window = NULL; 36 app->accounts.window = NULL;
37 app->chats.window = NULL; 37 app->chats.window = NULL;
38 app->messages.window = NULL; 38 app->current.members.window = NULL;
39 app->current.messages.window = NULL;
39 40
40 if (!account) 41 if (!account)
41 app->accounts.window = stdscr; 42 app->accounts.window = stdscr;
42 else if (app->chat.context) 43 else if (app->chat.context)
43 app->messages.window = stdscr; 44 {
45 if (app->chat.show_members)
46 app->current.members.window = stdscr;
47 else
48 app->current.messages.window = stdscr;
49 }
44 else 50 else
45 app->chats.window = stdscr; 51 app->chats.window = stdscr;
46 52
47 accounts_print(&(app->accounts), app); 53 accounts_print(&(app->accounts), app);
48 chats_print(&(app->chats), app); 54 chats_print(&(app->chats), app);
49 messages_print(&(app->messages)); 55 members_print(&(app->current.members));
56 messages_print(&(app->current.messages));
50} 57}
51 58
52static int 59static int
@@ -63,7 +70,12 @@ _chat_event(MESSENGER_Application *app,
63 if (!account) 70 if (!account)
64 accounts_event(&(app->accounts), app, key); 71 accounts_event(&(app->accounts), app, key);
65 else if (app->chat.context) 72 else if (app->chat.context)
66 messages_event(&(app->messages), app, key); 73 {
74 if (app->chat.show_members)
75 members_event(&(app->current.members), app, key);
76 else
77 messages_event(&(app->current.messages), app, key);
78 }
67 else 79 else
68 chats_event(&(app->chats), app, key); 80 chats_event(&(app->chats), app, key);
69 81
@@ -82,21 +94,7 @@ _chat_message(void *cls,
82{ 94{
83 MESSENGER_Application *app = cls; 95 MESSENGER_Application *app = cls;
84 96
85 UI_MESSAGES_Handle *messages = (UI_MESSAGES_Handle*) ( 97 chat_process_message(&(app->chat), context, message);
86 GNUNET_CHAT_context_get_user_pointer(context)
87 );
88
89 if (messages)
90 {
91 if (GNUNET_CHAT_KIND_DELETION == GNUNET_CHAT_message_get_kind(message))
92 messages_remove(
93 &(app->messages),
94 context,
95 GNUNET_CHAT_message_get_target(message)
96 );
97
98 messages_add(&(app->messages), context, message);
99 }
100 98
101 _chat_event(app, KEY_RESIZE); 99 _chat_event(app, KEY_RESIZE);
102 return GNUNET_YES; 100 return GNUNET_YES;
@@ -160,3 +158,35 @@ chat_stop(MESSENGER_Chat *chat)
160 158
161 chat->quit = GNUNET_YES; 159 chat->quit = GNUNET_YES;
162} 160}
161
162void
163chat_process_message(UNUSED MESSENGER_Chat *chat,
164 struct GNUNET_CHAT_Context *context,
165 const struct GNUNET_CHAT_Message *message)
166{
167 enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message);
168
169 struct GNUNET_CHAT_Contact *sender = GNUNET_CHAT_message_get_sender(message);
170
171 UI_CHAT_Handle *current = (UI_CHAT_Handle*) (
172 GNUNET_CHAT_context_get_user_pointer(context)
173 );
174
175 if (!current)
176 return;
177
178 bool new_member = FALSE;
179
180 if (GNUNET_CHAT_KIND_LEAVE)
181 members_remove(&(current->members), sender);
182 else if (GNUNET_CHAT_KIND_JOIN == kind)
183 new_member = members_add(&(current->members), sender);
184
185 if (GNUNET_CHAT_KIND_DELETION == kind)
186 messages_remove(
187 &(current->messages),
188 GNUNET_CHAT_message_get_target(message)
189 );
190 else if ((GNUNET_CHAT_KIND_JOIN != kind) || (new_member))
191 messages_add(&(current->messages), message);
192}
diff --git a/src/chat.h b/src/chat.h
index 8d5cd0b..8f3a309 100644
--- a/src/chat.h
+++ b/src/chat.h
@@ -38,6 +38,7 @@ typedef struct MESSENGER_Chat
38 38
39 struct GNUNET_SCHEDULER_Task *idle; 39 struct GNUNET_SCHEDULER_Task *idle;
40 40
41 bool show_members;
41 int quit; 42 int quit;
42} MESSENGER_Chat; 43} MESSENGER_Chat;
43 44
@@ -49,4 +50,9 @@ chat_start(MESSENGER_Chat *chat,
49void 50void
50chat_stop(MESSENGER_Chat *chat); 51chat_stop(MESSENGER_Chat *chat);
51 52
53void
54chat_process_message(MESSENGER_Chat *chat,
55 struct GNUNET_CHAT_Context *context,
56 const struct GNUNET_CHAT_Message *message);
57
52#endif /* CHAT_H_ */ 58#endif /* CHAT_H_ */
diff --git a/src/ui/chat.h b/src/ui/chat.h
new file mode 100644
index 0000000..b8febf4
--- /dev/null
+++ b/src/ui/chat.h
@@ -0,0 +1,37 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file ui/chat.h
23 */
24
25#ifndef UI_CHAT_H_
26#define UI_CHAT_H_
27
28#include "members.h"
29#include "messages.h"
30
31typedef struct UI_CHAT_Handle
32{
33 UI_MEMBERS_Handle members;
34 UI_MESSAGES_Handle messages;
35} UI_CHAT_Handle;
36
37#endif /* UI_CHAT_H_ */
diff --git a/src/ui/chats.c b/src/ui/chats.c
index dbffc26..fc7056c 100644
--- a/src/ui/chats.c
+++ b/src/ui/chats.c
@@ -49,10 +49,8 @@ _chats_iterate_messages(void *cls,
49 struct GNUNET_CHAT_Context *context, 49 struct GNUNET_CHAT_Context *context,
50 const struct GNUNET_CHAT_Message *message) 50 const struct GNUNET_CHAT_Message *message)
51{ 51{
52 UI_MESSAGES_Handle *messages = cls; 52 MESSENGER_Chat *chat = cls;
53 53 chat_process_message(chat, context, message);
54 messages_add(messages, context, message);
55
56 return GNUNET_YES; 54 return GNUNET_YES;
57} 55}
58 56
@@ -101,17 +99,18 @@ chats_event(UI_CHATS_Handle *chats,
101 { 99 {
102 struct GNUNET_CHAT_Context *context = GNUNET_CHAT_group_get_context(chats->selected); 100 struct GNUNET_CHAT_Context *context = GNUNET_CHAT_group_get_context(chats->selected);
103 101
104 messages_clear(&(app->messages)); 102 members_clear(&(app->current.members));
103 messages_clear(&(app->current.messages));
105 104
106 GNUNET_CHAT_context_iterate_messages( 105 GNUNET_CHAT_context_set_user_pointer(
107 context, 106 context,
108 &_chats_iterate_messages, 107 &(app->current)
109 &(app->messages)
110 ); 108 );
111 109
112 GNUNET_CHAT_context_set_user_pointer( 110 GNUNET_CHAT_context_iterate_messages(
113 context, 111 context,
114 &(app->messages) 112 &_chats_iterate_messages,
113 &(app->chat)
115 ); 114 );
116 115
117 app->chat.context = context; 116 app->chat.context = context;
diff --git a/src/ui/members.c b/src/ui/members.c
new file mode 100644
index 0000000..c500d58
--- /dev/null
+++ b/src/ui/members.c
@@ -0,0 +1,217 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file ui/members.c
23 */
24
25#include "members.h"
26
27#include "../application.h"
28#include "../util.h"
29
30void
31members_event(UI_MEMBERS_Handle *members,
32 struct MESSENGER_Application *app,
33 int key)
34{
35 members->line_index = 0;
36 members->selected = NULL;
37
38 int count = 0;
39
40 UI_MEMBERS_List *element = members->head;
41 while (element)
42 {
43 count++;
44
45 element = element->next;
46 }
47
48 switch (key)
49 {
50 case 27:
51 case KEY_EXIT:
52 case '\t':
53 {
54 app->chat.show_members = FALSE;
55 break;
56 }
57 case KEY_UP:
58 {
59 members->line_selected--;
60 break;
61 }
62 case KEY_DOWN:
63 {
64 members->line_selected++;
65 break;
66 }
67 case '\n':
68 case KEY_ENTER:
69 {
70 if (members->selected)
71 {
72 // TODO
73 }
74
75 break;
76 }
77 default:
78 break;
79 }
80
81 if (members->line_selected < 0)
82 members->line_selected = 0;
83 else if (members->line_selected >= count)
84 members->line_selected = count - 1;
85
86 if (!(members->window))
87 return;
88
89 const int height = getmaxy(members->window) - getbegy(members->window);
90 const int y = members->line_selected - members->line_offset;
91
92 if (y < 0)
93 members->line_offset += y;
94 else if (y + 1 >= height)
95 members->line_offset += y + 1 - height;
96
97 if (members->line_offset < 0)
98 members->line_offset = 0;
99 else if (members->line_offset >= count)
100 members->line_offset = count - 1;
101}
102
103static void
104_members_iterate_print(UI_MEMBERS_Handle *members,
105 const struct GNUNET_CHAT_Contact *contact)
106{
107 const bool selected = (members->line_selected == members->line_index);
108 const int y = members->line_index - members->line_offset;
109
110 members->line_index++;
111
112 if (y < 0)
113 return;
114
115 const int height = getmaxy(members->window) - getbegy(members->window);
116
117 if (y >= height)
118 return;
119
120 const int attrs_select = A_BOLD;
121
122 if (selected) wattron(members->window, attrs_select);
123
124 wmove(members->window, y, 0);
125
126 const char *name = GNUNET_CHAT_contact_get_name(contact);
127 wprintw(members->window, "%s", name);
128
129 if (selected) wattroff(members->window, attrs_select);
130}
131
132void
133members_print(UI_MEMBERS_Handle *members)
134{
135 if (!(members->window))
136 return;
137
138 members->line_index = 0;
139 werase(members->window);
140
141 UI_MEMBERS_List *element = members->head;
142 while (element)
143 {
144 _members_iterate_print(members, element->contact);
145
146 element = element->next;
147 }
148}
149
150void
151members_clear(UI_MEMBERS_Handle *members)
152{
153 UI_MEMBERS_List *element;
154 while (members->head)
155 {
156 element = members->head;
157
158 GNUNET_CONTAINER_DLL_remove(
159 members->head,
160 members->tail,
161 element
162 );
163
164 GNUNET_free(element);
165 }
166
167 members->line_selected = 0;
168}
169
170bool
171members_add(UI_MEMBERS_Handle *members,
172 const struct GNUNET_CHAT_Contact *contact)
173{
174 UI_MEMBERS_List *element = members->head;
175 while (element)
176 {
177 if (element->contact == contact)
178 break;
179
180 element = element->next;
181 }
182
183 if (element)
184 return FALSE;
185
186 element = GNUNET_new(UI_MEMBERS_List);
187 element->contact = contact;
188
189 GNUNET_CONTAINER_DLL_insert_tail(
190 members->head,
191 members->tail,
192 element
193 );
194
195 return TRUE;
196}
197
198void
199members_remove(UI_MEMBERS_Handle *members,
200 const struct GNUNET_CHAT_Contact *contact)
201{
202 UI_MEMBERS_List *element = members->head;
203 while (element)
204 {
205 if (element->contact == contact)
206 break;
207
208 element = element->next;
209 }
210
211 if (element)
212 GNUNET_CONTAINER_DLL_remove(
213 members->head,
214 members->tail,
215 element
216 );
217}
diff --git a/src/ui/members.h b/src/ui/members.h
new file mode 100644
index 0000000..4f7c50d
--- /dev/null
+++ b/src/ui/members.h
@@ -0,0 +1,78 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2022 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/*
21 * @author Tobias Frisch
22 * @file ui/members.h
23 */
24
25#ifndef UI_MEMBERS_H_
26#define UI_MEMBERS_H_
27
28#include <stdlib.h>
29#include <curses.h>
30
31#include <gnunet/platform.h>
32#include <gnunet/gnunet_chat_lib.h>
33#include <gnunet/gnunet_util_lib.h>
34
35struct MESSENGER_Application;
36
37typedef struct UI_MEMBERS_List
38{
39 const struct GNUNET_CHAT_Contact *contact;
40
41 struct UI_MEMBERS_List *prev;
42 struct UI_MEMBERS_List *next;
43} UI_MEMBERS_List;
44
45typedef struct UI_MEMBERS_Handle
46{
47 WINDOW *window;
48
49 UI_MEMBERS_List *head;
50 UI_MEMBERS_List *tail;
51
52 int line_index;
53 int line_offset;
54 int line_selected;
55
56 const struct GNUNET_CHAT_Contact *selected;
57} UI_MEMBERS_Handle;
58
59void
60members_event(UI_MEMBERS_Handle *members,
61 struct MESSENGER_Application *app,
62 int key);
63
64void
65members_print(UI_MEMBERS_Handle *members);
66
67void
68members_clear(UI_MEMBERS_Handle *members);
69
70bool
71members_add(UI_MEMBERS_Handle *members,
72 const struct GNUNET_CHAT_Contact *contact);
73
74void
75members_remove(UI_MEMBERS_Handle *members,
76 const struct GNUNET_CHAT_Contact *contact);
77
78#endif /* UI_MEMBERS_H_ */
diff --git a/src/ui/messages.c b/src/ui/messages.c
index 70d64df..9b0a692 100644
--- a/src/ui/messages.c
+++ b/src/ui/messages.c
@@ -86,6 +86,11 @@ messages_event(UI_MESSAGES_Handle *messages,
86 messages->line_selected++; 86 messages->line_selected++;
87 break; 87 break;
88 } 88 }
89 case '\t':
90 {
91 app->chat.show_members = TRUE;
92 break;
93 }
89 case '\n': 94 case '\n':
90 case KEY_ENTER: 95 case KEY_ENTER:
91 { 96 {
@@ -337,7 +342,6 @@ _message_compare_timestamps(UNUSED void *cls,
337 342
338void 343void
339messages_add(UI_MESSAGES_Handle *messages, 344messages_add(UI_MESSAGES_Handle *messages,
340 struct GNUNET_CHAT_Context *context,
341 const struct GNUNET_CHAT_Message *message) 345 const struct GNUNET_CHAT_Message *message)
342{ 346{
343 enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message); 347 enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message);
@@ -351,15 +355,6 @@ messages_add(UI_MESSAGES_Handle *messages,
351 break; 355 break;
352 } 356 }
353 357
354 struct GNUNET_CHAT_Contact *sender = GNUNET_CHAT_message_get_sender(message);
355 struct GNUNET_CHAT_Group *group = GNUNET_CHAT_context_get_group(context);
356
357 if ((GNUNET_CHAT_KIND_JOIN == kind) &&
358 (GNUNET_CHAT_member_get_user_pointer(group, sender)))
359 {
360 return;
361 }
362
363 const int height = getmaxy(messages->window) - getbegy(messages->window); 358 const int height = getmaxy(messages->window) - getbegy(messages->window);
364 const int line_height = height - 2; 359 const int line_height = height - 2;
365 360
@@ -384,9 +379,6 @@ messages_add(UI_MESSAGES_Handle *messages,
384 element 379 element
385 ); 380 );
386 381
387 if (GNUNET_CHAT_KIND_JOIN == kind)
388 GNUNET_CHAT_member_set_user_pointer(group, sender, element);
389
390 if (messages->line_selected >= count) 382 if (messages->line_selected >= count)
391 messages->line_selected = count + 1; 383 messages->line_selected = count + 1;
392 384
@@ -396,7 +388,6 @@ messages_add(UI_MESSAGES_Handle *messages,
396 388
397void 389void
398messages_remove(UI_MESSAGES_Handle *messages, 390messages_remove(UI_MESSAGES_Handle *messages,
399 UNUSED struct GNUNET_CHAT_Context *context,
400 const struct GNUNET_CHAT_Message *message) 391 const struct GNUNET_CHAT_Message *message)
401{ 392{
402 UI_MESSAGES_List *element = messages->head; 393 UI_MESSAGES_List *element = messages->head;
diff --git a/src/ui/messages.h b/src/ui/messages.h
index d969782..06de97f 100644
--- a/src/ui/messages.h
+++ b/src/ui/messages.h
@@ -75,12 +75,10 @@ messages_clear(UI_MESSAGES_Handle *messages);
75 75
76void 76void
77messages_add(UI_MESSAGES_Handle *messages, 77messages_add(UI_MESSAGES_Handle *messages,
78 struct GNUNET_CHAT_Context *context,
79 const struct GNUNET_CHAT_Message *message); 78 const struct GNUNET_CHAT_Message *message);
80 79
81void 80void
82messages_remove(UI_MESSAGES_Handle *messages, 81messages_remove(UI_MESSAGES_Handle *messages,
83 struct GNUNET_CHAT_Context *context,
84 const struct GNUNET_CHAT_Message *message); 82 const struct GNUNET_CHAT_Message *message);
85 83
86#endif /* UI_MESSAGES_H_ */ 84#endif /* UI_MESSAGES_H_ */