Skip to content

Commit 68db143

Browse files
authored
Merge pull request #279 from uowuo/stages
Support for stages
2 parents e6191d9 + b19782c commit 68db143

25 files changed

Lines changed: 707 additions & 135 deletions

src/abaddon.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "windows/profilewindow.hpp"
2020
#include "windows/pinnedwindow.hpp"
2121
#include "windows/threadswindow.hpp"
22-
#include "windows/voicewindow.hpp"
22+
#include "windows/voice/voicewindow.hpp"
2323
#include "startup.hpp"
2424
#include "notifications/notifications.hpp"
2525
#include "remoteauth/remoteauthdialog.hpp"

src/components/channellist/cellrendererchannels.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ void CellRendererChannels::get_preferred_width_vfunc(Gtk::Widget &widget, int &m
123123
case RenderType::Thread:
124124
return get_preferred_width_vfunc_thread(widget, minimum_width, natural_width);
125125
case RenderType::VoiceChannel:
126+
case RenderType::VoiceStage:
126127
return get_preferred_width_vfunc_voice_channel(widget, minimum_width, natural_width);
127128
case RenderType::VoiceParticipant:
128129
return get_preferred_width_vfunc_voice_participant(widget, minimum_width, natural_width);
@@ -146,6 +147,7 @@ void CellRendererChannels::get_preferred_width_for_height_vfunc(Gtk::Widget &wid
146147
case RenderType::Thread:
147148
return get_preferred_width_for_height_vfunc_thread(widget, height, minimum_width, natural_width);
148149
case RenderType::VoiceChannel:
150+
case RenderType::VoiceStage:
149151
return get_preferred_width_for_height_vfunc_voice_channel(widget, height, minimum_width, natural_width);
150152
case RenderType::VoiceParticipant:
151153
return get_preferred_width_for_height_vfunc_voice_participant(widget, height, minimum_width, natural_width);
@@ -169,6 +171,7 @@ void CellRendererChannels::get_preferred_height_vfunc(Gtk::Widget &widget, int &
169171
case RenderType::Thread:
170172
return get_preferred_height_vfunc_thread(widget, minimum_height, natural_height);
171173
case RenderType::VoiceChannel:
174+
case RenderType::VoiceStage:
172175
return get_preferred_height_vfunc_voice_channel(widget, minimum_height, natural_height);
173176
case RenderType::VoiceParticipant:
174177
return get_preferred_height_vfunc_voice_participant(widget, minimum_height, natural_height);
@@ -192,6 +195,7 @@ void CellRendererChannels::get_preferred_height_for_width_vfunc(Gtk::Widget &wid
192195
case RenderType::Thread:
193196
return get_preferred_height_for_width_vfunc_thread(widget, width, minimum_height, natural_height);
194197
case RenderType::VoiceChannel:
198+
case RenderType::VoiceStage:
195199
return get_preferred_height_for_width_vfunc_voice_channel(widget, width, minimum_height, natural_height);
196200
case RenderType::VoiceParticipant:
197201
return get_preferred_height_for_width_vfunc_voice_participant(widget, width, minimum_height, natural_height);
@@ -215,7 +219,9 @@ void CellRendererChannels::render_vfunc(const Cairo::RefPtr<Cairo::Context> &cr,
215219
case RenderType::Thread:
216220
return render_vfunc_thread(cr, widget, background_area, cell_area, flags);
217221
case RenderType::VoiceChannel:
218-
return render_vfunc_voice_channel(cr, widget, background_area, cell_area, flags);
222+
return render_vfunc_voice_channel(cr, widget, background_area, cell_area, flags, "\U0001F50A");
223+
case RenderType::VoiceStage:
224+
return render_vfunc_voice_channel(cr, widget, background_area, cell_area, flags, "\U0001F4E1");
219225
case RenderType::VoiceParticipant:
220226
return render_vfunc_voice_participant(cr, widget, background_area, cell_area, flags);
221227
case RenderType::DMHeader:
@@ -571,7 +577,7 @@ void CellRendererChannels::get_preferred_height_for_width_vfunc_voice_channel(Gt
571577
m_renderer_text.get_preferred_height_for_width(widget, width, minimum_height, natural_height);
572578
}
573579

574-
void CellRendererChannels::render_vfunc_voice_channel(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags) {
580+
void CellRendererChannels::render_vfunc_voice_channel(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, const Gdk::Rectangle &background_area, const Gdk::Rectangle &cell_area, Gtk::CellRendererState flags, const char *emoji) {
575581
// channel name text
576582
Gtk::Requisition minimum_size, natural_size;
577583
m_renderer_text.get_preferred_size(widget, minimum_size, natural_size);
@@ -588,7 +594,7 @@ void CellRendererChannels::render_vfunc_voice_channel(const Cairo::RefPtr<Cairo:
588594
Pango::FontDescription font;
589595
font.set_family("sans 14");
590596

591-
auto layout = widget.create_pango_layout("\U0001F50A");
597+
auto layout = widget.create_pango_layout(emoji);
592598
layout->set_font_description(font);
593599
layout->set_alignment(Pango::ALIGN_LEFT);
594600
cr->set_source_rgba(1.0, 1.0, 1.0, 1.0);

src/components/channellist/cellrendererchannels.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include <gtkmm/cellrendererpixbuf.h>
77
#include <gtkmm/cellrenderertext.h>
88
#include "discord/snowflake.hpp"
9-
#include "discord/voicestateflags.hpp"
9+
#include "discord/voicestate.hpp"
1010
#include "misc/bitwise.hpp"
1111

1212
enum class RenderType : uint8_t {
@@ -16,6 +16,7 @@ enum class RenderType : uint8_t {
1616
TextChannel,
1717
Thread,
1818
VoiceChannel,
19+
VoiceStage, // identical to non-stage except for icon
1920
VoiceParticipant,
2021

2122
DMHeader,
@@ -112,7 +113,8 @@ class CellRendererChannels : public Gtk::CellRenderer {
112113
Gtk::Widget &widget,
113114
const Gdk::Rectangle &background_area,
114115
const Gdk::Rectangle &cell_area,
115-
Gtk::CellRendererState flags);
116+
Gtk::CellRendererState flags,
117+
const char *emoji);
116118

117119
// voice participant
118120
void get_preferred_width_vfunc_voice_participant(Gtk::Widget &widget, int &minimum_width, int &natural_width) const;

src/components/channellist/channellisttree.cpp

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ ChannelListTree::ChannelListTree()
2828
#endif
2929
, m_menu_voice_channel_join("_Join", true)
3030
, m_menu_voice_channel_disconnect("_Disconnect", true)
31+
, m_menu_voice_stage_join("_Join", true)
32+
, m_menu_voice_stage_disconnect("_Disconnect", true)
3133
, m_menu_voice_channel_mark_as_read("Mark as _Read", true)
3234
, m_menu_voice_open_chat("Open _Chat", true)
3335
, m_menu_dm_copy_id("_Copy ID", true)
@@ -225,6 +227,21 @@ ChannelListTree::ChannelListTree()
225227
m_menu_voice_channel.append(m_menu_voice_open_chat);
226228
m_menu_voice_channel.show_all();
227229

230+
#ifdef WITH_VOICE
231+
m_menu_voice_stage_join.signal_activate().connect([this]() {
232+
const auto id = static_cast<Snowflake>((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]);
233+
m_signal_action_join_voice_channel.emit(id);
234+
});
235+
236+
m_menu_voice_stage_disconnect.signal_activate().connect([this]() {
237+
m_signal_action_disconnect_voice.emit();
238+
});
239+
#endif
240+
241+
m_menu_voice_stage.append(m_menu_voice_stage_join);
242+
m_menu_voice_stage.append(m_menu_voice_stage_disconnect);
243+
m_menu_voice_stage.show_all();
244+
228245
m_menu_dm_copy_id.signal_activate().connect([this] {
229246
Gtk::Clipboard::get()->set_text(std::to_string((*m_model->get_iter(m_path_for_menu))[m_columns.m_id]));
230247
});
@@ -366,8 +383,8 @@ int ChannelListTree::SortFunc(const Gtk::TreeModel::iterator &a, const Gtk::Tree
366383
const int64_t b_sort = (*b)[m_columns.m_sort];
367384
if (a_type == RenderType::DMHeader) return -1;
368385
if (b_type == RenderType::DMHeader) return 1;
369-
if (a_type == RenderType::TextChannel && b_type == RenderType::VoiceChannel) return -1;
370-
if (b_type == RenderType::TextChannel && a_type == RenderType::VoiceChannel) return 1;
386+
if (a_type == RenderType::TextChannel && (b_type == RenderType::VoiceChannel || b_type == RenderType::VoiceStage)) return -1;
387+
if (b_type == RenderType::TextChannel && (a_type == RenderType::VoiceChannel || a_type == RenderType::VoiceStage)) return 1;
371388
return static_cast<int>(std::clamp(a_sort - b_sort, int64_t(-1), int64_t(1)));
372389
}
373390

@@ -634,6 +651,7 @@ void ChannelListTree::OnThreadListSync(const ThreadListSyncData &data) {
634651

635652
void ChannelListTree::OnVoiceUserConnect(Snowflake user_id, Snowflake channel_id) {
636653
auto parent_iter = GetIteratorForRowFromIDOfType(channel_id, RenderType::VoiceChannel);
654+
if (!parent_iter) parent_iter = GetIteratorForRowFromIDOfType(channel_id, RenderType::VoiceStage);
637655
if (!parent_iter) parent_iter = GetIteratorForRowFromIDOfType(channel_id, RenderType::DM);
638656
if (!parent_iter) return;
639657
const auto user = Abaddon::Get().GetDiscordClient().GetUser(user_id);
@@ -914,7 +932,7 @@ Gtk::TreeModel::iterator ChannelListTree::AddGuild(const GuildData &guild, const
914932
for (const auto &channel_ : *guild.Channels) {
915933
const auto channel = discord.GetChannel(channel_.ID);
916934
if (!channel.has_value()) continue;
917-
if (channel->Type == ChannelType::GUILD_TEXT || channel->Type == ChannelType::GUILD_NEWS || channel->Type == ChannelType::GUILD_VOICE) {
935+
if (channel->Type == ChannelType::GUILD_TEXT || channel->Type == ChannelType::GUILD_NEWS || channel->Type == ChannelType::GUILD_VOICE || channel->Type == ChannelType::GUILD_STAGE_VOICE) {
918936
if (channel->ParentID.has_value())
919937
categories[*channel->ParentID].push_back(*channel);
920938
else
@@ -954,6 +972,10 @@ Gtk::TreeModel::iterator ChannelListTree::AddGuild(const GuildData &guild, const
954972
if (IsTextChannel(channel.Type)) {
955973
channel_row[m_columns.m_type] = RenderType::TextChannel;
956974
channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name);
975+
} else if (channel.Type == ChannelType::GUILD_STAGE_VOICE) {
976+
channel_row[m_columns.m_type] = RenderType::VoiceStage;
977+
channel_row[m_columns.m_name] = Glib::Markup::escape_text(*channel.Name);
978+
add_voice_participants(channel, channel_row->children());
957979
} else {
958980
channel_row[m_columns.m_type] = RenderType::VoiceChannel;
959981
channel_row[m_columns.m_name] = Glib::Markup::escape_text(*channel.Name);
@@ -983,6 +1005,10 @@ Gtk::TreeModel::iterator ChannelListTree::AddGuild(const GuildData &guild, const
9831005
if (IsTextChannel(channel.Type)) {
9841006
channel_row[m_columns.m_type] = RenderType::TextChannel;
9851007
channel_row[m_columns.m_name] = "#" + Glib::Markup::escape_text(*channel.Name);
1008+
} else if (channel.Type == ChannelType::GUILD_STAGE_VOICE) {
1009+
channel_row[m_columns.m_type] = RenderType::VoiceStage;
1010+
channel_row[m_columns.m_name] = Glib::Markup::escape_text(*channel.Name);
1011+
add_voice_participants(channel, channel_row->children());
9861012
} else {
9871013
channel_row[m_columns.m_type] = RenderType::VoiceChannel;
9881014
channel_row[m_columns.m_name] = Glib::Markup::escape_text(*channel.Name);
@@ -1033,7 +1059,7 @@ Gtk::TreeModel::iterator ChannelListTree::CreateVoiceParticipantRow(const UserDa
10331059

10341060
const auto voice_state = Abaddon::Get().GetDiscordClient().GetVoiceState(user.ID);
10351061
if (voice_state.has_value()) {
1036-
row[m_columns.m_voice_flags] = voice_state->second;
1062+
row[m_columns.m_voice_flags] = voice_state->second.Flags;
10371063
}
10381064

10391065
auto &img = Abaddon::Get().GetImageManager();
@@ -1331,6 +1357,10 @@ bool ChannelListTree::OnButtonPressEvent(GdkEventButton *ev) {
13311357
OnVoiceChannelSubmenuPopup();
13321358
m_menu_voice_channel.popup_at_pointer(reinterpret_cast<GdkEvent *>(ev));
13331359
break;
1360+
case RenderType::VoiceStage:
1361+
OnVoiceStageSubmenuPopup();
1362+
m_menu_voice_stage.popup_at_pointer(reinterpret_cast<GdkEvent *>(ev));
1363+
break;
13341364
case RenderType::DM: {
13351365
OnDMSubmenuPopup();
13361366
const auto channel = Abaddon::Get().GetDiscordClient().GetChannel(static_cast<Snowflake>(row[m_columns.m_id]));
@@ -1442,6 +1472,25 @@ void ChannelListTree::OnVoiceChannelSubmenuPopup() {
14421472
#endif
14431473
}
14441474

1475+
void ChannelListTree::OnVoiceStageSubmenuPopup() {
1476+
#ifdef WITH_VOICE
1477+
const auto iter = m_model->get_iter(m_path_for_menu);
1478+
if (!iter) return;
1479+
const auto id = static_cast<Snowflake>((*iter)[m_columns.m_id]);
1480+
auto &discord = Abaddon::Get().GetDiscordClient();
1481+
if (discord.IsVoiceConnected() || discord.IsVoiceConnecting()) {
1482+
m_menu_voice_stage_join.set_sensitive(false);
1483+
m_menu_voice_stage_disconnect.set_sensitive(discord.GetVoiceChannelID() == id);
1484+
} else {
1485+
m_menu_voice_stage_join.set_sensitive(true);
1486+
m_menu_voice_stage_disconnect.set_sensitive(false);
1487+
}
1488+
#else
1489+
m_menu_voice_stage_join.set_sensitive(false);
1490+
m_menu_voice_stage_disconnect.set_sensitive(false);
1491+
#endif
1492+
}
1493+
14451494
void ChannelListTree::OnDMSubmenuPopup() {
14461495
auto iter = m_model->get_iter(m_path_for_menu);
14471496
if (!iter) return;

src/components/channellist/channellisttree.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ class ChannelListTree : public Gtk::ScrolledWindow {
162162
Gtk::Menu m_menu_voice_channel;
163163
Gtk::MenuItem m_menu_voice_channel_join;
164164
Gtk::MenuItem m_menu_voice_channel_disconnect;
165+
166+
Gtk::Menu m_menu_voice_stage;
167+
Gtk::MenuItem m_menu_voice_stage_join;
168+
Gtk::MenuItem m_menu_voice_stage_disconnect;
165169
Gtk::MenuItem m_menu_voice_channel_mark_as_read;
166170
Gtk::MenuItem m_menu_voice_open_chat;
167171

@@ -192,6 +196,7 @@ class ChannelListTree : public Gtk::ScrolledWindow {
192196
void OnDMSubmenuPopup();
193197
void OnThreadSubmenuPopup();
194198
void OnVoiceChannelSubmenuPopup();
199+
void OnVoiceStageSubmenuPopup();
195200

196201
bool m_updating_listing = false;
197202

src/discord/channel.hpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,6 @@ enum class ChannelType : int {
2727
GUILD_MEDIA = 16,
2828
};
2929

30-
enum class StagePrivacy {
31-
PUBLIC = 1,
32-
GUILD_ONLY = 2,
33-
};
34-
35-
constexpr const char *GetStagePrivacyDisplayString(StagePrivacy e) {
36-
switch (e) {
37-
case StagePrivacy::PUBLIC:
38-
return "Public";
39-
case StagePrivacy::GUILD_ONLY:
40-
return "Guild Only";
41-
default:
42-
return "Unknown";
43-
}
44-
}
45-
4630
// should be moved somewhere?
4731

4832
struct ThreadMetadataData {

0 commit comments

Comments
 (0)