summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorouwou <26526779+ouwou@users.noreply.github.com>2020-08-20 03:19:16 -0400
committerouwou <26526779+ouwou@users.noreply.github.com>2020-08-20 03:19:16 -0400
commita201d5905ad9188e890eeb0cc0aee8d4fb9dcf3c (patch)
treee7b28048f1150c379db1fb27e8efa032aafaf06d
parent4b903bbd3e8436e1d63b8c12e76d8a3c924da5fc (diff)
downloadabaddon-portaudio-a201d5905ad9188e890eeb0cc0aee8d4fb9dcf3c.tar.gz
abaddon-portaudio-a201d5905ad9188e890eeb0cc0aee8d4fb9dcf3c.zip
rudimentary chat
-rw-r--r--Abaddon.vcxproj2
-rw-r--r--Abaddon.vcxproj.filters6
-rw-r--r--abaddon.cpp15
-rw-r--r--abaddon.hpp6
-rw-r--r--components/channels.cpp7
-rw-r--r--components/channels.hpp6
-rw-r--r--components/chatwindow.cpp164
-rw-r--r--components/chatwindow.hpp33
-rw-r--r--discord/discord.cpp57
-rw-r--r--discord/discord.hpp74
-rw-r--r--discord/http.cpp31
-rw-r--r--discord/http.hpp1
-rw-r--r--windows/mainwindow.cpp26
-rw-r--r--windows/mainwindow.hpp5
14 files changed, 426 insertions, 7 deletions
diff --git a/Abaddon.vcxproj b/Abaddon.vcxproj
index 8544549..8e33741 100644
--- a/Abaddon.vcxproj
+++ b/Abaddon.vcxproj
@@ -143,6 +143,7 @@
<ItemGroup>
<ClCompile Include="abaddon.cpp" />
<ClCompile Include="components\channels.cpp" />
+ <ClCompile Include="components\chatwindow.cpp" />
<ClCompile Include="dialogs\token.cpp" />
<ClCompile Include="discord\discord.cpp" />
<ClCompile Include="discord\http.cpp" />
@@ -153,6 +154,7 @@
<ItemGroup>
<ClInclude Include="components\channels.hpp" />
<ClInclude Include="abaddon.hpp" />
+ <ClInclude Include="components\chatwindow.hpp" />
<ClInclude Include="dialogs\token.hpp" />
<ClInclude Include="discord\discord.hpp" />
<ClInclude Include="discord\http.hpp" />
diff --git a/Abaddon.vcxproj.filters b/Abaddon.vcxproj.filters
index e2ae882..10ecb62 100644
--- a/Abaddon.vcxproj.filters
+++ b/Abaddon.vcxproj.filters
@@ -39,6 +39,9 @@
<ClCompile Include="discord\http.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="components\chatwindow.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="windows\mainwindow.hpp">
@@ -65,5 +68,8 @@
<ClInclude Include="discord\http.hpp">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="components\chatwindow.hpp">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/abaddon.cpp b/abaddon.cpp
index f2b973f..48b5b5a 100644
--- a/abaddon.cpp
+++ b/abaddon.cpp
@@ -107,7 +107,7 @@ void Abaddon::ActionMoveGuildUp(Snowflake id) {
std::vector<Snowflake> &pos = d.GuildPositions;
if (pos.size() == 0) {
auto x = m_discord.GetUserSortedGuilds();
- for (const auto& pair : x)
+ for (const auto &pair : x)
pos.push_back(pair.first);
}
@@ -136,7 +136,20 @@ void Abaddon::ActionMoveGuildDown(Snowflake id) {
m_discord.UpdateSettingsGuildPositions(pos);
}
+void Abaddon::ActionListChannelItemClick(Snowflake id) {
+ m_main_window->UpdateChatActiveChannel(id);
+ if (m_channels_requested.find(id) == m_channels_requested.end()) {
+ m_discord.FetchMessagesInChannel(id, [this, id](const std::vector<MessageData> &msgs) {
+ m_channels_requested.insert(id);
+ m_main_window->UpdateChatWindowContents();
+ });
+ } else {
+ m_main_window->UpdateChatWindowContents();
+ }
+}
+
int main(int argc, char **argv) {
+ Gtk::Main::init_gtkmm_internals(); // why???
Abaddon abaddon;
return abaddon.StartGTK();
}
diff --git a/abaddon.hpp b/abaddon.hpp
index 29b7801..17624be 100644
--- a/abaddon.hpp
+++ b/abaddon.hpp
@@ -2,6 +2,7 @@
#include <memory>
#include <mutex>
#include <string>
+#include <unordered_set>
#include "discord/discord.hpp"
#include "windows/mainwindow.hpp"
#include "settings.hpp"
@@ -22,6 +23,7 @@ public:
void ActionSetToken();
void ActionMoveGuildUp(Snowflake id);
void ActionMoveGuildDown(Snowflake id);
+ void ActionListChannelItemClick(Snowflake id);
std::string GetDiscordToken() const;
bool IsDiscordActive() const;
@@ -31,10 +33,12 @@ public:
void DiscordNotifyChannelListFullRefresh();
private:
+ DiscordClient m_discord;
std::string m_discord_token;
+ std::unordered_set<Snowflake> m_channels_requested;
+
mutable std::mutex m_mutex;
Glib::RefPtr<Gtk::Application> m_gtk_app;
- DiscordClient m_discord;
SettingsManager m_settings;
std::unique_ptr<MainWindow> m_main_window; // wah wah cant create a gtkstylecontext fuck you
};
diff --git a/components/channels.cpp b/components/channels.cpp
index 40645ee..d556d40 100644
--- a/components/channels.cpp
+++ b/components/channels.cpp
@@ -52,6 +52,10 @@ void ChannelList::on_row_activated(Gtk::ListBoxRow *row) {
bool new_collapsed = !info.IsUserCollapsed;
info.IsUserCollapsed = new_collapsed;
+ if (info.Type == ListItemInfo::ListItemType::Channel) {
+ m_abaddon->ActionListChannelItemClick(info.ID);
+ }
+
if (info.CatArrow != nullptr)
info.CatArrow->set(new_collapsed ? Gtk::ARROW_RIGHT : Gtk::ARROW_DOWN, Gtk::SHADOW_NONE);
@@ -143,6 +147,7 @@ void ChannelList::SetListingFromGuildsInternal() {
info.ID = id;
info.IsUserCollapsed = false;
info.IsHidden = false;
+ info.Type = ListItemInfo::ListItemType::Channel;
m_infos[channel_row] = std::move(info);
return channel_row;
@@ -168,6 +173,7 @@ void ChannelList::SetListingFromGuildsInternal() {
info.IsUserCollapsed = false;
info.IsHidden = true;
info.CatArrow = category_arrow;
+ info.Type = ListItemInfo::ListItemType::Category;
if (cat_to_channels.find(id) != cat_to_channels.end()) {
std::map<int, const ChannelData *> sorted_channels;
@@ -206,6 +212,7 @@ void ChannelList::SetListingFromGuildsInternal() {
info.IsUserCollapsed = true;
info.IsHidden = false;
info.GuildIndex = m_guild_count++;
+ info.Type = ListItemInfo::ListItemType::Guild;
if (orphan_channels.find(id) != orphan_channels.end()) {
std::map<int, const ChannelData *> sorted_orphans;
diff --git a/components/channels.hpp b/components/channels.hpp
index b98f094..1576783 100644
--- a/components/channels.hpp
+++ b/components/channels.hpp
@@ -21,11 +21,17 @@ protected:
Gtk::ScrolledWindow *m_main;
struct ListItemInfo {
+ enum ListItemType {
+ Guild,
+ Category,
+ Channel,
+ };
int GuildIndex;
Snowflake ID;
std::unordered_set<Gtk::ListBoxRow *> Children;
bool IsUserCollapsed;
bool IsHidden;
+ ListItemType Type;
// for categories
Gtk::Arrow *CatArrow = nullptr;
};
diff --git a/components/chatwindow.cpp b/components/chatwindow.cpp
new file mode 100644
index 0000000..b5fc94d
--- /dev/null
+++ b/components/chatwindow.cpp
@@ -0,0 +1,164 @@
+#include "chatwindow.hpp"
+#include <map>
+
+ChatWindow::ChatWindow() {
+ m_update_dispatcher.connect(sigc::mem_fun(*this, &ChatWindow::SetMessagesInternal));
+
+ m_main = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
+ m_listbox = Gtk::manage(new Gtk::ListBox);
+ m_viewport = Gtk::manage(new Gtk::Viewport(Gtk::Adjustment::create(0, 0, 0, 0, 0, 0), Gtk::Adjustment::create(0, 0, 0, 0, 0, 0)));
+ m_scroll = Gtk::manage(new Gtk::ScrolledWindow);
+ m_input = Gtk::manage(new Gtk::TextView);
+ m_entry_scroll = Gtk::manage(new Gtk::ScrolledWindow);
+
+ m_main->set_hexpand(true);
+ m_main->set_vexpand(true);
+ m_main->show();
+
+ m_scroll->set_can_focus(false);
+ m_scroll->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
+ m_scroll->show();
+
+ m_listbox->signal_size_allocate().connect([this](Gtk::Allocation &) {
+ ScrollToBottom();
+ });
+
+ m_listbox->set_selection_mode(Gtk::SELECTION_NONE);
+ m_listbox->set_hexpand(true);
+ m_listbox->set_vexpand(true);
+ m_listbox->set_focus_hadjustment(m_scroll->get_hadjustment());
+ m_listbox->set_focus_vadjustment(m_scroll->get_vadjustment());
+ m_listbox->show();
+
+ m_viewport->set_can_focus(false);
+ m_viewport->set_valign(Gtk::ALIGN_END);
+ m_viewport->set_vscroll_policy(Gtk::SCROLL_NATURAL);
+ m_viewport->set_shadow_type(Gtk::SHADOW_NONE);
+ m_viewport->show();
+
+ m_input->set_hexpand(true);
+ m_input->set_wrap_mode(Gtk::WRAP_WORD_CHAR);
+ m_input->show();
+
+ m_entry_scroll->set_max_content_height(150);
+ m_entry_scroll->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
+ m_entry_scroll->add(*m_input);
+ m_entry_scroll->show();
+
+ m_viewport->add(*m_listbox);
+ m_scroll->add(*m_viewport);
+ m_main->add(*m_scroll);
+ m_main->add(*m_entry_scroll);
+}
+
+Gtk::Widget *ChatWindow::GetRoot() const {
+ return m_main;
+}
+
+void ChatWindow::SetActiveChannel(Snowflake id) {
+ m_active_channel = id;
+}
+
+Snowflake ChatWindow::GetActiveChannel() const {
+ return m_active_channel;
+}
+
+Gtk::ListBoxRow *ChatWindow::CreateChatEntryComponentText(const MessageData *data) {
+ auto *row = Gtk::manage(new Gtk::ListBoxRow);
+ auto *main_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
+ auto *sub_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
+ auto *meta_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
+ auto *author = Gtk::manage(new Gtk::Label);
+ auto *timestamp = Gtk::manage(new Gtk::Label);
+ auto *text = Gtk::manage(new Gtk::TextView);
+
+ text->set_can_focus(false);
+ text->set_editable(false);
+ text->set_wrap_mode(Gtk::WRAP_WORD_CHAR);
+ text->set_halign(Gtk::ALIGN_FILL);
+ text->set_hexpand(true);
+ text->get_buffer()->set_text(data->Content);
+ text->show();
+
+ author->set_markup("<span weight=\"bold\">" + Glib::Markup::escape_text(data->Author.Username) + "</span>");
+ author->set_single_line_mode(true);
+ author->set_line_wrap(false);
+ author->set_ellipsize(Pango::ELLIPSIZE_END);
+ author->set_xalign(0.f);
+ author->show();
+
+ timestamp->set_text(data->Timestamp);
+ timestamp->set_opacity(0.5);
+ timestamp->set_single_line_mode(true);
+ timestamp->set_margin_start(12);
+ timestamp->show();
+
+ main_box->set_hexpand(true);
+ main_box->set_vexpand(true);
+ main_box->show();
+
+ meta_box->show();
+ sub_box->show();
+
+ meta_box->add(*author);
+ meta_box->add(*timestamp);
+ sub_box->add(*meta_box);
+ sub_box->add(*text);
+ main_box->add(*sub_box);
+ row->add(*main_box);
+ row->set_margin_bottom(8);
+
+ row->show();
+
+ return row;
+}
+
+Gtk::ListBoxRow *ChatWindow::CreateChatEntryComponent(const MessageData *data) {
+ if (data->Type == MessageType::DEFAULT && data->Content.size() > 0)
+ return CreateChatEntryComponentText(data);
+
+ return nullptr;
+}
+
+void ChatWindow::SetMessages(std::unordered_set<const MessageData *> msgs) {
+ std::scoped_lock<std::mutex> guard(m_update_mutex);
+ m_update_queue.push(msgs);
+ m_update_dispatcher.emit();
+}
+
+void ChatWindow::ScrollToBottom() {
+ auto x = m_scroll->get_vadjustment();
+ x->set_value(x->get_upper());
+}
+
+void ChatWindow::SetMessagesInternal() {
+ auto children = m_listbox->get_children();
+ auto it = children.begin();
+
+ while (it != children.end()) {
+ delete *it;
+ it++;
+ }
+
+ std::unordered_set<const MessageData *> *msgs;
+ {
+ std::scoped_lock<std::mutex> guard(m_update_mutex);
+ msgs = &m_update_queue.front();
+ }
+
+ // sort
+ std::map<Snowflake, const MessageData *> sorted_messages;
+ for (const auto msg : *msgs)
+ sorted_messages[msg->ID] = msg;
+
+ for (const auto &[id, msg] : sorted_messages) {
+ auto *row = CreateChatEntryComponent(msg);
+ if (row != nullptr)
+ m_listbox->add(*row);
+ }
+
+ {
+ std::scoped_lock<std::mutex> guard(m_update_mutex);
+ m_update_queue.pop();
+ }
+}
diff --git a/components/chatwindow.hpp b/components/chatwindow.hpp
new file mode 100644
index 0000000..9b4a16d
--- /dev/null
+++ b/components/chatwindow.hpp
@@ -0,0 +1,33 @@
+#pragma once
+#include <gtkmm.h>
+#include <queue>
+#include <mutex>
+#include "../discord/discord.hpp"
+
+class ChatWindow {
+public:
+ ChatWindow();
+ Gtk::Widget *GetRoot() const;
+ void SetActiveChannel(Snowflake id);
+ Snowflake GetActiveChannel() const;
+ void SetMessages(std::unordered_set<const MessageData *> msgs);
+
+protected:
+ void ScrollToBottom();
+ void SetMessagesInternal();
+ Gtk::ListBoxRow *CreateChatEntryComponentText(const MessageData *data);
+ Gtk::ListBoxRow *CreateChatEntryComponent(const MessageData *data);
+
+ Glib::Dispatcher m_update_dispatcher;
+ std::queue<std::unordered_set<const MessageData *>> m_update_queue;
+ std::mutex m_update_mutex;
+
+ Snowflake m_active_channel;
+
+ Gtk::Box *m_main;
+ Gtk::ListBox *m_listbox;
+ Gtk::Viewport *m_viewport;
+ Gtk::ScrolledWindow *m_scroll;
+ Gtk::ScrolledWindow *m_entry_scroll;
+ Gtk::TextView *m_input;
+};
diff --git a/discord/discord.cpp b/discord/discord.cpp
index bb06c52..89c7694 100644
--- a/discord/discord.cpp
+++ b/discord/discord.cpp
@@ -84,6 +84,13 @@ std::vector<std::pair<Snowflake, GuildData>> DiscordClient::GetUserSortedGuilds(
return sorted_guilds;
}
+std::unordered_set<const MessageData *> DiscordClient::GetMessagesForChannel(Snowflake id) const {
+ auto it = m_chan_to_message_map.find(id);
+ if (it == m_chan_to_message_map.end())
+ return std::unordered_set<const MessageData *>();
+ return it->second;
+}
+
void DiscordClient::UpdateSettingsGuildPositions(const std::vector<Snowflake> &pos) {
assert(pos.size() == m_guilds.size());
nlohmann::json body;
@@ -94,6 +101,18 @@ void DiscordClient::UpdateSettingsGuildPositions(const std::vector<Snowflake> &p
});
}
+void DiscordClient::FetchMessagesInChannel(Snowflake id, std::function<void(const std::vector<MessageData> &)> cb) {
+ std::string path = "/channels/" + std::to_string(id) + "/messages?limit=50";
+ m_http.MakeGET(path, [this, id, cb](cpr::Response r) {
+ std::vector<MessageData> msgs;
+ nlohmann::json::parse(r.text).get_to(msgs);
+ for (const auto &msg : msgs)
+ StoreMessage(msg.ID, msg);
+
+ cb(msgs);
+ });
+}
+
void DiscordClient::UpdateToken(std::string token) {
m_token = token;
m_http.SetAuth(token);
@@ -153,6 +172,15 @@ void DiscordClient::StoreGuild(Snowflake id, const GuildData &g) {
m_guilds[id] = g;
}
+void DiscordClient::StoreMessage(Snowflake id, const MessageData &m) {
+ assert(id.IsValid());
+ m_messages[id] = m;
+ auto it = m_chan_to_message_map.find(m.ChannelID);
+ if (it == m_chan_to_message_map.end())
+ m_chan_to_message_map[m.ChannelID] = decltype(m_chan_to_message_map)::mapped_type();
+ m_chan_to_message_map[m.ChannelID].insert(&m_messages[id]);
+}
+
void DiscordClient::HeartbeatThread() {
while (m_client_connected) {
if (!m_heartbeat_acked) {
@@ -308,6 +336,33 @@ void from_json(const nlohmann::json &j, ChannelData &m) {
JS_ON("last_pin_timestamp", m.LastPinTimestamp);
}
+void from_json(const nlohmann::json &j, MessageData &m) {
+ JS_D("id", m.ID);
+ JS_D("channel_id", m.ChannelID);
+ JS_O("guild_id", m.GuildID);
+ JS_D("author", m.Author);
+ // JS_O("member", m.Member);
+ JS_D("content", m.Content);
+ JS_D("timestamp", m.Timestamp);
+ JS_N("edited_timestamp", m.EditedTimestamp);
+ JS_D("tts", m.IsTTS);
+ JS_D("mention_everyone", m.DoesMentionEveryone);
+ JS_D("mentions", m.Mentions);
+ // JS_D("mention_roles", m.MentionRoles);
+ // JS_O("mention_channels", m.MentionChannels);
+ // JS_D("attachments", m.Attachments);
+ // JS_D("embeds", m.Embeds);
+ // JS_O("reactions", m.Reactions);
+ JS_O("nonce", m.Nonce);
+ JS_D("pinned", m.IsPinned);
+ JS_O("webhook_id", m.WebhookID);
+ JS_D("type", m.Type);
+ // JS_O("activity", m.Activity);
+ // JS_O("application", m.Application);
+ // JS_O("message_reference", m.MessageReference);
+ JS_O("flags", m.Flags);
+}
+
void from_json(const nlohmann::json &j, ReadyEventData &m) {
JS_D("v", m.GatewayVersion);
JS_D("user", m.User);
@@ -400,7 +455,7 @@ void from_json(const nlohmann::json &j, Snowflake &s) {
s.m_num = std::stoull(tmp);
}
-void to_json(nlohmann::json& j, const Snowflake& s) {
+void to_json(nlohmann::json &j, const Snowflake &s) {
j = std::to_string(s);
}
diff --git a/discord/discord.hpp b/discord/discord.hpp
index fa09ce2..4ece752 100644
--- a/discord/discord.hpp
+++ b/discord/discord.hpp
@@ -4,6 +4,7 @@
#include <nlohmann/json.hpp>
#include <thread>
#include <unordered_map>
+#include <unordered_set>
#include <mutex>
struct Snowflake {
@@ -33,6 +34,7 @@ struct Snowflake {
private:
friend struct std::hash<Snowflake>;
+ friend struct std::less<Snowflake>;
unsigned long long m_num;
};
@@ -43,6 +45,13 @@ struct hash<Snowflake> {
return k.m_num;
}
};
+
+template<>
+struct less<Snowflake> {
+ bool operator()(const Snowflake &l, const Snowflake &r) const {
+ return l.m_num < r.m_num;
+ }
+};
} // namespace std
enum class GatewayOp : int {
@@ -222,6 +231,62 @@ struct UserSettingsData {
friend void from_json(const nlohmann::json &j, UserSettingsData &m);
};
+enum class MessageType {
+ DEFAULT = 0,
+ RECIPIENT_ADD = 1,
+ RECIPIENT_REMOVE = 2,
+ CALL = 3,
+ CHANNEL_NaME_CHANGE = 4,
+ CHANNEL_ICON_CHANGE = 5,
+ CHANNEL_PINNED_MESSAGE = 6,
+ GUILD_MEMBER_JOIN = 6,
+ USER_PREMIUM_GUILD_SUBSCRIPTION = 7,
+ USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1 = 8,
+ USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2 = 9,
+ USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3 = 10,
+ CHANNEL_FOLLOW_ADD = 12,
+ GUILD_DISCOVERY_DISQUALIFIED = 13,
+ GUILD_DISCOVERY_REQUALIFIED = 14,
+};
+
+enum class MessageFlags {
+ NONE = 0,
+ CROSSPOSTED = 1 << 0,
+ IS_CROSSPOST = 1 << 1,
+ SUPPRESS_EMBEDS = 1 << 2,
+ SOURCE_MESSAGE_DELETE = 1 << 3,
+ URGENT = 1 << 4,
+};
+
+struct MessageData {
+ Snowflake ID; //
+ Snowflake ChannelID; //
+ Snowflake GuildID; // opt
+ UserData Author; //
+ // GuildMemberData Member; // opt
+ std::string Content; //
+ std::string Timestamp; //
+ std::string EditedTimestamp; // null
+ bool IsTTS; //
+ bool DoesMentionEveryone; //
+ std::vector<UserData> Mentions; //
+ // std::vector<RoleData> MentionRoles; //
+ // std::vector<ChannelMentionData> MentionChannels; // opt
+ // std::vector<AttachmentData> Attachments; //
+ // std::vector<EmbedData> Embeds; //
+ // std::vector<ReactionData> Reactions; // opt
+ std::string Nonce; // opt
+ bool IsPinned; //
+ Snowflake WebhookID; // opt
+ MessageType Type; //
+ // MessageActivityData Activity; // opt
+ // MessageApplicationData Application; // opt
+ // MessageReferenceData MessageReference; // opt
+ MessageFlags Flags = MessageFlags::NONE; // opt
+
+ friend void from_json(const nlohmann::json &j, MessageData &m);
+};
+
struct ReadyEventData {
int GatewayVersion; //
UserData User; //
@@ -307,10 +372,15 @@ public:
bool IsStarted() const;
using Guilds_t = std::unordered_map<Snowflake, GuildData>;
+ using Messages_t = std::unordered_map<Snowflake, MessageData>;
+
const Guilds_t &GetGuilds() const;
const UserSettingsData &GetUserSettings() const;
std::vector<std::pair<Snowflake, GuildData>> GetUserSortedGuilds() const;
+ std::unordered_set<const MessageData *> GetMessagesForChannel(Snowflake id) const;
+
void UpdateSettingsGuildPositions(const std::vector<Snowflake> &pos);
+ void FetchMessagesInChannel(Snowflake id, std::function<void(const std::vector<MessageData> &)> cb);
void UpdateToken(std::string token);
@@ -330,6 +400,10 @@ private:
void StoreGuild(Snowflake id, const GuildData &g);
Guilds_t m_guilds;
+ void StoreMessage(Snowflake id, const MessageData &m);
+ Messages_t m_messages;
+ std::unordered_map<Snowflake, std::unordered_set<const MessageData *>> m_chan_to_message_map;
+
UserSettingsData m_user_settings;
Websocket m_websocket;
diff --git a/discord/http.cpp b/discord/http.cpp
index 429a3b2..db41aa4 100644
--- a/discord/http.cpp
+++ b/discord/http.cpp
@@ -36,6 +36,37 @@ void HTTPClient::MakePOST(std::string path, std::string payload, std::function<v
{ "Content-Type", "application/json" },
};
auto body = cpr::Body { payload };
+#ifdef USE_LOCAL_PROXY
+ m_futures.push_back(cpr::GetCallback(
+ std::bind(&HTTPClient::OnResponse, this, std::placeholders::_1, cb),
+ url, headers, body,
+ cpr::Proxies { { "http", "127.0.0.1:8888" }, { "https", "127.0.0.1:8888" } },
+ cpr::VerifySsl { false }));
+#else
+ m_futures.push_back(cpr::PatchCallback(
+ std::bind(&HTTPClient::OnResponse, this, std::placeholders::_1, cb),
+ url, headers, body));
+#endif
+}
+
+void HTTPClient::MakeGET(std::string path, std::function<void(cpr::Response r)> cb) {
+ printf("POST %s\n", path.c_str());
+ auto url = cpr::Url { m_api_base + path };
+ auto headers = cpr::Header {
+ { "Authorization", m_authorization },
+ { "Content-Type", "application/json" },
+ };
+#ifdef USE_LOCAL_PROXY
+ m_futures.push_back(cpr::GetCallback(
+ std::bind(&HTTPClient::OnResponse, this, std::placeholders::_1, cb),
+ url, headers,
+ cpr::Proxies { { "http", "127.0.0.1:8888" }, { "https", "127.0.0.1:8888" } },
+ cpr::VerifySsl { false }));
+#else
+ m_futures.push_back(cpr::GetCallback(
+ std::bind(&HTTPClient::OnResponse, this, std::placeholders::_1, cb),
+ url, headers));
+#endif
}
void HTTPClient::CleanupFutures() {
diff --git a/discord/http.hpp b/discord/http.hpp
index ded2758..7a72589 100644
--- a/discord/http.hpp
+++ b/discord/http.hpp
@@ -19,6 +19,7 @@ public:
HTTPClient(std::string api_base);
void SetAuth(std::string auth);
+ void MakeGET(std::string path, std::function<void(cpr::Response r)> cb);
void MakePATCH(std::string path, std::string payload, std::function<void(cpr::Response r)> cb);
void MakePOST(std::string path, std::string payload, std::function<void(cpr::Response r)> cb);
diff --git a/windows/mainwindow.cpp b/windows/mainwindow.cpp
index cbb6e8a..645b354 100644
--- a/windows/mainwindow.cpp
+++ b/windows/mainwindow.cpp
@@ -3,7 +3,8 @@
MainWindow::MainWindow()
: m_main_box(Gtk::ORIENTATION_VERTICAL)
- , m_content_box(Gtk::ORIENTATION_HORIZONTAL) {
+ , m_content_box(Gtk::ORIENTATION_HORIZONTAL)
+ , m_chan_chat_paned(Gtk::ORIENTATION_HORIZONTAL) {
set_default_size(800, 600);
m_menu_discord.set_label("Discord");
@@ -20,7 +21,7 @@ MainWindow::MainWindow()
m_menu_bar.append(m_menu_discord);
m_menu_discord_connect.signal_activate().connect([&] {
- m_abaddon->ActionConnect(); // this feels maybe not too smart
+ m_abaddon->ActionConnect();
});
m_menu_discord_disconnect.signal_activate().connect([&] {
@@ -38,9 +39,17 @@ MainWindow::MainWindow()
m_main_box.add(m_content_box);
auto *channel_list = m_channel_list.GetRoot();
- channel_list->set_hexpand(true);
channel_list->set_vexpand(true);
- m_content_box.add(*channel_list);
+ channel_list->set_size_request(-1, -1);
+ m_chan_chat_paned.pack1(*channel_list);
+ auto *chat = m_chat.GetRoot();
+ chat->set_vexpand(true);
+ chat->set_hexpand(true);
+ m_chan_chat_paned.pack2(*chat);
+ m_chan_chat_paned.set_position(200);
+ m_chan_chat_paned.child_property_shrink(*channel_list) = true;
+ m_chan_chat_paned.child_property_resize(*channel_list) = true;
+ m_content_box.add(m_chan_chat_paned);
add(m_main_box);
@@ -70,6 +79,15 @@ void MainWindow::UpdateChannelListing() {
m_channel_list.SetListingFromGuilds(discord.GetGuilds());
}
+void MainWindow::UpdateChatWindowContents() {
+ auto &discord = m_abaddon->GetDiscordClient();
+ m_chat.SetMessages(discord.GetMessagesForChannel(m_chat.GetActiveChannel()));
+}
+
+void MainWindow::UpdateChatActiveChannel(Snowflake id) {
+ m_chat.SetActiveChannel(id);
+}
+
void MainWindow::SetAbaddon(Abaddon *ptr) {
m_abaddon = ptr;
m_channel_list.SetAbaddon(ptr);
diff --git a/windows/mainwindow.hpp b/windows/mainwindow.hpp
index c315c32..adf82ef 100644
--- a/windows/mainwindow.hpp
+++ b/windows/mainwindow.hpp
@@ -1,5 +1,6 @@
#pragma once
#include "../components/channels.hpp"
+#include "../components/chatwindow.hpp"
#include <gtkmm.h>
class Abaddon;
@@ -10,12 +11,16 @@ public:
void UpdateComponents();
void UpdateChannelListing();
+ void UpdateChatWindowContents();
+ void UpdateChatActiveChannel(Snowflake id);
protected:
Gtk::Box m_main_box;
Gtk::Box m_content_box;
+ Gtk::Paned m_chan_chat_paned;
ChannelList m_channel_list;
+ ChatWindow m_chat;
Gtk::MenuBar m_menu_bar;
Gtk::MenuItem m_menu_discord;