fix(app): keep dictation shortcuts responsive (#2268)
The composer mirrored dictation state in a second ref that could remain stale after the recording surface changed. Route shortcut decisions through the dictation lifecycle's synchronous state so finishing or rejecting a recording cannot leave Command-D latched.
This commit is contained in:
@@ -4,12 +4,40 @@ import {
|
||||
resolveComposerSurfacePresentation,
|
||||
runAlternateSendAction,
|
||||
runDefaultSendAction,
|
||||
runMessageInputKeyboardAction,
|
||||
stopRealtimeVoice,
|
||||
} from "./state";
|
||||
|
||||
const connected = { isConnected: true } as never;
|
||||
const disconnected = { isConnected: false } as never;
|
||||
|
||||
function createDictationKeyboard({ startsRecording }: { startsRecording: boolean }) {
|
||||
let isRecording = false;
|
||||
const actions: string[] = [];
|
||||
|
||||
return {
|
||||
actions,
|
||||
pressDictationShortcut: () =>
|
||||
runMessageInputKeyboardAction("dictation-toggle", {
|
||||
focusInput: () => undefined,
|
||||
isDictationRecording: () => isRecording,
|
||||
markTranscriptForSend: () => actions.push("send transcript"),
|
||||
startDictation: () => {
|
||||
actions.push("start");
|
||||
isRecording = startsRecording;
|
||||
},
|
||||
confirmDictation: () => {
|
||||
actions.push("confirm");
|
||||
isRecording = false;
|
||||
},
|
||||
cancelDictation: () => undefined,
|
||||
toggleRealtimeVoice: () => undefined,
|
||||
isRealtimeVoiceActive: false,
|
||||
toggleRealtimeVoiceMute: () => undefined,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
describe("composer surface presentation", () => {
|
||||
it("shows only the input when no voice overlay is active", () => {
|
||||
expect(resolveComposerSurfacePresentation(false)).toEqual({
|
||||
@@ -114,6 +142,27 @@ describe("computeCanStartDictation", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("dictation keyboard behavior", () => {
|
||||
it("starts dictation again after the previous dictation finishes", () => {
|
||||
const keyboard = createDictationKeyboard({ startsRecording: true });
|
||||
|
||||
keyboard.pressDictationShortcut();
|
||||
keyboard.pressDictationShortcut();
|
||||
keyboard.pressDictationShortcut();
|
||||
|
||||
expect(keyboard.actions).toEqual(["start", "send transcript", "confirm", "start"]);
|
||||
});
|
||||
|
||||
it("can retry when starting dictation does not enter the recording state", () => {
|
||||
const keyboard = createDictationKeyboard({ startsRecording: false });
|
||||
|
||||
keyboard.pressDictationShortcut();
|
||||
keyboard.pressDictationShortcut();
|
||||
|
||||
expect(keyboard.actions).toEqual(["start", "start"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("composer send behavior", () => {
|
||||
function actions() {
|
||||
const calls: string[] = [];
|
||||
|
||||
Reference in New Issue
Block a user