mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 17:22:45 -05:00
Merge from vscode 61d5f2b82f17bf9f99f56405204caab88a7e8747
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { PickerQuickAccessProvider, IPickerQuickAccessItem } from 'vs/platform/quickinput/browser/pickerQuickAccess';
|
||||
import { PickerQuickAccessProvider, IPickerQuickAccessItem, IPickerQuickAccessProviderOptions } from 'vs/platform/quickinput/browser/pickerQuickAccess';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -30,7 +30,7 @@ export interface ICommandQuickPick extends IPickerQuickAccessItem {
|
||||
commandAlias: string | undefined;
|
||||
}
|
||||
|
||||
export interface ICommandsQuickAccessOptions {
|
||||
export interface ICommandsQuickAccessOptions extends IPickerQuickAccessProviderOptions {
|
||||
showAlias: boolean;
|
||||
}
|
||||
|
||||
@@ -43,14 +43,14 @@ export abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAcc
|
||||
private readonly commandsHistory = this._register(this.instantiationService.createInstance(CommandsHistory));
|
||||
|
||||
constructor(
|
||||
private options: ICommandsQuickAccessOptions,
|
||||
protected options: ICommandsQuickAccessOptions,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@INotificationService private readonly notificationService: INotificationService
|
||||
) {
|
||||
super(AbstractCommandsQuickAccessProvider.PREFIX);
|
||||
super(AbstractCommandsQuickAccessProvider.PREFIX, options);
|
||||
}
|
||||
|
||||
protected async getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<ICommandQuickPick | IQuickPickSeparator>> {
|
||||
|
||||
@@ -8,6 +8,7 @@ import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cance
|
||||
import { IQuickPickSeparator, IKeyMods, IQuickPickAcceptEvent } from 'vs/base/parts/quickinput/common/quickInput';
|
||||
import { IQuickAccessProvider } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
|
||||
export enum TriggerAction {
|
||||
|
||||
@@ -53,17 +54,31 @@ export interface IPickerQuickAccessItem extends IQuickPickItem {
|
||||
trigger?(buttonIndex: number, keyMods: IKeyMods): TriggerAction | Promise<TriggerAction>;
|
||||
}
|
||||
|
||||
export interface IPickerQuickAccessProviderOptions {
|
||||
canAcceptInBackground?: boolean;
|
||||
}
|
||||
|
||||
export type FastAndSlowPicksType<T> = { picks: Array<T | IQuickPickSeparator>, additionalPicks: Promise<Array<T | IQuickPickSeparator>> };
|
||||
|
||||
function isFastAndSlowPicksType<T>(obj: unknown): obj is FastAndSlowPicksType<T> {
|
||||
const candidate = obj as FastAndSlowPicksType<T>;
|
||||
|
||||
return Array.isArray(candidate.picks) && candidate.additionalPicks instanceof Promise;
|
||||
}
|
||||
|
||||
export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem> extends Disposable implements IQuickAccessProvider {
|
||||
|
||||
constructor(private prefix: string) {
|
||||
private static FAST_PICKS_RACE_DELAY = 200; // timeout before we accept fast results before slow results are present
|
||||
|
||||
constructor(private prefix: string, protected options?: IPickerQuickAccessProviderOptions) {
|
||||
super();
|
||||
}
|
||||
|
||||
provide(picker: IQuickPick<T>, token: CancellationToken): IDisposable {
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
// Allow subclasses to configure picker
|
||||
this.configure(picker);
|
||||
// Apply options if any
|
||||
picker.canAcceptInBackground = !!this.options?.canAcceptInBackground;
|
||||
|
||||
// Disable filtering & sorting, we control the results
|
||||
picker.matchOnLabel = picker.matchOnDescription = picker.matchOnDetail = picker.sortByLabel = false;
|
||||
@@ -79,21 +94,77 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
|
||||
// Create new cancellation source for this run
|
||||
picksCts = new CancellationTokenSource(token);
|
||||
|
||||
// Collect picks and support both long running and short
|
||||
const res = this.getPicks(picker.value.substr(this.prefix.length).trim(), disposables.add(new DisposableStore()), picksCts.token);
|
||||
if (Array.isArray(res)) {
|
||||
// Collect picks and support both long running and short or combined
|
||||
const picksToken = picksCts.token;
|
||||
const res = this.getPicks(picker.value.substr(this.prefix.length).trim(), disposables.add(new DisposableStore()), picksToken);
|
||||
if (isFastAndSlowPicksType(res)) {
|
||||
let fastPicksHandlerDone = false;
|
||||
let slowPicksHandlerDone = false;
|
||||
|
||||
await Promise.all([
|
||||
|
||||
// Fast Picks: to reduce amount of flicker, we race against
|
||||
// the slow picks over 500ms and then set the fast picks.
|
||||
// If the slow picks are faster, we reduce the flicker by
|
||||
// only setting the items once.
|
||||
(async () => {
|
||||
try {
|
||||
await timeout(PickerQuickAccessProvider.FAST_PICKS_RACE_DELAY);
|
||||
if (picksToken.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!slowPicksHandlerDone) {
|
||||
picker.items = res.picks;
|
||||
}
|
||||
} finally {
|
||||
fastPicksHandlerDone = true;
|
||||
}
|
||||
})(),
|
||||
|
||||
|
||||
// Slow Picks: we await the slow picks and then set them at
|
||||
// once together with the fast picks, but only if we actually
|
||||
// have additional results.
|
||||
(async () => {
|
||||
picker.busy = true;
|
||||
try {
|
||||
const additionalPicks = await res.additionalPicks;
|
||||
if (picksToken.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (additionalPicks.length > 0 || !fastPicksHandlerDone) {
|
||||
picker.items = [...res.picks, ...additionalPicks];
|
||||
}
|
||||
} finally {
|
||||
if (!picksToken.isCancellationRequested) {
|
||||
picker.busy = false;
|
||||
}
|
||||
|
||||
slowPicksHandlerDone = true;
|
||||
}
|
||||
})()
|
||||
]);
|
||||
}
|
||||
|
||||
// Fast Picks
|
||||
else if (Array.isArray(res)) {
|
||||
picker.items = res;
|
||||
} else {
|
||||
}
|
||||
|
||||
// Slow Picks
|
||||
else {
|
||||
picker.busy = true;
|
||||
try {
|
||||
const items = await res;
|
||||
if (token.isCancellationRequested) {
|
||||
if (picksToken.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
picker.items = items;
|
||||
} finally {
|
||||
if (!token.isCancellationRequested) {
|
||||
if (!picksToken.isCancellationRequested) {
|
||||
picker.busy = false;
|
||||
}
|
||||
}
|
||||
@@ -142,13 +213,6 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
|
||||
return disposables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can override this method to configure the picker before showing it.
|
||||
*
|
||||
* @param picker the picker instance used for the quick access before it opens.
|
||||
*/
|
||||
protected configure(picker: IQuickPick<T>): void { }
|
||||
|
||||
/**
|
||||
* Returns an array of picks and separators as needed. If the picks are resolved
|
||||
* long running, the provided cancellation token should be used to cancel the
|
||||
@@ -162,6 +226,7 @@ export abstract class PickerQuickAccessProvider<T extends IPickerQuickAccessItem
|
||||
* up when the picker closes.
|
||||
* @param token for long running tasks, implementors need to check on cancellation
|
||||
* through this token.
|
||||
* @returns the picks either directly, as promise or combined fast and slow results.
|
||||
*/
|
||||
protected abstract getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Array<T | IQuickPickSeparator> | Promise<Array<T | IQuickPickSeparator>>;
|
||||
protected abstract getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Array<T | IQuickPickSeparator> | Promise<Array<T | IQuickPickSeparator>> | FastAndSlowPicksType<T>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user