From 067fcc8dfbfefb5902236daee3d5b03fd65ebbb4 Mon Sep 17 00:00:00 2001 From: Anthony Dresser Date: Wed, 26 Feb 2020 00:23:48 -0800 Subject: [PATCH] Merge from vscode dbe62be3266ffb6772a7f3db0bf61d63f4aa7f65 (#9337) --- .../schemas/devContainer.schema.json | 50 ++++---- extensions/git/src/commands.ts | 20 ++-- extensions/git/src/repository.ts | 44 +++---- extensions/git/src/timelineProvider.ts | 67 +++-------- .../github-authentication/src/github.ts | 29 ++++- extensions/image-preview/package.json | 4 +- extensions/image-preview/package.nls.json | 2 +- extensions/image-preview/src/extension.ts | 2 +- extensions/image-preview/src/preview.ts | 10 +- .../markdown-language-features/package.json | 2 +- .../src/features/previewManager.ts | 12 +- extensions/vscode-account/src/AADHelper.ts | 6 +- src/vs/base/common/date.ts | 109 ++++++++++++++---- .../platform/extensions/common/extensions.ts | 2 +- .../common/abstractKeybindingService.ts | 4 + .../platform/keybinding/common/keybinding.ts | 2 + .../keybinding/common/keybindingResolver.ts | 5 + .../test/common/mockKeybindingService.ts | 2 + src/vs/platform/product/common/product.ts | 10 +- .../userDataSync/common/settingsMerge.ts | 4 +- .../userDataSync/common/userDataSync.ts | 47 +++----- src/vs/vscode.d.ts | 13 ++- src/vs/vscode.proposed.d.ts | 96 +++------------ .../workbench/api/common/extHost.api.impl.ts | 12 +- .../api/common/extHostTypeConverters.ts | 17 ++- src/vs/workbench/api/common/extHostWebview.ts | 93 +++++++-------- .../common/jsonValidationExtensionPoint.ts | 4 +- .../browser/parts/editor/editorActions.ts | 7 +- .../contrib/customEditor/browser/commands.ts | 10 +- .../customEditor/browser/customEditors.ts | 10 +- .../customEditor/browser/extensionPoint.ts | 4 +- .../customEditor/common/customEditor.ts | 2 +- .../extensions/browser/extensionEditor.ts | 2 +- .../contrib/scm/browser/repositoryPane.ts | 2 - .../contrib/search/common/searchModel.ts | 9 ++ .../contrib/searchEditor/browser/constants.ts | 1 + .../browser/searchEditor.contribution.ts | 9 ++ .../searchEditor/browser/searchEditor.ts | 4 + .../browser/searchEditorSerialization.ts | 7 +- .../terminal/browser/terminalInstance.ts | 4 +- .../contrib/timeline/browser/timelinePane.ts | 12 +- .../browser/userDataSync.contribution.ts | 42 +------ 42 files changed, 384 insertions(+), 409 deletions(-) diff --git a/extensions/configuration-editing/schemas/devContainer.schema.json b/extensions/configuration-editing/schemas/devContainer.schema.json index 3cff1bd58f..9cb171915f 100644 --- a/extensions/configuration-editing/schemas/devContainer.schema.json +++ b/extensions/configuration-editing/schemas/devContainer.schema.json @@ -142,23 +142,7 @@ } } }, - "dockerFileAndContext": { - "type": "object", - "properties": { - "dockerFile": { - "type": "string", - "description": "The location of the Dockerfile that defines the contents of the container. The path is relative to the folder containing the `devcontainer.json` file." - }, - "context": { - "type": "string", - "description": "The location of the context folder for building the Docker image. The path is relative to the folder containing the `devcontainer.json` file." - } - }, - "required": [ - "dockerFile" - ] - }, - "dockerFileContainer": { + "dockerfileContainer": { "oneOf": [ { "type": "object", @@ -168,7 +152,20 @@ "description": "Docker build-related options.", "allOf": [ { - "$ref": "#/definitions/dockerFileAndContext" + "type": "object", + "properties": { + "dockerfile": { + "type": "string", + "description": "The location of the Dockerfile that defines the contents of the container. The path is relative to the folder containing the `devcontainer.json` file." + }, + "context": { + "type": "string", + "description": "The location of the context folder for building the Docker image. The path is relative to the folder containing the `devcontainer.json` file." + } + }, + "required": [ + "dockerfile" + ] }, { "$ref": "#/definitions/buildOptions" @@ -183,7 +180,20 @@ { "allOf": [ { - "$ref": "#/definitions/dockerFileAndContext" + "type": "object", + "properties": { + "dockerFile": { + "type": "string", + "description": "The location of the Dockerfile that defines the contents of the container. The path is relative to the folder containing the `devcontainer.json` file." + }, + "context": { + "type": "string", + "description": "The location of the context folder for building the Docker image. The path is relative to the folder containing the `devcontainer.json` file." + } + }, + "required": [ + "dockerFile" + ] }, { "type": "object", @@ -280,7 +290,7 @@ { "oneOf": [ { - "$ref": "#/definitions/dockerFileContainer" + "$ref": "#/definitions/dockerfileContainer" }, { "$ref": "#/definitions/imageContainer" diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index ecce3fbc74..a44f5c6302 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -430,25 +430,25 @@ export class CommandCenter { case Status.INDEX_MODIFIED: case Status.INDEX_RENAMED: case Status.INDEX_ADDED: - return `${basename} (Index)`; + return localize('git.title.index', '{0} (Index)', basename); case Status.MODIFIED: case Status.BOTH_ADDED: case Status.BOTH_MODIFIED: - return `${basename} (Working Tree)`; + return localize('git.title.workingTree', '{0} (Working Tree)', basename); case Status.DELETED_BY_US: - return `${basename} (Theirs)`; + return localize('git.title.theirs', '{0} (Theirs)', basename); case Status.DELETED_BY_THEM: - return `${basename} (Ours)`; + return localize('git.title.ours', '{0} (Ours)', basename); case Status.UNTRACKED: + return localize('git.title.untracked', '{0} (Untracked)', basename); - return `${basename} (Untracked)`; + default: + return ''; } - - return ''; } @command('git.clone') @@ -2348,12 +2348,12 @@ export class CommandCenter { let title; if ((item.previousRef === 'HEAD' || item.previousRef === '~') && item.ref === '') { - title = `${basename} (Working Tree)`; + title = localize('git.title.workingTree', '{0} (Working Tree)', basename); } else if (item.previousRef === 'HEAD' && item.ref === '~') { - title = `${basename} (Index)`; + title = localize('git.title.index', '{0} (Index)', basename); } else { - title = `${basename} (${item.shortPreviousRef}) \u27f7 ${basename} (${item.shortRef})`; + title = localize('git.title.diffRefs', '{0} ({1}) \u27f7 {0} ({2})', basename, item.shortPreviousRef, item.shortRef); } return commands.executeCommand('vscode.diff', toGitUri(uri, item.previousRef), item.ref === '' ? uri : toGitUri(uri, item.ref), title); diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index fd49a8024c..472e8a2a18 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -40,6 +40,29 @@ export const enum ResourceGroupType { export class Resource implements SourceControlResourceState { + static getStatusText(type: Status) { + switch (type) { + case Status.INDEX_MODIFIED: return localize('index modified', "Index Modified"); + case Status.MODIFIED: return localize('modified', "Modified"); + case Status.INDEX_ADDED: return localize('index added', "Index Added"); + case Status.INDEX_DELETED: return localize('index deleted', "Index Deleted"); + case Status.DELETED: return localize('deleted', "Deleted"); + case Status.INDEX_RENAMED: return localize('index renamed', "Index Renamed"); + case Status.INDEX_COPIED: return localize('index copied', "Index Copied"); + case Status.UNTRACKED: return localize('untracked', "Untracked"); + case Status.IGNORED: return localize('ignored', "Ignored"); + case Status.INTENT_TO_ADD: return localize('intent to add', "Intent to Add"); + case Status.BOTH_DELETED: return localize('both deleted', "Both Deleted"); + case Status.ADDED_BY_US: return localize('added by us', "Added By Us"); + case Status.DELETED_BY_THEM: return localize('deleted by them', "Deleted By Them"); + case Status.ADDED_BY_THEM: return localize('added by them', "Added By Them"); + case Status.DELETED_BY_US: return localize('deleted by us', "Deleted By Us"); + case Status.BOTH_ADDED: return localize('both added', "Both Added"); + case Status.BOTH_MODIFIED: return localize('both modified', "Both Modified"); + default: return ''; + } + } + @memoize get resourceUri(): Uri { if (this.renameResourceUri && (this._type === Status.MODIFIED || this._type === Status.DELETED || this._type === Status.INDEX_RENAMED || this._type === Status.INDEX_COPIED)) { @@ -110,26 +133,7 @@ export class Resource implements SourceControlResourceState { } private get tooltip(): string { - switch (this.type) { - case Status.INDEX_MODIFIED: return localize('index modified', "Index Modified"); - case Status.MODIFIED: return localize('modified', "Modified"); - case Status.INDEX_ADDED: return localize('index added', "Index Added"); - case Status.INDEX_DELETED: return localize('index deleted', "Index Deleted"); - case Status.DELETED: return localize('deleted', "Deleted"); - case Status.INDEX_RENAMED: return localize('index renamed', "Index Renamed"); - case Status.INDEX_COPIED: return localize('index copied', "Index Copied"); - case Status.UNTRACKED: return localize('untracked', "Untracked"); - case Status.IGNORED: return localize('ignored', "Ignored"); - case Status.INTENT_TO_ADD: return localize('intent to add', "Intent to Add"); - case Status.BOTH_DELETED: return localize('both deleted', "Both Deleted"); - case Status.ADDED_BY_US: return localize('added by us', "Added By Us"); - case Status.DELETED_BY_THEM: return localize('deleted by them', "Deleted By Them"); - case Status.ADDED_BY_THEM: return localize('added by them', "Added By Them"); - case Status.DELETED_BY_US: return localize('deleted by us', "Deleted By Us"); - case Status.BOTH_ADDED: return localize('both added', "Both Added"); - case Status.BOTH_MODIFIED: return localize('both modified', "Both Modified"); - default: return ''; - } + return Resource.getStatusText(this.type); } private get strikeThrough(): boolean { diff --git a/extensions/git/src/timelineProvider.ts b/extensions/git/src/timelineProvider.ts index d240bc8ed5..0fd723f3c7 100644 --- a/extensions/git/src/timelineProvider.ts +++ b/extensions/git/src/timelineProvider.ts @@ -3,17 +3,18 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as nls from 'vscode-nls'; import * as dayjs from 'dayjs'; import * as advancedFormat from 'dayjs/plugin/advancedFormat'; import { CancellationToken, Disposable, Event, EventEmitter, ThemeIcon, Timeline, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvider, Uri, workspace } from 'vscode'; import { Model } from './model'; -import { Repository } from './repository'; +import { Repository, Resource } from './repository'; import { debounce } from './decorators'; -import { Status } from './api/git'; dayjs.extend(advancedFormat); -// TODO[ECA]: Localize all the strings +const localize = nls.loadMessageBundle(); + // TODO[ECA]: Localize or use a setting for date format export class GitTimelineItem extends TimelineItem { @@ -68,7 +69,7 @@ export class GitTimelineProvider implements TimelineProvider { } readonly id = 'git-history'; - readonly label = 'Git History'; + readonly label = localize('git.timeline.source', 'Git History'); private _disposable: Disposable; @@ -171,38 +172,18 @@ export class GitTimelineProvider implements TimelineProvider { }); if (options.cursor === undefined || options.before) { + const you = localize('git.timeline.you', 'You'); + const index = repo.indexGroup.resourceStates.find(r => r.resourceUri.fsPath === uri.fsPath); if (index) { const date = this._repoStatusDate ?? new Date(); dateFormatter = dayjs(date); - let status; - switch (index.type) { - case Status.INDEX_MODIFIED: - status = 'Modified'; - break; - case Status.INDEX_ADDED: - status = 'Added'; - break; - case Status.INDEX_DELETED: - status = 'Deleted'; - break; - case Status.INDEX_RENAMED: - status = 'Renamed'; - break; - case Status.INDEX_COPIED: - status = 'Copied'; - break; - default: - status = ''; - break; - } - - const item = new GitTimelineItem('~', 'HEAD', 'Staged Changes', date.getTime(), 'index', 'git:file:index'); + const item = new GitTimelineItem('~', 'HEAD', localize('git.timeline.stagedChanges', 'Staged Changes'), date.getTime(), 'index', 'git:file:index'); // TODO[ECA]: Replace with a better icon -- reflecting its status maybe? item.iconPath = new (ThemeIcon as any)('git-commit'); - item.description = 'You'; - item.detail = `You \u2014 Index\n${dateFormatter.format('MMMM Do, YYYY h:mma')}\n${status}`; + item.description = you; + item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.index', 'Index'), dateFormatter.format('MMMM Do, YYYY h:mma'), Resource.getStatusText(index.type)); item.command = { title: 'Open Comparison', command: 'git.timeline.openDiff', @@ -217,33 +198,11 @@ export class GitTimelineProvider implements TimelineProvider { const date = new Date(); dateFormatter = dayjs(date); - let status; - switch (working.type) { - case Status.INDEX_MODIFIED: - status = 'Modified'; - break; - case Status.INDEX_ADDED: - status = 'Added'; - break; - case Status.INDEX_DELETED: - status = 'Deleted'; - break; - case Status.INDEX_RENAMED: - status = 'Renamed'; - break; - case Status.INDEX_COPIED: - status = 'Copied'; - break; - default: - status = ''; - break; - } - - const item = new GitTimelineItem('', index ? '~' : 'HEAD', 'Uncommited Changes', date.getTime(), 'working', 'git:file:working'); + const item = new GitTimelineItem('', index ? '~' : 'HEAD', localize('git.timeline.uncommitedChanges', 'Uncommited Changes'), date.getTime(), 'working', 'git:file:working'); // TODO[ECA]: Replace with a better icon -- reflecting its status maybe? item.iconPath = new (ThemeIcon as any)('git-commit'); - item.description = 'You'; - item.detail = `You \u2014 Working Tree\n${dateFormatter.format('MMMM Do, YYYY h:mma')}\n${status}`; + item.description = you; + item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.workingTree', 'Working Tree'), dateFormatter.format('MMMM Do, YYYY h:mma'), Resource.getStatusText(working.type)); item.command = { title: 'Open Comparison', command: 'git.timeline.openDiff', diff --git a/extensions/github-authentication/src/github.ts b/extensions/github-authentication/src/github.ts index ce0a1b518a..d9f3c06d22 100644 --- a/extensions/github-authentication/src/github.ts +++ b/extensions/github-authentication/src/github.ts @@ -10,6 +10,13 @@ import Logger from './common/logger'; export const onDidChangeSessions = new vscode.EventEmitter(); +interface SessionData { + id: string; + accountName: string; + scopes: string[]; + accessToken: string; +} + export class GitHubAuthenticationProvider { private _sessions: vscode.AuthenticationSession[] = []; private _githubServer = new GitHubServer(); @@ -58,7 +65,15 @@ export class GitHubAuthenticationProvider { const storedSessions = await keychain.getToken(); if (storedSessions) { try { - return JSON.parse(storedSessions); + const sessionData: SessionData[] = JSON.parse(storedSessions); + return sessionData.map(session => { + return { + id: session.id, + accountName: session.accountName, + scopes: session.scopes, + accessToken: () => Promise.resolve(session.accessToken) + }; + }); } catch (e) { Logger.error(`Error reading sessions: ${e}`); } @@ -68,7 +83,17 @@ export class GitHubAuthenticationProvider { } private async storeSessions(): Promise { - await keychain.setToken(JSON.stringify(this._sessions)); + const sessionData: SessionData[] = await Promise.all(this._sessions.map(async session => { + const resolvedAccessToken = await session.accessToken(); + return { + id: session.id, + accountName: session.accountName, + scopes: session.scopes, + accessToken: resolvedAccessToken + }; + })); + + await keychain.setToken(JSON.stringify(sessionData)); } get sessions(): vscode.AuthenticationSession[] { diff --git a/extensions/image-preview/package.json b/extensions/image-preview/package.json index a0664f98e3..998f3799f4 100644 --- a/extensions/image-preview/package.json +++ b/extensions/image-preview/package.json @@ -22,10 +22,10 @@ "onCommand:imagePreview.zoomOut" ], "contributes": { - "webviewEditors": [ + "customEditors": [ { "viewType": "imagePreview.previewEditor", - "displayName": "%webviewEditors.displayName%", + "displayName": "%customEditors.displayName%", "priority": "builtin", "selector": [ { diff --git a/extensions/image-preview/package.nls.json b/extensions/image-preview/package.nls.json index 304b1df9a3..d1860bc2fb 100644 --- a/extensions/image-preview/package.nls.json +++ b/extensions/image-preview/package.nls.json @@ -1,7 +1,7 @@ { "displayName": "Image Preview", "description": "Provides VS Code's built-in image preview", - "webviewEditors.displayName": "Image Preview", + "customEditors.displayName": "Image Preview", "command.zoomIn": "Zoom in", "command.zoomOut": "Zoom out" } diff --git a/extensions/image-preview/src/extension.ts b/extensions/image-preview/src/extension.ts index 8c66a98170..8093a99964 100644 --- a/extensions/image-preview/src/extension.ts +++ b/extensions/image-preview/src/extension.ts @@ -23,7 +23,7 @@ export function activate(context: vscode.ExtensionContext) { const previewManager = new PreviewManager(extensionRoot, sizeStatusBarEntry, binarySizeStatusBarEntry, zoomStatusBarEntry); - context.subscriptions.push(vscode.window.registerWebviewCustomEditorProvider(PreviewManager.viewType, previewManager)); + context.subscriptions.push(vscode.window.registerCustomEditorProvider(PreviewManager.viewType, previewManager)); context.subscriptions.push(vscode.commands.registerCommand('imagePreview.zoomIn', () => { previewManager.activePreview?.zoomIn(); diff --git a/extensions/image-preview/src/preview.ts b/extensions/image-preview/src/preview.ts index fb8a5b138c..e87b7bc9cd 100644 --- a/extensions/image-preview/src/preview.ts +++ b/extensions/image-preview/src/preview.ts @@ -13,7 +13,7 @@ import { BinarySizeStatusBarEntry } from './binarySizeStatusBarEntry'; const localize = nls.loadMessageBundle(); -export class PreviewManager implements vscode.WebviewCustomEditorProvider { +export class PreviewManager implements vscode.CustomEditorProvider { public static readonly viewType = 'imagePreview.previewEditor'; @@ -27,12 +27,12 @@ export class PreviewManager implements vscode.WebviewCustomEditorProvider { private readonly zoomStatusBarEntry: ZoomStatusBarEntry, ) { } - public async provideWebviewCustomEditorDocument(resource: vscode.Uri) { - return vscode.window.createWebviewEditorCustomDocument(PreviewManager.viewType, resource, undefined, {}); + public async resolveCustomDocument(_document: vscode.CustomDocument): Promise { + return {}; } - public async resolveWebviewCustomEditor( - document: vscode.WebviewEditorCustomDocument, + public async resolveCustomEditor( + document: vscode.CustomDocument, webviewEditor: vscode.WebviewPanel, ): Promise { const preview = new Preview(this.extensionRoot, document.uri, webviewEditor, this.sizeStatusBarEntry, this.binarySizeStatusBarEntry, this.zoomStatusBarEntry); diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 82c8f9fae3..49e81f8af1 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -310,7 +310,7 @@ "markdown.previewScripts": [ "./media/index.js" ], - "webviewEditors": [ + "customEditors": [ { "viewType": "vscode.markdown.preview.editor", "displayName": "(Experimental) VS Code Markdown Preview", diff --git a/extensions/markdown-language-features/src/features/previewManager.ts b/extensions/markdown-language-features/src/features/previewManager.ts index 632e1936ca..e64c7e9e0f 100644 --- a/extensions/markdown-language-features/src/features/previewManager.ts +++ b/extensions/markdown-language-features/src/features/previewManager.ts @@ -52,7 +52,7 @@ class PreviewStore extends Disposable { } } -export class MarkdownPreviewManager extends Disposable implements vscode.WebviewPanelSerializer, vscode.WebviewCustomEditorProvider { +export class MarkdownPreviewManager extends Disposable implements vscode.WebviewPanelSerializer, vscode.CustomEditorProvider { private static readonly markdownPreviewActiveContextKey = 'markdownPreviewFocus'; private readonly _topmostLineMonitor = new TopmostLineMonitor(); @@ -70,7 +70,7 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview ) { super(); this._register(vscode.window.registerWebviewPanelSerializer(DynamicMarkdownPreview.viewType, this)); - this._register(vscode.window.registerWebviewCustomEditorProvider('vscode.markdown.preview.editor', this)); + this._register(vscode.window.registerCustomEditorProvider('vscode.markdown.preview.editor', this)); } public refresh() { @@ -148,12 +148,12 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview this.registerDynamicPreview(preview); } - public async provideWebviewCustomEditorDocument(resource: vscode.Uri) { - return vscode.window.createWebviewEditorCustomDocument('vscode.markdown.preview.editor', resource, undefined, {}); + public async resolveCustomDocument(_document: vscode.CustomDocument): Promise { + return {}; } - public async resolveWebviewCustomEditor( - document: vscode.WebviewEditorCustomDocument, + public async resolveCustomEditor( + document: vscode.CustomDocument, webview: vscode.WebviewPanel ): Promise { const preview = DynamicMarkdownPreview.revive( diff --git a/extensions/vscode-account/src/AADHelper.ts b/extensions/vscode-account/src/AADHelper.ts index f2796a1a93..190bddf312 100644 --- a/extensions/vscode-account/src/AADHelper.ts +++ b/extensions/vscode-account/src/AADHelper.ts @@ -295,8 +295,8 @@ export class AzureActiveDirectoryService { private getCallbackEnvironment(callbackUri: vscode.Uri): string { switch (callbackUri.authority) { - case 'online.visualstudio.com,': - return 'vso'; + case 'online.visualstudio.com': + return 'vso,'; case 'online-ppe.core.vsengsaas.visualstudio.com': return 'vsoppe,'; case 'online.dev.core.vsengsaas.visualstudio.com': @@ -397,7 +397,7 @@ export class AzureActiveDirectoryService { const claims = this.getTokenClaims(json.access_token); return { expiresIn: json.expires_in, - expiresAt: Date.now() + json.expires_in * 1000, + expiresAt: json.expires_in ? Date.now() + json.expires_in * 1000 : undefined, accessToken: json.access_token, refreshToken: json.refresh_token, scope, diff --git a/src/vs/base/common/date.ts b/src/vs/base/common/date.ts index 571cc0ab91..2cccf674a5 100644 --- a/src/vs/base/common/date.ts +++ b/src/vs/base/common/date.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { pad } from './strings'; +import { localize } from 'vs/nls'; const minute = 60; const hour = minute * 60; @@ -12,7 +13,6 @@ const week = day * 7; const month = day * 30; const year = day * 365; -// TODO[ECA]: Localize strings export function fromNow(date: number | Date, appendAgoLabel?: boolean): string { if (typeof date !== 'number') { date = date.getTime(); @@ -20,36 +20,99 @@ export function fromNow(date: number | Date, appendAgoLabel?: boolean): string { const seconds = Math.round((new Date().getTime() - date) / 1000); if (seconds < 30) { - return 'now'; + return localize('date.fromNow.now', 'now'); } let value: number; - let unit: string; if (seconds < minute) { value = seconds; - unit = 'sec'; - } else if (seconds < hour) { - value = Math.floor(seconds / minute); - unit = 'min'; - } else if (seconds < day) { - value = Math.floor(seconds / hour); - unit = 'hr'; - } else if (seconds < week) { - value = Math.floor(seconds / day); - unit = 'day'; - } else if (seconds < month) { - value = Math.floor(seconds / week); - unit = 'wk'; - } else if (seconds < year) { - value = Math.floor(seconds / month); - unit = 'mo'; - } else { - value = Math.floor(seconds / year); - unit = 'yr'; + + if (appendAgoLabel) { + return value === 1 + ? localize('date.fromNow.seconds.singular.ago', '{0} sec ago', value) + : localize('date.fromNow.seconds.plural.ago', '{0} secs ago', value); + } else { + return value === 1 + ? localize('date.fromNow.seconds.singular', '{0} sec', value) + : localize('date.fromNow.seconds.plural', '{0} secs', value); + } } - return `${value} ${unit}${value === 1 ? '' : 's'}${appendAgoLabel ? ' ago' : ''}`; + if (seconds < hour) { + value = Math.floor(seconds / minute); + if (appendAgoLabel) { + return value === 1 + ? localize('date.fromNow.minutes.singular.ago', '{0} min ago', value) + : localize('date.fromNow.minutes.plural.ago', '{0} mins ago', value); + } else { + return value === 1 + ? localize('date.fromNow.minutes.singular', '{0} min', value) + : localize('date.fromNow.minutes.plural', '{0} mins', value); + } + } + if (seconds < day) { + value = Math.floor(seconds / hour); + if (appendAgoLabel) { + return value === 1 + ? localize('date.fromNow.hours.singular.ago', '{0} hr ago', value) + : localize('date.fromNow.hours.plural.ago', '{0} hrs ago', value); + } else { + return value === 1 + ? localize('date.fromNow.hours.singular', '{0} hr', value) + : localize('date.fromNow.hours.plural', '{0} hrs', value); + } + } + + if (seconds < week) { + value = Math.floor(seconds / day); + if (appendAgoLabel) { + return value === 1 + ? localize('date.fromNow.days.singular.ago', '{0} day ago', value) + : localize('date.fromNow.days.plural.ago', '{0} days ago', value); + } else { + return value === 1 + ? localize('date.fromNow.days.singular', '{0} day', value) + : localize('date.fromNow.days.plural', '{0} days', value); + } + } + + if (seconds < month) { + value = Math.floor(seconds / week); + if (appendAgoLabel) { + return value === 1 + ? localize('date.fromNow.weeks.singular.ago', '{0} wk ago', value) + : localize('date.fromNow.weeks.plural.ago', '{0} wks ago', value); + } else { + return value === 1 + ? localize('date.fromNow.weeks.singular', '{0} wk', value) + : localize('date.fromNow.weeks.plural', '{0} wks', value); + } + } + + if (seconds < year) { + value = Math.floor(seconds / month); + if (appendAgoLabel) { + return value === 1 + ? localize('date.fromNow.months.singular.ago', '{0} mo ago', value) + : localize('date.fromNow.months.plural.ago', '{0} mos ago', value); + } else { + return value === 1 + ? localize('date.fromNow.months.singular', '{0} mo', value) + : localize('date.fromNow.months.plural', '{0} mos', value); + } + } + + value = Math.floor(seconds / year); + if (appendAgoLabel) { + return value === 1 + ? localize('date.fromNow.years.singular.ago', '{0} yr ago', value) + : localize('date.fromNow.years.plural.ago', '{0} yrs ago', value); + } else { + return value === 1 + ? localize('date.fromNow.years.singular', '{0} yr', value) + : localize('date.fromNow.years.plural', '{0} yrs', value); + } } export function toLocalISOString(date: Date): string { diff --git a/src/vs/platform/extensions/common/extensions.ts b/src/vs/platform/extensions/common/extensions.ts index f1e3b860ed..b1c563557b 100644 --- a/src/vs/platform/extensions/common/extensions.ts +++ b/src/vs/platform/extensions/common/extensions.ts @@ -130,7 +130,7 @@ export interface IExtensionContributions { views?: { [location: string]: IView[] }; colors?: IColor[]; localizations?: ILocalization[]; - readonly webviewEditors?: readonly IWebviewEditor[]; + readonly customEditors?: readonly IWebviewEditor[]; readonly codeActions?: readonly ICodeActionContribution[]; } diff --git a/src/vs/platform/keybinding/common/abstractKeybindingService.ts b/src/vs/platform/keybinding/common/abstractKeybindingService.ts index 05ca3828c4..c74ceb4c35 100644 --- a/src/vs/platform/keybinding/common/abstractKeybindingService.ts +++ b/src/vs/platform/keybinding/common/abstractKeybindingService.ts @@ -35,6 +35,10 @@ export abstract class AbstractKeybindingService extends Disposable implements IK private _currentChordChecker: IntervalTimer; private _currentChordStatusMessage: IDisposable | null; + public get inChordMode(): boolean { + return !!this._currentChord; + } + constructor( private _contextKeyService: IContextKeyService, protected _commandService: ICommandService, diff --git a/src/vs/platform/keybinding/common/keybinding.ts b/src/vs/platform/keybinding/common/keybinding.ts index 7fa513352f..2aeac6ec9c 100644 --- a/src/vs/platform/keybinding/common/keybinding.ts +++ b/src/vs/platform/keybinding/common/keybinding.ts @@ -50,6 +50,8 @@ export const IKeybindingService = createDecorator('keybindin export interface IKeybindingService { _serviceBrand: undefined; + readonly inChordMode: boolean; + onDidUpdateKeybindings: Event; /** diff --git a/src/vs/platform/keybinding/common/keybindingResolver.ts b/src/vs/platform/keybinding/common/keybindingResolver.ts index a1569b601f..102650bc7b 100644 --- a/src/vs/platform/keybinding/common/keybindingResolver.ts +++ b/src/vs/platform/keybinding/common/keybindingResolver.ts @@ -11,7 +11,10 @@ import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKe import { keys } from 'vs/base/common/map'; export interface IResolveResult { + /** Whether the resolved keybinding is entering a chord */ enterChord: boolean; + /** Whether the resolved keybinding is leaving (and executing) a chord */ + leaveChord: boolean; commandId: string | null; commandArgs: any; bubble: boolean; @@ -285,6 +288,7 @@ export class KeybindingResolver { if (currentChord === null && result.keypressParts.length > 1 && result.keypressParts[1] !== null) { return { enterChord: true, + leaveChord: false, commandId: null, commandArgs: null, bubble: false @@ -293,6 +297,7 @@ export class KeybindingResolver { return { enterChord: false, + leaveChord: result.keypressParts.length > 1, commandId: result.command, commandArgs: result.commandArgs, bubble: result.bubble diff --git a/src/vs/platform/keybinding/test/common/mockKeybindingService.ts b/src/vs/platform/keybinding/test/common/mockKeybindingService.ts index 39111c9ee0..42d38eba8d 100644 --- a/src/vs/platform/keybinding/test/common/mockKeybindingService.ts +++ b/src/vs/platform/keybinding/test/common/mockKeybindingService.ts @@ -71,6 +71,8 @@ export class MockContextKeyService implements IContextKeyService { export class MockKeybindingService implements IKeybindingService { public _serviceBrand: undefined; + public readonly inChordMode: boolean = false; + public get onDidUpdateKeybindings(): Event { return Event.None; } diff --git a/src/vs/platform/product/common/product.ts b/src/vs/platform/product/common/product.ts index c6b3b6cc81..0488f13581 100644 --- a/src/vs/platform/product/common/product.ts +++ b/src/vs/platform/product/common/product.ts @@ -21,11 +21,11 @@ if (isWeb) { // Running out of sources if (Object.keys(product).length === 0) { assign(product, { - version: '1.41.0-dev', - vscodeVersion: '1.39.0-dev', - nameLong: 'Visual Studio Code Web Dev', - nameShort: 'VSCode Web Dev', - urlProtocol: 'code-oss' + version: '1.16.0-dev', + vscodeVersion: '1.43.0-dev', + nameLong: 'Azure Data Studio Web Dev', + nameShort: 'Azure Data Studio Web Dev', + urlProtocol: 'azuredatastudio-oss' }); } } diff --git a/src/vs/platform/userDataSync/common/settingsMerge.ts b/src/vs/platform/userDataSync/common/settingsMerge.ts index c0787da608..29e1c69cf1 100644 --- a/src/vs/platform/userDataSync/common/settingsMerge.ts +++ b/src/vs/platform/userDataSync/common/settingsMerge.ts @@ -10,7 +10,7 @@ import { values } from 'vs/base/common/map'; import { IStringDictionary } from 'vs/base/common/collections'; import { FormattingOptions, Edit, getEOL } from 'vs/base/common/jsonFormatter'; import * as contentUtil from 'vs/platform/userDataSync/common/content'; -import { IConflictSetting } from 'vs/platform/userDataSync/common/userDataSync'; +import { IConflictSetting, getDisallowedIgnoredSettings } from 'vs/platform/userDataSync/common/userDataSync'; import { firstIndex, distinct } from 'vs/base/common/arrays'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { startsWith } from 'vs/base/common/strings'; @@ -32,7 +32,7 @@ export function getIgnoredSettings(defaultIgnoredSettings: string[], configurati } else { value = configurationService.getValue('sync.ignoredSettings'); } - const added: string[] = [], removed: string[] = []; + const added: string[] = [], removed: string[] = [...getDisallowedIgnoredSettings()]; if (Array.isArray(value)) { for (const key of value) { if (startsWith(key, '-')) { diff --git a/src/vs/platform/userDataSync/common/userDataSync.ts b/src/vs/platform/userDataSync/common/userDataSync.ts index a6b3facf88..d978311e27 100644 --- a/src/vs/platform/userDataSync/common/userDataSync.ts +++ b/src/vs/platform/userDataSync/common/userDataSync.ts @@ -21,6 +21,7 @@ import { URI } from 'vs/base/common/uri'; import { isEqual, joinPath } from 'vs/base/common/resources'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IProductService } from 'vs/platform/product/common/productService'; +import { distinct } from 'vs/base/common/arrays'; export const CONFIGURATION_SYNC_STORE_KEY = 'configurationSync.store'; @@ -37,10 +38,16 @@ export interface ISyncConfiguration { } } +export function getDisallowedIgnoredSettings(): string[] { + const allSettings = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); + return Object.keys(allSettings).filter(setting => !!allSettings[setting].disallowSyncIgnore); +} + export function getDefaultIgnoredSettings(): string[] { const allSettings = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); const machineSettings = Object.keys(allSettings).filter(setting => allSettings[setting].scope === ConfigurationScope.MACHINE || allSettings[setting].scope === ConfigurationScope.MACHINE_OVERRIDABLE); - return [CONFIGURATION_SYNC_STORE_KEY, ...machineSettings]; + const disallowedSettings = getDisallowedIgnoredSettings(); + return distinct([CONFIGURATION_SYNC_STORE_KEY, ...machineSettings, ...disallowedSettings]); } export function registerConfiguration(): IDisposable { @@ -53,36 +60,6 @@ export function registerConfiguration(): IDisposable { title: localize('sync', "Sync"), type: 'object', properties: { - 'sync.enable': { - type: 'boolean', - default: false, - scope: ConfigurationScope.APPLICATION, - deprecationMessage: 'deprecated' - }, - 'sync.enableSettings': { - type: 'boolean', - default: true, - scope: ConfigurationScope.APPLICATION, - deprecationMessage: 'deprecated' - }, - 'sync.enableKeybindings': { - type: 'boolean', - default: true, - scope: ConfigurationScope.APPLICATION, - deprecationMessage: 'Deprecated' - }, - 'sync.enableUIState': { - type: 'boolean', - default: true, - scope: ConfigurationScope.APPLICATION, - deprecationMessage: 'deprecated' - }, - 'sync.enableExtensions': { - type: 'boolean', - default: true, - scope: ConfigurationScope.APPLICATION, - deprecationMessage: 'deprecated' - }, 'sync.keybindingsPerPlatform': { type: 'boolean', description: localize('sync.keybindingsPerPlatform', "Synchronize keybindings per platform."), @@ -115,11 +92,15 @@ export function registerConfiguration(): IDisposable { }); const jsonRegistry = Registry.as(JSONExtensions.JSONContribution); const registerIgnoredSettingsSchema = () => { - const defaultIgnoreSettings = getDefaultIgnoredSettings().filter(s => s !== CONFIGURATION_SYNC_STORE_KEY); + const disallowedIgnoredSettings = getDisallowedIgnoredSettings(); + const defaultIgnoredSettings = getDefaultIgnoredSettings().filter(s => s !== CONFIGURATION_SYNC_STORE_KEY); + const settings = Object.keys(allSettings.properties).filter(setting => defaultIgnoredSettings.indexOf(setting) === -1); + const ignoredSettings = defaultIgnoredSettings.filter(setting => disallowedIgnoredSettings.indexOf(setting) === -1); + console.log(ignoredSettings); const ignoredSettingsSchema: IJSONSchema = { items: { type: 'string', - enum: [...Object.keys(allSettings.properties).filter(setting => defaultIgnoreSettings.indexOf(setting) === -1), ...defaultIgnoreSettings.map(setting => `-${setting}`)] + enum: [...settings, ...ignoredSettings.map(setting => `-${setting}`)] }, }; jsonRegistry.registerSchema(ignoredSettingsSchemaId, ignoredSettingsSchema); diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 9d39f98dd4..9ccc6bac79 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -4675,7 +4675,18 @@ declare module 'vscode' { * A code or identifier for this diagnostic. * Should be used for later processing, e.g. when providing [code actions](#CodeActionContext). */ - code?: string | number; + code?: string | number | { + /** + * A code or identifier for this diagnostic. + * Should be used for later processing, e.g. when providing [code actions](#CodeActionContext). + */ + value: string | number; + + /** + * A target URI to open with more information about the diagnostic error. + */ + target: Uri; + }; /** * An array of related diagnostic information, e.g. when symbol-names within diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index b612ec583a..8ef1701611 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1188,22 +1188,21 @@ declare module 'vscode' { //#region Custom editors: https://github.com/microsoft/vscode/issues/77131 // TODO: - // - Naming! // - Think about where a rename would live. - // - Think about handling go to line? + // - Think about handling go to line? (add other editor options? reveal?) // - Should we expose edits? // - More properties from `TextDocument`? /** * Defines the capabilities of a custom webview editor. */ - interface WebviewCustomEditorCapabilities { + interface CustomEditorCapabilities { /** * Defines the editing capability of a custom webview document. * * When not provided, the document is considered readonly. */ - readonly editing?: WebviewCustomEditorEditingCapability; + readonly editing?: CustomEditorEditingCapability; } /** @@ -1212,7 +1211,7 @@ declare module 'vscode' { * * @param EditType Type of edits. */ - interface WebviewCustomEditorEditingCapability { + interface CustomEditorEditingCapability { /** * Save the resource. * @@ -1286,7 +1285,7 @@ declare module 'vscode' { * * @param UserDataType Type of custom object that extensions can store on the document. */ - interface WebviewEditorCustomDocument { + interface CustomDocument { /** * The associated viewType for this document. */ @@ -1305,7 +1304,7 @@ declare module 'vscode' { /** * Custom data that an extension can store on the document. */ - readonly userData: UserDataType; + userData?: UserDataType; // TODO: Should we expose edits here? // This could be helpful for tracking the life cycle of edits @@ -1320,13 +1319,13 @@ declare module 'vscode' { * You should use custom text based editors when dealing with binary files or more complex scenarios. For simple text * based documents, use [`WebviewTextEditorProvider`](#WebviewTextEditorProvider) instead. */ - export interface WebviewCustomEditorProvider { + export interface CustomEditorProvider { /** * Create the model for a given * * @param document Resource being resolved. */ - provideWebviewCustomEditorDocument(resource: Uri): Thenable; + resolveCustomDocument(document: CustomDocument): Thenable; /** * Resolve a webview editor for a given resource. @@ -1339,7 +1338,7 @@ declare module 'vscode' { * * @return Thenable indicating that the webview editor has been resolved. */ - resolveWebviewCustomEditor(document: WebviewEditorCustomDocument, webview: WebviewPanel): Thenable; + resolveCustomEditor(document: CustomDocument, webview: WebviewPanel): Thenable; } /** @@ -1352,7 +1351,7 @@ declare module 'vscode' { * You should use text based webview editors when dealing with text based file formats, such as `xml` or `json`. * For binary files or more specialized use cases, see [WebviewCustomEditorProvider](#WebviewCustomEditorProvider). */ - export interface WebviewTextEditorProvider { + export interface CustomTextEditorProvider { /** * Resolve a webview editor for a given resource. * @@ -1364,64 +1363,25 @@ declare module 'vscode' { * * @return Thenable indicating that the webview editor has been resolved. */ - resolveWebviewTextEditor(document: TextDocument, webview: WebviewPanel): Thenable; + resolveCustomTextEditor(document: TextDocument, webview: WebviewPanel): Thenable; } namespace window { /** - * Register a new provider for text based webview editors. - * - * @param viewType Type of the webview editor provider. This should match the `viewType` from the - * `package.json` contributions - * @param provider Provider that resolves webview editors. - * @param webviewOptions Content settings for the webview panels that provider is given. - * - * @return Disposable that unregisters the `WebviewTextEditorProvider`. - */ - export function registerWebviewTextEditorProvider( - viewType: string, - provider: WebviewTextEditorProvider, - webviewOptions?: WebviewPanelOptions, - ): Disposable; - - /** - * Register a new provider for custom webview editors. + * Register a new provider for a custom editor. * * @param viewType Type of the webview editor provider. This should match the `viewType` from the * `package.json` contributions. - * @param provider Provider that resolves webview editors. - * @param webviewOptions Content settings for the webview panels that provider is given. + * @param provider Provider that resolves editors. + * @param webviewOptions Content settings for the webview panels that the provider is given. * - * @return Disposable that unregisters the `WebviewCustomEditorProvider`. + * @return Disposable that unregisters the provider. */ - export function registerWebviewCustomEditorProvider( + export function registerCustomEditorProvider( viewType: string, - provider: WebviewCustomEditorProvider, + provider: CustomEditorProvider | CustomTextEditorProvider, webviewOptions?: WebviewPanelOptions, ): Disposable; - - /** - * Create a new `WebviewEditorCustomDocument`. - * - * Note that this method only creates a custom document object. To have it be registered with VS Code, you - * must return the document from `WebviewCustomEditorProvider.provideWebviewCustomEditorDocument`. - * - * @param viewType Type of the webview editor provider. This should match the `viewType` from the - * `package.json` contributions. - * @param uri The document's resource. - * @param userData Custom data attached to the document. - * @param capabilities Controls the editing functionality of a webview editor. This allows the webview - * editor to hook into standard editor events such as `undo` or `save`. - * - * WebviewEditors that do not have `editingCapability` are considered to be readonly. Users can still interact - * with readonly editors, but these editors will not integrate with VS Code's standard editor functionality. - */ - export function createWebviewEditorCustomDocument( - viewType: string, - uri: Uri, - userData: UserDataType, - capabilities: WebviewCustomEditorCapabilities - ): WebviewEditorCustomDocument; } //#endregion @@ -1522,28 +1482,6 @@ declare module 'vscode' { //#endregion - //#region Diagnostic links https://github.com/microsoft/vscode/issues/11847 - - export interface Diagnostic { - /** - * Will be merged into `Diagnostic#code` - */ - code2?: { - /** - * A code or identifier for this diagnostic. - * Should be used for later processing, e.g. when providing [code actions](#CodeActionContext). - */ - value: string | number; - - /** - * A target URI to open with more information about the diagnostic error. - */ - target: Uri; - } - } - - //#endregion - //#region eamodio - timeline: https://github.com/microsoft/vscode/issues/84297 export class TimelineItem { diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 06243a4814..cd57b2d401 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -564,17 +564,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I registerWebviewPanelSerializer: (viewType: string, serializer: vscode.WebviewPanelSerializer) => { return extHostWebviews.registerWebviewPanelSerializer(extension, viewType, serializer); }, - registerWebviewTextEditorProvider: (viewType: string, provider: vscode.WebviewTextEditorProvider, options?: vscode.WebviewPanelOptions) => { + registerCustomEditorProvider: (viewType: string, provider: vscode.CustomEditorProvider | vscode.CustomTextEditorProvider, options?: vscode.WebviewPanelOptions) => { checkProposedApiEnabled(extension); - return extHostWebviews.registerWebviewTextEditorProvider(extension, viewType, provider, options); - }, - registerWebviewCustomEditorProvider: (viewType: string, provider: vscode.WebviewCustomEditorProvider, options?: vscode.WebviewPanelOptions) => { - checkProposedApiEnabled(extension); - return extHostWebviews.registerWebviewCustomEditorProvider(extension, viewType, provider, options); - }, - createWebviewEditorCustomDocument: (viewType: string, resource: vscode.Uri, userData: UserDataType, capabilities: vscode.WebviewCustomEditorCapabilities) => { - checkProposedApiEnabled(extension); - return extHostWebviews.createWebviewEditorCustomDocument(viewType, resource, userData, capabilities); + return extHostWebviews.registerCustomEditorProvider(extension, viewType, provider, options); }, registerDecorationProvider(provider: vscode.DecorationProvider) { checkProposedApiEnabled(extension); diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 42e905f489..5b93b7a43b 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -127,12 +127,17 @@ export namespace DiagnosticTag { export namespace Diagnostic { export function from(value: vscode.Diagnostic): IMarkerData { - let code: string | { value: string; target: URI } | undefined = isString(value.code) || isNumber(value.code) ? String(value.code) : undefined; - if (value.code2) { - code = { - value: String(value.code2.value), - target: value.code2.target - }; + let code: string | { value: string; target: URI } | undefined; + + if (value.code) { + if (isString(value.code) || isNumber(value.code)) { + code = String(value.code); + } else { + code = { + value: String(value.code.value), + target: value.code.target, + }; + } } return { diff --git a/src/vs/workbench/api/common/extHostWebview.ts b/src/vs/workbench/api/common/extHostWebview.ts index 1e19cbf9db..1779060450 100644 --- a/src/vs/workbench/api/common/extHostWebview.ts +++ b/src/vs/workbench/api/common/extHostWebview.ts @@ -247,22 +247,30 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa type EditType = unknown; -class WebviewEditorCustomDocument extends Disposable implements vscode.WebviewEditorCustomDocument { +class WebviewEditorCustomDocument extends Disposable implements vscode.CustomDocument { private _currentEditIndex: number = -1; private _savePoint: number = -1; private readonly _edits: Array = []; + public userData: unknown; + + public _capabilities?: vscode.CustomEditorCapabilities = undefined; + constructor( private readonly _proxy: MainThreadWebviewsShape, public readonly viewType: string, public readonly uri: vscode.Uri, - public readonly userData: unknown, - public readonly _capabilities: vscode.WebviewCustomEditorCapabilities, ) { super(); + } - // Hook up events - _capabilities.editing?.onDidEdit(edit => { + _setCapabilities(capabilities: vscode.CustomEditorCapabilities) { + if (this._capabilities) { + throw new Error('Capabilities already provided'); + } + + this._capabilities = capabilities; + capabilities.editing?.onDidEdit(edit => { this.pushEdit(edit, this); }); } @@ -356,12 +364,12 @@ class WebviewEditorCustomDocument extends Disposable implements vscode.WebviewEd return this.getEditingCapability().saveAs(target); } - backup(cancellation: CancellationToken): boolean | PromiseLike { - throw new Error('Method not implemented.'); + backup(cancellation: CancellationToken) { + return this.getEditingCapability().backup(cancellation); } - private getEditingCapability(): vscode.WebviewCustomEditorEditingCapability { - if (!this._capabilities.editing) { + private getEditingCapability(): vscode.CustomEditorEditingCapability { + if (!this._capabilities?.editing) { throw new Error('Document is not editable'); } return this._capabilities.editing; @@ -401,21 +409,21 @@ const enum WebviewEditorType { type ProviderEntry = { readonly extension: IExtensionDescription; readonly type: WebviewEditorType.Text; - readonly provider: vscode.WebviewTextEditorProvider; + readonly provider: vscode.CustomTextEditorProvider; } | { readonly extension: IExtensionDescription; readonly type: WebviewEditorType.Custom; - readonly provider: vscode.WebviewCustomEditorProvider; + readonly provider: vscode.CustomEditorProvider; }; class EditorProviderStore { private readonly _providers = new Map(); - public addTextProvider(viewType: string, extension: IExtensionDescription, provider: vscode.WebviewTextEditorProvider): vscode.Disposable { + public addTextProvider(viewType: string, extension: IExtensionDescription, provider: vscode.CustomTextEditorProvider): vscode.Disposable { return this.add(WebviewEditorType.Text, viewType, extension, provider); } - public addCustomProvider(viewType: string, extension: IExtensionDescription, provider: vscode.WebviewCustomEditorProvider): vscode.Disposable { + public addCustomProvider(viewType: string, extension: IExtensionDescription, provider: vscode.CustomEditorProvider): vscode.Disposable { return this.add(WebviewEditorType.Custom, viewType, extension, provider); } @@ -423,7 +431,7 @@ class EditorProviderStore { return this._providers.get(viewType); } - private add(type: WebviewEditorType, viewType: string, extension: IExtensionDescription, provider: vscode.WebviewTextEditorProvider | vscode.WebviewCustomEditorProvider): vscode.Disposable { + private add(type: WebviewEditorType, viewType: string, extension: IExtensionDescription, provider: vscode.CustomTextEditorProvider | vscode.CustomEditorProvider): vscode.Disposable { if (this._providers.has(viewType)) { throw new Error(`Provider for viewType:${viewType} already registered`); } @@ -501,43 +509,26 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { }); } - public registerWebviewTextEditorProvider( + public registerCustomEditorProvider( extension: IExtensionDescription, viewType: string, - provider: vscode.WebviewTextEditorProvider, + provider: vscode.CustomEditorProvider | vscode.CustomTextEditorProvider, options: vscode.WebviewPanelOptions | undefined = {} ): vscode.Disposable { - const unregisterProvider = this._editorProviders.addTextProvider(viewType, extension, provider); - this._proxy.$registerTextEditorProvider(toExtensionData(extension), viewType, options); + let disposable: vscode.Disposable; + if ('resolveCustomTextEditor' in provider) { + disposable = this._editorProviders.addTextProvider(viewType, extension, provider); + this._proxy.$registerTextEditorProvider(toExtensionData(extension), viewType, options); + } else { + disposable = this._editorProviders.addCustomProvider(viewType, extension, provider); + this._proxy.$registerCustomEditorProvider(toExtensionData(extension), viewType, options); + } - return new VSCodeDisposable(() => { - unregisterProvider.dispose(); - this._proxy.$unregisterEditorProvider(viewType); - }); - } - - public registerWebviewCustomEditorProvider( - extension: IExtensionDescription, - viewType: string, - provider: vscode.WebviewCustomEditorProvider, - options: vscode.WebviewPanelOptions | undefined = {}, - ): vscode.Disposable { - const unregisterProvider = this._editorProviders.addCustomProvider(viewType, extension, provider); - this._proxy.$registerCustomEditorProvider(toExtensionData(extension), viewType, options); - - return new VSCodeDisposable(() => { - unregisterProvider.dispose(); - this._proxy.$unregisterEditorProvider(viewType); - }); - } - - public createWebviewEditorCustomDocument( - viewType: string, - resource: vscode.Uri, - userData: UserDataType, - capabilities: vscode.WebviewCustomEditorCapabilities, - ): vscode.WebviewEditorCustomDocument { - return Object.seal(new WebviewEditorCustomDocument(this._proxy, viewType, resource, userData, capabilities) as vscode.WebviewEditorCustomDocument); + return VSCodeDisposable.from( + disposable, + new VSCodeDisposable(() => { + this._proxy.$unregisterEditorProvider(viewType); + })); } public $onMessage( @@ -631,10 +622,12 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { } const revivedResource = URI.revive(resource); - const document = await entry.provider.provideWebviewCustomEditorDocument(revivedResource) as WebviewEditorCustomDocument; + const document = Object.seal(new WebviewEditorCustomDocument(this._proxy, viewType, revivedResource)); + const capabilities = await entry.provider.resolveCustomDocument(document); + document._setCapabilities(capabilities); this._documents.add(document); return { - editable: !!document._capabilities.editing + editable: !!capabilities.editing }; } @@ -677,13 +670,13 @@ export class ExtHostWebviews implements ExtHostWebviewsShape { case WebviewEditorType.Custom: { const document = this.getDocument(viewType, revivedResource); - return entry.provider.resolveWebviewCustomEditor(document, revivedPanel); + return entry.provider.resolveCustomEditor(document, revivedPanel); } case WebviewEditorType.Text: { await this._extHostDocuments.ensureDocumentData(revivedResource); const document = this._extHostDocuments.getDocument(revivedResource); - return entry.provider.resolveWebviewTextEditor(document, revivedPanel); + return entry.provider.resolveCustomTextEditor(document, revivedPanel); } default: { diff --git a/src/vs/workbench/api/common/jsonValidationExtensionPoint.ts b/src/vs/workbench/api/common/jsonValidationExtensionPoint.ts index 18d0f74733..9925ab160e 100644 --- a/src/vs/workbench/api/common/jsonValidationExtensionPoint.ts +++ b/src/vs/workbench/api/common/jsonValidationExtensionPoint.ts @@ -69,8 +69,8 @@ export class JSONValidationExtensionPoint { } catch (e) { collector.error(nls.localize('invalid.url.fileschema', "'configuration.jsonValidation.url' is an invalid relative URL: {0}", e.message)); } - } else if (!strings.startsWith(uri, 'https:/') && strings.startsWith(uri, 'https:/')) { - collector.error(nls.localize('invalid.url.schema', "'configuration.jsonValidation.url' must start with 'http:', 'https:' or './' to reference schemas located in the extension")); + } else if (!/^[^:/?#]+:\/\//.test(uri)) { + collector.error(nls.localize('invalid.url.schema', "'configuration.jsonValidation.url' must be an absolute URL or start with './' to reference schemas located in the extension.")); return; } }); diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index cd8242dd6f..1e05a85500 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -642,14 +642,13 @@ export abstract class BaseCloseAllAction extends Action { return; } - let saveOrRevert: boolean; if (confirm === ConfirmResult.DONT_SAVE) { - saveOrRevert = await this.editorService.revertAll({ soft: true, includeUntitled: true }); + await this.editorService.revertAll({ soft: true, includeUntitled: true }); } else { - saveOrRevert = await this.editorService.saveAll({ reason: SaveReason.EXPLICIT, includeUntitled: true }); + await this.editorService.saveAll({ reason: SaveReason.EXPLICIT, includeUntitled: true }); } - if (saveOrRevert) { + if (!this.workingCopyService.hasDirty) { return this.doCloseAll(); } } diff --git a/src/vs/workbench/contrib/customEditor/browser/commands.ts b/src/vs/workbench/contrib/customEditor/browser/commands.ts index 0c2ebfd7fa..dd3d5714bb 100644 --- a/src/vs/workbench/contrib/customEditor/browser/commands.ts +++ b/src/vs/workbench/contrib/customEditor/browser/commands.ts @@ -17,7 +17,7 @@ import { EditorViewColumn, viewColumnToEditorGroup } from 'vs/workbench/api/comm import { IEditorCommandsContext } from 'vs/workbench/common/editor'; import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput'; import { defaultEditorId } from 'vs/workbench/contrib/customEditor/browser/customEditors'; -import { CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CONTEXT_HAS_CUSTOM_EDITORS, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; +import { CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CONTEXT_CUSTOM_EDITORS, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import type { ITextEditorOptions } from 'vs/platform/editor/common/editor'; @@ -80,7 +80,7 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, { title: REOPEN_WITH_TITLE, category: viewCategory, }, - when: CONTEXT_HAS_CUSTOM_EDITORS, + when: CONTEXT_CUSTOM_EDITORS.notEqualsTo(''), }); MenuRegistry.appendMenuItem(MenuId.EditorTitle, { @@ -89,9 +89,9 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { title: REOPEN_WITH_TITLE, category: viewCategory, }, - group: '3_open', + group: '6_reopen', order: 20, - when: CONTEXT_HAS_CUSTOM_EDITORS, + when: CONTEXT_CUSTOM_EDITORS.notEqualsTo(''), }); // #endregion @@ -155,7 +155,7 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, { constructor() { super({ id: ToggleCustomEditorCommand.ID, - precondition: CONTEXT_HAS_CUSTOM_EDITORS, + precondition: CONTEXT_CUSTOM_EDITORS, }); } diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts index d02db01be9..405a4b2780 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditors.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditors.ts @@ -25,7 +25,7 @@ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { EditorInput, EditorOptions, IEditor, IEditorInput } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { webviewEditorsExtensionPoint } from 'vs/workbench/contrib/customEditor/browser/extensionPoint'; -import { CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CONTEXT_HAS_CUSTOM_EDITORS, CustomEditorInfo, CustomEditorInfoCollection, CustomEditorPriority, CustomEditorSelector, ICustomEditor, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; +import { CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CONTEXT_CUSTOM_EDITORS, CustomEditorInfo, CustomEditorInfoCollection, CustomEditorPriority, CustomEditorSelector, ICustomEditor, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor'; import { CustomEditorModelManager } from 'vs/workbench/contrib/customEditor/common/customEditorModelManager'; import { IWebviewService, webviewHasOwnEditFunctionsContext } from 'vs/workbench/contrib/webview/browser/webview'; import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; @@ -98,7 +98,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ private readonly _models: CustomEditorModelManager; - private readonly _hasCustomEditor: IContextKey; + private readonly _customEditorContextKey: IContextKey; private readonly _focusedCustomEditorIsEditable: IContextKey; private readonly _webviewHasOwnEditFunctions: IContextKey; @@ -118,7 +118,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ this._models = new CustomEditorModelManager(workingCopyService, labelService); - this._hasCustomEditor = CONTEXT_HAS_CUSTOM_EDITORS.bindTo(contextKeyService); + this._customEditorContextKey = CONTEXT_CUSTOM_EDITORS.bindTo(contextKeyService); this._focusedCustomEditorIsEditable = CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE.bindTo(contextKeyService); this._webviewHasOwnEditFunctions = webviewHasOwnEditFunctionsContext.bindTo(contextKeyService); @@ -310,7 +310,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ const activeControl = this.editorService.activeControl; const resource = activeControl?.input.resource; if (!resource) { - this._hasCustomEditor.reset(); + this._customEditorContextKey.reset(); this._focusedCustomEditorIsEditable.reset(); this._webviewHasOwnEditFunctions.reset(); return; @@ -320,7 +320,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ ...this.getContributedCustomEditors(resource).allEditors, ...this.getUserConfiguredCustomEditors(resource).allEditors, ]; - this._hasCustomEditor.set(possibleEditors.length > 0); + this._customEditorContextKey.set(possibleEditors.map(x => x.id).join(',')); this._focusedCustomEditorIsEditable.set(activeControl?.input instanceof CustomEditorInput); this._webviewHasOwnEditFunctions.set(possibleEditors.length > 0); } diff --git a/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts b/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts index 6f23a3bede..ee468c4a64 100644 --- a/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts +++ b/src/vs/workbench/contrib/customEditor/browser/extensionPoint.ts @@ -24,7 +24,7 @@ interface IWebviewEditorsExtensionPoint { } const webviewEditorsContribution: IJSONSchema = { - description: nls.localize('contributes.webviewEditors', 'Contributes webview editors.'), + description: nls.localize('contributes.customEditors', 'Contributed custom editors.'), type: 'array', defaultSnippets: [{ body: [{ viewType: '', displayName: '' }] }], items: { @@ -76,7 +76,7 @@ const webviewEditorsContribution: IJSONSchema = { }; export const webviewEditorsExtensionPoint = ExtensionsRegistry.registerExtensionPoint({ - extensionPoint: 'webviewEditors', + extensionPoint: 'customEditors', deps: [languagesExtPoint], jsonSchema: webviewEditorsContribution }); diff --git a/src/vs/workbench/contrib/customEditor/common/customEditor.ts b/src/vs/workbench/contrib/customEditor/common/customEditor.ts index cf35eefe17..5acba2e3ff 100644 --- a/src/vs/workbench/contrib/customEditor/common/customEditor.ts +++ b/src/vs/workbench/contrib/customEditor/common/customEditor.ts @@ -18,7 +18,7 @@ import { IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCo export const ICustomEditorService = createDecorator('customEditorService'); -export const CONTEXT_HAS_CUSTOM_EDITORS = new RawContextKey('hasCustomEditors', false); +export const CONTEXT_CUSTOM_EDITORS = new RawContextKey('customEditors', ''); export const CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE = new RawContextKey('focusedCustomEditorIsEditable', false); export interface ICustomEditor { diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index 1c4e157fc5..a99eed56dd 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -1082,7 +1082,7 @@ export class ExtensionEditor extends BaseEditor { } private renderCustomEditors(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean { - const webviewEditors = manifest.contributes?.webviewEditors || []; + const webviewEditors = manifest.contributes?.customEditors || []; if (!webviewEditors.length) { return false; } diff --git a/src/vs/workbench/contrib/scm/browser/repositoryPane.ts b/src/vs/workbench/contrib/scm/browser/repositoryPane.ts index 6d7ad578e1..2b30baa53b 100644 --- a/src/vs/workbench/contrib/scm/browser/repositoryPane.ts +++ b/src/vs/workbench/contrib/scm/browser/repositoryPane.ts @@ -621,8 +621,6 @@ export class RepositoryPane extends ViewPane { protected contextKeyService: IContextKeyService; private commitTemplate = ''; - shouldShowWelcome() { return true; } - constructor( readonly repository: ISCMRepository, options: IViewPaneOptions, diff --git a/src/vs/workbench/contrib/search/common/searchModel.ts b/src/vs/workbench/contrib/search/common/searchModel.ts index d63fc26960..1ed7c150b7 100644 --- a/src/vs/workbench/contrib/search/common/searchModel.ts +++ b/src/vs/workbench/contrib/search/common/searchModel.ts @@ -141,6 +141,15 @@ export class Match { return thisMatchPreviewLines.join('\n'); } + rangeInPreview() { + // convert to editor's base 1 positions. + return { + ...this._fullPreviewRange, + startColumn: this._fullPreviewRange.startColumn + 1, + endColumn: this._fullPreviewRange.endColumn + 1 + }; + } + fullPreviewLines(): string[] { return this._fullPreviewLines.slice(this._fullPreviewRange.startLineNumber, this._fullPreviewRange.endLineNumber + 1); } diff --git a/src/vs/workbench/contrib/searchEditor/browser/constants.ts b/src/vs/workbench/contrib/searchEditor/browser/constants.ts index 430f4403f5..b3e0899d67 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/constants.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/constants.ts @@ -13,6 +13,7 @@ export const ToggleSearchEditorWholeWordCommandId = 'toggleSearchEditorWholeWord export const ToggleSearchEditorRegexCommandId = 'toggleSearchEditorRegex'; export const ToggleSearchEditorContextLinesCommandId = 'toggleSearchEditorContextLines'; export const RerunSearchEditorSearchCommandId = 'rerunSearchEditorSearch'; +export const CleanSearchEditorStateCommandId = 'cleanSearchEditorState'; export const SelectAllSearchEditorMatchesCommandId = 'selectAllSearchEditorMatches'; export const InSearchEditor = new RawContextKey('inSearchEditor', false); diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts index 3ed9b1c149..6d5b6cac5a 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts @@ -162,6 +162,15 @@ CommandsRegistry.registerCommand( activeControl.triggerSearch({ resetCursor: false }); } }); + +CommandsRegistry.registerCommand( + SearchEditorConstants.CleanSearchEditorStateCommandId, + (accessor: ServicesAccessor) => { + const activeControl = accessor.get(IEditorService).activeControl; + if (activeControl instanceof SearchEditor) { + activeControl.cleanState(); + } + }); //#endregion //#region Actions diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts index 4f05c901eb..1d46ef63c6 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts @@ -297,6 +297,10 @@ export class SearchEditor extends BaseTextEditor { this.toggleIncludesExcludes(); } + cleanState() { + this.getInput()?.setDirty(false); + } + private get searchConfig(): ISearchConfigurationProperties { return this.configurationService.getValue('search'); } diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts index b5dec3258b..288243d378 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditorSerialization.ts @@ -42,7 +42,7 @@ const matchToSearchResultFormat = (match: Match): { line: string, ranges: Range[ const rangeOnThisLine = ({ start, end }: { start?: number; end?: number; }) => new Range(1, (start ?? 1) + prefixOffset, 1, (end ?? sourceLine.length + 1) + prefixOffset); - const matchRange = match.range(); + const matchRange = match.rangeInPreview(); const matchIsSingleLine = matchRange.startLineNumber === matchRange.endLineNumber; let lineRange; @@ -211,9 +211,12 @@ export const serializeSearchResultForEditor = ? contentPatternToSearchResultHeader(searchResult.query, rawIncludePattern, rawExcludePattern, contextLines) : []; + const filecount = searchResult.fileCount() > 1 ? localize('numFiles', "{0} files", searchResult.fileCount()) : localize('oneFile', "1 file"); + const resultcount = searchResult.count() > 1 ? localize('numResults', "{0} results", searchResult.count()) : localize('oneResult', "1 result"); + const info = [ searchResult.count() - ? localize('resultCount', "{0} results in {1} files", searchResult.count(), searchResult.fileCount()) + ? `${filecount} - ${resultcount}` : localize('noResults', "No Results"), '']; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index ab9d80dd14..24c048f1ea 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -602,8 +602,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // Respect chords if the allowChords setting is set and it's not Escape. Escape is // handled specially for Zen Mode's Escape, Escape chord, plus it's important in // terminals generally - const allowChords = resolveResult && resolveResult.enterChord && this._configHelper.config.allowChords && event.key !== 'Escape'; - if (allowChords || resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) { + const allowChords = resolveResult?.enterChord && this._configHelper.config.allowChords && event.key !== 'Escape'; + if (this._keybindingService.inChordMode || allowChords || resolveResult && this._skipTerminalCommands.some(k => k === resolveResult.commandId)) { event.preventDefault(); return false; } diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 73cddec0c0..15f5262e76 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -38,8 +38,6 @@ import { MenuItemAction, IMenuService, MenuId } from 'vs/platform/actions/common import { fromNow } from 'vs/base/common/date'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -// TODO[ECA]: Localize all the strings - const InitialPageSize = 20; const SubsequentPageSize = 40; @@ -240,7 +238,7 @@ export class TimelinePane extends ViewPane { // TODO[ECA]: Are these the right the list of schemes to exclude? Is there a better way? if (this._uri && (this._uri.scheme === 'vscode-settings' || this._uri.scheme === 'webview-panel' || this._uri.scheme === 'walkThrough')) { - this.message = 'The active editor cannot provide timeline information.'; + this.message = localize('timeline.editorCannotProvideTimeline', 'The active editor cannot provide timeline information.'); this._tree.setChildren(null, undefined); return; @@ -253,7 +251,7 @@ export class TimelinePane extends ViewPane { } this._tree.setChildren(null, undefined); - this.message = `Loading timeline for ${basename(uri.fsPath)}...`; + this.message = localize('timeline.loading', 'Loading timeline for ${0}...', basename(uri.fsPath)); }, 500, this._uri); } } @@ -410,7 +408,7 @@ export class TimelinePane extends ViewPane { this._items.push({ element: { handle: 'vscode-command:loadMore', - label: 'Load more', + label: localize('timeline.loadMore', 'Load more'), timestamp: 0 } as CommandItem }); @@ -512,7 +510,7 @@ export class TimelinePane extends ViewPane { } if (this._items.length === 0) { - this.message = 'No timeline information was provided.'; + this.message = localize('timeline.noTimelineInfo', 'No timeline information was provided.'); } else { this.message = undefined; } @@ -556,7 +554,7 @@ export class TimelinePane extends ViewPane { this._messageElement = DOM.append(this._container, DOM.$('.message')); DOM.addClass(this._messageElement, 'timeline-subtle'); - this.message = 'The active editor cannot provide timeline information.'; + this.message = localize('timeline.editorCannotProvideTimeline', 'The active editor cannot provide timeline information.'); this._treeElement = document.createElement('div'); DOM.addClasses(this._treeElement, 'customview-tree', 'file-icon-themable-tree', 'hide-arrows'); diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.contribution.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.contribution.ts index e588584595..2c9482fb8c 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSync.contribution.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSync.contribution.ts @@ -3,50 +3,10 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions'; +import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { Registry } from 'vs/platform/registry/common/platform'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { UserDataSyncWorkbenchContribution } from 'vs/workbench/contrib/userDataSync/browser/userDataSync'; -import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; -import { IUserDataSyncEnablementService, getUserDataSyncStore } from 'vs/platform/userDataSync/common/userDataSync'; -import { IProductService } from 'vs/platform/product/common/productService'; - -class UserDataSyncSettingsMigrationContribution implements IWorkbenchContribution { - - constructor( - @IProductService productService: IProductService, - @IConfigurationService private readonly configurationService: IConfigurationService, - @IUserDataSyncEnablementService userDataSyncEnablementService: IUserDataSyncEnablementService, - ) { - if (getUserDataSyncStore(productService, configurationService)) { - if (!configurationService.getValue('sync.enableSettings')) { - userDataSyncEnablementService.setResourceEnablement('settings', false); - } - if (!configurationService.getValue('sync.enableKeybindings')) { - userDataSyncEnablementService.setResourceEnablement('keybindings', false); - } - if (!configurationService.getValue('sync.enableUIState')) { - userDataSyncEnablementService.setResourceEnablement('globalState', false); - } - if (!configurationService.getValue('sync.enableExtensions')) { - userDataSyncEnablementService.setResourceEnablement('extensions', false); - } - if (configurationService.getValue('sync.enable')) { - userDataSyncEnablementService.setEnablement(true); - } - this.removeFromConfiguration(); - } - } - - private async removeFromConfiguration(): Promise { - await this.configurationService.updateValue('sync.enable', undefined, {}, ConfigurationTarget.USER, true); - await this.configurationService.updateValue('sync.enableSettings', undefined, {}, ConfigurationTarget.USER, true); - await this.configurationService.updateValue('sync.enableKeybindings', undefined, {}, ConfigurationTarget.USER, true); - await this.configurationService.updateValue('sync.enableUIState', undefined, {}, ConfigurationTarget.USER, true); - await this.configurationService.updateValue('sync.enableExtensions', undefined, {}, ConfigurationTarget.USER, true); - } -} const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); workbenchRegistry.registerWorkbenchContribution(UserDataSyncWorkbenchContribution, LifecyclePhase.Ready); -workbenchRegistry.registerWorkbenchContribution(UserDataSyncSettingsMigrationContribution, LifecyclePhase.Ready);