mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-26 10:16:01 +01:00
add audio cues for reviewing a diff editor (#166413)
This commit is contained in:
@@ -1878,6 +1878,11 @@ function createDecoration(startLineNumber: number, startColumn: number, endLineN
|
||||
};
|
||||
}
|
||||
|
||||
const enum DiffEditorLineClasses {
|
||||
Insert = 'line-insert',
|
||||
Delete = 'line-delete'
|
||||
}
|
||||
|
||||
const DECORATIONS = {
|
||||
|
||||
arrowRevertChange: ModelDecorationOptions.register({
|
||||
@@ -1907,13 +1912,13 @@ const DECORATIONS = {
|
||||
|
||||
lineInsert: ModelDecorationOptions.register({
|
||||
description: 'diff-editor-line-insert',
|
||||
className: 'line-insert',
|
||||
className: DiffEditorLineClasses.Insert,
|
||||
marginClassName: 'gutter-insert',
|
||||
isWholeLine: true
|
||||
}),
|
||||
lineInsertWithSign: ModelDecorationOptions.register({
|
||||
description: 'diff-editor-line-insert-with-sign',
|
||||
className: 'line-insert',
|
||||
className: DiffEditorLineClasses.Insert,
|
||||
linesDecorationsClassName: 'insert-sign ' + ThemeIcon.asClassName(diffInsertIcon),
|
||||
marginClassName: 'gutter-insert',
|
||||
isWholeLine: true
|
||||
@@ -1921,13 +1926,13 @@ const DECORATIONS = {
|
||||
|
||||
lineDelete: ModelDecorationOptions.register({
|
||||
description: 'diff-editor-line-delete',
|
||||
className: 'line-delete',
|
||||
className: DiffEditorLineClasses.Delete,
|
||||
marginClassName: 'gutter-delete',
|
||||
isWholeLine: true
|
||||
}),
|
||||
lineDeleteWithSign: ModelDecorationOptions.register({
|
||||
description: 'diff-editor-line-delete-with-sign',
|
||||
className: 'line-delete',
|
||||
className: DiffEditorLineClasses.Delete,
|
||||
linesDecorationsClassName: 'delete-sign ' + ThemeIcon.asClassName(diffRemoveIcon),
|
||||
marginClassName: 'gutter-delete',
|
||||
isWholeLine: true
|
||||
|
||||
@@ -33,6 +33,7 @@ import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
|
||||
import { ILanguageIdCodec } from 'vs/editor/common/languages';
|
||||
import { ILanguageService } from 'vs/editor/common/languages/language';
|
||||
import { ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer';
|
||||
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
|
||||
const DIFF_LINES_PADDING = 3;
|
||||
|
||||
@@ -66,6 +67,11 @@ class DiffEntry {
|
||||
}
|
||||
}
|
||||
|
||||
const enum DiffEditorLineClasses {
|
||||
Insert = 'line-insert',
|
||||
Delete = 'line-delete'
|
||||
}
|
||||
|
||||
class Diff {
|
||||
readonly entries: DiffEntry[];
|
||||
|
||||
@@ -95,7 +101,8 @@ export class DiffReview extends Disposable {
|
||||
|
||||
constructor(
|
||||
diffEditor: DiffEditorWidget,
|
||||
@ILanguageService private readonly _languageService: ILanguageService
|
||||
@ILanguageService private readonly _languageService: ILanguageService,
|
||||
@IAudioCueService private readonly _audioCueService: IAudioCueService
|
||||
) {
|
||||
super();
|
||||
this._diffEditor = diffEditor;
|
||||
@@ -149,7 +156,7 @@ export class DiffReview extends Disposable {
|
||||
|| e.equals(KeyMod.Alt | KeyCode.DownArrow)
|
||||
) {
|
||||
e.preventDefault();
|
||||
this._goToRow(this._getNextRow());
|
||||
this._goToRow(this._getNextRow(), 'next');
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -158,7 +165,7 @@ export class DiffReview extends Disposable {
|
||||
|| e.equals(KeyMod.Alt | KeyCode.UpArrow)
|
||||
) {
|
||||
e.preventDefault();
|
||||
this._goToRow(this._getPrevRow());
|
||||
this._goToRow(this._getPrevRow(), 'previous');
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -215,7 +222,7 @@ export class DiffReview extends Disposable {
|
||||
this._isVisible = true;
|
||||
this._diffEditor.doLayout();
|
||||
this._render();
|
||||
this._goToRow(this._getNextRow());
|
||||
this._goToRow(this._getPrevRow(), 'previous');
|
||||
}
|
||||
|
||||
public next(): void {
|
||||
@@ -250,7 +257,7 @@ export class DiffReview extends Disposable {
|
||||
this._isVisible = true;
|
||||
this._diffEditor.doLayout();
|
||||
this._render();
|
||||
this._goToRow(this._getNextRow());
|
||||
this._goToRow(this._getNextRow(), 'next');
|
||||
}
|
||||
|
||||
private accept(): void {
|
||||
@@ -312,12 +319,18 @@ export class DiffReview extends Disposable {
|
||||
return null;
|
||||
}
|
||||
|
||||
private _goToRow(row: HTMLElement): void {
|
||||
const prev = this._getCurrentFocusedRow();
|
||||
private _goToRow(row: HTMLElement, type?: 'next' | 'previous'): void {
|
||||
const current = this._getCurrentFocusedRow();
|
||||
row.tabIndex = 0;
|
||||
row.focus();
|
||||
if (prev && prev !== row) {
|
||||
prev.tabIndex = -1;
|
||||
if (current && current !== row) {
|
||||
current.tabIndex = -1;
|
||||
}
|
||||
const element = !type ? current : type === 'next' ? current?.nextElementSibling : current?.previousElementSibling;
|
||||
if (element?.classList.contains(DiffEditorLineClasses.Insert)) {
|
||||
this._audioCueService.playAudioCue(AudioCue.diffLineInserted, true);
|
||||
} else if (element?.classList.contains(DiffEditorLineClasses.Delete)) {
|
||||
this._audioCueService.playAudioCue(AudioCue.diffLineDeleted, true);
|
||||
}
|
||||
this.scrollbar.scanDomNode();
|
||||
}
|
||||
|
||||
@@ -495,7 +495,7 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IEditorProgressService editorProgressService: IEditorProgressService,
|
||||
@IClipboardService clipboardService: IClipboardService,
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
const options = { ..._options };
|
||||
updateConfigurationService(configurationService, options, true);
|
||||
|
||||
+18
-4
@@ -17,7 +17,7 @@ export const IAudioCueService = createDecorator<IAudioCueService>('audioCue');
|
||||
|
||||
export interface IAudioCueService {
|
||||
readonly _serviceBrand: undefined;
|
||||
playAudioCue(cue: AudioCue): Promise<void>;
|
||||
playAudioCue(cue: AudioCue, allowManyInParallel?: boolean): Promise<void>;
|
||||
playAudioCues(cues: AudioCue[]): Promise<void>;
|
||||
isEnabled(cue: AudioCue): IObservable<boolean>;
|
||||
|
||||
@@ -39,9 +39,9 @@ export class AudioCueService extends Disposable implements IAudioCueService {
|
||||
super();
|
||||
}
|
||||
|
||||
public async playAudioCue(cue: AudioCue): Promise<void> {
|
||||
public async playAudioCue(cue: AudioCue, allowManyInParallel = false): Promise<void> {
|
||||
if (this.isEnabled(cue).get()) {
|
||||
await this.playSound(cue.sound);
|
||||
await this.playSound(cue.sound, allowManyInParallel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ export class AudioCueService extends Disposable implements IAudioCueService {
|
||||
this.playingSounds.add(sound);
|
||||
|
||||
const url = FileAccess.asBrowserUri(
|
||||
`vs/workbench/contrib/audioCues/browser/media/${sound.fileName}`
|
||||
`vs/platform/audioCues/common/media/${sound.fileName}`
|
||||
).toString();
|
||||
const audio = new Audio(url);
|
||||
audio.volume = this.getVolumeInPercent() / 100;
|
||||
@@ -164,6 +164,8 @@ export class Sound {
|
||||
public static readonly taskCompleted = Sound.register({ fileName: 'taskCompleted.mp3' });
|
||||
public static readonly taskFailed = Sound.register({ fileName: 'taskFailed.mp3' });
|
||||
public static readonly terminalBell = Sound.register({ fileName: 'terminalBell.mp3' });
|
||||
public static readonly diffLineInserted = Sound.register({ fileName: 'diffLineInserted.mp3' });
|
||||
public static readonly diffLineDeleted = Sound.register({ fileName: 'diffLineDeleted.mp3' });
|
||||
|
||||
private constructor(public readonly fileName: string) { }
|
||||
}
|
||||
@@ -247,6 +249,18 @@ export class AudioCue {
|
||||
settingsKey: 'audioCues.terminalBell'
|
||||
});
|
||||
|
||||
public static readonly diffLineInserted = AudioCue.register({
|
||||
name: localize('audioCues.diffLineInserted', 'Diff Line Inserted'),
|
||||
sound: Sound.diffLineInserted,
|
||||
settingsKey: 'audioCues.diffLineInserted'
|
||||
});
|
||||
|
||||
public static readonly diffLineDeleted = AudioCue.register({
|
||||
name: localize('audioCues.diffLineDeleted', 'Diff Line Deleted'),
|
||||
sound: Sound.diffLineDeleted,
|
||||
settingsKey: 'audioCues.diffLineDeleted'
|
||||
});
|
||||
|
||||
private constructor(
|
||||
public readonly sound: Sound,
|
||||
public readonly name: string,
|
||||
Binary file not shown.
Binary file not shown.
@@ -129,7 +129,6 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DynamicEditorConfigurations, LifecyclePhase.Ready);
|
||||
|
||||
registerEditorContribution(FloatingClickMenu.ID, FloatingClickMenu);
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Quick Access
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { autorunWithStore } from 'vs/base/common/observable';
|
||||
import { IAudioCueService, AudioCue } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
|
||||
import { IDebugService, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
|
||||
|
||||
export class AudioCueLineDebuggerContribution
|
||||
|
||||
@@ -14,9 +14,9 @@ import { FoldingController } from 'vs/editor/contrib/folding/browser/folding';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { GhostTextController } from 'vs/editor/contrib/inlineCompletions/browser/ghostTextController';
|
||||
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
|
||||
import { CursorChangeReason } from 'vs/editor/common/cursorEvents';
|
||||
import { autorun, autorunDelta, constObservable, debouncedObservable, derived, IObservable, observableFromEvent, observableFromPromise, wasEventTriggeredRecently } from 'vs/base/common/observable';
|
||||
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
|
||||
export class AudioCueLineFeatureContribution
|
||||
extends Disposable
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ShowAudioCueHelp } from 'vs/workbench/contrib/audioCues/browser/commands';
|
||||
import { localize } from 'vs/nls';
|
||||
import { registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { Extensions as ConfigurationExtensions, IConfigurationPropertySchema, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { IAudioCueService, AudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
import { AudioCueLineDebuggerContribution } from 'vs/workbench/contrib/audioCues/browser/audioCueDebuggerContribution';
|
||||
import { AudioCueLineFeatureContribution } from 'vs/workbench/contrib/audioCues/browser/audioCueLineFeatureContribution';
|
||||
import { AudioCueService, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
|
||||
import { ShowAudioCueHelp } from 'vs/workbench/contrib/audioCues/browser/commands';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
|
||||
registerSingleton(IAudioCueService, AudioCueService, InstantiationType.Delayed);
|
||||
|
||||
@@ -87,6 +87,14 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
|
||||
'description': localize('audioCues.terminalQuickFix', "Plays a sound when terminal Quick Fixes are available."),
|
||||
...audioCueFeatureBase,
|
||||
},
|
||||
'audioCues.diffLineInserted': {
|
||||
'description': localize('audioCues.diffLineInserted', "Plays a sound when the focus moves to an inserted line in diff review mode"),
|
||||
...audioCueFeatureBase,
|
||||
},
|
||||
'audioCues.diffLineDeleted': {
|
||||
'description': localize('audioCues.diffLineDeleted', "Plays a sound when the focus moves to a deleted line in diff review mode"),
|
||||
...audioCueFeatureBase,
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import { Codicon } from 'vs/base/common/codicons';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { Action2 } from 'vs/platform/actions/common/actions';
|
||||
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
|
||||
export class ShowAudioCueHelp extends Action2 {
|
||||
|
||||
@@ -15,11 +15,11 @@ import { InlayHintItem, asCommandLink } from 'vs/editor/contrib/inlayHints/brows
|
||||
import { InlayHintsController } from 'vs/editor/contrib/inlayHints/browser/inlayHintsController';
|
||||
import { localize } from 'vs/nls';
|
||||
import { registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { Link } from 'vs/platform/opener/browser/link';
|
||||
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
|
||||
|
||||
|
||||
export class InlayHintsAccessibility implements IEditorContribution {
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ITerminalStatus } from 'vs/workbench/contrib/terminal/browser/terminalS
|
||||
import { MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
import { spinningLoading } from 'vs/platform/theme/common/iconRegistry';
|
||||
import { IMarker } from 'vs/platform/terminal/common/capabilities/capabilities';
|
||||
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
|
||||
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
|
||||
interface ITerminalData {
|
||||
terminal: ITerminalInstance;
|
||||
|
||||
@@ -46,7 +46,7 @@ import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/b
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
|
||||
import { IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
|
||||
interface IWorkspaceFolderConfigurationResult {
|
||||
workspaceFolder: IWorkspaceFolder;
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
|
||||
import { ok } from 'assert';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
|
||||
import { ACTIVE_TASK_STATUS, FAILED_TASK_STATUS, SUCCEEDED_TASK_STATUS, TaskTerminalStatus } from 'vs/workbench/contrib/tasks/browser/taskTerminalStatus';
|
||||
import { AbstractProblemCollector } from 'vs/workbench/contrib/tasks/common/problemCollectors';
|
||||
import { CommonTask, ITaskEvent, TaskEventKind, TaskRunType } from 'vs/workbench/contrib/tasks/common/tasks';
|
||||
|
||||
@@ -55,7 +55,6 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views';
|
||||
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
|
||||
import { TaskSettingId } from 'vs/workbench/contrib/tasks/common/tasks';
|
||||
import { IDetectedLinks, TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager';
|
||||
import { TerminalLinkQuickpick } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkQuickpick';
|
||||
@@ -89,6 +88,7 @@ import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/
|
||||
import { IPathService } from 'vs/workbench/services/path/common/pathService';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import type { IMarker, ITerminalAddon, Terminal as XTermTerminal } from 'xterm';
|
||||
import { IAudioCueService, AudioCue } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
|
||||
const enum Constants {
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,6 @@ import { asArray } from 'vs/base/common/arrays';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { AudioCue, IAudioCueService } from 'vs/workbench/contrib/audioCues/browser/audioCueService';
|
||||
import { ITerminalQuickFixOpenerAction, ITerminalQuickFixOptions, TerminalQuickFixAction, TerminalQuickFixMatchResult } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { DecorationSelector, updateLayout } from 'vs/workbench/contrib/terminal/browser/xterm/decorationStyles';
|
||||
import { IDecoration, Terminal } from 'xterm';
|
||||
@@ -24,6 +23,7 @@ import { ITerminalContributionService } from 'vs/workbench/contrib/terminal/comm
|
||||
import { IExtensionTerminalQuickFix } from 'vs/platform/terminal/common/terminal';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { gitCreatePr, gitPushSetUpstream, gitSimilar } from 'vs/workbench/contrib/terminal/browser/terminalQuickFixBuiltinActions';
|
||||
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IActionWidgetService } from 'vs/platform/actionWidget/browser/actionWidget';
|
||||
import { ActionSet } from 'vs/platform/actionWidget/common/actionWidget';
|
||||
|
||||
Reference in New Issue
Block a user