fix(android): adapt fold layout and diagnostics

This commit is contained in:
Edison Jwa
2026-05-20 14:52:34 +09:00
parent 30ff955439
commit 3ae8e1ab77
3 changed files with 80 additions and 71 deletions
+55 -20
View File
@@ -32,6 +32,40 @@ fn runtime() -> &'static Runtime {
})
}
fn task_join_error(task: &'static str, error: tokio::task::JoinError) -> BridgeError {
warn!(
target: "chanora_bridge",
task,
error = %error,
"runtime task failed; surfacing in diagnostics"
);
BridgeError::Unmapped(format!("join: {error}"))
}
fn install_panic_diagnostic_hook() {
static INSTALLED: OnceLock<()> = OnceLock::new();
let _ = INSTALLED.get_or_init(|| {
std::panic::set_hook(Box::new(|panic_info| {
let message = panic_info
.payload()
.downcast_ref::<&'static str>()
.map(|s| (*s).to_string())
.or_else(|| panic_info.payload().downcast_ref::<String>().cloned())
.unwrap_or_else(|| "non-string panic payload".to_string());
let location = panic_info
.location()
.map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column()))
.unwrap_or_else(|| "unknown".to_string());
warn!(
target: "chanora_bridge",
panic_message = %message,
panic_location = %location,
"panic captured for diagnostic export"
);
}));
});
}
/// Process-wide session handle. One instance per process is enough
/// for Alpha (DEC-006 single-connection invariant); the Mutex inside
/// `ChanoraSession` enforces the connection-count invariant.
@@ -177,6 +211,7 @@ pub fn bridge_init() {
}
}
install_panic_diagnostic_hook();
info!(target: "chanora_bridge", "bridge initialised");
if let Some(p) = log_file_path() {
info!(target: "chanora_bridge", path = %p.display(), "log file path");
@@ -415,7 +450,7 @@ pub async fn connect(
let snap = runtime()
.spawn(async move { session().connect(cfg).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("connect", e))??;
Ok(snap.into())
}
@@ -424,7 +459,7 @@ pub async fn snapshot() -> Result<BridgeSnapshot, BridgeError> {
let snap = runtime()
.spawn(async { session().snapshot().await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("snapshot", e))??;
Ok(snap.into())
}
@@ -433,7 +468,7 @@ pub async fn disconnect() -> Result<(), BridgeError> {
runtime()
.spawn(async { session().disconnect().await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("disconnect", e))??;
Ok(())
}
@@ -488,7 +523,7 @@ pub async fn set_ptt(active: bool) -> Result<(), BridgeError> {
runtime()
.spawn(async move { session().set_ptt(active).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("set_ptt", e))??;
Ok(())
}
@@ -545,7 +580,7 @@ pub async fn voice_join(channel_id: u64, password: String) -> Result<(), BridgeE
runtime()
.spawn(async move { session().voice_join(channel_id, pw).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("voice_join", e))??;
Ok(())
}
@@ -555,7 +590,7 @@ pub async fn voice_leave() -> Result<(), BridgeError> {
runtime()
.spawn(async { session().voice_leave().await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("voice_leave", e))??;
Ok(())
}
@@ -564,7 +599,7 @@ pub async fn set_transmit_mode(mode: BridgeTransmitMode) -> Result<(), BridgeErr
runtime()
.spawn(async move { session().set_transmit_mode(mode.into()).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("set_transmit_mode", e))??;
Ok(())
}
@@ -584,7 +619,7 @@ pub async fn set_release_tail_ms(ms: u32) -> Result<(), BridgeError> {
runtime()
.spawn(async move { session().set_release_tail_ms(ms).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("set_release_tail_ms", e))??;
Ok(())
}
@@ -602,7 +637,7 @@ pub async fn set_hard_mute(muted: bool) -> Result<(), BridgeError> {
runtime()
.spawn(async move { session().set_hard_mute(muted).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("set_hard_mute", e))??;
Ok(())
}
@@ -644,7 +679,7 @@ pub async fn set_ptt_binding(
runtime()
.spawn(async move { session().set_ptt_binding(binding).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("set_ptt_binding", e))??;
Ok(())
}
@@ -683,7 +718,7 @@ pub async fn move_to_channel(channel_id: u64, password: String) -> Result<(), Br
runtime()
.spawn(async move { session().move_to_channel(channel_id, pw).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("move_to_channel", e))??;
Ok(())
}
@@ -694,7 +729,7 @@ pub async fn set_input_muted(muted: bool) -> Result<(), BridgeError> {
runtime()
.spawn(async move { session().set_self_muted(Some(muted), None).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("set_input_muted", e))??;
Ok(())
}
@@ -706,7 +741,7 @@ pub async fn set_output_muted(muted: bool) -> Result<(), BridgeError> {
runtime()
.spawn(async move { session().set_self_muted(None, Some(muted)).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("set_output_muted", e))??;
Ok(())
}
@@ -717,7 +752,7 @@ pub async fn set_output_gain(gain: f32) -> Result<(), BridgeError> {
runtime()
.spawn(async move { session().set_output_gain(gain).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("set_output_gain", e))??;
Ok(())
}
@@ -790,7 +825,7 @@ pub async fn init_storage(dir: String) -> Result<(), BridgeError> {
runtime()
.spawn(async move { session().init_storage(&dir).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("init_storage", e))??;
Ok(())
}
@@ -843,7 +878,7 @@ pub async fn list_bookmarks() -> Result<Vec<BridgeBookmark>, BridgeError> {
let v = runtime()
.spawn(async { session().list_bookmarks().await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("list_bookmarks", e))??;
Ok(v.into_iter().map(Into::into).collect())
}
@@ -854,7 +889,7 @@ pub async fn add_bookmark(b: BridgeBookmark) -> Result<i64, BridgeError> {
let id = runtime()
.spawn(async move { session().add_bookmark(core_b).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("add_bookmark", e))??;
Ok(id)
}
@@ -864,7 +899,7 @@ pub async fn update_bookmark(b: BridgeBookmark) -> Result<(), BridgeError> {
runtime()
.spawn(async move { session().update_bookmark(core_b).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("update_bookmark", e))??;
Ok(())
}
@@ -873,7 +908,7 @@ pub async fn delete_bookmark(id: i64) -> Result<(), BridgeError> {
runtime()
.spawn(async move { session().delete_bookmark(id).await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("delete_bookmark", e))??;
Ok(())
}
@@ -1273,7 +1308,7 @@ pub async fn audio_stats() -> Result<BridgeAudioStats, BridgeError> {
let (s, r, p) = runtime()
.spawn(async { session().audio_stats().await })
.await
.map_err(|e| BridgeError::Unmapped(format!("join: {e}")))??;
.map_err(|e| task_join_error("audio_stats", e))??;
Ok(BridgeAudioStats {
frames_sent: s,
frames_received: r,