mirror of
https://github.com/Microsoft/vscode
synced 2024-08-26 20:39:37 +00:00
Improves audio cue implementation.
This commit is contained in:
parent
1565485f7c
commit
3bb027eb95
|
@ -12,7 +12,7 @@ import { ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/edito
|
|||
import { IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
import { FoldingController } from 'vs/editor/contrib/folding/browser/folding';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { autorun, autorunDelta, constObservable, debouncedObservable, fromEvent, fromPromise, IObservable, LazyDerived, wasEventTriggeredRecently } from 'vs/workbench/contrib/audioCues/browser/observable';
|
||||
import { autorun, autorunDelta, constObservable, debouncedObservable, derivedObservable, fromEvent, fromPromise, IObservable, LazyDerived, wasEventTriggeredRecently } from 'vs/workbench/contrib/audioCues/browser/observable';
|
||||
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';
|
||||
|
@ -83,14 +83,14 @@ export class AudioCueLineFeatureContribution
|
|||
editorModel: ITextModel,
|
||||
store: DisposableStore
|
||||
): void {
|
||||
const observableFeatureStates = this.features.map((feature) =>
|
||||
feature.getObservableState(editor, editorModel)
|
||||
);
|
||||
|
||||
const curLineNumber = fromEvent(
|
||||
editor.onDidChangeCursorPosition,
|
||||
(args) => {
|
||||
if (args && args.reason !== CursorChangeReason.Explicit) {
|
||||
if (
|
||||
args &&
|
||||
args.reason !== CursorChangeReason.Explicit &&
|
||||
args.reason !== CursorChangeReason.NotSet
|
||||
) {
|
||||
// Ignore cursor changes caused by navigation (e.g. which happens when execution is paused).
|
||||
return undefined;
|
||||
}
|
||||
|
@ -99,61 +99,55 @@ export class AudioCueLineFeatureContribution
|
|||
);
|
||||
const debouncedLineNumber = debouncedObservable(curLineNumber, 100, store);
|
||||
|
||||
const lineNumberWithObservableFeatures = debouncedLineNumber.map(
|
||||
(lineNumber) =>
|
||||
lineNumber === undefined
|
||||
? undefined
|
||||
: {
|
||||
lineNumber,
|
||||
featureStatesForLine: observableFeatureStates.map(
|
||||
(featureResult, idx) =>
|
||||
// This caches the feature state for the active line
|
||||
new LazyDerived(
|
||||
(reader) =>
|
||||
this.audioCueService
|
||||
.isEnabled(this.features[idx].audioCue)
|
||||
.read(reader) &&
|
||||
featureResult.read(reader).isPresent(lineNumber),
|
||||
'isActiveForLine'
|
||||
)
|
||||
),
|
||||
const isFeaturePresentInDebouncedLine = (
|
||||
feature: LineFeature,
|
||||
lineFeatureState: IObservable<LineFeatureState>
|
||||
): IObservable<boolean> =>
|
||||
derivedObservable(
|
||||
`isPresentInLine:${feature.audioCue.name}`,
|
||||
(reader) => {
|
||||
if (!this.audioCueService.isEnabled(feature.audioCue).read(reader)) {
|
||||
return false;
|
||||
}
|
||||
);
|
||||
const lineNumber = debouncedLineNumber.read(reader);
|
||||
return lineNumber === undefined
|
||||
? false
|
||||
: lineFeatureState.read(reader).isPresent(lineNumber);
|
||||
}
|
||||
);
|
||||
|
||||
const isTyping = wasEventTriggeredRecently(
|
||||
editorModel.onDidChangeContent.bind(editorModel),
|
||||
1000,
|
||||
store
|
||||
);
|
||||
const featureStatesBeforeTyping = isTyping.map(
|
||||
(isTyping) =>
|
||||
(!isTyping
|
||||
? undefined
|
||||
: lineNumberWithObservableFeatures
|
||||
.get()
|
||||
?.featureStatesForLine?.map((featureState, idx) =>
|
||||
this.features[idx].debounceWhileTyping
|
||||
? featureState.get()
|
||||
: undefined
|
||||
)) ?? []
|
||||
);
|
||||
|
||||
const state = new LazyDerived((reader) => {
|
||||
const lineInfo = lineNumberWithObservableFeatures.read(reader);
|
||||
if (lineInfo === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
lineNumber: lineInfo.lineNumber,
|
||||
const featureStates = this.features.map((feature) => {
|
||||
const isFeaturePresent = isFeaturePresentInDebouncedLine(
|
||||
feature,
|
||||
feature.getObservableState(editor, editorModel)
|
||||
);
|
||||
return derivedObservable(
|
||||
`typingDebouncedFeatureState:\n${feature.audioCue.name}`,
|
||||
(reader) =>
|
||||
feature.debounceWhileTyping && isTyping.read(reader)
|
||||
? (debouncedLineNumber.read(reader), isFeaturePresent.get())
|
||||
: isFeaturePresent.read(reader)
|
||||
);
|
||||
});
|
||||
|
||||
const state = new LazyDerived(
|
||||
(reader) => ({
|
||||
lineNumber: debouncedLineNumber.read(reader),
|
||||
featureStates: new Map(
|
||||
lineInfo.featureStatesForLine.map((featureState, idx) => [
|
||||
this.features[idx],
|
||||
featureStatesBeforeTyping.read(reader)[idx] ??
|
||||
featureState.read(reader),
|
||||
this.features.map((feature, idx) => [
|
||||
feature,
|
||||
featureStates[idx].read(reader),
|
||||
])
|
||||
),
|
||||
};
|
||||
}, 'state');
|
||||
}),
|
||||
'state'
|
||||
);
|
||||
|
||||
store.add(
|
||||
autorunDelta(state, ({ lastValue, newValue }) => {
|
||||
|
|
|
@ -314,6 +314,9 @@ export class AutorunObserver implements IObserver, IReader, IDisposable {
|
|||
}
|
||||
}
|
||||
|
||||
export namespace autorun {
|
||||
export const Observer = AutorunObserver;
|
||||
}
|
||||
export function autorunDelta<T>(
|
||||
observable: IObservable<T>,
|
||||
handler: (args: { lastValue: T | undefined; newValue: T }) => void
|
||||
|
@ -330,6 +333,9 @@ export function autorunDelta<T>(
|
|||
|
||||
// == Lazy Derived ==
|
||||
|
||||
export function derivedObservable<T>(name: string, computeFn: (reader: IReader) => T): IObservable<T> {
|
||||
return new LazyDerived(computeFn, name);
|
||||
}
|
||||
export class LazyDerived<T> extends ConvenientObservable<T> {
|
||||
private readonly observer: LazyDerivedObserver<T>;
|
||||
|
||||
|
@ -346,6 +352,10 @@ export class LazyDerived<T> extends ConvenientObservable<T> {
|
|||
this.observer.unsubscribe(observer);
|
||||
}
|
||||
|
||||
public override read(reader: IReader): T {
|
||||
return this.observer.read(reader);
|
||||
}
|
||||
|
||||
public get(): T {
|
||||
return this.observer.get();
|
||||
}
|
||||
|
@ -485,6 +495,10 @@ class LazyDerivedObserver<T>
|
|||
}
|
||||
}
|
||||
|
||||
export namespace LazyDerived {
|
||||
export const Observer = LazyDerivedObserver;
|
||||
}
|
||||
|
||||
export function fromPromise<T>(promise: Promise<T>): IObservable<{ value?: T }> {
|
||||
const observable = new ObservableValue<{ value?: T }>({}, 'promiseValue');
|
||||
promise.then((value) => {
|
||||
|
@ -553,6 +567,10 @@ class FromEventObservable<TArgs, T> extends BaseObservable<T> {
|
|||
}
|
||||
}
|
||||
|
||||
export namespace fromEvent {
|
||||
export const Observer = FromEventObservable;
|
||||
}
|
||||
|
||||
export function debouncedObservable<T>(observable: IObservable<T>, debounceMs: number, disposableStore: DisposableStore): IObservable<T> {
|
||||
const debouncedObservable = new ObservableValue(observable.get(), 'debounced');
|
||||
|
||||
|
|
Loading…
Reference in a new issue