Merge from vscode 93309f060778f6480a7d2a13913e6e7c624e9bc7

This commit is contained in:
ADS Merger
2020-03-26 07:08:23 +00:00
parent 685e0ccf7e
commit f5134198e2
87 changed files with 942 additions and 631 deletions

View File

@@ -121,21 +121,33 @@ suite.skip('BackupRestorer', () => { // {{SQL CARBON EDIT}} TODO @anthonydresser
const resource = editor.resource;
if (isEqual(resource, untitledFile1)) {
const model = await accessor.textFileService.untitled.resolve({ untitledResource: resource });
assert.equal(model.textEditorModel.getValue(), 'untitled-1');
if (model.textEditorModel.getValue() !== 'untitled-1') {
const backupContents = await backupFileService.getBackupContents(untitledFile1);
assert.fail(`Unable to restore backup for resource ${untitledFile1.toString()}. Backup contents: ${backupContents}`);
}
model.dispose();
counter++;
} else if (isEqual(resource, untitledFile2)) {
const model = await accessor.textFileService.untitled.resolve({ untitledResource: resource });
assert.equal(model.textEditorModel.getValue(), 'untitled-2');
if (model.textEditorModel.getValue() !== 'untitled-2') {
const backupContents = await backupFileService.getBackupContents(untitledFile2);
assert.fail(`Unable to restore backup for resource ${untitledFile2.toString()}. Backup contents: ${backupContents}`);
}
model.dispose();
counter++;
} else if (isEqual(resource, fooFile)) {
const model = await accessor.textFileService.files.get(resource!)?.load();
assert.equal(model?.textEditorModel?.getValue(), 'fooFile');
const model = await accessor.textFileService.files.get(fooFile!)?.load();
if (model?.textEditorModel?.getValue() !== 'fooFile') {
const backupContents = await backupFileService.getBackupContents(fooFile);
assert.fail(`Unable to restore backup for resource ${fooFile.toString()}. Backup contents: ${backupContents}`);
}
counter++;
} else {
const model = await accessor.textFileService.files.get(resource!)?.load();
assert.equal(model?.textEditorModel?.getValue(), 'barFile');
const model = await accessor.textFileService.files.get(barFile!)?.load();
if (model?.textEditorModel?.getValue() !== 'barFile') {
const backupContents = await backupFileService.getBackupContents(barFile);
assert.fail(`Unable to restore backup for resource ${barFile.toString()}. Backup contents: ${backupContents}`);
}
counter++;
}
}

View File

@@ -70,6 +70,12 @@ class InspectEditorTokensController extends Disposable implements IEditorContrib
this._register(this._editor.onDidChangeModel((e) => this.stop()));
this._register(this._editor.onDidChangeModelLanguage((e) => this.stop()));
this._register(this._editor.onKeyUp((e) => e.keyCode === KeyCode.Escape && this.stop()));
this._register(this._themeService.onDidColorThemeChange(_ => {
if (this._widget) {
this.stop();
this.launch();
}
}));
}
public dispose(): void {

View File

@@ -6,6 +6,7 @@
import { memoize } from 'vs/base/common/decorators';
import { Lazy } from 'vs/base/common/lazy';
import { IReference } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
import { basename } from 'vs/base/common/path';
import { isEqual } from 'vs/base/common/resources';
import { assertIsDefined } from 'vs/base/common/types';
@@ -99,6 +100,10 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
return this._modelRef ? this._modelRef.object.isReadonly() : false;
}
public isUntitled(): boolean {
return this.resource.scheme === Schemas.untitled;
}
public isDirty(): boolean {
if (!this._modelRef) {
return false;
@@ -120,8 +125,16 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
public async save(groupId: GroupIdentifier, options?: ISaveOptions): Promise<IEditorInput | undefined> {
const modelRef = assertIsDefined(this._modelRef);
const result = await modelRef.object.save(options);
return result ? this : undefined;
const target = await modelRef.object.saveCustomEditor(options);
if (!target) {
return undefined; // save cancelled
}
if (!isEqual(target, this.resource)) {
return this.customEditorService.createInput(target, this.viewType, groupId);
}
return this;
}
public async saveAs(groupId: GroupIdentifier, options?: ISaveOptions): Promise<IEditorInput | undefined> {
@@ -133,7 +146,7 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
return undefined; // save cancelled
}
if (!await modelRef.object.saveAs(this._editorResource, target, options)) {
if (!await modelRef.object.saveCustomEditorAs(this._editorResource, target, options)) {
return undefined;
}
@@ -160,29 +173,29 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
}
move(group: GroupIdentifier, newResource: URI): { editor: IEditorInput } | undefined {
// See if we can keep using the same custom editor provider
const editorInfo = this.customEditorService.getCustomEditor(this.viewType);
if (editorInfo?.matches(newResource)) {
// We can keep using the same custom editor provider
if (!this._moveHandler) {
return {
editor: this.customEditorService.createInput(newResource, this.viewType, group),
};
}
this._moveHandler(newResource);
const newEditor = this.instantiationService.createInstance(CustomEditorInput,
newResource,
this.viewType,
this.id,
new Lazy(() => undefined!)); // this webview is replaced in the transfer call
this.transfer(newEditor);
newEditor.updateGroup(group);
return { editor: newEditor };
} else {
// const possible = this.customEditorService.getContributedCustomEditors(newResource);
return { editor: this.editorService.createEditorInput({ resource: newResource, forceFile: true }) };
return { editor: this.doMove(group, newResource) };
}
return { editor: this.editorService.createEditorInput({ resource: newResource, forceFile: true }) };
}
private doMove(group: GroupIdentifier, newResource: URI): IEditorInput {
if (!this._moveHandler) {
return this.customEditorService.createInput(newResource, this.viewType, group);
}
this._moveHandler(newResource);
const newEditor = this.instantiationService.createInstance(CustomEditorInput,
newResource,
this.viewType,
this.id,
new Lazy(() => undefined!)); // this webview is replaced in the transfer call
this.transfer(newEditor);
newEditor.updateGroup(group);
return newEditor;
}

View File

@@ -327,8 +327,8 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
private async handleMovedFileInOpenedFileEditors(_oldResource: URI, newResource: URI): Promise<void> {
// See if the new resource can be opened in a custom editor
const possibleEditors = this.getAllCustomEditors(newResource).allEditors;
if (!possibleEditors.length) {
const possibleEditors = this.getAllCustomEditors(newResource);
if (!possibleEditors.allEditors.length) {
return;
}
@@ -354,19 +354,25 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
return;
}
// If there is, show a single prompt for all editors to see if the user wants to re-open them
//
// TODO: instead of prompting eagerly, it'd likly be better to replace all the editors with
// ones that would prompt when they first become visible
await new Promise(resolve => setTimeout(resolve, 50));
const pickedViewType = await this.showOpenWithPrompt(newResource);
if (!pickedViewType) {
let viewType: string | undefined;
if (possibleEditors.defaultEditor) {
viewType = possibleEditors.defaultEditor.id;
} else {
// If there is, show a single prompt for all editors to see if the user wants to re-open them
//
// TODO: instead of prompting eagerly, it'd likly be better to replace all the editors with
// ones that would prompt when they first become visible
await new Promise(resolve => setTimeout(resolve, 50));
viewType = await this.showOpenWithPrompt(newResource);
}
if (!viewType) {
return;
}
for (const [group, entries] of editorsToReplace) {
this.editorService.replaceEditors(entries.map(editor => {
const replacement = this.createInput(newResource, pickedViewType, group);
const replacement = this.createInput(newResource, viewType!, group);
return {
editor,
replacement,

View File

@@ -26,7 +26,15 @@ interface IWebviewEditorsExtensionPoint {
const webviewEditorsContribution: IJSONSchema = {
description: nls.localize('contributes.customEditors', 'Contributed custom editors.'),
type: 'array',
defaultSnippets: [{ body: [{ viewType: '', displayName: '' }] }],
defaultSnippets: [{
body: [{
[WebviewEditorContribution.viewType]: '$1',
[WebviewEditorContribution.displayName]: '$2',
[WebviewEditorContribution.selector]: [{
filenamePattern: '$3'
}],
}]
}],
items: {
type: 'object',
required: [
@@ -48,6 +56,11 @@ const webviewEditorsContribution: IJSONSchema = {
description: nls.localize('contributes.selector', 'Set of globs that the custom editor is enabled for.'),
items: {
type: 'object',
defaultSnippets: [{
body: {
filenamePattern: '$1',
}
}],
properties: {
filenamePattern: {
type: 'string',
@@ -64,7 +77,7 @@ const webviewEditorsContribution: IJSONSchema = {
CustomEditorPriority.option,
CustomEditorPriority.builtin,
],
enumDescriptions: [
markdownEnumDescriptions: [
nls.localize('contributes.priority.default', 'Editor is automatically used for a resource if no other default custom editors are registered for it.'),
nls.localize('contributes.priority.option', 'Editor is not automatically used but can be selected by a user.'),
nls.localize('contributes.priority.builtin', 'Editor automatically used if no other `default` or `builtin` editors are registered for the resource.'),

View File

@@ -57,8 +57,8 @@ export interface ICustomEditorModel extends IDisposable {
revert(options?: IRevertOptions): Promise<void>;
save(options?: ISaveOptions): Promise<boolean>;
saveAs(resource: URI, targetResource: URI, currentOptions?: ISaveOptions): Promise<boolean>;
saveCustomEditor(options?: ISaveOptions): Promise<URI | undefined>;
saveCustomEditorAs(resource: URI, targetResource: URI, currentOptions?: ISaveOptions): Promise<boolean>;
}
export const enum CustomEditorPriority {

View File

@@ -68,11 +68,11 @@ export class CustomTextEditorModel extends Disposable implements ICustomEditorMo
return this.textFileService.revert(this.resource, options);
}
public async save(options?: ISaveOptions): Promise<boolean> {
return !!await this.textFileService.save(this.resource, options);
public saveCustomEditor(options?: ISaveOptions): Promise<URI | undefined> {
return this.textFileService.save(this.resource, options);
}
public async saveAs(resource: URI, targetResource: URI, options?: ISaveOptions): Promise<boolean> {
public async saveCustomEditorAs(resource: URI, targetResource: URI, options?: ISaveOptions): Promise<boolean> {
return !!await this.textFileService.saveAs(resource, targetResource, options);
}
}

View File

@@ -103,6 +103,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewE
Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry).registerViews([{
id: REPL_VIEW_ID,
name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'),
containerIcon: 'codicon-debug-console',
canToggleVisibility: false,
canMoveView: true,
ctorDescriptor: new SyncDescriptor(Repl),

View File

@@ -36,7 +36,7 @@ import { IDecorationOptions } from 'vs/editor/common/editorCommon';
import { transparent, editorForeground } from 'vs/platform/theme/common/colorRegistry';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems';
import { CompletionContext, CompletionList, CompletionProviderRegistry, CompletionItem, completionKindFromString, CompletionItemKind } from 'vs/editor/common/modes';
import { CompletionContext, CompletionList, CompletionProviderRegistry, CompletionItem, completionKindFromString, CompletionItemKind, CompletionItemInsertTextRule } from 'vs/editor/common/modes';
import { first } from 'vs/base/common/arrays';
import { ITreeNode, ITreeContextMenuEvent, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -147,13 +147,24 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
if (response && response.body && response.body.targets) {
response.body.targets.forEach(item => {
if (item && item.label) {
let insertTextRules: CompletionItemInsertTextRule | undefined = undefined;
let insertText = item.text || item.label;
if (typeof item.selectionStart === 'number') {
// If a debug completion item sets a selection we need to use snippets to make sure the selection is selected #90974
insertTextRules = CompletionItemInsertTextRule.InsertAsSnippet;
const selectionLength = typeof item.selectionLength === 'number' ? item.selectionLength : 0;
const placeholder = selectionLength > 0 ? '${1:' + insertText.substr(item.selectionStart, selectionLength) + '}$0' : '$0';
insertText = insertText.substr(0, item.selectionStart) + placeholder + insertText.substr(item.selectionStart + selectionLength);
}
suggestions.push({
label: item.label,
insertText: item.text || item.label,
insertText,
kind: completionKindFromString(item.type || 'property'),
filterText: (item.start && item.length) ? text.substr(item.start, item.length).concat(item.label) : undefined,
range: computeRange(item.length || overwriteBefore),
sortText: item.sortText
sortText: item.sortText,
insertTextRules
});
}
});

View File

@@ -247,6 +247,9 @@ function convertPaths(msg: DebugProtocol.ProtocolMessage, fixSourcePath: (toDA:
export function getVisibleAndSorted<T extends { presentation?: IConfigPresentation }>(array: T[]): T[] {
return array.filter(config => !config.presentation?.hidden).sort((first, second) => {
if (!first.presentation) {
if (!second.presentation) {
return 0;
}
return 1;
}
if (!second.presentation) {
@@ -271,6 +274,10 @@ export function getVisibleAndSorted<T extends { presentation?: IConfigPresentati
function compareOrders(first: number | undefined, second: number | undefined): number {
if (typeof first !== 'number') {
if (typeof second !== 'number') {
return 0;
}
return 1;
}
if (typeof second !== 'number') {

View File

@@ -207,6 +207,7 @@ export class ExtensionEditor extends BaseEditor {
const root = append(parent, $('.extension-editor'));
root.tabIndex = 0; // this is required for the focus tracker on the editor
root.style.outline = 'none';
root.setAttribute('role', 'document');
const header = append(root, $('.header'));
const iconContainer = append(header, $('.icon-container'));

View File

@@ -32,6 +32,7 @@ import { isWindows } from 'vs/base/common/platform';
import { Schemas } from 'vs/base/common/network';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { SaveReason } from 'vs/workbench/common/editor';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
export const CONFLICT_RESOLUTION_CONTEXT = 'saveConflictResolutionContext';
export const CONFLICT_RESOLUTION_SCHEME = 'conflictResolution';
@@ -53,10 +54,14 @@ export class TextFileSaveErrorHandler extends Disposable implements ISaveErrorHa
@IEditorService private readonly editorService: IEditorService,
@ITextModelService textModelService: ITextModelService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IStorageService private readonly storageService: IStorageService
@IStorageService private readonly storageService: IStorageService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
) {
super();
// opt-in to syncing
storageKeysSyncRegistryService.registerStorageKey({ key: LEARN_MORE_DIRTY_WRITE_IGNORE_KEY, version: 1 });
this.messages = new ResourceMap<INotificationHandle>();
this.conflictResolutionContext = new RawContextKey<boolean>(CONFLICT_RESOLUTION_CONTEXT, false).bindTo(contextKeyService);

View File

@@ -26,11 +26,14 @@ import { minimumTranslatedStrings } from 'vs/workbench/contrib/localizations/bro
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
// Register action to configure locale and related settings
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
registry.registerWorkbenchAction(SyncActionDescriptor.create(ConfigureLocaleAction, ConfigureLocaleAction.ID, ConfigureLocaleAction.LABEL), 'Configure Display Language');
const LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY = 'extensionsAssistant/languagePackSuggestionIgnore';
export class LocalizationWorkbenchContribution extends Disposable implements IWorkbenchContribution {
constructor(
@INotificationService private readonly notificationService: INotificationService,
@@ -41,9 +44,12 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
@IViewletService private readonly viewletService: IViewletService,
@ITelemetryService private readonly telemetryService: ITelemetryService
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
) {
super();
storageKeysSyncRegistryService.registerStorageKey({ key: LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY, version: 1 });
this.checkAndInstall();
this._register(this.extensionManagementService.onDidInstallExtension(e => this.onDidInstallExtension(e)));
}
@@ -77,7 +83,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
private checkAndInstall(): void {
const language = platform.language;
const locale = platform.locale;
const languagePackSuggestionIgnoreList = <string[]>JSON.parse(this.storageService.get('extensionsAssistant/languagePackSuggestionIgnore', StorageScope.GLOBAL, '[]'));
const languagePackSuggestionIgnoreList = <string[]>JSON.parse(this.storageService.get(LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY, StorageScope.GLOBAL, '[]'));
if (!this.galleryService.isEnabled()) {
return;
@@ -168,7 +174,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
run: () => {
languagePackSuggestionIgnoreList.push(language);
this.storageService.store(
'extensionsAssistant/languagePackSuggestionIgnore',
LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY,
JSON.stringify(languagePackSuggestionIgnoreList),
StorageScope.GLOBAL
);

View File

@@ -20,11 +20,11 @@ export const COPY_CELL_DOWN_COMMAND_ID = 'workbench.notebook.cell.copyDown';
export const EXECUTE_CELL_COMMAND_ID = 'workbench.notebook.cell.execute';
// Cell sizing related
export const CELL_MARGIN = 32;
export const CELL_MARGIN = 20;
export const CELL_RUN_GUTTER = 32; // TODO should be dynamic based on execution order width, and runnable enablement
export const EDITOR_TOP_PADDING = 8;
export const EDITOR_BOTTOM_PADDING = 8;
export const EDITOR_TOOLBAR_HEIGHT = 22;
export const RUN_BUTTON_WIDTH = 20;
// Cell context keys
export const NOTEBOOK_CELL_TYPE_CONTEXT_KEY = 'notebookCellType'; // code, markdown

View File

@@ -16,6 +16,7 @@ import { CellRenderTemplate, CellEditState, ICellViewModel, INotebookEditor, KEY
import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { CellKind, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
const enum CellToolbarOrder {
MoveCellUp,
@@ -709,9 +710,9 @@ registerAction2(class extends Action2 {
id: 'workbench.action.notebook.cursorDown',
title: 'Notebook Cursor Move Down',
keybinding: {
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.has(InputFocusedContextKey), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('top'), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('none')),
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.has(InputFocusedContextKey), EditorContextKeys.editorTextFocus, NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('top'), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('none')),
primary: KeyCode.DownArrow,
weight: KeybindingWeight.WorkbenchContrib
weight: KeybindingWeight.EditorContrib // smaller than Suggest Widget, etc
}
});
}
@@ -748,9 +749,9 @@ registerAction2(class extends Action2 {
id: 'workbench.action.notebook.cursorUp',
title: 'Notebook Cursor Move Up',
keybinding: {
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.has(InputFocusedContextKey), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('bottom'), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('none')),
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.has(InputFocusedContextKey), EditorContextKeys.editorTextFocus, NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('bottom'), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('none')),
primary: KeyCode.UpArrow,
weight: KeybindingWeight.WorkbenchContrib
weight: KeybindingWeight.EditorContrib // smaller than Suggest Widget, etc
},
});
}

View File

@@ -30,7 +30,7 @@
position: relative;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .cell {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell {
display: flex;
}
@@ -87,16 +87,16 @@
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row {
overflow: visible !important;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row:focus-within {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:focus-within {
z-index: 10;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .menu {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu {
position: absolute;
left: 0;
top: 28px;
@@ -107,40 +107,65 @@
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .menu.mouseover,
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row:hover .menu {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu.mouseover,
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .menu {
visibility: visible;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list .monaco-list-row:hover {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover {
outline: none !important;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list .monaco-list-row.selected,
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list .monaco-list-row.focused {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.selected,
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused {
outline: none !important;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .menu.mouseover,
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .menu:hover {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu.mouseover,
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu:hover {
cursor: pointer;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > .monaco-toolbar {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .monaco-toolbar {
visibility: hidden;
margin-right: 24px;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .cell .run-button-container .monaco-toolbar {
margin-top: 8px;
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container {
position: relative;
}
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .monaco-toolbar {
margin-top: 5px;
visibility: hidden;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row:hover .cell .run-button-container .monaco-toolbar,
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row.focused .cell .run-button-container .monaco-toolbar {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .monaco-toolbar .codicon-play {
margin-right: 8px;
}
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .cell.runnable .run-button-container .monaco-toolbar,
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused .cell.runnable .run-button-container .monaco-toolbar {
visibility: visible;
}
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .execution-count-label {
position: absolute;
top: 2px;
font-size: 12px;
visibility: visible;
white-space: pre;
width: 100%;
text-align: center;
padding-right: 2px;
box-sizing: border-box;
}
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .cell .run-button-container .execution-count-label,
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused .cell .run-button-container .execution-count-label {
visibility: hidden;
}
.monaco-workbench .part.editor > .content .notebook-editor .cell .cell-editor-container {
position: relative;
}
@@ -149,13 +174,13 @@
top: 0px;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row.focused .monaco-toolbar,
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row:hover .monaco-toolbar {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused .monaco-toolbar,
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .monaco-toolbar {
visibility: visible;
}
.monaco-workbench .part.editor > .content .notebook-editor .monaco-tree.focused.no-focused-item:focus:before,
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list:not(.element-focused):focus:before {
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list:not(.element-focused):focus:before {
outline: none !important;
}
@@ -167,7 +192,7 @@
width: 6px;
border-left-width: 2px;
border-left-style: solid;
left: 28px;
left: 20px;
top: 22px;
bottom: 8px;
visibility: hidden;

View File

@@ -15,7 +15,7 @@ import { FindMatch } from 'vs/editor/common/model';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
import { IModelDecorationsChangeAccessor, NotebookViewModel, CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellKind, IOutput, IRenderOutput, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellKind, IOutput, IRenderOutput, NotebookCellMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NOTEBOOK_EDITABLE_CONTEXT_KEY } from 'vs/workbench/contrib/notebook/browser/constants';
export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey<boolean>('notebookFindWidgetFocused', false);
@@ -72,6 +72,7 @@ export interface ICellViewModel {
focusMode: CellFocusMode;
getText(): string;
metadata: NotebookCellMetadata | undefined;
getEvaluatedMetadata(documentMetadata: NotebookDocumentMetadata | undefined): NotebookCellMetadata;
}
export interface INotebookEditor {
@@ -249,6 +250,7 @@ export interface CellRenderTemplate {
focusIndicator?: HTMLElement;
runToolbar?: ToolBar;
runButtonContainer?: HTMLElement;
executionOrderLabel?: HTMLElement;
editingContainer?: HTMLElement;
outputContainer?: HTMLElement;
editor?: CodeEditorWidget;

View File

@@ -14,7 +14,6 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -29,7 +28,6 @@ import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/outpu
import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
import { CodeCellRenderer, MarkdownCellRenderer, NotebookCellListDelegate } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
import { IOutput, CellKind, CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
@@ -42,7 +40,7 @@ import { NotebookViewModel, INotebookEditorViewState, IModelDecorationsChangeAcc
import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { Range } from 'vs/editor/common/core/range';
import { CELL_MARGIN, RUN_BUTTON_WIDTH } from 'vs/workbench/contrib/notebook/browser/constants';
import { CELL_MARGIN, CELL_RUN_GUTTER } from 'vs/workbench/contrib/notebook/browser/constants';
import { Color, RGBA } from 'vs/base/common/color';
import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
@@ -113,11 +111,9 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
@IThemeService themeService: IThemeService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IStorageService storageService: IStorageService,
@IWebviewService private webviewService: IWebviewService,
@INotebookService private notebookService: INotebookService,
@IEditorGroupsService editorGroupService: IEditorGroupsService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IEnvironmentService private readonly environmentSerice: IEnvironmentService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
) {
super(NotebookEditor.ID, telemetryService, themeService, storageService);
@@ -223,7 +219,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
);
this.control = new NotebookCodeEditors(this.list, this.renderedEditors);
this.webview = new BackLayerWebView(this.webviewService, this.notebookService, this, this.environmentSerice);
this.webview = this.instantiationService.createInstance(BackLayerWebView, this);
this._register(this.webview.onMessage(message => {
if (this.viewModel) {
this.notebookService.onDidReceiveMessage(this.viewModel.viewType, this.viewModel.uri, message);
@@ -334,7 +330,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
private async attachModel(input: NotebookEditorInput, model: NotebookEditorModel) {
if (!this.webview) {
this.webview = new BackLayerWebView(this.webviewService, this.notebookService, this, this.environmentSerice);
this.webview = this.instantiationService.createInstance(BackLayerWebView, this);
this.list?.rowsContainer.insertAdjacentElement('afterbegin', this.webview!.element);
}
@@ -798,8 +794,10 @@ registerThemingParticipant((theme, collector) => {
}
// Cell Margin
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > div.cell { padding: 8px ${CELL_MARGIN}px 8px ${CELL_MARGIN}px; }`);
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { margin: 8px ${CELL_MARGIN}px 8px ${CELL_MARGIN + RUN_BUTTON_WIDTH}px }`);
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > div.cell { margin: 8px ${CELL_MARGIN}px 8px ${CELL_MARGIN}px; }`);
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { margin: 8px ${CELL_MARGIN}px 8px ${CELL_MARGIN + CELL_RUN_GUTTER}px }`);
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .cell-editor-container { width: calc(100% - ${RUN_BUTTON_WIDTH}px); }`);
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .cell-editor-container { width: calc(100% - ${CELL_RUN_GUTTER}px); }`);
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > div.cell.markdown { padding-left: ${CELL_RUN_GUTTER}px; }`);
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .run-button-container { width: ${CELL_RUN_GUTTER}px; }`);
});

View File

@@ -15,8 +15,9 @@ import { IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IWebviewService, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewResourceScheme } from 'vs/workbench/contrib/webview/common/resourceLoader';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { CELL_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants';
import { CELL_MARGIN, CELL_RUN_GUTTER } from 'vs/workbench/contrib/notebook/browser/constants';
import { Emitter, Event } from 'vs/base/common/event';
import { IOpenerService } from 'vs/platform/opener/common/opener';
export interface IDimentionMessage {
__vscode_notebook_message: boolean;
@@ -43,11 +44,13 @@ export interface ICreationRequestMessage {
id: string;
outputId: string;
top: number;
left: number;
}
export interface IContentWidgetTopRequest {
id: string;
top: number;
left: number;
}
export interface IViewScrollTopRequestMessage {
@@ -85,7 +88,13 @@ export class BackLayerWebView extends Disposable {
public readonly onMessage: Event<any> = this._onMessage.event;
constructor(public webviewService: IWebviewService, public notebookService: INotebookService, public notebookEditor: INotebookEditor, public environmentSerice: IEnvironmentService) {
constructor(
public notebookEditor: INotebookEditor,
@IWebviewService webviewService: IWebviewService,
@IOpenerService openerService: IOpenerService,
@IEnvironmentService private readonly environmentSerice: IEnvironmentService,
@INotebookService private readonly notebookService: INotebookService,
) {
super();
this.element = document.createElement('div');
@@ -194,6 +203,7 @@ export class BackLayerWebView extends Disposable {
let outputNode = document.createElement('div');
outputNode.style.position = 'absolute';
outputNode.style.top = event.data.top + 'px';
outputNode.style.left = event.data.left + 'px';
outputNode.id = outputId;
let content = event.data.content;
@@ -258,6 +268,10 @@ export class BackLayerWebView extends Disposable {
this.webview = this._createInset(webviewService, content);
this.webview.mountTo(this.element);
this._register(this.webview.onDidClickLink(link => {
openerService.open(link, { fromUserGesture: true });
}));
this._register(this.webview.onDidWheel(e => {
this.notebookEditor.triggerScroll(e);
}));
@@ -331,7 +345,8 @@ export class BackLayerWebView extends Disposable {
return {
id: id,
top: outputOffset
top: outputOffset,
left: CELL_RUN_GUTTER
};
});
@@ -355,7 +370,8 @@ export class BackLayerWebView extends Disposable {
content: shadowContent,
id: cell.id,
outputId: outputId,
top: initialTop
top: initialTop,
left: CELL_RUN_GUTTER
};
this.webview.sendMessage(message);

View File

@@ -6,6 +6,7 @@
import { getZoomLevel } from 'vs/base/browser/browser';
import * as DOM from 'vs/base/browser/dom';
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
import { IAction } from 'vs/base/common/actions';
import { DisposableStore } from 'vs/base/common/lifecycle';
@@ -16,15 +17,16 @@ import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { MenuItemAction, IMenu } from 'vs/platform/actions/common/actions';
import { IMenu, MenuItemAction } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, NOTEBOOK_CELL_TYPE_CONTEXT_KEY, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY } from 'vs/workbench/contrib/notebook/browser/constants';
import { CellRenderTemplate, CellRunState, ICellViewModel, INotebookEditor, CellEditState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, NOTEBOOK_CELL_TYPE_CONTEXT_KEY } from 'vs/workbench/contrib/notebook/browser/constants';
import { ExecuteCellAction, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/notebookActions';
import { CellEditState, CellRenderTemplate, CellRunState, ICellViewModel, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus';
import { CodeCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/codeCell';
import { StatefullMarkdownCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/markdownCell';
@@ -32,8 +34,6 @@ import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewMod
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookCellActionContext, ExecuteCellAction } from 'vs/workbench/contrib/notebook/browser/contrib/notebookActions';
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
const $ = DOM.$;
@@ -221,8 +221,8 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
const contextKeyService = this.contextKeyService.createScoped(templateData.container);
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'markdown');
const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, !!(element.metadata?.editable));
elementDisposable.add(element.onDidChangeMetadata((e) => {
cellEditableKey.set(!!e?.editable);
elementDisposable.add(element.onDidChangeMetadata(() => {
cellEditableKey.set(!!element.metadata?.editable);
}));
const editModeKey = contextKeyService.createKey(NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, element.editState === CellEditState.Editing);
@@ -286,6 +286,8 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
])();
disposables.add(runToolbar);
const executionOrderLabel = DOM.append(runButtonContainer, $('div.execution-count-label'));
const editorContainer = DOM.append(cellContainer, $('.cell-editor-container'));
const editor = this.instantiationService.createInstance(CodeEditorWidget, editorContainer, {
...this.editorOptions,
@@ -314,6 +316,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
toolbar,
runToolbar,
runButtonContainer,
executionOrderLabel,
outputContainer,
editor,
disposables,
@@ -352,21 +355,36 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
}
}));
function renderExecutionOrder() {
const executionOrdeerLabel = typeof element.metadata?.executionOrder === 'number' ? `[ ${element.metadata.executionOrder} ]` :
'[ ]';
templateData.executionOrderLabel!.innerText = executionOrdeerLabel;
}
const contextKeyService = this.contextKeyService.createScoped(templateData.container);
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'code');
const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, !!(element.metadata?.editable));
const updateForMetadata = () => {
const metadata = element.getEvaluatedMetadata(this.notebookEditor.viewModel!.notebookDocument.metadata);
DOM.toggleClass(templateData.cellContainer, 'runnable', !!metadata.runnable);
renderExecutionOrder();
cellEditableKey.set(!!metadata.editable);
};
updateForMetadata();
elementDisposable.add(element.onDidChangeMetadata(() => {
updateForMetadata();
}));
this.setupCellToolbarActions(contextKeyService, templateData, elementDisposable);
const toolbarContext = <INotebookCellActionContext>{
cell: element,
cellTemplate: templateData,
notebookEditor: this.notebookEditor,
$mid: 12
};
const contextKeyService = this.contextKeyService.createScoped(templateData.container);
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'code');
const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, !!(element.metadata?.editable));
elementDisposable.add(element.onDidChangeMetadata((e) => {
cellEditableKey.set(!!e?.editable);
}));
this.setupCellToolbarActions(contextKeyService, templateData, elementDisposable);
templateData.toolbar.context = toolbarContext;
templateData.runToolbar!.context = toolbarContext;
}

View File

@@ -83,7 +83,7 @@ export class CodeCell extends Disposable {
}));
templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel?.metadata).editable) });
this._register(viewCell.onDidChangeMetadata((e) => {
this._register(viewCell.onDidChangeMetadata(() => {
templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel?.metadata).editable) });
}));

View File

@@ -32,8 +32,8 @@ export abstract class BaseCellViewModel extends Disposable {
readonly onDidChangeEditorAttachState = this._onDidChangeEditorAttachState.event;
protected readonly _onDidChangeCursorSelection: Emitter<void> = this._register(new Emitter<void>());
public readonly onDidChangeCursorSelection: Event<void> = this._onDidChangeCursorSelection.event;
protected readonly _onDidChangeMetadata: Emitter<NotebookCellMetadata | undefined> = this._register(new Emitter<NotebookCellMetadata | undefined>());
public readonly onDidChangeMetadata: Event<NotebookCellMetadata | undefined> = this._onDidChangeMetadata.event;
protected readonly _onDidChangeMetadata: Emitter<void> = this._register(new Emitter<void>());
public readonly onDidChangeMetadata: Event<void> = this._onDidChangeMetadata.event;
protected readonly _onDidChangeLanguage: Emitter<string> = this._register(new Emitter<string>());
public readonly onDidChangeLanguage: Event<string> = this._onDidChangeLanguage.event;
get handle() {
@@ -106,8 +106,8 @@ export abstract class BaseCellViewModel extends Disposable {
this._onDidChangeLanguage.fire(e);
}));
this._register(cell.onDidChangeMetadata((e) => {
this._onDidChangeMetadata.fire(e);
this._register(cell.onDidChangeMetadata(() => {
this._onDidChangeMetadata.fire();
}));
}

View File

@@ -8,7 +8,7 @@ import * as UUID from 'vs/base/common/uuid';
import * as model from 'vs/editor/common/model';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer';
import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, CELL_MARGIN, RUN_BUTTON_WIDTH } from 'vs/workbench/contrib/notebook/browser/constants';
import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, CELL_MARGIN, CELL_RUN_GUTTER } from 'vs/workbench/contrib/notebook/browser/constants';
import { CellEditState, ICellViewModel, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellKind, ICell, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { BaseCellViewModel } from './baseCellViewModel';
@@ -72,6 +72,10 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
}));
}
this._register(this.cell.onDidChangeMetadata(() => {
this._onDidChangeMetadata.fire();
}));
this._outputCollection = new Array(this.cell.outputs.length);
this._buffer = null;
@@ -105,7 +109,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
? EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + 16 + outputTotalHeight
: EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + outputTotalHeight;
const indicatorHeight = totalHeight - EDITOR_TOOLBAR_HEIGHT - 16;
const editorWidth = state.outerWidth !== undefined ? state.outerWidth - CELL_MARGIN * 2 - RUN_BUTTON_WIDTH : 0;
const editorWidth = state.outerWidth !== undefined ? state.outerWidth - CELL_MARGIN * 2 - CELL_RUN_GUTTER : 0;
this._layoutInfo = {
fontInfo: state.font || null,
editorHeight: this._editorHeight,

View File

@@ -15,8 +15,8 @@ export class NotebookCellTextModel implements ICell {
private _onDidChangeContent = new Emitter<void>();
onDidChangeContent: Event<void> = this._onDidChangeContent.event;
private _onDidChangeMetadata = new Emitter<NotebookCellMetadata | undefined>();
onDidChangeMetadata: Event<NotebookCellMetadata | undefined> = this._onDidChangeMetadata.event;
private _onDidChangeMetadata = new Emitter<void>();
onDidChangeMetadata: Event<void> = this._onDidChangeMetadata.event;
private _onDidChangeLanguage = new Emitter<string>();
onDidChangeLanguage: Event<string> = this._onDidChangeLanguage.event;
@@ -44,7 +44,7 @@ export class NotebookCellTextModel implements ICell {
set metadata(newMetadata: NotebookCellMetadata | undefined) {
this._metadata = newMetadata;
this._onDidChangeMetadata.fire(this._metadata);
this._onDidChangeMetadata.fire();
}
get language() {

View File

@@ -45,6 +45,7 @@ export interface NotebookDocumentMetadata {
export interface NotebookCellMetadata {
editable?: boolean;
runnable?: boolean;
executionOrder?: number;
}
export interface INotebookDisplayOrder {
@@ -135,8 +136,8 @@ export interface ICell {
outputs: IOutput[];
metadata?: NotebookCellMetadata;
onDidChangeOutputs?: Event<NotebookCellOutputsSplice[]>;
onDidChangeMetadata: Event<NotebookCellMetadata | undefined>;
onDidChangeLanguage: Event<string>;
onDidChangeMetadata: Event<void>;
resolveTextBufferFactory(): PieceTreeTextBufferFactory;
// TODO@rebornix it should be later on replaced by moving textmodel resolution into CellTextModel
contentChange(): void;

View File

@@ -83,4 +83,81 @@ suite('NotebookViewModel', () => {
}
);
});
test('metadata', function () {
withTestNotebook(
instantiationService,
blukEditService,
undoRedoService,
[
[['var a = 1;'], 'javascript', CellKind.Code, [], {}],
[['var b = 2;'], 'javascript', CellKind.Code, [], { editable: true, runnable: true }],
[['var c = 3;'], 'javascript', CellKind.Code, [], { editable: true, runnable: false }],
[['var d = 4;'], 'javascript', CellKind.Code, [], { editable: false, runnable: true }],
[['var e = 5;'], 'javascript', CellKind.Code, [], { editable: false, runnable: false }],
],
(editor, viewModel) => {
viewModel.notebookDocument.metadata = { editable: true, cellRunnable: true, cellEditable: true };
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), {
editable: true,
runnable: true
});
assert.deepEqual(viewModel.viewCells[1].getEvaluatedMetadata(viewModel.metadata), {
editable: true,
runnable: true
});
assert.deepEqual(viewModel.viewCells[2].getEvaluatedMetadata(viewModel.metadata), {
editable: true,
runnable: false
});
assert.deepEqual(viewModel.viewCells[3].getEvaluatedMetadata(viewModel.metadata), {
editable: false,
runnable: true
});
assert.deepEqual(viewModel.viewCells[4].getEvaluatedMetadata(viewModel.metadata), {
editable: false,
runnable: false
});
viewModel.notebookDocument.metadata = { editable: true, cellRunnable: false, cellEditable: true };
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), {
editable: true,
runnable: false
});
assert.deepEqual(viewModel.viewCells[1].getEvaluatedMetadata(viewModel.metadata), {
editable: true,
runnable: true
});
assert.deepEqual(viewModel.viewCells[2].getEvaluatedMetadata(viewModel.metadata), {
editable: true,
runnable: false
});
assert.deepEqual(viewModel.viewCells[3].getEvaluatedMetadata(viewModel.metadata), {
editable: false,
runnable: true
});
assert.deepEqual(viewModel.viewCells[4].getEvaluatedMetadata(viewModel.metadata), {
editable: false,
runnable: false
});
viewModel.notebookDocument.metadata = { editable: true, cellRunnable: false, cellEditable: false };
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), {
editable: false,
runnable: false
});
}
);
});
});

View File

@@ -25,11 +25,10 @@ export class TestCell implements ICell {
uri: URI;
private _onDidChangeOutputs = new Emitter<NotebookCellOutputsSplice[]>();
onDidChangeOutputs: Event<NotebookCellOutputsSplice[]> = this._onDidChangeOutputs.event;
private _onDidChangeMetadata = new Emitter<NotebookCellMetadata>();
onDidChangeMetadata: Event<NotebookCellMetadata> = this._onDidChangeMetadata.event;
private _onDidChangeLanguage = new Emitter<string>();
onDidChangeLanguage: Event<string> = this._onDidChangeLanguage.event;
private _onDidChangeMetadata = new Emitter<void>();
onDidChangeMetadata: Event<void> = this._onDidChangeMetadata.event;
private _isDirty: boolean = false;
private _outputs: IOutput[];

View File

@@ -1,111 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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 { STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND } from 'vs/workbench/common/theme';
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
import { Disposable } from 'vs/base/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchContributionsExtensions } from 'vs/workbench/common/contributions';
import { StatusbarAlignment, IStatusbarService, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { Action } from 'vs/base/common/actions';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IApplicationLink } from 'vs/workbench/workbench.web.api';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { IOpenerService } from 'vs/platform/opener/common/opener';
export class OpenInDesktopIndicator extends Disposable implements IWorkbenchContribution {
constructor(
@IStatusbarService private readonly statusbarService: IStatusbarService,
@IWorkspaceContextService workspaceService: IWorkspaceContextService,
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService
) {
super();
const links = environmentService.options?.applicationLinks;
if (Array.isArray(links) && links?.length > 0) {
this.installOpenInDesktopIndicator(links);
}
}
private installOpenInDesktopIndicator(links: readonly IApplicationLink[]): void {
// Register action to trigger "Open In Desktop"
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenInDesktopAction, OpenInDesktopAction.ID, OpenInDesktopAction.LABEL), 'Open Workspace in Desktop');
// Show in status bar
const properties: IStatusbarEntry = {
backgroundColor: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_BACKGROUND),
color: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_FOREGROUND),
text: links.length === 1 ? links[0].label : localize('openInDesktop', "Open in Desktop..."),
command: 'workbench.web.openWorkspaceInDesktop'
};
this.statusbarService.addEntry(properties, 'status.openInDesktop', properties.text, StatusbarAlignment.LEFT, Number.MAX_VALUE /* first entry */);
}
}
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchContributionsExtensions.Workbench);
workbenchContributionsRegistry.registerWorkbenchContribution(OpenInDesktopIndicator, LifecyclePhase.Starting);
export class OpenInDesktopAction extends Action {
static readonly ID = 'workbench.web.openWorkspaceInDesktop';
static readonly LABEL = localize('openWorkspaceInDesktop', "Open Workspace in Desktop");
constructor(
id: string,
label: string,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IOpenerService private readonly openerService: IOpenerService
) {
super(id, label);
}
async run(): Promise<boolean> {
const links = this.environmentService.options?.applicationLinks;
if (Array.isArray(links)) {
if (links.length === 1) {
return this.openApplicationLink(links[0]);
}
return this.runWithPicker(links);
}
return true;
}
private async runWithPicker(links: readonly IApplicationLink[]): Promise<boolean> {
// Show a picker with choices
const quickPick = this.quickInputService.createQuickPick<IApplicationLink>();
quickPick.items = links;
quickPick.placeholder = OpenInDesktopAction.LABEL;
quickPick.canSelectMany = false;
quickPick.onDidAccept(() => {
const selectedItems = quickPick.selectedItems;
if (selectedItems.length === 1) {
this.openApplicationLink(selectedItems[0]);
}
quickPick.hide();
});
quickPick.show();
return true;
}
private async openApplicationLink(link: IApplicationLink): Promise<boolean> {
this.openerService.open(link.uri, { openExternal: true });
return true;
}
}

View File

@@ -69,6 +69,8 @@ const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewC
Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry).registerViews([{
id: OUTPUT_VIEW_ID,
name: nls.localize('output', "Output"),
containerIcon: 'codicon-output',
canMoveView: true,
canToggleVisibility: false,
ctorDescriptor: new SyncDescriptor(OutputViewPane),
}], VIEW_CONTAINER);

View File

@@ -50,6 +50,7 @@ import { IPreferencesService, ISearchResult, ISettingsEditorModel, ISettingsEdit
import { SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput';
import { Settings2EditorModel } from 'vs/workbench/services/preferences/common/preferencesModels';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
function createGroupIterator(group: SettingsTreeGroupElement): Iterator<ITreeElement<SettingsTreeGroupChild>> {
const groupsIt = Iterator.fromArray(group.children);
@@ -70,6 +71,7 @@ interface IFocusEventFromScroll extends KeyboardEvent {
fromScroll: true;
}
const SETTINGS_AUTOSAVE_NOTIFIED_KEY = 'hasNotifiedOfSettingsAutosave';
const SETTINGS_EDITOR_STATE_KEY = 'settingsEditorState';
export class SettingsEditor2 extends BaseEditor {
@@ -160,7 +162,8 @@ export class SettingsEditor2 extends BaseEditor {
@IStorageService private readonly storageService: IStorageService,
@INotificationService private readonly notificationService: INotificationService,
@IEditorGroupsService protected editorGroupService: IEditorGroupsService,
@IKeybindingService private readonly keybindingService: IKeybindingService
@IKeybindingService private readonly keybindingService: IKeybindingService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService,
) {
super(SettingsEditor2.ID, telemetryService, themeService, storageService);
this.delayedFilterLogging = new Delayer<void>(1000);
@@ -186,6 +189,8 @@ export class SettingsEditor2 extends BaseEditor {
this.onConfigUpdate(e.affectedKeys);
}
}));
storageKeysSyncRegistryService.registerStorageKey({ key: SETTINGS_AUTOSAVE_NOTIFIED_KEY, version: 1 });
}
get minimumWidth(): number { return 375; }
@@ -712,8 +717,8 @@ export class SettingsEditor2 extends BaseEditor {
}
private notifyNoSaveNeeded() {
if (!this.storageService.getBoolean('hasNotifiedOfSettingsAutosave', StorageScope.GLOBAL, false)) {
this.storageService.store('hasNotifiedOfSettingsAutosave', true, StorageScope.GLOBAL);
if (!this.storageService.getBoolean(SETTINGS_AUTOSAVE_NOTIFIED_KEY, StorageScope.GLOBAL, false)) {
this.storageService.store(SETTINGS_AUTOSAVE_NOTIFIED_KEY, true, StorageScope.GLOBAL);
this.notificationService.info(localize('settingsNoSaveNeeded', "Your changes are automatically saved as you edit."));
}
}

View File

@@ -23,6 +23,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { DefaultQuickAccessFilterValue } from 'vs/platform/quickinput/common/quickAccess';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchQuickOpenConfiguration } from 'vs/workbench/browser/quickopen';
import { stripCodicons } from 'vs/base/common/codicons';
export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAccessProvider {
@@ -114,7 +115,7 @@ export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAcce
globalCommandPicks.push({
commandId: action.item.id,
commandAlias,
label
label: stripCodicons(label)
});
}

View File

@@ -4,8 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/anythingQuickAccess';
import { IQuickPickSeparator, IQuickInputButton, IKeyMods, quickPickItemScorerAccessor, QuickPickItemScorerAccessor, IQuickPick } from 'vs/platform/quickinput/common/quickInput';
import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction, FastAndSlowPicksType } from 'vs/platform/quickinput/browser/pickerQuickAccess';
import { IQuickInputButton, IKeyMods, quickPickItemScorerAccessor, QuickPickItemScorerAccessor, IQuickPick } from 'vs/platform/quickinput/common/quickInput';
import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction, FastAndSlowPicks, Picks, PicksWithActive } from 'vs/platform/quickinput/browser/pickerQuickAccess';
import { prepareQuery, IPreparedQuery, compareItemsByScore, scoreItem, ScorerCache } from 'vs/base/common/fuzzyScorer';
import { IFileQueryBuilderOptions, QueryBuilder } from 'vs/workbench/contrib/search/common/queryBuilder';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -88,7 +88,8 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
lastOriginalFilter: string | undefined = undefined;
lastFilter: string | undefined = undefined;
lastRange: IRange | undefined = undefined;
lastActiveGlobalPick: IAnythingQuickPickItem | undefined = undefined;
lastGlobalPicks: PicksWithActive<IAnythingQuickPickItem> | undefined = undefined;
isQuickNavigating: boolean | undefined = undefined;
@@ -116,7 +117,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
this.lastOriginalFilter = undefined;
this.lastFilter = undefined;
this.lastRange = undefined;
this.lastActiveGlobalPick = undefined;
this.lastGlobalPicks = undefined;
this.editorViewState = undefined;
}
@@ -240,7 +241,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
return toDisposable(() => this.clearDecorations(activeEditorControl));
}
protected getPicks(originalFilter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> | FastAndSlowPicksType<IAnythingQuickPickItem> | null {
protected getPicks(originalFilter: string, disposables: DisposableStore, token: CancellationToken): Picks<IAnythingQuickPickItem> | Promise<Picks<IAnythingQuickPickItem>> | FastAndSlowPicks<IAnythingQuickPickItem> | null {
// Find a suitable range from the pattern looking for ":", "#" or ","
// unless we have the `@` editor symbol character inside the filter
@@ -269,16 +270,25 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
this.pickState.lastOriginalFilter = originalFilter;
this.pickState.lastFilter = filter;
// Remember last active pick (unless editor symbol)
// Remember our pick state before returning new picks
// unless an editor symbol is selected. We can use this
// state to return back to the global pick when the
// user is narrowing back out of editor symbols.
const picks = this.pickState.picker?.items;
const activePick = this.pickState.picker?.activeItems[0];
if (activePick && !isEditorSymbolQuickPickItem(activePick)) {
this.pickState.lastActiveGlobalPick = activePick;
if (picks && activePick) {
if (!isEditorSymbolQuickPickItem(activePick)) {
this.pickState.lastGlobalPicks = {
items: picks,
active: activePick
};
}
}
return this.doGetPicks(filter, disposables, token);
}
private doGetPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> | FastAndSlowPicksType<IAnythingQuickPickItem> | null {
private doGetPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Picks<IAnythingQuickPickItem> | Promise<Picks<IAnythingQuickPickItem>> | FastAndSlowPicks<IAnythingQuickPickItem> | null {
const query = prepareQuery(filter);
// Return early if we have editor symbol picks. We support this by:
@@ -289,6 +299,14 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
return editorSymbolPicks;
}
// If we have a known last active editor symbol pick, we try to restore
// the last global pick to support the case of narrowing out from a
// editor symbol search back into the global search
const activePick = this.pickState.picker?.activeItems[0];
if (isEditorSymbolQuickPickItem(activePick) && this.pickState.lastGlobalPicks) {
return this.pickState.lastGlobalPicks;
}
// Otherwise return normally with history and file/symbol results
const historyEditorPicks = this.getEditorHistoryPicks(query);
@@ -304,7 +322,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
],
// Slow picks: files and symbols
additionalPicks: (async (): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> => {
additionalPicks: (async (): Promise<Picks<IAnythingQuickPickItem>> => {
// Exclude any result that is already present in editor history
const additionalPicksExcludes = new ResourceMap<boolean>();
@@ -636,13 +654,13 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
private readonly editorSymbolsQuickAccess = this.instantiationService.createInstance(GotoSymbolQuickAccessProvider);
private getEditorSymbolPicks(query: IPreparedQuery, disposables: DisposableStore, token: CancellationToken): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> | null {
private getEditorSymbolPicks(query: IPreparedQuery, disposables: DisposableStore, token: CancellationToken): Promise<Picks<IAnythingQuickPickItem>> | null {
const filter = query.original.split(GotoSymbolQuickAccessProvider.PREFIX)[1]?.trim();
if (typeof filter !== 'string') {
return null; // we need to be searched for editor symbols via `@`
}
const activeGlobalPick = this.pickState.lastActiveGlobalPick;
const activeGlobalPick = this.pickState.lastGlobalPicks?.active;
if (!activeGlobalPick) {
return null; // we need an active global pick to find symbols for
}
@@ -655,7 +673,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
return this.doGetEditorSymbolPicks(activeGlobalPick, activeGlobalResource, filter, disposables, token);
}
private async doGetEditorSymbolPicks(activeGlobalPick: IAnythingQuickPickItem, activeGlobalResource: URI, filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> {
private async doGetEditorSymbolPicks(activeGlobalPick: IAnythingQuickPickItem, activeGlobalResource: URI, filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Picks<IAnythingQuickPickItem>> {
// Bring the editor to front to review symbols to go to
try {

View File

@@ -390,6 +390,7 @@ Registry.as<panel.PanelRegistry>(panel.Extensions.Panels).setDefaultPanelId(TERM
Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry).registerViews([{
id: TERMINAL_VIEW_ID,
name: nls.localize('terminal', "Terminal"),
containerIcon: 'codicon-terminal',
canToggleVisibility: false,
canMoveView: true,
ctorDescriptor: new SyncDescriptor(TerminalViewPane)
@@ -459,10 +460,7 @@ actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ManageWorkspa
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(RenameTerminalAction, RenameTerminalAction.ID, RenameTerminalAction.LABEL), 'Terminal: Rename', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.KEY_F
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Find Widget', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.KEY_F
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Focus Find Widget', category);
}, ContextKeyExpr.or(KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FOCUS)), 'Terminal: Focus Find Widget', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(HideTerminalFindWidgetAction, HideTerminalFindWidgetAction.ID, HideTerminalFindWidgetAction.LABEL, {
primary: KeyCode.Escape,
secondary: [KeyMod.Shift | KeyCode.Escape]
@@ -550,43 +548,25 @@ actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NavigationMod
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Exit Navigation Mode', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NavigationModeFocusPreviousTerminalAction, NavigationModeFocusPreviousTerminalAction.ID, NavigationModeFocusPreviousTerminalAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.UpArrow
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Previous Line (Navigation Mode)', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NavigationModeFocusPreviousTerminalAction, NavigationModeFocusPreviousTerminalAction.ID, NavigationModeFocusPreviousTerminalAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.UpArrow
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Previous Line (Navigation Mode)', category);
}, ContextKeyExpr.or(ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED), ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED))), 'Terminal: Focus Previous Line (Navigation Mode)', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NavigationModeFocusNextTerminalAction, NavigationModeFocusNextTerminalAction.ID, NavigationModeFocusNextTerminalAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.DownArrow
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Next Line (Navigation Mode)', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NavigationModeFocusNextTerminalAction, NavigationModeFocusNextTerminalAction.ID, NavigationModeFocusNextTerminalAction.LABEL, {
primary: KeyMod.CtrlCmd | KeyCode.DownArrow
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Next Line (Navigation Mode)', category);
}, ContextKeyExpr.or(ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED), ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED))), 'Terminal: Focus Next Line (Navigation Mode)', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SelectToPreviousLineAction, SelectToPreviousLineAction.ID, SelectToPreviousLineAction.LABEL), 'Terminal: Select To Previous Line', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SelectToNextLineAction, SelectToNextLineAction.ID, SelectToNextLineAction.LABEL), 'Terminal: Select To Next Line', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleEscapeSequenceLoggingAction, ToggleEscapeSequenceLoggingAction.ID, ToggleEscapeSequenceLoggingAction.LABEL), 'Terminal: Toggle Escape Sequence Logging', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleRegexCommand, ToggleRegexCommand.ID, ToggleRegexCommand.LABEL, {
primary: KeyMod.Alt | KeyCode.KEY_R,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R }
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using regex', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleRegexCommand, ToggleRegexCommand.ID, ToggleRegexCommand.LABEL, {
primary: KeyMod.Alt | KeyCode.KEY_R,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R }
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find using regex', category);
}, ContextKeyExpr.or(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED)), 'Terminal: Toggle find using regex', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleWholeWordCommand, ToggleWholeWordCommand.ID, ToggleWholeWordCommand.LABEL, {
primary: KeyMod.Alt | KeyCode.KEY_W,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W }
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using whole word', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleWholeWordCommand, ToggleWholeWordCommand.ID, ToggleWholeWordCommand.LABEL, {
primary: KeyMod.Alt | KeyCode.KEY_W,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W }
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find using whole word', category);
}, ContextKeyExpr.or(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED)), 'Terminal: Toggle find using whole word', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID, ToggleCaseSensitiveCommand.LABEL, {
primary: KeyMod.Alt | KeyCode.KEY_C,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C }
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using case sensitive', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID, ToggleCaseSensitiveCommand.LABEL, {
primary: KeyMod.Alt | KeyCode.KEY_C,
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C }
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find using case sensitive', category);
}, ContextKeyExpr.or(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED)), 'Terminal: Toggle find using case sensitive', category);
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FindNext, FindNext.ID, FindNext.LABEL, {
primary: KeyCode.F3,
mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, secondary: [KeyCode.F3] }

View File

@@ -776,12 +776,14 @@ export class TimelinePane extends ViewPane {
// Refresh the view on focus to update the relative timestamps
this.onDidFocus(() => this.refreshDebounced(), this, this.visibilityDisposables);
super.setVisible(visible);
this.onActiveEditorChanged();
} else {
this.visibilityDisposables?.dispose();
}
super.setVisible(visible);
super.setVisible(visible);
}
}
protected layoutBody(height: number, width: number): void {

View File

@@ -53,6 +53,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { timeout } from 'vs/base/common/async';
import { distinct } from 'vs/base/common/arrays';
const enum AuthStatus {
Initializing = 'Initializing',
@@ -98,19 +99,19 @@ const getActivityTitle = (label: string, userDataSyncService: IUserDataSyncServi
const getIdentityTitle = (label: string, authenticationProviderId: string, account: AuthenticationSession | undefined, authenticationService: IAuthenticationService): string => {
return account ? `${label} (${authenticationService.getDisplayName(authenticationProviderId)}:${account.accountName})` : label;
};
const turnOnSyncCommand = { id: 'workbench.userData.actions.syncStart', title: localize('turn on sync with category', "Sync: Turn on Sync") };
const signInCommand = { id: 'workbench.userData.actions.signin', title: localize('sign in', "Sync: Sign in to sync") };
const stopSyncCommand = { id: 'workbench.userData.actions.stopSync', title(authenticationProviderId: string, account: AuthenticationSession | undefined, authenticationService: IAuthenticationService) { return getIdentityTitle(localize('stop sync', "Sync: Turn off Sync"), authenticationProviderId, account, authenticationService); } };
const resolveSettingsConflictsCommand = { id: 'workbench.userData.actions.resolveSettingsConflicts', title: localize('showConflicts', "Sync: Show Settings Conflicts") };
const resolveKeybindingsConflictsCommand = { id: 'workbench.userData.actions.resolveKeybindingsConflicts', title: localize('showKeybindingsConflicts', "Sync: Show Keybindings Conflicts") };
const resolveSnippetsConflictsCommand = { id: 'workbench.userData.actions.resolveSnippetsConflicts', title: localize('showSnippetsConflicts', "Sync: Show User Snippets Conflicts") };
const configureSyncCommand = { id: 'workbench.userData.actions.configureSync', title: localize('configure sync', "Sync: Configure") };
const turnOnSyncCommand = { id: 'workbench.userData.actions.syncStart', title: localize('turn on sync with category', "Preferences Sync: Turn on...") };
const signInCommand = { id: 'workbench.userData.actions.signin', title: localize('sign in', "Preferences Sync: Sign in to sync") };
const stopSyncCommand = { id: 'workbench.userData.actions.stopSync', title(authenticationProviderId: string, account: AuthenticationSession | undefined, authenticationService: IAuthenticationService) { return getIdentityTitle(localize('stop sync', "Preferences Sync: Turn off"), authenticationProviderId, account, authenticationService); } };
const resolveSettingsConflictsCommand = { id: 'workbench.userData.actions.resolveSettingsConflicts', title: localize('showConflicts', "Preferences Sync: Show Settings Conflicts") };
const resolveKeybindingsConflictsCommand = { id: 'workbench.userData.actions.resolveKeybindingsConflicts', title: localize('showKeybindingsConflicts', "Preferences Sync: Show Keybindings Conflicts") };
const resolveSnippetsConflictsCommand = { id: 'workbench.userData.actions.resolveSnippetsConflicts', title: localize('showSnippetsConflicts', "Preferences Sync: Show User Snippets Conflicts") };
const configureSyncCommand = { id: 'workbench.userData.actions.configureSync', title: localize('configure sync', "Preferences Sync: Configure...") };
const showSyncActivityCommand = {
id: 'workbench.userData.actions.showSyncActivity', title(userDataSyncService: IUserDataSyncService): string {
return getActivityTitle(localize('show sync log', "Sync: Show Log"), userDataSyncService);
return getActivityTitle(localize('show sync log', "Preferences Sync: Show Log"), userDataSyncService);
}
};
const showSyncSettingsCommand = { id: 'workbench.userData.actions.syncSettings', title: localize('sync settings', "Sync: Settings"), };
const showSyncSettingsCommand = { id: 'workbench.userData.actions.syncSettings', title: localize('sync settings', "Preferences Sync: Show Settings"), };
export class UserDataSyncWorkbenchContribution extends Disposable implements IWorkbenchContribution {
@@ -249,9 +250,10 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
private async showSwitchAccountPicker(sessions: readonly AuthenticationSession[]): Promise<void> {
return new Promise((resolve, _) => {
const quickPick = this.quickInputService.createQuickPick<{ label: string, session: AuthenticationSession }>();
quickPick.title = localize('chooseAccountTitle', "Sync: Choose Account");
quickPick.title = localize('chooseAccountTitle', "Preferences Sync: Choose Account");
quickPick.placeholder = localize('chooseAccount', "Choose an account you would like to use for settings sync");
quickPick.items = sessions.map(session => {
const dedupedSessions = distinct(sessions, (session) => session.accountName);
quickPick.items = dedupedSessions.map(session => {
return {
label: session.accountName,
session: session
@@ -577,7 +579,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
if (this.userDataSyncService.status !== SyncStatus.Uninitialized && this.userDataSyncEnablementService.isEnabled() && this.authenticationState.get() === AuthStatus.SignedOut) {
badge = new NumberBadge(1, () => localize('sign in to sync', "Sign in to Sync"));
} else if (this.userDataSyncService.conflicts.length) {
badge = new NumberBadge(this.userDataSyncService.conflicts.reduce((result, syncResourceConflict) => { return result + syncResourceConflict.conflicts.length; }, 0), () => localize('has conflicts', "Sync: Conflicts Detected"));
badge = new NumberBadge(this.userDataSyncService.conflicts.reduce((result, syncResourceConflict) => { return result + syncResourceConflict.conflicts.length; }, 0), () => localize('has conflicts', "Preferences Sync: Conflicts Detected"));
}
if (badge) {
@@ -608,7 +610,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
const disposables: DisposableStore = new DisposableStore();
const quickPick = this.quickInputService.createQuickPick<ConfigureSyncQuickPickItem>();
disposables.add(quickPick);
quickPick.title = localize('turn on title', "Sync: Turn On");
quickPick.title = localize('turn on title', "Preferences Sync: Turn On");
quickPick.ok = false;
quickPick.customButton = true;
if (this.authenticationState.get() === AuthStatus.SignedIn) {
@@ -713,7 +715,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
const disposables: DisposableStore = new DisposableStore();
const quickPick = this.quickInputService.createQuickPick<ConfigureSyncQuickPickItem>();
disposables.add(quickPick);
quickPick.title = localize('turn on sync', "Turn on Sync");
quickPick.title = localize('configure sync', "Preferences Sync: Configure...");
quickPick.placeholder = localize('configure sync placeholder', "Choose what to sync");
quickPick.canSelectMany = true;
quickPick.ignoreFocusOut = true;
@@ -888,7 +890,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
group: '5_sync',
command: {
id: turnOnSyncCommand.id,
title: localize('global activity turn on sync', "Turn on Sync...")
title: localize('global activity turn on sync', "Preferences Sync: Turn on...")
},
when: turnOnSyncWhenContext,
order: 1
@@ -901,7 +903,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
group: '5_sync',
command: {
id: turnOnSyncCommand.id,
title: localize('global activity turn on sync', "Turn on Sync...")
title: localize('global activity turn on sync', "Preferences Sync: Turn on...")
},
when: turnOnSyncWhenContext,
});
@@ -913,7 +915,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
constructor() {
super({
id: signInCommand.id,
title: localize('sign in 2', "Sync: Sign in to sync (1)"),
title: localize('sign in 2', "Preferences Sync: Sign in to sync (1)"),
menu: {
group: '5_sync',
id: MenuId.GlobalActivity,
@@ -939,7 +941,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
group: '5_sync',
command: {
id: resolveSettingsConflictsCommand.id,
title: localize('resolveConflicts_global', "Sync: Show Settings Conflicts (1)"),
title: localize('resolveConflicts_global', "Preferences Sync: Show Settings Conflicts (1)"),
},
when: resolveSettingsConflictsWhenContext,
order: 2
@@ -948,7 +950,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
group: '5_sync',
command: {
id: resolveSettingsConflictsCommand.id,
title: localize('resolveConflicts_global', "Sync: Show Settings Conflicts (1)"),
title: localize('resolveConflicts_global', "Preferences Sync: Show Settings Conflicts (1)"),
},
when: resolveSettingsConflictsWhenContext,
order: 2
@@ -966,7 +968,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
group: '5_sync',
command: {
id: resolveKeybindingsConflictsCommand.id,
title: localize('resolveKeybindingsConflicts_global', "Sync: Show Keybindings Conflicts (1)"),
title: localize('resolveKeybindingsConflicts_global', "Preferences Sync: Show Keybindings Conflicts (1)"),
},
when: resolveKeybindingsConflictsWhenContext,
order: 2
@@ -975,7 +977,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
group: '5_sync',
command: {
id: resolveKeybindingsConflictsCommand.id,
title: localize('resolveKeybindingsConflicts_global', "Sync: Show Keybindings Conflicts (1)"),
title: localize('resolveKeybindingsConflicts_global', "Preferences Sync: Show Keybindings Conflicts (1)"),
},
when: resolveKeybindingsConflictsWhenContext,
order: 2
@@ -996,7 +998,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
group: '5_sync',
command: {
id: resolveSnippetsConflictsCommand.id,
title: localize('resolveSnippetsConflicts_global', "Sync: Show User Snippets Conflicts ({0})", conflicts?.length || 1),
title: localize('resolveSnippetsConflicts_global', "Preferences Sync: Show User Snippets Conflicts ({0})", conflicts?.length || 1),
},
when: resolveSnippetsConflictsWhenContext,
order: 2
@@ -1005,7 +1007,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
group: '5_sync',
command: {
id: resolveSnippetsConflictsCommand.id,
title: localize('resolveSnippetsConflicts_global', "Sync: Show User Snippets Conflicts ({0})", conflicts?.length || 1),
title: localize('resolveSnippetsConflicts_global', "Preferences Sync: Show User Snippets Conflicts ({0})", conflicts?.length || 1),
},
when: resolveSnippetsConflictsWhenContext,
order: 2
@@ -1023,7 +1025,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
constructor() {
super({
id: 'workbench.userData.actions.syncStatus',
title: localize('sync is on', "Sync is on"),
title: localize('sync is on', "Preferences Sync: On"),
menu: [
{
id: MenuId.GlobalActivity,
@@ -1262,8 +1264,8 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
const result = await this.dialogService.confirm({
type: 'info',
title: isRemote
? localize('Sync accept remote', "Sync: {0}", acceptRemoteLabel)
: localize('Sync accept local', "Sync: {0}", acceptLocalLabel),
? localize('Sync accept remote', "Preferences Sync: {0}", acceptRemoteLabel)
: localize('Sync accept local', "Preferences Sync: {0}", acceptLocalLabel),
message: isRemote
? localize('confirm replace and overwrite local', "Would you like to accept remote {0} and replace local {1}?", syncAreaLabel.toLowerCase(), syncAreaLabel.toLowerCase())
: localize('confirm replace and overwrite remote', "Would you like to accept local {0} and replace remote {1}?", syncAreaLabel.toLowerCase(), syncAreaLabel.toLowerCase()),

View File

@@ -36,7 +36,7 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
return Registry.as<IViewContainersRegistry>(Extensions.ViewContainersRegistry).registerViewContainer(
{
id: 'workbench.view.sync',
name: localize('sync', "Sync"),
name: localize('sync preferences', "Preferences Sync"),
ctorDescriptor: new SyncDescriptor(
ViewPaneContainer,
['workbench.view.sync', `workbench.view.sync.state`, { mergeViewWithContainerWhenSingleView: true }]
@@ -80,7 +80,7 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
title: remote ?
{ value: localize('workbench.action.showSyncRemoteBackup', "Show Remote Backup"), original: `Show Remote Backup` }
: { value: localize('workbench.action.showSyncLocalBackup', "Show Local Backup"), original: `Show Local Backup` },
category: { value: localize('sync', "Sync"), original: `Sync` },
category: { value: localize('sync preferences', "Preferences Sync"), original: `Preferences Sync` },
menu: {
id: MenuId.CommandPalette,
when: CONTEXT_SYNC_ENABLEMENT

View File

@@ -33,7 +33,8 @@ registerAction2(class OpenSyncBackupsFolder extends Action2 {
constructor() {
super({
id: 'workbench.userData.actions.openSyncBackupsFolder',
title: localize('Open Backup folder', "Sync: Open Local Backups Folder"),
title: { value: localize('Open Backup folder', "Open Local Backups Folder"), original: 'Open Local Backups Folder' },
category: { value: localize('sync preferences', "Preferences Sync"), original: `Preferences Sync` },
menu: {
id: MenuId.CommandPalette,
when: CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized),

View File

@@ -233,11 +233,10 @@ export class ElectronWebviewBasedWebview extends BaseWebview<WebviewTag> impleme
const webviewAndContents = this._register(new WebviewTagHandle(this.element!));
const session = this._register(new WebviewSession(webviewAndContents));
this._protocolProvider = new WebviewProtocolProvider
(webviewAndContents,
() => this.extension ? this.extension.location : undefined,
() => (this.content.options.localResourceRoots || []),
fileService);
this._protocolProvider = new WebviewProtocolProvider(webviewAndContents,
() => this.extension?.location,
() => (this.content.options.localResourceRoots || []),
fileService);
this._register(this._protocolProvider);
this._register(new WebviewPortMappingProvider(

View File

@@ -8,7 +8,7 @@ import { localize } from 'vs/nls';
export default () => `
<div class="welcomePageContainer">
<div class="welcomePage">
<div class="welcomePage" role="document">
<div class="title">
<h1 class="caption">${escape(localize('welcomePage.vscode', "Visual Studio Code"))}</h1>
<p class="subtitle detail">${escape(localize({ key: 'welcomePage.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))}</p>