From 9b67d565baf5ce0f555cb38abdda22696cbfe778 Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Thu, 25 Nov 2021 22:45:04 +0100 Subject: Added emoji picker Signed-off-by: TheJackiMonster --- .gitmodules | 3 + Makefile | 5 +- resources/css/style.css | 8 + resources/ui/chat.ui | 19 +- resources/ui/picker.ui | 508 ++++++++++++++++++++++++++++++++++++++++++++ src/application.c | 2 - src/ui/chat.c | 35 ++- src/ui/chat.h | 5 + src/ui/messenger.c | 2 + src/ui/picker.c | 251 ++++++++++++++++++++++ src/ui/picker.h | 65 ++++++ submodules/gnome-characters | 1 + 12 files changed, 898 insertions(+), 6 deletions(-) create mode 100644 .gitmodules create mode 100644 resources/ui/picker.ui create mode 100644 src/ui/picker.c create mode 100644 src/ui/picker.h create mode 160000 submodules/gnome-characters diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..65ecbeb --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "submodules/gnome-characters"] + path = submodules/gnome-characters + url = https://gitlab.gnome.org/GNOME/gnome-characters.git diff --git a/Makefile b/Makefile index 2869414..6484d14 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ SOURCES = messenger_gtk.c\ ui/messenger.c\ ui/new_contact.c\ ui/new_platform.c\ + ui/picker.c\ ui/profile_entry.c\ ui/settings.c @@ -22,6 +23,7 @@ HEADERS = LIBRARIES = gnunetchat PACKAGES = gnunetutil libhandy-1 gtk+-3.0 libnotify zbar libqrencode +INCLUDES = submodules/gnome-characters/lib GNU_CC ?= gcc GNU_LD ?= gcc @@ -38,6 +40,7 @@ OBJECT_FILES = $(SOURCE_FILES:%.c=%.o) HEADER_FILES = $(addprefix $(SOURCE_DIR), $(HEADERS)) LIBRARY_FLAGS = $(addprefix -l, $(LIBRARIES)) PACKAGE_FLAGS = $(shell pkg-config --cflags --libs $(PACKAGES)) +INCLUDE_FLAGS = $(addprefix -I, $(INCLUDES)) all: $(BINARY) @@ -48,7 +51,7 @@ release: CFLAGS += $(RELEASEFLAGS) release: $(BINARY) %.o: %.c - $(GNU_CC) $(CFLAGS) -c $< -o $@ $(LIBRARY_FLAGS) $(PACKAGE_FLAGS) + $(GNU_CC) $(CFLAGS) -c $< -o $@ $(LIBRARY_FLAGS) $(PACKAGE_FLAGS) $(INCLUDE_FLAGS) $(BINARY): $(OBJECT_FILES) $(GNU_LD) $(LDFLAGS) $^ -o $@ $(LIBRARY_FLAGS) $(PACKAGE_FLAGS) diff --git a/resources/css/style.css b/resources/css/style.css index a75a5e2..1f923d6 100644 --- a/resources/css/style.css +++ b/resources/css/style.css @@ -61,6 +61,14 @@ padding: 2px 4px; } +.picker-switcher-box { + padding: 0px 8px; +} + +.emoji-flow-box { + font-size: large; +} + .settings-entry { margin: 8px; } diff --git a/resources/ui/chat.ui b/resources/ui/chat.ui index c653b3e..f6e8cc8 100644 --- a/resources/ui/chat.ui +++ b/resources/ui/chat.ui @@ -168,6 +168,22 @@ Author: Tobias Frisch 1 + + + True + False + slide-up + + + + + + False + True + end + 2 + + True @@ -263,7 +279,8 @@ Author: Tobias Frisch False True - 2 + end + 3 diff --git a/resources/ui/picker.ui b/resources/ui/picker.ui new file mode 100644 index 0000000..fec48e5 --- /dev/null +++ b/resources/ui/picker.ui @@ -0,0 +1,508 @@ + + + + + + + 250 + True + False + vertical + + + True + False + + + True + False + vertical + + + True + True + never + in + + + True + False + + + True + False + emoji_stack + True + + + + + + + False + True + 0 + + + + + True + False + + + True + True + in + + + True + False + + + True + False + 8 + True + 8 + none + + + + + + + + recent + emoji-recent-symbolic + + + + + True + True + in + + + True + False + + + True + False + 8 + True + 8 + none + + + + + + + + people + emoji-people-symbolic + 1 + + + + + True + True + in + + + True + False + + + True + False + 8 + True + 8 + none + + + + + + + + nature + emoji-nature-symbolic + 2 + + + + + True + True + in + + + True + False + + + True + False + 8 + True + 8 + none + + + + + + + + food + emoji-food-symbolic + 3 + + + + + True + True + in + + + True + False + + + True + False + 8 + True + 8 + none + + + + + + + + activities + emoji-activities-symbolic + 4 + + + + + True + True + in + + + True + False + + + True + False + 8 + True + 8 + none + + + + + + + + travel + emoji-travel-symbolic + 5 + + + + + True + True + in + + + True + False + + + True + False + 8 + True + 8 + none + + + + + + + + objects + emoji-objects-symbolic + 6 + + + + + True + True + in + + + True + False + + + True + False + 8 + True + 8 + none + + + + + + + + symbols + emoji-symbols-symbolic + 7 + + + + + True + True + in + + + True + False + + + True + False + 8 + True + 8 + none + + + + + + + + flags + emoji-flags-symbolic + 8 + + + + + True + True + end + 1 + + + + + True + False + True + + + True + True + edit-find-symbolic + False + False + + + + + False + True + 2 + + + + + emoji + Emoji + face-smile-symbolic + + + + + True + False + vertical + + + + + + + + + + + + gif + GIF + video-x-generic-symbolic + 1 + + + + + True + False + vertical + + + + + + + + + + + + stickers + Stickers + image-x-generic-symbolic + 2 + + + + + True + True + 1 + + + + + True + False + + + True + True + True + center + none + + + True + False + system-search-symbolic + + + + + False + True + 0 + + + + + True + False + auto + picker_stack + True + + + True + True + 1 + + + + + True + True + True + center + none + + + True + False + preferences-other-symbolic + + + + + False + True + end + 2 + + + + + + False + True + 3 + + + + diff --git a/src/application.c b/src/application.c index dfb214a..2062b82 100644 --- a/src/application.c +++ b/src/application.c @@ -157,8 +157,6 @@ application_run(MESSENGER_Application *app) pthread_join(app->chat.tid, NULL); - ui_messenger_cleanup(&(app->ui.messenger)); - g_hash_table_destroy(app->ui.bindings); notify_uninit(); diff --git a/src/ui/chat.c b/src/ui/chat.c index b4dcca9..42943c3 100644 --- a/src/ui/chat.c +++ b/src/ui/chat.c @@ -25,6 +25,7 @@ #include "chat.h" #include "messenger.h" +#include "picker.h" #include "../application.h" static void @@ -67,7 +68,7 @@ handle_send_text_buffer_changed(GtkTextBuffer *buffer, gtk_image_set_from_icon_name( symbol, - 0 < g_utf8_strlen(text, 1)? + 0 < strlen(text)? "mail-send-symbolic" : "audio-input-microphone-symbolic", GTK_ICON_SIZE_BUTTON @@ -86,7 +87,7 @@ _send_text_from_view(MESSENGER_Application *app, const gchar *text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); - if (0 == g_utf8_strlen(text, 1)) + if (0 == strlen(text)) return FALSE; struct GNUNET_CHAT_Context *context = g_hash_table_lookup( @@ -132,6 +133,16 @@ handle_send_text_key_press (GtkWidget *widget, return _send_text_from_view(app, GTK_TEXT_VIEW(widget)); } +static void +handle_picker_button_click(UNUSED GtkButton *button, + gpointer user_data) +{ + GtkRevealer *revealer = GTK_REVEALER(user_data); + gboolean reveal = !gtk_revealer_get_child_revealed(revealer); + + gtk_revealer_set_reveal_child(revealer, reveal); +} + UI_CHAT_Handle* ui_chat_new(MESSENGER_Application *app) { @@ -239,12 +250,32 @@ ui_chat_new(MESSENGER_Application *app) handle->send_text_view ); + handle->picker_revealer = GTK_REVEALER( + gtk_builder_get_object(handle->builder, "picker_revealer") + ); + + handle->picker = ui_picker_new(app, handle); + + gtk_container_add( + GTK_CONTAINER(handle->picker_revealer), + handle->picker->picker_box + ); + + g_signal_connect( + handle->emoji_button, + "clicked", + G_CALLBACK(handle_picker_button_click), + handle->picker_revealer + ); + return handle; } void ui_chat_delete(UI_CHAT_Handle *handle) { + ui_picker_delete(handle->picker); + g_object_unref(handle->builder); g_free(handle); diff --git a/src/ui/chat.h b/src/ui/chat.h index 250ac08..77e4553 100644 --- a/src/ui/chat.h +++ b/src/ui/chat.h @@ -30,6 +30,7 @@ #include typedef struct MESSENGER_Application MESSENGER_Application; +typedef struct UI_PICKER_Handle UI_PICKER_Handle; typedef struct UI_CHAT_Handle { @@ -49,6 +50,10 @@ typedef struct UI_CHAT_Handle GtkButton *emoji_button; GtkButton *send_record_button; GtkImage *send_record_symbol; + + GtkRevealer *picker_revealer; + + UI_PICKER_Handle *picker; } UI_CHAT_Handle; UI_CHAT_Handle* diff --git a/src/ui/messenger.c b/src/ui/messenger.c index 669ef19..8f463ca 100644 --- a/src/ui/messenger.c +++ b/src/ui/messenger.c @@ -150,6 +150,8 @@ handle_main_window_destroy(UNUSED GtkWidget *window, { MESSENGER_Application *app = (MESSENGER_Application*) user_data; + ui_messenger_cleanup(&(app->ui.messenger)); + application_exit(app, MESSENGER_QUIT); } diff --git a/src/ui/picker.c b/src/ui/picker.c new file mode 100644 index 0000000..f6c89a6 --- /dev/null +++ b/src/ui/picker.c @@ -0,0 +1,251 @@ +/* + This file is part of GNUnet. + Copyright (C) 2021 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 . + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/* + * @author Tobias Frisch + * @file ui/picker.c + */ + +#include "picker.h" + +#include "../application.h" + +#include + +static void +handle_emoji_button_click(GtkButton *button, + gpointer user_data) +{ + GtkTextView *text_view = GTK_TEXT_VIEW(user_data); + GtkTextBuffer *text_buffer = gtk_text_view_get_buffer(text_view); + + const gchar *label = gtk_button_get_label(button); + + if (label) + gtk_text_buffer_insert_at_cursor(text_buffer, label, strlen(label)); +} + +static void +_add_emoji_buttons(GtkFlowBox *flow_box, + GtkTextView *text_view, + size_t characters_count, + const uint32_t *characters) +{ + for (size_t i = 0; i < characters_count; i++) { + GString *string = g_string_new(""); + g_string_append_unichar(string, (gunichar) characters[i]); + + GtkButton *emoji_button = GTK_BUTTON( + gtk_button_new_with_label(string->str) + ); + + gtk_button_set_relief(emoji_button, GTK_RELIEF_NONE); + + g_signal_connect( + emoji_button, + "clicked", + G_CALLBACK(handle_emoji_button_click), + text_view + ); + + gtk_flow_box_insert(flow_box, GTK_WIDGET(emoji_button), -1); + gtk_widget_show(GTK_WIDGET(emoji_button)); + + g_string_free(string, TRUE); + } +} + +static void +handle_search_button_click(UNUSED GtkButton *button, + gpointer user_data) +{ + UI_PICKER_Handle *handle = (UI_PICKER_Handle*) user_data; + + const gchar* picked = gtk_stack_get_visible_child_name(handle->picker_stack); + + HdySearchBar *search_bar = NULL; + + if (0 == g_strcmp0(picked, "emoji")) + search_bar = handle->emoji_search_bar; + + if (search_bar) + hdy_search_bar_set_search_mode( + search_bar, + !hdy_search_bar_get_search_mode(search_bar) + ); +} + +UI_PICKER_Handle* +ui_picker_new(UNUSED MESSENGER_Application *app, + UI_CHAT_Handle *chat) +{ + UI_PICKER_Handle *handle = g_malloc(sizeof(UI_PICKER_Handle)); + + handle->builder = gtk_builder_new_from_file( + "resources/ui/picker.ui" + ); + + handle->picker_box = GTK_WIDGET( + gtk_builder_get_object(handle->builder, "picker_box") + ); + + handle->picker_stack = GTK_STACK( + gtk_builder_get_object(handle->builder, "picker_stack") + ); + + handle->emoji_stack = GTK_STACK( + gtk_builder_get_object(handle->builder, "emoji_stack") + ); + + handle->picker_switcher_bar = HDY_VIEW_SWITCHER_BAR( + gtk_builder_get_object(handle->builder, "picker_switcher_bar") + ); + + handle->emoji_switcher_bar = HDY_VIEW_SWITCHER_BAR( + gtk_builder_get_object(handle->builder, "emoji_switcher_bar") + ); + + handle->recent_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "recent_flow_box") + ); + + handle->people_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "people_flow_box") + ); + + _add_emoji_buttons( + handle->people_flow_box, + chat->send_text_view, + EMOJI_SMILEYS_CHARACTER_COUNT, + emoji_smileys_characters + ); + + handle->nature_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "nature_flow_box") + ); + + _add_emoji_buttons( + handle->nature_flow_box, + chat->send_text_view, + EMOJI_ANIMALS_CHARACTER_COUNT, + emoji_animals_characters + ); + + handle->food_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "food_flow_box") + ); + + _add_emoji_buttons( + handle->food_flow_box, + chat->send_text_view, + EMOJI_FOOD_CHARACTER_COUNT, + emoji_food_characters + ); + + handle->activities_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "activities_flow_box") + ); + + _add_emoji_buttons( + handle->activities_flow_box, + chat->send_text_view, + EMOJI_ACTIVITIES_CHARACTER_COUNT, + emoji_activities_characters + ); + + handle->travel_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "travel_flow_box") + ); + + _add_emoji_buttons( + handle->travel_flow_box, + chat->send_text_view, + EMOJI_TRAVEL_CHARACTER_COUNT, + emoji_travel_characters + ); + + handle->objects_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "objects_flow_box") + ); + + _add_emoji_buttons( + handle->objects_flow_box, + chat->send_text_view, + EMOJI_OBJECTS_CHARACTER_COUNT, + emoji_objects_characters + ); + + handle->symbols_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "symbols_flow_box") + ); + + _add_emoji_buttons( + handle->symbols_flow_box, + chat->send_text_view, + EMOJI_SYMBOLS_CHARACTER_COUNT, + emoji_symbols_characters + ); + + handle->flags_flow_box = GTK_FLOW_BOX( + gtk_builder_get_object(handle->builder, "flags_flow_box") + ); + + _add_emoji_buttons( + handle->flags_flow_box, + chat->send_text_view, + EMOJI_FLAGS_CHARACTER_COUNT, + emoji_flags_characters + ); + + handle->emoji_search_bar = HDY_SEARCH_BAR( + gtk_builder_get_object(handle->builder, "emoji_search_bar") + ); + + handle->emoji_search_entry = GTK_SEARCH_ENTRY( + gtk_builder_get_object(handle->builder, "emoji_search_entry") + ); + + handle->search_button = GTK_BUTTON( + gtk_builder_get_object(handle->builder, "search_button") + ); + + g_signal_connect( + handle->search_button, + "clicked", + G_CALLBACK(handle_search_button_click), + handle + ); + + handle->settings_button = GTK_BUTTON( + gtk_builder_get_object(handle->builder, "settings_button") + ); + + return handle; +} + +void +ui_picker_delete(UI_PICKER_Handle *handle) +{ + hdy_view_switcher_bar_set_stack(handle->picker_switcher_bar, NULL); + hdy_view_switcher_bar_set_stack(handle->emoji_switcher_bar, NULL); + + g_object_unref(handle->builder); + + g_free(handle); +} diff --git a/src/ui/picker.h b/src/ui/picker.h new file mode 100644 index 0000000..99c7fa2 --- /dev/null +++ b/src/ui/picker.h @@ -0,0 +1,65 @@ +/* + This file is part of GNUnet. + Copyright (C) 2021 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 . + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/* + * @author Tobias Frisch + * @file ui/picker.h + */ + +#ifndef UI_PICKER_H_ +#define UI_PICKER_H_ + +#include "chat.h" + +typedef struct UI_PICKER_Handle +{ + GtkBuilder *builder; + GtkWidget *picker_box; + + GtkStack *picker_stack; + GtkStack *emoji_stack; + + HdyViewSwitcherBar *picker_switcher_bar; + HdyViewSwitcherBar *emoji_switcher_bar; + + GtkFlowBox *recent_flow_box; + GtkFlowBox *people_flow_box; + GtkFlowBox *nature_flow_box; + GtkFlowBox *food_flow_box; + GtkFlowBox *activities_flow_box; + GtkFlowBox *travel_flow_box; + GtkFlowBox *objects_flow_box; + GtkFlowBox *symbols_flow_box; + GtkFlowBox *flags_flow_box; + + HdySearchBar *emoji_search_bar; + GtkSearchEntry *emoji_search_entry; + + GtkButton *search_button; + GtkButton *settings_button; +} UI_PICKER_Handle; + +UI_PICKER_Handle* +ui_picker_new(MESSENGER_Application *app, + UI_CHAT_Handle *chat); + +void +ui_picker_delete(UI_PICKER_Handle *handle); + +#endif /* UI_PICKER_H_ */ diff --git a/submodules/gnome-characters b/submodules/gnome-characters new file mode 160000 index 0000000..f732b51 --- /dev/null +++ b/submodules/gnome-characters @@ -0,0 +1 @@ +Subproject commit f732b513cd5b8882d4176ed6ada1a78aba61a636 -- cgit v1.2.3