handle mutable categories

This commit is contained in:
ouwou 2022-01-05 03:52:20 -05:00
parent 8695562cb4
commit 40106ddeb1
9 changed files with 94 additions and 3 deletions

View File

@ -116,7 +116,15 @@ ChannelList::ChannelList()
m_menu_category_copy_id.signal_activate().connect([this] {
Gtk::Clipboard::get()->set_text(std::to_string((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]));
});
m_menu_category_toggle_mute.signal_activate().connect([this] {
const auto id = static_cast<Snowflake>((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]);
auto &discord = Abaddon::Get().GetDiscordClient();
if (discord.IsChannelMuted(id))
discord.UnmuteChannel(id, NOOP_CALLBACK);
else
discord.MuteChannel(id, NOOP_CALLBACK);
});
m_menu_category.append(m_menu_category_toggle_mute);
m_menu_category.append(m_menu_category_copy_id);
m_menu_category.show_all();
@ -177,6 +185,7 @@ ChannelList::ChannelList()
m_menu_thread.show_all();
m_menu_guild.signal_popped_up().connect(sigc::mem_fun(*this, &ChannelList::OnGuildSubmenuPopup));
m_menu_category.signal_popped_up().connect(sigc::mem_fun(*this, &ChannelList::OnCategorySubmenuPopup));
m_menu_channel.signal_popped_up().connect(sigc::mem_fun(*this, &ChannelList::OnChannelSubmenuPopup));
m_menu_thread.signal_popped_up().connect(sigc::mem_fun(*this, &ChannelList::OnThreadSubmenuPopup));
@ -857,6 +866,16 @@ void ChannelList::OnGuildSubmenuPopup(const Gdk::Rectangle *flipped_rect, const
m_menu_guild_toggle_mute.set_label("Mute");
}
void ChannelList::OnCategorySubmenuPopup(const Gdk::Rectangle *flipped_rect, const Gdk::Rectangle *final_rect, bool flipped_x, bool flipped_y) {
const auto iter = m_model->get_iter(m_path_for_menu);
if (!iter) return;
const auto id = static_cast<Snowflake>((*iter)[m_columns.m_id]);
if (Abaddon::Get().GetDiscordClient().IsChannelMuted(id))
m_menu_category_toggle_mute.set_label("Unmute");
else
m_menu_category_toggle_mute.set_label("Mute");
}
void ChannelList::OnChannelSubmenuPopup(const Gdk::Rectangle *flipped_rect, const Gdk::Rectangle *final_rect, bool flipped_x, bool flipped_y) {
const auto iter = m_model->get_iter(m_path_for_menu);
if (!iter) return;

View File

@ -114,6 +114,7 @@ protected:
Gtk::Menu m_menu_category;
Gtk::MenuItem m_menu_category_copy_id;
Gtk::MenuItem m_menu_category_toggle_mute;
Gtk::Menu m_menu_channel;
Gtk::MenuItem m_menu_channel_copy_id;
@ -131,6 +132,7 @@ protected:
Gtk::MenuItem m_menu_thread_unarchive;
void OnGuildSubmenuPopup(const Gdk::Rectangle *flipped_rect, const Gdk::Rectangle *final_rect, bool flipped_x, bool flipped_y);
void OnCategorySubmenuPopup(const Gdk::Rectangle *flipped_rect, const Gdk::Rectangle *final_rect, bool flipped_x, bool flipped_y);
void OnChannelSubmenuPopup(const Gdk::Rectangle *flipped_rect, const Gdk::Rectangle *final_rect, bool flipped_x, bool flipped_y);
void OnThreadSubmenuPopup(const Gdk::Rectangle *flipped_rect, const Gdk::Rectangle *final_rect, bool flipped_x, bool flipped_y);

View File

@ -327,7 +327,11 @@ void CellRendererChannels::render_vfunc_category(const Cairo::RefPtr<Cairo::Cont
Gdk::Rectangle text_cell_area(text_x, text_y, text_w, text_h);
static Gdk::RGBA muted_color("#7f7f7f");
if (Abaddon::Get().GetDiscordClient().IsChannelMuted(m_property_id.get_value()))
m_renderer_text.property_foreground_rgba() = muted_color;
m_renderer_text.render(cr, widget, background_area, text_cell_area, flags);
m_renderer_text.property_foreground_set() = false;
}
// text channel

View File

@ -78,6 +78,14 @@ bool ChannelData::IsJoinedThread() const {
return Abaddon::Get().GetDiscordClient().IsThreadJoined(ID);
}
bool ChannelData::IsCategory() const noexcept {
return Type == ChannelType::GUILD_CATEGORY;
}
std::vector<Snowflake> ChannelData::GetChildIDs() const {
return Abaddon::Get().GetDiscordClient().GetChildChannelIDs(ID);
}
std::optional<PermissionOverwrite> ChannelData::GetOverwrite(Snowflake id) const {
return Abaddon::Get().GetDiscordClient().GetPermissionOverwrite(ID, id);
}

View File

@ -88,6 +88,8 @@ struct ChannelData {
bool IsDM() const noexcept;
bool IsThread() const noexcept;
bool IsJoinedThread() const;
bool IsCategory() const noexcept;
std::vector<Snowflake> GetChildIDs() const;
std::optional<PermissionOverwrite> GetOverwrite(Snowflake id) const;
std::vector<UserData> GetDMRecipients() const;
};

View File

@ -307,6 +307,10 @@ void DiscordClient::GetArchivedPrivateThreads(Snowflake channel_id, sigc::slot<v
});
}
std::vector<Snowflake> DiscordClient::GetChildChannelIDs(Snowflake parent_id) const {
return m_store.GetChannelIDsWithParentID(parent_id);
}
bool DiscordClient::IsThreadJoined(Snowflake thread_id) const {
return std::find(m_joined_threads.begin(), m_joined_threads.end(), thread_id) != m_joined_threads.end();
}
@ -1184,10 +1188,15 @@ bool DiscordClient::GetUnreadStateForGuild(Snowflake id, int &total_mentions) co
const auto channels = GetChannelsInGuild(id);
for (const auto channel_id : channels) {
const auto channel_unread = GetUnreadStateForChannel(channel_id);
if (!has_any_unread && channel_unread > -1 && !IsChannelMuted(channel_id))
has_any_unread = true;
if (channel_unread > -1)
total_mentions += channel_unread;
// channels under muted categories wont contribute to unread state
if (const auto iter = m_channel_muted_parent.find(channel_id); iter != m_channel_muted_parent.end())
continue;
if (!has_any_unread && channel_unread > -1 && !IsChannelMuted(channel_id))
has_any_unread = true;
}
return has_any_unread;
}
@ -1974,11 +1983,19 @@ void DiscordClient::HandleGatewayUserGuildSettingsUpdate(const GatewayMessage &m
if (now_muted) {
m_muted_channels.insert(channel_id);
if (!was_muted) {
if (const auto chan = GetChannel(channel_id); chan.has_value() && chan->IsCategory())
for (const auto child_id : chan->GetChildIDs())
m_channel_muted_parent.insert(child_id);
m_signal_channel_muted.emit(channel_id);
}
} else {
m_muted_channels.erase(channel_id);
if (was_muted) {
if (const auto chan = GetChannel(channel_id); chan.has_value() && chan->IsCategory())
for (const auto child_id : chan->GetChildIDs())
m_channel_muted_parent.erase(child_id);
m_signal_channel_unmuted.emit(channel_id);
}
}
@ -2357,6 +2374,14 @@ void DiscordClient::HandleReadyReadState(const ReadyEventData &data) {
}
void DiscordClient::HandleReadyGuildSettings(const ReadyEventData &data) {
// i dont like this implementation for muted categories but its rather simple and doesnt use a horriiible amount of ram
std::unordered_map<Snowflake, std::vector<Snowflake>> category_children;
for (const auto &guild : data.Guilds)
for (const auto &channel : *guild.Channels)
if (channel.ParentID.has_value() && !channel.IsThread())
category_children[*channel.ParentID].push_back(channel.ID);
const auto now = Snowflake::FromNow();
for (const auto &entry : data.GuildSettings.Entries) {
// even if muted is true a guild/channel can be unmuted if the current time passes mute_config.end_time
@ -2371,6 +2396,10 @@ void DiscordClient::HandleReadyGuildSettings(const ReadyEventData &data) {
}
for (const auto &override : entry.ChannelOverrides) {
if (override.Muted) {
if (const auto iter = category_children.find(override.ChannelID); iter != category_children.end())
for (const auto child : iter->second)
m_channel_muted_parent.insert(child);
if (override.MuteConfig.EndTime.has_value()) {
const auto end = Snowflake::FromISO8601(*override.MuteConfig.EndTime);
if (end.IsValid() && end > now)

View File

@ -82,6 +82,7 @@ public:
std::vector<ChannelData> GetActiveThreads(Snowflake channel_id) const;
void GetArchivedPublicThreads(Snowflake channel_id, sigc::slot<void(DiscordError, const ArchivedThreadsResponseData &)> callback);
void GetArchivedPrivateThreads(Snowflake channel_id, sigc::slot<void(DiscordError, const ArchivedThreadsResponseData &)> callback);
std::vector<Snowflake> GetChildChannelIDs(Snowflake parent_id) const;
bool IsThreadJoined(Snowflake thread_id) const;
bool HasGuildPermission(Snowflake user_id, Snowflake guild_id, Permission perm) const;
@ -290,6 +291,7 @@ private:
std::unordered_set<Snowflake> m_muted_guilds;
std::unordered_set<Snowflake> m_muted_channels;
std::unordered_map<Snowflake, int> m_unread;
std::unordered_set<Snowflake> m_channel_muted_parent;
UserData m_user_data;
UserSettings m_user_settings;

View File

@ -571,6 +571,21 @@ std::vector<ChannelData> Store::GetActiveThreads(Snowflake channel_id) const {
return ret;
}
std::vector<Snowflake> Store::GetChannelIDsWithParentID(Snowflake channel_id) const {
auto &s = m_stmt_get_chan_ids_parent;
s->Bind(1, channel_id);
std::vector<Snowflake> ret;
while (s->FetchOne()) {
Snowflake x;
s->Get(0, x);
ret.push_back(x);
}
return ret;
}
void Store::AddReaction(const MessageReactionAddObject &data, bool byself) {
auto &s = m_stmt_add_reaction;
@ -2120,6 +2135,14 @@ bool Store::CreateStatements() {
return false;
}
m_stmt_get_chan_ids_parent = std::make_unique<Statement>(m_db, R"(
SELECT id FROM channels WHERE parent_id = ?
)");
if (!m_stmt_get_chan_ids_parent->OK()) {
fprintf(stderr, "failed to prepare get channel ids for parent statement: %s\n", m_db.ErrStr());
return false;
}
return true;
}

View File

@ -43,6 +43,7 @@ public:
std::vector<Message> GetMessagesBefore(Snowflake channel_id, Snowflake message_id, size_t limit) const;
std::vector<Message> GetPinnedMessages(Snowflake channel_id) const;
std::vector<ChannelData> GetActiveThreads(Snowflake channel_id) const; // public
std::vector<Snowflake> GetChannelIDsWithParentID(Snowflake channel_id) const;
void AddReaction(const MessageReactionAddObject &data, bool byself);
void RemoveReaction(const MessageReactionRemoveObject &data, bool byself);
@ -300,5 +301,6 @@ private:
STMT(add_reaction);
STMT(sub_reaction);
STMT(get_reactions);
STMT(get_chan_ids_parent);
#undef STMT
};