summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--abaddon.hpp4
-rw-r--r--components/friendslist.cpp173
-rw-r--r--components/friendslist.hpp66
-rw-r--r--discord/activity.hpp14
-rw-r--r--discord/discord.cpp4
-rw-r--r--discord/discord.hpp1
-rw-r--r--windows/mainwindow.cpp14
-rw-r--r--windows/mainwindow.hpp4
8 files changed, 278 insertions, 2 deletions
diff --git a/abaddon.hpp b/abaddon.hpp
index 6bcb385..c8c4351 100644
--- a/abaddon.hpp
+++ b/abaddon.hpp
@@ -84,13 +84,13 @@ public:
void ShowUserMenu(const GdkEvent *event, Snowflake id, Snowflake guild_id);
+ void ManageHeapWindow(Gtk::Window *window);
+
protected:
void ShowGuildVerificationGateDialog(Snowflake guild_id);
void SetupUserMenu();
- void ManageHeapWindow(Gtk::Window *window);
-
Snowflake m_shown_user_menu_id;
Snowflake m_shown_user_menu_guild_id;
diff --git a/components/friendslist.cpp b/components/friendslist.cpp
new file mode 100644
index 0000000..35f2291
--- /dev/null
+++ b/components/friendslist.cpp
@@ -0,0 +1,173 @@
+#include "friendslist.hpp"
+#include "../abaddon.hpp"
+
+FriendsList::FriendsList()
+ : Gtk::Box(Gtk::ORIENTATION_VERTICAL)
+ , m_filter_mode(FILTER_FRIENDS) {
+ for (const auto &[id, type] : Abaddon::Get().GetDiscordClient().GetRelationships()) {
+ const auto user = Abaddon::Get().GetDiscordClient().GetUser(id);
+ if (!user.has_value()) continue;
+ auto *row = Gtk::manage(new FriendsListFriendRow(type, *user));
+ m_list.add(*row);
+ row->show();
+ }
+
+ constexpr static std::array<const char *, 4> strs = {
+ "Friends",
+ "Online",
+ "Pending",
+ "Blocked",
+ };
+ for (const auto &x : strs) {
+ auto *btn = Gtk::manage(new Gtk::RadioButton(m_group, x));
+ m_buttons.add(*btn);
+ btn->show();
+ btn->signal_toggled().connect([this, btn, str = x] {
+ if (!btn->get_active()) return;
+ switch (str[0]) { // hehe
+ case 'F':
+ m_filter_mode = FILTER_FRIENDS;
+ break;
+ case 'O':
+ m_filter_mode = FILTER_ONLINE;
+ break;
+ case 'P':
+ m_filter_mode = FILTER_PENDING;
+ break;
+ case 'B':
+ m_filter_mode = FILTER_BLOCKED;
+ break;
+ }
+ m_list.invalidate_filter();
+ });
+ }
+ m_buttons.set_homogeneous(true);
+ m_buttons.set_halign(Gtk::ALIGN_CENTER);
+
+ m_add.set_halign(Gtk::ALIGN_CENTER);
+ m_add.set_margin_top(5);
+ m_add.set_margin_bottom(5);
+
+ m_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+
+ m_list.set_sort_func(sigc::mem_fun(*this, &FriendsList::ListSortFunc));
+ m_list.set_filter_func(sigc::mem_fun(*this, &FriendsList::ListFilterFunc));
+ m_list.set_selection_mode(Gtk::SELECTION_NONE);
+ m_list.set_hexpand(true);
+ m_list.set_vexpand(true);
+ m_scroll.add(m_list);
+ add(m_add);
+ add(m_buttons);
+ add(m_scroll);
+
+ m_add.show();
+ m_scroll.show();
+ m_buttons.show();
+ m_list.show();
+}
+
+int FriendsList::ListSortFunc(Gtk::ListBoxRow *a_, Gtk::ListBoxRow *b_) {
+ auto *a = dynamic_cast<FriendsListFriendRow *>(a_);
+ auto *b = dynamic_cast<FriendsListFriendRow *>(b_);
+ if (a == nullptr || b == nullptr) return 0;
+ return a->Name.compare(b->Name);
+}
+
+bool FriendsList::ListFilterFunc(Gtk::ListBoxRow *row_) {
+ auto *row = dynamic_cast<FriendsListFriendRow *>(row_);
+ if (row == nullptr) return false;
+ switch (m_filter_mode) {
+ case FILTER_FRIENDS:
+ return row->Type == RelationshipType::Friend;
+ case FILTER_ONLINE:
+ return false; // blah
+ case FILTER_PENDING:
+ return row->Type == RelationshipType::PendingIncoming || row->Type == RelationshipType::PendingOutgoing;
+ case FILTER_BLOCKED:
+ return row->Type == RelationshipType::Blocked;
+ default:
+ return false;
+ }
+}
+
+FriendsListAddComponent::FriendsListAddComponent()
+ : Gtk::Box(Gtk::ORIENTATION_VERTICAL)
+ , m_label("Add a Friend", Gtk::ALIGN_START)
+ , m_box(Gtk::ORIENTATION_HORIZONTAL)
+ , m_add("Add")
+ , m_status("Failed to whatever lol", Gtk::ALIGN_START) {
+ m_box.add(m_entry);
+ m_box.add(m_add);
+ m_box.add(m_status);
+
+ m_label.set_halign(Gtk::ALIGN_CENTER);
+
+ m_entry.set_placeholder_text("Enter a Username#1234");
+
+ add(m_label);
+ add(m_box);
+
+ show_all_children();
+}
+
+FriendsListFriendRow::FriendsListFriendRow(RelationshipType type, const UserData &data)
+ : Name(data.Username + "#" + data.Discriminator)
+ , Type(type)
+ , ID(data.ID) {
+ auto *ev = Gtk::manage(new Gtk::EventBox);
+ auto *box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
+ auto *img = Gtk::manage(new Gtk::Image(Abaddon::Get().GetImageManager().GetPlaceholder(32)));
+ auto *namelbl = Gtk::manage(new Gtk::Label(Name, Gtk::ALIGN_START));
+ const auto status = Abaddon::Get().GetDiscordClient().GetUserStatus(data.ID);
+ auto *statuslbl = Gtk::manage(new Gtk::Label(GetPresenceDisplayString(status), Gtk::ALIGN_START));
+ auto *lblbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
+
+ AddWidgetMenuHandler(ev, m_menu, [this] {
+ switch (Type) {
+ case RelationshipType::Blocked:
+ case RelationshipType::Friend:
+ m_remove.set_label("Remove");
+ break;
+ case RelationshipType::PendingIncoming:
+ m_remove.set_label("Ignore");
+ break;
+ case RelationshipType::PendingOutgoing:
+ m_remove.set_label("Cancel");
+ break;
+ default:
+ break;
+ }
+ });
+
+ m_remove.signal_activate().connect([this] {
+ m_signal_remove.emit();
+ });
+ m_menu.append(m_remove);
+ m_menu.show_all();
+
+ lblbox->set_valign(Gtk::ALIGN_CENTER);
+
+ img->set_margin_end(5);
+
+ lblbox->add(*namelbl);
+ lblbox->add(*statuslbl);
+
+ box->add(*img);
+ box->add(*lblbox);
+
+ ev->add(*box);
+ add(*ev);
+ show_all_children();
+}
+
+FriendsListFriendRow::type_signal_remove FriendsListFriendRow::signal_action_remove() {
+ return m_signal_remove;
+}
+
+FriendsListWindow::FriendsListWindow() {
+ add(m_friends);
+ set_default_size(500, 500);
+ get_style_context()->add_class("app-window");
+ get_style_context()->add_class("app-popup");
+ m_friends.show();
+}
diff --git a/components/friendslist.hpp b/components/friendslist.hpp
new file mode 100644
index 0000000..8d05c1e
--- /dev/null
+++ b/components/friendslist.hpp
@@ -0,0 +1,66 @@
+#pragma once
+#include <gtkmm.h>
+#include "../discord/relationship.hpp"
+
+class FriendsListAddComponent : public Gtk::Box {
+public:
+ FriendsListAddComponent();
+
+private:
+ Gtk::Label m_label;
+ Gtk::Label m_status;
+ Gtk::Entry m_entry;
+ Gtk::Button m_add;
+ Gtk::Box m_box;
+};
+
+class FriendsList : public Gtk::Box {
+public:
+ FriendsList();
+
+private:
+ enum FilterMode {
+ FILTER_FRIENDS,
+ FILTER_ONLINE,
+ FILTER_PENDING,
+ FILTER_BLOCKED,
+ };
+
+ FilterMode m_filter_mode;
+
+ int ListSortFunc(Gtk::ListBoxRow *a, Gtk::ListBoxRow *b);
+ bool ListFilterFunc(Gtk::ListBoxRow *row);
+
+ FriendsListAddComponent m_add;
+ Gtk::RadioButtonGroup m_group;
+ Gtk::ButtonBox m_buttons;
+ Gtk::ScrolledWindow m_scroll;
+ Gtk::ListBox m_list;
+};
+
+class FriendsListFriendRow : public Gtk::ListBoxRow {
+public:
+ FriendsListFriendRow(RelationshipType type, const UserData &str);
+
+ Snowflake ID;
+ RelationshipType Type;
+ Glib::ustring Name;
+
+private:
+ Gtk::Menu m_menu;
+ Gtk::MenuItem m_remove; // or cancel or ignore
+
+ using type_signal_remove = sigc::signal<void>;
+ type_signal_remove m_signal_remove;
+
+public:
+ type_signal_remove signal_action_remove();
+};
+
+class FriendsListWindow : public Gtk::Window {
+public:
+ FriendsListWindow();
+
+private:
+ FriendsList m_friends;
+};
diff --git a/discord/activity.hpp b/discord/activity.hpp
index b50d176..76ba9cd 100644
--- a/discord/activity.hpp
+++ b/discord/activity.hpp
@@ -26,6 +26,20 @@ constexpr inline const char *GetPresenceString(PresenceStatus s) {
return "";
}
+constexpr inline const char* GetPresenceDisplayString(PresenceStatus s) {
+ switch (s) {
+ case PresenceStatus::Online:
+ return "Online";
+ case PresenceStatus::Offline:
+ return "Offline";
+ case PresenceStatus::Idle:
+ return "Away";
+ case PresenceStatus::DND:
+ return "Do Not Disturb";
+ }
+ return "";
+}
+
enum class ActivityType : int {
Game = 0,
Streaming = 1,
diff --git a/discord/discord.cpp b/discord/discord.cpp
index c85ad6e..e25b138 100644
--- a/discord/discord.cpp
+++ b/discord/discord.cpp
@@ -850,6 +850,10 @@ PresenceStatus DiscordClient::GetUserStatus(Snowflake id) const {
return PresenceStatus::Offline;
}
+std::unordered_map<Snowflake, RelationshipType> DiscordClient::GetRelationships() const {
+ return m_user_relationships;
+}
+
std::unordered_set<Snowflake> DiscordClient::GetRelationships(RelationshipType type) const {
std::unordered_set<Snowflake> ret;
for (const auto &[id, rtype] : m_user_relationships)
diff --git a/discord/discord.hpp b/discord/discord.hpp
index 2983ddf..e3e43a1 100644
--- a/discord/discord.hpp
+++ b/discord/discord.hpp
@@ -178,6 +178,7 @@ public:
PresenceStatus GetUserStatus(Snowflake id) const;
+ std::unordered_map<Snowflake, RelationshipType> GetRelationships() const;
std::unordered_set<Snowflake> GetRelationships(RelationshipType type) const;
private:
diff --git a/windows/mainwindow.cpp b/windows/mainwindow.cpp
index b6d3ca5..778e52a 100644
--- a/windows/mainwindow.cpp
+++ b/windows/mainwindow.cpp
@@ -1,5 +1,6 @@
#include "mainwindow.hpp"
#include "../abaddon.hpp"
+#include "../components/friendslist.hpp"
MainWindow::MainWindow()
: m_main_box(Gtk::ORIENTATION_VERTICAL)
@@ -39,8 +40,14 @@ MainWindow::MainWindow()
m_menu_file_sub.append(m_menu_file_reload_css);
m_menu_file_sub.append(m_menu_file_clear_cache);
+ m_menu_view.set_label("View");
+ m_menu_view.set_submenu(m_menu_view_sub);
+ m_menu_view_friends.set_label("Friends");
+ m_menu_view_sub.append(m_menu_view_friends);
+
m_menu_bar.append(m_menu_file);
m_menu_bar.append(m_menu_discord);
+ m_menu_bar.append(m_menu_view);
m_menu_bar.show_all();
m_menu_discord_connect.signal_activate().connect([this] {
@@ -79,6 +86,13 @@ MainWindow::MainWindow()
m_signal_action_add_recipient.emit(GetChatActiveChannel());
});
+ m_menu_view_friends.signal_activate().connect([this] {
+ auto *window = new FriendsListWindow;
+ window->set_position(Gtk::WIN_POS_CENTER);
+ window->show();
+ Abaddon::Get().ManageHeapWindow(window);
+ });
+
m_content_box.set_hexpand(true);
m_content_box.set_vexpand(true);
m_content_box.show();
diff --git a/windows/mainwindow.hpp b/windows/mainwindow.hpp
index 0be4bc0..261d23b 100644
--- a/windows/mainwindow.hpp
+++ b/windows/mainwindow.hpp
@@ -93,4 +93,8 @@ protected:
Gtk::MenuItem m_menu_file_reload_settings;
Gtk::MenuItem m_menu_file_reload_css;
Gtk::MenuItem m_menu_file_clear_cache;
+
+ Gtk::MenuItem m_menu_view;
+ Gtk::Menu m_menu_view_sub;
+ Gtk::MenuItem m_menu_view_friends;
};