chats.c (6041B)
1 /* 2 This file is part of GNUnet. 3 Copyright (C) 2022--2025 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/chats.c 23 */ 24 25 #include "chats.h" 26 27 #include "list_input.h" 28 #include "../application.h" 29 #include "../util.h" 30 #include <gnunet/gnunet_chat_lib.h> 31 #include <gnunet/gnunet_common.h> 32 33 static enum GNUNET_GenericReturnValue 34 _chats_iterate_group(void *cls, 35 UNUSED struct GNUNET_CHAT_Handle *handle, 36 struct GNUNET_CHAT_Group *group) 37 { 38 UI_CHATS_Handle *chats = cls; 39 list_input_select(chats, 1, GNUNET_CHAT_group_get_context(group)); 40 return GNUNET_YES; 41 } 42 43 static enum GNUNET_GenericReturnValue 44 _chats_iterate_contact(void *cls, 45 UNUSED struct GNUNET_CHAT_Handle *handle, 46 struct GNUNET_CHAT_Contact *contact) 47 { 48 UI_CHATS_Handle *chats = cls; 49 list_input_select(chats, 1, GNUNET_CHAT_contact_get_context(contact)); 50 return GNUNET_YES; 51 } 52 53 static enum GNUNET_GenericReturnValue 54 _chats_iterate_messages(void *cls, 55 struct GNUNET_CHAT_Context *context, 56 struct GNUNET_CHAT_Message *message) 57 { 58 MESSENGER_Chat *chat = cls; 59 chat_process_message(chat, context, message); 60 return GNUNET_YES; 61 } 62 63 void 64 chats_event(UI_CHATS_Handle *chats, 65 MESSENGER_Application *app, 66 int key) 67 { 68 if (chats->open_dialog.window) 69 { 70 chat_open_dialog_event(&(chats->open_dialog), app, key); 71 return; 72 } 73 else if (chats->create_dialog.win) 74 { 75 lobby_create_dialog_event(&(chats->create_dialog), app, key); 76 return; 77 } 78 else if (chats->enter_dialog.window) 79 { 80 lobby_enter_dialog_event(&(chats->enter_dialog), app, key); 81 return; 82 } 83 84 list_input_reset(chats); 85 86 GNUNET_CHAT_iterate_groups( 87 app->chat.handle, 88 &_chats_iterate_group, 89 chats 90 ); 91 92 GNUNET_CHAT_iterate_contacts( 93 app->chat.handle, 94 &_chats_iterate_contact, 95 chats 96 ); 97 98 list_input_select(chats, 1, NULL); 99 list_input_select(chats, 1, NULL); 100 list_input_select(chats, 1, NULL); 101 102 const int count = chats->line_index; 103 104 switch (key) 105 { 106 case 27: 107 case KEY_EXIT: 108 GNUNET_CHAT_disconnect(app->chat.handle); 109 break; 110 case '\n': 111 case KEY_ENTER: 112 if (chats->selected) 113 { 114 GNUNET_CHAT_context_request(chats->selected); 115 116 members_clear(&(app->current.members)); 117 messages_clear(&(app->current.messages)); 118 119 GNUNET_CHAT_context_set_user_pointer( 120 chats->selected, 121 &(app->current) 122 ); 123 124 GNUNET_CHAT_context_iterate_messages( 125 chats->selected, 126 &_chats_iterate_messages, 127 &(app->chat) 128 ); 129 130 app->chat.context = chats->selected; 131 } 132 else if (chats->line_selected == count - 3) 133 chats->open_dialog.window = &(chats->window); 134 else if (chats->line_selected == count - 2) 135 chats->create_dialog.win = &(chats->window); 136 else if (chats->line_selected == count - 1) 137 chats->enter_dialog.window = &(chats->window); 138 break; 139 default: 140 break; 141 } 142 143 list_input_event(chats, key); 144 } 145 146 static int 147 _chats_print_entry(UI_CHATS_Handle *chats, 148 char type, 149 char chat_type, 150 const char *text, 151 const void *data) 152 { 153 list_input_print_gnunet(chats, 1); 154 155 const int attrs_select = A_BOLD; 156 157 if (selected) wattron(chats->window, attrs_select); 158 else type = ' '; 159 160 wmove(chats->window, y, 0); 161 162 util_enable_unique_color(chats->window, data); 163 164 if (chat_type) 165 wprintw(chats->window, "[%c][%c] %s", type, chat_type, text); 166 else 167 wprintw(chats->window, "[%c] %s", type, text); 168 169 util_disable_unique_color(chats->window, data); 170 171 if (selected) wattroff(chats->window, attrs_select); 172 173 return GNUNET_YES; 174 } 175 176 enum GNUNET_GenericReturnValue 177 _chats_iterate_print_group(void *cls, 178 UNUSED struct GNUNET_CHAT_Handle *handle, 179 struct GNUNET_CHAT_Group *group) 180 { 181 UI_CHATS_Handle *chats = cls; 182 const char *name = GNUNET_CHAT_group_get_name(group); 183 return _chats_print_entry(chats, 'x', 'G', name, group); 184 } 185 186 enum GNUNET_GenericReturnValue 187 _chats_iterate_print_contact(void *cls, 188 UNUSED struct GNUNET_CHAT_Handle *handle, 189 struct GNUNET_CHAT_Contact *contact) 190 { 191 UI_CHATS_Handle *chats = cls; 192 const char *name = GNUNET_CHAT_contact_get_name(contact); 193 return _chats_print_entry(chats, 'x', 'C', name, contact); 194 } 195 196 void 197 chats_print(UI_CHATS_Handle *chats, 198 MESSENGER_Application *app) 199 { 200 if (chats->open_dialog.window) 201 { 202 chat_open_dialog_print(&(chats->open_dialog)); 203 return; 204 } 205 else if (chats->create_dialog.win) 206 { 207 lobby_create_dialog_print(&(chats->create_dialog)); 208 return; 209 } 210 else if (chats->enter_dialog.window) 211 { 212 lobby_enter_dialog_print(&(chats->enter_dialog)); 213 return; 214 } 215 216 if (!(chats->window)) 217 return; 218 219 list_input_reset(chats); 220 werase(chats->window); 221 222 GNUNET_CHAT_iterate_groups( 223 app->chat.handle, 224 &_chats_iterate_print_group, 225 chats 226 ); 227 228 GNUNET_CHAT_iterate_contacts( 229 app->chat.handle, 230 &_chats_iterate_print_contact, 231 chats 232 ); 233 234 _chats_print_entry(chats, '+', '\0', "Add chat", NULL); 235 _chats_print_entry(chats, '+', '\0', "Open lobby", NULL); 236 _chats_print_entry(chats, '+', '\0', "Enter lobby", NULL); 237 }