messenger-cli

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

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 }