summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorouwou <26526779+ouwou@users.noreply.github.com>2020-12-15 01:51:49 -0500
committerouwou <26526779+ouwou@users.noreply.github.com>2020-12-15 01:51:49 -0500
commit2667a4b30dd346f70aa8ca1ee7994c559be6d2bb (patch)
tree0ff7113d5c30e465e83a330fc1f19bd803bcc68d /components
parent0c313ce5e8e849bcbaf23fcdf86f31ea38475d0e (diff)
downloadabaddon-portaudio-2667a4b30dd346f70aa8ca1ee7994c559be6d2bb.tar.gz
abaddon-portaudio-2667a4b30dd346f70aa8ca1ee7994c559be6d2bb.zip
display reactions + click to add/remove
Diffstat (limited to 'components')
-rw-r--r--components/chatmessage.cpp108
-rw-r--r--components/chatmessage.hpp10
-rw-r--r--components/chatwindow.cpp22
-rw-r--r--components/chatwindow.hpp7
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 &param) {
+ m_signal_action_reaction_add.emit(id, param);
+ });
+ content->signal_action_reaction_remove().connect([this, id](const Glib::ustring &param) {
+ 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;
};