annotate dictation/web/dictation.js @ 279:b3b547563ec7

Add Google connector service and agent wiki Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code. Co-authored-by: Copilot <[email protected]> Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
author MrJuneJune <me@mrjunejune.com>
date Mon, 17 Aug 2026 22:22:36 -0700
parents 78699f810817
children 49e9e591c9bb
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
275
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1 const startButton = document.querySelector("[data-start]");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2 const stopButton = document.querySelector("[data-stop]");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
3 const status = document.querySelector("[data-status]");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
4 const partial = document.querySelector("[data-partial]");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
5 const finalText = document.querySelector("[data-final]");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
6
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
7 let peer = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
8 let channel = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
9 let stream = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
10 let sessionId = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
11 let stopResolver = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
12
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
13 function setStatus(message, state = "") {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
14 status.textContent = message;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
15 status.dataset.state = state;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
16 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
17
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
18 function waitForIceGathering(connection) {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
19 if (connection.iceGatheringState === "complete") return Promise.resolve();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
20 return new Promise(resolve => {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
21 const listener = () => {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
22 if (connection.iceGatheringState !== "complete") return;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
23 connection.removeEventListener("icegatheringstatechange", listener);
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
24 resolve();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
25 };
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
26 connection.addEventListener("icegatheringstatechange", listener);
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
27 });
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
28 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
29
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
30 function handleTranscript(message) {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
31 let event;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
32 try {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
33 event = JSON.parse(message.data);
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
34 } catch {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
35 setStatus("Received an invalid server event", "error");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
36 return;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
37 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
38 switch (event.type) {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
39 case "ready":
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
40 setStatus("Listening", "ready");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
41 break;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
42 case "speech.started":
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
43 setStatus("Speech detected", "working");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
44 break;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
45 case "transcript.partial":
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
46 partial.textContent = event.text;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
47 break;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
48 case "transcript.final":
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
49 finalText.value += `${finalText.value ? " " : ""}${event.text}`;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
50 partial.textContent = "Waiting for speech...";
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
51 break;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
52 case "speech.ended":
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
53 setStatus("Listening", "ready");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
54 stopResolver?.();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
55 stopResolver = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
56 break;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
57 case "error":
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
58 setStatus(event.message || "Transcription failed", "error");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
59 break;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
60 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
61 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
62
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
63 async function start() {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
64 if (peer) return;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
65 startButton.disabled = true;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
66 setStatus("Requesting microphone access...", "working");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
67 try {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
68 stream = await navigator.mediaDevices.getUserMedia({
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
69 audio: {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
70 channelCount: 1,
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
71 echoCancellation: true,
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
72 noiseSuppression: true,
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
73 },
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
74 video: false,
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
75 });
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
76 peer = new RTCPeerConnection();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
77 channel = peer.createDataChannel("transcripts", { ordered: true });
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
78 channel.addEventListener("message", handleTranscript);
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
79 channel.addEventListener("close", () => {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
80 if (peer) setStatus("Transcript channel closed", "error");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
81 });
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
82 peer.addEventListener("connectionstatechange", () => {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
83 if (peer?.connectionState === "failed") {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
84 setStatus("WebRTC connection failed", "error");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
85 void stop();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
86 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
87 });
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
88 for (const track of stream.getTracks()) peer.addTrack(track, stream);
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
89
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
90 const offer = await peer.createOffer();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
91 await peer.setLocalDescription(offer);
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
92 await waitForIceGathering(peer);
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
93 const response = await fetch("/api/webrtc/offer", {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
94 method: "POST",
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
95 headers: { "Content-Type": "application/json" },
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
96 body: JSON.stringify(peer.localDescription),
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
97 });
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
98 if (!response.ok) {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
99 const detail = await response.text();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
100 throw new Error(`Signaling failed (${response.status}): ${detail}`);
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
101 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
102 const answer = await response.json();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
103 sessionId = answer.sessionId;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
104 await peer.setRemoteDescription({
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
105 sdp: answer.sdp,
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
106 type: answer.type,
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
107 });
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
108 stopButton.disabled = false;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
109 setStatus("Connecting...", "working");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
110 } catch (error) {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
111 setStatus(error.message || "Unable to start dictation", "error");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
112 await stop();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
113 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
114 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
115
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
116 async function stop(waitForFinal = true) {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
117 const closingSession = sessionId;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
118 sessionId = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
119 const tracks = stream?.getTracks() || [];
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
120 if (channel?.readyState === "open" && waitForFinal) {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
121 const ended = new Promise(resolve => {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
122 stopResolver = resolve;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
123 });
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
124 channel.send("stop");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
125 for (const track of tracks) track.enabled = false;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
126 await Promise.race([
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
127 ended,
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
128 new Promise(resolve => window.setTimeout(resolve, 10000)),
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
129 ]);
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
130 stopResolver = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
131 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
132 for (const track of tracks) track.stop();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
133 stream = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
134 channel?.close();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
135 channel = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
136 peer?.close();
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
137 peer = null;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
138 if (closingSession) {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
139 await fetch(`/api/webrtc/session/${encodeURIComponent(closingSession)}/close`, {
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
140 method: "POST",
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
141 keepalive: true,
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
142 }).catch(() => {});
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
143 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
144 startButton.disabled = false;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
145 stopButton.disabled = true;
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
146 setStatus("Idle");
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
147 }
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
148
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
149 startButton.addEventListener("click", () => void start());
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
150 stopButton.addEventListener("click", () => void stop());
78699f810817 Add Qwen3-VL and WebRTC dictation services
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
151 window.addEventListener("pagehide", () => void stop(false));