mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 04:49:35 +00:00
support screen reader reading the line when go to next/previous diff are used (#170985)
This commit is contained in:
parent
2fae780e49
commit
c717e011fa
|
@ -466,6 +466,10 @@ export class TextAreaHandler extends ViewPart {
|
|||
}));
|
||||
}
|
||||
|
||||
public writeScreenReaderContent(reason: string): void {
|
||||
this._textAreaInput.writeScreenReaderContent(reason);
|
||||
}
|
||||
|
||||
public override dispose(): void {
|
||||
super.dispose();
|
||||
}
|
||||
|
|
|
@ -929,6 +929,11 @@ export interface ICodeEditor extends editorCommon.IEditor {
|
|||
*/
|
||||
setAriaOptions(options: IEditorAriaOptions): void;
|
||||
|
||||
/**
|
||||
* Write the screen reader content to be the current selection
|
||||
*/
|
||||
writeScreenReaderContent(reason: string): void;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
|
|
@ -487,6 +487,10 @@ export class View extends ViewEventHandler {
|
|||
}
|
||||
}
|
||||
|
||||
public writeScreenReaderContent(reason: string): void {
|
||||
this._textAreaHandler.writeScreenReaderContent(reason);
|
||||
}
|
||||
|
||||
public focus(): void {
|
||||
this._textAreaHandler.focusTextArea();
|
||||
}
|
||||
|
|
|
@ -398,6 +398,10 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
|||
this._codeEditorService.addCodeEditor(this);
|
||||
}
|
||||
|
||||
public writeScreenReaderContent(reason: string): void {
|
||||
this._modelData?.view.writeScreenReaderContent(reason);
|
||||
}
|
||||
|
||||
protected _createConfiguration(isSimpleWidget: boolean, options: Readonly<IEditorConstructionOptions>, accessibilityService: IAccessibilityService): EditorConfiguration {
|
||||
return new EditorConfiguration(isSimpleWidget, options, this._domElement, accessibilityService);
|
||||
}
|
||||
|
|
4
src/vs/monaco.d.ts
vendored
4
src/vs/monaco.d.ts
vendored
|
@ -5631,6 +5631,10 @@ declare namespace monaco.editor {
|
|||
* Get the vertical position (top offset) for the position w.r.t. to the first line.
|
||||
*/
|
||||
getTopForPosition(lineNumber: number, column: number): number;
|
||||
/**
|
||||
* Write the screen reader content to be the current selection
|
||||
*/
|
||||
writeScreenReaderContent(reason: string): void;
|
||||
/**
|
||||
* Returns the editor's container dom node
|
||||
*/
|
||||
|
|
|
@ -69,7 +69,7 @@ export class AudioCueService extends Disposable implements IAudioCueService {
|
|||
}
|
||||
|
||||
this.playingSounds.add(sound);
|
||||
|
||||
console.log('playing', sound);
|
||||
const url = FileAccess.asBrowserUri(
|
||||
`vs/platform/audioCues/browser/media/${sound.fileName}`
|
||||
).toString();
|
||||
|
@ -77,6 +77,7 @@ export class AudioCueService extends Disposable implements IAudioCueService {
|
|||
audio.volume = this.getVolumeInPercent() / 100;
|
||||
audio.addEventListener('ended', () => {
|
||||
this.playingSounds.delete(sound);
|
||||
console.log('ending', sound);
|
||||
});
|
||||
try {
|
||||
try {
|
||||
|
|
|
@ -57,6 +57,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
|
|||
import { DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
|
||||
import { FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files';
|
||||
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
|
||||
class DiffActionRunner extends ActionRunner {
|
||||
|
||||
|
@ -464,9 +465,11 @@ export class GotoPreviousChangeAction extends EditorAction {
|
|||
});
|
||||
}
|
||||
|
||||
run(accessor: ServicesAccessor): void {
|
||||
async run(accessor: ServicesAccessor): Promise<void> {
|
||||
const outerEditor = getOuterEditorFromDiffEditor(accessor);
|
||||
const audioCueService = accessor.get(IAudioCueService);
|
||||
const accessibilityService = accessor.get(IAccessibilityService);
|
||||
const codeEditorService = accessor.get(ICodeEditorService);
|
||||
|
||||
if (!outerEditor || !outerEditor.hasModel()) {
|
||||
return;
|
||||
|
@ -486,11 +489,9 @@ export class GotoPreviousChangeAction extends EditorAction {
|
|||
|
||||
const index = model.findPreviousClosestChange(lineNumber, false);
|
||||
const change = model.changes[index];
|
||||
playAudioCueForChange(change, audioCueService);
|
||||
|
||||
const position = new Position(change.modifiedStartLineNumber, 1);
|
||||
outerEditor.setPosition(position);
|
||||
outerEditor.revealPositionInCenter(position);
|
||||
await playAudioCueForChange(change, audioCueService);
|
||||
// The audio cue can take up to a second to load. Give it a chance to play before we read the line content
|
||||
await setTimeout(() => setPositionAndSelection(change, outerEditor, accessibilityService, codeEditorService), 500);
|
||||
}
|
||||
}
|
||||
registerEditorAction(GotoPreviousChangeAction);
|
||||
|
@ -507,9 +508,11 @@ export class GotoNextChangeAction extends EditorAction {
|
|||
});
|
||||
}
|
||||
|
||||
run(accessor: ServicesAccessor): void {
|
||||
async run(accessor: ServicesAccessor): Promise<void> {
|
||||
const audioCueService = accessor.get(IAudioCueService);
|
||||
const outerEditor = getOuterEditorFromDiffEditor(accessor);
|
||||
const accessibilityService = accessor.get(IAccessibilityService);
|
||||
const codeEditorService = accessor.get(ICodeEditorService);
|
||||
|
||||
if (!outerEditor || !outerEditor.hasModel()) {
|
||||
return;
|
||||
|
@ -530,23 +533,31 @@ export class GotoNextChangeAction extends EditorAction {
|
|||
|
||||
const index = model.findNextClosestChange(lineNumber, false);
|
||||
const change = model.changes[index];
|
||||
playAudioCueForChange(change, audioCueService);
|
||||
|
||||
const position = new Position(change.modifiedStartLineNumber, 1);
|
||||
outerEditor.setPosition(position);
|
||||
outerEditor.revealPositionInCenter(position);
|
||||
await playAudioCueForChange(change, audioCueService);
|
||||
// The audio cue can take up to a second to load. Give it a chance to play before we read the line content
|
||||
await setTimeout(() => setPositionAndSelection(change, outerEditor, accessibilityService, codeEditorService), 500);
|
||||
}
|
||||
}
|
||||
|
||||
function playAudioCueForChange(change: IChange, audioCueService: IAudioCueService) {
|
||||
function setPositionAndSelection(change: IChange, editor: ICodeEditor, accessibilityService: IAccessibilityService, codeEditorService: ICodeEditorService) {
|
||||
const position = new Position(change.modifiedStartLineNumber, 1);
|
||||
editor.setPosition(position);
|
||||
editor.revealPositionInCenter(position);
|
||||
if (accessibilityService.isScreenReaderOptimized()) {
|
||||
editor.setSelection({ startLineNumber: change.modifiedStartLineNumber, startColumn: 0, endLineNumber: change.modifiedStartLineNumber, endColumn: Number.MAX_VALUE });
|
||||
codeEditorService.getActiveCodeEditor()?.writeScreenReaderContent('diff-navigation');
|
||||
}
|
||||
}
|
||||
|
||||
async function playAudioCueForChange(change: IChange, audioCueService: IAudioCueService) {
|
||||
const changeType = getChangeType(change);
|
||||
switch (changeType) {
|
||||
case ChangeType.Add:
|
||||
audioCueService.playAudioCue(AudioCue.diffLineInserted);
|
||||
audioCueService.playAudioCue(AudioCue.diffLineInserted, true);
|
||||
case ChangeType.Delete:
|
||||
audioCueService.playAudioCue(AudioCue.diffLineDeleted);
|
||||
audioCueService.playAudioCue(AudioCue.diffLineDeleted, true);
|
||||
case ChangeType.Modify:
|
||||
audioCueService.playAudioCue(AudioCue.diffLineModified);
|
||||
audioCueService.playAudioCue(AudioCue.diffLineModified, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue