Skip to content

Commit 65dd28d

Browse files
authored
voice - add a new action to stop and accept voice input (microsoft#191802)
1 parent 8813aca commit 65dd28d

File tree

1 file changed

+65
-22
lines changed

1 file changed

+65
-22
lines changed

src/vs/workbench/contrib/chat/electron-sandbox/actions/voiceChatActions.ts

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -160,21 +160,26 @@ class VoiceChatSessionControllerFactory {
160160
}
161161
}
162162

163-
class VoiceChatSession {
163+
interface ActiveVoiceChatSession {
164+
readonly controller: IVoiceChatSessionController;
165+
readonly disposables: DisposableStore;
166+
}
167+
168+
class VoiceChatSessions {
164169

165-
private static instance: VoiceChatSession | undefined = undefined;
166-
static getInstance(instantiationService: IInstantiationService): VoiceChatSession {
167-
if (!VoiceChatSession.instance) {
168-
VoiceChatSession.instance = instantiationService.createInstance(VoiceChatSession);
170+
private static instance: VoiceChatSessions | undefined = undefined;
171+
static getInstance(instantiationService: IInstantiationService): VoiceChatSessions {
172+
if (!VoiceChatSessions.instance) {
173+
VoiceChatSessions.instance = instantiationService.createInstance(VoiceChatSessions);
169174
}
170175

171-
return VoiceChatSession.instance;
176+
return VoiceChatSessions.instance;
172177
}
173178

174179
private voiceChatInProgressKey = CONTEXT_VOICE_CHAT_IN_PROGRESS.bindTo(this.contextKeyService);
175180
private voiceChatGettingReadyKey = CONTEXT_VOICE_CHAT_GETTING_READY.bindTo(this.contextKeyService);
176181

177-
private currentVoiceChatSession: DisposableStore | undefined = undefined;
182+
private currentVoiceChatSession: ActiveVoiceChatSession | undefined = undefined;
178183
private voiceChatSessionIds = 0;
179184

180185
constructor(
@@ -186,14 +191,18 @@ class VoiceChatSession {
186191
this.stop();
187192

188193
const voiceChatSessionId = ++this.voiceChatSessionIds;
189-
this.currentVoiceChatSession = new DisposableStore();
194+
this.currentVoiceChatSession = {
195+
controller,
196+
disposables: new DisposableStore()
197+
};
190198

191199
const cts = new CancellationTokenSource();
192-
this.currentVoiceChatSession.add(toDisposable(() => cts.dispose(true)));
200+
this.currentVoiceChatSession.disposables.add(toDisposable(() => cts.dispose(true)));
193201

194-
this.currentVoiceChatSession.add(controller.onDidAcceptInput(() => this.stop(voiceChatSessionId)));
195-
this.currentVoiceChatSession.add(controller.onDidCancelInput(() => this.stop(voiceChatSessionId)));
202+
this.currentVoiceChatSession.disposables.add(controller.onDidAcceptInput(() => this.stop(voiceChatSessionId)));
203+
this.currentVoiceChatSession.disposables.add(controller.onDidCancelInput(() => this.stop(voiceChatSessionId)));
196204

205+
controller.updateInput('');
197206
controller.focusInput();
198207

199208
this.voiceChatGettingReadyKey.set(true);
@@ -209,14 +218,14 @@ class VoiceChatSession {
209218
this.voiceChatGettingReadyKey.set(false);
210219
this.voiceChatInProgressKey.set(true);
211220

212-
this.registerTranscriptionListener(controller, onDidTranscribe, this.currentVoiceChatSession);
221+
this.registerTranscriptionListener(this.currentVoiceChatSession, onDidTranscribe);
213222
}
214223

215-
private registerTranscriptionListener(controller: IVoiceChatSessionController, onDidTranscribe: Event<string>, disposables: DisposableStore) {
224+
private registerTranscriptionListener(session: ActiveVoiceChatSession, onDidTranscribe: Event<string>) {
216225
let lastText: string | undefined = undefined;
217226
let lastTextSimilarCount = 0;
218227

219-
disposables.add(onDidTranscribe(text => {
228+
session.disposables.add(onDidTranscribe(text => {
220229
if (!text && lastText) {
221230
text = lastText;
222231
}
@@ -230,9 +239,9 @@ class VoiceChatSession {
230239
}
231240

232241
if (lastTextSimilarCount >= 2) {
233-
controller.acceptInput();
242+
session.controller.acceptInput();
234243
} else {
235-
controller.updateInput(text);
244+
session.controller.updateInput(text);
236245
}
237246

238247
}
@@ -261,12 +270,23 @@ class VoiceChatSession {
261270
return;
262271
}
263272

264-
this.currentVoiceChatSession.dispose();
273+
this.currentVoiceChatSession.disposables.dispose();
265274
this.currentVoiceChatSession = undefined;
266275

267276
this.voiceChatGettingReadyKey.set(false);
268277
this.voiceChatInProgressKey.set(false);
269278
}
279+
280+
accept(voiceChatSessionId = this.voiceChatSessionIds): void {
281+
if (
282+
!this.currentVoiceChatSession ||
283+
this.voiceChatSessionIds !== voiceChatSessionId
284+
) {
285+
return;
286+
}
287+
288+
this.currentVoiceChatSession.controller.acceptInput();
289+
}
270290
}
271291

272292
class VoiceChatInChatViewAction extends Action2 {
@@ -291,7 +311,7 @@ class VoiceChatInChatViewAction extends Action2 {
291311

292312
const controller = await VoiceChatSessionControllerFactory.create(accessor, 'view');
293313
if (controller) {
294-
VoiceChatSession.getInstance(instantiationService).start(controller);
314+
VoiceChatSessions.getInstance(instantiationService).start(controller);
295315
}
296316
}
297317
}
@@ -318,7 +338,7 @@ class InlineVoiceChatAction extends Action2 {
318338

319339
const controller = await VoiceChatSessionControllerFactory.create(accessor, 'inline');
320340
if (controller) {
321-
VoiceChatSession.getInstance(instantiationService).start(controller);
341+
VoiceChatSessions.getInstance(instantiationService).start(controller);
322342
}
323343
}
324344
}
@@ -345,7 +365,7 @@ class QuickVoiceChatAction extends Action2 {
345365

346366
const controller = await VoiceChatSessionControllerFactory.create(accessor, 'quick');
347367
if (controller) {
348-
VoiceChatSession.getInstance(instantiationService).start(controller);
368+
VoiceChatSessions.getInstance(instantiationService).start(controller);
349369
}
350370
}
351371
}
@@ -391,7 +411,7 @@ class StartVoiceChatAction extends Action2 {
391411

392412
const controller = await VoiceChatSessionControllerFactory.create(accessor, 'focussed');
393413
if (controller) {
394-
VoiceChatSession.getInstance(instantiationService).start(controller);
414+
VoiceChatSessions.getInstance(instantiationService).start(controller);
395415
} else {
396416
// fallback to Quick Voice Chat command
397417
commandService.executeCommand(QuickVoiceChatAction.ID);
@@ -434,7 +454,29 @@ class StopVoiceChatAction extends Action2 {
434454
}
435455

436456
run(accessor: ServicesAccessor): void {
437-
VoiceChatSession.getInstance(accessor.get(IInstantiationService)).stop();
457+
VoiceChatSessions.getInstance(accessor.get(IInstantiationService)).stop();
458+
}
459+
}
460+
461+
class StopVoiceChatAndSubmitAction extends Action2 {
462+
463+
static readonly ID = 'workbench.action.chat.stopVoiceChatAndSubmit';
464+
465+
constructor() {
466+
super({
467+
id: StopVoiceChatAndSubmitAction.ID,
468+
title: {
469+
value: localize('workbench.action.chat.stopAndAcceptVoiceChat.label', "Stop Voice Chat and Submit"),
470+
original: 'Stop Voice Chat and Submit'
471+
},
472+
category: CHAT_CATEGORY,
473+
f1: true,
474+
precondition: CONTEXT_VOICE_CHAT_IN_PROGRESS
475+
});
476+
}
477+
478+
run(accessor: ServicesAccessor): void {
479+
VoiceChatSessions.getInstance(accessor.get(IInstantiationService)).accept();
438480
}
439481
}
440482

@@ -446,5 +488,6 @@ export function registerVoiceChatActions() {
446488

447489
registerAction2(StartVoiceChatAction);
448490
registerAction2(StopVoiceChatAction);
491+
registerAction2(StopVoiceChatAndSubmitAction);
449492
}
450493
}

0 commit comments

Comments
 (0)