summaryrefslogtreecommitdiff
path: root/src/dialogs
diff options
context:
space:
mode:
authorDylam De La Torre <DyXel04@gmail.com>2021-11-23 05:21:56 +0100
committerGitHub <noreply@github.com>2021-11-23 04:21:56 +0000
commita51a54bc5979a2491f152abc47ad54e6b63f27c8 (patch)
treece67092b2f6df366033a65a6111e4650866766b2 /src/dialogs
parentd88079000a79e6bcbe51c5a2868d57b303b5fcb6 (diff)
downloadabaddon-portaudio-a51a54bc5979a2491f152abc47ad54e6b63f27c8.tar.gz
abaddon-portaudio-a51a54bc5979a2491f152abc47ad54e6b63f27c8.zip
Restructure source and resource files (#46)
importantly, res is now res/res and css is now res/css
Diffstat (limited to 'src/dialogs')
-rw-r--r--src/dialogs/confirm.cpp36
-rw-r--r--src/dialogs/confirm.hpp15
-rw-r--r--src/dialogs/editmessage.cpp45
-rw-r--r--src/dialogs/editmessage.hpp21
-rw-r--r--src/dialogs/friendpicker.cpp93
-rw-r--r--src/dialogs/friendpicker.hpp35
-rw-r--r--src/dialogs/joinguild.cpp97
-rw-r--r--src/dialogs/joinguild.hpp31
-rw-r--r--src/dialogs/setstatus.cpp72
-rw-r--r--src/dialogs/setstatus.hpp22
-rw-r--r--src/dialogs/token.cpp43
-rw-r--r--src/dialogs/token.hpp19
-rw-r--r--src/dialogs/verificationgate.cpp51
-rw-r--r--src/dialogs/verificationgate.hpp22
14 files changed, 602 insertions, 0 deletions
diff --git a/src/dialogs/confirm.cpp b/src/dialogs/confirm.cpp
new file mode 100644
index 0000000..39d8971
--- /dev/null
+++ b/src/dialogs/confirm.cpp
@@ -0,0 +1,36 @@
+#include "confirm.hpp"
+
+ConfirmDialog::ConfirmDialog(Gtk::Window &parent)
+ : Gtk::Dialog("Confirm", parent, true)
+ , m_layout(Gtk::ORIENTATION_VERTICAL)
+ , m_ok("OK")
+ , m_cancel("Cancel")
+ , m_bbox(Gtk::ORIENTATION_HORIZONTAL) {
+ set_default_size(300, 50);
+ get_style_context()->add_class("app-window");
+ get_style_context()->add_class("app-popup");
+
+ m_label.set_text("Are you sure?");
+
+ m_ok.signal_clicked().connect([&]() {
+ 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_layout.add(m_label);
+ m_layout.add(m_bbox);
+ get_content_area()->add(m_layout);
+
+ show_all_children();
+}
+
+void ConfirmDialog::SetConfirmText(const Glib::ustring &text) {
+ m_label.set_text(text);
+}
diff --git a/src/dialogs/confirm.hpp b/src/dialogs/confirm.hpp
new file mode 100644
index 0000000..df1e185
--- /dev/null
+++ b/src/dialogs/confirm.hpp
@@ -0,0 +1,15 @@
+#pragma once
+#include <gtkmm.h>
+
+class ConfirmDialog : public Gtk::Dialog {
+public:
+ ConfirmDialog(Gtk::Window &parent);
+ void SetConfirmText(const Glib::ustring &text);
+
+protected:
+ Gtk::Label m_label;
+ Gtk::Box m_layout;
+ Gtk::Button m_ok;
+ Gtk::Button m_cancel;
+ Gtk::ButtonBox m_bbox;
+};
diff --git a/src/dialogs/editmessage.cpp b/src/dialogs/editmessage.cpp
new file mode 100644
index 0000000..b4308a0
--- /dev/null
+++ b/src/dialogs/editmessage.cpp
@@ -0,0 +1,45 @@
+#include "editmessage.hpp"
+
+EditMessageDialog::EditMessageDialog(Gtk::Window &parent)
+ : Gtk::Dialog("Edit Message", parent, true)
+ , m_layout(Gtk::ORIENTATION_VERTICAL)
+ , m_ok("OK")
+ , m_cancel("Cancel")
+ , m_bbox(Gtk::ORIENTATION_HORIZONTAL) {
+ set_default_size(300, 50);
+ get_style_context()->add_class("app-window");
+ get_style_context()->add_class("app-popup");
+
+ 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();
+}
+
+Glib::ustring EditMessageDialog::GetContent() {
+ return m_content;
+}
+
+void EditMessageDialog::SetContent(const Glib::ustring &str) {
+ m_text.get_buffer()->set_text(str);
+}
diff --git a/src/dialogs/editmessage.hpp b/src/dialogs/editmessage.hpp
new file mode 100644
index 0000000..bf6307d
--- /dev/null
+++ b/src/dialogs/editmessage.hpp
@@ -0,0 +1,21 @@
+#pragma once
+#include <gtkmm.h>
+#include <string>
+
+class EditMessageDialog : public Gtk::Dialog {
+public:
+ EditMessageDialog(Gtk::Window &parent);
+ Glib::ustring GetContent();
+ void SetContent(const Glib::ustring &str);
+
+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:
+ Glib::ustring m_content;
+};
diff --git a/src/dialogs/friendpicker.cpp b/src/dialogs/friendpicker.cpp
new file mode 100644
index 0000000..fc099aa
--- /dev/null
+++ b/src/dialogs/friendpicker.cpp
@@ -0,0 +1,93 @@
+#include "friendpicker.hpp"
+#include "abaddon.hpp"
+
+FriendPickerDialog::FriendPickerDialog(Gtk::Window &parent)
+ : Gtk::Dialog("Pick a friend", parent, true)
+ , m_bbox(Gtk::ORIENTATION_HORIZONTAL) {
+ set_default_size(300, 300);
+ get_style_context()->add_class("app-window");
+ get_style_context()->add_class("app-popup");
+
+ m_ok_button = add_button("OK", Gtk::RESPONSE_OK);
+ m_cancel_button = add_button("Cancel", Gtk::RESPONSE_CANCEL);
+
+ m_ok_button->set_sensitive(false);
+
+ auto &discord = Abaddon::Get().GetDiscordClient();
+ auto relationships = discord.GetRelationships(RelationshipType::Friend);
+ for (auto id : relationships) {
+ auto *item = Gtk::manage(new FriendPickerDialogItem(id));
+ item->show();
+ m_list.add(*item);
+ }
+
+ m_list.signal_row_activated().connect(sigc::mem_fun(*this, &FriendPickerDialog::OnRowActivated));
+ m_list.signal_selected_rows_changed().connect(sigc::mem_fun(*this, &FriendPickerDialog::OnSelectionChange));
+ m_list.set_activate_on_single_click(false);
+ m_list.set_selection_mode(Gtk::SELECTION_SINGLE);
+
+ m_main.set_propagate_natural_height(true);
+
+ m_main.add(m_list);
+
+ get_content_area()->add(m_main);
+
+ show_all_children();
+}
+
+Snowflake FriendPickerDialog::GetUserID() const {
+ return m_chosen_id;
+}
+
+void FriendPickerDialog::OnRowActivated(Gtk::ListBoxRow *row) {
+ auto *x = dynamic_cast<FriendPickerDialogItem *>(row);
+ if (x != nullptr) {
+ m_chosen_id = x->ID;
+ response(Gtk::RESPONSE_OK);
+ }
+}
+
+void FriendPickerDialog::OnSelectionChange() {
+ auto selection = m_list.get_selected_row();
+ m_ok_button->set_sensitive(false);
+ if (selection != nullptr) {
+ auto *row = dynamic_cast<FriendPickerDialogItem *>(selection);
+ if (!row) return;
+ m_chosen_id = row->ID;
+ m_ok_button->set_sensitive(true);
+ }
+}
+
+FriendPickerDialogItem::FriendPickerDialogItem(Snowflake user_id)
+ : ID(user_id)
+ , m_layout(Gtk::ORIENTATION_HORIZONTAL) {
+ auto user = *Abaddon::Get().GetDiscordClient().GetUser(user_id);
+
+ m_name.set_markup(user.GetEscapedBoldString<false>());
+ m_name.set_single_line_mode(true);
+
+ m_avatar.property_pixbuf() = Abaddon::Get().GetImageManager().GetPlaceholder(32);
+ if (user.HasAnimatedAvatar() && Abaddon::Get().GetSettings().GetShowAnimations()) {
+ auto cb = [this](const Glib::RefPtr<Gdk::PixbufAnimation> &pb) {
+ m_avatar.property_pixbuf_animation() = pb;
+ };
+ Abaddon::Get().GetImageManager().LoadAnimationFromURL(user.GetAvatarURL("gif", "32"), 32, 32, sigc::track_obj(cb, *this));
+ } else {
+ auto cb = [this](const Glib::RefPtr<Gdk::Pixbuf> &pb) {
+ m_avatar.property_pixbuf() = pb->scale_simple(32, 32, Gdk::INTERP_BILINEAR);
+ };
+ Abaddon::Get().GetImageManager().LoadFromURL(user.GetAvatarURL("png", "32"), sigc::track_obj(cb, *this));
+ }
+
+ m_avatar.set_margin_end(5);
+ m_avatar.set_halign(Gtk::ALIGN_START);
+ m_avatar.set_valign(Gtk::ALIGN_CENTER);
+ m_name.set_halign(Gtk::ALIGN_START);
+ m_name.set_valign(Gtk::ALIGN_CENTER);
+
+ m_layout.add(m_avatar);
+ m_layout.add(m_name);
+ add(m_layout);
+
+ show_all_children();
+}
diff --git a/src/dialogs/friendpicker.hpp b/src/dialogs/friendpicker.hpp
new file mode 100644
index 0000000..81d02a3
--- /dev/null
+++ b/src/dialogs/friendpicker.hpp
@@ -0,0 +1,35 @@
+#pragma once
+#include <gtkmm.h>
+#include "discord/snowflake.hpp"
+
+class FriendPickerDialog : public Gtk::Dialog {
+public:
+ FriendPickerDialog(Gtk::Window &parent);
+
+ Snowflake GetUserID() const;
+
+protected:
+ void OnRowActivated(Gtk::ListBoxRow *row);
+ void OnSelectionChange();
+
+ Snowflake m_chosen_id;
+
+ Gtk::ScrolledWindow m_main;
+ Gtk::ListBox m_list;
+ Gtk::ButtonBox m_bbox;
+
+ Gtk::Button *m_ok_button;
+ Gtk::Button *m_cancel_button;
+};
+
+class FriendPickerDialogItem : public Gtk::ListBoxRow {
+public:
+ FriendPickerDialogItem(Snowflake user_id);
+
+ Snowflake ID;
+
+private:
+ Gtk::Box m_layout;
+ Gtk::Image m_avatar;
+ Gtk::Label m_name;
+};
diff --git a/src/dialogs/joinguild.cpp b/src/dialogs/joinguild.cpp
new file mode 100644
index 0000000..14fab53
--- /dev/null
+++ b/src/dialogs/joinguild.cpp
@@ -0,0 +1,97 @@
+#include "joinguild.hpp"
+#include "abaddon.hpp"
+#include <nlohmann/json.hpp>
+#include <regex>
+
+JoinGuildDialog::JoinGuildDialog(Gtk::Window &parent)
+ : Gtk::Dialog("Join Server", parent, true)
+ , m_layout(Gtk::ORIENTATION_VERTICAL)
+ , m_ok("OK")
+ , m_cancel("Cancel")
+ , m_info("Enter code") {
+ set_default_size(300, 50);
+ get_style_context()->add_class("app-window");
+ get_style_context()->add_class("app-popup");
+
+ Glib::signal_idle().connect(sigc::mem_fun(*this, &JoinGuildDialog::on_idle_slot));
+
+ m_entry.signal_changed().connect(sigc::mem_fun(*this, &JoinGuildDialog::on_entry_changed));
+
+ m_ok.set_sensitive(false);
+
+ m_ok.signal_clicked().connect([&]() {
+ response(Gtk::RESPONSE_OK);
+ });
+
+ m_cancel.signal_clicked().connect([&]() {
+ response(Gtk::RESPONSE_CANCEL);
+ });
+
+ m_entry.set_hexpand(true);
+ m_layout.add(m_entry);
+ m_lower.set_hexpand(true);
+ m_lower.pack_start(m_info);
+ m_info.set_halign(Gtk::ALIGN_START);
+ m_lower.pack_start(m_ok, Gtk::PACK_SHRINK);
+ m_lower.pack_start(m_cancel, Gtk::PACK_SHRINK);
+ m_ok.set_halign(Gtk::ALIGN_END);
+ m_cancel.set_halign(Gtk::ALIGN_END);
+ m_layout.add(m_lower);
+ get_content_area()->add(m_layout);
+
+ show_all_children();
+}
+
+void JoinGuildDialog::on_entry_changed() {
+ std::string s = m_entry.get_text();
+ std::regex invite_regex(R"((https?:\/\/)?discord\.(gg(\/invite)?\/|com\/invite\/)([A-Za-z0-9\-]+))", std::regex_constants::ECMAScript);
+ std::smatch match;
+ bool full_url = std::regex_search(s, match, invite_regex);
+ if (full_url || IsCode(s)) {
+ m_code = full_url ? match[4].str() : s;
+ m_needs_request = true;
+ m_ok.set_sensitive(false);
+ } else {
+ m_ok.set_sensitive(false);
+ }
+}
+
+void JoinGuildDialog::CheckCode() {
+ auto cb = [this](const std::optional<InviteData> &invite) {
+ if (invite.has_value()) {
+ m_ok.set_sensitive(true);
+ if (invite->Guild.has_value()) {
+ if (invite->MemberCount.has_value())
+ m_info.set_text(invite->Guild->Name + " (" + std::to_string(*invite->MemberCount) + " members)");
+ else
+ m_info.set_text(invite->Guild->Name);
+ } else {
+ m_info.set_text("Group DM (" + std::to_string(*invite->MemberCount) + " members)");
+ }
+ } else {
+ m_ok.set_sensitive(false);
+ m_info.set_text("Invalid invite");
+ }
+ };
+ Abaddon::Get().GetDiscordClient().FetchInvite(m_code, sigc::track_obj(cb, *this));
+}
+
+bool JoinGuildDialog::IsCode(std::string str) {
+ return str.length() >= 2 && std::all_of(str.begin(), str.end(), [](char c) -> bool { return std::isalnum(c) || c == '-'; });
+}
+
+std::string JoinGuildDialog::GetCode() {
+ return m_code;
+}
+
+static const constexpr int RateLimitMS = 1500;
+bool JoinGuildDialog::on_idle_slot() {
+ const auto now = std::chrono::steady_clock::now();
+ if (m_needs_request && ((now - m_last_req_time) > std::chrono::milliseconds(RateLimitMS))) {
+ m_needs_request = false;
+ m_last_req_time = now;
+ CheckCode();
+ }
+
+ return true;
+}
diff --git a/src/dialogs/joinguild.hpp b/src/dialogs/joinguild.hpp
new file mode 100644
index 0000000..109d010
--- /dev/null
+++ b/src/dialogs/joinguild.hpp
@@ -0,0 +1,31 @@
+#pragma once
+#include <gtkmm.h>
+#include <string>
+#include <chrono>
+
+class JoinGuildDialog : public Gtk::Dialog {
+public:
+ JoinGuildDialog(Gtk::Window &parent);
+ std::string GetCode();
+
+protected:
+ void on_entry_changed();
+ bool IsCode(std::string str);
+
+ Gtk::Box m_layout;
+ Gtk::Button m_ok;
+ Gtk::Button m_cancel;
+ Gtk::Box m_lower;
+ Gtk::Label m_info;
+ Gtk::Entry m_entry;
+
+ void CheckCode();
+
+ // needs a rate limit cuz if u hit it u get ip banned from /invites for a long time :(
+ bool m_needs_request = false;
+ std::chrono::time_point<std::chrono::steady_clock> m_last_req_time;
+ bool on_idle_slot();
+
+private:
+ std::string m_code;
+};
diff --git a/src/dialogs/setstatus.cpp b/src/dialogs/setstatus.cpp
new file mode 100644
index 0000000..7a3a038
--- /dev/null
+++ b/src/dialogs/setstatus.cpp
@@ -0,0 +1,72 @@
+#include "setstatus.hpp"
+
+SetStatusDialog::SetStatusDialog(Gtk::Window &parent)
+ : Gtk::Dialog("Set Status", parent, true)
+ , m_layout(Gtk::ORIENTATION_VERTICAL)
+ , m_bottom(Gtk::ORIENTATION_HORIZONTAL)
+ , m_ok("OK")
+ , m_cancel("Cancel")
+ , m_bbox(Gtk::ORIENTATION_HORIZONTAL) {
+ set_default_size(300, 50);
+ get_style_context()->add_class("app-window");
+ get_style_context()->add_class("app-popup");
+
+ m_text.set_placeholder_text("Status text");
+
+ m_status_combo.append("online", "Online");
+ m_status_combo.append("dnd", "Do Not Disturb");
+ m_status_combo.append("idle", "Away");
+ m_status_combo.append("invisible", "Invisible");
+ m_status_combo.set_active_text("Online");
+
+ m_type_combo.append("0", "Playing");
+ m_type_combo.append("1", "Streaming");
+ m_type_combo.append("2", "Listening to");
+ m_type_combo.append("3", "Watching");
+ m_type_combo.append("4", "Custom");
+ m_type_combo.append("5", "Competing in");
+ m_type_combo.set_active_text("Custom");
+
+ m_ok.signal_clicked().connect([this]() {
+ response(Gtk::RESPONSE_OK);
+ });
+
+ m_cancel.signal_clicked().connect([this]() {
+ 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_bottom.add(m_status_combo);
+ m_bottom.add(m_type_combo);
+ m_bottom.add(m_bbox);
+ m_layout.add(m_text);
+ m_layout.add(m_bottom);
+ get_content_area()->add(m_layout);
+
+ show_all_children();
+}
+
+ActivityType SetStatusDialog::GetActivityType() const {
+ const auto x = m_type_combo.get_active_id();
+ return static_cast<ActivityType>(std::stoul(x));
+}
+
+PresenceStatus SetStatusDialog::GetStatusType() const {
+ const auto &x = m_status_combo.get_active_id();
+ if (x == "online")
+ return PresenceStatus::Online;
+ else if (x == "idle")
+ return PresenceStatus::Idle;
+ else if (x == "dnd")
+ return PresenceStatus::DND;
+ else if (x == "invisible")
+ return PresenceStatus::Offline;
+ return PresenceStatus::Online;
+}
+
+std::string SetStatusDialog::GetActivityName() const {
+ return m_text.get_text();
+}
diff --git a/src/dialogs/setstatus.hpp b/src/dialogs/setstatus.hpp
new file mode 100644
index 0000000..b06c182
--- /dev/null
+++ b/src/dialogs/setstatus.hpp
@@ -0,0 +1,22 @@
+#pragma once
+#include <gtkmm.h>
+#include "discord/objects.hpp"
+
+class SetStatusDialog : public Gtk::Dialog {
+public:
+ SetStatusDialog(Gtk::Window &parent);
+ ActivityType GetActivityType() const;
+ PresenceStatus GetStatusType() const;
+ std::string GetActivityName() const;
+
+protected:
+ Gtk::Box m_layout;
+ Gtk::Box m_bottom;
+ Gtk::Entry m_text;
+ Gtk::ComboBoxText m_status_combo;
+ Gtk::ComboBoxText m_type_combo;
+
+ Gtk::Button m_ok;
+ Gtk::Button m_cancel;
+ Gtk::ButtonBox m_bbox;
+};
diff --git a/src/dialogs/token.cpp b/src/dialogs/token.cpp
new file mode 100644
index 0000000..f984990
--- /dev/null
+++ b/src/dialogs/token.cpp
@@ -0,0 +1,43 @@
+#include "token.hpp"
+
+std::string trim(const std::string& str) {
+ const auto first = str.find_first_not_of(' ');
+ if (first == std::string::npos) return str;
+ const auto last = str.find_last_not_of(' ');
+ return str.substr(first, last - first + 1);
+}
+
+TokenDialog::TokenDialog(Gtk::Window &parent)
+ : Gtk::Dialog("Set Token", parent, true)
+ , m_layout(Gtk::ORIENTATION_VERTICAL)
+ , m_ok("OK")
+ , m_cancel("Cancel")
+ , m_bbox(Gtk::ORIENTATION_HORIZONTAL) {
+ set_default_size(300, 50);
+ get_style_context()->add_class("app-window");
+ get_style_context()->add_class("app-popup");
+
+ m_ok.signal_clicked().connect([&]() {
+ m_token = trim(m_entry.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_entry.set_hexpand(true);
+ m_layout.add(m_entry);
+ m_layout.add(m_bbox);
+ get_content_area()->add(m_layout);
+
+ show_all_children();
+}
+
+std::string TokenDialog::GetToken() {
+ return m_token;
+}
diff --git a/src/dialogs/token.hpp b/src/dialogs/token.hpp
new file mode 100644
index 0000000..7778bfb
--- /dev/null
+++ b/src/dialogs/token.hpp
@@ -0,0 +1,19 @@
+#pragma once
+#include <gtkmm.h>
+#include <string>
+
+class TokenDialog : public Gtk::Dialog {
+public:
+ TokenDialog(Gtk::Window &parent);
+ std::string GetToken();
+
+protected:
+ Gtk::Box m_layout;
+ Gtk::Button m_ok;
+ Gtk::Button m_cancel;
+ Gtk::ButtonBox m_bbox;
+ Gtk::Entry m_entry;
+
+private:
+ std::string m_token;
+};
diff --git a/src/dialogs/verificationgate.cpp b/src/dialogs/verificationgate.cpp
new file mode 100644
index 0000000..698ddff
--- /dev/null
+++ b/src/dialogs/verificationgate.cpp
@@ -0,0 +1,51 @@
+#include "verificationgate.hpp"
+#include "abaddon.hpp"
+
+VerificationGateDialog::VerificationGateDialog(Gtk::Window &parent, Snowflake guild_id)
+ : Gtk::Dialog("Verification Required", parent, true)
+ , m_bbox(Gtk::ORIENTATION_HORIZONTAL) {
+ set_default_size(300, 300);
+ get_style_context()->add_class("app-window");
+ get_style_context()->add_class("app-popup");
+
+ m_ok_button = add_button("Accept", Gtk::RESPONSE_OK);
+
+ m_scroll_rules.set_vexpand(true);
+ m_scroll_rules.set_hexpand(true);
+
+ m_description.set_line_wrap(true);
+ m_description.set_line_wrap_mode(Pango::WRAP_WORD_CHAR);
+ m_description.set_halign(Gtk::ALIGN_CENTER);
+ m_description.set_margin_bottom(5);
+
+ m_scroll_rules.add(m_rules);
+ get_content_area()->add(m_description);
+ get_content_area()->add(m_scroll_rules);
+ show_all_children();
+
+ Abaddon::Get().GetDiscordClient().GetVerificationGateInfo(guild_id, sigc::mem_fun(*this, &VerificationGateDialog::OnVerificationGateFetch));
+}
+
+const VerificationGateInfoObject &VerificationGateDialog::GetVerificationGate() const {
+ return m_gate_info;
+}
+
+void VerificationGateDialog::OnVerificationGateFetch(const std::optional<VerificationGateInfoObject> &info) {
+ m_gate_info = *info;
+ if (m_gate_info.Description.has_value())
+ m_description.set_markup("<b>" + Glib::Markup::escape_text(*m_gate_info.Description) + "</b>");
+ else
+ m_description.hide();
+ for (const auto &field : *info->VerificationFields) {
+ if (field.Type == "TERMS") {
+ for (const auto &rule : field.Values) {
+ auto *lbl = Gtk::manage(new Gtk::Label(rule));
+ lbl->set_halign(Gtk::ALIGN_START);
+ lbl->set_ellipsize(Pango::ELLIPSIZE_END);
+ lbl->show();
+ m_rules.add(*lbl);
+ }
+ break;
+ }
+ }
+}
diff --git a/src/dialogs/verificationgate.hpp b/src/dialogs/verificationgate.hpp
new file mode 100644
index 0000000..0a0dc08
--- /dev/null
+++ b/src/dialogs/verificationgate.hpp
@@ -0,0 +1,22 @@
+#pragma once
+#include <gtkmm.h>
+#include <optional>
+#include "discord/objects.hpp"
+
+class VerificationGateDialog : public Gtk::Dialog {
+public:
+ VerificationGateDialog(Gtk::Window &parent, Snowflake guild_id);
+ const VerificationGateInfoObject &GetVerificationGate() const;
+
+protected:
+ void OnVerificationGateFetch(const std::optional<VerificationGateInfoObject> &info);
+
+ VerificationGateInfoObject m_gate_info;
+
+ Gtk::Label m_description;
+ Gtk::ScrolledWindow m_scroll_rules;
+ Gtk::ListBox m_rules;
+ Gtk::ButtonBox m_bbox;
+
+ Gtk::Button *m_ok_button;
+};