Skip to content

Commit d4bac00

Browse files
authored
report progress to screen reader users (microsoft#210589)
1 parent 7524e9d commit d4bac00

File tree

5 files changed

+41
-6
lines changed

5 files changed

+41
-6
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { IDisposable } from 'vs/base/common/lifecycle';
7+
8+
export interface IScopedAccessibilityProgressSignalDelegate extends IDisposable { }
9+
10+
const nullScopedAccessibilityProgressSignalFactory = () => ({
11+
msLoopTime: -1,
12+
msDelayTime: -1,
13+
dispose: () => { },
14+
});
15+
let progressAccessibilitySignalSchedulerFactory: (msDelayTime: number, msLoopTime?: number) => IScopedAccessibilityProgressSignalDelegate = nullScopedAccessibilityProgressSignalFactory;
16+
17+
export function setProgressAcccessibilitySignalScheduler(progressAccessibilitySignalScheduler: (msDelayTime: number, msLoopTime?: number) => IScopedAccessibilityProgressSignalDelegate) {
18+
progressAccessibilitySignalSchedulerFactory = progressAccessibilitySignalScheduler;
19+
}
20+
21+
export function getProgressAcccessibilitySignalScheduler(msDelayTime: number, msLoopTime?: number): IScopedAccessibilityProgressSignalDelegate {
22+
return progressAccessibilitySignalSchedulerFactory(msDelayTime, msLoopTime);
23+
}

src/vs/base/browser/ui/progressbar/progressbar.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { hide, show } from 'vs/base/browser/dom';
7+
import { getProgressAcccessibilitySignalScheduler } from 'vs/base/browser/ui/progressbar/progressAccessibilitySignal';
78
import { RunOnceScheduler } from 'vs/base/common/async';
8-
import { Disposable } from 'vs/base/common/lifecycle';
9+
import { Disposable, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
910
import { isNumber } from 'vs/base/common/types';
1011
import 'vs/css!./progressbar';
1112

@@ -41,12 +42,15 @@ export class ProgressBar extends Disposable {
4142
*/
4243
private static readonly LONG_RUNNING_INFINITE_THRESHOLD = 10000;
4344

45+
private static readonly PROGRESS_SIGNAL_DEFAULT_DELAY = 3000;
46+
4447
private workedVal: number;
4548
private element!: HTMLElement;
4649
private bit!: HTMLElement;
4750
private totalWork: number | undefined;
4851
private showDelayedScheduler: RunOnceScheduler;
4952
private longRunningScheduler: RunOnceScheduler;
53+
private readonly progressSignal = this._register(new MutableDisposable<IDisposable>());
5054

5155
constructor(container: HTMLElement, options?: IProgressBarOptions) {
5256
super();
@@ -81,6 +85,7 @@ export class ProgressBar extends Disposable {
8185
this.totalWork = undefined;
8286

8387
this.longRunningScheduler.cancel();
88+
this.progressSignal.clear();
8489
}
8590

8691
/**
@@ -201,6 +206,7 @@ export class ProgressBar extends Disposable {
201206

202207
show(delay?: number): void {
203208
this.showDelayedScheduler.cancel();
209+
this.progressSignal.value = getProgressAcccessibilitySignalScheduler(ProgressBar.PROGRESS_SIGNAL_DEFAULT_DELAY);
204210

205211
if (typeof delay === 'number') {
206212
this.showDelayedScheduler.schedule(delay);
@@ -211,6 +217,8 @@ export class ProgressBar extends Disposable {
211217

212218
hide(): void {
213219
hide(this.element);
220+
214221
this.showDelayedScheduler.cancel();
222+
this.progressSignal.clear();
215223
}
216224
}

src/vs/platform/accessibilitySignal/browser/progressAccessibilitySignalScheduler.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@ import { RunOnceScheduler } from 'vs/base/common/async';
77
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
88
import { AccessibilitySignal, IAccessibilitySignalService } from 'vs/platform/accessibilitySignal/browser/accessibilitySignalService';
99

10+
const PROGRESS_SIGNAL_LOOP_DELAY = 5000;
11+
1012
/**
1113
* Schedules a signal to play while progress is happening.
1214
*/
1315
export class AccessibilityProgressSignalScheduler extends Disposable {
1416
private _scheduler: RunOnceScheduler;
1517
private _signalLoop: IDisposable | undefined;
16-
constructor(msLoopTime: number, msDelayTime: number, @IAccessibilitySignalService private readonly _accessibilitySignalService: IAccessibilitySignalService) {
18+
constructor(msDelayTime: number, msLoopTime: number | undefined, @IAccessibilitySignalService private readonly _accessibilitySignalService: IAccessibilitySignalService) {
1719
super();
1820
this._scheduler = new RunOnceScheduler(() => {
19-
this._signalLoop = this._accessibilitySignalService.playSignalLoop(AccessibilitySignal.chatResponsePending, msLoopTime);
21+
this._signalLoop = this._accessibilitySignalService.playSignalLoop(AccessibilitySignal.chatResponsePending, msLoopTime ?? PROGRESS_SIGNAL_LOOP_DELAY);
2022
}, msDelayTime);
2123
this._scheduler.schedule();
2224
}

src/vs/workbench/browser/workbench.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ import { PixelRatio } from 'vs/base/browser/pixelRatio';
4646
import { IHoverService, WorkbenchHoverDelegate } from 'vs/platform/hover/browser/hover';
4747
import { setHoverDelegateFactory } from 'vs/base/browser/ui/hover/hoverDelegateFactory';
4848
import { setBaseLayerHoverDelegate } from 'vs/base/browser/ui/hover/hoverDelegate2';
49+
import { AccessibilityProgressSignalScheduler } from 'vs/platform/accessibilitySignal/browser/progressAccessibilitySignalScheduler';
50+
import { setProgressAcccessibilitySignalScheduler } from 'vs/base/browser/ui/progressbar/progressAccessibilitySignal';
4951

5052
export interface IWorkbenchOptions {
5153

@@ -327,8 +329,9 @@ export class Workbench extends Layout {
327329

328330
private renderWorkbench(instantiationService: IInstantiationService, notificationService: NotificationService, storageService: IStorageService, configurationService: IConfigurationService): void {
329331

330-
// ARIA
332+
// ARIA & Signals
331333
setARIAContainer(this.mainContainer);
334+
setProgressAcccessibilitySignalScheduler((msDelayTime: number, msLoopTime?: number) => instantiationService.createInstance(AccessibilityProgressSignalScheduler, msDelayTime, msLoopTime));
332335

333336
// State specific classes
334337
const platformClass = isWindows ? 'windows' : isLinux ? 'linux' : 'mac';

src/vs/workbench/contrib/chat/browser/chatAccessibilityService.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { AccessibilityProgressSignalScheduler } from 'vs/platform/accessibilityS
1111
import { IChatAccessibilityService } from 'vs/workbench/contrib/chat/browser/chat';
1212
import { IChatResponseViewModel } from 'vs/workbench/contrib/chat/common/chatViewModel';
1313

14-
const CHAT_RESPONSE_PENDING_AUDIO_CUE_LOOP_MS = 5000;
1514
const CHAT_RESPONSE_PENDING_ALLOWANCE_MS = 4000;
1615
export class ChatAccessibilityService extends Disposable implements IChatAccessibilityService {
1716

@@ -27,7 +26,7 @@ export class ChatAccessibilityService extends Disposable implements IChatAccessi
2726
acceptRequest(): number {
2827
this._requestId++;
2928
this._accessibilitySignalService.playSignal(AccessibilitySignal.chatRequestSent, { allowManyInParallel: true });
30-
this._pendingSignalMap.set(this._requestId, this._instantiationService.createInstance(AccessibilityProgressSignalScheduler, CHAT_RESPONSE_PENDING_AUDIO_CUE_LOOP_MS, CHAT_RESPONSE_PENDING_ALLOWANCE_MS));
29+
this._pendingSignalMap.set(this._requestId, this._instantiationService.createInstance(AccessibilityProgressSignalScheduler, CHAT_RESPONSE_PENDING_ALLOWANCE_MS, undefined));
3130
return this._requestId;
3231
}
3332
acceptResponse(response: IChatResponseViewModel | string | undefined, requestId: number): void {

0 commit comments

Comments
 (0)