more signal usage and some other fixes

This commit is contained in:
ouwou 2020-09-07 02:45:46 -04:00
parent 902c96ee53
commit da2182a5e7
12 changed files with 220 additions and 26 deletions

View File

@ -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();
}

View File

@ -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<std::mutex> 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;
}

View File

@ -4,6 +4,7 @@
#include <queue>
#include <mutex>
#include <unordered_set>
#include <sigc++/sigc++.h>
#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<void, Snowflake> type_signal_action_channel_item_select;
typedef sigc::signal<void, Snowflake> type_signal_action_guild_move_up;
typedef sigc::signal<void, Snowflake> type_signal_action_guild_move_down;
typedef sigc::signal<void, Snowflake> 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;
};

View File

@ -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() {

View File

@ -1,6 +1,7 @@
#pragma once
#include <gtkmm.h>
#include <string>
#include <sigc++/sigc++.h>
#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<void, Snowflake, Snowflake> type_signal_action_message_delete;
typedef sigc::signal<void, Snowflake, Snowflake> 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

View File

@ -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<Snowflake> msgs) {
@ -191,8 +199,9 @@ void ChatWindow::UpdateMessageContent(Snowflake id) {
m_message_edit_dispatch.emit();
}
void ChatWindow::ClearMessages() {
void ChatWindow::Clear() {
std::scoped_lock<std::mutex> guard(m_update_mutex);
m_active_channel = Snowflake::Invalid;
m_message_set_queue.push(std::set<Snowflake>());
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;
}

View File

@ -3,6 +3,7 @@
#include <queue>
#include <mutex>
#include <unordered_map>
#include <sigc++/sigc++.h>
#include "chatmessage.hpp"
#include "../discord/discord.hpp"
@ -18,7 +19,7 @@ public:
void AddNewHistory(const std::vector<Snowflake> &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<void, Snowflake, Snowflake> type_signal_action_message_delete;
typedef sigc::signal<void, Snowflake, Snowflake> type_signal_action_message_edit;
typedef sigc::signal<void, std::string, Snowflake> type_signal_action_chat_submit;
typedef sigc::signal<void, Snowflake> 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;
};

View File

@ -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<std::mutex> 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<Snowflake> 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<MemberListUserRow *>(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;
}

View File

@ -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<void, Snowflake> 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;
};

View File

@ -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<void(cons
void DiscordClient::FetchMessagesInChannelBefore(Snowflake channel_id, Snowflake before_id, std::function<void(const std::vector<Snowflake> &)> 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<MessageData> msgs;
std::vector<Snowflake> 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<uint8_t> buf(str.begin(), str.end());
int len = buf.size();
int len = static_cast<int>(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<uInt>(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<uInt>(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) {

View File

@ -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<Snowflake> &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;
}

View File

@ -20,6 +20,27 @@ public:
void UpdateChatPrependHistory(const std::vector<Snowflake> &msgs);
void InsertChatInput(std::string text);
ChannelList *GetChannelList();
ChatWindow *GetChatWindow();
MemberList *GetMemberList();
public:
typedef sigc::signal<void> type_signal_action_connect;
typedef sigc::signal<void> type_signal_action_disconnect;
typedef sigc::signal<void> type_signal_action_set_token;
typedef sigc::signal<void> 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;