mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode 1df23554b2e3d5f1efc6fbc76ee61d3f7f186c6d
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { PickerQuickAccessProvider, IPickerQuickAccessItem } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { PickerQuickAccessProvider, IPickerQuickAccessItem, TriggerAction } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { localize } from 'vs/nls';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IDebugService } from 'vs/workbench/contrib/debug/common/debug';
|
||||
@@ -47,9 +47,18 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider<IPi
|
||||
// Launch entry
|
||||
picks.push({
|
||||
label: config.name,
|
||||
ariaLabel: localize('entryAriaLabel', "{0}, debug", config.name),
|
||||
ariaLabel: localize('entryAriaLabel', "{0}, debug picker", config.name),
|
||||
description: this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? config.launch.name : '',
|
||||
highlights: { label: highlights },
|
||||
buttons: [{
|
||||
iconClass: 'codicon-gear',
|
||||
tooltip: localize('customizeTask', "Configure Launch Configuration")
|
||||
}],
|
||||
trigger: () => {
|
||||
config.launch.openConfigFile(false, false);
|
||||
|
||||
return TriggerAction.CLOSE_PICKER;
|
||||
},
|
||||
accept: async () => {
|
||||
if (StartAction.isEnabled(this.debugService)) {
|
||||
this.debugService.getConfigurationManager().selectConfiguration(config.launch, config.name);
|
||||
@@ -80,7 +89,7 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider<IPi
|
||||
// Add Config entry
|
||||
picks.push({
|
||||
label,
|
||||
ariaLabel: localize('entryAriaLabel', "{0}, debug", label),
|
||||
ariaLabel: localize('entryAriaLabel', "{0}, debug picker", label),
|
||||
description: this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE ? launch.name : '',
|
||||
highlights: { label: withNullAsUndefined(matchesFuzzy(filter, label, true)) },
|
||||
accept: () => this.commandService.executeCommand('debug.addConfiguration', launch.uri.toString())
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import severity from 'vs/base/common/severity';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
@@ -34,6 +33,7 @@ import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cance
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
export class DebugSession implements IDebugSession {
|
||||
|
||||
@@ -232,7 +232,7 @@ export class DebugSession implements IDebugSession {
|
||||
*/
|
||||
async launchOrAttach(config: IConfig): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'launch or attach'));
|
||||
}
|
||||
|
||||
// __sessionID only used for EH debugging (but we add it always for now...)
|
||||
@@ -250,7 +250,7 @@ export class DebugSession implements IDebugSession {
|
||||
*/
|
||||
async terminate(restart = false): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'terminate'));
|
||||
}
|
||||
|
||||
this.cancelAllRequests();
|
||||
@@ -266,7 +266,7 @@ export class DebugSession implements IDebugSession {
|
||||
*/
|
||||
async disconnect(restart = false): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'disconnect'));
|
||||
}
|
||||
|
||||
this.cancelAllRequests();
|
||||
@@ -278,7 +278,7 @@ export class DebugSession implements IDebugSession {
|
||||
*/
|
||||
async restart(): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'restart'));
|
||||
}
|
||||
|
||||
this.cancelAllRequests();
|
||||
@@ -287,7 +287,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async sendBreakpoints(modelUri: URI, breakpointsToSend: IBreakpoint[], sourceModified: boolean): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'breakpoints'));
|
||||
}
|
||||
|
||||
if (!this.raw.readyForBreakpoints) {
|
||||
@@ -321,7 +321,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async sendFunctionBreakpoints(fbpts: IFunctionBreakpoint[]): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'function breakpoints'));
|
||||
}
|
||||
|
||||
if (this.raw.readyForBreakpoints) {
|
||||
@@ -338,7 +338,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'exception breakpoints'));
|
||||
}
|
||||
|
||||
if (this.raw.readyForBreakpoints) {
|
||||
@@ -348,10 +348,10 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean }> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'data breakpoints info'));
|
||||
}
|
||||
if (!this.raw.readyForBreakpoints) {
|
||||
throw new Error(nls.localize('sessionNotReadyForBreakpoints', "Session is not ready for breakpoints"));
|
||||
throw new Error(localize('sessionNotReadyForBreakpoints', "Session is not ready for breakpoints"));
|
||||
}
|
||||
|
||||
const response = await this.raw.dataBreakpointInfo({ name, variablesReference });
|
||||
@@ -360,7 +360,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async sendDataBreakpoints(dataBreakpoints: IDataBreakpoint[]): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'data breakpoints'));
|
||||
}
|
||||
|
||||
if (this.raw.readyForBreakpoints) {
|
||||
@@ -377,7 +377,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async breakpointsLocations(uri: URI, lineNumber: number): Promise<IPosition[]> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'breakpoints locations'));
|
||||
}
|
||||
|
||||
const source = this.getRawSource(uri);
|
||||
@@ -393,7 +393,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
customRequest(request: string, args: any): Promise<DebugProtocol.Response> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", request));
|
||||
}
|
||||
|
||||
return this.raw.custom(request, args);
|
||||
@@ -401,7 +401,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
stackTrace(threadId: number, startFrame: number, levels: number): Promise<DebugProtocol.StackTraceResponse> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stackTrace'));
|
||||
}
|
||||
|
||||
const token = this.getNewCancellationToken(threadId);
|
||||
@@ -410,7 +410,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async exceptionInfo(threadId: number): Promise<IExceptionInfo | undefined> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'exceptionInfo'));
|
||||
}
|
||||
|
||||
const response = await this.raw.exceptionInfo({ threadId });
|
||||
@@ -428,7 +428,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
scopes(frameId: number, threadId: number): Promise<DebugProtocol.ScopesResponse> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'scopes'));
|
||||
}
|
||||
|
||||
const token = this.getNewCancellationToken(threadId);
|
||||
@@ -437,7 +437,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
variables(variablesReference: number, threadId: number | undefined, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise<DebugProtocol.VariablesResponse> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'variables'));
|
||||
}
|
||||
|
||||
const token = threadId ? this.getNewCancellationToken(threadId) : undefined;
|
||||
@@ -446,7 +446,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
evaluate(expression: string, frameId: number, context?: string): Promise<DebugProtocol.EvaluateResponse> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'evaluate'));
|
||||
}
|
||||
|
||||
return this.raw.evaluate({ expression, frameId, context });
|
||||
@@ -454,7 +454,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async restartFrame(frameId: number, threadId: number): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'restartFrame'));
|
||||
}
|
||||
|
||||
await this.raw.restartFrame({ frameId }, threadId);
|
||||
@@ -462,7 +462,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async next(threadId: number): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'next'));
|
||||
}
|
||||
|
||||
await this.raw.next({ threadId });
|
||||
@@ -470,7 +470,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async stepIn(threadId: number): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stepIn'));
|
||||
}
|
||||
|
||||
await this.raw.stepIn({ threadId });
|
||||
@@ -478,7 +478,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async stepOut(threadId: number): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stepOut'));
|
||||
}
|
||||
|
||||
await this.raw.stepOut({ threadId });
|
||||
@@ -486,7 +486,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async stepBack(threadId: number): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'stepBack'));
|
||||
}
|
||||
|
||||
await this.raw.stepBack({ threadId });
|
||||
@@ -494,7 +494,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async continue(threadId: number): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'continue'));
|
||||
}
|
||||
|
||||
await this.raw.continue({ threadId });
|
||||
@@ -502,7 +502,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async reverseContinue(threadId: number): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'reverse continue'));
|
||||
}
|
||||
|
||||
await this.raw.reverseContinue({ threadId });
|
||||
@@ -510,7 +510,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async pause(threadId: number): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'pause'));
|
||||
}
|
||||
|
||||
await this.raw.pause({ threadId });
|
||||
@@ -518,7 +518,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async terminateThreads(threadIds?: number[]): Promise<void> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'terminateThreads'));
|
||||
}
|
||||
|
||||
await this.raw.terminateThreads({ threadIds });
|
||||
@@ -526,7 +526,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
setVariable(variablesReference: number, name: string, value: string): Promise<DebugProtocol.SetVariableResponse> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'setVariable'));
|
||||
}
|
||||
|
||||
return this.raw.setVariable({ variablesReference, name, value });
|
||||
@@ -534,7 +534,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
gotoTargets(source: DebugProtocol.Source, line: number, column?: number): Promise<DebugProtocol.GotoTargetsResponse> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'gotoTargets'));
|
||||
}
|
||||
|
||||
return this.raw.gotoTargets({ source, line, column });
|
||||
@@ -542,7 +542,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
goto(threadId: number, targetId: number): Promise<DebugProtocol.GotoResponse> {
|
||||
if (!this.raw) {
|
||||
throw new Error('no debug adapter');
|
||||
throw new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'goto'));
|
||||
}
|
||||
|
||||
return this.raw.goto({ threadId, targetId });
|
||||
@@ -550,7 +550,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
loadSource(resource: URI): Promise<DebugProtocol.SourceResponse> {
|
||||
if (!this.raw) {
|
||||
return Promise.reject(new Error('no debug adapter'));
|
||||
return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'loadSource')));
|
||||
}
|
||||
|
||||
const source = this.getSourceForUri(resource);
|
||||
@@ -568,7 +568,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async getLoadedSources(): Promise<Source[]> {
|
||||
if (!this.raw) {
|
||||
return Promise.reject(new Error('no debug adapter'));
|
||||
return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'getLoadedSources')));
|
||||
}
|
||||
|
||||
const response = await this.raw.loadedSources({});
|
||||
@@ -581,7 +581,7 @@ export class DebugSession implements IDebugSession {
|
||||
|
||||
async completions(frameId: number | undefined, text: string, position: Position, overwriteBefore: number, token: CancellationToken): Promise<DebugProtocol.CompletionsResponse> {
|
||||
if (!this.raw) {
|
||||
return Promise.reject(new Error('no debug adapter'));
|
||||
return Promise.reject(new Error(localize('noDebugAdapter', "No debug adapter, can not send '{0}'", 'completions')));
|
||||
}
|
||||
|
||||
return this.raw.completions({
|
||||
@@ -700,7 +700,7 @@ export class DebugSession implements IDebugSession {
|
||||
}
|
||||
|
||||
this.rawListeners.push(this.raw.onDidInitialize(async () => {
|
||||
aria.status(nls.localize('debuggingStarted', "Debugging started."));
|
||||
aria.status(localize('debuggingStarted', "Debugging started."));
|
||||
const sendConfigurationDone = async () => {
|
||||
if (this.raw && this.raw.capabilities.supportsConfigurationDoneRequest) {
|
||||
try {
|
||||
@@ -782,7 +782,7 @@ export class DebugSession implements IDebugSession {
|
||||
}));
|
||||
|
||||
this.rawListeners.push(this.raw.onDidTerminateDebugee(async event => {
|
||||
aria.status(nls.localize('debuggingStopped', "Debugging stopped."));
|
||||
aria.status(localize('debuggingStopped', "Debugging stopped."));
|
||||
if (event.body && event.body.restart) {
|
||||
await this.debugService.restartSession(this, event.body.restart);
|
||||
} else if (this.raw) {
|
||||
|
||||
@@ -230,7 +230,7 @@ export class RawDebugSession implements IDisposable {
|
||||
*/
|
||||
async start(): Promise<void> {
|
||||
if (!this.debugAdapter) {
|
||||
return Promise.reject(new Error('no debug adapter'));
|
||||
return Promise.reject(new Error(nls.localize('noDebugAdapterStart', "No debug adapter, can not start debug session.")));
|
||||
}
|
||||
|
||||
await this.debugAdapter.startSession();
|
||||
|
||||
@@ -754,18 +754,24 @@ export class ShowOpenedFileInNewWindow extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
export function validateFileName(item: ExplorerItem, name: string): string | null {
|
||||
export function validateFileName(item: ExplorerItem, name: string): { content: string, severity: Severity } | null {
|
||||
// Produce a well formed file name
|
||||
name = getWellFormedFileName(name);
|
||||
|
||||
// Name not provided
|
||||
if (!name || name.length === 0 || /^\s+$/.test(name)) {
|
||||
return nls.localize('emptyFileNameError', "A file or folder name must be provided.");
|
||||
return {
|
||||
content: nls.localize('emptyFileNameError', "A file or folder name must be provided."),
|
||||
severity: Severity.Error
|
||||
};
|
||||
}
|
||||
|
||||
// Relative paths only
|
||||
if (name[0] === '/' || name[0] === '\\') {
|
||||
return nls.localize('fileNameStartsWithSlashError', "A file or folder name cannot start with a slash.");
|
||||
return {
|
||||
content: nls.localize('fileNameStartsWithSlashError', "A file or folder name cannot start with a slash."),
|
||||
severity: Severity.Error
|
||||
};
|
||||
}
|
||||
|
||||
const names = coalesce(name.split(/[\\/]/));
|
||||
@@ -775,14 +781,27 @@ export function validateFileName(item: ExplorerItem, name: string): string | nul
|
||||
// Do not allow to overwrite existing file
|
||||
const child = parent?.getChild(name);
|
||||
if (child && child !== item) {
|
||||
return nls.localize('fileNameExistsError', "A file or folder **{0}** already exists at this location. Please choose a different name.", name);
|
||||
return {
|
||||
content: nls.localize('fileNameExistsError', "A file or folder **{0}** already exists at this location. Please choose a different name.", name),
|
||||
severity: Severity.Error
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid File name
|
||||
const windowsBasenameValidity = item.resource.scheme === Schemas.file && isWindows;
|
||||
if (names.some((folderName) => !extpath.isValidBasename(folderName, windowsBasenameValidity))) {
|
||||
return nls.localize('invalidFileNameError', "The name **{0}** is not valid as a file or folder name. Please choose a different name.", trimLongName(name));
|
||||
return {
|
||||
content: nls.localize('invalidFileNameError', "The name **{0}** is not valid as a file or folder name. Please choose a different name.", trimLongName(name)),
|
||||
severity: Severity.Error
|
||||
};
|
||||
}
|
||||
|
||||
if (names.some(name => /^\s|\s$/.test(name))) {
|
||||
return {
|
||||
content: nls.localize('fileNameWhitespaceWarning', "Leading or trailing whitespace detected in file or folder name."),
|
||||
severity: Severity.Warning
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -804,7 +823,7 @@ export function getWellFormedFileName(filename: string): string {
|
||||
// Trim tabs
|
||||
filename = strings.trim(filename, '\t');
|
||||
|
||||
// Remove trailing dots, slashes, and spaces
|
||||
// Remove trailing dots and slashes
|
||||
filename = strings.rtrim(filename, '.');
|
||||
filename = strings.rtrim(filename, '/');
|
||||
filename = strings.rtrim(filename, '\\');
|
||||
|
||||
@@ -376,13 +376,13 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
|
||||
const inputBox = new InputBox(label.element, this.contextViewService, {
|
||||
validationOptions: {
|
||||
validation: (value) => {
|
||||
const content = editableData.validationMessage(value);
|
||||
if (!content) {
|
||||
const message = editableData.validationMessage(value);
|
||||
if (!message || message.severity !== Severity.Error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
content,
|
||||
content: message.content,
|
||||
formatContent: true,
|
||||
type: MessageType.ERROR
|
||||
};
|
||||
@@ -392,10 +392,6 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
|
||||
});
|
||||
const styler = attachInputBoxStyler(inputBox, this.themeService);
|
||||
|
||||
inputBox.onDidChange(value => {
|
||||
label.setFile(joinPath(parent, value || ' '), labelOptions); // update label icon while typing!
|
||||
});
|
||||
|
||||
const lastDot = value.lastIndexOf('.');
|
||||
|
||||
inputBox.value = value;
|
||||
@@ -412,8 +408,27 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
|
||||
}
|
||||
});
|
||||
|
||||
const showInputBoxNotification = () => {
|
||||
if (inputBox.isInputValid()) {
|
||||
const message = editableData.validationMessage(inputBox.value);
|
||||
if (message) {
|
||||
inputBox.showMessage({
|
||||
content: message.content,
|
||||
formatContent: true,
|
||||
type: message.severity === Severity.Info ? MessageType.INFO : message.severity === Severity.Warning ? MessageType.WARNING : MessageType.ERROR
|
||||
});
|
||||
} else {
|
||||
inputBox.hideMessage();
|
||||
}
|
||||
}
|
||||
};
|
||||
showInputBoxNotification();
|
||||
|
||||
const toDispose = [
|
||||
inputBox,
|
||||
inputBox.onDidChange(value => {
|
||||
label.setFile(joinPath(parent, value || ' '), labelOptions); // update label icon while typing!
|
||||
}),
|
||||
DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: IKeyboardEvent) => {
|
||||
if (e.equals(KeyCode.Enter)) {
|
||||
if (inputBox.validate()) {
|
||||
@@ -423,6 +438,9 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
|
||||
done(false, true);
|
||||
}
|
||||
}),
|
||||
DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_UP, (e: IKeyboardEvent) => {
|
||||
showInputBoxNotification();
|
||||
}),
|
||||
DOM.addDisposableListener(inputBox.inputElement, DOM.EventType.BLUR, () => {
|
||||
done(inputBox.isInputValid(), true);
|
||||
}),
|
||||
|
||||
@@ -95,6 +95,7 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
|
||||
if (this.contextKeyService.contextMatchesRules(view.when)) {
|
||||
result.push({
|
||||
label: view.name,
|
||||
ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", view.name),
|
||||
containerLabel: viewlet.name,
|
||||
accept: () => this.viewsService.openView(view.id, true)
|
||||
});
|
||||
@@ -110,6 +111,7 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
|
||||
if (this.includeViewlet(viewlet)) {
|
||||
viewEntries.push({
|
||||
label: viewlet.name,
|
||||
ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", viewlet.name),
|
||||
containerLabel: localize('views', "Side Bar"),
|
||||
accept: () => this.viewletService.openViewlet(viewlet.id, true)
|
||||
});
|
||||
@@ -121,6 +123,7 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
|
||||
for (const panel of panels) {
|
||||
viewEntries.push({
|
||||
label: panel.name,
|
||||
ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", panel.name),
|
||||
containerLabel: localize('panels', "Panel"),
|
||||
accept: () => this.panelService.openPanel(panel.id, true)
|
||||
});
|
||||
@@ -137,8 +140,10 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
|
||||
// Terminals
|
||||
this.terminalService.terminalTabs.forEach((tab, tabIndex) => {
|
||||
tab.terminalInstances.forEach((terminal, terminalIndex) => {
|
||||
const label = localize('terminalTitle', "{0}: {1}", `${tabIndex + 1}.${terminalIndex + 1}`, terminal.title);
|
||||
viewEntries.push({
|
||||
label: localize('terminalTitle', "{0}: {1}", `${tabIndex + 1}.${terminalIndex + 1}`, terminal.title),
|
||||
label,
|
||||
ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", label),
|
||||
containerLabel: localize('terminals', "Terminal"),
|
||||
accept: async () => {
|
||||
await this.terminalService.showPanel(true);
|
||||
@@ -152,8 +157,10 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuic
|
||||
// Output Channels
|
||||
const channels = this.outputService.getChannelDescriptors();
|
||||
for (const channel of channels) {
|
||||
const label = channel.log ? localize('logChannel', "Log ({0})", channel.label) : channel.label;
|
||||
viewEntries.push({
|
||||
label: channel.log ? localize('logChannel', "Log ({0})", channel.label) : channel.label,
|
||||
label,
|
||||
ariaLabel: localize('viewPickAriaLabel', "{0}, view picker", label),
|
||||
containerLabel: localize('channels', "Output"),
|
||||
accept: () => this.outputService.showChannel(channel.id)
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ import { IMenuService, MenuId, IMenu, MenuRegistry, MenuItemAction } from 'vs/pl
|
||||
import { createAndFillInContextMenuActions, createAndFillInActionBarActions, ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IRemoteExplorerService, TunnelModel, MakeAddress, TunnelType, ITunnelItem, Tunnel } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { InputBox, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
|
||||
import { once } from 'vs/base/common/functional';
|
||||
@@ -282,13 +282,13 @@ class TunnelTreeRenderer extends Disposable implements ITreeRenderer<ITunnelGrou
|
||||
ariaLabel: nls.localize('remote.tunnelsView.input', "Press Enter to confirm or Escape to cancel."),
|
||||
validationOptions: {
|
||||
validation: (value) => {
|
||||
const content = editableData.validationMessage(value);
|
||||
if (!content) {
|
||||
const message = editableData.validationMessage(value);
|
||||
if (!message || message.severity !== Severity.Error) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
content,
|
||||
content: message.content,
|
||||
formatContent: true,
|
||||
type: MessageType.ERROR
|
||||
};
|
||||
@@ -657,6 +657,17 @@ export class TunnelPanelDescriptor implements IViewDescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
function validationMessage(validationString: string | null): { content: string, severity: Severity } | null {
|
||||
if (!validationString) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
content: validationString,
|
||||
severity: Severity.Error
|
||||
};
|
||||
}
|
||||
|
||||
namespace LabelTunnelAction {
|
||||
export const ID = 'remote.tunnel.label';
|
||||
export const LABEL = nls.localize('remote.tunnel.label', "Set Label");
|
||||
@@ -733,7 +744,7 @@ namespace ForwardPortAction {
|
||||
}
|
||||
remoteExplorerService.setEditable(undefined, null);
|
||||
},
|
||||
validationMessage: validateInput,
|
||||
validationMessage: (value) => validationMessage(validateInput(value)),
|
||||
placeholder: forwardPrompt
|
||||
});
|
||||
}
|
||||
@@ -916,7 +927,7 @@ namespace ChangeLocalPortAction {
|
||||
}
|
||||
}
|
||||
},
|
||||
validationMessage: validateInput,
|
||||
validationMessage: (value) => validationMessage(validateInput(value)),
|
||||
placeholder: nls.localize('remote.tunnelsView.changePort', "New local port")
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IPickerQuickAccessItem, PickerQuickAccessProvider } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { matchesFuzzy } from 'vs/base/common/filters';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ITaskService } from 'vs/workbench/contrib/tasks/common/taskService';
|
||||
@@ -59,14 +59,12 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
|
||||
taskMap[key] = task;
|
||||
}
|
||||
}
|
||||
|
||||
recentlyUsedTasks.keys().forEach(key => {
|
||||
for (const key of recentlyUsedTasks.keys()) {
|
||||
const task = taskMap[key];
|
||||
if (task) {
|
||||
recent.push(task);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
for (const task of tasks) {
|
||||
const key = task.getRecentlyUsedKey();
|
||||
if (!key || !recentlyUsedTasks.has(key)) {
|
||||
@@ -83,13 +81,13 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
|
||||
|
||||
// Fill picks in sorted order
|
||||
|
||||
this.fillPicks(taskPicks, filter, recent, localize('recentlyUsed', 'recently used tasks'));
|
||||
this.fillPicks(taskPicks, filter, recent, localize('recentlyUsed', "recently used tasks"));
|
||||
|
||||
configured.sort((a, b) => sorter.compare(a, b));
|
||||
this.fillPicks(taskPicks, filter, configured, localize('configured', 'configured tasks'));
|
||||
this.fillPicks(taskPicks, filter, configured, localize('configured', "configured tasks"));
|
||||
|
||||
detected.sort((a, b) => sorter.compare(a, b));
|
||||
this.fillPicks(taskPicks, filter, detected, localize('detected', 'detected tasks'));
|
||||
this.fillPicks(taskPicks, filter, detected, localize('detected', "detected tasks"));
|
||||
|
||||
return taskPicks;
|
||||
}
|
||||
@@ -107,7 +105,7 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
|
||||
}
|
||||
taskPicks.push({
|
||||
label: task._label,
|
||||
ariaLabel: localize('entryAriaLabel', "{0}, tasks", task._label),
|
||||
ariaLabel: localize('entryAriaLabel', "{0}, tasks picker", task._label),
|
||||
description: this.taskService.getTaskDescription(task),
|
||||
highlights: { label: highlights },
|
||||
buttons: (() => {
|
||||
@@ -122,9 +120,6 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
|
||||
|
||||
return buttons;
|
||||
})(),
|
||||
accept: () => {
|
||||
this.taskService.run(task, { attachProblemMatcher: true });
|
||||
},
|
||||
trigger: () => {
|
||||
if (ContributedTask.is(task)) {
|
||||
this.taskService.customize(task, undefined, true);
|
||||
@@ -132,7 +127,10 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider<IPickerQ
|
||||
this.taskService.openConfig(task);
|
||||
}
|
||||
|
||||
return true; // close picker
|
||||
return TriggerAction.CLOSE_PICKER;
|
||||
},
|
||||
accept: () => {
|
||||
this.taskService.run(task, { attachProblemMatcher: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { matchesFuzzy } from 'vs/base/common/filters';
|
||||
import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
|
||||
export class TerminalQuickAccessProvider extends PickerQuickAccessProvider<IPickerQuickAccessItem> {
|
||||
|
||||
static PREFIX = 'term ';
|
||||
|
||||
constructor(
|
||||
@ITerminalService private readonly terminalService: ITerminalService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
) {
|
||||
super(TerminalQuickAccessProvider.PREFIX);
|
||||
}
|
||||
|
||||
protected getPicks(filter: string): Array<IPickerQuickAccessItem | IQuickPickSeparator> {
|
||||
const terminalPicks: Array<IPickerQuickAccessItem | IQuickPickSeparator> = [];
|
||||
|
||||
const terminalTabs = this.terminalService.terminalTabs;
|
||||
for (let tabIndex = 0; tabIndex < terminalTabs.length; tabIndex++) {
|
||||
const terminalTab = terminalTabs[tabIndex];
|
||||
for (let terminalIndex = 0; terminalIndex < terminalTab.terminalInstances.length; terminalIndex++) {
|
||||
const terminal = terminalTab.terminalInstances[terminalIndex];
|
||||
const label = `${tabIndex + 1}.${terminalIndex + 1}: ${terminal.title}`;
|
||||
|
||||
const highlights = matchesFuzzy(filter, label, true);
|
||||
if (highlights) {
|
||||
terminalPicks.push({
|
||||
label,
|
||||
ariaLabel: localize('termEntryAriaLabel', "{0}, terminal picker", label),
|
||||
highlights: { label: highlights },
|
||||
buttons: [
|
||||
{
|
||||
iconClass: 'codicon-gear',
|
||||
tooltip: localize('renameTerminal', "Rename Terminal")
|
||||
},
|
||||
{
|
||||
iconClass: 'codicon-trash',
|
||||
tooltip: localize('killTerminal', "Kill Terminal Instance")
|
||||
}
|
||||
],
|
||||
trigger: buttonIndex => {
|
||||
switch (buttonIndex) {
|
||||
case 0:
|
||||
this.commandService.executeCommand(TERMINAL_COMMAND_ID.RENAME, terminal);
|
||||
return TriggerAction.NO_ACTION;
|
||||
case 1:
|
||||
terminal.dispose(true);
|
||||
return TriggerAction.REFRESH_PICKER;
|
||||
}
|
||||
|
||||
return TriggerAction.NO_ACTION;
|
||||
},
|
||||
accept: () => {
|
||||
this.terminalService.setActiveInstance(terminal);
|
||||
this.terminalService.showPanel(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (terminalPicks.length > 0) {
|
||||
terminalPicks.push({ type: 'separator' });
|
||||
}
|
||||
|
||||
const createTerminalLabel = localize("workbench.action.terminal.newplus", "Create New Integrated Terminal");
|
||||
terminalPicks.push({
|
||||
label: `$(plus) ${createTerminalLabel}`,
|
||||
ariaLabel: localize('termEntryAriaLabel', "{0}, terminal picker", createTerminalLabel),
|
||||
accept: () => this.commandService.executeCommand('workbench.action.terminal.new')
|
||||
});
|
||||
|
||||
return terminalPicks;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,8 @@ import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal
|
||||
import { BrowserFeatures } from 'vs/base/browser/canIUse';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminaQuickAccess';
|
||||
|
||||
registerSingleton(ITerminalService, TerminalService, true);
|
||||
|
||||
@@ -60,6 +62,16 @@ quickOpenRegistry.registerQuickOpenHandler(
|
||||
)
|
||||
);
|
||||
|
||||
const quickAccessRegistry = (Registry.as<IQuickAccessRegistry>(QuickAccessExtensions.Quickaccess));
|
||||
|
||||
quickAccessRegistry.registerQuickAccessProvider({
|
||||
ctor: TerminalQuickAccessProvider,
|
||||
prefix: TerminalQuickAccessProvider.PREFIX,
|
||||
contextKey: inTerminalsPicker,
|
||||
placeholder: nls.localize('tasksQuickAccessPlaceholder', "Type the name of a terminal to open."),
|
||||
helpEntries: [{ description: nls.localize('tasksQuickAccessHelp', "Show All Opened Terminals"), needsEditor: false }]
|
||||
});
|
||||
|
||||
const quickOpenNavigateNextInTerminalPickerId = 'workbench.action.quickOpenNavigateNextInTerminalPicker';
|
||||
CommandsRegistry.registerCommand(
|
||||
{ id: quickOpenNavigateNextInTerminalPickerId, handler: getQuickNavigateHandler(quickOpenNavigateNextInTerminalPickerId, true) });
|
||||
|
||||
@@ -24,7 +24,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati
|
||||
import { ITimelineService, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvidersChangeEvent, TimelineRequest, Timeline, TimelinePaneId } from 'vs/workbench/contrib/timeline/common/timeline';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { SideBySideEditor, toResource } from 'vs/workbench/common/editor';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IThemeService, LIGHT, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { basename } from 'vs/base/common/path';
|
||||
@@ -34,7 +34,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IActionViewItemProvider, ActionBar, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction, ActionRunner } from 'vs/base/common/actions';
|
||||
import { ContextAwareMenuEntryActionViewItem, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { MenuItemAction, IMenuService, MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
|
||||
import { MenuItemAction, IMenuService, MenuId, registerAction2, Action2, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { fromNow } from 'vs/base/common/date';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { escapeRegExpCharacters } from 'vs/base/common/strings';
|
||||
@@ -403,7 +403,7 @@ export class TimelinePane extends ViewPane {
|
||||
private async handleRequest(request: TimelineRequest) {
|
||||
let timeline: Timeline | undefined;
|
||||
try {
|
||||
timeline = await this.progressService.withProgress({ location: this.getProgressLocation() }, () => request.result);
|
||||
timeline = await this.progressService.withProgress({ location: this.id }, () => request.result);
|
||||
}
|
||||
finally {
|
||||
this._pendingRequests.delete(request.source);
|
||||
@@ -932,38 +932,35 @@ class TimelinePaneCommands extends Disposable {
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(registerAction2(class extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'timeline.toggleFollowActiveEditor',
|
||||
title: { value: localize('timeline.toggleFollowActiveEditorCommand', "Toggle Active Editor Following"), original: 'Toggle Active Editor Following' },
|
||||
category: { value: localize('timeline', "Timeline"), original: 'Timeline' },
|
||||
menu: [{
|
||||
id: MenuId.TimelineTitle,
|
||||
command: {
|
||||
// title: localize(`timeline.toggleFollowActiveEditorCommand.stop`, "Stop following the Active Editor"),
|
||||
icon: { id: 'codicon/eye' }
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 98,
|
||||
when: TimelineFollowActiveEditorContext
|
||||
},
|
||||
{
|
||||
id: MenuId.TimelineTitle,
|
||||
command: {
|
||||
// title: localize(`ToggleFollowActiveEditorCommand.follow`, "Follow the Active Editor"),
|
||||
icon: { id: 'codicon/eye-closed' }
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 98,
|
||||
when: TimelineFollowActiveEditorContext.toNegated()
|
||||
}]
|
||||
});
|
||||
}
|
||||
run(accessor: ServicesAccessor, ...args: any[]) {
|
||||
pane.followActiveEditor = !pane.followActiveEditor;
|
||||
}
|
||||
}));
|
||||
this._register(CommandsRegistry.registerCommand('timeline.toggleFollowActiveEditor',
|
||||
(accessor: ServicesAccessor, ...args: any[]) => pane.followActiveEditor = !pane.followActiveEditor
|
||||
));
|
||||
|
||||
this._register(MenuRegistry.appendMenuItem(MenuId.TimelineTitle, ({
|
||||
command: {
|
||||
id: 'timeline.toggleFollowActiveEditor',
|
||||
title: { value: localize('timeline.toggleFollowActiveEditorCommand', "Toggle Active Editor Following"), original: 'Toggle Active Editor Following' },
|
||||
// title: localize(`timeline.toggleFollowActiveEditorCommand.stop`, "Stop following the Active Editor"),
|
||||
icon: { id: 'codicon/eye' },
|
||||
category: { value: localize('timeline', "Timeline"), original: 'Timeline' },
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 98,
|
||||
when: TimelineFollowActiveEditorContext
|
||||
})));
|
||||
|
||||
this._register(MenuRegistry.appendMenuItem(MenuId.TimelineTitle, ({
|
||||
command: {
|
||||
id: 'timeline.toggleFollowActiveEditor',
|
||||
title: { value: localize('timeline.toggleFollowActiveEditorCommand', "Toggle Active Editor Following"), original: 'Toggle Active Editor Following' },
|
||||
// title: localize(`timeline.toggleFollowActiveEditorCommand.stop`, "Stop following the Active Editor"),
|
||||
icon: { id: 'codicon/eye-closed' },
|
||||
category: { value: localize('timeline', "Timeline"), original: 'Timeline' },
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 98,
|
||||
when: TimelineFollowActiveEditorContext.toNegated()
|
||||
})));
|
||||
|
||||
this._register(timelineService.onDidChangeProviders(() => this.updateTimelineSourceFilters()));
|
||||
this.updateTimelineSourceFilters();
|
||||
|
||||
@@ -30,7 +30,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { CONTEXT_SYNC_STATE, getUserDataSyncStore, ISyncConfiguration, IUserDataAutoSyncService, IUserDataSyncService, IUserDataSyncStore, registerConfiguration, SyncSource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, USER_DATA_SYNC_SCHEME, IUserDataSyncEnablementService, ResourceKey, getSyncSourceFromPreviewResource, CONTEXT_SYNC_ENABLEMENT, toRemoteSyncResourceFromSource, PREVIEW_QUERY, resolveSyncResource, getSyncSourceFromResourceKey } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { CONTEXT_SYNC_STATE, getUserDataSyncStore, ISyncConfiguration, IUserDataAutoSyncService, IUserDataSyncService, IUserDataSyncStore, registerConfiguration, SyncResource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, USER_DATA_SYNC_SCHEME, IUserDataSyncEnablementService, getSyncSourceFromPreviewResource, CONTEXT_SYNC_ENABLEMENT, PREVIEW_QUERY, resolveSyncResource, toRemoteSyncResource } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { FloatingClickWidget } from 'vs/workbench/browser/parts/editor/editorWidgets';
|
||||
import { GLOBAL_ACTIVITY_ID } from 'vs/workbench/common/activity';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
@@ -60,14 +60,14 @@ const enum AuthStatus {
|
||||
const CONTEXT_AUTH_TOKEN_STATE = new RawContextKey<string>('authTokenStatus', AuthStatus.Initializing);
|
||||
const CONTEXT_CONFLICTS_SOURCES = new RawContextKey<string>('conflictsSources', '');
|
||||
|
||||
type ConfigureSyncQuickPickItem = { id: ResourceKey, label: string, description?: string };
|
||||
type ConfigureSyncQuickPickItem = { id: SyncResource, label: string, description?: string };
|
||||
|
||||
function getSyncAreaLabel(source: SyncSource): string {
|
||||
function getSyncAreaLabel(source: SyncResource): string {
|
||||
switch (source) {
|
||||
case SyncSource.Settings: return localize('settings', "Settings");
|
||||
case SyncSource.Keybindings: return localize('keybindings', "Keyboard Shortcuts");
|
||||
case SyncSource.Extensions: return localize('extensions', "Extensions");
|
||||
case SyncSource.GlobalState: return localize('ui state label', "UI State");
|
||||
case SyncResource.Settings: return localize('settings', "Settings");
|
||||
case SyncResource.Keybindings: return localize('keybindings', "Keyboard Shortcuts");
|
||||
case SyncResource.Extensions: return localize('extensions', "Extensions");
|
||||
case SyncResource.GlobalState: return localize('ui state label', "UI State");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,8 +283,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
this.updateBadge();
|
||||
}
|
||||
|
||||
private readonly conflictsDisposables = new Map<SyncSource, IDisposable>();
|
||||
private onDidChangeConflicts(conflicts: SyncSource[]) {
|
||||
private readonly conflictsDisposables = new Map<SyncResource, IDisposable>();
|
||||
private onDidChangeConflicts(conflicts: SyncResource[]) {
|
||||
this.updateBadge();
|
||||
if (conflicts.length) {
|
||||
this.conflictsSources.set(this.userDataSyncService.conflictsSources.join(','));
|
||||
@@ -352,22 +352,22 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
}
|
||||
}
|
||||
|
||||
private async acceptRemote(syncSource: SyncSource) {
|
||||
private async acceptRemote(syncResource: SyncResource) {
|
||||
try {
|
||||
const contents = await this.userDataSyncService.resolveContent(toRemoteSyncResourceFromSource(syncSource).with({ query: PREVIEW_QUERY }));
|
||||
const contents = await this.userDataSyncService.resolveContent(toRemoteSyncResource(syncResource).with({ query: PREVIEW_QUERY }));
|
||||
if (contents) {
|
||||
await this.userDataSyncService.accept(syncSource, contents);
|
||||
await this.userDataSyncService.accept(syncResource, contents);
|
||||
}
|
||||
} catch (e) {
|
||||
this.notificationService.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private async acceptLocal(syncSource: SyncSource): Promise<void> {
|
||||
private async acceptLocal(syncSource: SyncResource): Promise<void> {
|
||||
try {
|
||||
const previewResource = syncSource === SyncSource.Settings
|
||||
const previewResource = syncSource === SyncResource.Settings
|
||||
? this.workbenchEnvironmentService.settingsSyncPreviewResource
|
||||
: syncSource === SyncSource.Keybindings
|
||||
: syncSource === SyncResource.Keybindings
|
||||
? this.workbenchEnvironmentService.keybindingsSyncPreviewResource
|
||||
: null;
|
||||
if (previewResource) {
|
||||
@@ -415,15 +415,15 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
});
|
||||
return;
|
||||
case UserDataSyncErrorCode.TooLarge:
|
||||
if (error.source === SyncSource.Keybindings || error.source === SyncSource.Settings) {
|
||||
this.disableSync(error.source);
|
||||
const sourceArea = getSyncAreaLabel(error.source);
|
||||
if (error.resource === SyncResource.Keybindings || error.resource === SyncResource.Settings) {
|
||||
this.disableSync(error.resource);
|
||||
const sourceArea = getSyncAreaLabel(error.resource);
|
||||
this.notificationService.notify({
|
||||
severity: Severity.Error,
|
||||
message: localize('too large', "Disabled syncing {0} because size of the {1} file to sync is larger than {2}. Please open the file and reduce the size and enable sync", sourceArea.toLowerCase(), sourceArea.toLowerCase(), '100kb'),
|
||||
actions: {
|
||||
primary: [new Action('open sync file', localize('open file', "Open {0} File", sourceArea), undefined, true,
|
||||
() => error.source === SyncSource.Settings ? this.preferencesService.openGlobalSettings(true) : this.preferencesService.openGlobalKeybindingSettings(true))]
|
||||
() => error.resource === SyncResource.Settings ? this.preferencesService.openGlobalSettings(true) : this.preferencesService.openGlobalKeybindingSettings(true))]
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -438,8 +438,8 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
}
|
||||
}
|
||||
|
||||
private readonly invalidContentErrorDisposables = new Map<SyncSource, IDisposable>();
|
||||
private onSyncErrors(errors: [SyncSource, UserDataSyncError][]): void {
|
||||
private readonly invalidContentErrorDisposables = new Map<SyncResource, IDisposable>();
|
||||
private onSyncErrors(errors: [SyncResource, UserDataSyncError][]): void {
|
||||
if (errors.length) {
|
||||
for (const [source, error] of errors) {
|
||||
switch (error.code) {
|
||||
@@ -460,14 +460,14 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
}
|
||||
}
|
||||
|
||||
private handleInvalidContentError(source: SyncSource): void {
|
||||
private handleInvalidContentError(source: SyncResource): void {
|
||||
if (this.invalidContentErrorDisposables.has(source)) {
|
||||
return;
|
||||
}
|
||||
if (source !== SyncSource.Settings && source !== SyncSource.Keybindings) {
|
||||
if (source !== SyncResource.Settings && source !== SyncResource.Keybindings) {
|
||||
return;
|
||||
}
|
||||
const resource = source === SyncSource.Settings ? this.workbenchEnvironmentService.settingsResource : this.workbenchEnvironmentService.keybindingsResource;
|
||||
const resource = source === SyncResource.Settings ? this.workbenchEnvironmentService.settingsResource : this.workbenchEnvironmentService.keybindingsResource;
|
||||
if (isEqual(resource, toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.MASTER }))) {
|
||||
// Do not show notification if the file in error is active
|
||||
return;
|
||||
@@ -478,7 +478,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
message: localize('errorInvalidConfiguration', "Unable to sync {0} because there are some errors/warnings in the file. Please open the file to correct errors/warnings in it.", errorArea.toLowerCase()),
|
||||
actions: {
|
||||
primary: [new Action('open sync file', localize('open file', "Open {0} File", errorArea), undefined, true,
|
||||
() => source === SyncSource.Settings ? this.preferencesService.openGlobalSettings(true) : this.preferencesService.openGlobalKeybindingSettings(true))]
|
||||
() => source === SyncResource.Settings ? this.preferencesService.openGlobalSettings(true) : this.preferencesService.openGlobalKeybindingSettings(true))]
|
||||
}
|
||||
});
|
||||
this.invalidContentErrorDisposables.set(source, toDisposable(() => {
|
||||
@@ -602,17 +602,17 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
|
||||
private getConfigureSyncQuickPickItems(): ConfigureSyncQuickPickItem[] {
|
||||
return [{
|
||||
id: 'settings',
|
||||
label: getSyncAreaLabel(SyncSource.Settings)
|
||||
id: SyncResource.Settings,
|
||||
label: getSyncAreaLabel(SyncResource.Settings)
|
||||
}, {
|
||||
id: 'keybindings',
|
||||
label: getSyncAreaLabel(SyncSource.Keybindings)
|
||||
id: SyncResource.Keybindings,
|
||||
label: getSyncAreaLabel(SyncResource.Keybindings)
|
||||
}, {
|
||||
id: 'extensions',
|
||||
label: getSyncAreaLabel(SyncSource.Extensions)
|
||||
id: SyncResource.Extensions,
|
||||
label: getSyncAreaLabel(SyncResource.Extensions)
|
||||
}, {
|
||||
id: 'globalState',
|
||||
label: getSyncAreaLabel(SyncSource.GlobalState),
|
||||
id: SyncResource.GlobalState,
|
||||
label: getSyncAreaLabel(SyncResource.GlobalState),
|
||||
description: localize('ui state description', "only 'Display Language' for now")
|
||||
}];
|
||||
}
|
||||
@@ -707,15 +707,15 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
}
|
||||
}
|
||||
|
||||
private disableSync(source?: SyncSource): void {
|
||||
private disableSync(source?: SyncResource): void {
|
||||
if (source === undefined) {
|
||||
this.userDataSyncEnablementService.setEnablement(false);
|
||||
} else {
|
||||
switch (source) {
|
||||
case SyncSource.Settings: return this.userDataSyncEnablementService.setResourceEnablement('settings', false);
|
||||
case SyncSource.Keybindings: return this.userDataSyncEnablementService.setResourceEnablement('keybindings', false);
|
||||
case SyncSource.Extensions: return this.userDataSyncEnablementService.setResourceEnablement('extensions', false);
|
||||
case SyncSource.GlobalState: return this.userDataSyncEnablementService.setResourceEnablement('globalState', false);
|
||||
case SyncResource.Settings: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.Settings, false);
|
||||
case SyncResource.Keybindings: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.Keybindings, false);
|
||||
case SyncResource.Extensions: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.Extensions, false);
|
||||
case SyncResource.GlobalState: return this.userDataSyncEnablementService.setResourceEnablement(SyncResource.GlobalState, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -729,9 +729,9 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
}
|
||||
}
|
||||
|
||||
private getConflictsEditorInput(source: SyncSource): IEditorInput | undefined {
|
||||
const previewResource = source === SyncSource.Settings ? this.workbenchEnvironmentService.settingsSyncPreviewResource
|
||||
: source === SyncSource.Keybindings ? this.workbenchEnvironmentService.keybindingsSyncPreviewResource
|
||||
private getConflictsEditorInput(source: SyncResource): IEditorInput | undefined {
|
||||
const previewResource = source === SyncResource.Settings ? this.workbenchEnvironmentService.settingsSyncPreviewResource
|
||||
: source === SyncResource.Keybindings ? this.workbenchEnvironmentService.keybindingsSyncPreviewResource
|
||||
: null;
|
||||
return previewResource ? this.editorService.editors.filter(input => input instanceof DiffEditorInput && isEqual(previewResource, input.master.resource))[0] : undefined;
|
||||
}
|
||||
@@ -743,18 +743,18 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
});
|
||||
}
|
||||
|
||||
private async handleConflicts(source: SyncSource): Promise<void> {
|
||||
private async handleConflicts(resource: SyncResource): Promise<void> {
|
||||
let previewResource: URI | undefined = undefined;
|
||||
let label: string = '';
|
||||
if (source === SyncSource.Settings) {
|
||||
if (resource === SyncResource.Settings) {
|
||||
previewResource = this.workbenchEnvironmentService.settingsSyncPreviewResource;
|
||||
label = localize('settings conflicts preview', "Settings Conflicts (Remote ↔ Local)");
|
||||
} else if (source === SyncSource.Keybindings) {
|
||||
} else if (resource === SyncResource.Keybindings) {
|
||||
previewResource = this.workbenchEnvironmentService.keybindingsSyncPreviewResource;
|
||||
label = localize('keybindings conflicts preview', "Keybindings Conflicts (Remote ↔ Local)");
|
||||
}
|
||||
if (previewResource) {
|
||||
const remoteContentResource = toRemoteSyncResourceFromSource(source).with({ query: PREVIEW_QUERY });
|
||||
const remoteContentResource = toRemoteSyncResource(resource).with({ query: PREVIEW_QUERY });
|
||||
await this.editorService.openEditor({
|
||||
leftResource: remoteContentResource,
|
||||
rightResource: previewResource,
|
||||
@@ -846,7 +846,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
|
||||
private registerShowSettingsConflictsAction(): void {
|
||||
const resolveSettingsConflictsWhenContext = ContextKeyExpr.regex(CONTEXT_CONFLICTS_SOURCES.keys()[0], /.*settings.*/i);
|
||||
CommandsRegistry.registerCommand(resolveSettingsConflictsCommand.id, () => this.handleConflicts(SyncSource.Settings));
|
||||
CommandsRegistry.registerCommand(resolveSettingsConflictsCommand.id, () => this.handleConflicts(SyncResource.Settings));
|
||||
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
|
||||
group: '5_sync',
|
||||
command: {
|
||||
@@ -873,7 +873,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
|
||||
private registerShowKeybindingsConflictsAction(): void {
|
||||
const resolveKeybindingsConflictsWhenContext = ContextKeyExpr.regex(CONTEXT_CONFLICTS_SOURCES.keys()[0], /.*keybindings.*/i);
|
||||
CommandsRegistry.registerCommand(resolveKeybindingsConflictsCommand.id, () => this.handleConflicts(SyncSource.Keybindings));
|
||||
CommandsRegistry.registerCommand(resolveKeybindingsConflictsCommand.id, () => this.handleConflicts(SyncResource.Keybindings));
|
||||
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
|
||||
group: '5_sync',
|
||||
command: {
|
||||
@@ -934,10 +934,10 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
if (that.userDataSyncService.conflictsSources.length) {
|
||||
for (const source of that.userDataSyncService.conflictsSources) {
|
||||
switch (source) {
|
||||
case SyncSource.Settings:
|
||||
case SyncResource.Settings:
|
||||
items.push({ id: resolveSettingsConflictsCommand.id, label: resolveSettingsConflictsCommand.title });
|
||||
break;
|
||||
case SyncSource.Keybindings:
|
||||
case SyncResource.Keybindings:
|
||||
items.push({ id: resolveKeybindingsConflictsCommand.id, label: resolveKeybindingsConflictsCommand.title });
|
||||
break;
|
||||
}
|
||||
@@ -1130,7 +1130,7 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
|
||||
this._register(this.acceptChangesButton.onClick(async () => {
|
||||
const model = this.editor.getModel();
|
||||
if (model) {
|
||||
const conflictsSource = (getSyncSourceFromPreviewResource(model.uri, this.environmentService) || getSyncSourceFromResourceKey(resolveSyncResource(model.uri)!.resourceKey))!;
|
||||
const conflictsSource = (getSyncSourceFromPreviewResource(model.uri, this.environmentService) || resolveSyncResource(model.uri)!.resource)!;
|
||||
this.telemetryService.publicLog2<{ source: string, action: string }, SyncConflictsClassification>('sync/handleConflicts', { source: conflictsSource, action: isRemote ? 'acceptRemote' : 'acceptLocal' });
|
||||
const syncAreaLabel = getSyncAreaLabel(conflictsSource);
|
||||
const result = await this.dialogService.confirm({
|
||||
|
||||
@@ -10,7 +10,7 @@ import { localize } from 'vs/nls';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { TreeViewPane, TreeView } from 'vs/workbench/browser/parts/views/treeView';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ALL_RESOURCE_KEYS, CONTEXT_SYNC_ENABLEMENT, IUserDataSyncStoreService, toRemoteSyncResource, resolveSyncResource, IUserDataSyncBackupStoreService, IResourceRefHandle, ResourceKey, toLocalBackupSyncResource } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { ALL_SYNC_RESOURCES, CONTEXT_SYNC_ENABLEMENT, IUserDataSyncStoreService, toRemoteSyncResource, resolveSyncResource, IUserDataSyncBackupStoreService, IResourceRefHandle, toLocalBackupSyncResource, SyncResource } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { registerAction2, Action2, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IContextKeyService, RawContextKey, ContextKeyExpr, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -61,8 +61,8 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
|
||||
if (visible && !treeView.dataProvider) {
|
||||
disposable.dispose();
|
||||
treeView.dataProvider = this.instantiationService.createInstance(UserDataSyncHistoryViewDataProvider, id,
|
||||
(resourceKey: ResourceKey) => remote ? this.userDataSyncStoreService.getAllRefs(resourceKey) : this.userDataSyncBackupStoreService.getAllRefs(resourceKey),
|
||||
(resourceKey: ResourceKey, ref: string) => remote ? toRemoteSyncResource(resourceKey, ref) : toLocalBackupSyncResource(resourceKey, ref));
|
||||
(resource: SyncResource) => remote ? this.userDataSyncStoreService.getAllRefs(resource) : this.userDataSyncBackupStoreService.getAllRefs(resource),
|
||||
(resource: SyncResource, ref: string) => remote ? toRemoteSyncResource(resource, ref) : toLocalBackupSyncResource(resource, ref));
|
||||
}
|
||||
});
|
||||
const viewsRegistry = Registry.as<IViewsRegistry>(Extensions.ViewsRegistry);
|
||||
@@ -114,7 +114,7 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
|
||||
let resource = URI.parse(handle.$treeItemHandle);
|
||||
const result = resolveSyncResource(resource);
|
||||
if (result) {
|
||||
resource = resource.with({ fragment: result.resourceKey });
|
||||
resource = resource.with({ fragment: result.resource });
|
||||
await editorService.openEditor({ resource });
|
||||
}
|
||||
}
|
||||
@@ -152,8 +152,8 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
|
||||
const resource = URI.parse(handle.$treeItemHandle);
|
||||
const result = resolveSyncResource(resource);
|
||||
if (result) {
|
||||
const leftResource: URI = resource.with({ fragment: result.resourceKey });
|
||||
const rightResource: URI = result.resourceKey === 'settings' ? environmentService.settingsResource : environmentService.keybindingsResource;
|
||||
const leftResource: URI = resource.with({ fragment: result.resource });
|
||||
const rightResource: URI = result.resource === 'settings' ? environmentService.settingsResource : environmentService.keybindingsResource;
|
||||
await editorService.openEditor({
|
||||
leftResource,
|
||||
rightResource,
|
||||
@@ -174,8 +174,8 @@ class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvider {
|
||||
|
||||
constructor(
|
||||
private readonly viewId: string,
|
||||
private getAllRefs: (resourceKey: ResourceKey) => Promise<IResourceRefHandle[]>,
|
||||
private toResource: (resourceKey: ResourceKey, ref: string) => URI
|
||||
private getAllRefs: (resource: SyncResource) => Promise<IResourceRefHandle[]>,
|
||||
private toResource: (resource: SyncResource, ref: string) => URI
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvider {
|
||||
if (element) {
|
||||
return this.getResources(element.handle);
|
||||
}
|
||||
return ALL_RESOURCE_KEYS.map(resourceKey => ({
|
||||
return ALL_SYNC_RESOURCES.map(resourceKey => ({
|
||||
handle: resourceKey,
|
||||
collapsibleState: TreeItemCollapsibleState.Collapsed,
|
||||
label: { label: resourceKey },
|
||||
@@ -193,7 +193,7 @@ class UserDataSyncHistoryViewDataProvider implements ITreeViewDataProvider {
|
||||
}
|
||||
|
||||
private async getResources(handle: string): Promise<ITreeItem[]> {
|
||||
const resourceKey = ALL_RESOURCE_KEYS.filter(key => key === handle)[0];
|
||||
const resourceKey = ALL_SYNC_RESOURCES.filter(key => key === handle)[0];
|
||||
if (resourceKey) {
|
||||
const refHandles = await this.getAllRefs(resourceKey);
|
||||
return refHandles.map(({ ref, created }) => {
|
||||
|
||||
Reference in New Issue
Block a user