mirror of
https://github.com/uowuo/abaddon.git
synced 2024-09-20 06:51:51 +00:00
add members panel/change member roles
This commit is contained in:
parent
11358da24e
commit
d6a8b8c333
|
@ -78,10 +78,11 @@ public:
|
|||
|
||||
Glib::RefPtr<Gtk::CssProvider> GetStyleProvider();
|
||||
|
||||
void ShowUserMenu(const GdkEvent *event, Snowflake id, Snowflake guild_id);
|
||||
|
||||
protected:
|
||||
Snowflake m_shown_user_menu_id;
|
||||
Snowflake m_shown_user_menu_guild_id;
|
||||
void ShowUserMenu(const GdkEvent *event, Snowflake id, Snowflake guild_id);
|
||||
|
||||
Gtk::Menu *m_user_menu;
|
||||
Gtk::MenuItem *m_user_menu_info;
|
||||
|
|
23
css/main.css
23
css/main.css
|
@ -292,3 +292,26 @@
|
|||
.app-window textview text {
|
||||
caret-color: #ababab;
|
||||
}
|
||||
|
||||
.guild-members-pane-info {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
||||
check,
|
||||
radio {
|
||||
background-clip: padding-box;
|
||||
background: #32506e;
|
||||
border-color: #070707;
|
||||
box-shadow: 0 1px rgba(0, 0, 0, 0);
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
check:checked,
|
||||
radio:checked {
|
||||
background-clip: border-box;
|
||||
background: #185fb4;
|
||||
border-color: #092444;
|
||||
box-shadow: 0 1px rgba(0, 0, 0, 0);
|
||||
color: #dddddd;
|
||||
}
|
||||
|
|
|
@ -1477,6 +1477,15 @@ bool DiscordClient::CheckCode(const http::response_type &r) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DiscordClient::CheckCode(const http::response_type &r, int expected) {
|
||||
if (!CheckCode(r)) return false;
|
||||
if (r.status_code != expected) {
|
||||
fprintf(stderr, "api request to %s returned %d, expected %d\n", r.url.c_str(), r.status_code, expected);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DiscordClient::StoreMessageData(Message &msg) {
|
||||
const auto chan = m_store.GetChannel(msg.ChannelID);
|
||||
if (chan.has_value() && chan->GuildID.has_value())
|
||||
|
|
|
@ -124,6 +124,16 @@ public:
|
|||
void AddGroupDMRecipient(Snowflake channel_id, Snowflake user_id);
|
||||
void RemoveGroupDMRecipient(Snowflake channel_id, Snowflake user_id);
|
||||
|
||||
// real client doesn't seem to use the single role endpoints so neither do we
|
||||
template<typename Iter>
|
||||
auto SetMemberRoles(Snowflake guild_id, Snowflake user_id, Iter begin, Iter end, sigc::slot<void(bool success)> callback) {
|
||||
ModifyGuildMemberObject obj;
|
||||
obj.Roles = { begin, end };
|
||||
m_http.MakePATCH("/guilds/" + std::to_string(guild_id) + "/members/" + std::to_string(user_id), nlohmann::json(obj).dump(), [this, callback](const http::response_type &response) {
|
||||
callback(CheckCode(response, 200));
|
||||
});
|
||||
}
|
||||
|
||||
// FetchGuildBans fetches all bans+reasons via api, this func fetches stored bans (so usually just GUILD_BAN_ADD data)
|
||||
std::vector<BanData> GetBansInGuild(Snowflake guild_id);
|
||||
void FetchGuildBan(Snowflake guild_id, Snowflake user_id, sigc::slot<void(BanData)> callback);
|
||||
|
@ -196,6 +206,7 @@ private:
|
|||
void HandleSocketClose(uint16_t code);
|
||||
|
||||
bool CheckCode(const http::response_type &r);
|
||||
bool CheckCode(const http::response_type &r, int expected);
|
||||
|
||||
void StoreMessageData(Message &msg);
|
||||
|
||||
|
|
|
@ -186,3 +186,14 @@ std::vector<Snowflake> GuildData::GetSortedChannels(Snowflake ignore) const {
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<RoleData> GuildData::FetchRoles() const {
|
||||
if (!Roles.has_value()) return {};
|
||||
std::vector<RoleData> ret;
|
||||
for (const auto thing : *Roles)
|
||||
ret.push_back(*Abaddon::Get().GetDiscordClient().GetRole(thing.ID));
|
||||
std::sort(ret.begin(), ret.end(), [](const RoleData &a, const RoleData &b) -> bool {
|
||||
return a.Position > b.Position;
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -75,4 +75,5 @@ struct GuildData {
|
|||
bool HasAnimatedIcon() const;
|
||||
std::string GetIconURL(std::string ext = "png", std::string size = "32") const;
|
||||
std::vector<Snowflake> GetSortedChannels(Snowflake ignore = Snowflake::Invalid) const;
|
||||
std::vector<RoleData> FetchRoles() const; // sorted
|
||||
};
|
||||
|
|
|
@ -363,3 +363,7 @@ void from_json(const nlohmann::json &j, UserNoteUpdateMessage &m) {
|
|||
void from_json(const nlohmann::json &j, RelationshipsData &m) {
|
||||
j.get_to(m.Users);
|
||||
}
|
||||
|
||||
void to_json(nlohmann::json &j, const ModifyGuildMemberObject &m) {
|
||||
JS_IF("roles", m.Roles);
|
||||
}
|
||||
|
|
|
@ -503,3 +503,14 @@ struct RelationshipsData {
|
|||
|
||||
friend void from_json(const nlohmann::json &j, RelationshipsData &m);
|
||||
};
|
||||
|
||||
struct ModifyGuildMemberObject {
|
||||
// std::optional<std::string> Nick;
|
||||
// std::optional<bool> IsMuted;
|
||||
// std::optional<bool> IsDeaf;
|
||||
// std::optional<Snowflake> ChannelID;
|
||||
|
||||
std::optional<std::vector<Snowflake>> Roles;
|
||||
|
||||
friend void to_json(nlohmann::json &j, const ModifyGuildMemberObject &m);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include "user.hpp"
|
||||
#include "../abaddon.hpp"
|
||||
|
||||
bool UserData::IsDeleted() const {
|
||||
return Discriminator == "0000";
|
||||
}
|
||||
|
||||
bool UserData::HasAvatar() const {
|
||||
return Avatar.size() > 0;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ struct UserData {
|
|||
friend void to_json(nlohmann::json &j, const UserData &m);
|
||||
void update_from_json(const nlohmann::json &j);
|
||||
|
||||
bool IsDeleted() const;
|
||||
bool HasAvatar() const;
|
||||
bool HasAnimatedAvatar() const;
|
||||
std::string GetAvatarURL(std::string ext = "png", std::string size = "32") const;
|
||||
|
|
8
util.cpp
8
util.cpp
|
@ -134,6 +134,14 @@ std::string IntToCSSColor(int color) {
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
Gdk::RGBA IntToRGBA(int color) {
|
||||
Gdk::RGBA ret;
|
||||
ret.set_red(((color & 0xFF0000) >> 16) / 255.0);
|
||||
ret.set_green(((color & 0x00FF00) >> 8) / 255.0);
|
||||
ret.set_blue(((color & 0x0000FF) >> 0) / 255.0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AddWidgetMenuHandler(Gtk::Widget *widget, Gtk::Menu &menu) {
|
||||
AddWidgetMenuHandler(widget, menu, []() {});
|
||||
}
|
||||
|
|
1
util.hpp
1
util.hpp
|
@ -38,6 +38,7 @@ private:
|
|||
void LaunchBrowser(Glib::ustring url);
|
||||
void GetImageDimensions(int inw, int inh, int &outw, int &outh, int clampw = 400, int clamph = 300);
|
||||
std::string IntToCSSColor(int color);
|
||||
Gdk::RGBA IntToRGBA(int color);
|
||||
void AddWidgetMenuHandler(Gtk::Widget *widget, Gtk::Menu &menu);
|
||||
void AddWidgetMenuHandler(Gtk::Widget *widget, Gtk::Menu &menu, sigc::slot<void()> pre_callback);
|
||||
std::vector<std::string> StringSplit(const std::string &str, const char *delim);
|
||||
|
|
394
windows/guildsettings/memberspane.cpp
Normal file
394
windows/guildsettings/memberspane.cpp
Normal file
|
@ -0,0 +1,394 @@
|
|||
#include "memberspane.hpp"
|
||||
#include "../../abaddon.hpp"
|
||||
|
||||
GuildSettingsMembersPane::GuildSettingsMembersPane(Snowflake id)
|
||||
: Gtk::Box(Gtk::ORIENTATION_VERTICAL)
|
||||
, m_layout(Gtk::ORIENTATION_HORIZONTAL)
|
||||
, m_member_list(id)
|
||||
, m_member_info(id)
|
||||
, GuildID(id) {
|
||||
set_name("guild-members-pane");
|
||||
set_hexpand(true);
|
||||
set_vexpand(true);
|
||||
|
||||
m_member_list.signal_member_select().connect(sigc::mem_fun(m_member_info, &GuildSettingsMembersPaneInfo::SetUser));
|
||||
|
||||
m_note.set_label("Some members may not be shown if the client is not aware of them");
|
||||
m_note.set_single_line_mode(true);
|
||||
m_note.set_ellipsize(Pango::ELLIPSIZE_END);
|
||||
|
||||
m_layout.set_homogeneous(true);
|
||||
m_layout.add(m_member_list);
|
||||
m_layout.add(m_member_info);
|
||||
add(m_note);
|
||||
add(m_layout);
|
||||
|
||||
m_member_list.show();
|
||||
m_member_info.show();
|
||||
m_note.show();
|
||||
m_layout.show();
|
||||
}
|
||||
|
||||
GuildSettingsMembersPaneMembers::GuildSettingsMembersPaneMembers(Snowflake id)
|
||||
: Gtk::Box(Gtk::ORIENTATION_VERTICAL)
|
||||
, GuildID(id) {
|
||||
m_list_scroll.get_style_context()->add_class("guild-members-pane-list");
|
||||
|
||||
m_list_scroll.set_hexpand(true);
|
||||
m_list_scroll.set_vexpand(true);
|
||||
m_list_scroll.set_propagate_natural_height(true);
|
||||
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
auto members = discord.GetUsersInGuild(id);
|
||||
for (const auto member_id : members) {
|
||||
auto member = *discord.GetMember(member_id, GuildID);
|
||||
member.User = discord.GetUser(member_id);
|
||||
if (member.User->IsDeleted()) continue;
|
||||
auto *row = Gtk::manage(new GuildSettingsMembersListItem(GuildID, member));
|
||||
row->show();
|
||||
m_list.add(*row);
|
||||
}
|
||||
|
||||
m_list.set_selection_mode(Gtk::SELECTION_SINGLE);
|
||||
m_list.signal_row_selected().connect([this](Gtk::ListBoxRow *selected_) {
|
||||
if (auto *selected = dynamic_cast<GuildSettingsMembersListItem *>(selected_))
|
||||
m_signal_member_select.emit(selected->UserID);
|
||||
});
|
||||
|
||||
m_search.set_placeholder_text("Filter");
|
||||
m_search.signal_changed().connect([this] {
|
||||
m_list.invalidate_filter();
|
||||
});
|
||||
|
||||
m_list.set_filter_func([this](Gtk::ListBoxRow *row_) -> bool {
|
||||
const auto search_term = m_search.get_text();
|
||||
if (search_term.size() == 0) return true;
|
||||
if (auto *row = dynamic_cast<GuildSettingsMembersListItem *>(row_))
|
||||
return StringContainsCaseless(row->DisplayTerm, m_search.get_text());
|
||||
return true;
|
||||
});
|
||||
|
||||
m_list_scroll.add(m_list);
|
||||
add(m_search);
|
||||
add(m_list_scroll);
|
||||
|
||||
m_search.show();
|
||||
m_list.show();
|
||||
m_list_scroll.show();
|
||||
}
|
||||
|
||||
GuildSettingsMembersPaneMembers::type_signal_member_select GuildSettingsMembersPaneMembers::signal_member_select() {
|
||||
return m_signal_member_select;
|
||||
}
|
||||
|
||||
GuildSettingsMembersListItem::GuildSettingsMembersListItem(Snowflake guild_id, const GuildMember &member)
|
||||
: UserID(member.User->ID)
|
||||
, GuildID(guild_id)
|
||||
, m_avatar(32, 32) {
|
||||
m_avatar.SetAnimated(true);
|
||||
|
||||
m_ev.signal_button_press_event().connect([this](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_SECONDARY) {
|
||||
Abaddon::Get().ShowUserMenu(reinterpret_cast<GdkEvent *>(event), UserID, GuildID);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
|
||||
if (member.User->HasAvatar()) {
|
||||
if (member.User->HasAnimatedAvatar() && Abaddon::Get().GetSettings().GetShowAnimations())
|
||||
m_avatar.SetURL(member.User->GetAvatarURL("gif", "32"));
|
||||
else
|
||||
m_avatar.SetURL(member.User->GetAvatarURL("png", "32"));
|
||||
}
|
||||
|
||||
DisplayTerm = member.User->Username + "#" + member.User->Discriminator;
|
||||
|
||||
const auto member_update_cb = [this](Snowflake guild_id, Snowflake user_id) {
|
||||
if (user_id == UserID)
|
||||
UpdateColor();
|
||||
};
|
||||
discord.signal_guild_member_update().connect(sigc::track_obj(member_update_cb, *this));
|
||||
UpdateColor();
|
||||
|
||||
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_main.add(m_avatar);
|
||||
m_main.add(m_name);
|
||||
|
||||
m_ev.add(m_main);
|
||||
add(m_ev);
|
||||
|
||||
m_avatar.show();
|
||||
m_name.show();
|
||||
m_main.show();
|
||||
m_ev.show();
|
||||
}
|
||||
|
||||
void GuildSettingsMembersListItem::UpdateColor() {
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
const auto user = *discord.GetUser(UserID);
|
||||
if (auto color_id = discord.GetMemberHoistedRole(GuildID, UserID, true); color_id.IsValid()) {
|
||||
auto role = *discord.GetRole(color_id);
|
||||
m_name.set_markup("<span color='#" + IntToCSSColor(role.Color) + "'>" + user.GetEscapedBoldString<false>() + "</span>");
|
||||
} else
|
||||
m_name.set_markup(user.GetEscapedBoldString<false>());
|
||||
}
|
||||
|
||||
GuildSettingsMembersPaneInfo::GuildSettingsMembersPaneInfo(Snowflake guild_id)
|
||||
: m_box(Gtk::ORIENTATION_VERTICAL)
|
||||
, GuildID(guild_id)
|
||||
, m_roles(guild_id) {
|
||||
get_style_context()->add_class("guild-members-pane-info");
|
||||
|
||||
const auto label = [](Gtk::Label &lbl) {
|
||||
lbl.set_single_line_mode(true);
|
||||
lbl.set_halign(Gtk::ALIGN_START);
|
||||
lbl.set_valign(Gtk::ALIGN_START);
|
||||
lbl.set_ellipsize(Pango::ELLIPSIZE_END);
|
||||
lbl.set_margin_bottom(5);
|
||||
lbl.show();
|
||||
};
|
||||
|
||||
m_bot.set_text("User is a bot");
|
||||
|
||||
label(m_bot);
|
||||
label(m_id);
|
||||
label(m_created);
|
||||
label(m_joined);
|
||||
label(m_nickname);
|
||||
label(m_boosting);
|
||||
|
||||
m_box.set_halign(Gtk::ALIGN_FILL);
|
||||
m_box.set_valign(Gtk::ALIGN_START);
|
||||
m_box.set_hexpand(true);
|
||||
m_box.set_vexpand(true);
|
||||
m_box.add(m_bot);
|
||||
m_box.add(m_id);
|
||||
m_box.add(m_created);
|
||||
m_box.add(m_joined);
|
||||
m_box.add(m_nickname);
|
||||
m_box.add(m_boosting);
|
||||
m_box.add(m_roles);
|
||||
|
||||
m_bot.hide();
|
||||
m_box.show();
|
||||
|
||||
add(m_box);
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneInfo::SetUser(Snowflake user_id) {
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
const auto guild = *discord.GetGuild(GuildID);
|
||||
auto member = *discord.GetMember(user_id, GuildID);
|
||||
member.User = discord.GetUser(user_id);
|
||||
|
||||
m_bot.set_visible(member.User->IsBot.has_value() && *member.User->IsBot);
|
||||
|
||||
m_id.set_text("User ID: " + std::to_string(user_id));
|
||||
m_created.set_text("Account created: " + user_id.GetLocalTimestamp());
|
||||
if (member.JoinedAt != "")
|
||||
m_joined.set_text("Joined server: " + FormatISO8601(member.JoinedAt));
|
||||
else
|
||||
m_joined.set_text("Joined server: Unknown");
|
||||
m_nickname.set_text("Nickname: " + member.Nickname);
|
||||
m_nickname.set_visible(member.Nickname != "");
|
||||
if (member.PremiumSince.has_value()) {
|
||||
m_boosting.set_text("Boosting since " + FormatISO8601(*member.PremiumSince));
|
||||
m_boosting.show();
|
||||
} else
|
||||
m_boosting.hide();
|
||||
|
||||
m_roles.show();
|
||||
m_roles.SetRoles(user_id, member.Roles, guild.OwnerID == discord.GetUserData().ID);
|
||||
}
|
||||
|
||||
GuildSettingsMembersPaneRoles::GuildSettingsMembersPaneRoles(Snowflake guild_id)
|
||||
: GuildID(guild_id) {
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
const auto self_id = discord.GetUserData().ID;
|
||||
const bool can_modify = discord.HasGuildPermission(self_id, guild_id, Permission::MANAGE_ROLES);
|
||||
const auto highest_id = discord.GetMemberHighestRole(GuildID, self_id);
|
||||
if (highest_id.IsValid())
|
||||
m_hoisted_position = discord.GetRole(highest_id)->Position;
|
||||
|
||||
discord.signal_role_create().connect(sigc::mem_fun(*this, &GuildSettingsMembersPaneRoles::OnRoleCreate));
|
||||
discord.signal_role_update().connect(sigc::mem_fun(*this, &GuildSettingsMembersPaneRoles::OnRoleUpdate));
|
||||
discord.signal_role_delete().connect(sigc::mem_fun(*this, &GuildSettingsMembersPaneRoles::OnRoleDelete));
|
||||
|
||||
const auto guild = *discord.GetGuild(guild_id);
|
||||
const auto roles = guild.FetchRoles();
|
||||
for (const auto &role : roles) {
|
||||
CreateRow(can_modify, role, guild.OwnerID == self_id);
|
||||
}
|
||||
|
||||
m_list.set_sort_func([this](Gtk::ListBoxRow *a, Gtk::ListBoxRow *b) -> int {
|
||||
auto *rowa = dynamic_cast<GuildSettingsMembersPaneRolesItem *>(a);
|
||||
auto *rowb = dynamic_cast<GuildSettingsMembersPaneRolesItem *>(b);
|
||||
return rowb->Position - rowa->Position;
|
||||
});
|
||||
|
||||
set_propagate_natural_height(true);
|
||||
set_propagate_natural_width(true);
|
||||
set_hexpand(true);
|
||||
set_vexpand(true);
|
||||
set_halign(Gtk::ALIGN_FILL);
|
||||
set_valign(Gtk::ALIGN_START);
|
||||
|
||||
m_list.show();
|
||||
|
||||
add(m_list);
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRoles::SetRoles(Snowflake user_id, const std::vector<Snowflake> &roles, bool is_owner) {
|
||||
UserID = user_id;
|
||||
|
||||
for (auto it = m_update_connection.begin(); it != m_update_connection.end();) {
|
||||
it->disconnect();
|
||||
it = m_update_connection.erase(it);
|
||||
}
|
||||
|
||||
m_set_role_ids = { roles.begin(), roles.end() };
|
||||
for (const auto &[role_id, row] : m_rows) {
|
||||
auto role = *Abaddon::Get().GetDiscordClient().GetRole(role_id);
|
||||
if (role.ID == GuildID) {
|
||||
row->SetChecked(true);
|
||||
row->SetToggleable(false);
|
||||
} else {
|
||||
row->SetToggleable(role.Position < m_hoisted_position || is_owner);
|
||||
row->SetChecked(m_set_role_ids.find(role_id) != m_set_role_ids.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRoles::CreateRow(bool has_manage_roles, const RoleData &role, bool is_owner) {
|
||||
auto *row = Gtk::manage(new GuildSettingsMembersPaneRolesItem(has_manage_roles, role));
|
||||
if (role.ID == GuildID) {
|
||||
row->SetChecked(true);
|
||||
row->SetToggleable(false);
|
||||
} else
|
||||
row->SetToggleable(role.Position < m_hoisted_position || is_owner);
|
||||
row->signal_role_click().connect(sigc::mem_fun(*this, &GuildSettingsMembersPaneRoles::OnRoleToggle));
|
||||
row->show();
|
||||
m_rows[role.ID] = row;
|
||||
m_list.add(*row);
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRoles::OnRoleToggle(Snowflake role_id, bool new_set) {
|
||||
auto row = m_rows.at(role_id);
|
||||
row->SetToggleable(false);
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
auto cb = [this, new_set, role_id, row](bool success) {
|
||||
if (!success) { // undo
|
||||
if (new_set)
|
||||
m_set_role_ids.erase(role_id);
|
||||
else
|
||||
m_set_role_ids.insert(role_id);
|
||||
} else
|
||||
row->SetChecked(new_set);
|
||||
|
||||
row->SetToggleable(true);
|
||||
};
|
||||
|
||||
if (new_set)
|
||||
m_set_role_ids.insert(role_id);
|
||||
else
|
||||
m_set_role_ids.erase(role_id);
|
||||
|
||||
// hack to prevent cb from being called if SetRoles is called before callback completion
|
||||
sigc::signal<void, bool> tmp;
|
||||
m_update_connection.push_back(tmp.connect(std::move(cb)));
|
||||
const auto tmp_cb = [this, tmp = std::move(tmp)](bool success) { tmp.emit(success); };
|
||||
discord.SetMemberRoles(GuildID, UserID, m_set_role_ids.begin(), m_set_role_ids.end(), sigc::track_obj(tmp_cb, *this));
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRoles::OnRoleCreate(Snowflake guild_id, Snowflake role_id) {
|
||||
if (guild_id != GuildID) return;
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
const auto self_id = discord.GetUserData().ID;
|
||||
const bool can_modify = discord.HasGuildPermission(self_id, GuildID, Permission::MANAGE_ROLES);
|
||||
const auto role = *discord.GetRole(role_id);
|
||||
CreateRow(can_modify, role, discord.GetGuild(guild_id)->OwnerID == self_id);
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRoles::OnRoleUpdate(Snowflake guild_id, Snowflake role_id) {
|
||||
if (guild_id != GuildID) return;
|
||||
auto role = *Abaddon::Get().GetDiscordClient().GetRole(role_id);
|
||||
m_rows.at(role_id)->UpdateRoleData(role);
|
||||
m_list.invalidate_sort();
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRoles::OnRoleDelete(Snowflake guild_id, Snowflake role_id) {
|
||||
if (guild_id != GuildID) return;
|
||||
delete m_rows.at(role_id);
|
||||
}
|
||||
|
||||
GuildSettingsMembersPaneRolesItem::GuildSettingsMembersPaneRolesItem(bool sensitive, const RoleData &role)
|
||||
: RoleID(role.ID) {
|
||||
UpdateRoleData(role);
|
||||
|
||||
m_main.set_hexpand(true);
|
||||
m_main.set_vexpand(true);
|
||||
|
||||
const auto cb = [this](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) {
|
||||
m_signal_role_click.emit(RoleID, !m_check.get_active());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
m_check.signal_button_press_event().connect(cb, false);
|
||||
|
||||
m_desired_sensitivity = sensitive;
|
||||
ComputeSensitivity();
|
||||
|
||||
m_check.set_margin_start(5);
|
||||
m_label.set_margin_start(5);
|
||||
|
||||
m_main.add(m_check);
|
||||
m_main.add(m_label);
|
||||
add(m_main);
|
||||
m_check.show();
|
||||
m_label.show();
|
||||
m_main.show();
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRolesItem::SetChecked(bool checked) {
|
||||
m_check.set_active(checked);
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRolesItem::SetToggleable(bool toggleable) {
|
||||
m_desired_sensitivity = toggleable;
|
||||
ComputeSensitivity();
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRolesItem::UpdateRoleData(const RoleData &role) {
|
||||
m_role = role;
|
||||
Position = role.Position;
|
||||
UpdateLabel();
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRolesItem::UpdateLabel() {
|
||||
if (m_role.Color)
|
||||
m_label.set_markup("<span color='#" + IntToCSSColor(m_role.Color) + "'>" + Glib::Markup::escape_text(m_role.Name) + "</span>");
|
||||
else
|
||||
m_label.set_text(m_role.Name);
|
||||
}
|
||||
|
||||
void GuildSettingsMembersPaneRolesItem::ComputeSensitivity() {
|
||||
if (m_role.IsManaged) {
|
||||
m_check.set_sensitive(false);
|
||||
return;
|
||||
}
|
||||
m_check.set_sensitive(m_desired_sensitivity);
|
||||
}
|
||||
|
||||
GuildSettingsMembersPaneRolesItem::type_signal_role_click GuildSettingsMembersPaneRolesItem::signal_role_click() {
|
||||
return m_signal_role_click;
|
||||
}
|
133
windows/guildsettings/memberspane.hpp
Normal file
133
windows/guildsettings/memberspane.hpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
#pragma once
|
||||
#include <unordered_set>
|
||||
#include <gtkmm.h>
|
||||
#include "../../discord/member.hpp"
|
||||
#include "../../components/lazyimage.hpp"
|
||||
|
||||
class GuildSettingsMembersPaneRolesItem : public Gtk::ListBoxRow {
|
||||
public:
|
||||
GuildSettingsMembersPaneRolesItem(bool sensitive, const RoleData &role);
|
||||
void SetChecked(bool checked);
|
||||
void SetToggleable(bool toggleable);
|
||||
void UpdateRoleData(const RoleData &role);
|
||||
|
||||
Snowflake RoleID;
|
||||
int Position;
|
||||
|
||||
private:
|
||||
void UpdateLabel();
|
||||
void ComputeSensitivity();
|
||||
bool m_desired_sensitivity = true;
|
||||
|
||||
RoleData m_role;
|
||||
|
||||
Gtk::Box m_main;
|
||||
Gtk::CheckButton m_check;
|
||||
Gtk::Label m_label;
|
||||
|
||||
// own thing so we can stop it from actually changing
|
||||
typedef sigc::signal<void, Snowflake, bool> type_signal_role_click;
|
||||
|
||||
type_signal_role_click m_signal_role_click;
|
||||
|
||||
public:
|
||||
type_signal_role_click signal_role_click();
|
||||
};
|
||||
|
||||
class GuildSettingsMembersPaneRoles : public Gtk::ScrolledWindow {
|
||||
public:
|
||||
GuildSettingsMembersPaneRoles(Snowflake guild_id);
|
||||
|
||||
void SetRoles(Snowflake user_id, const std::vector<Snowflake> &roles, bool is_owner);
|
||||
|
||||
private:
|
||||
void CreateRow(bool has_manage_roles, const RoleData &role, bool is_owner);
|
||||
|
||||
void OnRoleToggle(Snowflake role_id, bool new_set);
|
||||
|
||||
void OnRoleCreate(Snowflake guild_id, Snowflake role_id);
|
||||
void OnRoleUpdate(Snowflake guild_id, Snowflake role_id);
|
||||
void OnRoleDelete(Snowflake guild_id, Snowflake role_id);
|
||||
|
||||
int m_hoisted_position = 0;
|
||||
|
||||
std::vector<sigc::connection> m_update_connection;
|
||||
|
||||
std::unordered_set<Snowflake> m_set_role_ids;
|
||||
|
||||
Snowflake GuildID;
|
||||
Snowflake UserID;
|
||||
|
||||
Gtk::ListBox m_list;
|
||||
|
||||
std::unordered_map<Snowflake, GuildSettingsMembersPaneRolesItem *> m_rows;
|
||||
};
|
||||
|
||||
class GuildSettingsMembersPaneInfo : public Gtk::ScrolledWindow {
|
||||
public:
|
||||
GuildSettingsMembersPaneInfo(Snowflake guild_id);
|
||||
|
||||
void SetUser(Snowflake user_id);
|
||||
|
||||
private:
|
||||
Snowflake GuildID;
|
||||
Snowflake UserID;
|
||||
|
||||
Gtk::Label m_bot;
|
||||
Gtk::Label m_id;
|
||||
Gtk::Label m_created;
|
||||
Gtk::Label m_joined;
|
||||
Gtk::Label m_nickname;
|
||||
Gtk::Label m_boosting;
|
||||
GuildSettingsMembersPaneRoles m_roles;
|
||||
Gtk::Box m_box;
|
||||
};
|
||||
|
||||
class GuildSettingsMembersPaneMembers : public Gtk::Box {
|
||||
public:
|
||||
GuildSettingsMembersPaneMembers(Snowflake id);
|
||||
|
||||
private:
|
||||
Snowflake GuildID;
|
||||
|
||||
Gtk::Entry m_search;
|
||||
Gtk::ScrolledWindow m_list_scroll;
|
||||
Gtk::ListBox m_list;
|
||||
|
||||
typedef sigc::signal<void, Snowflake> type_signal_member_select;
|
||||
type_signal_member_select m_signal_member_select;
|
||||
|
||||
public:
|
||||
type_signal_member_select signal_member_select();
|
||||
};
|
||||
|
||||
class GuildSettingsMembersListItem : public Gtk::ListBoxRow {
|
||||
public:
|
||||
GuildSettingsMembersListItem(Snowflake guild_id, const GuildMember &member);
|
||||
|
||||
Glib::ustring DisplayTerm;
|
||||
|
||||
Snowflake UserID;
|
||||
Snowflake GuildID;
|
||||
|
||||
private:
|
||||
void UpdateColor();
|
||||
|
||||
Gtk::EventBox m_ev;
|
||||
LazyImage m_avatar;
|
||||
Gtk::Label m_name;
|
||||
Gtk::Box m_main;
|
||||
};
|
||||
|
||||
class GuildSettingsMembersPane : public Gtk::Box {
|
||||
public:
|
||||
GuildSettingsMembersPane(Snowflake id);
|
||||
|
||||
private:
|
||||
Snowflake GuildID;
|
||||
|
||||
Gtk::Box m_layout;
|
||||
Gtk::Label m_note;
|
||||
GuildSettingsMembersPaneMembers m_member_list;
|
||||
GuildSettingsMembersPaneInfo m_member_info;
|
||||
};
|
|
@ -7,7 +7,8 @@ GuildSettingsWindow::GuildSettingsWindow(Snowflake id)
|
|||
, m_pane_info(id)
|
||||
, m_pane_bans(id)
|
||||
, m_pane_invites(id)
|
||||
, m_pane_audit_log(id) {
|
||||
, m_pane_audit_log(id)
|
||||
, m_pane_members(id) {
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
const auto guild = *discord.GetGuild(id);
|
||||
|
||||
|
@ -39,6 +40,7 @@ GuildSettingsWindow::GuildSettingsWindow(Snowflake id)
|
|||
m_switcher.show();
|
||||
|
||||
m_pane_info.show();
|
||||
m_pane_members.show();
|
||||
m_pane_bans.show();
|
||||
m_pane_invites.show();
|
||||
m_pane_audit_log.show();
|
||||
|
@ -53,6 +55,7 @@ GuildSettingsWindow::GuildSettingsWindow(Snowflake id)
|
|||
const auto self_id = discord.GetUserData().ID;
|
||||
|
||||
m_stack.add(m_pane_info, "info", "Info");
|
||||
m_stack.add(m_pane_members, "members", "Members");
|
||||
m_stack.add(m_pane_bans, "bans", "Bans");
|
||||
if (discord.HasGuildPermission(self_id, GuildID, Permission::MANAGE_GUILD))
|
||||
m_stack.add(m_pane_invites, "invites", "Invites");
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "guildsettings/banspane.hpp"
|
||||
#include "guildsettings/invitespane.hpp"
|
||||
#include "guildsettings/auditlogpane.hpp"
|
||||
#include "guildsettings/memberspane.hpp"
|
||||
|
||||
class GuildSettingsWindow : public Gtk::Window {
|
||||
public:
|
||||
|
@ -19,6 +20,7 @@ private:
|
|||
Gtk::StackSwitcher m_switcher;
|
||||
|
||||
GuildSettingsInfoPane m_pane_info;
|
||||
GuildSettingsMembersPane m_pane_members;
|
||||
GuildSettingsBansPane m_pane_bans;
|
||||
GuildSettingsInvitesPane m_pane_invites;
|
||||
GuildSettingsAuditLogPane m_pane_audit_log;
|
||||
|
|
Loading…
Reference in New Issue
Block a user