From 7ed65a89ae71c3c5d2ba99797bd2b1d93ce172ca Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sat, 20 Apr 2024 04:16:57 +0800 Subject: [PATCH 01/25] platform.cpp: add a missing spdlog include --- src/platform.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform.cpp b/src/platform.cpp index 0a69721..a26822d 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -4,6 +4,8 @@ #include #include +#include + using namespace std::literals::string_literals; #if defined(_WIN32) From 11fb36809d6ea4d6d1328149e995435f56466c2f Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 14 May 2024 01:25:42 -0400 Subject: [PATCH 02/25] make qr code black (closes #297) --- src/remoteauth/remoteauthdialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remoteauth/remoteauthdialog.cpp b/src/remoteauth/remoteauthdialog.cpp index aa0cf38..d6df926 100644 --- a/src/remoteauth/remoteauthdialog.cpp +++ b/src/remoteauth/remoteauthdialog.cpp @@ -75,7 +75,7 @@ void RemoteAuthDialog::OnFingerprint(const std::string &fingerprint) { int size = qr.getSize(); const int border = 4; - const auto module_set = "192 0 255"; + const auto module_set = "0 0 0"; const auto module_clr = "255 255 255"; std::ostringstream sb; From cba2f6c66ef27c992072afa79ebaae541814506b Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sun, 19 May 2024 07:07:04 +0800 Subject: [PATCH 03/25] Fix-ups for macOS (#291) * Do not use precomp headers target with GCC on Apple * CMakeLists: also link to AudioUnit on Apple * platform.cpp: add missing --------- Co-authored-by: ouwou <26526779+ouwou@users.noreply.github.com> --- CMakeLists.txt | 5 ++++- src/platform.cpp | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 236dbd2..99cc9ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,9 @@ if (ENABLE_QRCODE_LOGIN) target_compile_definitions(abaddon PRIVATE WITH_QRLOGIN) endif () -target_precompile_headers(abaddon PRIVATE src/abaddon.hpp src/util.hpp) +if (NOT (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")) + target_precompile_headers(abaddon PRIVATE src/abaddon.hpp src/util.hpp) +endif() if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND @@ -146,6 +148,7 @@ if (APPLE) target_link_libraries(abaddon "-framework CoreFoundation") target_link_libraries(abaddon "-framework CoreAudio") target_link_libraries(abaddon "-framework AudioToolbox") + target_link_libraries(abaddon "-framework AudioUnit") endif () if (ENABLE_VOICE) diff --git a/src/platform.cpp b/src/platform.cpp index a26822d..ce0ac74 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -4,6 +4,10 @@ #include #include +#ifdef __APPLE__ + #include +#endif + #include using namespace std::literals::string_literals; From 72975d8517c7d3230faffe4a3ee030da5d594f8e Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 21 May 2024 01:51:16 -0400 Subject: [PATCH 04/25] handle new and updated voice channels i hope --- src/components/channellist/channellisttree.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/channellist/channellisttree.cpp b/src/components/channellist/channellisttree.cpp index 4816b42..3b11485 100644 --- a/src/components/channellist/channellisttree.cpp +++ b/src/components/channellist/channellisttree.cpp @@ -490,7 +490,13 @@ void ChannelListTree::UpdateChannel(Snowflake id) { auto channel = Abaddon::Get().GetDiscordClient().GetChannel(id); if (!iter || !channel.has_value()) return; if (channel->Type == ChannelType::GUILD_CATEGORY) return UpdateChannelCategory(*channel); + // TODO: theres like 4 different fucking ways of checking if somethin g is text or voice can i fix that How stupid . + // fun fact clang-format is indenting me right now i wonder why ,,,,,,,,,,, +#ifdef WITH_VOICE + if (!channel->IsText() && channel->Type != ChannelType::GUILD_VOICE) return; +#else if (!channel->IsText()) return; +#endif // refresh stuff that might have changed const bool is_orphan_TMP = !channel->ParentID.has_value(); @@ -512,7 +518,11 @@ void ChannelListTree::UpdateChannel(Snowflake id) { void ChannelListTree::UpdateCreateChannel(const ChannelData &channel) { if (channel.Type == ChannelType::GUILD_CATEGORY) return (void)UpdateCreateChannelCategory(channel); if (channel.Type == ChannelType::DM || channel.Type == ChannelType::GROUP_DM) return UpdateCreateDMChannel(channel); +#ifdef WITH_VOICE + if (channel.Type != ChannelType::GUILD_TEXT && channel.Type != ChannelType::GUILD_NEWS && channel.Type != ChannelType::GUILD_VOICE) return; +#else if (channel.Type != ChannelType::GUILD_TEXT && channel.Type != ChannelType::GUILD_NEWS) return; +#endif Gtk::TreeRow channel_row; bool orphan; @@ -525,7 +535,7 @@ void ChannelListTree::UpdateCreateChannel(const ChannelData &channel) { auto iter = GetIteratorForGuildFromID(*channel.GuildID); channel_row = *m_model->append(iter->children()); } - channel_row[m_columns.m_type] = RenderType::TextChannel; + channel_row[m_columns.m_type] = IsTextChannel(channel.Type) ? RenderType::TextChannel : RenderType::VoiceChannel; channel_row[m_columns.m_id] = channel.ID; channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name); channel_row[m_columns.m_nsfw] = channel.NSFW(); From 057dd2a1f8de65e4885f48211e324e1b966f4e2f Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 21 May 2024 02:06:20 -0400 Subject: [PATCH 05/25] add ugly little mention indicator to classic guild listing --- .../channellist/cellrendererchannels.cpp | 19 ++---- .../channellist/cellrendererchannels.hpp | 1 - .../channellist/classic/guildlist.cpp | 14 ++++- .../classic/guildlistfolderitem.cpp | 2 +- .../classic/guildlistfolderitem.hpp | 2 +- .../channellist/classic/mentionoverlay.cpp | 62 +++++++++++++++++++ .../channellist/classic/mentionoverlay.hpp | 19 ++++++ src/misc/cairo.cpp | 17 +++++ src/misc/cairo.hpp | 5 ++ 9 files changed, 122 insertions(+), 19 deletions(-) create mode 100644 src/components/channellist/classic/mentionoverlay.cpp create mode 100644 src/components/channellist/classic/mentionoverlay.hpp create mode 100644 src/misc/cairo.cpp create mode 100644 src/misc/cairo.hpp diff --git a/src/components/channellist/cellrendererchannels.cpp b/src/components/channellist/cellrendererchannels.cpp index b049252..bb2b9ba 100644 --- a/src/components/channellist/cellrendererchannels.cpp +++ b/src/components/channellist/cellrendererchannels.cpp @@ -1,13 +1,15 @@ #include "cellrendererchannels.hpp" + #include + +#include "misc/cairo.hpp" + #include "abaddon.hpp" constexpr static int MentionsRightPad = 7; #ifndef M_PI constexpr static double M_PI = 3.14159265358979; #endif -constexpr static double M_PI_H = M_PI / 2.0; -constexpr static double M_PI_3_2 = M_PI * 3.0 / 2.0; void AddUnreadIndicator(const Cairo::RefPtr &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area) { static const auto color_setting = Gdk::RGBA(Abaddon::Get().GetSettings().UnreadIndicatorColor); @@ -832,17 +834,6 @@ void CellRendererChannels::render_vfunc_dm(const Cairo::RefPtr & } } -void CellRendererChannels::cairo_path_rounded_rect(const Cairo::RefPtr &cr, double x, double y, double w, double h, double r) { - const double degrees = M_PI / 180.0; - - cr->begin_new_sub_path(); - cr->arc(x + w - r, y + r, r, -M_PI_H, 0); - cr->arc(x + w - r, y + h - r, r, 0, M_PI_H); - cr->arc(x + r, y + h - r, r, M_PI_H, M_PI); - cr->arc(x + r, y + r, r, M_PI, M_PI_3_2); - cr->close_path(); -} - void CellRendererChannels::unread_render_mentions(const Cairo::RefPtr &cr, Gtk::Widget &widget, int mentions, int edge, const Gdk::Rectangle &cell_area) { Pango::FontDescription font; font.set_family("sans 14"); @@ -863,7 +854,7 @@ void CellRendererChannels::unread_render_mentions(const Cairo::RefPtrset_source_rgb(bg.get_red(), bg.get_green(), bg.get_blue()); cr->fill(); cr->set_source_rgb(text.get_red(), text.get_green(), text.get_blue()); diff --git a/src/components/channellist/cellrendererchannels.hpp b/src/components/channellist/cellrendererchannels.hpp index e142b2a..a313dc7 100644 --- a/src/components/channellist/cellrendererchannels.hpp +++ b/src/components/channellist/cellrendererchannels.hpp @@ -153,7 +153,6 @@ protected: const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags); - static void cairo_path_rounded_rect(const Cairo::RefPtr &cr, double x, double y, double w, double h, double r); static void unread_render_mentions(const Cairo::RefPtr &cr, Gtk::Widget &widget, int mentions, int edge, const Gdk::Rectangle &cell_area); private: diff --git a/src/components/channellist/classic/guildlist.cpp b/src/components/channellist/classic/guildlist.cpp index 6a6e3d4..17cd79a 100644 --- a/src/components/channellist/classic/guildlist.cpp +++ b/src/components/channellist/classic/guildlist.cpp @@ -3,6 +3,7 @@ #include "abaddon.hpp" #include "util.hpp" #include "guildlistfolderitem.hpp" +#include "mentionoverlay.hpp" class GuildListDMsButton : public Gtk::EventBox { public: @@ -93,10 +94,19 @@ void GuildList::UpdateListing() { } } +static Gtk::Widget *AddMentionOverlay(Gtk::Widget *widget, Snowflake guild_id) { + auto *overlay = Gtk::make_managed(); + overlay->add(*widget); + auto *mention_overlay = Gtk::make_managed(guild_id); + overlay->add_overlay(*mention_overlay); + overlay->show_all(); + return overlay; +} + void GuildList::AddGuild(Snowflake id) { if (auto item = CreateGuildWidget(id)) { item->show(); - add(*item); + add(*AddMentionOverlay(item, id)); } } @@ -132,7 +142,7 @@ void GuildList::AddFolder(const UserSettingsGuildFoldersEntry &folder) { for (const auto guild_id : folder.GuildIDs) { if (auto *guild_widget = CreateGuildWidget(guild_id)) { guild_widget->show(); - folder_widget->AddGuildWidget(guild_widget); + folder_widget->AddGuildWidget(AddMentionOverlay(guild_widget, guild_id)); } } diff --git a/src/components/channellist/classic/guildlistfolderitem.cpp b/src/components/channellist/classic/guildlistfolderitem.cpp index e062d42..337d4b3 100644 --- a/src/components/channellist/classic/guildlistfolderitem.cpp +++ b/src/components/channellist/classic/guildlistfolderitem.cpp @@ -95,7 +95,7 @@ GuildListFolderItem::GuildListFolderItem(const UserSettingsGuildFoldersEntry &fo CheckUnreadStatus(); } -void GuildListFolderItem::AddGuildWidget(GuildListGuildItem *widget) { +void GuildListFolderItem::AddGuildWidget(Gtk::Widget *widget) { m_box.add(*widget); } diff --git a/src/components/channellist/classic/guildlistfolderitem.hpp b/src/components/channellist/classic/guildlistfolderitem.hpp index e5772c0..06d05f1 100644 --- a/src/components/channellist/classic/guildlistfolderitem.hpp +++ b/src/components/channellist/classic/guildlistfolderitem.hpp @@ -24,7 +24,7 @@ class GuildListFolderItem : public Gtk::VBox { public: GuildListFolderItem(const UserSettingsGuildFoldersEntry &folder); - void AddGuildWidget(GuildListGuildItem *widget); + void AddGuildWidget(Gtk::Widget *widget); private: void OnMessageCreate(const Message &msg); diff --git a/src/components/channellist/classic/mentionoverlay.cpp b/src/components/channellist/classic/mentionoverlay.cpp new file mode 100644 index 0000000..c734ced --- /dev/null +++ b/src/components/channellist/classic/mentionoverlay.cpp @@ -0,0 +1,62 @@ +#include "mentionoverlay.hpp" + +#include "misc/cairo.hpp" + +#include "abaddon.hpp" + +MentionOverlay::MentionOverlay(Snowflake guild_id) + : m_guild_id(guild_id) { + m_font.set_family("sans 14"); + m_layout = create_pango_layout("12"); + m_layout->set_font_description(m_font); + m_layout->set_alignment(Pango::ALIGN_RIGHT); + + get_style_context()->add_class("classic-mention-overlay"); // fuck you + + set_hexpand(false); + set_vexpand(false); + + signal_draw().connect(sigc::mem_fun(*this, &MentionOverlay::OnDraw)); + + Abaddon::Get().GetDiscordClient().signal_message_ack().connect([this](const MessageAckData &data) { + // fetching and checking guild id is probably more expensive than just forcing a redraw anyways + queue_draw(); + }); + + Abaddon::Get().GetDiscordClient().signal_message_create().connect([this](const Message &msg) { + if (msg.GuildID.has_value() && *msg.GuildID != m_guild_id) return; + if (!msg.DoesMentionEveryone && msg.Mentions.empty() && msg.MentionRoles.empty()) return; + queue_draw(); + }); +} + +bool MentionOverlay::OnDraw(const Cairo::RefPtr &cr) { + int mentions; + Abaddon::Get().GetDiscordClient().GetUnreadStateForGuild(m_guild_id, mentions); + if (mentions == 0) return true; + m_layout->set_text(std::to_string(mentions)); + + const int width = get_allocated_width(); + const int height = get_allocated_height(); + + int lw, lh; + m_layout->get_pixel_size(lw, lh); + { + static const auto badge_setting = Gdk::RGBA(Abaddon::Get().GetSettings().MentionBadgeColor); + static const auto text_setting = Gdk::RGBA(Abaddon::Get().GetSettings().MentionBadgeTextColor); + + auto bg = badge_setting.get_alpha_u() > 0 ? badge_setting : get_style_context()->get_background_color(Gtk::STATE_FLAG_SELECTED); + auto text = text_setting.get_alpha_u() > 0 ? text_setting : get_style_context()->get_color(Gtk::STATE_FLAG_SELECTED); + + const auto x = width - lw - 5; + const auto y = height - lh - 1; + CairoUtil::PathRoundedRect(cr, x - 4, y + 2, lw + 8, lh, 5); + cr->set_source_rgb(bg.get_red(), bg.get_green(), bg.get_blue()); + cr->fill(); + cr->set_source_rgb(text.get_red(), text.get_green(), text.get_blue()); + cr->move_to(x, y); + m_layout->show_in_cairo_context(cr); + } + + return true; +} diff --git a/src/components/channellist/classic/mentionoverlay.hpp b/src/components/channellist/classic/mentionoverlay.hpp new file mode 100644 index 0000000..24eb7e2 --- /dev/null +++ b/src/components/channellist/classic/mentionoverlay.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +#include "discord/snowflake.hpp" + +class MentionOverlay : public Gtk::DrawingArea { +public: + MentionOverlay(Snowflake guild_id); + +private: + bool OnDraw(const Cairo::RefPtr &cr); + + Snowflake m_guild_id; + + Pango::FontDescription m_font; + Glib::RefPtr m_layout; +}; diff --git a/src/misc/cairo.cpp b/src/misc/cairo.cpp new file mode 100644 index 0000000..1272f75 --- /dev/null +++ b/src/misc/cairo.cpp @@ -0,0 +1,17 @@ +#include "cairo.hpp" + +#include + +constexpr static double M_PI_H = M_PI / 2.0; +constexpr static double M_PI_3_2 = M_PI * 3.0 / 2.0; + +void CairoUtil::PathRoundedRect(const Cairo::RefPtr &cr, double x, double y, double w, double h, double r) { + const double degrees = M_PI / 180.0; + + cr->begin_new_sub_path(); + cr->arc(x + w - r, y + r, r, -M_PI_H, 0); + cr->arc(x + w - r, y + h - r, r, 0, M_PI_H); + cr->arc(x + r, y + h - r, r, M_PI_H, M_PI); + cr->arc(x + r, y + r, r, M_PI, M_PI_3_2); + cr->close_path(); +} \ No newline at end of file diff --git a/src/misc/cairo.hpp b/src/misc/cairo.hpp new file mode 100644 index 0000000..b66fa34 --- /dev/null +++ b/src/misc/cairo.hpp @@ -0,0 +1,5 @@ +#pragma once + +namespace CairoUtil { +void PathRoundedRect(const Cairo::RefPtr &cr, double x, double y, double w, double h, double r); +} // namespace CairoUtil From ead06ca864714e6804344da37da2f74230bfa39b Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 21 May 2024 02:12:28 -0400 Subject: [PATCH 06/25] fix cringe --- src/components/channellist/channellisttree.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/channellist/channellisttree.cpp b/src/components/channellist/channellisttree.cpp index 3b11485..ebbed58 100644 --- a/src/components/channellist/channellisttree.cpp +++ b/src/components/channellist/channellisttree.cpp @@ -535,7 +535,11 @@ void ChannelListTree::UpdateCreateChannel(const ChannelData &channel) { auto iter = GetIteratorForGuildFromID(*channel.GuildID); channel_row = *m_model->append(iter->children()); } +#ifdef WITH_VOICE channel_row[m_columns.m_type] = IsTextChannel(channel.Type) ? RenderType::TextChannel : RenderType::VoiceChannel; +#else + channel_row[m_columns.m_type] = RenderType::TextChannel; +#endif channel_row[m_columns.m_id] = channel.ID; channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name); channel_row[m_columns.m_nsfw] = channel.NSFW(); From 23621a50e6e8fd3b4fdceae2395a100970b4a20b Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 21 May 2024 02:15:45 -0400 Subject: [PATCH 07/25] update css --- res/css/main.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/res/css/main.css b/res/css/main.css index db548ac..65d6eeb 100644 --- a/res/css/main.css +++ b/res/css/main.css @@ -157,6 +157,11 @@ min-height: 0px; } +.classic-mention-overlay:selected { + color: @theme_selected_color; + background-color: @theme_selected_bg_color; +} + .channel-list .view:selected { background-color: @theme_selected_bg_color; } @@ -176,6 +181,10 @@ background: radial-gradient(7px circle at left, @theme_selected_bg_color 50%, transparent 20%); } +.classic-guild-list-folder.has-unread stack { + background: radial-gradient(7px circle at left, @theme_selected_bg_color 50%, transparent 20%); +} + .classic-guild-list-guild box, .classic-guild-list-folder stack { padding-left: 10px; } From bf29c44d9fa7bbc11fd68824c2468d4946ea29a6 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 21 May 2024 14:43:16 -0400 Subject: [PATCH 08/25] mention overlay passthrough --- src/components/channellist/classic/guildlist.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/channellist/classic/guildlist.cpp b/src/components/channellist/classic/guildlist.cpp index 17cd79a..6bee484 100644 --- a/src/components/channellist/classic/guildlist.cpp +++ b/src/components/channellist/classic/guildlist.cpp @@ -99,6 +99,10 @@ static Gtk::Widget *AddMentionOverlay(Gtk::Widget *widget, Snowflake guild_id) { overlay->add(*widget); auto *mention_overlay = Gtk::make_managed(guild_id); overlay->add_overlay(*mention_overlay); + overlay->set_overlay_pass_through(*mention_overlay, true); + mention_overlay->signal_realize().connect([mention_overlay]() { + mention_overlay->get_window()->set_pass_through(true); + }); overlay->show_all(); return overlay; } From 96687f019e415d830a7ebf57fe7c1372f76ba115 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sat, 25 May 2024 00:09:08 -0400 Subject: [PATCH 09/25] add mention overlay to folders in classic --- .../channellist/classic/guildlist.cpp | 19 +++++++++++-- .../channellist/classic/mentionoverlay.cpp | 27 ++++++++++++++----- .../channellist/classic/mentionoverlay.hpp | 6 ++++- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/components/channellist/classic/guildlist.cpp b/src/components/channellist/classic/guildlist.cpp index 6bee484..fdc15f9 100644 --- a/src/components/channellist/classic/guildlist.cpp +++ b/src/components/channellist/classic/guildlist.cpp @@ -103,7 +103,22 @@ static Gtk::Widget *AddMentionOverlay(Gtk::Widget *widget, Snowflake guild_id) { mention_overlay->signal_realize().connect([mention_overlay]() { mention_overlay->get_window()->set_pass_through(true); }); - overlay->show_all(); + mention_overlay->show(); + overlay->show(); + return overlay; +} + +static Gtk::Widget *AddMentionOverlay(Gtk::Widget *widget, const UserSettingsGuildFoldersEntry &folder) { + auto *overlay = Gtk::make_managed(); + overlay->add(*widget); + auto *mention_overlay = Gtk::make_managed(folder); + overlay->add_overlay(*mention_overlay); + overlay->set_overlay_pass_through(*mention_overlay, true); + mention_overlay->signal_realize().connect([mention_overlay]() { + mention_overlay->get_window()->set_pass_through(true); + }); + mention_overlay->show(); + overlay->show(); return overlay; } @@ -151,7 +166,7 @@ void GuildList::AddFolder(const UserSettingsGuildFoldersEntry &folder) { } folder_widget->show(); - add(*folder_widget); + add(*AddMentionOverlay(folder_widget, folder)); } void GuildList::Clear() { diff --git a/src/components/channellist/classic/mentionoverlay.cpp b/src/components/channellist/classic/mentionoverlay.cpp index c734ced..9fdd694 100644 --- a/src/components/channellist/classic/mentionoverlay.cpp +++ b/src/components/channellist/classic/mentionoverlay.cpp @@ -5,7 +5,16 @@ #include "abaddon.hpp" MentionOverlay::MentionOverlay(Snowflake guild_id) - : m_guild_id(guild_id) { + : m_guild_ids({ guild_id }) { + Init(); +} + +MentionOverlay::MentionOverlay(const UserSettingsGuildFoldersEntry &folder) + : m_guild_ids({ folder.GuildIDs.begin(), folder.GuildIDs.end() }) { + Init(); +} + +void MentionOverlay::Init() { m_font.set_family("sans 14"); m_layout = create_pango_layout("12"); m_layout->set_font_description(m_font); @@ -24,20 +33,24 @@ MentionOverlay::MentionOverlay(Snowflake guild_id) }); Abaddon::Get().GetDiscordClient().signal_message_create().connect([this](const Message &msg) { - if (msg.GuildID.has_value() && *msg.GuildID != m_guild_id) return; + if (msg.GuildID.has_value() && m_guild_ids.find(*msg.GuildID) == m_guild_ids.end()) return; if (!msg.DoesMentionEveryone && msg.Mentions.empty() && msg.MentionRoles.empty()) return; queue_draw(); }); } bool MentionOverlay::OnDraw(const Cairo::RefPtr &cr) { - int mentions; - Abaddon::Get().GetDiscordClient().GetUnreadStateForGuild(m_guild_id, mentions); - if (mentions == 0) return true; - m_layout->set_text(std::to_string(mentions)); + int total_mentions = 0; + for (auto guild_id : m_guild_ids) { + int mentions; + Abaddon::Get().GetDiscordClient().GetUnreadStateForGuild(guild_id, mentions); + total_mentions += mentions; + } + if (total_mentions == 0) return true; + m_layout->set_text(std::to_string(total_mentions)); const int width = get_allocated_width(); - const int height = get_allocated_height(); + const int height = std::min(get_allocated_height(), 48); // cope int lw, lh; m_layout->get_pixel_size(lw, lh); diff --git a/src/components/channellist/classic/mentionoverlay.hpp b/src/components/channellist/classic/mentionoverlay.hpp index 24eb7e2..ceb4f01 100644 --- a/src/components/channellist/classic/mentionoverlay.hpp +++ b/src/components/channellist/classic/mentionoverlay.hpp @@ -4,15 +4,19 @@ #include #include "discord/snowflake.hpp" +#include "discord/usersettings.hpp" class MentionOverlay : public Gtk::DrawingArea { public: MentionOverlay(Snowflake guild_id); + MentionOverlay(const UserSettingsGuildFoldersEntry &folder); private: + void Init(); + bool OnDraw(const Cairo::RefPtr &cr); - Snowflake m_guild_id; + std::set m_guild_ids; Pango::FontDescription m_font; Glib::RefPtr m_layout; From 8215a8d39f7daf0df84f2ec3c113a79a166990dc Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sat, 1 Jun 2024 02:12:46 -0400 Subject: [PATCH 10/25] add disconnect button to voice window as Per Special Request --- src/windows/voicewindow.cpp | 6 ++++++ src/windows/voicewindow.hpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index 18f4a41..1e00f90 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -91,6 +91,7 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) , m_deafen("Deafen") , m_noise_suppression("Suppress Noise") , m_mix_mono("Mix Mono") + , m_disconnect("Disconnect") , m_channel_id(channel_id) , m_menu_view("View") , m_menu_view_settings("More _Settings", true) { @@ -185,6 +186,10 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) Abaddon::Get().GetAudio().SetMixMono(m_mix_mono.get_active()); }); + m_disconnect.signal_clicked().connect([this]() { + Abaddon::Get().GetDiscordClient().DisconnectFromVoice(); + }); + auto *playback_renderer = Gtk::make_managed(); m_playback_combo.set_valign(Gtk::ALIGN_END); m_playback_combo.set_hexpand(true); @@ -253,6 +258,7 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) m_controls.add(m_deafen); m_controls.add(m_noise_suppression); m_controls.add(m_mix_mono); + m_controls.pack_end(m_disconnect, false, true); m_main.pack_start(m_menu_bar, false, true); m_main.pack_start(m_controls, false, true); m_main.pack_start(m_vad_value, false, true); diff --git a/src/windows/voicewindow.hpp b/src/windows/voicewindow.hpp index 018934b..fb64010 100644 --- a/src/windows/voicewindow.hpp +++ b/src/windows/voicewindow.hpp @@ -56,6 +56,8 @@ private: Gtk::CheckButton m_noise_suppression; Gtk::CheckButton m_mix_mono; + Gtk::Button m_disconnect; + Gtk::ComboBoxText m_vad_combo; Gtk::ComboBox m_playback_combo; Gtk::ComboBox m_capture_combo; From 8ab9828f6fc2d82f1b33645a6c92963b382dda9a Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sat, 1 Jun 2024 02:17:08 -0400 Subject: [PATCH 11/25] bump voice window height as Per Special Request --- src/windows/voicewindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/windows/voicewindow.cpp b/src/windows/voicewindow.cpp index 1e00f90..a005e79 100644 --- a/src/windows/voicewindow.cpp +++ b/src/windows/voicewindow.cpp @@ -97,7 +97,7 @@ VoiceWindow::VoiceWindow(Snowflake channel_id) , m_menu_view_settings("More _Settings", true) { get_style_context()->add_class("app-window"); - set_default_size(300, 300); + set_default_size(300, 400); auto &discord = Abaddon::Get().GetDiscordClient(); auto &audio = Abaddon::Get().GetAudio(); From b677db90483610848e7f6789893ed3db8b226328 Mon Sep 17 00:00:00 2001 From: chris <62446202+5xp@users.noreply.github.com> Date: Sat, 1 Jun 2024 15:46:42 -0500 Subject: [PATCH 12/25] Correct default setting for hideconsole in README (#303) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c2fab19..b1d1a35 100644 --- a/README.md +++ b/README.md @@ -347,7 +347,7 @@ For example, memory_db would be set by adding `memory_db = true` under the line | Setting | Type | Default | Description | |---------------|---------|---------|-------------------------| -| `hideconsole` | boolean | true | Hide console on startup | +| `hideconsole` | boolean | false | Hide console on startup | ### Environment variables From f8e7ea3ca93d919db744b9e30113fe8f5907761e Mon Sep 17 00:00:00 2001 From: Skeevert <45735359+Skeevert@users.noreply.github.com> Date: Mon, 3 Jun 2024 03:10:40 +0300 Subject: [PATCH 13/25] Refactoring: changed user flag enum to enum class (#299) --- src/discord/user.cpp | 60 +++++++++++++++++------------------ src/discord/user.hpp | 3 +- src/windows/profilewindow.cpp | 5 +-- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/discord/user.cpp b/src/discord/user.cpp index 8129273..a5bb0ae 100644 --- a/src/discord/user.cpp +++ b/src/discord/user.cpp @@ -220,34 +220,34 @@ void UserData::update_from_json(const nlohmann::json &j) { } const char *UserData::GetFlagName(uint64_t flag) { - switch (flag) { - case DiscordEmployee: + switch (static_cast(flag)) { + case UserData::EFlags::DiscordEmployee: return "discordstaff"; - case PartneredServerOwner: + case UserData::EFlags::PartneredServerOwner: return "partneredowner"; - case HypeSquadEvents: + case UserData::EFlags::HypeSquadEvents: return "hypesquadevents"; - case BugHunterLevel1: + case UserData::EFlags::BugHunterLevel1: return "discordbughunter"; - case HouseBravery: + case UserData::EFlags::HouseBravery: return "hypesquadbravery"; - case HouseBrilliance: + case UserData::EFlags::HouseBrilliance: return "hypesquadbrilliance"; - case HouseBalance: + case UserData::EFlags::HouseBalance: return "hypesquadbalance"; - case EarlySupporter: + case UserData::EFlags::EarlySupporter: return "earlysupporter"; - case TeamUser: + case UserData::EFlags::TeamUser: return "teamuser"; - case System: + case UserData::EFlags::System: return "system"; - case BugHunterLevel2: + case UserData::EFlags::BugHunterLevel2: return "discordbughunter2"; - case VerifiedBot: + case UserData::EFlags::VerifiedBot: return "verifiedbot"; - case EarlyVerifiedBotDeveloper: + case UserData::EFlags::EarlyVerifiedBotDeveloper: return "earlyverifiedbotdeveloper"; - case CertifiedModerator: + case UserData::EFlags::CertifiedModerator: return "certifiedmoderator"; default: return "unknown"; @@ -255,34 +255,34 @@ const char *UserData::GetFlagName(uint64_t flag) { } const char *UserData::GetFlagReadableName(uint64_t flag) { - switch (flag) { - case DiscordEmployee: + switch (static_cast(flag)) { + case UserData::EFlags::DiscordEmployee: return "Discord Staff"; - case PartneredServerOwner: + case UserData::EFlags::PartneredServerOwner: return "Partnered Server Owner"; - case HypeSquadEvents: + case UserData::EFlags::HypeSquadEvents: return "HypeSquad Events"; - case BugHunterLevel1: + case UserData::EFlags::BugHunterLevel1: return "Discord Bug Hunter"; - case HouseBravery: + case UserData::EFlags::HouseBravery: return "HypeSquad Bravery"; - case HouseBrilliance: + case UserData::EFlags::HouseBrilliance: return "HypeSquad Brilliance"; - case HouseBalance: + case UserData::EFlags::HouseBalance: return "HypeSquad Balance"; - case EarlySupporter: + case UserData::EFlags::EarlySupporter: return "Early Supporter"; - case TeamUser: + case UserData::EFlags::TeamUser: return "Team User"; // ??? - case System: + case UserData::EFlags::System: return "System"; - case BugHunterLevel2: + case UserData::EFlags::BugHunterLevel2: return "Discord Bug Hunter Level 2"; - case VerifiedBot: + case UserData::EFlags::VerifiedBot: return "Verified Bot"; - case EarlyVerifiedBotDeveloper: + case UserData::EFlags::EarlyVerifiedBotDeveloper: return "Early Verified Bot Developer"; - case CertifiedModerator: + case UserData::EFlags::CertifiedModerator: return "Discord Certified Moderator"; default: return ""; diff --git a/src/discord/user.hpp b/src/discord/user.hpp index 3e356a4..6aee6be 100644 --- a/src/discord/user.hpp +++ b/src/discord/user.hpp @@ -11,8 +11,7 @@ enum class EPremiumType { }; struct UserData { - // todo: enum class? (for consistencys sake) - enum { + enum class EFlags : uint64_t { DiscordEmployee = 1 << 0, PartneredServerOwner = 1 << 1, HypeSquadEvents = 1 << 2, diff --git a/src/windows/profilewindow.cpp b/src/windows/profilewindow.cpp index 8c4b67f..4547ae4 100644 --- a/src/windows/profilewindow.cpp +++ b/src/windows/profilewindow.cpp @@ -1,6 +1,7 @@ #include "profilewindow.hpp" #include "abaddon.hpp" +#include "discord/user.hpp" #include "util.hpp" ProfileWindow::ProfileWindow(Snowflake user_id) @@ -116,13 +117,13 @@ void ProfileWindow::OnFetchProfile(const UserProfileData &data) { if (!data.User.PublicFlags.has_value()) return; const auto x = *data.User.PublicFlags; - for (uint64_t i = 1; i <= UserData::MaxFlag; i <<= 1) { + for (uint64_t i = 1; i <= static_cast(UserData::EFlags::MaxFlag); i <<= 1) { if (!(x & i)) continue; const std::string name = UserData::GetFlagName(i); if (name == "unknown") continue; Glib::RefPtr pixbuf; try { - if (name == "verifiedbot") + if (i == static_cast(UserData::EFlags::VerifiedBot)) pixbuf = Gdk::Pixbuf::create_from_file(Abaddon::GetResPath("/checkmark.png"), 24, 24); else pixbuf = Gdk::Pixbuf::create_from_file(Abaddon::GetResPath("/" + name + ".png"), 24, 24); From 5b9d10a897f0e61f85ca4b2b70e95591a27eb81e Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Sun, 2 Jun 2024 20:32:26 -0400 Subject: [PATCH 14/25] fix linking curl maybe somehow i guess --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 99cc9ef..526c8c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,7 +68,7 @@ endif () if (NOT (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")) target_precompile_headers(abaddon PRIVATE src/abaddon.hpp src/util.hpp) -endif() +endif () if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND @@ -115,11 +115,12 @@ target_link_libraries(abaddon spdlog::spdlog) target_link_libraries(abaddon ${SQLite3_LIBRARIES}) target_link_libraries(abaddon ${GTKMM_LIBRARIES}) -target_link_libraries(abaddon ${CURL_LIBRARIES}) target_link_libraries(abaddon ${ZLIB_LIBRARY}) target_link_libraries(abaddon ${NLOHMANN_JSON_LIBRARIES}) target_link_libraries(abaddon ${CMAKE_DL_LIBS}) +target_link_libraries(abaddon CURL::libcurl) + include(CheckAtomic) if (NOT HAVE_CXX_ATOMICS_WITHOUT_LIB OR NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) target_link_libraries(abaddon atomic) From 25ecbce043cc4644d8cce559eba2931ed3df9826 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Tue, 4 Jun 2024 21:36:55 -0400 Subject: [PATCH 15/25] ignore unread state from undisplayed channel types --- src/discord/discord.cpp | 18 ++++++++++++++++-- src/discord/discord.hpp | 2 ++ src/discord/store.cpp | 12 ++++++------ src/discord/store.hpp | 2 +- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index 385d6b7..f955f45 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -351,7 +351,9 @@ void DiscordClient::GetArchivedPrivateThreads(Snowflake channel_id, const sigc:: } std::vector DiscordClient::GetChildChannelIDs(Snowflake parent_id) const { - return m_store.GetChannelIDsWithParentID(parent_id); + std::vector ids; + for (auto [id, type] : m_store.GetChannelIDsWithParentID(parent_id)) ids.push_back(id); + return ids; } std::optional DiscordClient::GetWebhookMessageData(Snowflake message_id) const { @@ -1371,7 +1373,8 @@ int DiscordClient::GetUnreadStateForChannel(Snowflake id) const noexcept { int DiscordClient::GetUnreadChannelsCountForCategory(Snowflake id) const noexcept { int result = 0; - for (Snowflake channel_id : m_store.GetChannelIDsWithParentID(id)) { + for (auto [channel_id, channel_type] : m_store.GetChannelIDsWithParentID(id)) { + if (!ShouldChannelTypeCountInUnread(channel_type)) continue; if (IsChannelMuted(channel_id)) continue; const auto iter = m_unread.find(channel_id); if (iter == m_unread.end()) continue; @@ -1393,6 +1396,9 @@ bool DiscordClient::GetUnreadStateForGuild(Snowflake id, int &total_mentions) co if (const auto iter = m_channel_muted_parent.find(channel_id); iter != m_channel_muted_parent.end()) continue; + const auto channel = GetChannel(channel_id); + if (channel.has_value() && !ShouldChannelTypeCountInUnread(channel->Type)) continue; + if (!has_any_unread && channel_unread > -1 && !IsChannelMuted(channel_id)) has_any_unread = true; } @@ -2753,6 +2759,14 @@ bool DiscordClient::CheckCode(const http::response_type &r, int expected) { return true; } +bool DiscordClient::ShouldChannelTypeCountInUnread(ChannelType type) { + return type != ChannelType::GUILD_VOICE && + type != ChannelType::GUILD_FORUM && + type != ChannelType::GUILD_MEDIA && + type != ChannelType::GUILD_STORE && + type != ChannelType::GUILD_DIRECTORY; +} + void DiscordClient::StoreMessageData(Message &msg) { const auto chan = m_store.GetChannel(msg.ChannelID); if (chan.has_value() && chan->GuildID.has_value()) diff --git a/src/discord/discord.hpp b/src/discord/discord.hpp index 9c2c080..6b2853b 100644 --- a/src/discord/discord.hpp +++ b/src/discord/discord.hpp @@ -321,6 +321,8 @@ private: void StoreMessageData(Message &msg); + static bool ShouldChannelTypeCountInUnread(ChannelType type); + void HandleReadyReadState(const ReadyEventData &data); void HandleReadyGuildSettings(const ReadyEventData &data); diff --git a/src/discord/store.cpp b/src/discord/store.cpp index bf630aa..4de5d63 100644 --- a/src/discord/store.cpp +++ b/src/discord/store.cpp @@ -638,16 +638,16 @@ std::vector Store::GetActiveThreads(Snowflake channel_id) const { return ret; } -std::vector Store::GetChannelIDsWithParentID(Snowflake channel_id) const { +std::vector> Store::GetChannelIDsWithParentID(Snowflake channel_id) const { auto &s = m_stmt_get_chan_ids_parent; s->Bind(1, channel_id); - std::vector ret; + std::vector> ret; while (s->FetchOne()) { - Snowflake x; - s->Get(0, x); - ret.push_back(x); + auto &p = ret.emplace_back(); + s->Get(0, p.first); + s->Get(1, p.second); } s->Reset(); @@ -2315,7 +2315,7 @@ bool Store::CreateStatements() { } m_stmt_get_chan_ids_parent = std::make_unique(m_db, R"( - SELECT id FROM channels WHERE parent_id = ? + SELECT id, type 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()); diff --git a/src/discord/store.hpp b/src/discord/store.hpp index 6157f09..e53d5c7 100644 --- a/src/discord/store.hpp +++ b/src/discord/store.hpp @@ -50,7 +50,7 @@ public: std::vector GetMessagesBefore(Snowflake channel_id, Snowflake message_id, size_t limit) const; std::vector GetPinnedMessages(Snowflake channel_id) const; std::vector GetActiveThreads(Snowflake channel_id) const; // public - std::vector GetChannelIDsWithParentID(Snowflake channel_id) const; + std::vector> GetChannelIDsWithParentID(Snowflake channel_id) const; std::unordered_set GetMembersInGuild(Snowflake guild_id) const; // ^ not the same as GetUsersInGuild since users in a guild may include users who do not have retrieved member data From 28f56725c30113eb0aab6ce3709675f512df5a48 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Fri, 7 Jun 2024 00:27:44 -0400 Subject: [PATCH 16/25] add new dll (fixes #307) --- ci/msys-deps.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/msys-deps.txt b/ci/msys-deps.txt index d37418b..56fc676 100644 --- a/ci/msys-deps.txt +++ b/ci/msys-deps.txt @@ -40,6 +40,7 @@ /bin/libjpeg-8.dll /bin/liblzma-5.dll /bin/libnghttp2-14.dll +/bin/libnghttp3-9.dll /bin/libopus-0.dll /bin/libpango-1.0-0.dll /bin/libpangocairo-1.0-0.dll From e6b4871df3c0642d6feaf5fea4626973653bf36c Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Wed, 12 Jun 2024 22:00:02 -0400 Subject: [PATCH 17/25] build number shenanigans --- src/startup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/startup.cpp b/src/startup.cpp index 4939c2f..f2ed5ce 100644 --- a/src/startup.cpp +++ b/src/startup.cpp @@ -46,8 +46,8 @@ std::optional GetJavascriptFileFromAppPage(const Glib::ustring &c start_position += str.size(); } - if (matches.size() >= 7) { - return matches[matches.size() - 7]; + if (matches.size() >= 8) { + return matches[matches.size() - 8]; } return {}; From bc7c5f9ec3f1f19517a556a4c4f9e830ca191c32 Mon Sep 17 00:00:00 2001 From: pastalian <28638872+pastalian@users.noreply.github.com> Date: Sun, 16 Jun 2024 05:47:48 +0900 Subject: [PATCH 18/25] Explicitly include headers for PCH free build (#312) There are some headers that implicitly included by PCH. Include those explicitly so PCH free build succeeds. --- src/components/channellist/classic/guildlist.cpp | 2 ++ src/components/channellist/classic/mentionoverlay.hpp | 2 ++ src/misc/cairo.cpp | 2 -- src/misc/cairo.hpp | 2 ++ src/platform.cpp | 3 +++ 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/channellist/classic/guildlist.cpp b/src/components/channellist/classic/guildlist.cpp index fdc15f9..11a6775 100644 --- a/src/components/channellist/classic/guildlist.cpp +++ b/src/components/channellist/classic/guildlist.cpp @@ -1,3 +1,5 @@ +#include + #include "guildlist.hpp" #include "abaddon.hpp" diff --git a/src/components/channellist/classic/mentionoverlay.hpp b/src/components/channellist/classic/mentionoverlay.hpp index ceb4f01..7c168c2 100644 --- a/src/components/channellist/classic/mentionoverlay.hpp +++ b/src/components/channellist/classic/mentionoverlay.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include diff --git a/src/misc/cairo.cpp b/src/misc/cairo.cpp index 1272f75..a1c6220 100644 --- a/src/misc/cairo.cpp +++ b/src/misc/cairo.cpp @@ -1,7 +1,5 @@ #include "cairo.hpp" -#include - constexpr static double M_PI_H = M_PI / 2.0; constexpr static double M_PI_3_2 = M_PI * 3.0 / 2.0; diff --git a/src/misc/cairo.hpp b/src/misc/cairo.hpp index b66fa34..37c71d6 100644 --- a/src/misc/cairo.hpp +++ b/src/misc/cairo.hpp @@ -1,5 +1,7 @@ #pragma once +#include + namespace CairoUtil { void PathRoundedRect(const Cairo::RefPtr &cr, double x, double y, double w, double h, double r); } // namespace CairoUtil diff --git a/src/platform.cpp b/src/platform.cpp index ce0ac74..726655b 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -7,6 +7,9 @@ #ifdef __APPLE__ #include #endif +#ifdef __linux__ + #include "util.hpp" +#endif #include From f8de54e47eadc40fad4027a34902476527f48a5c Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Mon, 17 Jun 2024 03:29:03 -0400 Subject: [PATCH 19/25] add open chat to voice channels --- src/components/channellist/channellisttree.cpp | 14 ++++++++++++-- src/components/channellist/channellisttree.hpp | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/components/channellist/channellisttree.cpp b/src/components/channellist/channellisttree.cpp index ebbed58..e5bc06e 100644 --- a/src/components/channellist/channellisttree.cpp +++ b/src/components/channellist/channellisttree.cpp @@ -29,6 +29,7 @@ ChannelListTree::ChannelListTree() #ifdef WITH_VOICE , m_menu_voice_channel_join("_Join", true) , m_menu_voice_channel_disconnect("_Disconnect", true) + , m_menu_voice_open_chat("Open _Chat", true) #endif , m_menu_dm_copy_id("_Copy ID", true) , m_menu_dm_close("") // changes depending on if group or not @@ -209,8 +210,14 @@ ChannelListTree::ChannelListTree() m_signal_action_disconnect_voice.emit(); }); + m_menu_voice_open_chat.signal_activate().connect([this]() { + const auto id = static_cast((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]); + m_signal_action_channel_item_select.emit(id); + }); + m_menu_voice_channel.append(m_menu_voice_channel_join); m_menu_voice_channel.append(m_menu_voice_channel_disconnect); + m_menu_voice_channel.append(m_menu_voice_open_chat); m_menu_voice_channel.show_all(); #endif @@ -1172,8 +1179,11 @@ bool ChannelListTree::SelectionFunc(const Glib::RefPtr &model, c } } - auto type = (*model->get_iter(path))[m_columns.m_type]; - return type == RenderType::TextChannel || type == RenderType::DM || type == RenderType::Thread; + const auto type = (*model->get_iter(path))[m_columns.m_type]; + const auto id = static_cast((*model->get_iter(path))[m_columns.m_id]); + // todo maybe just keep this last check? + if (type == RenderType::TextChannel || type == RenderType::DM || type == RenderType::Thread || (id == m_active_channel)) return true; + return is_currently_selected; } void ChannelListTree::AddPrivateChannels() { diff --git a/src/components/channellist/channellisttree.hpp b/src/components/channellist/channellisttree.hpp index 4eebbdb..17acb46 100644 --- a/src/components/channellist/channellisttree.hpp +++ b/src/components/channellist/channellisttree.hpp @@ -166,6 +166,7 @@ protected: Gtk::Menu m_menu_voice_channel; Gtk::MenuItem m_menu_voice_channel_join; Gtk::MenuItem m_menu_voice_channel_disconnect; + Gtk::MenuItem m_menu_voice_open_chat; #endif Gtk::Menu m_menu_dm; From eb9ad703be7769958bee959ce2f83f5325ef206b Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Mon, 17 Jun 2024 03:50:50 -0400 Subject: [PATCH 20/25] show voice channels and participants even if compiled without audio --- .../channellist/cellrendererchannels.cpp | 14 ---- .../channellist/cellrendererchannels.hpp | 6 -- .../channellist/channellisttree.cpp | 53 +++---------- .../channellist/channellisttree.hpp | 8 -- src/discord/discord.cpp | 77 ++++++++++--------- src/discord/discord.hpp | 44 ++++++----- 6 files changed, 75 insertions(+), 127 deletions(-) diff --git a/src/components/channellist/cellrendererchannels.cpp b/src/components/channellist/cellrendererchannels.cpp index bb2b9ba..8758a7d 100644 --- a/src/components/channellist/cellrendererchannels.cpp +++ b/src/components/channellist/cellrendererchannels.cpp @@ -122,12 +122,10 @@ void CellRendererChannels::get_preferred_width_vfunc(Gtk::Widget &widget, int &m return get_preferred_width_vfunc_channel(widget, minimum_width, natural_width); case RenderType::Thread: return get_preferred_width_vfunc_thread(widget, minimum_width, natural_width); -#ifdef WITH_VOICE case RenderType::VoiceChannel: return get_preferred_width_vfunc_voice_channel(widget, minimum_width, natural_width); case RenderType::VoiceParticipant: return get_preferred_width_vfunc_voice_participant(widget, minimum_width, natural_width); -#endif case RenderType::DMHeader: return get_preferred_width_vfunc_dmheader(widget, minimum_width, natural_width); case RenderType::DM: @@ -147,12 +145,10 @@ void CellRendererChannels::get_preferred_width_for_height_vfunc(Gtk::Widget &wid return get_preferred_width_for_height_vfunc_channel(widget, height, minimum_width, natural_width); case RenderType::Thread: return get_preferred_width_for_height_vfunc_thread(widget, height, minimum_width, natural_width); -#ifdef WITH_VOICE case RenderType::VoiceChannel: return get_preferred_width_for_height_vfunc_voice_channel(widget, height, minimum_width, natural_width); case RenderType::VoiceParticipant: return get_preferred_width_for_height_vfunc_voice_participant(widget, height, minimum_width, natural_width); -#endif case RenderType::DMHeader: return get_preferred_width_for_height_vfunc_dmheader(widget, height, minimum_width, natural_width); case RenderType::DM: @@ -172,12 +168,10 @@ void CellRendererChannels::get_preferred_height_vfunc(Gtk::Widget &widget, int & return get_preferred_height_vfunc_channel(widget, minimum_height, natural_height); case RenderType::Thread: return get_preferred_height_vfunc_thread(widget, minimum_height, natural_height); -#ifdef WITH_VOICE case RenderType::VoiceChannel: return get_preferred_height_vfunc_voice_channel(widget, minimum_height, natural_height); case RenderType::VoiceParticipant: return get_preferred_height_vfunc_voice_participant(widget, minimum_height, natural_height); -#endif case RenderType::DMHeader: return get_preferred_height_vfunc_dmheader(widget, minimum_height, natural_height); case RenderType::DM: @@ -197,12 +191,10 @@ void CellRendererChannels::get_preferred_height_for_width_vfunc(Gtk::Widget &wid return get_preferred_height_for_width_vfunc_channel(widget, width, minimum_height, natural_height); case RenderType::Thread: return get_preferred_height_for_width_vfunc_thread(widget, width, minimum_height, natural_height); -#ifdef WITH_VOICE case RenderType::VoiceChannel: return get_preferred_height_for_width_vfunc_voice_channel(widget, width, minimum_height, natural_height); case RenderType::VoiceParticipant: return get_preferred_height_for_width_vfunc_voice_participant(widget, width, minimum_height, natural_height); -#endif case RenderType::DMHeader: return get_preferred_height_for_width_vfunc_dmheader(widget, width, minimum_height, natural_height); case RenderType::DM: @@ -222,12 +214,10 @@ void CellRendererChannels::render_vfunc(const Cairo::RefPtr &cr, return render_vfunc_channel(cr, widget, background_area, cell_area, flags); case RenderType::Thread: return render_vfunc_thread(cr, widget, background_area, cell_area, flags); -#ifdef WITH_VOICE case RenderType::VoiceChannel: return render_vfunc_voice_channel(cr, widget, background_area, cell_area, flags); case RenderType::VoiceParticipant: return render_vfunc_voice_participant(cr, widget, background_area, cell_area, flags); -#endif case RenderType::DMHeader: return render_vfunc_dmheader(cr, widget, background_area, cell_area, flags); case RenderType::DM: @@ -563,8 +553,6 @@ void CellRendererChannels::render_vfunc_thread(const Cairo::RefPtr((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]); @@ -219,7 +218,6 @@ ChannelListTree::ChannelListTree() m_menu_voice_channel.append(m_menu_voice_channel_disconnect); m_menu_voice_channel.append(m_menu_voice_open_chat); m_menu_voice_channel.show_all(); -#endif m_menu_dm_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])); @@ -362,10 +360,8 @@ int ChannelListTree::SortFunc(const Gtk::TreeModel::iterator &a, const Gtk::Tree const int64_t b_sort = (*b)[m_columns.m_sort]; if (a_type == RenderType::DMHeader) return -1; if (b_type == RenderType::DMHeader) return 1; -#ifdef WITH_VOICE if (a_type == RenderType::TextChannel && b_type == RenderType::VoiceChannel) return -1; if (b_type == RenderType::TextChannel && a_type == RenderType::VoiceChannel) return 1; -#endif return static_cast(std::clamp(a_sort - b_sort, int64_t(-1), int64_t(1))); } @@ -497,13 +493,9 @@ void ChannelListTree::UpdateChannel(Snowflake id) { auto channel = Abaddon::Get().GetDiscordClient().GetChannel(id); if (!iter || !channel.has_value()) return; if (channel->Type == ChannelType::GUILD_CATEGORY) return UpdateChannelCategory(*channel); - // TODO: theres like 4 different fucking ways of checking if somethin g is text or voice can i fix that How stupid . - // fun fact clang-format is indenting me right now i wonder why ,,,,,,,,,,, -#ifdef WITH_VOICE + // TODO: theres like 4 different fucking ways of checking if somethin g is text or voice can i fix that How stupid . + // fun fact clang-format is indenting me right now i wonder why ,,,,,,,,,,, if (!channel->IsText() && channel->Type != ChannelType::GUILD_VOICE) return; -#else - if (!channel->IsText()) return; -#endif // refresh stuff that might have changed const bool is_orphan_TMP = !channel->ParentID.has_value(); @@ -525,11 +517,7 @@ void ChannelListTree::UpdateChannel(Snowflake id) { void ChannelListTree::UpdateCreateChannel(const ChannelData &channel) { if (channel.Type == ChannelType::GUILD_CATEGORY) return (void)UpdateCreateChannelCategory(channel); if (channel.Type == ChannelType::DM || channel.Type == ChannelType::GROUP_DM) return UpdateCreateDMChannel(channel); -#ifdef WITH_VOICE if (channel.Type != ChannelType::GUILD_TEXT && channel.Type != ChannelType::GUILD_NEWS && channel.Type != ChannelType::GUILD_VOICE) return; -#else - if (channel.Type != ChannelType::GUILD_TEXT && channel.Type != ChannelType::GUILD_NEWS) return; -#endif Gtk::TreeRow channel_row; bool orphan; @@ -542,11 +530,7 @@ void ChannelListTree::UpdateCreateChannel(const ChannelData &channel) { auto iter = GetIteratorForGuildFromID(*channel.GuildID); channel_row = *m_model->append(iter->children()); } -#ifdef WITH_VOICE channel_row[m_columns.m_type] = IsTextChannel(channel.Type) ? RenderType::TextChannel : RenderType::VoiceChannel; -#else - channel_row[m_columns.m_type] = RenderType::TextChannel; -#endif channel_row[m_columns.m_id] = channel.ID; channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name); channel_row[m_columns.m_nsfw] = channel.NSFW(); @@ -642,7 +626,6 @@ void ChannelListTree::OnThreadListSync(const ThreadListSyncData &data) { } } -#ifdef WITH_VOICE void ChannelListTree::OnVoiceUserConnect(Snowflake user_id, Snowflake channel_id) { auto parent_iter = GetIteratorForRowFromIDOfType(channel_id, RenderType::VoiceChannel); if (!parent_iter) parent_iter = GetIteratorForRowFromIDOfType(channel_id, RenderType::DM); @@ -664,7 +647,6 @@ void ChannelListTree::OnVoiceStateSet(Snowflake user_id, Snowflake channel_id, V (*iter)[m_columns.m_voice_flags] = flags; } } -#endif void ChannelListTree::DeleteThreadRow(Snowflake id) { auto iter = GetIteratorForRowFromID(id); @@ -926,11 +908,7 @@ Gtk::TreeModel::iterator ChannelListTree::AddGuild(const GuildData &guild, const for (const auto &channel_ : *guild.Channels) { const auto channel = discord.GetChannel(channel_.ID); if (!channel.has_value()) continue; -#ifdef WITH_VOICE if (channel->Type == ChannelType::GUILD_TEXT || channel->Type == ChannelType::GUILD_NEWS || channel->Type == ChannelType::GUILD_VOICE) { -#else - if (channel->Type == ChannelType::GUILD_TEXT || channel->Type == ChannelType::GUILD_NEWS) { -#endif if (channel->ParentID.has_value()) categories[*channel->ParentID].push_back(*channel); else @@ -957,7 +935,6 @@ Gtk::TreeModel::iterator ChannelListTree::AddGuild(const GuildData &guild, const } }; -#ifdef WITH_VOICE auto add_voice_participants = [this, &discord](const ChannelData &channel, const Gtk::TreeNodeChildren &root) { for (auto user_id : discord.GetUsersInVoiceChannel(channel.ID)) { if (const auto user = discord.GetUser(user_id); user.has_value()) { @@ -965,21 +942,17 @@ Gtk::TreeModel::iterator ChannelListTree::AddGuild(const GuildData &guild, const } } }; -#endif for (const auto &channel : orphan_channels) { auto channel_row = *m_model->append(guild_row.children()); if (IsTextChannel(channel.Type)) { channel_row[m_columns.m_type] = RenderType::TextChannel; channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name); - } -#ifdef WITH_VOICE - else { + } else { channel_row[m_columns.m_type] = RenderType::VoiceChannel; channel_row[m_columns.m_name] = Glib::Markup::escape_text(*channel.Name); add_voice_participants(channel, channel_row->children()); } -#endif channel_row[m_columns.m_id] = channel.ID; channel_row[m_columns.m_sort] = *channel.Position + OrphanChannelSortOffset; channel_row[m_columns.m_nsfw] = channel.NSFW(); @@ -1004,14 +977,11 @@ Gtk::TreeModel::iterator ChannelListTree::AddGuild(const GuildData &guild, const if (IsTextChannel(channel.Type)) { channel_row[m_columns.m_type] = RenderType::TextChannel; channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name); - } -#ifdef WITH_VOICE - else { + } else { channel_row[m_columns.m_type] = RenderType::VoiceChannel; channel_row[m_columns.m_name] = Glib::Markup::escape_text(*channel.Name); add_voice_participants(channel, channel_row->children()); } -#endif channel_row[m_columns.m_id] = channel.ID; channel_row[m_columns.m_sort] = *channel.Position; channel_row[m_columns.m_nsfw] = channel.NSFW(); @@ -1049,7 +1019,6 @@ Gtk::TreeModel::iterator ChannelListTree::CreateThreadRow(const Gtk::TreeNodeChi return thread_iter; } -#ifdef WITH_VOICE Gtk::TreeModel::iterator ChannelListTree::CreateVoiceParticipantRow(const UserData &user, const Gtk::TreeNodeChildren &parent) { auto row = *m_model->append(parent); row[m_columns.m_type] = RenderType::VoiceParticipant; @@ -1071,7 +1040,6 @@ Gtk::TreeModel::iterator ChannelListTree::CreateVoiceParticipantRow(const UserDa return row; } -#endif void ChannelListTree::UpdateChannelCategory(const ChannelData &channel) { auto iter = GetIteratorForRowFromID(channel.ID); @@ -1215,13 +1183,11 @@ void ChannelListTree::AddPrivateChannels() { row[m_columns.m_icon] = img.GetPlaceholder(DMIconSize); row[m_columns.m_expanded] = true; -#ifdef WITH_VOICE for (auto user_id : discord.GetUsersInVoiceChannel(dm_id)) { if (const auto user = discord.GetUser(user_id); user.has_value()) { CreateVoiceParticipantRow(*user, row->children()); } } -#endif SetDMChannelIcon(iter, *dm); } @@ -1352,12 +1318,10 @@ bool ChannelListTree::OnButtonPressEvent(GdkEventButton *ev) { OnChannelSubmenuPopup(); m_menu_channel.popup_at_pointer(reinterpret_cast(ev)); break; -#ifdef WITH_VOICE case RenderType::VoiceChannel: OnVoiceChannelSubmenuPopup(); m_menu_voice_channel.popup_at_pointer(reinterpret_cast(ev)); break; -#endif case RenderType::DM: { OnDMSubmenuPopup(); const auto channel = Abaddon::Get().GetDiscordClient().GetChannel(static_cast(row[m_columns.m_id])); @@ -1450,8 +1414,8 @@ void ChannelListTree::OnChannelSubmenuPopup() { m_menu_channel_toggle_mute.set_label("Mute"); } -#ifdef WITH_VOICE void ChannelListTree::OnVoiceChannelSubmenuPopup() { +#ifdef WITH_VOICE const auto iter = m_model->get_iter(m_path_for_menu); if (!iter) return; const auto id = static_cast((*iter)[m_columns.m_id]); @@ -1463,8 +1427,11 @@ void ChannelListTree::OnVoiceChannelSubmenuPopup() { m_menu_voice_channel_join.set_sensitive(true); m_menu_voice_channel_disconnect.set_sensitive(false); } -} +#else + m_menu_voice_channel_join.set_sensitive(false); + m_menu_voice_channel_disconnect.set_sensitive(false); #endif +} void ChannelListTree::OnDMSubmenuPopup() { auto iter = m_model->get_iter(m_path_for_menu); diff --git a/src/components/channellist/channellisttree.hpp b/src/components/channellist/channellisttree.hpp index 17acb46..abceca9 100644 --- a/src/components/channellist/channellisttree.hpp +++ b/src/components/channellist/channellisttree.hpp @@ -104,10 +104,7 @@ protected: Gtk::TreeModel::iterator AddGuild(const GuildData &guild, const Gtk::TreeNodeChildren &root); Gtk::TreeModel::iterator UpdateCreateChannelCategory(const ChannelData &channel); Gtk::TreeModel::iterator CreateThreadRow(const Gtk::TreeNodeChildren &children, const ChannelData &channel); - -#ifdef WITH_VOICE Gtk::TreeModel::iterator CreateVoiceParticipantRow(const UserData &user, const Gtk::TreeNodeChildren &parent); -#endif void UpdateChannelCategory(const ChannelData &channel); @@ -162,12 +159,10 @@ protected: Gtk::MenuItem m_menu_channel_open_tab; #endif -#ifdef WITH_VOICE Gtk::Menu m_menu_voice_channel; Gtk::MenuItem m_menu_voice_channel_join; Gtk::MenuItem m_menu_voice_channel_disconnect; Gtk::MenuItem m_menu_voice_open_chat; -#endif Gtk::Menu m_menu_dm; Gtk::MenuItem m_menu_dm_copy_id; @@ -195,10 +190,7 @@ protected: void OnChannelSubmenuPopup(); void OnDMSubmenuPopup(); void OnThreadSubmenuPopup(); - -#ifdef WITH_VOICE void OnVoiceChannelSubmenuPopup(); -#endif bool m_updating_listing = false; diff --git a/src/discord/discord.cpp b/src/discord/discord.cpp index f955f45..062a871 100644 --- a/src/discord/discord.cpp +++ b/src/discord/discord.cpp @@ -1284,21 +1284,10 @@ Snowflake DiscordClient::GetVoiceChannelID() const noexcept { return m_voice_channel_id; } -std::unordered_set DiscordClient::GetUsersInVoiceChannel(Snowflake channel_id) { - return m_voice_state_channel_users[channel_id]; -} - std::optional DiscordClient::GetSSRCOfUser(Snowflake id) const { return m_voice.GetSSRCOfUser(id); } -std::optional> DiscordClient::GetVoiceState(Snowflake user_id) const { - if (const auto it = m_voice_states.find(user_id); it != m_voice_states.end()) { - return it->second; - } - return std::nullopt; -} - DiscordVoiceClient &DiscordClient::GetVoiceClient() { return m_voice; } @@ -1314,6 +1303,17 @@ void DiscordClient::SetVoiceDeafened(bool is_deaf) { } #endif +std::optional> DiscordClient::GetVoiceState(Snowflake user_id) const { + if (const auto it = m_voice_states.find(user_id); it != m_voice_states.end()) { + return it->second; + } + return std::nullopt; +} + +std::unordered_set DiscordClient::GetUsersInVoiceChannel(Snowflake channel_id) { + return m_voice_state_channel_users[channel_id]; +} + void DiscordClient::SetReferringChannel(Snowflake id) { if (!id.IsValid()) { m_http.SetPersistentHeader("Referer", "https://discord.com/channels/@me"); @@ -1652,10 +1652,10 @@ void DiscordClient::HandleGatewayMessage(std::string str) { case GatewayEvent::GUILD_MEMBERS_CHUNK: { HandleGatewayGuildMembersChunk(m); } break; -#ifdef WITH_VOICE case GatewayEvent::VOICE_STATE_UPDATE: { HandleGatewayVoiceStateUpdate(m); } break; +#ifdef WITH_VOICE case GatewayEvent::VOICE_SERVER_UPDATE: { HandleGatewayVoiceServerUpdate(m); } break; @@ -2336,12 +2336,6 @@ void DiscordClient::HandleGatewayGuildMembersChunk(const GatewayMessage &msg) { * */ -void DiscordClient::HandleGatewayVoiceStateUpdate(const GatewayMessage &msg) { - spdlog::get("discord")->trace("VOICE_STATE_UPDATE"); - - CheckVoiceState(msg.Data); -} - void DiscordClient::HandleGatewayVoiceServerUpdate(const GatewayMessage &msg) { spdlog::get("discord")->trace("VOICE_SERVER_UPDATE"); @@ -2371,8 +2365,17 @@ void DiscordClient::HandleGatewayCallCreate(const GatewayMessage &msg) { } } +#endif + +void DiscordClient::HandleGatewayVoiceStateUpdate(const GatewayMessage &msg) { + spdlog::get("discord")->trace("VOICE_STATE_UPDATE"); + + CheckVoiceState(msg.Data); +} + void DiscordClient::CheckVoiceState(const VoiceState &data) { if (data.UserID == m_user_data.ID) { +#ifdef WITH_VOICE spdlog::get("discord")->debug("Voice session ID: {}", data.SessionID); m_voice.SetSessionID(data.SessionID); @@ -2383,6 +2386,7 @@ void DiscordClient::CheckVoiceState(const VoiceState &data) { m_voice_channel_id = *data.ChannelID; m_signal_voice_channel_changed.emit(m_voice_channel_id); } +#endif } else { if (data.GuildID.has_value() && data.Member.has_value()) { if (data.Member->User.has_value()) { @@ -2409,7 +2413,6 @@ void DiscordClient::CheckVoiceState(const VoiceState &data) { } } } -#endif void DiscordClient::HandleGatewayReadySupplemental(const GatewayMessage &msg) { ReadySupplementalData data = msg.Data; @@ -2929,6 +2932,15 @@ void DiscordClient::SendVoiceStateUpdate() { m_websocket.Send(msg); } +void DiscordClient::OnVoiceConnected() { + m_signal_voice_connected.emit(); +} + +void DiscordClient::OnVoiceDisconnected() { + m_signal_voice_disconnected.emit(); +} +#endif + void DiscordClient::SetVoiceState(Snowflake user_id, const VoiceState &state) { if (!state.ChannelID.has_value()) { spdlog::get("discord")->error("SetVoiceState called with missing channel ID"); @@ -2958,15 +2970,6 @@ void DiscordClient::ClearVoiceState(Snowflake user_id) { } } -void DiscordClient::OnVoiceConnected() { - m_signal_voice_connected.emit(); -} - -void DiscordClient::OnVoiceDisconnected() { - m_signal_voice_disconnected.emit(); -} -#endif - void DiscordClient::LoadEventMap() { m_event_map["READY"] = GatewayEvent::READY; m_event_map["MESSAGE_CREATE"] = GatewayEvent::MESSAGE_CREATE; @@ -3242,14 +3245,6 @@ DiscordClient::type_signal_voice_speaking DiscordClient::signal_voice_speaking() return m_signal_voice_speaking; } -DiscordClient::type_signal_voice_user_disconnect DiscordClient::signal_voice_user_disconnect() { - return m_signal_voice_user_disconnect; -} - -DiscordClient::type_signal_voice_user_connect DiscordClient::signal_voice_user_connect() { - return m_signal_voice_user_connect; -} - DiscordClient::type_signal_voice_requested_connect DiscordClient::signal_voice_requested_connect() { return m_signal_voice_requested_connect; } @@ -3265,8 +3260,16 @@ DiscordClient::type_signal_voice_client_state_update DiscordClient::signal_voice DiscordClient::type_signal_voice_channel_changed DiscordClient::signal_voice_channel_changed() { return m_signal_voice_channel_changed; } +#endif + +DiscordClient::type_signal_voice_user_disconnect DiscordClient::signal_voice_user_disconnect() { + return m_signal_voice_user_disconnect; +} + +DiscordClient::type_signal_voice_user_connect DiscordClient::signal_voice_user_connect() { + return m_signal_voice_user_connect; +} DiscordClient::type_signal_voice_state_set DiscordClient::signal_voice_state_set() { return m_signal_voice_state_set; } -#endif diff --git a/src/discord/discord.hpp b/src/discord/discord.hpp index 6b2853b..4e898dc 100644 --- a/src/discord/discord.hpp +++ b/src/discord/discord.hpp @@ -200,9 +200,7 @@ public: [[nodiscard]] bool IsVoiceConnected() const noexcept; [[nodiscard]] bool IsVoiceConnecting() const noexcept; [[nodiscard]] Snowflake GetVoiceChannelID() const noexcept; - [[nodiscard]] std::unordered_set GetUsersInVoiceChannel(Snowflake channel_id); [[nodiscard]] std::optional GetSSRCOfUser(Snowflake id) const; - [[nodiscard]] std::optional> GetVoiceState(Snowflake user_id) const; DiscordVoiceClient &GetVoiceClient(); @@ -210,6 +208,9 @@ public: void SetVoiceDeafened(bool is_deaf); #endif + [[nodiscard]] std::optional> GetVoiceState(Snowflake user_id) const; + [[nodiscard]] std::unordered_set GetUsersInVoiceChannel(Snowflake channel_id); + void SetReferringChannel(Snowflake id); void SetBuildNumber(uint32_t build_number); @@ -299,12 +300,13 @@ private: void HandleGatewayInvalidSession(const GatewayMessage &msg); #ifdef WITH_VOICE - void HandleGatewayVoiceStateUpdate(const GatewayMessage &msg); void HandleGatewayVoiceServerUpdate(const GatewayMessage &msg); void HandleGatewayCallCreate(const GatewayMessage &msg); +#endif + + void HandleGatewayVoiceStateUpdate(const GatewayMessage &msg); void CheckVoiceState(const VoiceState &data); -#endif void HeartbeatThread(); void SendIdentify(); @@ -375,19 +377,20 @@ private: bool m_deaf_requested = false; Snowflake m_voice_channel_id; - // todo sql i guess - std::unordered_map> m_voice_states; - std::unordered_map> m_voice_state_channel_users; void SendVoiceStateUpdate(); - void SetVoiceState(Snowflake user_id, const VoiceState &state); - void ClearVoiceState(Snowflake user_id); - void OnVoiceConnected(); void OnVoiceDisconnected(); #endif + void SetVoiceState(Snowflake user_id, const VoiceState &state); + void ClearVoiceState(Snowflake user_id); + + // todo sql i guess + std::unordered_map> m_voice_states; + std::unordered_map> m_voice_state_channel_users; + mutable std::mutex m_msg_mutex; Glib::Dispatcher m_msg_dispatch; std::queue m_msg_queue; @@ -465,15 +468,16 @@ public: using type_signal_voice_connected = sigc::signal; using type_signal_voice_disconnected = sigc::signal; using type_signal_voice_speaking = sigc::signal; - using type_signal_voice_user_disconnect = sigc::signal; - using type_signal_voice_user_connect = sigc::signal; using type_signal_voice_requested_connect = sigc::signal; using type_signal_voice_requested_disconnect = sigc::signal; using type_signal_voice_client_state_update = sigc::signal; using type_signal_voice_channel_changed = sigc::signal; - using type_signal_voice_state_set = sigc::signal; #endif + using type_signal_voice_user_disconnect = sigc::signal; + using type_signal_voice_user_connect = sigc::signal; + using type_signal_voice_state_set = sigc::signal; + type_signal_gateway_ready signal_gateway_ready(); type_signal_gateway_ready_supplemental signal_gateway_ready_supplemental(); type_signal_message_create signal_message_create(); @@ -533,15 +537,16 @@ public: type_signal_voice_connected signal_voice_connected(); type_signal_voice_disconnected signal_voice_disconnected(); type_signal_voice_speaking signal_voice_speaking(); - type_signal_voice_user_disconnect signal_voice_user_disconnect(); - type_signal_voice_user_connect signal_voice_user_connect(); type_signal_voice_requested_connect signal_voice_requested_connect(); type_signal_voice_requested_disconnect signal_voice_requested_disconnect(); type_signal_voice_client_state_update signal_voice_client_state_update(); type_signal_voice_channel_changed signal_voice_channel_changed(); - type_signal_voice_state_set signal_voice_state_set(); #endif + type_signal_voice_user_disconnect signal_voice_user_disconnect(); + type_signal_voice_user_connect signal_voice_user_connect(); + type_signal_voice_state_set signal_voice_state_set(); + protected: type_signal_gateway_ready m_signal_gateway_ready; type_signal_gateway_ready_supplemental m_signal_gateway_ready_supplemental; @@ -602,12 +607,13 @@ protected: type_signal_voice_connected m_signal_voice_connected; type_signal_voice_disconnected m_signal_voice_disconnected; type_signal_voice_speaking m_signal_voice_speaking; - type_signal_voice_user_disconnect m_signal_voice_user_disconnect; - type_signal_voice_user_connect m_signal_voice_user_connect; type_signal_voice_requested_connect m_signal_voice_requested_connect; type_signal_voice_requested_disconnect m_signal_voice_requested_disconnect; type_signal_voice_client_state_update m_signal_voice_client_state_update; type_signal_voice_channel_changed m_signal_voice_channel_changed; - type_signal_voice_state_set m_signal_voice_state_set; #endif + + type_signal_voice_user_disconnect m_signal_voice_user_disconnect; + type_signal_voice_user_connect m_signal_voice_user_connect; + type_signal_voice_state_set m_signal_voice_state_set; }; From 15955050f45a4ee0c3aff60e8cf0c0c54da6dc41 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Mon, 17 Jun 2024 03:56:14 -0400 Subject: [PATCH 21/25] show mentions on voice channels --- .../channellist/cellrendererchannels.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/components/channellist/cellrendererchannels.cpp b/src/components/channellist/cellrendererchannels.cpp index 8758a7d..8a6097e 100644 --- a/src/components/channellist/cellrendererchannels.cpp +++ b/src/components/channellist/cellrendererchannels.cpp @@ -600,6 +600,21 @@ void CellRendererChannels::render_vfunc_voice_channel(const Cairo::RefPtrshow_in_cairo_context(cr); RenderExpander(24, cr, widget, background_area, property_expanded()); + + // unread + if (!Abaddon::Get().GetSettings().Unreads) return; + + const auto id = m_property_id.get_value(); + const auto unread_state = Abaddon::Get().GetDiscordClient().GetUnreadStateForChannel(id); + + if (unread_state < 1) return; + + auto *paned = dynamic_cast(widget.get_ancestor(Gtk::Paned::get_type())); + if (paned != nullptr) { + const auto edge = std::min(paned->get_position(), cell_area.get_width()); + + unread_render_mentions(cr, widget, unread_state, edge, cell_area); + } } // voice participant From bd4162b18aa460782a015e4cf982119a2b7a1153 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Mon, 17 Jun 2024 04:00:29 -0400 Subject: [PATCH 22/25] add mark as read to voice channels --- src/components/channellist/channellisttree.cpp | 6 ++++++ src/components/channellist/channellisttree.hpp | 1 + 2 files changed, 7 insertions(+) diff --git a/src/components/channellist/channellisttree.cpp b/src/components/channellist/channellisttree.cpp index 611dc03..4597a1f 100644 --- a/src/components/channellist/channellisttree.cpp +++ b/src/components/channellist/channellisttree.cpp @@ -28,6 +28,7 @@ ChannelListTree::ChannelListTree() #endif , m_menu_voice_channel_join("_Join", true) , m_menu_voice_channel_disconnect("_Disconnect", true) + , m_menu_voice_channel_mark_as_read("Mark as _Read", true) , m_menu_voice_open_chat("Open _Chat", true) , m_menu_dm_copy_id("_Copy ID", true) , m_menu_dm_close("") // changes depending on if group or not @@ -209,6 +210,10 @@ ChannelListTree::ChannelListTree() }); #endif + m_menu_voice_channel_mark_as_read.signal_activate().connect([this]() { + Abaddon::Get().GetDiscordClient().MarkChannelAsRead(static_cast((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]), NOOP_CALLBACK); + }); + m_menu_voice_open_chat.signal_activate().connect([this]() { const auto id = static_cast((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]); m_signal_action_channel_item_select.emit(id); @@ -216,6 +221,7 @@ ChannelListTree::ChannelListTree() m_menu_voice_channel.append(m_menu_voice_channel_join); m_menu_voice_channel.append(m_menu_voice_channel_disconnect); + m_menu_voice_channel.append(m_menu_voice_channel_mark_as_read); m_menu_voice_channel.append(m_menu_voice_open_chat); m_menu_voice_channel.show_all(); diff --git a/src/components/channellist/channellisttree.hpp b/src/components/channellist/channellisttree.hpp index abceca9..9e2c544 100644 --- a/src/components/channellist/channellisttree.hpp +++ b/src/components/channellist/channellisttree.hpp @@ -162,6 +162,7 @@ protected: Gtk::Menu m_menu_voice_channel; Gtk::MenuItem m_menu_voice_channel_join; Gtk::MenuItem m_menu_voice_channel_disconnect; + Gtk::MenuItem m_menu_voice_channel_mark_as_read; Gtk::MenuItem m_menu_voice_open_chat; Gtk::Menu m_menu_dm; From f34b9f68f607d82085a9786e1eb0eca3e2798d38 Mon Sep 17 00:00:00 2001 From: trigg Date: Mon, 17 Jun 2024 14:28:21 +0100 Subject: [PATCH 23/25] - Fix typo in tray setting --- src/settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings.cpp b/src/settings.cpp index fc76ddb..e9b6fc7 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -96,7 +96,7 @@ void SettingsManager::DefineSettings() { AddSetting("gui", "stock_emojis", false, &Settings::ShowStockEmojis); AddSetting("gui", "unreads", true, &Settings::Unreads); AddSetting("gui", "alt_menu", false, &Settings::AltMenu); - AddSetting("gui", "hide_to_try", false, &Settings::HideToTray); + AddSetting("gui", "hide_to_tray", false, &Settings::HideToTray); AddSetting("gui", "show_deleted_indicator", true, &Settings::ShowDeletedIndicator); AddSetting("gui", "font_scale", -1.0, &Settings::FontScale); AddSetting("gui", "folder_icon_only", false, &Settings::FolderIconOnly); From 12c9ff640dd9a6007a7b15feac524517aa61106d Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Thu, 20 Jun 2024 18:50:18 -0400 Subject: [PATCH 24/25] fixed build number once more --- src/startup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/startup.cpp b/src/startup.cpp index f2ed5ce..ed42358 100644 --- a/src/startup.cpp +++ b/src/startup.cpp @@ -46,8 +46,8 @@ std::optional GetJavascriptFileFromAppPage(const Glib::ustring &c start_position += str.size(); } - if (matches.size() >= 8) { - return matches[matches.size() - 8]; + if (matches.size() >= 9) { + return matches[matches.size() - 9]; } return {}; From 7af15b326df5a638b24c5e637d5f37396276f906 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Fri, 21 Jun 2024 20:04:35 -0400 Subject: [PATCH 25/25] add workaround for musl (#317) --- src/abaddon.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/abaddon.cpp b/src/abaddon.cpp index 7f4281d..23abfd3 100644 --- a/src/abaddon.cpp +++ b/src/abaddon.cpp @@ -1,4 +1,5 @@ #include "abaddon.hpp" +#include #include #include #include @@ -1153,7 +1154,32 @@ void Abaddon::on_window_hide() { } } +// clang-format off + +#ifdef __GLIBC__ + #ifndef _GNU_SOURCE + #define _GNU_SOURCE + #include + #ifndef __USE_GNU + #define __MUSL__ + #endif + #undef _GNU_SOURCE + #else + #include + #ifndef __USE_GNU + #define __MUSL__ + #endif + #endif +#endif + +// clang-format on + int main(int argc, char **argv) { +#ifdef __MUSL__ + char env[] = "LANG=C"; + putenv(env); +#endif + if (std::getenv("ABADDON_NO_FC") == nullptr) Platform::SetupFonts();