new_account.c (7812B)
1 /* 2 This file is part of GNUnet. 3 Copyright (C) 2021--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 ui/new_account.c 23 */ 24 25 #include "new_account.h" 26 27 #include "../application.h" 28 #include "../contact.h" 29 #include "../file.h" 30 #include "../ui.h" 31 32 static void 33 _open_new_account(GtkEntry *entry, 34 MESSENGER_Application *app) 35 { 36 g_assert((entry) && (app)); 37 38 const gchar *name = gtk_entry_get_text(entry); 39 40 application_chat_lock(app); 41 42 const enum GNUNET_GenericReturnValue result = GNUNET_CHAT_account_create( 43 app->chat.messenger.handle, name 44 ); 45 46 application_chat_unlock(app); 47 48 if (GNUNET_OK != result) 49 return; 50 51 app->ui.state = MESSENGER_STATE_NEW_ACCOUNT; 52 53 gtk_list_box_unselect_all(app->ui.messenger.accounts_listbox); 54 gtk_widget_set_sensitive(GTK_WIDGET(app->ui.new_account.dialog), FALSE); 55 } 56 57 static void 58 handle_account_entry_changed(GtkEditable *editable, 59 gpointer user_data) 60 { 61 g_assert((editable) && (user_data)); 62 63 UI_NEW_ACCOUNT_Handle *handle = (UI_NEW_ACCOUNT_Handle*) user_data; 64 65 const gchar *text = gtk_entry_get_text(GTK_ENTRY(editable)); 66 67 hdy_avatar_set_text(handle->account_avatar, text); 68 69 gtk_widget_set_sensitive( 70 GTK_WIDGET(handle->confirm_button), 71 (text) && (strlen(text) > 0) 72 ); 73 } 74 75 static void 76 handle_account_entry_activate(UNUSED GtkEntry *entry, 77 gpointer user_data) 78 { 79 g_assert(user_data); 80 81 MESSENGER_Application *app = (MESSENGER_Application*) user_data; 82 83 _open_new_account(app->ui.new_account.account_entry, app); 84 } 85 86 static void 87 handle_account_avatar_file_update_preview(GtkFileChooser *file_chooser, 88 gpointer user_data) 89 { 90 g_assert((file_chooser) && (user_data)); 91 92 HdyAvatar *avatar = HDY_AVATAR(user_data); 93 94 gboolean have_preview = false; 95 gchar *filename = gtk_file_chooser_get_preview_filename(file_chooser); 96 97 if ((!filename) || (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))) 98 goto skip_preview; 99 100 GFile *file = g_file_new_for_path(filename); 101 102 if (!file) 103 goto skip_icon; 104 105 GIcon *icon = g_file_icon_new(file); 106 107 if (!icon) 108 goto skip_avatar; 109 110 hdy_avatar_set_loadable_icon(avatar, G_LOADABLE_ICON(icon)); 111 g_object_unref(icon); 112 have_preview = true; 113 114 skip_avatar: 115 g_object_unref(file); 116 117 skip_icon: 118 g_free(filename); 119 120 skip_preview: 121 gtk_file_chooser_set_preview_widget_active(file_chooser, have_preview); 122 } 123 124 static void 125 handle_account_avatar_file_set(GtkFileChooserButton *button, 126 gpointer user_data) 127 { 128 g_assert(user_data); 129 130 GtkFileChooser *file_chooser = GTK_FILE_CHOOSER(button); 131 UI_NEW_ACCOUNT_Handle *handle = (UI_NEW_ACCOUNT_Handle*) user_data; 132 133 if (handle->filename) 134 g_free(handle->filename); 135 136 handle->filename = gtk_file_chooser_get_preview_filename(file_chooser); 137 } 138 139 static void 140 handle_cancel_button_click(UNUSED GtkButton *button, 141 gpointer user_data) 142 { 143 g_assert(user_data); 144 145 GtkDialog *dialog = GTK_DIALOG(user_data); 146 gtk_window_close(GTK_WINDOW(dialog)); 147 } 148 149 static void 150 handle_confirm_button_click(UNUSED GtkButton *button, 151 gpointer user_data) 152 { 153 g_assert(user_data); 154 155 MESSENGER_Application *app = (MESSENGER_Application*) user_data; 156 157 _open_new_account(app->ui.new_account.account_entry, app); 158 } 159 160 static void 161 handle_dialog_destroy(UNUSED GtkWidget *window, 162 gpointer user_data) 163 { 164 g_assert(user_data); 165 166 MESSENGER_Application *app = (MESSENGER_Application*) user_data; 167 168 ui_new_account_dialog_cleanup(&(app->ui.new_account)); 169 170 if (MESSENGER_STATE_MAIN_WINDOW == app->ui.state) 171 return; 172 173 gtk_widget_destroy(GTK_WIDGET(app->ui.messenger.main_window)); 174 } 175 176 void 177 ui_new_account_dialog_init(MESSENGER_Application *app, 178 UI_NEW_ACCOUNT_Handle *handle) 179 { 180 g_assert((app) && (handle)); 181 182 handle->builder = ui_builder_from_resource( 183 application_get_resource_path(app, "ui/new_account.ui") 184 ); 185 186 handle->dialog = GTK_DIALOG( 187 gtk_builder_get_object(handle->builder, "new_account_dialog") 188 ); 189 190 gtk_window_set_transient_for( 191 GTK_WINDOW(handle->dialog), 192 GTK_WINDOW(app->ui.messenger.main_window) 193 ); 194 195 handle->account_avatar = HDY_AVATAR( 196 gtk_builder_get_object(handle->builder, "account_avatar") 197 ); 198 199 handle->account_avatar_file = GTK_FILE_CHOOSER_BUTTON( 200 gtk_builder_get_object(handle->builder, "account_avatar_file") 201 ); 202 203 g_signal_connect( 204 handle->account_avatar_file, 205 "update-preview", 206 G_CALLBACK(handle_account_avatar_file_update_preview), 207 handle->account_avatar 208 ); 209 210 g_signal_connect( 211 handle->account_avatar_file, 212 "file-set", 213 G_CALLBACK(handle_account_avatar_file_set), 214 handle 215 ); 216 217 handle->account_entry = GTK_ENTRY( 218 gtk_builder_get_object(handle->builder, "account_entry") 219 ); 220 221 g_signal_connect( 222 handle->account_entry, 223 "changed", 224 G_CALLBACK(handle_account_entry_changed), 225 handle 226 ); 227 228 g_signal_connect( 229 handle->account_entry, 230 "activate", 231 G_CALLBACK(handle_account_entry_activate), 232 app 233 ); 234 235 handle->cancel_button = GTK_BUTTON( 236 gtk_builder_get_object(handle->builder, "cancel_button") 237 ); 238 239 g_signal_connect( 240 handle->cancel_button, 241 "clicked", 242 G_CALLBACK(handle_cancel_button_click), 243 handle->dialog 244 ); 245 246 handle->confirm_button = GTK_BUTTON( 247 gtk_builder_get_object(handle->builder, "confirm_button") 248 ); 249 250 g_signal_connect( 251 handle->confirm_button, 252 "clicked", 253 G_CALLBACK(handle_confirm_button_click), 254 app 255 ); 256 257 g_signal_connect( 258 handle->dialog, 259 "destroy", 260 G_CALLBACK(handle_dialog_destroy), 261 app 262 ); 263 } 264 265 static void 266 _cb_file_upload(void *cls, 267 struct GNUNET_CHAT_File *file, 268 uint64_t completed, 269 uint64_t size) 270 { 271 g_assert((cls) && (file)); 272 273 MESSENGER_Application *app = (MESSENGER_Application*) cls; 274 275 file_update_upload_info(file, completed, size); 276 277 if (completed < size) 278 return; 279 280 struct GNUNET_CHAT_Uri *uri = GNUNET_CHAT_file_get_uri(file); 281 282 if (!uri) 283 return; 284 285 char *uri_string = GNUNET_CHAT_uri_to_string(uri); 286 287 if (uri_string) 288 { 289 GNUNET_CHAT_set_attribute( 290 app->chat.messenger.handle, 291 GNUNET_CHAT_ATTRIBUTE_AVATAR, 292 uri_string 293 ); 294 295 GNUNET_free(uri_string); 296 } 297 298 GNUNET_CHAT_uri_destroy(uri); 299 } 300 301 void 302 ui_new_account_dialog_update(MESSENGER_Application *app, 303 UI_NEW_ACCOUNT_Handle *handle) 304 { 305 g_assert((app) && (handle)); 306 307 gtk_widget_set_sensitive(GTK_WIDGET(app->ui.new_account.dialog), TRUE); 308 gtk_window_close(GTK_WINDOW(app->ui.new_account.dialog)); 309 310 if (!(handle->filename)) 311 return; 312 313 GNUNET_CHAT_upload_file( 314 app->chat.messenger.handle, 315 handle->filename, 316 _cb_file_upload, 317 app 318 ); 319 320 g_free(handle->filename); 321 handle->filename = NULL; 322 } 323 324 void 325 ui_new_account_dialog_cleanup(UI_NEW_ACCOUNT_Handle *handle) 326 { 327 g_assert(handle); 328 329 g_object_unref(handle->builder); 330 331 if (handle->filename) 332 g_free(handle->filename); 333 334 memset(handle, 0, sizeof(*handle)); 335 }