diff --git a/abaddon.cpp b/abaddon.cpp index bf82910..1f775b0 100644 --- a/abaddon.cpp +++ b/abaddon.cpp @@ -48,6 +48,23 @@ int Abaddon::StartGTK() { m_main_window->show(); m_main_window->UpdateComponents(); + m_main_window->signal_action_connect().connect(sigc::mem_fun(*this, &Abaddon::ActionConnect)); + m_main_window->signal_action_disconnect().connect(sigc::mem_fun(*this, &Abaddon::ActionDisconnect)); + m_main_window->signal_action_set_token().connect(sigc::mem_fun(*this, &Abaddon::ActionSetToken)); + m_main_window->signal_action_reload_css().connect(sigc::mem_fun(*this, &Abaddon::ActionReloadCSS)); + + m_main_window->GetChannelList()->signal_action_channel_item_select().connect(sigc::mem_fun(*this, &Abaddon::ActionListChannelItemClick)); + m_main_window->GetChannelList()->signal_action_guild_move_up().connect(sigc::mem_fun(*this, &Abaddon::ActionMoveGuildUp)); + m_main_window->GetChannelList()->signal_action_guild_move_down().connect(sigc::mem_fun(*this, &Abaddon::ActionMoveGuildDown)); + m_main_window->GetChannelList()->signal_action_guild_copy_id().connect(sigc::mem_fun(*this, &Abaddon::ActionCopyGuildID)); + + m_main_window->GetChatWindow()->signal_action_message_delete().connect(sigc::mem_fun(*this, &Abaddon::ActionChatDeleteMessage)); + m_main_window->GetChatWindow()->signal_action_message_edit().connect(sigc::mem_fun(*this, &Abaddon::ActionChatEditMessage)); + m_main_window->GetChatWindow()->signal_action_chat_submit().connect(sigc::mem_fun(*this, &Abaddon::ActionChatInputSubmit)); + m_main_window->GetChatWindow()->signal_action_chat_load_history().connect(sigc::mem_fun(*this, &Abaddon::ActionChatLoadHistory)); + + m_main_window->GetMemberList()->signal_action_insert_mention().connect(sigc::mem_fun(*this, &Abaddon::ActionInsertMention)); + ActionReloadCSS(); m_gtk_app->signal_shutdown().connect([&]() { @@ -124,6 +141,10 @@ void Abaddon::ActionConnect() { void Abaddon::ActionDisconnect() { if (m_discord.IsStarted()) StopDiscord(); + m_channels_history_loaded.clear(); + m_channels_history_loading.clear(); + m_channels_requested.clear(); + m_oldest_listed_message.clear(); m_main_window->set_title(APP_TITLE); m_main_window->UpdateComponents(); } diff --git a/components/channels.cpp b/components/channels.cpp index 6a91227..eed0e88 100644 --- a/components/channels.cpp +++ b/components/channels.cpp @@ -41,7 +41,7 @@ void ChannelList::SetListingFromGuilds(const DiscordClient::guilds_type &guilds) m_update_dispatcher.emit(); } -void ChannelList::ClearListing() { +void ChannelList::Clear() { std::scoped_lock guard(m_update_mutex); m_update_queue.push(DiscordClient::guilds_type()); m_update_dispatcher.emit(); @@ -53,7 +53,7 @@ void ChannelList::on_row_activated(Gtk::ListBoxRow *row) { info.IsUserCollapsed = new_collapsed; if (info.Type == ListItemInfo::ListItemType::Channel) { - Abaddon::Get().ActionListChannelItemClick(info.ID); + m_signal_action_channel_item_select.emit(info.ID); } if (info.CatArrow != nullptr) @@ -306,17 +306,17 @@ void ChannelList::SetListingFromGuildsInternal() { void ChannelList::on_menu_move_up() { auto row = m_list->get_selected_row(); - Abaddon::Get().ActionMoveGuildUp(m_infos[row].ID); + m_signal_action_guild_move_up.emit(m_infos[row].ID); } void ChannelList::on_menu_move_down() { auto row = m_list->get_selected_row(); - Abaddon::Get().ActionMoveGuildDown(m_infos[row].ID); + m_signal_action_guild_move_down.emit(m_infos[row].ID); } void ChannelList::on_menu_copyid() { auto row = m_list->get_selected_row(); - Abaddon::Get().ActionCopyGuildID(m_infos[row].ID); + m_signal_action_guild_copy_id.emit(m_infos[row].ID); } void ChannelList::AttachMenuHandler(Gtk::ListBoxRow *row) { @@ -332,3 +332,19 @@ void ChannelList::AttachMenuHandler(Gtk::ListBoxRow *row) { return false; }); } + +ChannelList::type_signal_action_channel_item_select ChannelList::signal_action_channel_item_select() { + return m_signal_action_channel_item_select; +} + +ChannelList::type_signal_action_guild_move_up ChannelList::signal_action_guild_move_up() { + return m_signal_action_guild_move_up; +} + +ChannelList::type_signal_action_guild_move_down ChannelList::signal_action_guild_move_down() { + return m_signal_action_guild_move_down; +} + +ChannelList::type_signal_action_guild_copy_id ChannelList::signal_action_guild_copy_id() { + return m_signal_action_guild_copy_id; +} diff --git a/components/channels.hpp b/components/channels.hpp index ad0879b..53f3789 100644 --- a/components/channels.hpp +++ b/components/channels.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "../discord/discord.hpp" class ChannelList { @@ -11,7 +12,7 @@ public: ChannelList(); Gtk::Widget *GetRoot() const; void SetListingFromGuilds(const DiscordClient::guilds_type &guilds); - void ClearListing(); + void Clear(); protected: Gtk::ListBox *m_list; @@ -51,4 +52,21 @@ protected: void AddPrivateChannels(); // retard moment void SetListingFromGuildsInternal(); void AttachMenuHandler(Gtk::ListBoxRow *row); + +public: + typedef sigc::signal type_signal_action_channel_item_select; + typedef sigc::signal type_signal_action_guild_move_up; + typedef sigc::signal type_signal_action_guild_move_down; + typedef sigc::signal type_signal_action_guild_copy_id; + + type_signal_action_channel_item_select signal_action_channel_item_select(); + type_signal_action_guild_move_up signal_action_guild_move_up(); + type_signal_action_guild_move_down signal_action_guild_move_down(); + type_signal_action_guild_copy_id signal_action_guild_copy_id(); + +protected: + type_signal_action_channel_item_select m_signal_action_channel_item_select; + type_signal_action_guild_move_up m_signal_action_guild_move_up; + type_signal_action_guild_move_down m_signal_action_guild_move_down; + type_signal_action_guild_copy_id m_signal_action_guild_copy_id; }; diff --git a/components/chatmessage.cpp b/components/chatmessage.cpp index 32ce326..f922d5f 100644 --- a/components/chatmessage.cpp +++ b/components/chatmessage.cpp @@ -90,11 +90,19 @@ ChatMessageItem::ChatMessageItem() { } void ChatMessageItem::on_menu_message_delete() { - Abaddon::Get().ActionChatDeleteMessage(ChannelID, ID); + m_signal_action_message_delete.emit(ChannelID, ID); } void ChatMessageItem::on_menu_message_edit() { - Abaddon::Get().ActionChatEditMessage(ChannelID, ID); + m_signal_action_message_edit.emit(ChannelID, ID); +} + +ChatMessageItem::type_signal_action_message_delete ChatMessageItem::signal_action_message_delete() { + return m_signal_action_message_delete; +} + +ChatMessageItem::type_signal_action_message_edit ChatMessageItem::signal_action_message_edit() { + return m_signal_action_message_edit; } void ChatMessageItem::on_menu_copy_id() { diff --git a/components/chatmessage.hpp b/components/chatmessage.hpp index 7bd9efd..5620f60 100644 --- a/components/chatmessage.hpp +++ b/components/chatmessage.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include "../discord/discord.hpp" enum class ChatDisplayType { @@ -9,8 +10,6 @@ enum class ChatDisplayType { Embed, }; -class Abaddon; - // contains the username and timestamp, chat items get stuck into its box class ChatMessageContainer : public Gtk::ListBoxRow { public: @@ -52,6 +51,17 @@ protected: Gtk::MenuItem *m_menu_copy_id; Gtk::MenuItem *m_menu_delete_message; Gtk::MenuItem *m_menu_edit_message; + +public: + typedef sigc::signal type_signal_action_message_delete; + typedef sigc::signal type_signal_action_message_edit; + + type_signal_action_message_delete signal_action_message_delete(); + type_signal_action_message_edit signal_action_message_edit(); + +private: + type_signal_action_message_delete m_signal_action_message_delete; + type_signal_action_message_edit m_signal_action_message_edit; }; class ChatMessageTextItem diff --git a/components/chatwindow.cpp b/components/chatwindow.cpp index 363d6f0..603ebb0 100644 --- a/components/chatwindow.cpp +++ b/components/chatwindow.cpp @@ -88,6 +88,8 @@ ChatDisplayType ChatWindow::GetMessageDisplayType(const MessageData *data) { } void ChatWindow::ProcessMessage(const MessageData *data, bool prepend) { + if (!Abaddon::Get().GetDiscordClient().IsStarted()) return; + ChatMessageContainer *last_row = nullptr; bool should_attach = false; if (m_num_rows > 0) { @@ -117,6 +119,12 @@ void ChatWindow::ProcessMessage(const MessageData *data, bool prepend) { auto *text = Gtk::manage(new ChatMessageTextItem(data)); text->ID = data->ID; text->ChannelID = m_active_channel; + text->signal_action_message_delete().connect([this](Snowflake channel_id, Snowflake id) { + m_signal_action_message_delete.emit(channel_id, id); + }); + text->signal_action_message_edit().connect([this](Snowflake channel_id, Snowflake id) { + m_signal_action_message_edit.emit(channel_id, id); + }); container->AddNewContent(text, prepend); m_id_to_widget[data->ID] = text; } else if (type == ChatDisplayType::Embed) { @@ -148,7 +156,7 @@ bool ChatWindow::on_key_press_event(GdkEventKey *e) { auto text = buffer->get_text(); buffer->set_text(""); - Abaddon::Get().ActionChatInputSubmit(text, m_active_channel); + m_signal_action_chat_submit.emit(text, m_active_channel); return true; } @@ -158,7 +166,7 @@ bool ChatWindow::on_key_press_event(GdkEventKey *e) { void ChatWindow::on_scroll_edge_overshot(Gtk::PositionType pos) { if (pos == Gtk::POS_TOP) - Abaddon::Get().ActionChatLoadHistory(m_active_channel); + m_signal_action_chat_load_history.emit(m_active_channel); } void ChatWindow::SetMessages(std::set msgs) { @@ -191,8 +199,9 @@ void ChatWindow::UpdateMessageContent(Snowflake id) { m_message_edit_dispatch.emit(); } -void ChatWindow::ClearMessages() { +void ChatWindow::Clear() { std::scoped_lock guard(m_update_mutex); + m_active_channel = Snowflake::Invalid; m_message_set_queue.push(std::set()); m_message_set_dispatch.emit(); } @@ -307,3 +316,19 @@ void ChatWindow::SetMessagesInternal() { m_message_set_queue.pop(); } } + +ChatWindow::type_signal_action_message_delete ChatWindow::signal_action_message_delete() { + return m_signal_action_message_delete; +} + +ChatWindow::type_signal_action_message_edit ChatWindow::signal_action_message_edit() { + return m_signal_action_message_edit; +} + +ChatWindow::type_signal_action_chat_submit ChatWindow::signal_action_chat_submit() { + return m_signal_action_chat_submit; +} + +ChatWindow::type_signal_action_chat_load_history ChatWindow::signal_action_chat_load_history() { + return m_signal_action_chat_load_history; +} diff --git a/components/chatwindow.hpp b/components/chatwindow.hpp index 3855603..c16216d 100644 --- a/components/chatwindow.hpp +++ b/components/chatwindow.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "chatmessage.hpp" #include "../discord/discord.hpp" @@ -18,7 +19,7 @@ public: void AddNewHistory(const std::vector &msgs); void DeleteMessage(Snowflake id); void UpdateMessageContent(Snowflake id); - void ClearMessages(); + void Clear(); void InsertChatInput(std::string text); protected: @@ -58,4 +59,21 @@ protected: Gtk::ScrolledWindow *m_scroll; Gtk::ScrolledWindow *m_entry_scroll; Gtk::TextView *m_input; + +public: + typedef sigc::signal type_signal_action_message_delete; + typedef sigc::signal type_signal_action_message_edit; + typedef sigc::signal type_signal_action_chat_submit; + typedef sigc::signal type_signal_action_chat_load_history; + + type_signal_action_message_delete signal_action_message_delete(); + type_signal_action_message_edit signal_action_message_edit(); + type_signal_action_chat_submit signal_action_chat_submit(); + type_signal_action_chat_load_history signal_action_chat_load_history(); + +private: + type_signal_action_message_delete m_signal_action_message_delete; + type_signal_action_message_edit m_signal_action_message_edit; + type_signal_action_chat_submit m_signal_action_chat_submit; + type_signal_action_chat_load_history m_signal_action_chat_load_history; }; diff --git a/components/memberlist.cpp b/components/memberlist.cpp index 61f5791..36bce1f 100644 --- a/components/memberlist.cpp +++ b/components/memberlist.cpp @@ -29,10 +29,19 @@ Gtk::Widget *MemberList::GetRoot() const { return m_main; } +void MemberList::Clear() { + SetActiveChannel(Snowflake::Invalid); + UpdateMemberList(); +} + void MemberList::SetActiveChannel(Snowflake id) { std::scoped_lock guard(m_mutex); m_chan_id = id; - m_guild_id = Abaddon::Get().GetDiscordClient().GetChannel(id)->GuildID; + m_guild_id = Snowflake::Invalid; + if (m_chan_id.IsValid()) { + auto *chan = Abaddon::Get().GetDiscordClient().GetChannel(id); + if (chan != nullptr) m_guild_id = chan->GuildID; + } } void MemberList::UpdateMemberList() { @@ -48,10 +57,12 @@ void MemberList::UpdateMemberListInternal() { it++; } + if (!Abaddon::Get().GetDiscordClient().IsStarted()) return; if (!m_chan_id.IsValid()) return; auto &discord = Abaddon::Get().GetDiscordClient(); auto *chan = discord.GetChannel(m_chan_id); + if (chan == nullptr) return; std::unordered_set ids; if (chan->Type == ChannelType::DM || chan->Type == ChannelType::GROUP_DM) { for (const auto &user : chan->Recipients) @@ -165,7 +176,7 @@ void MemberList::on_copy_id_activate() { void MemberList::on_insert_mention_activate() { auto *row = dynamic_cast(m_row_menu_target); if (row == nullptr) return; - Abaddon::Get().ActionInsertMention(row->ID); + m_signal_action_insert_mention.emit(row->ID); } void MemberList::AttachUserMenuHandler(Gtk::ListBoxRow *row, Snowflake id) { @@ -179,3 +190,7 @@ void MemberList::AttachUserMenuHandler(Gtk::ListBoxRow *row, Snowflake id) { return false; }); } + +MemberList::type_signal_action_insert_mention MemberList::signal_action_insert_mention() { + return m_signal_action_insert_mention; +} diff --git a/components/memberlist.hpp b/components/memberlist.hpp index 3118c1c..ffcc4eb 100644 --- a/components/memberlist.hpp +++ b/components/memberlist.hpp @@ -14,6 +14,7 @@ public: Gtk::Widget *GetRoot() const; void UpdateMemberList(); + void Clear(); void SetActiveChannel(Snowflake id); private: @@ -36,4 +37,12 @@ private: Snowflake m_guild_id; Snowflake m_chan_id; + +public: + typedef sigc::signal type_signal_action_insert_mention; + + type_signal_action_insert_mention signal_action_insert_mention(); + +private: + type_signal_action_insert_mention m_signal_action_insert_mention; }; diff --git a/discord/discord.cpp b/discord/discord.cpp index b9f3bbf..88933b5 100644 --- a/discord/discord.cpp +++ b/discord/discord.cpp @@ -27,6 +27,8 @@ void DiscordClient::Stop() { m_client_connected = false; m_store.ClearAll(); + m_chan_to_message_map.clear(); + m_guild_to_users.clear(); m_websocket.Stop(); } @@ -132,6 +134,8 @@ void DiscordClient::FetchMessagesInChannel(Snowflake id, std::function &)> cb) { std::string path = "/channels/" + std::to_string(channel_id) + "/messages?limit=50&before=" + std::to_string(before_id); m_http.MakeGET(path, [this, channel_id, cb](cpr::Response r) { + if (!CheckCode(r)) return; + std::vector msgs; std::vector ids; @@ -242,7 +246,7 @@ void DiscordClient::UpdateToken(std::string token) { void DiscordClient::HandleGatewayMessageRaw(std::string str) { // handles multiple zlib compressed messages, calling HandleGatewayMessage when a full message is received std::vector buf(str.begin(), str.end()); - int len = buf.size(); + int len = static_cast(buf.size()); bool has_suffix = buf[len - 4] == 0x00 && buf[len - 3] == 0x00 && buf[len - 2] == 0xFF && buf[len - 1] == 0xFF; m_compressed_buf.insert(m_compressed_buf.end(), buf.begin(), buf.end()); @@ -250,13 +254,13 @@ void DiscordClient::HandleGatewayMessageRaw(std::string str) { if (!has_suffix) return; m_zstream.next_in = m_compressed_buf.data(); - m_zstream.avail_in = m_compressed_buf.size(); + m_zstream.avail_in = static_cast(m_compressed_buf.size()); m_zstream.total_in = m_zstream.total_out = 0; // loop in case of really big messages (e.g. READY) while (true) { m_zstream.next_out = m_decompress_buf.data() + m_zstream.total_out; - m_zstream.avail_out = m_decompress_buf.size() - m_zstream.total_out; + m_zstream.avail_out = static_cast(m_decompress_buf.size() - m_zstream.total_out); int err = inflate(&m_zstream, Z_SYNC_FLUSH); if ((err == Z_OK || err == Z_BUF_ERROR) && m_zstream.avail_in > 0) { @@ -335,7 +339,7 @@ void DiscordClient::HandleGatewayReady(const GatewayMessage &msg) { ReadyEventData data = msg.Data; for (auto &g : data.Guilds) { if (g.IsUnavailable) - printf("guild (%lld) unavailable\n", g.ID); + printf("guild (%lld) unavailable\n", (uint64_t)g.ID); else { m_store.SetGuild(g.ID, g); for (auto &c : g.Channels) { diff --git a/windows/mainwindow.cpp b/windows/mainwindow.cpp index a14d3d7..30d52bb 100644 --- a/windows/mainwindow.cpp +++ b/windows/mainwindow.cpp @@ -29,19 +29,19 @@ MainWindow::MainWindow() m_menu_bar.append(m_menu_discord); m_menu_discord_connect.signal_activate().connect([&] { - Abaddon::Get().ActionConnect(); + m_signal_action_connect.emit(); }); m_menu_discord_disconnect.signal_activate().connect([&] { - Abaddon::Get().ActionDisconnect(); + m_signal_action_disconnect.emit(); }); m_menu_discord_set_token.signal_activate().connect([&] { - Abaddon::Get().ActionSetToken(); + m_signal_action_set_token.emit(); }); m_menu_file_reload_css.signal_activate().connect([this] { - Abaddon::Get().ActionReloadCSS(); + m_signal_action_reload_css.emit(); }); m_content_box.set_hexpand(true); @@ -91,8 +91,9 @@ void MainWindow::UpdateComponents() { m_menu_discord_disconnect.set_sensitive(discord_active); if (!discord_active) { - m_channel_list.ClearListing(); - m_chat.ClearMessages(); + m_channel_list.Clear(); + m_chat.Clear(); + m_members.Clear(); } else { UpdateChannelListing(); m_members.UpdateMemberList(); @@ -149,3 +150,31 @@ void MainWindow::UpdateChatPrependHistory(const std::vector &msgs) { void MainWindow::InsertChatInput(std::string text) { m_chat.InsertChatInput(text); } + +ChannelList *MainWindow::GetChannelList() { + return &m_channel_list; +} + +ChatWindow *MainWindow::GetChatWindow() { + return &m_chat; +} + +MemberList *MainWindow::GetMemberList() { + return &m_members; +} + +MainWindow::type_signal_action_connect MainWindow::signal_action_connect() { + return m_signal_action_connect; +} + +MainWindow::type_signal_action_disconnect MainWindow::signal_action_disconnect() { + return m_signal_action_disconnect; +} + +MainWindow::type_signal_action_set_token MainWindow::signal_action_set_token() { + return m_signal_action_set_token; +} + +MainWindow::type_signal_action_reload_css MainWindow::signal_action_reload_css() { + return m_signal_action_reload_css; +} diff --git a/windows/mainwindow.hpp b/windows/mainwindow.hpp index 0cb5084..e850fa2 100644 --- a/windows/mainwindow.hpp +++ b/windows/mainwindow.hpp @@ -20,6 +20,27 @@ public: void UpdateChatPrependHistory(const std::vector &msgs); void InsertChatInput(std::string text); + ChannelList *GetChannelList(); + ChatWindow *GetChatWindow(); + MemberList *GetMemberList(); + +public: + typedef sigc::signal type_signal_action_connect; + typedef sigc::signal type_signal_action_disconnect; + typedef sigc::signal type_signal_action_set_token; + typedef sigc::signal type_signal_action_reload_css; + + type_signal_action_connect signal_action_connect(); + type_signal_action_disconnect signal_action_disconnect(); + type_signal_action_set_token signal_action_set_token(); + type_signal_action_reload_css signal_action_reload_css(); + +protected: + type_signal_action_connect m_signal_action_connect; + type_signal_action_disconnect m_signal_action_disconnect; + type_signal_action_set_token m_signal_action_set_token; + type_signal_action_reload_css m_signal_action_reload_css; + protected: Gtk::Box m_main_box; Gtk::Box m_content_box;