feat: add mic mute button with visual state
This commit is contained in:
+21
@@ -39,6 +39,8 @@ let wakeLock = null;
|
||||
// ── DOM ─────────────────────────────────────────────────────────────────────
|
||||
const startBtn = document.getElementById("startBtn");
|
||||
const stopBtn = document.getElementById("stopBtn");
|
||||
const muteBtn = document.getElementById("muteBtn");
|
||||
let micMuted = false;
|
||||
const statusEl = document.getElementById("status");
|
||||
const messagesEl = document.getElementById("messages");
|
||||
const orbEl = document.getElementById("orb");
|
||||
@@ -600,6 +602,8 @@ startBtn.addEventListener("click", async () => {
|
||||
statusEl.textContent = "Connected — speak now";
|
||||
startBtn.disabled = true;
|
||||
stopBtn.disabled = false;
|
||||
muteBtn.disabled = false;
|
||||
micMuted = false;
|
||||
|
||||
setupMicAnalyser();
|
||||
startVisualLoop();
|
||||
@@ -627,8 +631,25 @@ stopBtn.addEventListener("click", () => {
|
||||
setState("idle");
|
||||
startBtn.disabled = false;
|
||||
stopBtn.disabled = true;
|
||||
muteBtn.disabled = true;
|
||||
micMuted = false;
|
||||
updateMuteIcon();
|
||||
});
|
||||
|
||||
// ── Mic mute toggle ─────────────────────────────────────────────────────────
|
||||
muteBtn.addEventListener("click", async () => {
|
||||
if (!room || !room.localParticipant) return;
|
||||
micMuted = !micMuted;
|
||||
await room.localParticipant.setMicrophoneEnabled(!micMuted);
|
||||
updateMuteIcon();
|
||||
});
|
||||
|
||||
function updateMuteIcon() {
|
||||
const muted = muteBtn.classList.toggle("muted", micMuted);
|
||||
muteBtn.setAttribute("aria-label", muted ? "Unmute microphone" : "Mute microphone");
|
||||
muteBtn.title = muted ? "Unmute microphone" : "Mute microphone";
|
||||
}
|
||||
|
||||
// ── Helper: fetch a signed access token from the token endpoint ────────────
|
||||
async function fetchToken(roomName) {
|
||||
const resp = await fetch("/token", {
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
<div class="controls">
|
||||
<button id="startBtn" class="btn btn-primary">Start Conversation</button>
|
||||
<button id="stopBtn" class="btn btn-danger" disabled>Stop</button>
|
||||
<button id="muteBtn" class="btn btn-icon" aria-label="Mute microphone" title="Mute microphone" disabled>
|
||||
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"></path><path d="M19 10v2a7 7 0 0 1-14 0v-2"></path><line x1="8" y1="22" x2="16" y2="22"></line></svg>
|
||||
</button>
|
||||
<button id="settingsBtn" class="btn btn-icon" aria-label="Voice settings" title="Voice settings">
|
||||
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
</button>
|
||||
|
||||
@@ -243,6 +243,12 @@ h1 {
|
||||
background: var(--panel-strong);
|
||||
}
|
||||
|
||||
.btn-icon.muted {
|
||||
color: #ef4444;
|
||||
border-color: #ef4444;
|
||||
background: rgba(239, 68, 68, 0.1);
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
background: transparent;
|
||||
color: var(--text-faint);
|
||||
|
||||
Reference in New Issue
Block a user