messenger-gtk

Gtk+3 graphical user interfaces for GNUnet Messenger
Log | Files | Refs | Submodules | README | LICENSE

account.c (6895B)


      1 /*
      2    This file is part of GNUnet.
      3    Copyright (C) 2024 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 account.c
     23  */
     24 
     25 #include "account.h"
     26 
     27 #include "contact.h"
     28 #include "ui.h"
     29 
     30 #include <gnunet/gnunet_chat_lib.h>
     31 #include <gnunet/gnunet_common.h>
     32 #include <string.h>
     33 
     34 static GList *infos = NULL;
     35 
     36 enum GNUNET_GenericReturnValue
     37 account_create_info(struct GNUNET_CHAT_Account *account)
     38 {
     39   if ((!account) || (GNUNET_CHAT_account_get_user_pointer(account)))
     40     return GNUNET_NO;
     41 
     42   MESSENGER_AccountInfo *info = g_malloc(sizeof(MESSENGER_AccountInfo));
     43 
     44   info->account = account;
     45 
     46   info->icon_file = NULL;
     47   info->icon = NULL;
     48   info->task = 0;
     49 
     50   info->name_avatars = NULL;
     51 
     52   infos = g_list_append(infos, info);
     53 
     54   GNUNET_CHAT_account_set_user_pointer(account, info);
     55   return GNUNET_YES;
     56 }
     57 
     58 static void
     59 _destroy_account_info(gpointer data)
     60 {
     61   g_assert(data);
     62 
     63   MESSENGER_AccountInfo *info = (MESSENGER_AccountInfo*) data;
     64 
     65   if (info->name_avatars)
     66     g_list_free(info->name_avatars);
     67 
     68   if (info->task)
     69     util_source_remove(info->task);
     70 
     71   if (info->icon)
     72     g_object_unref(info->icon);
     73 
     74   if (info->icon_file)
     75     g_object_unref(info->icon_file);
     76 
     77   GNUNET_CHAT_account_set_user_pointer(info->account, NULL);
     78 
     79   g_free(info);
     80 }
     81 
     82 void
     83 account_destroy_info(struct GNUNET_CHAT_Account *account)
     84 {
     85   g_assert(account);
     86 
     87   MESSENGER_AccountInfo* info = GNUNET_CHAT_account_get_user_pointer(account);
     88 
     89   if (!info)
     90     return;
     91 
     92   if (infos)
     93     infos = g_list_remove(infos, info);
     94 
     95   _destroy_account_info(info);
     96 }
     97 
     98 void
     99 account_cleanup_infos()
    100 {
    101   if (!infos)
    102     return;
    103 
    104   g_list_free_full(infos, (GDestroyNotify) _destroy_account_info);
    105 
    106   infos = NULL;
    107 }
    108 
    109 void
    110 account_add_name_avatar_to_info(const struct GNUNET_CHAT_Account *account,
    111                                 HdyAvatar *avatar)
    112 {
    113   g_assert(avatar);
    114 
    115   MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account);
    116 
    117   if (!info)
    118     return;
    119 
    120   const char *name = GNUNET_CHAT_account_get_name(account);
    121 
    122   ui_avatar_set_text(avatar, name);
    123   ui_avatar_set_icon(avatar, info->icon);
    124 
    125   info->name_avatars = g_list_append(info->name_avatars, avatar);  
    126 }
    127 
    128 void
    129 account_switch_name_avatar_to_info(const struct GNUNET_CHAT_Account *account,
    130                                    HdyAvatar *avatar)
    131 {
    132   g_assert(avatar);
    133 
    134   MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account);
    135 
    136   if (!info)
    137     return;
    138 
    139   if (g_list_find(info->name_avatars, avatar))
    140     return;
    141 
    142   GList *list = infos;
    143   while (list)
    144   {
    145     MESSENGER_AccountInfo *other = (MESSENGER_AccountInfo*) list->data;
    146 
    147     if (g_list_find(other->name_avatars, avatar))
    148     {
    149       account_remove_name_avatar_from_info(other->account, avatar);
    150       break;
    151     }
    152 
    153     list = g_list_next(list);
    154   }
    155 
    156   account_add_name_avatar_to_info(account, avatar);
    157 }
    158 
    159 void
    160 account_remove_name_avatar_from_info(const struct GNUNET_CHAT_Account *account,
    161                                      HdyAvatar *avatar)
    162 {
    163   g_assert(avatar);
    164 
    165   MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account);
    166 
    167   if (!info)
    168     return;
    169 
    170   if (info->name_avatars)
    171     info->name_avatars = g_list_remove(info->name_avatars, avatar);
    172 }
    173 
    174 static gboolean
    175 _task_update_avatars(gpointer data)
    176 {
    177   g_assert(data);
    178 
    179   MESSENGER_AccountInfo *info = (MESSENGER_AccountInfo*) data;
    180 
    181   info->task = 0;
    182 
    183   GList* list;
    184   for (list = info->name_avatars; list; list = list->next)
    185     ui_avatar_set_icon(HDY_AVATAR(list->data), info->icon);
    186 
    187   return FALSE;
    188 }
    189 
    190 static void
    191 _info_profile_downloaded(void *cls,
    192                          struct GNUNET_CHAT_File *file,
    193                          uint64_t completed,
    194                          uint64_t size)
    195 {
    196   g_assert((cls) && (file));
    197 
    198   struct GNUNET_CHAT_Account *account = (struct GNUNET_CHAT_Account*) cls;
    199 
    200   MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account);
    201 
    202   if ((!info) || (completed < size))
    203     return;
    204 
    205   const char *preview = GNUNET_CHAT_file_open_preview(file);
    206 
    207   if (!preview)
    208     return;
    209 
    210   GFile *file_object = g_file_new_for_path(preview);
    211 
    212   if (!file_object)
    213     return;
    214 
    215   if (!(info->icon_file))
    216     goto skip_comparison;
    217 
    218   if (g_file_equal(info->icon_file, file_object))
    219   {
    220     g_object_unref(file_object);
    221     return;
    222   }
    223 
    224   g_object_unref(info->icon_file);
    225 
    226 skip_comparison:
    227   info->icon_file = file_object;
    228 
    229   if (info->icon)
    230     g_object_unref(info->icon);
    231 
    232   info->icon = g_file_icon_new(file_object);
    233 
    234   if (!(info->task))
    235     info->task = util_idle_add(G_SOURCE_FUNC(_task_update_avatars), info);
    236 }
    237 
    238 static enum GNUNET_GenericReturnValue
    239 _account_iterate_attribute(void *cls,
    240                            struct GNUNET_CHAT_Account *account,
    241                            const char *name,
    242                            const char *value)
    243 {
    244   g_assert((cls) && (account) && (name));
    245 
    246   struct GNUNET_CHAT_Handle *handle = (struct GNUNET_CHAT_Handle*) cls;
    247 
    248   MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account);
    249 
    250   if (!info)
    251     return GNUNET_NO;
    252 
    253   if ((0 != strcmp(name, GNUNET_CHAT_ATTRIBUTE_AVATAR)) || (!value))
    254     return GNUNET_YES;
    255 
    256   struct GNUNET_CHAT_Uri *uri = GNUNET_CHAT_uri_parse(value, NULL);
    257 
    258   if (!uri)
    259     return GNUNET_YES;
    260 
    261   struct GNUNET_CHAT_File *file = GNUNET_CHAT_request_file(handle, uri);
    262 
    263   if (!file)
    264     goto skip_file;
    265 
    266   if (GNUNET_YES == GNUNET_CHAT_file_is_ready(file))
    267     _info_profile_downloaded(
    268       info->account,
    269       file,
    270       GNUNET_CHAT_file_get_local_size(file),
    271       GNUNET_CHAT_file_get_size(file)
    272     );
    273   else if (GNUNET_YES != GNUNET_CHAT_file_is_downloading(file))
    274     GNUNET_CHAT_file_start_download(
    275       file,
    276       _info_profile_downloaded,
    277       info->account
    278     );
    279 
    280 skip_file:
    281   GNUNET_CHAT_uri_destroy(uri);
    282   return GNUNET_YES;
    283 }
    284 
    285 void
    286 account_update_attributes(const struct GNUNET_CHAT_Account *account,
    287                           MESSENGER_Application *app)
    288 {
    289   g_assert(app);
    290 
    291   MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account);
    292 
    293   if ((!info) || (!(info->account)))
    294     return;
    295 
    296   GNUNET_CHAT_account_get_attributes(
    297     app->chat.messenger.handle,
    298     info->account,
    299     _account_iterate_attribute,
    300     app->chat.messenger.handle
    301   );
    302 }