fix: blocking_lock panic in status(), fingerprint copy-to-clipboard
Some checks failed
Build Release Binaries / build-amd64 (push) Failing after 3m13s

- Change status() from blocking_lock to async lock().await —
  fixes "Cannot block the current thread from within a runtime" panic
  that froze the call timer and broke audio
- Click fingerprint to copy to clipboard (both connect and settings screens)
- Show "Copied!" feedback on click

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-04-06 11:53:31 +04:00
parent 80d5bd7628
commit 9b733010ab
3 changed files with 37 additions and 3 deletions

View File

@@ -333,8 +333,8 @@ impl CallEngine {
!was !was
} }
pub fn status(&self) -> EngineStatus { pub async fn status(&self) -> EngineStatus {
let parts = self.participants.blocking_lock(); let parts = self.participants.lock().await;
EngineStatus { EngineStatus {
mic_muted: self.mic_muted.load(Ordering::Relaxed), mic_muted: self.mic_muted.load(Ordering::Relaxed),
spk_muted: self.spk_muted.load(Ordering::Relaxed), spk_muted: self.spk_muted.load(Ordering::Relaxed),

View File

@@ -108,7 +108,7 @@ async fn toggle_speaker(state: tauri::State<'_, Arc<AppState>>) -> Result<bool,
async fn get_status(state: tauri::State<'_, Arc<AppState>>) -> Result<CallStatus, String> { async fn get_status(state: tauri::State<'_, Arc<AppState>>) -> Result<CallStatus, String> {
let engine_lock = state.engine.lock().await; let engine_lock = state.engine.lock().await;
if let Some(ref engine) = *engine_lock { if let Some(ref engine) = *engine_lock {
let status = engine.status(); let status = engine.status().await;
Ok(CallStatus { Ok(CallStatus {
active: true, active: true,
mic_muted: status.mic_muted, mic_muted: status.mic_muted,

View File

@@ -108,6 +108,29 @@ function renderRecentRooms(rooms: string[]) {
applySettings(); applySettings();
// Click fingerprint to copy
myFingerprintEl.addEventListener("click", () => {
if (myFingerprint) {
navigator.clipboard.writeText(myFingerprint).then(() => {
const orig = myFingerprintEl.textContent;
myFingerprintEl.textContent = "Copied!";
setTimeout(() => { myFingerprintEl.textContent = orig; }, 1000);
});
}
});
myFingerprintEl.style.cursor = "pointer";
sFingerprint.addEventListener("click", () => {
if (myFingerprint) {
navigator.clipboard.writeText(myFingerprint).then(() => {
const orig = sFingerprint.textContent;
sFingerprint.textContent = "Copied!";
setTimeout(() => { sFingerprint.textContent = orig; }, 1000);
});
}
});
sFingerprint.style.cursor = "pointer";
// ── Connect ── // ── Connect ──
connectBtn.addEventListener("click", doConnect); connectBtn.addEventListener("click", doConnect);
// Enter key to connect // Enter key to connect
@@ -277,6 +300,17 @@ listen("call-event", (event: any) => {
}); });
// ── Settings panel ── // ── Settings panel ──
// Load fingerprint into settings when status is available
async function refreshFingerprint() {
try {
const st: CallStatus = await invoke("get_status");
if (st.fingerprint) {
myFingerprint = st.fingerprint;
myFingerprintEl.textContent = `ID: ${st.fingerprint}`;
}
} catch {}
}
function openSettings() { function openSettings() {
const s = loadSettings(); const s = loadSettings();
sRelay.value = s.relay; sRelay.value = s.relay;