Merge from vscode 313ede61cbad8f9dc748907b3384e059ddddb79a (#7436)

* Merge from vscode 313ede61cbad8f9dc748907b3384e059ddddb79a

* fix strict null checks
This commit is contained in:
Anthony Dresser
2019-09-30 23:35:45 -07:00
committed by GitHub
parent 6ab03053a0
commit 084524cd2d
196 changed files with 2927 additions and 2547 deletions

View File

@@ -3,7 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Schemas } from 'vs/base/common/network';
// import { Schemas } from 'vs/base/common/network';
import { firstOrDefault } from 'vs/base/common/arrays';
import { URI } from 'vs/base/common/uri';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import * as nls from 'vs/nls';
@@ -12,19 +13,18 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IListService } from 'vs/platform/list/browser/listService';
import { IEditorCommandsContext } from 'vs/workbench/common/editor';
import { ResourceContextKey } from 'vs/workbench/common/resources';
// import { ResourceContextKey } from 'vs/workbench/common/resources';
import { ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { firstOrDefault } from 'vs/base/common/arrays';
const viewCategory = nls.localize('viewCategory', "View");
// #region Open With
const OPEN_WITH_COMMAND_ID = 'openWith';
const OPEN_WITH_TITLE = { value: nls.localize('openWith.title', 'Open With'), original: 'Open With' };
// const OPEN_WITH_TITLE = { value: nls.localize('openWith.title', 'Open With'), original: 'Open With' };
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: OPEN_WITH_COMMAND_ID,
@@ -41,15 +41,15 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
}
});
MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
group: 'navigation',
order: 20,
command: {
id: OPEN_WITH_COMMAND_ID,
title: OPEN_WITH_TITLE,
},
when: ResourceContextKey.Scheme.isEqualTo(Schemas.file)
});
// MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
// group: 'navigation',
// order: 20,
// command: {
// id: OPEN_WITH_COMMAND_ID,
// title: OPEN_WITH_TITLE,
// },
// when: ResourceContextKey.Scheme.isEqualTo(Schemas.file)
// });
// #endregion

View File

