diff --git a/Abaddon.vcxproj b/Abaddon.vcxproj index 49dc4b8..7ac7422 100644 --- a/Abaddon.vcxproj +++ b/Abaddon.vcxproj @@ -148,6 +148,7 @@ + @@ -162,6 +163,7 @@ + diff --git a/Abaddon.vcxproj.filters b/Abaddon.vcxproj.filters index 41db77a..27b1d17 100644 --- a/Abaddon.vcxproj.filters +++ b/Abaddon.vcxproj.filters @@ -51,6 +51,9 @@ Source Files + + Source Files + @@ -89,5 +92,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/abaddon.cpp b/abaddon.cpp index 954814a..0f2d0bd 100644 --- a/abaddon.cpp +++ b/abaddon.cpp @@ -4,6 +4,7 @@ #include #include "discord/discord.hpp" #include "dialogs/token.hpp" +#include "dialogs/editmessage.hpp" #include "abaddon.hpp" #ifdef _WIN32 @@ -205,6 +206,15 @@ void Abaddon::ActionChatDeleteMessage(Snowflake channel_id, Snowflake id) { m_discord.DeleteMessage(channel_id, id); } +void Abaddon::ActionChatEditMessage(Snowflake channel_id, Snowflake id) { + EditMessageDialog dlg(*m_main_window); + auto response = dlg.run(); + if (response == Gtk::RESPONSE_OK) { + auto new_content = dlg.GetContent(); + m_discord.EditMessage(channel_id, id, new_content); + } +} + int main(int argc, char **argv) { Gtk::Main::init_gtkmm_internals(); // why??? Abaddon abaddon; diff --git a/abaddon.hpp b/abaddon.hpp index 4f804f0..5a533b3 100644 --- a/abaddon.hpp +++ b/abaddon.hpp @@ -28,6 +28,7 @@ public: void ActionChatInputSubmit(std::string msg, Snowflake channel); void ActionChatLoadHistory(Snowflake id); void ActionChatDeleteMessage(Snowflake channel_id, Snowflake id); + void ActionChatEditMessage(Snowflake channel_id, Snowflake id); std::string GetDiscordToken() const; bool IsDiscordActive() const; diff --git a/components/chatmessage.cpp b/components/chatmessage.cpp index c7cf21b..9074e91 100644 --- a/components/chatmessage.cpp +++ b/components/chatmessage.cpp @@ -62,6 +62,10 @@ ChatMessageItem::ChatMessageItem() { m_menu_delete_message->signal_activate().connect(sigc::mem_fun(*this, &ChatMessageItem::on_menu_message_delete)); m_menu.append(*m_menu_delete_message); + m_menu_edit_message = Gtk::manage(new Gtk::MenuItem("_Edit Message", true)); + m_menu_edit_message->signal_activate().connect(sigc::mem_fun(*this, &ChatMessageItem::on_menu_message_edit)); + m_menu.append(*m_menu_edit_message); + m_menu.show_all(); } @@ -73,6 +77,10 @@ void ChatMessageItem::on_menu_message_delete() { m_abaddon->ActionChatDeleteMessage(ChannelID, ID); } +void ChatMessageItem::on_menu_message_edit() { + m_abaddon->ActionChatEditMessage(ChannelID, ID); +} + void ChatMessageItem::on_menu_copy_id() { Gtk::Clipboard::get()->set_text(std::to_string(ID)); } @@ -94,7 +102,9 @@ void ChatMessageItem::AttachMenuHandler(Gtk::Widget *widget) { void ChatMessageItem::ShowMenu(const GdkEvent *event) { auto &client = m_abaddon->GetDiscordClient(); auto *data = client.GetMessage(ID); - m_menu_delete_message->set_sensitive(client.GetUserData().ID == data->Author.ID); + bool can_manage = client.GetUserData().ID == data->Author.ID; + m_menu_delete_message->set_sensitive(can_manage); + m_menu_edit_message->set_sensitive(can_manage); m_menu.popup_at_pointer(event); } diff --git a/components/chatmessage.hpp b/components/chatmessage.hpp index 82f4504..5796002 100644 --- a/components/chatmessage.hpp +++ b/components/chatmessage.hpp @@ -43,10 +43,12 @@ protected: void AttachMenuHandler(Gtk::Widget *widget); void on_menu_copy_id(); void on_menu_message_delete(); + void on_menu_message_edit(); Gtk::Menu m_menu; Gtk::MenuItem *m_menu_copy_id; Gtk::MenuItem *m_menu_delete_message; + Gtk::MenuItem *m_menu_edit_message; Abaddon *m_abaddon = nullptr; }; diff --git a/dialogs/editmessage.cpp b/dialogs/editmessage.cpp new file mode 100644 index 0000000..e6f226e --- /dev/null +++ b/dialogs/editmessage.cpp @@ -0,0 +1,39 @@ +#include "editmessage.hpp" + +EditMessageDialog::EditMessageDialog(Gtk::Window &parent) + : Gtk::Dialog("Edit Message", parent, true) + , m_layout(Gtk::ORIENTATION_VERTICAL) + , m_bbox(Gtk::ORIENTATION_HORIZONTAL) + , m_ok("OK") + , m_cancel("Cancel") { + set_default_size(300, 50); + + m_ok.signal_clicked().connect([&]() { + m_content = m_text.get_buffer()->get_text(); + response(Gtk::RESPONSE_OK); + }); + + m_cancel.signal_clicked().connect([&]() { + response(Gtk::RESPONSE_CANCEL); + }); + + m_bbox.pack_start(m_ok, Gtk::PACK_SHRINK); + m_bbox.pack_start(m_cancel, Gtk::PACK_SHRINK); + m_bbox.set_layout(Gtk::BUTTONBOX_END); + + m_text.set_hexpand(true); + + m_scroll.set_hexpand(true); + m_scroll.set_vexpand(true); + m_scroll.add(m_text); + + m_layout.add(m_scroll); + m_layout.add(m_bbox); + get_content_area()->add(m_layout); + + show_all_children(); +} + +std::string EditMessageDialog::GetContent() { + return m_content; +} diff --git a/dialogs/editmessage.hpp b/dialogs/editmessage.hpp new file mode 100644 index 0000000..5427897 --- /dev/null +++ b/dialogs/editmessage.hpp @@ -0,0 +1,20 @@ +#pragma once +#include +#include + +class EditMessageDialog : public Gtk::Dialog { +public: + EditMessageDialog(Gtk::Window &parent); + std::string GetContent(); + +protected: + Gtk::Box m_layout; + Gtk::Button m_ok; + Gtk::Button m_cancel; + Gtk::ButtonBox m_bbox; + Gtk::ScrolledWindow m_scroll; + Gtk::TextView m_text; + +private: + std::string m_content; +}; diff --git a/discord/discord.cpp b/discord/discord.cpp index 37ac59f..f04c136 100644 --- a/discord/discord.cpp +++ b/discord/discord.cpp @@ -172,6 +172,14 @@ void DiscordClient::DeleteMessage(Snowflake channel_id, Snowflake id) { m_http.MakeDELETE(path, [](auto) {}); } +void DiscordClient::EditMessage(Snowflake channel_id, Snowflake id, std::string content) { + std::string path = "/channels/" + std::to_string(channel_id) + "/messages/" + std::to_string(id); + MessageEditObject obj; + obj.Content = content; + nlohmann::json j = obj; + m_http.MakePATCH(path, j.dump(), [](auto) {}); +} + void DiscordClient::UpdateToken(std::string token) { m_token = token; m_http.SetAuth(token); diff --git a/discord/discord.hpp b/discord/discord.hpp index 87e09f4..707120e 100644 --- a/discord/discord.hpp +++ b/discord/discord.hpp @@ -70,6 +70,7 @@ public: void SendChatMessage(std::string content, Snowflake channel); void DeleteMessage(Snowflake channel_id, Snowflake id); + void EditMessage(Snowflake channel_id, Snowflake id, std::string content); void UpdateToken(std::string token); diff --git a/discord/objects.cpp b/discord/objects.cpp index ed556f4..1a8355e 100644 --- a/discord/objects.cpp +++ b/discord/objects.cpp @@ -295,6 +295,18 @@ void to_json(nlohmann::json &j, const CreateMessageObject &m) { j["content"] = m.Content; } +void to_json(nlohmann::json &j, const MessageEditObject &m) { + if (m.Content.size() > 0) + j["content"] = m.Content; + + // todo EmbedData to_json + // if (m.Embeds.size() > 0) + // j["embeds"] = m.Embeds; + + if (m.Flags != -1) + j["flags"] = m.Flags; +} + Snowflake::Snowflake() : m_num(Invalid) {} diff --git a/discord/objects.hpp b/discord/objects.hpp index a8bf082..e4b40b4 100644 --- a/discord/objects.hpp +++ b/discord/objects.hpp @@ -424,3 +424,11 @@ struct CreateMessageObject { friend void to_json(nlohmann::json &j, const CreateMessageObject &m); }; + +struct MessageEditObject { + std::string Content; // opt, null + std::vector Embeds; // opt, null + int Flags = -1; // opt, null + + friend void to_json(nlohmann::json &j, const MessageEditObject &m); +};