messenger-gtk

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

commit 9c4c0589f3d50425bd51c830f49110a107d3c541
parent 11bef15928c414e2a26e8e4b63104dd684bf60f2
Author: Jacki <jacki@thejackimonster.de>
Date:   Sun, 16 Jun 2024 01:16:24 +0200

Implement buttons switching icons on interaction

Signed-off-by: Jacki <jacki@thejackimonster.de>

Diffstat:
Mresources/ui/discourse.ui | 16++++++----------
Aresources/ui/discourse_panel.ui | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ui/chat.c | 2+-
Msrc/ui/discourse.c | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ui/discourse.h | 14++++++++++++++
5 files changed, 265 insertions(+), 11 deletions(-)

diff --git a/resources/ui/discourse.ui b/resources/ui/discourse.ui @@ -129,7 +129,7 @@ Author: Tobias Frisch <property name="receives-default">True</property> <property name="relief">none</property> <child> - <object class="GtkStack"> + <object class="GtkStack" id="microphone_stack"> <property name="visible">True</property> <property name="can-focus">False</property> <child> @@ -139,8 +139,7 @@ Author: Tobias Frisch <property name="icon-name">microphone-sensitivity-high-symbolic</property> </object> <packing> - <property name="name">page0</property> - <property name="title" translatable="yes">page0</property> + <property name="name">on_page</property> </packing> </child> <child> @@ -150,8 +149,7 @@ Author: Tobias Frisch <property name="icon-name">microphone-sensitivity-muted-symbolic</property> </object> <packing> - <property name="name">page1</property> - <property name="title" translatable="yes">page1</property> + <property name="name">off_page</property> <property name="position">1</property> </packing> </child> @@ -248,7 +246,7 @@ audio-volume-medium-symbolic</property> <property name="receives-default">True</property> <property name="relief">none</property> <child> - <object class="GtkStack"> + <object class="GtkStack" id="call_stack"> <property name="visible">True</property> <property name="can-focus">False</property> <child> @@ -258,8 +256,7 @@ audio-volume-medium-symbolic</property> <property name="icon-name">call-start-symbolic</property> </object> <packing> - <property name="name">page0</property> - <property name="title" translatable="yes">page0</property> + <property name="name">start_page</property> </packing> </child> <child> @@ -269,8 +266,7 @@ audio-volume-medium-symbolic</property> <property name="icon-name">call-stop-symbolic</property> </object> <packing> - <property name="name">page1</property> - <property name="title" translatable="yes">page1</property> + <property name="name">stop_page</property> <property name="position">1</property> </packing> </child> diff --git a/resources/ui/discourse_panel.ui b/resources/ui/discourse_panel.ui @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Generated with glade 3.40.0 + +Copyright (C) 2024 GNUnet e.V. + +GNUnet is free software: you can redistribute it and/or modify it +under the terms of the GNU Affero General Public License as published +by the Free Software Foundation, either version 3 of the License, +or (at your option) any later version. + +GNUnet is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +SPDX-License-Identifier: AGPL3.0-or-later +Author: Tobias Frisch + +--> +<interface> + <requires lib="gtk+" version="3.24"/> + <requires lib="libhandy" version="1.2"/> + <object class="GtkBox" id="panel_box"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkStack" id="panel_stack"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkBox" id="avatar_box"> + <property name="width-request">140</property> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="border-width">8</property> + <property name="orientation">vertical</property> + <property name="spacing">4</property> + <child> + <object class="HdyAvatar" id="panel_avatar"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="icon-name">avatar-default</property> + <property name="size">80</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="panel_label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="wrap">True</property> + <property name="wrap-mode">word-char</property> + <property name="ellipsize">end</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="name">avatar_page</property> + </packing> + </child> + <child> + <object class="GtkDrawingArea" id="video_drawing_area"> + <property name="visible">True</property> + <property name="can-focus">False</property> + </object> + <packing> + <property name="name">video_page</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> +</interface> diff --git a/src/ui/chat.c b/src/ui/chat.c @@ -25,8 +25,8 @@ #include "chat.h" #include <gdk/gdkkeysyms.h> -#include <gnunet/gnunet_chat_lib.h> #include <gnunet/gnunet_common.h> +#include <gnunet/gnunet_chat_lib.h> #include <gnunet/gnunet_time_lib.h> #include <stdlib.h> diff --git a/src/ui/discourse.c b/src/ui/discourse.c @@ -24,11 +24,18 @@ #include "discourse.h" +#include <gnunet/gnunet_common.h> +#include <gnunet/gnunet_chat_lib.h> +#include <gnunet/gnunet_time_lib.h> + #include "account_entry.h" #include "../application.h" #include "../ui.h" #include "../util.h" +#include <gnunet/gnunet_chat_lib.h> +#include <gnunet/gnunet_common.h> +#include <string.h> static void handle_back_button_click(UNUSED GtkButton *button, @@ -70,6 +77,64 @@ handle_details_folded(GObject* object, } static void +_update_microphone_icon(UI_DISCOURSE_Handle *handle) +{ + g_assert(handle); + + if (handle->muted) + gtk_stack_set_visible_child(handle->microphone_stack, handle->microphone_off_icon); + else + gtk_stack_set_visible_child(handle->microphone_stack, handle->microphone_on_icon); +} + +static void +handle_microphone_button_click(UNUSED GtkButton *button, + gpointer user_data) +{ + g_assert(user_data); + + UI_DISCOURSE_Handle *handle = (UI_DISCOURSE_Handle*) user_data; + + handle->muted = !(handle->muted); + _update_microphone_icon(handle); +} + +static void +handle_call_button_click(UNUSED GtkButton *button, + gpointer user_data) +{ + g_assert(user_data); + + UI_DISCOURSE_Handle *handle = (UI_DISCOURSE_Handle*) user_data; + + if (!(handle->context)) + return; + + const gboolean calling = ( + (handle->voice_discourse) && + (GNUNET_YES == GNUNET_CHAT_discourse_is_open(handle->voice_discourse)) + ); + + struct GNUNET_ShortHashCode voice_id; + memset(&voice_id, 0, sizeof(voice_id)); + + if (calling) + { + GNUNET_CHAT_discourse_close(handle->voice_discourse); + handle->voice_discourse = NULL; + } + else + handle->voice_discourse = GNUNET_CHAT_context_open_discourse( + handle->context, &voice_id + ); + + if (handle->voice_discourse) + gtk_stack_set_visible_child(handle->call_stack, handle->call_stop_icon); + else + gtk_stack_set_visible_child(handle->call_stack, handle->call_start_icon); +} + +static void handle_window_destroy(UNUSED GtkWidget *window, gpointer user_data) { @@ -87,6 +152,9 @@ ui_discourse_window_init(MESSENGER_Application *app, handle->app = app; handle->context = NULL; + handle->voice_discourse = NULL; + handle->muted = TRUE; + handle->parent = GTK_WINDOW(app->ui.messenger.main_window); handle->builder = ui_builder_from_resource( @@ -152,6 +220,13 @@ ui_discourse_window_init(MESSENGER_Application *app, gtk_builder_get_object(handle->builder, "microphone_button") ); + g_signal_connect( + handle->microphone_button, + "clicked", + G_CALLBACK(handle_microphone_button_click), + handle + ); + handle->camera_button = GTK_BUTTON( gtk_builder_get_object(handle->builder, "camera_button") ); @@ -168,6 +243,37 @@ ui_discourse_window_init(MESSENGER_Application *app, gtk_builder_get_object(handle->builder, "call_button") ); + g_signal_connect( + handle->call_button, + "clicked", + G_CALLBACK(handle_call_button_click), + handle + ); + + handle->microphone_stack = GTK_STACK( + gtk_builder_get_object(handle->builder, "microphone_stack") + ); + + handle->microphone_on_icon = GTK_WIDGET( + gtk_builder_get_object(handle->builder, "microphone_on_icon") + ); + + handle->microphone_off_icon = GTK_WIDGET( + gtk_builder_get_object(handle->builder, "microphone_off_icon") + ); + + handle->call_stack = GTK_STACK( + gtk_builder_get_object(handle->builder, "call_stack") + ); + + handle->call_start_icon = GTK_WIDGET( + gtk_builder_get_object(handle->builder, "call_start_icon") + ); + + handle->call_stop_icon = GTK_WIDGET( + gtk_builder_get_object(handle->builder, "call_stop_icon") + ); + handle->close_details_button = GTK_BUTTON( gtk_builder_get_object(handle->builder, "close_details_button") ); @@ -193,6 +299,49 @@ ui_discourse_window_init(MESSENGER_Application *app, gtk_widget_show_all(GTK_WIDGET(handle->window)); } +static enum GNUNET_GenericReturnValue +iterate_ui_discourse_update_discourse_members(void *cls, + const struct GNUNET_CHAT_Discourse *discourse, + struct GNUNET_CHAT_Contact *contact) +{ + UI_DISCOURSE_Handle *handle = (UI_DISCOURSE_Handle*) cls; + + printf("%s\n", GNUNET_CHAT_contact_get_name(contact)); + + return GNUNET_YES; +} + +static enum GNUNET_GenericReturnValue +iterate_ui_discourse_update_context_discourses(void *cls, + UNUSED struct GNUNET_CHAT_Context *context, + struct GNUNET_CHAT_Discourse *discourse) +{ + UI_DISCOURSE_Handle *handle = (UI_DISCOURSE_Handle*) cls; + + GNUNET_CHAT_discourse_iterate_contacts( + discourse, + iterate_ui_discourse_update_discourse_members, + handle + ); + + return GNUNET_YES; +} + +static void +_discourse_update_members(UI_DISCOURSE_Handle *handle) +{ + g_assert(handle); + + if (!(handle->context)) + return; + + GNUNET_CHAT_context_iterate_discourses( + handle->context, + iterate_ui_discourse_update_context_discourses, + handle + ); +} + struct IterateChatClosure { MESSENGER_Application *app; GtkContainer *container; @@ -287,6 +436,9 @@ ui_discourse_window_update(UI_DISCOURSE_Handle *handle, handle->context = context; + _update_microphone_icon(handle); + _discourse_update_members(handle); + struct GNUNET_CHAT_Group* group = GNUNET_CHAT_context_get_group( handle->context ); diff --git a/src/ui/discourse.h b/src/ui/discourse.h @@ -27,6 +27,8 @@ #include "messenger.h" +#include <gnunet/gnunet_chat_lib.h> + #include <glib-2.0/glib.h> #include <gstreamer-1.0/gst/gst.h> #include <pthread.h> @@ -36,6 +38,10 @@ typedef struct UI_DISCOURSE_Handle MESSENGER_Application *app; struct GNUNET_CHAT_Context *context; + struct GNUNET_CHAT_Discourse *voice_discourse; + + gboolean muted; + GtkWindow *parent; GtkBuilder *builder; @@ -55,6 +61,14 @@ typedef struct UI_DISCOURSE_Handle GtkVolumeButton *speakers_button; GtkButton *call_button; + GtkStack *microphone_stack; + GtkWidget *microphone_on_icon; + GtkWidget *microphone_off_icon; + + GtkStack *call_stack; + GtkWidget *call_start_icon; + GtkWidget *call_stop_icon; + GtkButton *close_details_button; GtkListBox *contacts_listbox; } UI_DISCOURSE_Handle;