Restructure source and resource files (#46)

importantly, res is now res/res and css is now res/css
This commit is contained in:
Dylam De La Torre
2021-11-23 05:21:56 +01:00
committed by GitHub
parent d88079000a
commit a51a54bc59
216 changed files with 21 additions and 33 deletions

36
src/dialogs/confirm.cpp Normal file
View File

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

15
src/dialogs/confirm.hpp Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

97
src/dialogs/joinguild.cpp Normal file
View File

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

31
src/dialogs/joinguild.hpp Normal file
View File

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

72
src/dialogs/setstatus.cpp Normal file
View File

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

22
src/dialogs/setstatus.hpp Normal file
View File

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

43
src/dialogs/token.cpp Normal file
View File

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

19
src/dialogs/token.hpp Normal file
View File

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

View File

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

View File

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