From c64a1e195ed83e7d2166fa1177ea60c5b5ece465 Mon Sep 17 00:00:00 2001 From: Frank Stellmacher <171614930+Psychotoxical@users.noreply.github.com> Date: Sun, 26 Apr 2026 23:25:20 +0200 Subject: [PATCH] chore(discord): debug-build logging for Rich Presence IPC path (#330) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Discord Rich Presence module deliberately swallows every IPC error so the app stays clean when Discord is not running. The downside: when the status genuinely stops working (Discord client glitches, app id rejected, socket pipe stuck), nothing is logged anywhere and we have no signal. Add debug-build logging at every step of the IPC handshake and every send: - try_connect: separate failure logs for new() vs connect(), success log with the app id. - discord_update_presence: log the rendered details/state on send, log set_activity failures with the underlying error. - discord_clear_presence: log clear success and clear failures. - The pause-path clear_activity inside discord_update_presence likewise logs failures. All log lines are wrapped in #[cfg(debug_assertions)] so they compile out of release builds — no runtime cost or log noise for end users. Co-authored-by: Claude Opus 4.7 (1M context) --- src-tauri/src/discord.rs | 43 +++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/discord.rs b/src-tauri/src/discord.rs index 590c68b9..baac8813 100644 --- a/src-tauri/src/discord.rs +++ b/src-tauri/src/discord.rs @@ -210,9 +210,26 @@ fn cache_and_return( } /// Try to create and connect a fresh IPC client. Returns None silently on failure. +/// +/// In debug builds (i.e. `npx tauri dev`) every step of the IPC handshake is +/// logged so the renderer's terminal output shows exactly where the +/// connection breaks. Release builds stay completely silent. fn try_connect() -> Option { - let mut client = DiscordIpcClient::new(DISCORD_APP_ID).ok()?; - client.connect().ok()?; + let mut client = match DiscordIpcClient::new(DISCORD_APP_ID) { + Ok(c) => c, + Err(_e) => { + #[cfg(debug_assertions)] + crate::app_eprintln!("[discord] new() failed (app_id={}): {}", DISCORD_APP_ID, _e); + return None; + } + }; + if let Err(_e) = client.connect() { + #[cfg(debug_assertions)] + crate::app_eprintln!("[discord] connect() failed: {} (Discord desktop running?)", _e); + return None; + } + #[cfg(debug_assertions)] + crate::app_eprintln!("[discord] IPC connected (app_id={})", DISCORD_APP_ID); Some(client) } @@ -316,7 +333,9 @@ pub async fn discord_update_presence( // When paused: clear activity completely to avoid any timer issues // When playing: show full activity with timer if !is_playing { - if client.clear_activity().is_err() { + if let Err(_e) = client.clear_activity() { + #[cfg(debug_assertions)] + crate::app_eprintln!("[discord] clear_activity (pause) failed, dropping client: {}", _e); *guard = None; } return Ok(()); @@ -339,8 +358,17 @@ pub async fn discord_update_presence( Timestamps::new() }); - if client.set_activity(activity).is_err() { + if let Err(_e) = client.set_activity(activity) { + #[cfg(debug_assertions)] + crate::app_eprintln!("[discord] set_activity failed, dropping client: {}", _e); *guard = None; + } else { + #[cfg(debug_assertions)] + crate::app_eprintln!( + "[discord] activity sent: \"{}\" / \"{}\"", + details_text, + state_text + ); } Ok(()) @@ -351,8 +379,13 @@ pub async fn discord_update_presence( pub fn discord_clear_presence(state: tauri::State) -> Result<(), String> { let mut guard = state.client.lock().unwrap(); if let Some(client) = guard.as_mut() { - if client.clear_activity().is_err() { + if let Err(_e) = client.clear_activity() { + #[cfg(debug_assertions)] + crate::app_eprintln!("[discord] clear_activity failed, dropping client: {}", _e); *guard = None; + } else { + #[cfg(debug_assertions)] + crate::app_eprintln!("[discord] activity cleared"); } } Ok(())