Skip to content

Commit c318de6

Browse files
committed
Fix dictation startup races and migrate tap defaults
What changed: - treat an in-flight dictation start as stoppable so a rapid second tap queues a stop instead of being ignored - preserve the requested stop mode through the before-start stop path and clear pending mode state on cancel/cleanup - migrate dictation toggle and auto-send preferences to v2 storage keys so devices with legacy values pick up the new tap-to-toggle defaults - extend manual verification steps with rapid-tap and touch-viewport coverage Why: - PR #48 received review feedback about startup race conditions in useDictation - phones with previously saved dictation settings could stay on hold-to-talk even after switching the product default to tap-to-toggle Impact: - desktop and mobile dictation now follow the same tap-to-toggle flow by default - rapid double taps during recorder startup stop and transcribe instead of leaving recording running Validation: - pnpm run build - Playwright verification on 375x812 and 768x1024, including legacy-pref mobile load and rapid second-tap startup handling
1 parent ce3ee23 commit c318de6

3 files changed

Lines changed: 18 additions & 8 deletions

File tree

src/App.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,8 +1003,8 @@ const accountActionError = ref('')
10031003
const SEND_WITH_ENTER_KEY = 'codex-web-local.send-with-enter.v1'
10041004
const IN_PROGRESS_SEND_MODE_KEY = 'codex-web-local.in-progress-send-mode.v1'
10051005
const DARK_MODE_KEY = 'codex-web-local.dark-mode.v1'
1006-
const DICTATION_CLICK_TO_TOGGLE_KEY = 'codex-web-local.dictation-click-to-toggle.v1'
1007-
const DICTATION_AUTO_SEND_KEY = 'codex-web-local.dictation-auto-send.v1'
1006+
const DICTATION_CLICK_TO_TOGGLE_KEY = 'codex-web-local.dictation-click-to-toggle.v2'
1007+
const DICTATION_AUTO_SEND_KEY = 'codex-web-local.dictation-auto-send.v2'
10081008
const DICTATION_LANGUAGE_KEY = 'codex-web-local.dictation-language.v1'
10091009
10101010
const GITHUB_TRENDING_PROJECTS_KEY = 'codex-web-local.github-trending-projects.v1'

src/composables/useDictation.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ export function useDictation(options: {
151151
if (state.value !== 'idle' || !isSupported.value || isStartingRecording) return
152152
isStartingRecording = true
153153
stopRequestedBeforeStart = false
154+
pendingStopMode = 'insert'
154155

155156
try {
156157
mediaStream = await navigator.mediaDevices.getUserMedia({ audio: { channelCount: 1 } })
@@ -171,10 +172,13 @@ export function useDictation(options: {
171172
mediaRecorder.start(250)
172173
state.value = 'recording'
173174
if (stopRequestedBeforeStart) {
174-
stopRecording()
175+
const stopMode = pendingStopMode
176+
stopRequestedBeforeStart = false
177+
stopRecording(stopMode)
175178
}
176179
} catch (error) {
177180
cleanup()
181+
stopRequestedBeforeStart = false
178182
state.value = 'idle'
179183
options.onError?.(error)
180184
} finally {
@@ -203,6 +207,7 @@ export function useDictation(options: {
203207

204208
function cancel() {
205209
stopRequestedBeforeStart = false
210+
pendingStopMode = 'insert'
206211
cancelTranscription()
207212
cleanup()
208213
state.value = 'idle'
@@ -274,6 +279,7 @@ export function useDictation(options: {
274279
function cleanup() {
275280
stopWaveformCapture()
276281
resetWaveformDisplay()
282+
pendingStopMode = 'insert'
277283
if (mediaRecorder) {
278284
mediaRecorder.ondataavailable = null
279285
mediaRecorder.onstop = null
@@ -291,7 +297,7 @@ export function useDictation(options: {
291297
})
292298

293299
function toggleRecording() {
294-
if (state.value === 'recording') {
300+
if (state.value === 'recording' || (isStartingRecording && state.value === 'idle')) {
295301
stopRecording()
296302
return
297303
}

tests.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,17 +2242,21 @@ Toggle "Free mode" in settings to use free OpenRouter models without an OpenAI A
22422242

22432243
#### Steps
22442244
1. Open Settings and confirm `Click to toggle dictation` is enabled by default and `Auto send dictation` is disabled by default.
2245-
2. In the composer, click the microphone once and verify recording starts without holding the button.
2245+
2. On desktop, click the microphone once and verify recording starts without holding the button.
22462246
3. Speak a short phrase, then click the microphone again to stop recording.
2247-
4. While transcription is processing, confirm the microphone button shows a loading spinner.
2248-
5. Confirm the transcript is inserted into the composer without being auto-sent.
2249-
6. Start dictation again, speak another short phrase, and click the send arrow instead of the microphone stop button.
2247+
4. Start dictation again and immediately click the microphone a second time before the recorder fully starts.
2248+
5. While transcription is processing, confirm the microphone button shows a loading spinner.
2249+
6. Confirm the transcript is inserted into the composer without being auto-sent.
2250+
7. Start dictation again, speak another short phrase, and click the send arrow instead of the microphone stop button.
2251+
8. Repeat steps 1-7 in a touch viewport or on a phone and verify a tap starts recording and the next tap stops it without requiring a press-and-hold.
22502252

22512253
#### Expected Results
22522254
- Dictation starts on first click and keeps recording hands-free until the next click.
2255+
- A rapid second tap during startup still queues a stop request instead of leaving recording running.
22532256
- Stopping with the microphone inserts the transcript into the composer and leaves it editable.
22542257
- The microphone shows a transcribing spinner while `/codex-api/transcribe` is still in progress.
22552258
- Clicking the send arrow during recording transcribes the audio and submits the message automatically.
2259+
- Devices with previously saved dictation preferences pick up the new tap-to-toggle default after the preference-key migration.
22562260

22572261
#### Rollback/Cleanup
22582262
- Clear the draft or delete the test thread message if needed.

0 commit comments

Comments
 (0)