@@ -33,7 +33,7 @@ const defaultEditorId = 'default';
const defaultEditorInfo: CustomEditorInfo = {
id: defaultEditorId,
displayName: nls.localize('promptOpenWith.defaultEditor', "Default built-in editor"),
displayName: nls.localize('promptOpenWith.defaultEditor', "VS Code's standard text editor"),
selector: [
{ filenamePattern: '*' }
],

View File

@@ -445,7 +445,8 @@
background: url('add-dark.svg') center center no-repeat;
}
.hc-black .debug-viewlet .debug-action.add-watch-expression {
.hc-black .debug-viewlet .debug-action.add-watch-expression,
.hc-black .debug-viewlet .debug-action.add-function-breakpoint {
background: url('add-hc.svg') center center no-repeat;
}

View File

@@ -527,9 +527,26 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
return false;
}
const installed = await this.extensionManagementService.getInstalled(ExtensionType.User);
let recommendationsToSuggest = Object.keys(this._importantExeBasedRecommendations);
recommendationsToSuggest = this.filterAllIgnoredInstalledAndNotAllowed(recommendationsToSuggest, installed);
const installed = await this.extensionManagementService.getInstalled(ExtensionType.User);
recommendationsToSuggest = this.filterInstalled(recommendationsToSuggest, installed, (extensionId) => {
const tip = this._importantExeBasedRecommendations[extensionId];
/* __GDPR__
exeExtensionRecommendations:alreadyInstalled" : {
"extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"exeName": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('exeExtensionRecommendations:alreadyInstalled', { extensionId, exeName: tip.exeFriendlyName || basename(tip.windowsPath!) });
});
if (recommendationsToSuggest.length === 0) {
return false;
}
recommendationsToSuggest = this.filterIgnoredOrNotAllowed(recommendationsToSuggest);
if (recommendationsToSuggest.length === 0) {
return false;
}
@@ -763,7 +780,12 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
private async promptRecommendedExtensionForFileType(recommendationsToSuggest: string[], installed: ILocalExtension[]): Promise<boolean> {
recommendationsToSuggest = this.filterAllIgnoredInstalledAndNotAllowed(recommendationsToSuggest, installed);
recommendationsToSuggest = this.filterIgnoredOrNotAllowed(recommendationsToSuggest);
if (recommendationsToSuggest.length === 0) {
return false;
}
recommendationsToSuggest = this.filterInstalled(recommendationsToSuggest, installed);
if (recommendationsToSuggest.length === 0) {
return false;
}
@@ -919,10 +941,8 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
);
}
private filterAllIgnoredInstalledAndNotAllowed(recommendationsToSuggest: string[], installed: ILocalExtension[]): string[] {
private filterIgnoredOrNotAllowed(recommendationsToSuggest: string[]): string[] {
const importantRecommendationsIgnoreList = <string[]>JSON.parse(this.storageService.get('extensionsAssistant/importantRecommendationsIgnore', StorageScope.GLOBAL, '[]'));
const installedExtensionsIds = installed.reduce((result, i) => { result.add(i.identifier.id.toLowerCase()); return result; }, new Set<string>());
return recommendationsToSuggest.filter(id => {
if (importantRecommendationsIgnoreList.indexOf(id) !== -1) {
return false;
@@ -930,7 +950,17 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
if (!this.isExtensionAllowedToBeRecommended(id)) {
return false;
}
return true;
});
}
private filterInstalled(recommendationsToSuggest: string[], installed: ILocalExtension[], onAlreadyInstalled?: (id: string) => void): string[] {
const installedExtensionsIds = installed.reduce((result, i) => { result.add(i.identifier.id.toLowerCase()); return result; }, new Set<string>());
return recommendationsToSuggest.filter(id => {
if (installedExtensionsIds.has(id.toLowerCase())) {
if (onAlreadyInstalled) {
onAlreadyInstalled(id);
}
return false;
}
return true;

View File

@@ -20,7 +20,7 @@ import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/brow
import {
OpenExtensionsViewletAction, InstallExtensionsAction, ShowOutdatedExtensionsAction, ShowRecommendedExtensionsAction, ShowRecommendedKeymapExtensionsAction, ShowPopularExtensionsAction,
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowDisabledExtensionsAction, ShowBuiltInExtensionsAction, UpdateAllAction,
EnableAllAction, EnableAllWorkpsaceAction, DisableAllAction, DisableAllWorkpsaceAction, CheckForUpdatesAction, ShowLanguageExtensionsAction, ShowAzureExtensionsAction, EnableAutoUpdateAction, DisableAutoUpdateAction, ConfigureRecommendedExtensionsCommandsContributor, InstallVSIXAction, ReinstallAction, InstallSpecificVersionOfExtensionAction
EnableAllAction, EnableAllWorkspaceAction, DisableAllAction, DisableAllWorkspaceAction, CheckForUpdatesAction, ShowLanguageExtensionsAction, ShowAzureExtensionsAction, EnableAutoUpdateAction, DisableAutoUpdateAction, ConfigureRecommendedExtensionsCommandsContributor, InstallVSIXAction, ReinstallAction, InstallSpecificVersionOfExtensionAction
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
@@ -137,13 +137,13 @@ actionRegistry.registerWorkbenchAction(installVSIXActionDescriptor, 'Extensions:
const disableAllAction = new SyncActionDescriptor(DisableAllAction, DisableAllAction.ID, DisableAllAction.LABEL);
actionRegistry.registerWorkbenchAction(disableAllAction, 'Extensions: Disable All Installed Extensions', ExtensionsLabel);
const disableAllWorkspaceAction = new SyncActionDescriptor(DisableAllWorkpsaceAction, DisableAllWorkpsaceAction.ID, DisableAllWorkpsaceAction.LABEL);
const disableAllWorkspaceAction = new SyncActionDescriptor(DisableAllWorkspaceAction, DisableAllWorkspaceAction.ID, DisableAllWorkspaceAction.LABEL);
actionRegistry.registerWorkbenchAction(disableAllWorkspaceAction, 'Extensions: Disable All Installed Extensions for this Workspace', ExtensionsLabel);
const enableAllAction = new SyncActionDescriptor(EnableAllAction, EnableAllAction.ID, EnableAllAction.LABEL);
actionRegistry.registerWorkbenchAction(enableAllAction, 'Extensions: Enable All Extensions', ExtensionsLabel);
const enableAllWorkspaceAction = new SyncActionDescriptor(EnableAllWorkpsaceAction, EnableAllWorkpsaceAction.ID, EnableAllWorkpsaceAction.LABEL);
const enableAllWorkspaceAction = new SyncActionDescriptor(EnableAllWorkspaceAction, EnableAllWorkspaceAction.ID, EnableAllWorkspaceAction.LABEL);
actionRegistry.registerWorkbenchAction(enableAllWorkspaceAction, 'Extensions: Enable All Extensions for this Workspace', ExtensionsLabel);
const checkForUpdatesAction = new SyncActionDescriptor(CheckForUpdatesAction, CheckForUpdatesAction.ID, CheckForUpdatesAction.LABEL);

View File

@@ -2707,14 +2707,14 @@ export class DisableAllAction extends Action {
}
}
export class DisableAllWorkpsaceAction extends Action {
export class DisableAllWorkspaceAction extends Action {
static readonly ID = 'workbench.extensions.action.disableAllWorkspace';
static LABEL = localize('disableAllWorkspace', "Disable All Installed Extensions for this Workspace");
constructor(
id: string = DisableAllWorkpsaceAction.ID, label: string = DisableAllWorkpsaceAction.LABEL,
id: string = DisableAllWorkspaceAction.ID, label: string = DisableAllWorkspaceAction.LABEL,
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService
@@ -2759,14 +2759,14 @@ export class EnableAllAction extends Action {
}
}
export class EnableAllWorkpsaceAction extends Action {
export class EnableAllWorkspaceAction extends Action {
static readonly ID = 'workbench.extensions.action.enableAllWorkspace';
static LABEL = localize('enableAllWorkspace', "Enable All Extensions for this Workspace");
constructor(
id: string = EnableAllWorkpsaceAction.ID, label: string = EnableAllWorkpsaceAction.LABEL,
id: string = EnableAllWorkspaceAction.ID, label: string = EnableAllWorkspaceAction.LABEL,
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService

View File

@@ -698,28 +698,28 @@ export class ExtensionsListView extends ViewletPanel {
// {{SQL CARBON EDIT}} - End
// Given all recommendations, trims and returns recommendations in the relevant order after filtering out installed extensions
private getTrimmedRecommendations(installedExtensions: IExtension[], value: string, fileBasedRecommendations: IExtensionRecommendation[], otherRecommendations: IExtensionRecommendation[], workpsaceRecommendations: IExtensionRecommendation[]): string[] {
private getTrimmedRecommendations(installedExtensions: IExtension[], value: string, fileBasedRecommendations: IExtensionRecommendation[], otherRecommendations: IExtensionRecommendation[], workspaceRecommendations: IExtensionRecommendation[]): string[] {
const totalCount = 8;
workpsaceRecommendations = workpsaceRecommendations
workspaceRecommendations = workspaceRecommendations
.filter(recommendation => {
return !this.isRecommendationInstalled(recommendation, installedExtensions)
&& recommendation.extensionId.toLowerCase().indexOf(value) > -1;
});
fileBasedRecommendations = fileBasedRecommendations.filter(recommendation => {
return !this.isRecommendationInstalled(recommendation, installedExtensions)
&& workpsaceRecommendations.every(workspaceRecommendation => workspaceRecommendation.extensionId !== recommendation.extensionId)
&& workspaceRecommendations.every(workspaceRecommendation => workspaceRecommendation.extensionId !== recommendation.extensionId)
&& recommendation.extensionId.toLowerCase().indexOf(value) > -1;
});
otherRecommendations = otherRecommendations.filter(recommendation => {
return !this.isRecommendationInstalled(recommendation, installedExtensions)
&& fileBasedRecommendations.every(fileBasedRecommendation => fileBasedRecommendation.extensionId !== recommendation.extensionId)
&& workpsaceRecommendations.every(workspaceRecommendation => workspaceRecommendation.extensionId !== recommendation.extensionId)
&& workspaceRecommendations.every(workspaceRecommendation => workspaceRecommendation.extensionId !== recommendation.extensionId)
&& recommendation.extensionId.toLowerCase().indexOf(value) > -1;
});
const otherCount = Math.min(2, otherRecommendations.length);
const fileBasedCount = Math.min(fileBasedRecommendations.length, totalCount - workpsaceRecommendations.length - otherCount);
const recommendations = workpsaceRecommendations;
const fileBasedCount = Math.min(fileBasedRecommendations.length, totalCount - workspaceRecommendations.length - otherCount);
const recommendations = workspaceRecommendations;
recommendations.push(...fileBasedRecommendations.splice(0, fileBasedCount));
recommendations.push(...otherRecommendations.splice(0, otherCount));

View File

@@ -54,6 +54,10 @@
flex: 1;
}
.extensions-viewlet > .extensions .panel-header > .actions.show {
flex: inherit;
}
.extensions-viewlet > .extensions .message-container {
padding: 5px 9px 5px 16px;
cursor: default;

View File

@@ -134,7 +134,7 @@ class ReportExtensionSlowAction extends Action {
// build issue
const title = encodeURIComponent('Extension causes high cpu load');
const osVersion = `${os.type()} ${os.arch()} ${os.release()}`;
const message = `:warning: Make sure to **attach** this file from your *home*-directory:\n:warning:\`${path}\`\n\nFind more details here: https://github.com/Microsoft/vscode/wiki/Explain:-extension-causes-high-cpu-load`;
const message = `:warning: Make sure to **attach** this file from your *home*-directory:\n:warning:\`${path}\`\n\nFind more details here: https://github.com/microsoft/vscode/wiki/Explain-extension-causes-high-cpu-load`;
const body = encodeURIComponent(`- Issue Type: \`Performance\`
- Extension Name: \`${this.extension.name}\`
- Extension Version: \`${this.extension.version}\`

View File

@@ -636,7 +636,7 @@ export class SaveExtensionHostProfileAction extends Action {
}]
});
if (!picked || !picked.filePath || picked.canceled) {
if (!picked || !picked.filePath) {
return;
}

View File

@@ -764,7 +764,7 @@ export class ShowOpenedFileInNewWindow extends Action {
const fileResource = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.MASTER });
if (fileResource) {
if (this.fileService.canHandleResource(fileResource)) {
this.hostService.openInWindow([{ fileUri: fileResource }], { forceNewWindow: true });
this.hostService.openWindow([{ fileUri: fileResource }], { forceNewWindow: true });
} else {
this.notificationService.info(nls.localize('openFileToShowInNewWindow.unsupportedschema', "The active editor must contain an openable resource."));
}

View File

@@ -6,7 +6,7 @@
import * as nls from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import { toResource, IEditorCommandsContext, SideBySideEditor, EditorInput } from 'vs/workbench/common/editor'; // {{SQL CARBON EDIT}} add edit input
import { IWindowOpenable, IOpenInWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
import { IWindowOpenable, IOpenWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
@@ -81,7 +81,7 @@ export const ResourceSelectedForCompareContext = new RawContextKey<boolean>('res
export const REMOVE_ROOT_FOLDER_COMMAND_ID = 'removeRootFolder';
export const REMOVE_ROOT_FOLDER_LABEL = nls.localize('removeFolderFromWorkspace', "Remove Folder from Workspace");
export const openWindowCommand = (accessor: ServicesAccessor, toOpen: IWindowOpenable[], options?: IOpenInWindowOptions) => {
export const openWindowCommand = (accessor: ServicesAccessor, toOpen: IWindowOpenable[], options?: IOpenWindowOptions) => {
if (Array.isArray(toOpen)) {
const hostService = accessor.get(IHostService);
const environmentService = accessor.get(IEnvironmentService);
@@ -97,13 +97,13 @@ export const openWindowCommand = (accessor: ServicesAccessor, toOpen: IWindowOpe
return openable;
});
hostService.openInWindow(toOpen, options);
hostService.openWindow(toOpen, options);
}
};
export const newWindowCommand = (accessor: ServicesAccessor, options?: IOpenEmptyWindowOptions) => {
const hostService = accessor.get(IHostService);
hostService.openEmptyWindow(options);
hostService.openWindow(options);
};
// {{SQL CARBON EDIT}}

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 9H4V10H9V9Z" fill="#C5C5C5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3L6 2H13L14 3V10L13 11H11V13L10 14H3L2 13V6L3 5H5V3ZM6 5H10L11 6V10H13V3H6V5ZM10 6H3V13H10V6Z" fill="#C5C5C5"/>
</svg>

After

Width:  |  Height:  |  Size: 309 B

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 9H4V10H9V9Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3L6 2H13L14 3V10L13 11H11V13L10 14H3L2 13V6L3 5H5V3ZM6 5H10L11 6V10H13V3H6V5ZM10 6H3V13H10V6Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 305 B

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 9H4V10H9V9Z" fill="#424242"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 3L6 2H13L14 3V10L13 11H11V13L10 14H3L2 13V6L3 5H5V3ZM6 5H10L11 6V10H13V3H6V5ZM10 6H3V13H10V6Z" fill="#424242"/>
</svg>

After

Width:  |  Height:  |  Size: 309 B

View File

@@ -163,3 +163,16 @@
.hc-black .monaco-workbench .explorer-viewlet .editor-group {
line-height: 20px;
}
/* TODO @misolori convert these to use icon font, for the debug viewlet */
.monaco-workbench .explorer-action.collapse-explorer {
background: url("collapse-all-light.svg") 50% no-repeat;
}
.vs-dark .monaco-workbench .explorer-action.collapse-explorer {
background: url("collapse-all-dark.svg") 50% no-repeat;
}
.hc-black .monaco-workbench .explorer-action.collapse-explorer {
background: url("collapse-all-hc.svg") 50% no-repeat;
}

View File

@@ -54,6 +54,10 @@ export class EmptyView extends ViewletPanel {
}
renderHeader(container: HTMLElement): void {
const twisties = document.createElement('div');
DOM.addClasses(twisties, 'twisties', 'codicon', 'codicon-chevron-right');
container.appendChild(twisties);
const titleContainer = document.createElement('div');
DOM.addClass(titleContainer, 'title');
container.appendChild(titleContainer);

View File

@@ -117,7 +117,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
this.rangeHighlightDecorations = this._register(this.instantiationService.createInstance(RangeHighlightDecorations));
// actions
this.collapseAllAction = this._register(new Action('vs.tree.collapse', localize('collapseAll', "Collapse All"), 'monaco-tree-action collapse-all', true, async () => this.collapseAll()));
this.collapseAllAction = this._register(new Action('vs.tree.collapse', localize('collapseAll', "Collapse All"), 'monaco-tree-action codicon-collapse-all', true, async () => this.collapseAll()));
this.filterAction = this._register(this.instantiationService.createInstance(MarkersFilterAction, { filterText: this.panelState['filter'] || '', filterHistory: this.panelState['filterHistory'] || [], useFilesExclude: !!this.panelState['useFilesExclude'] }));
}
@@ -341,11 +341,6 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
markerFocusContextKey.set(focus.elements.some(e => e instanceof Marker));
relatedInformationFocusContextKey.set(focus.elements.some(e => e instanceof RelatedInformation));
}));
const focusTracker = this._register(dom.trackFocus(this.tree.getHTMLElement()));
this._register(focusTracker.onDidBlur(() => {
markerFocusContextKey.set(false);
relatedInformationFocusContextKey.set(false);
}));
const markersNavigator = this._register(new TreeResourceNavigator2(this.tree, { openOnFocus: true }));
this._register(Event.debounce(markersNavigator.onDidOpenResource, (last, event) => event, 75, true)(options => {

View File

@@ -21,7 +21,6 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { didUseCachedData, ITimerService } from 'vs/workbench/services/timer/electron-browser/timerService';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { getEntries } from 'vs/base/common/performance';
import { IHostService } from 'vs/workbench/services/host/browser/host';
export class StartupTimings implements IWorkbenchContribution {
@@ -34,8 +33,7 @@ export class StartupTimings implements IWorkbenchContribution {
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@ILifecycleService private readonly _lifecycleService: ILifecycleService,
@IUpdateService private readonly _updateService: IUpdateService,
@IEnvironmentService private readonly _envService: IEnvironmentService,
@IHostService private readonly _hostService: IHostService
@IEnvironmentService private readonly _envService: IEnvironmentService
) {
//
this._report().catch(onUnexpectedError);
@@ -93,7 +91,7 @@ export class StartupTimings implements IWorkbenchContribution {
if (this._lifecycleService.startupKind !== StartupKind.NewWindow) {
return false;
}
if (await this._hostService.windowCount !== 1) {
if (await this._electronService.getWindowCount() !== 1) {
return false;
}
const activeViewlet = this._viewletService.getActiveViewlet();

View File

@@ -16,6 +16,10 @@
color: inherit !important;
}
.settings-editor:focus {
outline: none !important;
}
/* header styling */
.settings-editor > .settings-header {
box-sizing: border-box;
@@ -158,7 +162,7 @@
}
.settings-editor > .settings-body .settings-tree-container .monaco-list-row .mouseover .setting-toolbar-container > .monaco-toolbar .codicon-more,
.settings-editor > .settings-body .settings-tree-container .monaco-list-row .setting-item.focused .setting-toolbar-container > .monaco-toolbar .codicon-more,
.settings-editor > .settings-body .settings-tree-container .monaco-list-row .setting-item-contents.focused .setting-toolbar-container > .monaco-toolbar .codicon-more,
.settings-editor > .settings-body .settings-tree-container .monaco-list-row .setting-toolbar-container:hover > .monaco-toolbar .codicon-more,
.settings-editor > .settings-body .settings-tree-container .monaco-list-row .setting-toolbar-container > .monaco-toolbar .active .codicon-more {
opacity: 1;

View File

@@ -374,7 +374,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
constructor(
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@IPreferencesService private readonly preferencesService: IPreferencesService,
@IWorkspaceContextService private readonly workpsaceContextService: IWorkspaceContextService,
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@ILabelService labelService: ILabelService,
@IExtensionService extensionService: IExtensionService,
) {
@@ -410,8 +410,8 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
});
this.updatePreferencesEditorMenuItem();
this._register(workpsaceContextService.onDidChangeWorkbenchState(() => this.updatePreferencesEditorMenuItem()));
this._register(workpsaceContextService.onDidChangeWorkspaceFolders(() => this.updatePreferencesEditorMenuItemForWorkspaceFolders()));
this._register(workspaceContextService.onDidChangeWorkbenchState(() => this.updatePreferencesEditorMenuItem()));
this._register(workspaceContextService.onDidChangeWorkspaceFolders(() => this.updatePreferencesEditorMenuItemForWorkspaceFolders()));
extensionService.whenInstalledExtensionsRegistered()
.then(() => {
@@ -434,7 +434,7 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
private updatePreferencesEditorMenuItem() {
const commandId = '_workbench.openWorkspaceSettingsEditor';
if (this.workpsaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE && !CommandsRegistry.getCommand(commandId)) {
if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE && !CommandsRegistry.getCommand(commandId)) {
CommandsRegistry.registerCommand(commandId, () => this.preferencesService.openWorkspaceSettings(false));
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
@@ -454,11 +454,11 @@ class PreferencesActionsContribution extends Disposable implements IWorkbenchCon
}
private updatePreferencesEditorMenuItemForWorkspaceFolders() {
for (const folder of this.workpsaceContextService.getWorkspace().folders) {
for (const folder of this.workspaceContextService.getWorkspace().folders) {
const commandId = `_workbench.openFolderSettings.${folder.uri.toString()}`;
if (!CommandsRegistry.getCommand(commandId)) {
CommandsRegistry.registerCommand(commandId, () => {
if (this.workpsaceContextService.getWorkbenchState() === WorkbenchState.FOLDER) {
if (this.workspaceContextService.getWorkbenchState() === WorkbenchState.FOLDER) {
return this.preferencesService.openWorkspaceSettings(false);
} else {
return this.preferencesService.openFolderSettings(folder.uri, false);

View File

@@ -204,7 +204,7 @@ export class SettingsEditor2 extends BaseEditor {
createEditor(parent: HTMLElement): void {
parent.setAttribute('tabindex', '-1');
this.rootElement = DOM.append(parent, $('.settings-editor'));
this.rootElement = DOM.append(parent, $('.settings-editor', { tabindex: '-1' }));
this.createHeader(this.rootElement);
this.createBody(this.rootElement);

View File

@@ -37,7 +37,7 @@ import { IContextMenuService, IContextViewService } from 'vs/platform/contextvie
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { errorForeground, focusBorder, foreground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry';
import { errorForeground, focusBorder, foreground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground, transparent } from 'vs/platform/theme/common/colorRegistry';
import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler, attachStyler } from 'vs/platform/theme/common/styler';
import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { ITOCEntry } from 'vs/workbench/contrib/preferences/browser/settingsLayout';
@@ -394,15 +394,12 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre
});
toolbar.setActions([], this.settingActions)();
// change icon from ellipsis to gear
let icon = container.querySelector('.codicon-more');
if (icon) {
(<HTMLElement>icon).classList.add('codicon-gear');
}
const button = container.querySelector('.toolbar-toggle-more');
const button = container.querySelector('.codicon-more');
if (button) {
(<HTMLElement>button).tabIndex = -1;
// change icon from ellipsis to gear
(<HTMLElement>button).classList.add('codicon-gear');
}
return toolbar;
@@ -416,7 +413,6 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre
const setting = element.setting;
DOM.toggleClass(template.containerElement, 'is-configured', element.isConfigured);
DOM.toggleClass(template.containerElement, 'is-expanded', true);
template.containerElement.setAttribute(AbstractSettingRenderer.SETTING_KEY_ATTR, element.setting.key);
template.containerElement.setAttribute(AbstractSettingRenderer.SETTING_ID_ATTR, element.id);
@@ -1219,7 +1215,7 @@ export class SettingTreeRenderers {
}
showContextMenu(element: SettingsTreeSettingElement, settingDOMElement: HTMLElement): void {
const toolbarElement = settingDOMElement.querySelector('.toolbar-toggle-more');
const toolbarElement = settingDOMElement.querySelector('.monaco-toolbar');
if (toolbarElement) {
this._contextMenuService.showContextMenu({
getActions: () => this.settingActions,
@@ -1544,20 +1540,20 @@ export class SettingsTree extends ObjectTree<SettingsTreeElement> {
this.getHTMLElement().classList.add(treeClass);
this.disposables.push(attachStyler(themeService, {
listActiveSelectionBackground: 'transparent',
listActiveSelectionBackground: transparent(Color.white, 0),
listActiveSelectionForeground: foreground,
listFocusAndSelectionBackground: 'transparent',
listFocusAndSelectionBackground: transparent(Color.white, 0),
listFocusAndSelectionForeground: foreground,
listFocusBackground: 'transparent',
listFocusBackground: transparent(Color.white, 0),
listFocusForeground: foreground,
listHoverForeground: foreground,
listHoverBackground: 'transparent',
listHoverOutline: 'transparent',
listFocusOutline: 'transparent',
listInactiveSelectionBackground: 'transparent',
listHoverBackground: transparent(Color.white, 0),
listHoverOutline: transparent(Color.white, 0),
listFocusOutline: transparent(Color.white, 0),
listInactiveSelectionBackground: transparent(Color.white, 0),
listInactiveSelectionForeground: foreground,
listInactiveFocusBackground: 'transparent',
listInactiveFocusOutline: 'transparent'
listInactiveFocusBackground: transparent(Color.white, 0),
listInactiveFocusOutline: transparent(Color.white, 0)
}, colors => {
this.style(colors);
}));

View File

@@ -26,6 +26,7 @@ interface IConfiguration extends IWindowsConfiguration {
telemetry: { enableCrashReporter: boolean };
workbench: { list: { horizontalScrolling: boolean } };
debug: { console: { wordWrap: boolean } };
configurationSync: { enableAuth: boolean };
}
export class SettingsChangeRelauncher extends Disposable implements IWorkbenchContribution {
@@ -38,6 +39,7 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo
private enableCrashReporter: boolean | undefined;
private treeHorizontalScrolling: boolean | undefined;
private debugConsoleWordWrap: boolean | undefined;
private enableConfigSyncAuth: boolean | undefined;
constructor(
@IHostService private readonly hostService: IHostService,
@@ -105,6 +107,12 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo
}
}
// Configuration Sync Auth
if (config.configurationSync && typeof config.configurationSync.enableAuth === 'boolean' && config.configurationSync.enableAuth !== this.enableConfigSyncAuth) {
this.enableConfigSyncAuth = config.configurationSync.enableAuth;
changed = true;
}
// Notify only when changed and we are the focused window (avoids notification spam across windows)
if (notify && changed) {
this.doConfirm(

View File

@@ -91,7 +91,7 @@ export class RemoteWindowActiveIndicator extends Disposable implements IWorkbenc
menu: {
menuId: MenuId.CommandPalette
},
handler: (_accessor) => this.remoteAuthority && hostService.openEmptyWindow({ reuse: true })
handler: (_accessor) => this.remoteAuthority && hostService.openWindow({ forceReuseWindow: true })
});
// Pending entry until extensions are ready

View File

@@ -554,7 +554,7 @@ export class SearchView extends ViewletPanel {
return nls.localize('replaceAll.occurrence.file.message', "Replaced {0} occurrence across {1} file with '{2}'.", occurrences, fileCount, replaceValue);
}
return nls.localize('removeAll.occurrence.file.message', "Replaced {0} occurrence across {1} file'.", occurrences, fileCount);
return nls.localize('removeAll.occurrence.file.message', "Replaced {0} occurrence across {1} file.", occurrences, fileCount);
}
if (replaceValue) {
@@ -569,7 +569,7 @@ export class SearchView extends ViewletPanel {
return nls.localize('replaceAll.occurrences.file.message', "Replaced {0} occurrences across {1} file with '{2}'.", occurrences, fileCount, replaceValue);
}
return nls.localize('removeAll.occurrences.file.message', "Replaced {0} occurrences across {1} file'.", occurrences, fileCount);
return nls.localize('removeAll.occurrences.file.message', "Replaced {0} occurrences across {1} file.", occurrences, fileCount);
}
if (replaceValue) {
@@ -586,7 +586,7 @@ export class SearchView extends ViewletPanel {
return nls.localize('removeAll.occurrence.file.confirmation.message', "Replace {0} occurrence across {1} file with '{2}'?", occurrences, fileCount, replaceValue);
}
return nls.localize('replaceAll.occurrence.file.confirmation.message', "Replace {0} occurrence across {1} file'?", occurrences, fileCount);
return nls.localize('replaceAll.occurrence.file.confirmation.message', "Replace {0} occurrence across {1} file?", occurrences, fileCount);
}
if (replaceValue) {
@@ -601,7 +601,7 @@ export class SearchView extends ViewletPanel {
return nls.localize('removeAll.occurrences.file.confirmation.message', "Replace {0} occurrences across {1} file with '{2}'?", occurrences, fileCount, replaceValue);
}
return nls.localize('replaceAll.occurrences.file.confirmation.message', "Replace {0} occurrences across {1} file'?", occurrences, fileCount);
return nls.localize('replaceAll.occurrences.file.confirmation.message', "Replace {0} occurrences across {1} file?", occurrences, fileCount);
}
if (replaceValue) {

View File

@@ -454,7 +454,7 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
this.notificationService.prompt(Severity.Info, localize('workspaceFound', "This folder contains a workspace file '{0}'. Do you want to open it? [Learn more]({1}) about workspace files.", workspaceFile, 'https://go.microsoft.com/fwlink/?linkid=2025315'), [{
label: localize('openWorkspace', "Open Workspace"),
run: () => this.hostService.openInWindow([{ workspaceUri: joinPath(folder, workspaceFile) }])
run: () => this.hostService.openWindow([{ workspaceUri: joinPath(folder, workspaceFile) }])
}], { neverShowAgain });
}
@@ -467,7 +467,7 @@ export class WorkspaceStatsService implements IWorkspaceStatsService {
workspaces.map(workspace => ({ label: workspace } as IQuickPickItem)),
{ placeHolder: localize('selectToOpen', "Select a workspace to open") }).then(pick => {
if (pick) {
this.hostService.openInWindow([{ workspaceUri: joinPath(folder, pick.label) }]);
this.hostService.openWindow([{ workspaceUri: joinPath(folder, pick.label) }]);
}
});
}

View File

@@ -13,7 +13,6 @@ import { Action } from 'vs/base/common/actions';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
import * as Types from 'vs/base/common/types';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { TerminateResponseCode } from 'vs/base/common/processes';
import * as strings from 'vs/base/common/strings';
import { ValidationStatus, ValidationState } from 'vs/base/common/parsers';
@@ -28,7 +27,6 @@ import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configur
import { IFileService, IFileStat } from 'vs/platform/files/common/files';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ProblemMatcherRegistry, NamedProblemMatcher } from 'vs/workbench/contrib/tasks/common/problemMatcher';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IProgressService, IProgressOptions, ProgressLocation } from 'vs/platform/progress/common/progress';
@@ -354,13 +352,6 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
this.runBuildCommand();
});
KeybindingsRegistry.registerKeybindingRule({
id: 'workbench.action.tasks.build',
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_B
});
CommandsRegistry.registerCommand('workbench.action.tasks.test', () => {
if (!this.canRunCommand()) {
return;

View File

@@ -33,6 +33,8 @@ import { QuickOpenActionContributor } from '../browser/quickOpen';
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { RunAutomaticTasks, ManageAutomaticTaskRunning } from 'vs/workbench/contrib/tasks/browser/runAutomaticTasks';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
let tasksCategory = nls.localize('tasksCategory', "Tasks");
@@ -233,6 +235,13 @@ MenuRegistry.addCommand({ id: 'workbench.action.tasks.configureDefaultTestTask',
// MenuRegistry.addCommand( { id: 'workbench.action.tasks.rebuild', title: nls.localize('RebuildAction.label', 'Run Rebuild Task'), category: tasksCategory });
// MenuRegistry.addCommand( { id: 'workbench.action.tasks.clean', title: nls.localize('CleanAction.label', 'Run Clean Task'), category: tasksCategory });
KeybindingsRegistry.registerKeybindingRule({
id: 'workbench.action.tasks.build',
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_B
});
// Tasks Output channel. Register it before using it in Task Service.
let outputChannelRegistry = Registry.as<IOutputChannelRegistry>(OutputExt.OutputChannels);
outputChannelRegistry.registerChannel({ id: AbstractTaskService.OutputChannelId, label: AbstractTaskService.OutputChannelLabel, log: false });

View File

@@ -13,6 +13,15 @@
return;
}
hasRegistered = true;
// @ts-ignore
require('electron').webFrame.registerURLSchemeAsPrivileged('vscode-resource', {
secure: true,
bypassCSP: false,
allowServiceWorkers: false,
supportFetchAPI: true,
corsEnabled: true
});
};
}());

View File

@@ -4,22 +4,13 @@
*--------------------------------------------------------------------------------------------*/
import { Registry } from 'vs/platform/registry/common/platform';
import { TelemetryOptOut } from './telemetryOptOut';
import { BrowserTelemetryOptOut } from 'vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
// {{SQL CARBON EDIT}} - Add preview feature switch
import { EnablePreviewFeatures } from 'sql/workbench/common/enablePreviewFeatures';
// {{SQL CARBON EDIT}}
// Registry
// .as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
// .registerWorkbenchContribution(GettingStarted, LifecyclePhase.Running);
Registry
.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(TelemetryOptOut, LifecyclePhase.Eventually);
// {{SQL CARBON EDIT}} - Add preview feature switch
Registry
.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(EnablePreviewFeatures, LifecyclePhase.Eventually);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(BrowserTelemetryOptOut, LifecyclePhase.Eventually);

View File

@@ -19,7 +19,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { IProductService } from 'vs/platform/product/common/productService';
import { IHostService } from 'vs/workbench/services/host/browser/host';
export class TelemetryOptOut implements IWorkbenchContribution {
export abstract class AbstractTelemetryOptOut implements IWorkbenchContribution {
private static TELEMETRY_OPT_OUT_SHOWN = 'workbench.telemetryOptOutShown';
private privacyUrl: string | undefined;
@@ -35,18 +35,18 @@ export class TelemetryOptOut implements IWorkbenchContribution {
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
@IProductService productService: IProductService
) {
if (!productService.telemetryOptOutUrl || storageService.get(TelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, StorageScope.GLOBAL)) {
if (!productService.telemetryOptOutUrl || storageService.get(AbstractTelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, StorageScope.GLOBAL)) {
return;
}
const experimentId = 'telemetryOptOut';
Promise.all([
hostService.windowCount,
this.getWindowCount(),
experimentService.getExperimentById(experimentId)
]).then(([count, experimentState]) => {
if (!hostService.hasFocus && count > 1) {
return;
}
storageService.store(TelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, true, StorageScope.GLOBAL);
storageService.store(AbstractTelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, true, StorageScope.GLOBAL);
this.privacyUrl = productService.privacyStatementUrl || productService.telemetryOptOutUrl;
@@ -74,6 +74,8 @@ export class TelemetryOptOut implements IWorkbenchContribution {
.then(undefined, onUnexpectedError);
}
protected abstract getWindowCount(): Promise<number>;
private runExperiment(experimentId: string) {
const promptMessageKey = 'telemetryOptOut.optOutOption';
const yesLabelKey = 'telemetryOptOut.OptIn';
@@ -148,3 +150,10 @@ export class TelemetryOptOut implements IWorkbenchContribution {
});
}
}
export class BrowserTelemetryOptOut extends AbstractTelemetryOptOut {
protected async getWindowCount(): Promise<number> {
return 1;
}
}

View File

@@ -4,10 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import { Registry } from 'vs/platform/registry/common/platform';
import { OpenWelcomePageInBrowser } from './openWebsite';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { NativeTelemetryOptOut } from 'vs/workbench/contrib/welcome/gettingStarted/electron-browser/telemetryOptOut';
import { OpenWelcomePageInBrowser } from 'vs/workbench/contrib/welcome/gettingStarted/electron-browser/openWebsite';
Registry
.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(OpenWelcomePageInBrowser, LifecyclePhase.Restored);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(OpenWelcomePageInBrowser, LifecyclePhase.Restored);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NativeTelemetryOptOut, LifecyclePhase.Eventually);

View File

@@ -0,0 +1,38 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IProductService } from 'vs/platform/product/common/productService';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { AbstractTelemetryOptOut } from 'vs/workbench/contrib/welcome/gettingStarted/browser/telemetryOptOut';
import { IElectronService } from 'vs/platform/electron/node/electron';
export class NativeTelemetryOptOut extends AbstractTelemetryOptOut {
constructor(
@IStorageService storageService: IStorageService,
@IOpenerService openerService: IOpenerService,
@INotificationService notificationService: INotificationService,
@IHostService hostService: IHostService,
@ITelemetryService telemetryService: ITelemetryService,
@IExperimentService experimentService: IExperimentService,
@IConfigurationService configurationService: IConfigurationService,
@IExtensionGalleryService galleryService: IExtensionGalleryService,
@IProductService productService: IProductService,
@IElectronService private readonly electronService: IElectronService
) {
super(storageService, openerService, notificationService, hostService, telemetryService, experimentService, configurationService, galleryService, productService);
}
protected getWindowCount(): Promise<number> {
return this.electronService.getWindowCount();
}
}

View File

@@ -370,7 +370,7 @@ class WelcomePage extends Disposable {
id: 'openRecentFolder',
from: telemetryFrom
});
this.hostService.openInWindow([windowOpenable], { forceNewWindow: e.ctrlKey || e.metaKey });
this.hostService.openWindow([windowOpenable], { forceNewWindow: e.ctrlKey || e.metaKey });
e.preventDefault();
e.stopPropagation();
});