commit 7521023e5e1bd2df76006418085f7ef5e1246abe
parent 8885ce815870361670c5d12d757ab01f189b73b9
Author: Jacki <jacki@thejackimonster.de>
Date: Thu, 25 Apr 2024 20:27:27 +0200
Allow setting profile picture during creation
Signed-off-by: Jacki <jacki@thejackimonster.de>
Diffstat:
9 files changed, 198 insertions(+), 15 deletions(-)
diff --git a/resources/ui/contact_info.ui b/resources/ui/contact_info.ui
@@ -190,7 +190,7 @@ Author: Tobias Frisch
<child>
<object class="GtkFileChooserButton" id="profile_chooser_button">
<property name="can-focus">False</property>
- <property name="title" translatable="yes"/>
+ <property name="title" translatable="yes">Select profile picture</property>
</object>
<packing>
<property name="expand">False</property>
diff --git a/resources/ui/new_account.ui b/resources/ui/new_account.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.38.2
+<!-- Generated with glade 3.40.0
Copyright (C) 2021‑‑2022 GNUnet e.V.
@@ -125,7 +125,7 @@ Author: Tobias Frisch
<object class="GtkFileChooserButton" id="account_avatar_file">
<property name="visible">True</property>
<property name="can-focus">False</property>
- <property name="title" translatable="yes"/>
+ <property name="title" translatable="yes">Select profile picture</property>
</object>
<packing>
<property name="expand">False</property>
diff --git a/src/account.c b/src/account.c
@@ -126,6 +126,37 @@ account_add_name_avatar_to_info(const struct GNUNET_CHAT_Account *account,
}
void
+account_switch_name_avatar_to_info(const struct GNUNET_CHAT_Account *account,
+ HdyAvatar *avatar)
+{
+ g_assert(avatar);
+
+ MESSENGER_AccountInfo *info = GNUNET_CHAT_account_get_user_pointer(account);
+
+ if (!info)
+ return;
+
+ if (g_list_find(info->name_avatars, avatar))
+ return;
+
+ GList *list = infos;
+ while (list)
+ {
+ MESSENGER_AccountInfo *other = (MESSENGER_AccountInfo*) list->data;
+
+ if (g_list_find(other->name_avatars, avatar))
+ {
+ account_remove_name_avatar_from_info(other->account, avatar);
+ break;
+ }
+
+ list = g_list_next(list);
+ }
+
+ account_add_name_avatar_to_info(account, avatar);
+}
+
+void
account_remove_name_avatar_from_info(const struct GNUNET_CHAT_Account *account,
HdyAvatar *avatar)
{
diff --git a/src/account.h b/src/account.h
@@ -78,6 +78,18 @@ account_add_name_avatar_to_info(const struct GNUNET_CHAT_Account *account,
HdyAvatar *avatar);
/**
+ * Switches a HdyAvatar to the list of avatars
+ * in case it's in another list. Otherwise it
+ * gets added as usual.
+ *
+ * @param account Chat account
+ * @param avatar Avatar
+ */
+void
+account_switch_name_avatar_to_info(const struct GNUNET_CHAT_Account *account,
+ HdyAvatar *avatar);
+
+/**
* Removes a HdyAvatar from the list of avatars
* which get updated by state changes.
*
diff --git a/src/event.c b/src/event.c
@@ -126,8 +126,8 @@ _iterate_reload_account(void *cls,
MESSENGER_Application *app = (MESSENGER_Application*) cls;
- if (GNUNET_YES == account_create_info(account))
- account_update_attributes(account, app);
+ account_create_info(account);
+ account_update_attributes(account, app);
return GNUNET_YES;
}
@@ -135,8 +135,6 @@ _iterate_reload_account(void *cls,
static void
_reload_accounts(MESSENGER_Application *app)
{
- account_cleanup_infos();
-
GNUNET_CHAT_iterate_accounts(
app->chat.messenger.handle,
_iterate_reload_account,
@@ -330,6 +328,9 @@ event_update_profile(MESSENGER_Application *app)
{
g_assert(app);
+ if (app->ui.new_account.dialog)
+ ui_new_account_dialog_update(app, &(app->ui.new_account));
+
UI_MESSENGER_Handle *ui = &(app->ui.messenger);
CHAT_MESSENGER_Handle *chat = &(app->chat.messenger);
@@ -337,7 +338,7 @@ event_update_profile(MESSENGER_Application *app)
const char *name = GNUNET_CHAT_get_name(chat->handle);
- account_add_name_avatar_to_info(
+ account_switch_name_avatar_to_info(
GNUNET_CHAT_get_connected(chat->handle),
ui->profile_avatar
);
@@ -949,8 +950,6 @@ _iterate_contacts_update_own(void *cls,
if (GNUNET_YES != GNUNET_CHAT_contact_is_owned(contact))
return GNUNET_YES;
- printf("contact-update! %s\n", GNUNET_CHAT_contact_get_name(contact));
-
contact_update_attributes(contact, app);
return GNUNET_YES;
}
@@ -969,8 +968,6 @@ event_update_attributes(MESSENGER_Application *app)
if (account)
account_update_attributes(account, app);
- printf("update!\n");
-
GNUNET_CHAT_iterate_contacts(
chat->handle,
_iterate_contacts_update_own,
diff --git a/src/ui/contact_info.c b/src/ui/contact_info.c
@@ -124,6 +124,7 @@ handle_profile_chooser_update_preview(GtkFileChooser *file_chooser,
goto skip_avatar;
hdy_avatar_set_loadable_icon(avatar, G_LOADABLE_ICON(icon));
+ g_object_unref(icon);
have_preview = true;
skip_avatar:
diff --git a/src/ui/messenger.c b/src/ui/messenger.c
@@ -389,6 +389,8 @@ handle_main_window_destroy(UNUSED GtkWidget *window,
ui_messenger_cleanup(&(app->ui.messenger));
ui_accounts_dialog_cleanup(&(app->ui.accounts), app);
+ account_cleanup_infos();
+
application_exit(app, MESSENGER_QUIT);
}
diff --git a/src/ui/new_account.c b/src/ui/new_account.c
@@ -25,6 +25,8 @@
#include "new_account.h"
#include "../application.h"
+#include "../contact.h"
+#include "../file.h"
#include "../ui.h"
static gboolean
@@ -85,8 +87,59 @@ handle_account_entry_activate(UNUSED GtkEntry *entry,
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
_open_new_account(app->ui.new_account.account_entry, app);
+}
- gtk_window_close(GTK_WINDOW(app->ui.new_account.dialog));
+static void
+handle_account_avatar_file_update_preview(GtkFileChooser *file_chooser,
+ gpointer user_data)
+{
+ g_assert((file_chooser) && (user_data));
+
+ HdyAvatar *avatar = HDY_AVATAR(user_data);
+
+ gboolean have_preview = false;
+ gchar *filename = gtk_file_chooser_get_preview_filename(file_chooser);
+
+ if ((!filename) || (!g_file_test(filename, G_FILE_TEST_IS_REGULAR)))
+ goto skip_preview;
+
+ GFile *file = g_file_new_for_path(filename);
+
+ if (!file)
+ goto skip_icon;
+
+ GIcon *icon = g_file_icon_new(file);
+
+ if (!icon)
+ goto skip_avatar;
+
+ hdy_avatar_set_loadable_icon(avatar, G_LOADABLE_ICON(icon));
+ g_object_unref(icon);
+ have_preview = true;
+
+skip_avatar:
+ g_object_unref(file);
+
+skip_icon:
+ g_free(filename);
+
+skip_preview:
+ gtk_file_chooser_set_preview_widget_active(file_chooser, have_preview);
+}
+
+static void
+handle_account_avatar_file_set(GtkFileChooserButton *button,
+ gpointer user_data)
+{
+ g_assert(user_data);
+
+ GtkFileChooser *file_chooser = GTK_FILE_CHOOSER(button);
+ UI_NEW_ACCOUNT_Handle *handle = (UI_NEW_ACCOUNT_Handle*) user_data;
+
+ if (handle->filename)
+ g_free(handle->filename);
+
+ handle->filename = gtk_file_chooser_get_preview_filename(file_chooser);
}
static void
@@ -108,8 +161,6 @@ handle_confirm_button_click(UNUSED GtkButton *button,
MESSENGER_Application *app = (MESSENGER_Application*) user_data;
_open_new_account(app->ui.new_account.account_entry, app);
-
- gtk_window_close(GTK_WINDOW(app->ui.new_account.dialog));
}
static void
@@ -156,6 +207,20 @@ ui_new_account_dialog_init(MESSENGER_Application *app,
gtk_builder_get_object(handle->builder, "account_avatar_file")
);
+ g_signal_connect(
+ handle->account_avatar_file,
+ "update-preview",
+ G_CALLBACK(handle_account_avatar_file_update_preview),
+ handle->account_avatar
+ );
+
+ g_signal_connect(
+ handle->account_avatar_file,
+ "file-set",
+ G_CALLBACK(handle_account_avatar_file_set),
+ handle
+ );
+
handle->account_entry = GTK_ENTRY(
gtk_builder_get_object(handle->builder, "account_entry")
);
@@ -204,6 +269,65 @@ ui_new_account_dialog_init(MESSENGER_Application *app,
);
}
+static void
+_cb_file_upload(void *cls,
+ struct GNUNET_CHAT_File *file,
+ uint64_t completed,
+ uint64_t size)
+{
+ g_assert((cls) && (file));
+
+ MESSENGER_Application *app = (MESSENGER_Application*) cls;
+
+ file_update_upload_info(file, completed, size);
+
+ if (completed < size)
+ return;
+
+ struct GNUNET_CHAT_Uri *uri = GNUNET_CHAT_file_get_uri(file);
+
+ if (!uri)
+ return;
+
+ char *uri_string = GNUNET_CHAT_uri_to_string(uri);
+
+ if (uri_string)
+ {
+ GNUNET_CHAT_set_attribute(
+ app->chat.messenger.handle,
+ ATTRIBUTE_PROFILE_PICTURE,
+ uri_string,
+ GNUNET_TIME_relative_get_forever_()
+ );
+
+ GNUNET_free(uri_string);
+ }
+
+ GNUNET_CHAT_uri_destroy(uri);
+}
+
+void
+ui_new_account_dialog_update(MESSENGER_Application *app,
+ UI_NEW_ACCOUNT_Handle *handle)
+{
+ g_assert((app) && (handle));
+
+ gtk_window_close(GTK_WINDOW(app->ui.new_account.dialog));
+
+ if (!(handle->filename))
+ return;
+
+ GNUNET_CHAT_upload_file(
+ app->chat.messenger.handle,
+ handle->filename,
+ _cb_file_upload,
+ app
+ );
+
+ g_free(handle->filename);
+ handle->filename = NULL;
+}
+
void
ui_new_account_dialog_cleanup(UI_NEW_ACCOUNT_Handle *handle)
{
@@ -211,6 +335,9 @@ ui_new_account_dialog_cleanup(UI_NEW_ACCOUNT_Handle *handle)
g_object_unref(handle->builder);
+ if (handle->filename)
+ g_free(handle->filename);
+
guint show = handle->show_queued;
memset(handle, 0, sizeof(*handle));
handle->show_queued = show;
diff --git a/src/ui/new_account.h b/src/ui/new_account.h
@@ -30,6 +30,7 @@
typedef struct UI_NEW_ACCOUNT_Handle
{
guint show_queued;
+ gchar *filename;
GtkBuilder *builder;
GtkDialog *dialog;
@@ -55,6 +56,18 @@ ui_new_account_dialog_init(MESSENGER_Application *app,
UI_NEW_ACCOUNT_Handle *handle);
/**
+ * Triggers an update of a new account dialog handle
+ * to process selected changes regarding the new
+ * account and finish account creation.
+ *
+ * @param app Messenger application
+ * @param handle New account dialog handle
+ */
+void
+ui_new_account_dialog_update(MESSENGER_Application *app,
+ UI_NEW_ACCOUNT_Handle *handle);
+
+/**
* Cleans up the allocated resources and resets the
* state of a given new account dialog handle.
*