Add settings customize Discord status text

The new settings let you customize the "Listening to" status text, according to the [status display types](https://discord.com/developers/docs/events/gateway-events#activity-object).

Fixes #1796.
This commit is contained in:
7xnl
2025-08-28 01:30:25 +03:00
committed by Jonas Kvinge
parent 3c3480fb84
commit b5fd3d5717
7 changed files with 75 additions and 4 deletions

View File

@@ -32,6 +32,7 @@ extern "C" {
typedef struct DiscordRichPresence {
int type;
int status_display_type;
const char *name; /* max 128 bytes */
const char *state; /* max 128 bytes */
const char *details; /* max 128 bytes */

View File

@@ -128,6 +128,9 @@ size_t JsonWriteRichPresenceObj(char *dest, const size_t maxLen, const int nonce
if (presence->type >= 0 && presence->type <= 5) {
WriteKey(writer, "type");
writer.Int(presence->type);
WriteKey(writer, "status_display_type");
writer.Int(presence->status_display_type);
}
WriteOptionalString(writer, "name", presence->name);

View File

@@ -71,6 +71,14 @@ constexpr char kSettingsGroup[] = "DiscordRPC";
constexpr char kEnabled[] = "enabled";
constexpr char kStatusDisplayType[] = "StatusDisplayType";
enum class StatusDisplayType {
App = 0,
Artist,
Song
};
} // namespace
#endif // NOTIFICATIONSSETTINGS_H

View File

@@ -46,7 +46,8 @@ RichPresence::RichPresence(const SharedPtr<Player> player,
: QObject(parent),
player_(player),
playlist_manager_(playlist_manager),
initialized_(false) {
initialized_(false),
status_display_type_(0) {
QObject::connect(&*player_->engine(), &EngineBase::StateChanged, this, &RichPresence::EngineStateChanged);
QObject::connect(&*playlist_manager_, &PlaylistManager::CurrentSongChanged, this, &RichPresence::CurrentSongChanged);
@@ -69,6 +70,7 @@ void RichPresence::ReloadSettings() {
Settings s;
s.beginGroup(DiscordRPCSettings::kSettingsGroup);
const bool enabled = s.value(DiscordRPCSettings::kEnabled, false).toBool();
status_display_type_ = s.value(DiscordRPCSettings::kStatusDisplayType, static_cast<int>(DiscordRPCSettings::StatusDisplayType::App)).toInt();
s.endGroup();
if (enabled && !initialized_) {
@@ -117,7 +119,11 @@ void RichPresence::SendPresenceUpdate() {
::DiscordRichPresence presence_data{};
memset(&presence_data, 0, sizeof(presence_data));
presence_data.type = 2; // Listening
// Listening to
presence_data.type = 2;
presence_data.status_display_type = status_display_type_;
presence_data.largeImageKey = kStrawberryIconResourceName;
presence_data.smallImageKey = kStrawberryIconResourceName;
presence_data.smallImageText = kStrawberryIconDescription;
@@ -126,7 +132,9 @@ void RichPresence::SendPresenceUpdate() {
QByteArray artist;
if (!activity_.artist.isEmpty()) {
artist = activity_.artist.toUtf8();
artist.prepend(tr("by ").toUtf8());
if (artist.size() < 2) { // Discord activity 2 char min. fix
artist.append(" ");
}
presence_data.state = artist.constData();
}

View File

@@ -70,6 +70,7 @@ class RichPresence : public QObject {
};
Activity activity_;
bool initialized_;
int status_display_type_;
};
} // namespace discord

View File

@@ -209,6 +209,19 @@ void NotificationsSettingsPage::Load() {
// Discord
s.beginGroup(DiscordRPCSettings::kSettingsGroup);
ui_->richpresence_enabled->setChecked(s.value(DiscordRPCSettings::kEnabled, false).toBool());
const DiscordRPCSettings::StatusDisplayType discord_status_display_type = static_cast<DiscordRPCSettings::StatusDisplayType>(s.value(DiscordRPCSettings::kStatusDisplayType, static_cast<int>(DiscordRPCSettings::StatusDisplayType::App)).toInt());
switch (discord_status_display_type) {
case DiscordRPCSettings::StatusDisplayType::App:
ui_->richpresence_listening_to_app->setChecked(true);
break;
case DiscordRPCSettings::StatusDisplayType::Artist:
ui_->richpresence_listening_to_artist->setChecked(true);
break;
case DiscordRPCSettings::StatusDisplayType::Song:
ui_->richpresence_listening_to_song->setChecked(true);
break;
}
s.endGroup();
UpdatePopupVisible();
@@ -229,6 +242,11 @@ void NotificationsSettingsPage::Save() {
else if (osd_->SupportsTrayPopups() && ui_->notifications_tray->isChecked()) osd_type = OSDSettings::Type::TrayPopup;
else if (osd_->SupportsOSDPretty() && ui_->notifications_pretty->isChecked()) osd_type = OSDSettings::Type::Pretty;
DiscordRPCSettings::StatusDisplayType discord_status_display_type = DiscordRPCSettings::StatusDisplayType::App;
if (ui_->richpresence_listening_to_app->isChecked()) discord_status_display_type = DiscordRPCSettings::StatusDisplayType::App;
else if (ui_->richpresence_listening_to_artist->isChecked()) discord_status_display_type = DiscordRPCSettings::StatusDisplayType::Artist;
else if (ui_->richpresence_listening_to_song->isChecked()) discord_status_display_type = DiscordRPCSettings::StatusDisplayType::Song;
s.beginGroup(OSDSettings::kSettingsGroup);
s.setValue(OSDSettings::kType, static_cast<int>(osd_type));
s.setValue(OSDSettings::kTimeout, ui_->notifications_duration->value() * 1000);
@@ -255,7 +273,9 @@ void NotificationsSettingsPage::Save() {
s.beginGroup(DiscordRPCSettings::kSettingsGroup);
s.setValue(DiscordRPCSettings::kEnabled, ui_->richpresence_enabled->isChecked());
s.setValue(DiscordRPCSettings::kStatusDisplayType, static_cast<int>(discord_status_display_type));
s.endGroup();
}
void NotificationsSettingsPage::PrettyOpacityChanged(int value) {

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>518</width>
<height>778</height>
<height>844</height>
</rect>
</property>
<property name="windowTitle">
@@ -380,6 +380,36 @@
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="richpresence_listening_to">
<property name="title">
<string>&quot;Listening to...&quot;</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<widget class="QRadioButton" name="richpresence_listening_to_app">
<property name="text">
<string>Strawberry</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="richpresence_listening_to_artist">
<property name="text">
<string>Artist name</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="richpresence_listening_to_song">
<property name="text">
<string>Song title</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>