This commit is contained in:
1 parent
b1643b635d
commit
1fffed8ab3
1 file changed
+32
-8
+32
-8
@@ -162,6 +162,9 @@ function updateModeUI() {
|
|||||||
if (isText) {
|
if (isText) {
|
||||||
setState(room ? "listening" : "idle");
|
setState(room ? "listening" : "idle");
|
||||||
window.setTimeout(() => chatInput.focus(), 0);
|
window.setTimeout(() => chatInput.focus(), 0);
|
||||||
|
} else {
|
||||||
|
// Refresh mode-specific copy even when the underlying state is unchanged.
|
||||||
|
setState(uiState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,19 +191,28 @@ async function setConversationMode(mode) {
|
|||||||
stopVisualLoop();
|
stopVisualLoop();
|
||||||
statusEl.textContent = "Secure room · Text mode";
|
statusEl.textContent = "Secure room · Text mode";
|
||||||
} else {
|
} else {
|
||||||
await room.startAudio();
|
|
||||||
await room.localParticipant.setMicrophoneEnabled(true);
|
|
||||||
micMuted = false;
|
micMuted = false;
|
||||||
muteBtn.disabled = false;
|
muteBtn.disabled = false;
|
||||||
updateMuteIcon();
|
updateMuteIcon();
|
||||||
setupMicAnalyser();
|
|
||||||
startVisualLoop();
|
startVisualLoop();
|
||||||
|
try {
|
||||||
|
await room.startAudio();
|
||||||
|
await room.localParticipant.setMicrophoneEnabled(true);
|
||||||
|
setupMicAnalyser();
|
||||||
statusEl.textContent = "Secure room · Microphone on";
|
statusEl.textContent = "Secure room · Microphone on";
|
||||||
|
} catch (err) {
|
||||||
|
// Keep the conversation usable even if this browser denies or does
|
||||||
|
// not implement microphone capture. The mute control can retry.
|
||||||
|
console.warn("Microphone could not be enabled:", err);
|
||||||
|
micMuted = true;
|
||||||
|
updateMuteIcon();
|
||||||
|
statusEl.textContent = "Voice mode · Microphone unavailable";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
voiceModeBtn.addEventListener("click", () => setConversationMode("voice"));
|
voiceModeBtn.addEventListener("click", () => setConversationMode("voice").catch(console.error));
|
||||||
textModeBtn.addEventListener("click", () => setConversationMode("text"));
|
textModeBtn.addEventListener("click", () => setConversationMode("text").catch(console.error));
|
||||||
|
|
||||||
// ── Audio analysers (mic + remote agent audio) ─────────────────────────────
|
// ── Audio analysers (mic + remote agent audio) ─────────────────────────────
|
||||||
let micCtx = null;
|
let micCtx = null;
|
||||||
@@ -523,9 +535,15 @@ function handleDataPacket(payload, participant, topic) {
|
|||||||
agentReady = true;
|
agentReady = true;
|
||||||
} else if (msg.type === "transcript") {
|
} else if (msg.type === "transcript") {
|
||||||
addMessage(msg.role || "agent", msg.text);
|
addMessage(msg.role || "agent", msg.text);
|
||||||
if (conversationMode === "text" && (msg.role || "agent") === "agent") {
|
if ((msg.role || "agent") === "agent") {
|
||||||
|
if (conversationMode === "text") {
|
||||||
setState("listening");
|
setState("listening");
|
||||||
chatInput.focus();
|
chatInput.focus();
|
||||||
|
} else if (uiState === "thinking") {
|
||||||
|
// Text arrives even when headless playback or an analyser is
|
||||||
|
// unavailable; use it to release the thinking state.
|
||||||
|
setState("speaking");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (msg.type === "task_event") {
|
} else if (msg.type === "task_event") {
|
||||||
handleTaskEvent(msg);
|
handleTaskEvent(msg);
|
||||||
@@ -913,9 +931,15 @@ stopBtn.addEventListener("click", () => {
|
|||||||
// ── Mic mute toggle ─────────────────────────────────────────────────────────
|
// ── Mic mute toggle ─────────────────────────────────────────────────────────
|
||||||
muteBtn.addEventListener("click", async () => {
|
muteBtn.addEventListener("click", async () => {
|
||||||
if (!room || !room.localParticipant) return;
|
if (!room || !room.localParticipant) return;
|
||||||
micMuted = !micMuted;
|
const nextMuted = !micMuted;
|
||||||
await room.localParticipant.setMicrophoneEnabled(!micMuted);
|
try {
|
||||||
|
await room.localParticipant.setMicrophoneEnabled(!nextMuted);
|
||||||
|
micMuted = nextMuted;
|
||||||
updateMuteIcon();
|
updateMuteIcon();
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("Microphone toggle failed:", err);
|
||||||
|
statusEl.textContent = "Microphone unavailable in this browser";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function updateMuteIcon() {
|
function updateMuteIcon() {
|
||||||
|
|||||||
Reference in new issue
Block a user