mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 06:25:41 +00:00
feat(discord): show track title in Discord member list (configurable name template) (#885)
* feat(discord): override activity name in member list with track title (configurable template)
The Discord member list and the collapsed Rich Presence card display the
activity's `name` field next to the music icon. Without an override
Discord falls back to the registered application name ("Psysonic"), so
the line reads "Psysonic" while every track plays instead of the actual
track title that comparable players show.
Add a fourth user-configurable template `discordTemplateName` (Settings ->
Integrations -> Discord Rich Presence). The Rust side passes it through
`Activity::new().name(...)` when the rendered template is non-empty; an
empty template falls back to Discord's default application name. Default
template is "{title}".
Tauri boundary: additive optional `nameTemplate` field on the existing
`discord_update_presence` command. Existing call sites that omit it keep
working -- the Rust handler applies the same "{title}" fallback.
* i18n(settings): discord name template label in all locales
Adds the discordTemplateName label across en, de, fr, es, nl, nb, ro,
zh, ru -- shown next to the new "User list line (name)" template input
under Discord Rich Presence.
* docs(release): CHANGELOG and credits for discord name template (PR #885)
This commit is contained in:
committed by
GitHub
parent
403979b35d
commit
455aec4def
@@ -262,12 +262,13 @@ fn apply_template(template: &str, title: &str, artist: &str, album: Option<&str>
|
||||
|
||||
/// Bundled output of [`compute_discord_text_fields`].
|
||||
pub(crate) struct DiscordTextFields {
|
||||
pub name: String,
|
||||
pub details: String,
|
||||
pub state: String,
|
||||
pub large_text: String,
|
||||
}
|
||||
|
||||
/// Pure helper: resolve all three configurable Discord text fields, applying
|
||||
/// Pure helper: resolve all four configurable Discord text fields, applying
|
||||
/// the supplied templates (or falling back to documented defaults).
|
||||
pub(crate) fn compute_discord_text_fields(
|
||||
title: &str,
|
||||
@@ -276,7 +277,9 @@ pub(crate) fn compute_discord_text_fields(
|
||||
details_template: Option<&str>,
|
||||
state_template: Option<&str>,
|
||||
large_text_template: Option<&str>,
|
||||
name_template: Option<&str>,
|
||||
) -> DiscordTextFields {
|
||||
let name = apply_template(name_template.unwrap_or("{title}"), title, artist, album);
|
||||
let details = apply_template(
|
||||
details_template.unwrap_or("{artist} - {title}"),
|
||||
title,
|
||||
@@ -291,6 +294,7 @@ pub(crate) fn compute_discord_text_fields(
|
||||
album,
|
||||
);
|
||||
DiscordTextFields {
|
||||
name,
|
||||
details,
|
||||
state,
|
||||
large_text,
|
||||
@@ -318,6 +322,10 @@ pub(crate) fn compute_discord_start_timestamp(elapsed_secs: f64, now_unix_secs:
|
||||
/// Supported placeholders: {title}, {artist}, {album}
|
||||
/// - `large_text_template`: template string for the large image tooltip. Default: "{album}".
|
||||
/// Supported placeholders: {title}, {artist}, {album}
|
||||
/// - `name_template`: template string overriding Discord's default application name in the
|
||||
/// user list (e.g. "🎵 Bohemian Rhapsody" instead of "🎵 Psysonic"). Default: "{title}".
|
||||
/// Empty string falls back to the registered Discord application name.
|
||||
/// Supported placeholders: {title}, {artist}, {album}
|
||||
#[tauri::command]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn discord_update_presence(
|
||||
@@ -332,6 +340,7 @@ pub async fn discord_update_presence(
|
||||
details_template: Option<String>,
|
||||
state_template: Option<String>,
|
||||
large_text_template: Option<String>,
|
||||
name_template: Option<String>,
|
||||
) -> Result<(), String> {
|
||||
// Resolve artwork on a dedicated blocking thread — reqwest::blocking must not
|
||||
// run on the Tokio async executor directly.
|
||||
@@ -377,6 +386,7 @@ pub async fn discord_update_presence(
|
||||
details_template.as_deref(),
|
||||
state_template.as_deref(),
|
||||
large_text_template.as_deref(),
|
||||
name_template.as_deref(),
|
||||
);
|
||||
|
||||
let assets = if let Some(ref url) = artwork_url {
|
||||
@@ -402,8 +412,11 @@ pub async fn discord_update_presence(
|
||||
}
|
||||
|
||||
// Only reach here when playing
|
||||
let activity = Activity::new()
|
||||
.activity_type(ActivityType::Listening)
|
||||
let mut activity = Activity::new().activity_type(ActivityType::Listening);
|
||||
if !texts.name.is_empty() {
|
||||
activity = activity.name(texts.name.as_str());
|
||||
}
|
||||
let activity = activity
|
||||
.details(&texts.details)
|
||||
.state(&texts.state)
|
||||
.assets(assets)
|
||||
@@ -545,7 +558,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn text_fields_use_documented_defaults_when_templates_are_none() {
|
||||
let f = compute_discord_text_fields("Song", "Artist", Some("Album"), None, None, None);
|
||||
let f =
|
||||
compute_discord_text_fields("Song", "Artist", Some("Album"), None, None, None, None);
|
||||
assert_eq!(f.name, "Song");
|
||||
assert_eq!(f.details, "Artist - Song");
|
||||
assert_eq!(f.state, "Album");
|
||||
assert_eq!(f.large_text, "Album");
|
||||
@@ -560,7 +575,9 @@ mod tests {
|
||||
Some("{title} | {album}"),
|
||||
Some("by {artist}"),
|
||||
Some("{album} ({artist})"),
|
||||
Some("{title} ({artist})"),
|
||||
);
|
||||
assert_eq!(f.name, "Song (Artist)");
|
||||
assert_eq!(f.details, "Song | Album");
|
||||
assert_eq!(f.state, "by Artist");
|
||||
assert_eq!(f.large_text, "Album (Artist)");
|
||||
@@ -568,8 +585,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn text_fields_substitute_empty_for_missing_album() {
|
||||
let f = compute_discord_text_fields("Song", "Artist", None, None, None, None);
|
||||
let f = compute_discord_text_fields("Song", "Artist", None, None, None, None, None);
|
||||
// {album} placeholder → empty, but the surrounding template stays.
|
||||
assert_eq!(f.name, "Song");
|
||||
assert_eq!(f.details, "Artist - Song");
|
||||
assert_eq!(f.state, "");
|
||||
assert_eq!(f.large_text, "");
|
||||
@@ -584,7 +602,9 @@ mod tests {
|
||||
Some("{artist} – {title}"),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
assert_eq!(f.name, "Bohemian Rhapsody");
|
||||
assert_eq!(f.details, "Queen – Bohemian Rhapsody");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user