diff options
author | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-12-15 01:51:49 -0500 |
---|---|---|
committer | ouwou <26526779+ouwou@users.noreply.github.com> | 2020-12-15 01:51:49 -0500 |
commit | 2667a4b30dd346f70aa8ca1ee7994c559be6d2bb (patch) | |
tree | 0ff7113d5c30e465e83a330fc1f19bd803bcc68d /components | |
parent | 0c313ce5e8e849bcbaf23fcdf86f31ea38475d0e (diff) | |
download | abaddon-portaudio-2667a4b30dd346f70aa8ca1ee7994c559be6d2bb.tar.gz abaddon-portaudio-2667a4b30dd346f70aa8ca1ee7994c559be6d2bb.zip |
display reactions + click to add/remove
Diffstat (limited to 'components')
-rw-r--r-- | components/chatmessage.cpp | 108 | ||||
-rw-r--r-- | components/chatmessage.hpp | 10 | ||||
-rw-r--r-- | components/chatwindow.cpp | 22 | ||||
-rw-r--r-- | components/chatwindow.hpp | 7 |
4 files changed, 147 insertions, 0 deletions
diff --git a/components/chatmessage.cpp b/components/chatmessage.cpp index bae26c4..2579482 100644 --- a/components/chatmessage.cpp +++ b/components/chatmessage.cpp @@ -76,6 +76,11 @@ ChatMessageItemContainer *ChatMessageItemContainer::FromMessage(Snowflake id) { } } + if (data->Reactions.has_value() && data->Reactions->size() > 0) { + container->m_reactions_component = container->CreateReactionsComponent(&*data); + container->m_main->add(*container->m_reactions_component); + } + container->UpdateAttributes(); return container; @@ -125,6 +130,18 @@ void ChatMessageItemContainer::UpdateImage(std::string url, Glib::RefPtr<Gdk::Pi } } +void ChatMessageItemContainer::UpdateReactions() { + if (m_reactions_component != nullptr) + delete m_reactions_component; + + const auto data = Abaddon::Get().GetDiscordClient().GetMessage(ID); + if (data->Reactions.has_value() && data->Reactions->size() > 0) { + m_reactions_component = CreateReactionsComponent(&*data); + m_reactions_component->show_all(); + m_main->add(*m_reactions_component); + } +} + void ChatMessageItemContainer::UpdateAttributes() { const auto data = Abaddon::Get().GetDiscordClient().GetMessage(ID); if (!data.has_value()) return; @@ -395,6 +412,89 @@ Gtk::Widget *ChatMessageItemContainer::CreateStickerComponent(const Sticker &dat return box; } +Gtk::Widget *ChatMessageItemContainer::CreateReactionsComponent(const Message *data) { + auto *flow = Gtk::manage(new Gtk::FlowBox); + flow->set_orientation(Gtk::ORIENTATION_HORIZONTAL); + flow->set_min_children_per_line(5); + flow->set_max_children_per_line(20); + flow->set_halign(Gtk::ALIGN_START); + flow->set_hexpand(false); + flow->set_column_spacing(2); + flow->set_selection_mode(Gtk::SELECTION_NONE); + + auto &imgr = Abaddon::Get().GetImageManager(); + auto &emojis = Abaddon::Get().GetEmojis(); + const auto &placeholder = imgr.GetPlaceholder(16); + + for (const auto &reaction : *data->Reactions) { + auto *ev = Gtk::manage(new Gtk::EventBox); + auto *box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL)); + box->get_style_context()->add_class("reaction-box"); + ev->add(*box); + flow->add(*ev); + + bool is_stock = !reaction.Emoji.ID.IsValid(); + + bool has_reacted = reaction.HasReactedWith; + if (has_reacted) + box->get_style_context()->add_class("reacted"); + + ev->signal_button_press_event().connect([this, has_reacted, is_stock, reaction](GdkEventButton *event) -> bool { + if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) { + Glib::ustring param; // escaped in client + if (is_stock) + param = reaction.Emoji.Name; + else + param = std::to_string(reaction.Emoji.ID); + if (has_reacted) + m_signal_action_reaction_remove.emit(param); + else + m_signal_action_reaction_add.emit(param); + return true; + } + return false; + }); + + ev->signal_realize().connect([ev]() { + auto window = ev->get_window(); + auto display = window->get_display(); + auto cursor = Gdk::Cursor::create(display, "pointer"); + window->set_cursor(cursor); + }); + + // image + if (is_stock) { // unicode/stock + const auto &pb = emojis.GetPixBuf(reaction.Emoji.Name); + auto *img = Gtk::manage(new Gtk::Image(pb->scale_simple(16, 16, Gdk::INTERP_BILINEAR))); + img->set_can_focus(false); + box->add(*img); + } else { // custom + const auto &pb = imgr.GetFromURLIfCached(reaction.Emoji.GetURL()); + Gtk::Image *img; + if (pb) { + img = Gtk::manage(new Gtk::Image(pb->scale_simple(16, 16, Gdk::INTERP_BILINEAR))); + } else { + img = Gtk::manage(new Gtk::Image(placeholder)); + // can track_obj PLEASE work ??? + imgr.LoadFromURL(reaction.Emoji.GetURL(), sigc::bind<0>(sigc::mem_fun(*this, &ChatMessageItemContainer::ReactionUpdateImage), img)); + } + img->set_can_focus(false); + box->add(*img); + } + + auto *lbl = Gtk::manage(new Gtk::Label(std::to_string(reaction.Count))); + lbl->set_margin_left(5); + lbl->get_style_context()->add_class("reaction-count"); + box->add(*lbl); + } + + return flow; +} + +void ChatMessageItemContainer::ReactionUpdateImage(Gtk::Image *img, const Glib::RefPtr<Gdk::Pixbuf> &pb) { + img->property_pixbuf() = pb->scale_simple(16, 16, Gdk::INTERP_BILINEAR); +} + void ChatMessageItemContainer::HandleImage(const AttachmentData &data, Gtk::Image *img, std::string url) { m_img_loadmap[url] = std::make_pair(img, data); // ask the chatwindow to call UpdateImage because dealing with lifetimes sucks @@ -715,6 +815,14 @@ ChatMessageItemContainer::type_signal_channel_click ChatMessageItemContainer::si return m_signal_action_channel_click; } +ChatMessageItemContainer::type_signal_action_reaction_add ChatMessageItemContainer::signal_action_reaction_add() { + return m_signal_action_reaction_add; +} + +ChatMessageItemContainer::type_signal_action_reaction_remove ChatMessageItemContainer::signal_action_reaction_remove() { + return m_signal_action_reaction_remove; +} + ChatMessageItemContainer::type_signal_image_load ChatMessageItemContainer::signal_image_load() { return m_signal_image_load; } diff --git a/components/chatmessage.hpp b/components/chatmessage.hpp index 0f76f21..cbc774b 100644 --- a/components/chatmessage.hpp +++ b/components/chatmessage.hpp @@ -14,6 +14,7 @@ public: void UpdateAttributes(); void UpdateContent(); void UpdateImage(std::string url, Glib::RefPtr<Gdk::Pixbuf> buf); + void UpdateReactions(); protected: bool EmitImageLoad(std::string url); @@ -25,6 +26,8 @@ protected: Gtk::Widget *CreateImageComponent(const AttachmentData &data); Gtk::Widget *CreateAttachmentComponent(const AttachmentData &data); // non-image attachments Gtk::Widget *CreateStickerComponent(const Sticker &data); + Gtk::Widget *CreateReactionsComponent(const Message *data); + void ReactionUpdateImage(Gtk::Image *img, const Glib::RefPtr<Gdk::Pixbuf> &pb); void HandleImage(const AttachmentData &data, Gtk::Image *img, std::string url); void OnEmbedImageLoad(const Glib::RefPtr<Gdk::Pixbuf> &pixbuf); @@ -75,6 +78,7 @@ protected: Gtk::TextView *m_text_component = nullptr; Gtk::Widget *m_embed_component = nullptr; + Gtk::Widget *m_reactions_component = nullptr; public: typedef sigc::signal<void, std::string> type_signal_image_load; @@ -82,10 +86,14 @@ public: typedef sigc::signal<void> type_signal_action_delete; typedef sigc::signal<void> type_signal_action_edit; typedef sigc::signal<void, Snowflake> type_signal_channel_click; + typedef sigc::signal<void, Glib::ustring> type_signal_action_reaction_add; + typedef sigc::signal<void, Glib::ustring> type_signal_action_reaction_remove; type_signal_action_delete signal_action_delete(); type_signal_action_edit signal_action_edit(); type_signal_channel_click signal_action_channel_click(); + type_signal_action_reaction_add signal_action_reaction_add(); + type_signal_action_reaction_remove signal_action_reaction_remove(); type_signal_image_load signal_image_load(); @@ -93,6 +101,8 @@ private: type_signal_action_delete m_signal_action_delete; type_signal_action_edit m_signal_action_edit; type_signal_channel_click m_signal_action_channel_click; + type_signal_action_reaction_add m_signal_action_reaction_add; + type_signal_action_reaction_remove m_signal_action_reaction_remove; type_signal_image_load m_signal_image_load; }; diff --git a/components/chatwindow.cpp b/components/chatwindow.cpp index ea8da69..25492f8 100644 --- a/components/chatwindow.cpp +++ b/components/chatwindow.cpp @@ -128,6 +128,14 @@ Snowflake ChatWindow::GetOldestListedMessage() { return m; } +void ChatWindow::UpdateReactions(Snowflake id) { + auto it = m_id_to_widget.find(id); + if (it == m_id_to_widget.end()) return; + auto *widget = dynamic_cast<ChatMessageItemContainer *>(it->second); + if (widget == nullptr) return; + widget->UpdateReactions(); +} + Snowflake ChatWindow::GetActiveChannel() const { return m_active_channel; } @@ -206,6 +214,12 @@ void ChatWindow::ProcessNewMessage(Snowflake id, bool prepend) { content->signal_action_edit().connect([this, id] { m_signal_action_message_edit.emit(m_active_channel, id); }); + content->signal_action_reaction_add().connect([this, id](const Glib::ustring ¶m) { + m_signal_action_reaction_add.emit(id, param); + }); + content->signal_action_reaction_remove().connect([this, id](const Glib::ustring ¶m) { + m_signal_action_reaction_remove.emit(id, param); + }); content->signal_image_load().connect([this, id](std::string url) { auto &mgr = Abaddon::Get().GetImageManager(); mgr.LoadFromURL(url, [this, id, url](Glib::RefPtr<Gdk::Pixbuf> buf) { @@ -339,3 +353,11 @@ ChatWindow::type_signal_action_insert_mention ChatWindow::signal_action_insert_m ChatWindow::type_signal_action_open_user_menu ChatWindow::signal_action_open_user_menu() { return m_signal_action_open_user_menu; } + +ChatWindow::type_signal_action_reaction_add ChatWindow::signal_action_reaction_add() { + return m_signal_action_reaction_add; +} + +ChatWindow::type_signal_action_reaction_remove ChatWindow::signal_action_reaction_remove() { + return m_signal_action_reaction_remove; +} diff --git a/components/chatwindow.hpp b/components/chatwindow.hpp index 4b1a251..823e988 100644 --- a/components/chatwindow.hpp +++ b/components/chatwindow.hpp @@ -23,6 +23,7 @@ public: void AddNewHistory(const std::vector<Snowflake> &id); // prepend messages void InsertChatInput(std::string text); Snowflake GetOldestListedMessage(); // oldest message that is currently in the ListBox + void UpdateReactions(Snowflake id); protected: ChatMessageItemContainer *CreateMessageComponent(Snowflake id); // to be inserted into header's content box @@ -72,6 +73,8 @@ public: typedef sigc::signal<void, Snowflake> type_signal_action_channel_click; typedef sigc::signal<void, Snowflake> type_signal_action_insert_mention; typedef sigc::signal<void, const GdkEvent *, Snowflake, Snowflake> type_signal_action_open_user_menu; + typedef sigc::signal<void, Snowflake, Glib::ustring> type_signal_action_reaction_add; + typedef sigc::signal<void, Snowflake, Glib::ustring> type_signal_action_reaction_remove; type_signal_action_message_delete signal_action_message_delete(); type_signal_action_message_edit signal_action_message_edit(); @@ -80,6 +83,8 @@ public: type_signal_action_channel_click signal_action_channel_click(); type_signal_action_insert_mention signal_action_insert_mention(); type_signal_action_open_user_menu signal_action_open_user_menu(); + type_signal_action_reaction_add signal_action_reaction_add(); + type_signal_action_reaction_remove signal_action_reaction_remove(); private: type_signal_action_message_delete m_signal_action_message_delete; @@ -89,4 +94,6 @@ private: type_signal_action_channel_click m_signal_action_channel_click; type_signal_action_insert_mention m_signal_action_insert_mention; type_signal_action_open_user_menu m_signal_action_open_user_menu; + type_signal_action_reaction_add m_signal_action_reaction_add; + type_signal_action_reaction_remove m_signal_action_reaction_remove; }; |