mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-30 16:50:30 -04:00
Merge from vscode ec07311dab2556c9d66a4cb3eecdc21c524202e1 (#6739)
This commit is contained in:
@@ -607,11 +607,9 @@ class CallStackDataSource implements IAsyncDataSource<IDebugModel, CallStackItem
|
||||
return threads.length === 1 ? this.getThreadChildren(<Thread>threads[0]) : Promise.resolve(threads);
|
||||
} else if (isDebugSession(element)) {
|
||||
const childSessions = this.debugService.getModel().getSessions().filter(s => s.parentSession === element);
|
||||
if (childSessions.length) {
|
||||
return Promise.resolve(childSessions);
|
||||
}
|
||||
const threads: CallStackItem[] = element.getAllThreads();
|
||||
|
||||
return Promise.resolve(element.getAllThreads());
|
||||
return Promise.resolve(threads.concat(childSessions));
|
||||
} else {
|
||||
return this.getThreadChildren(<Thread>element);
|
||||
}
|
||||
|
||||
@@ -134,29 +134,33 @@ interface IActiveElement {
|
||||
focus(): void;
|
||||
}
|
||||
|
||||
interface IExtensionEditorTemplate {
|
||||
iconContainer: HTMLElement;
|
||||
icon: HTMLImageElement;
|
||||
name: HTMLElement;
|
||||
identifier: HTMLElement;
|
||||
preview: HTMLElement;
|
||||
builtin: HTMLElement;
|
||||
license: HTMLElement;
|
||||
publisher: HTMLElement;
|
||||
installCount: HTMLElement;
|
||||
rating: HTMLElement;
|
||||
repository: HTMLElement;
|
||||
description: HTMLElement;
|
||||
extensionActionBar: ActionBar;
|
||||
navbar: NavBar;
|
||||
content: HTMLElement;
|
||||
subtextContainer: HTMLElement;
|
||||
subtext: HTMLElement;
|
||||
ignoreActionbar: ActionBar;
|
||||
header: HTMLElement;
|
||||
}
|
||||
|
||||
export class ExtensionEditor extends BaseEditor {
|
||||
|
||||
static readonly ID: string = 'workbench.editor.extension';
|
||||
|
||||
private iconContainer: HTMLElement;
|
||||
private icon: HTMLImageElement;
|
||||
private name: HTMLElement;
|
||||
private identifier: HTMLElement;
|
||||
private preview: HTMLElement;
|
||||
private builtin: HTMLElement;
|
||||
private license: HTMLElement;
|
||||
private publisher: HTMLElement;
|
||||
private installCount: HTMLElement;
|
||||
private rating: HTMLElement;
|
||||
private repository: HTMLElement;
|
||||
private description: HTMLElement;
|
||||
private extensionActionBar: ActionBar;
|
||||
private navbar: NavBar;
|
||||
private content: HTMLElement;
|
||||
private subtextContainer: HTMLElement;
|
||||
private subtext: HTMLElement;
|
||||
private ignoreActionbar: ActionBar;
|
||||
private header: HTMLElement;
|
||||
private template: IExtensionEditorTemplate | undefined;
|
||||
|
||||
private extensionReadme: Cache<string> | null;
|
||||
private extensionChangelog: Cache<string> | null;
|
||||
@@ -165,7 +169,7 @@ export class ExtensionEditor extends BaseEditor {
|
||||
private layoutParticipants: ILayoutParticipant[] = [];
|
||||
private readonly contentDisposables = this._register(new DisposableStore());
|
||||
private readonly transientDisposables = this._register(new DisposableStore());
|
||||
private activeElement: IActiveElement | null;
|
||||
private activeElement: IActiveElement | null = null;
|
||||
private editorLoadComplete: boolean = false;
|
||||
|
||||
constructor(
|
||||
@@ -193,43 +197,43 @@ 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';
|
||||
this.header = append(root, $('.header'));
|
||||
const header = append(root, $('.header'));
|
||||
|
||||
this.iconContainer = append(this.header, $('.icon-container'));
|
||||
this.icon = append(this.iconContainer, $<HTMLImageElement>('img.icon', { draggable: false }));
|
||||
const iconContainer = append(header, $('.icon-container'));
|
||||
const icon = append(iconContainer, $<HTMLImageElement>('img.icon', { draggable: false }));
|
||||
|
||||
const details = append(this.header, $('.details'));
|
||||
const details = append(header, $('.details'));
|
||||
const title = append(details, $('.title'));
|
||||
this.name = append(title, $('span.name.clickable', { title: localize('name', "Extension name") }));
|
||||
this.identifier = append(title, $('span.identifier', { title: localize('extension id', "Extension identifier") }));
|
||||
const name = append(title, $('span.name.clickable', { title: localize('name', "Extension name") }));
|
||||
const identifier = append(title, $('span.identifier', { title: localize('extension id', "Extension identifier") }));
|
||||
|
||||
this.preview = append(title, $('span.preview', { title: localize('preview', "Preview") }));
|
||||
this.preview.textContent = localize('preview', "Preview");
|
||||
const preview = append(title, $('span.preview', { title: localize('preview', "Preview") }));
|
||||
preview.textContent = localize('preview', "Preview");
|
||||
|
||||
this.builtin = append(title, $('span.builtin'));
|
||||
this.builtin.textContent = localize('builtin', "Built-in");
|
||||
const builtin = append(title, $('span.builtin'));
|
||||
builtin.textContent = localize('builtin', "Built-in");
|
||||
|
||||
const subtitle = append(details, $('.subtitle'));
|
||||
this.publisher = append(subtitle, $('span.publisher.clickable', { title: localize('publisher', "Publisher name"), tabIndex: 0 }));
|
||||
const publisher = append(subtitle, $('span.publisher.clickable', { title: localize('publisher', "Publisher name"), tabIndex: 0 }));
|
||||
|
||||
this.installCount = append(subtitle, $('span.install', { title: localize('install count', "Install count"), tabIndex: 0 }));
|
||||
const installCount = append(subtitle, $('span.install', { title: localize('install count', "Install count"), tabIndex: 0 }));
|
||||
|
||||
this.rating = append(subtitle, $('span.rating.clickable', { title: localize('rating', "Rating"), tabIndex: 0 }));
|
||||
const rating = append(subtitle, $('span.rating.clickable', { title: localize('rating', "Rating"), tabIndex: 0 }));
|
||||
|
||||
this.repository = append(subtitle, $('span.repository.clickable'));
|
||||
this.repository.textContent = localize('repository', 'Repository');
|
||||
this.repository.style.display = 'none';
|
||||
this.repository.tabIndex = 0;
|
||||
const repository = append(subtitle, $('span.repository.clickable'));
|
||||
repository.textContent = localize('repository', 'Repository');
|
||||
repository.style.display = 'none';
|
||||
repository.tabIndex = 0;
|
||||
|
||||
this.license = append(subtitle, $('span.license.clickable'));
|
||||
this.license.textContent = localize('license', 'License');
|
||||
this.license.style.display = 'none';
|
||||
this.license.tabIndex = 0;
|
||||
const license = append(subtitle, $('span.license.clickable'));
|
||||
license.textContent = localize('license', 'License');
|
||||
license.style.display = 'none';
|
||||
license.tabIndex = 0;
|
||||
|
||||
this.description = append(details, $('.description'));
|
||||
const description = append(details, $('.description'));
|
||||
|
||||
const extensionActions = append(details, $('.actions'));
|
||||
this.extensionActionBar = new ActionBar(extensionActions, {
|
||||
const extensionActionBar = this._register(new ActionBar(extensionActions, {
|
||||
animated: false,
|
||||
actionViewItemProvider: (action: Action) => {
|
||||
if (action instanceof ExtensionEditorDropDownAction) {
|
||||
@@ -237,29 +241,48 @@ export class ExtensionEditor extends BaseEditor {
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
this.subtextContainer = append(details, $('.subtext-container'));
|
||||
this.subtext = append(this.subtextContainer, $('.subtext'));
|
||||
this.ignoreActionbar = new ActionBar(this.subtextContainer, { animated: false });
|
||||
const subtextContainer = append(details, $('.subtext-container'));
|
||||
const subtext = append(subtextContainer, $('.subtext'));
|
||||
const ignoreActionbar = this._register(new ActionBar(subtextContainer, { animated: false }));
|
||||
|
||||
this._register(this.extensionActionBar);
|
||||
this._register(this.ignoreActionbar);
|
||||
|
||||
this._register(Event.chain(this.extensionActionBar.onDidRun)
|
||||
this._register(Event.chain(extensionActionBar.onDidRun)
|
||||
.map(({ error }) => error)
|
||||
.filter(error => !!error)
|
||||
.on(this.onError, this));
|
||||
|
||||
this._register(Event.chain(this.ignoreActionbar.onDidRun)
|
||||
this._register(Event.chain(ignoreActionbar.onDidRun)
|
||||
.map(({ error }) => error)
|
||||
.filter(error => !!error)
|
||||
.on(this.onError, this));
|
||||
|
||||
const body = append(root, $('.body'));
|
||||
this.navbar = new NavBar(body);
|
||||
const navbar = new NavBar(body);
|
||||
|
||||
this.content = append(body, $('.content'));
|
||||
const content = append(body, $('.content'));
|
||||
|
||||
this.template = {
|
||||
builtin,
|
||||
content,
|
||||
description,
|
||||
extensionActionBar,
|
||||
header,
|
||||
icon,
|
||||
iconContainer,
|
||||
identifier,
|
||||
ignoreActionbar,
|
||||
installCount,
|
||||
license,
|
||||
name,
|
||||
navbar,
|
||||
preview,
|
||||
publisher,
|
||||
rating,
|
||||
repository,
|
||||
subtext,
|
||||
subtextContainer
|
||||
};
|
||||
}
|
||||
|
||||
private onClick(element: HTMLElement, callback: () => void): IDisposable {
|
||||
@@ -277,6 +300,13 @@ export class ExtensionEditor extends BaseEditor {
|
||||
}
|
||||
|
||||
async setInput(input: ExtensionsInput, options: EditorOptions, token: CancellationToken): Promise<void> {
|
||||
if (this.template) {
|
||||
await this.updateTemplate(input, this.template);
|
||||
}
|
||||
return super.setInput(input, options, token);
|
||||
}
|
||||
|
||||
private async updateTemplate(input: ExtensionsInput, template: IExtensionEditorTemplate): Promise<void> {
|
||||
const runningExtensions = await this.extensionService.getExtensions();
|
||||
const colorThemes = await this.workbenchThemeService.getColorThemes();
|
||||
const fileIconThemes = await this.workbenchThemeService.getFileIconThemes();
|
||||
@@ -291,18 +321,18 @@ export class ExtensionEditor extends BaseEditor {
|
||||
this.extensionChangelog = new Cache(() => createCancelablePromise(token => extension.getChangelog(token)));
|
||||
this.extensionManifest = new Cache(() => createCancelablePromise(token => extension.getManifest(token)));
|
||||
|
||||
const remoteBadge = this.instantiationService.createInstance(RemoteBadgeWidget, this.iconContainer, true);
|
||||
const onError = Event.once(domEvent(this.icon, 'error'));
|
||||
onError(() => this.icon.src = extension.iconUrlFallback, null, this.transientDisposables);
|
||||
this.icon.src = extension.iconUrl;
|
||||
const remoteBadge = this.instantiationService.createInstance(RemoteBadgeWidget, template.iconContainer, true);
|
||||
const onError = Event.once(domEvent(template.icon, 'error'));
|
||||
onError(() => template.icon.src = extension.iconUrlFallback, null, this.transientDisposables);
|
||||
template.icon.src = extension.iconUrl;
|
||||
|
||||
this.name.textContent = extension.displayName;
|
||||
this.identifier.textContent = extension.identifier.id;
|
||||
this.preview.style.display = extension.preview ? 'inherit' : 'none';
|
||||
this.builtin.style.display = extension.type === ExtensionType.System ? 'inherit' : 'none';
|
||||
template.name.textContent = extension.displayName;
|
||||
template.identifier.textContent = extension.identifier.id;
|
||||
template.preview.style.display = extension.preview ? 'inherit' : 'none';
|
||||
template.builtin.style.display = extension.type === ExtensionType.System ? 'inherit' : 'none';
|
||||
|
||||
this.publisher.textContent = extension.publisherDisplayName;
|
||||
this.description.textContent = extension.description;
|
||||
template.publisher.textContent = extension.publisherDisplayName;
|
||||
template.description.textContent = extension.description;
|
||||
|
||||
const extRecommendations = this.extensionTipsService.getAllRecommendationsWithReason();
|
||||
let recommendationsData = {};
|
||||
@@ -320,51 +350,50 @@ export class ExtensionEditor extends BaseEditor {
|
||||
*/
|
||||
this.telemetryService.publicLog('extensionGallery:openExtension', assign(extension.telemetryData, recommendationsData));
|
||||
|
||||
toggleClass(this.name, 'clickable', !!extension.url);
|
||||
toggleClass(this.publisher, 'clickable', !!extension.url);
|
||||
toggleClass(this.rating, 'clickable', !!extension.url);
|
||||
toggleClass(template.name, 'clickable', !!extension.url);
|
||||
toggleClass(template.publisher, 'clickable', !!extension.url);
|
||||
toggleClass(template.rating, 'clickable', !!extension.url);
|
||||
if (extension.url) {
|
||||
this.transientDisposables.add(this.onClick(this.name, () => window.open(extension.url)));
|
||||
this.transientDisposables.add(this.onClick(this.rating, () => window.open(`${extension.url}#review-details`)));
|
||||
this.transientDisposables.add(this.onClick(this.publisher, () => {
|
||||
this.transientDisposables.add(this.onClick(template.name, () => window.open(extension.url)));
|
||||
this.transientDisposables.add(this.onClick(template.rating, () => window.open(`${extension.url}#review-details`)));
|
||||
this.transientDisposables.add(this.onClick(template.publisher, () => {
|
||||
this.viewletService.openViewlet(VIEWLET_ID, true)
|
||||
.then(viewlet => viewlet as IExtensionsViewlet)
|
||||
.then(viewlet => viewlet.search(`publisher:"${extension.publisherDisplayName}"`));
|
||||
}));
|
||||
|
||||
if (extension.licenseUrl) {
|
||||
this.transientDisposables.add(this.onClick(this.license, () => window.open(extension.licenseUrl)));
|
||||
this.license.style.display = 'initial';
|
||||
this.transientDisposables.add(this.onClick(template.license, () => window.open(extension.licenseUrl)));
|
||||
template.license.style.display = 'initial';
|
||||
} else {
|
||||
this.license.style.display = 'none';
|
||||
template.license.style.display = 'none';
|
||||
}
|
||||
} else {
|
||||
this.license.style.display = 'none';
|
||||
template.license.style.display = 'none';
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}} add license url
|
||||
if (extension.licenseUrl) {
|
||||
this.license.onclick = finalHandler(() => window.open(extension.licenseUrl));
|
||||
this.license.style.display = 'initial';
|
||||
template.license.onclick = finalHandler(() => window.open(extension.licenseUrl));
|
||||
template.license.style.display = 'initial';
|
||||
} else {
|
||||
this.license.onclick = null;
|
||||
this.license.style.display = 'none';
|
||||
template.license.onclick = null;
|
||||
template.license.style.display = 'none';
|
||||
}
|
||||
// {{SQL CARBON EDIT}} - End
|
||||
|
||||
if (extension.repository) {
|
||||
this.transientDisposables.add(this.onClick(this.repository, () => window.open(extension.repository)));
|
||||
this.repository.style.display = 'initial';
|
||||
this.transientDisposables.add(this.onClick(template.repository, () => window.open(extension.repository)));
|
||||
template.repository.style.display = 'initial';
|
||||
}
|
||||
else {
|
||||
this.repository.style.display = 'none';
|
||||
template.repository.style.display = 'none';
|
||||
}
|
||||
|
||||
const widgets = [
|
||||
remoteBadge,
|
||||
// {{SQL CARBON EDIT}} Remove the widgets
|
||||
// this.instantiationService.createInstance(InstallCountWidget, this.installCount, false),
|
||||
// this.instantiationService.createInstance(RatingsWidget, this.rating, false)
|
||||
// this.instantiationService.createInstance(InstallCountWidget, template.installCount, false), {{SQL CARBON EDIT}} Remove the widgets
|
||||
// this.instantiationService.createInstance(RatingsWidget, template.rating, false) {{SQL CARBON EDIT}} Remove the widgets
|
||||
];
|
||||
const reloadAction = this.instantiationService.createInstance(ReloadAction);
|
||||
const combinedInstallAction = this.instantiationService.createInstance(CombinedInstallAction);
|
||||
@@ -387,20 +416,20 @@ export class ExtensionEditor extends BaseEditor {
|
||||
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets]);
|
||||
extensionContainers.extension = extension;
|
||||
|
||||
this.extensionActionBar.clear();
|
||||
this.extensionActionBar.push(actions, { icon: true, label: true });
|
||||
template.extensionActionBar.clear();
|
||||
template.extensionActionBar.push(actions, { icon: true, label: true });
|
||||
for (const disposable of [...actions, ...widgets, extensionContainers]) {
|
||||
this.transientDisposables.add(disposable);
|
||||
}
|
||||
|
||||
this.setSubText(extension, reloadAction);
|
||||
this.content.innerHTML = ''; // Clear content before setting navbar actions.
|
||||
this.setSubText(extension, reloadAction, template);
|
||||
template.content.innerHTML = ''; // Clear content before setting navbar actions.
|
||||
|
||||
this.navbar.clear();
|
||||
this.navbar.onChange(this.onNavbarChange.bind(this, extension), this, this.transientDisposables);
|
||||
template.navbar.clear();
|
||||
template.navbar.onChange(e => this.onNavbarChange(extension, e, template), this, this.transientDisposables);
|
||||
|
||||
if (extension.hasReadme()) {
|
||||
this.navbar.push(NavbarSection.Readme, localize('details', "Details"), localize('detailstooltip', "Extension details, rendered from the extension's 'README.md' file"));
|
||||
template.navbar.push(NavbarSection.Readme, localize('details', "Details"), localize('detailstooltip', "Extension details, rendered from the extension's 'README.md' file"));
|
||||
}
|
||||
this.extensionManifest.get()
|
||||
.promise
|
||||
@@ -409,25 +438,23 @@ export class ExtensionEditor extends BaseEditor {
|
||||
combinedInstallAction.manifest = manifest;
|
||||
}
|
||||
if (extension.extensionPack.length) {
|
||||
this.navbar.push(NavbarSection.ExtensionPack, localize('extensionPack', "Extension Pack"), localize('extensionsPack', "Set of extensions that can be installed together"));
|
||||
template.navbar.push(NavbarSection.ExtensionPack, localize('extensionPack', "Extension Pack"), localize('extensionsPack', "Set of extensions that can be installed together"));
|
||||
}
|
||||
if (manifest && manifest.contributes) {
|
||||
this.navbar.push(NavbarSection.Contributions, localize('contributions', "Contributions"), localize('contributionstooltip', "Lists contributions to VS Code by this extension"));
|
||||
template.navbar.push(NavbarSection.Contributions, localize('contributions', "Contributions"), localize('contributionstooltip', "Lists contributions to VS Code by this extension"));
|
||||
}
|
||||
if (extension.hasChangelog()) {
|
||||
this.navbar.push(NavbarSection.Changelog, localize('changelog', "Changelog"), localize('changelogtooltip', "Extension update history, rendered from the extension's 'CHANGELOG.md' file"));
|
||||
template.navbar.push(NavbarSection.Changelog, localize('changelog', "Changelog"), localize('changelogtooltip', "Extension update history, rendered from the extension's 'CHANGELOG.md' file"));
|
||||
}
|
||||
if (extension.dependencies.length) {
|
||||
this.navbar.push(NavbarSection.Dependencies, localize('dependencies', "Dependencies"), localize('dependenciestooltip', "Lists extensions this extension depends on"));
|
||||
template.navbar.push(NavbarSection.Dependencies, localize('dependencies', "Dependencies"), localize('dependenciestooltip', "Lists extensions this extension depends on"));
|
||||
}
|
||||
this.editorLoadComplete = true;
|
||||
});
|
||||
|
||||
return super.setInput(input, options, token);
|
||||
}
|
||||
|
||||
private setSubText(extension: IExtension, reloadAction: ReloadAction): void {
|
||||
hide(this.subtextContainer);
|
||||
private setSubText(extension: IExtension, reloadAction: ReloadAction, template: IExtensionEditorTemplate): void {
|
||||
hide(template.subtextContainer);
|
||||
|
||||
const ignoreAction = this.instantiationService.createInstance(IgnoreExtensionRecommendationAction);
|
||||
const undoIgnoreAction = this.instantiationService.createInstance(UndoIgnoreExtensionRecommendationAction);
|
||||
@@ -436,23 +463,23 @@ export class ExtensionEditor extends BaseEditor {
|
||||
ignoreAction.enabled = false;
|
||||
undoIgnoreAction.enabled = false;
|
||||
|
||||
this.ignoreActionbar.clear();
|
||||
this.ignoreActionbar.push([ignoreAction, undoIgnoreAction], { icon: true, label: true });
|
||||
template.ignoreActionbar.clear();
|
||||
template.ignoreActionbar.push([ignoreAction, undoIgnoreAction], { icon: true, label: true });
|
||||
this.transientDisposables.add(ignoreAction);
|
||||
this.transientDisposables.add(undoIgnoreAction);
|
||||
|
||||
const extRecommendations = this.extensionTipsService.getAllRecommendationsWithReason();
|
||||
if (extRecommendations[extension.identifier.id.toLowerCase()]) {
|
||||
ignoreAction.enabled = true;
|
||||
this.subtext.textContent = extRecommendations[extension.identifier.id.toLowerCase()].reasonText;
|
||||
show(this.subtextContainer);
|
||||
template.subtext.textContent = extRecommendations[extension.identifier.id.toLowerCase()].reasonText;
|
||||
show(template.subtextContainer);
|
||||
} else if (this.extensionTipsService.getAllIgnoredRecommendations().global.indexOf(extension.identifier.id.toLowerCase()) !== -1) {
|
||||
undoIgnoreAction.enabled = true;
|
||||
this.subtext.textContent = localize('recommendationHasBeenIgnored', "You have chosen not to receive recommendations for this extension.");
|
||||
show(this.subtextContainer);
|
||||
template.subtext.textContent = localize('recommendationHasBeenIgnored', "You have chosen not to receive recommendations for this extension.");
|
||||
show(template.subtextContainer);
|
||||
}
|
||||
else {
|
||||
this.subtext.textContent = '';
|
||||
template.subtext.textContent = '';
|
||||
}
|
||||
|
||||
this.extensionTipsService.onRecommendationChange(change => {
|
||||
@@ -462,28 +489,28 @@ export class ExtensionEditor extends BaseEditor {
|
||||
const extRecommendations = this.extensionTipsService.getAllRecommendationsWithReason();
|
||||
if (extRecommendations[extension.identifier.id.toLowerCase()]) {
|
||||
ignoreAction.enabled = true;
|
||||
this.subtext.textContent = extRecommendations[extension.identifier.id.toLowerCase()].reasonText;
|
||||
template.subtext.textContent = extRecommendations[extension.identifier.id.toLowerCase()].reasonText;
|
||||
}
|
||||
} else {
|
||||
undoIgnoreAction.enabled = true;
|
||||
ignoreAction.enabled = false;
|
||||
this.subtext.textContent = localize('recommendationHasBeenIgnored', "You have chosen not to receive recommendations for this extension.");
|
||||
template.subtext.textContent = localize('recommendationHasBeenIgnored', "You have chosen not to receive recommendations for this extension.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.transientDisposables.add(reloadAction.onDidChange(e => {
|
||||
if (e.tooltip) {
|
||||
this.subtext.textContent = reloadAction.tooltip;
|
||||
show(this.subtextContainer);
|
||||
template.subtext.textContent = reloadAction.tooltip;
|
||||
show(template.subtextContainer);
|
||||
ignoreAction.enabled = false;
|
||||
undoIgnoreAction.enabled = false;
|
||||
}
|
||||
if (e.enabled === true) {
|
||||
show(this.subtextContainer);
|
||||
show(template.subtextContainer);
|
||||
}
|
||||
if (e.enabled === false) {
|
||||
hide(this.subtextContainer);
|
||||
hide(template.subtextContainer);
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -507,7 +534,7 @@ export class ExtensionEditor extends BaseEditor {
|
||||
}
|
||||
}
|
||||
|
||||
private onNavbarChange(extension: IExtension, { id, focus }: { id: string, focus: boolean }): void {
|
||||
private onNavbarChange(extension: IExtension, { id, focus }: { id: string | null, focus: boolean }, template: IExtensionEditorTemplate): void {
|
||||
if (this.editorLoadComplete) {
|
||||
/* __GDPR__
|
||||
"extensionEditor:navbarChange" : {
|
||||
@@ -521,30 +548,32 @@ export class ExtensionEditor extends BaseEditor {
|
||||
}
|
||||
|
||||
this.contentDisposables.clear();
|
||||
this.content.innerHTML = '';
|
||||
template.content.innerHTML = '';
|
||||
this.activeElement = null;
|
||||
this.open(id, extension)
|
||||
.then(activeElement => {
|
||||
this.activeElement = activeElement;
|
||||
if (focus) {
|
||||
this.focus();
|
||||
}
|
||||
});
|
||||
if (id) {
|
||||
this.open(id, extension, template)
|
||||
.then(activeElement => {
|
||||
this.activeElement = activeElement;
|
||||
if (focus) {
|
||||
this.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private open(id: string, extension: IExtension): Promise<IActiveElement | null> {
|
||||
private open(id: string, extension: IExtension, template: IExtensionEditorTemplate): Promise<IActiveElement | null> {
|
||||
switch (id) {
|
||||
case NavbarSection.Readme: return this.openReadme();
|
||||
case NavbarSection.Contributions: return this.openContributions();
|
||||
case NavbarSection.Changelog: return this.openChangelog();
|
||||
case NavbarSection.Dependencies: return this.openDependencies(extension);
|
||||
case NavbarSection.ExtensionPack: return this.openExtensionPack(extension);
|
||||
case NavbarSection.Readme: return this.openReadme(template);
|
||||
case NavbarSection.Contributions: return this.openContributions(template);
|
||||
case NavbarSection.Changelog: return this.openChangelog(template);
|
||||
case NavbarSection.Dependencies: return this.openDependencies(extension, template);
|
||||
case NavbarSection.ExtensionPack: return this.openExtensionPack(extension, template);
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
private openMarkdown(cacheResult: CacheResult<string>, noContentCopy: string): Promise<IActiveElement> {
|
||||
return this.loadContents(() => cacheResult)
|
||||
private openMarkdown(cacheResult: CacheResult<string>, noContentCopy: string, template: IExtensionEditorTemplate): Promise<IActiveElement> {
|
||||
return this.loadContents(() => cacheResult, template)
|
||||
.then(marked.parse)
|
||||
.then(content => this.renderBody(content))
|
||||
.then(removeEmbeddedSVGs)
|
||||
@@ -556,7 +585,7 @@ export class ExtensionEditor extends BaseEditor {
|
||||
{
|
||||
svgWhiteList: this.extensionsWorkbenchService.allowedBadgeProviders,
|
||||
});
|
||||
webviewElement.mountTo(this.content);
|
||||
webviewElement.mountTo(template.content);
|
||||
this.contentDisposables.add(webviewElement.onDidFocus(() => this.fireOnDidFocus()));
|
||||
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, webviewElement);
|
||||
this.contentDisposables.add(toDisposable(removeLayoutParticipant));
|
||||
@@ -575,7 +604,7 @@ export class ExtensionEditor extends BaseEditor {
|
||||
return webviewElement;
|
||||
})
|
||||
.then(undefined, () => {
|
||||
const p = append(this.content, $('p.nocontent'));
|
||||
const p = append(template.content, $('p.nocontent'));
|
||||
p.textContent = noContentCopy;
|
||||
return p;
|
||||
});
|
||||
@@ -769,17 +798,17 @@ export class ExtensionEditor extends BaseEditor {
|
||||
</html>`;
|
||||
}
|
||||
|
||||
private openReadme(): Promise<IActiveElement> {
|
||||
return this.openMarkdown(this.extensionReadme!.get(), localize('noReadme', "No README available."));
|
||||
private openReadme(template: IExtensionEditorTemplate): Promise<IActiveElement> {
|
||||
return this.openMarkdown(this.extensionReadme!.get(), localize('noReadme', "No README available."), template);
|
||||
}
|
||||
|
||||
private openChangelog(): Promise<IActiveElement> {
|
||||
return this.openMarkdown(this.extensionChangelog!.get(), localize('noChangelog', "No Changelog available."));
|
||||
private openChangelog(template: IExtensionEditorTemplate): Promise<IActiveElement> {
|
||||
return this.openMarkdown(this.extensionChangelog!.get(), localize('noChangelog', "No Changelog available."), template);
|
||||
}
|
||||
|
||||
private openContributions(): Promise<IActiveElement> {
|
||||
private openContributions(template: IExtensionEditorTemplate): Promise<IActiveElement> {
|
||||
const content = $('div', { class: 'subcontent', tabindex: '0' });
|
||||
return this.loadContents(() => this.extensionManifest!.get())
|
||||
return this.loadContents(() => this.extensionManifest!.get(), template)
|
||||
.then(manifest => {
|
||||
if (!manifest) {
|
||||
return content;
|
||||
@@ -811,28 +840,28 @@ export class ExtensionEditor extends BaseEditor {
|
||||
const isEmpty = !renders.some(x => x);
|
||||
if (isEmpty) {
|
||||
append(content, $('p.nocontent')).textContent = localize('noContributions', "No Contributions");
|
||||
append(this.content, content);
|
||||
append(template.content, content);
|
||||
} else {
|
||||
append(this.content, scrollableContent.getDomNode());
|
||||
append(template.content, scrollableContent.getDomNode());
|
||||
this.contentDisposables.add(scrollableContent);
|
||||
}
|
||||
return content;
|
||||
}, () => {
|
||||
append(content, $('p.nocontent')).textContent = localize('noContributions', "No Contributions");
|
||||
append(this.content, content);
|
||||
append(template.content, content);
|
||||
return content;
|
||||
});
|
||||
}
|
||||
|
||||
private openDependencies(extension: IExtension): Promise<IActiveElement> {
|
||||
private openDependencies(extension: IExtension, template: IExtensionEditorTemplate): Promise<IActiveElement> {
|
||||
if (arrays.isFalsyOrEmpty(extension.dependencies)) {
|
||||
append(this.content, $('p.nocontent')).textContent = localize('noDependencies', "No Dependencies");
|
||||
return Promise.resolve(this.content);
|
||||
append(template.content, $('p.nocontent')).textContent = localize('noDependencies', "No Dependencies");
|
||||
return Promise.resolve(template.content);
|
||||
}
|
||||
|
||||
const content = $('div', { class: 'subcontent' });
|
||||
const scrollableContent = new DomScrollableElement(content, {});
|
||||
append(this.content, scrollableContent.getDomNode());
|
||||
append(template.content, scrollableContent.getDomNode());
|
||||
this.contentDisposables.add(scrollableContent);
|
||||
|
||||
const dependenciesTree = this.instantiationService.createInstance(ExtensionsTree, new ExtensionData(extension, null, extension => extension.dependencies || [], this.extensionsWorkbenchService), content);
|
||||
@@ -849,10 +878,10 @@ export class ExtensionEditor extends BaseEditor {
|
||||
return Promise.resolve({ focus() { dependenciesTree.domFocus(); } });
|
||||
}
|
||||
|
||||
private openExtensionPack(extension: IExtension): Promise<IActiveElement> {
|
||||
private openExtensionPack(extension: IExtension, template: IExtensionEditorTemplate): Promise<IActiveElement> {
|
||||
const content = $('div', { class: 'subcontent' });
|
||||
const scrollableContent = new DomScrollableElement(content, {});
|
||||
append(this.content, scrollableContent.getDomNode());
|
||||
append(template.content, scrollableContent.getDomNode());
|
||||
this.contentDisposables.add(scrollableContent);
|
||||
|
||||
const extensionsPackTree = this.instantiationService.createInstance(ExtensionsTree, new ExtensionData(extension, null, extension => extension.extensionPack || [], this.extensionsWorkbenchService), content);
|
||||
@@ -1272,11 +1301,11 @@ export class ExtensionEditor extends BaseEditor {
|
||||
return null;
|
||||
}
|
||||
|
||||
private loadContents<T>(loadingTask: () => CacheResult<T>): Promise<T> {
|
||||
addClass(this.content, 'loading');
|
||||
private loadContents<T>(loadingTask: () => CacheResult<T>, template: IExtensionEditorTemplate): Promise<T> {
|
||||
addClass(template.content, 'loading');
|
||||
|
||||
const result = loadingTask();
|
||||
const onDone = () => removeClass(this.content, 'loading');
|
||||
const onDone = () => removeClass(template.content, 'loading');
|
||||
result.promise.then(onDone, onDone);
|
||||
|
||||
this.contentDisposables.add(toDisposable(() => result.dispose()));
|
||||
|
||||
@@ -3097,7 +3097,10 @@ interface IExtensionPickItem extends IQuickPickItem {
|
||||
|
||||
export class InstallLocalExtensionsInRemoteAction extends Action {
|
||||
|
||||
private extensions: IExtension[] | undefined = undefined;
|
||||
|
||||
constructor(
|
||||
private readonly selectAndInstall: boolean,
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
|
||||
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
|
||||
@@ -3109,32 +3112,56 @@ export class InstallLocalExtensionsInRemoteAction extends Action {
|
||||
) {
|
||||
super('workbench.extensions.actions.installLocalExtensionsInRemote');
|
||||
this.update();
|
||||
this._register(this.extensionsWorkbenchService.onChange(() => this.update()));
|
||||
this.extensionsWorkbenchService.queryLocal().then(() => this.updateExtensions());
|
||||
this._register(this.extensionsWorkbenchService.onChange(() => {
|
||||
if (this.extensions) {
|
||||
this.updateExtensions();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
get label(): string {
|
||||
return this.extensionManagementServerService.remoteExtensionManagementServer ?
|
||||
localize('install local extensions', "Install Local Extensions in {0}...", this.extensionManagementServerService.remoteExtensionManagementServer.label) : '';
|
||||
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
return this.selectAndInstall ?
|
||||
localize('select and install local extensions', "Install Local Extensions in {0}...", this.extensionManagementServerService.remoteExtensionManagementServer.label)
|
||||
: localize('install local extensions', "Install Local Extensions in {0}", this.extensionManagementServerService.remoteExtensionManagementServer.label);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
private updateExtensions(): void {
|
||||
this.extensions = this.extensionsWorkbenchService.local;
|
||||
this.update();
|
||||
}
|
||||
|
||||
private update(): void {
|
||||
this.enabled = this.getLocalExtensionsToInstall().length > 0;
|
||||
this.enabled = !!this.extensions && this.getExtensionsToInstall(this.extensions).length > 0;
|
||||
this.tooltip = this.label;
|
||||
}
|
||||
|
||||
private getLocalExtensionsToInstall(): IExtension[] {
|
||||
return this.extensionsWorkbenchService.local.filter(extension => {
|
||||
async run(): Promise<void> {
|
||||
if (this.selectAndInstall) {
|
||||
return this.selectAndInstallLocalExtensions();
|
||||
} else {
|
||||
const extensionsToInstall = await this.queryExtensionsToInstall();
|
||||
return this.installLocalExtensions(extensionsToInstall);
|
||||
}
|
||||
}
|
||||
|
||||
private async queryExtensionsToInstall(): Promise<IExtension[]> {
|
||||
const local = await this.extensionsWorkbenchService.queryLocal();
|
||||
return this.getExtensionsToInstall(local);
|
||||
}
|
||||
|
||||
private getExtensionsToInstall(local: IExtension[]): IExtension[] {
|
||||
return local.filter(extension => {
|
||||
const action = this.instantiationService.createInstance(RemoteInstallAction);
|
||||
action.extension = extension;
|
||||
return action.enabled;
|
||||
});
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
this.selectAndInstallLocalExtensions();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
private selectAndInstallLocalExtensions(): void {
|
||||
private async selectAndInstallLocalExtensions(): Promise<void> {
|
||||
const quickPick = this.quickInputService.createQuickPick<IExtensionPickItem>();
|
||||
quickPick.busy = true;
|
||||
const disposable = quickPick.onDidAccept(() => {
|
||||
@@ -3144,7 +3171,7 @@ export class InstallLocalExtensionsInRemoteAction extends Action {
|
||||
this.onDidAccept(quickPick.selectedItems);
|
||||
});
|
||||
quickPick.show();
|
||||
const localExtensionsToInstall = this.getLocalExtensionsToInstall();
|
||||
const localExtensionsToInstall = await this.queryExtensionsToInstall();
|
||||
quickPick.busy = false;
|
||||
if (localExtensionsToInstall.length) {
|
||||
quickPick.title = localize('install local extensions title', "Install Local Extensions in {0}", this.extensionManagementServerService.remoteExtensionManagementServer!.label);
|
||||
|
||||
@@ -156,7 +156,7 @@ export class UnknownExtensionRenderer implements IListRenderer<ITreeNode<IExtens
|
||||
|
||||
class OpenExtensionAction extends Action {
|
||||
|
||||
private _extensionData: IExtensionData;
|
||||
private _extensionData: IExtensionData | undefined;
|
||||
|
||||
constructor(@IExtensionsWorkbenchService private readonly extensionsWorkdbenchService: IExtensionsWorkbenchService) {
|
||||
super('extensions.action.openExtension', '');
|
||||
@@ -166,12 +166,11 @@ class OpenExtensionAction extends Action {
|
||||
this._extensionData = extension;
|
||||
}
|
||||
|
||||
public get extensionData(): IExtensionData {
|
||||
return this._extensionData;
|
||||
}
|
||||
|
||||
run(sideByside: boolean): Promise<any> {
|
||||
return this.extensionsWorkdbenchService.open(this.extensionData.extension, sideByside);
|
||||
if (this._extensionData) {
|
||||
return this.extensionsWorkdbenchService.open(this._extensionData.extension, sideByside);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,4 +262,4 @@ export class ExtensionData implements IExtensionData {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, AutoUpdate
|
||||
import {
|
||||
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowDisabledExtensionsAction,
|
||||
ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction,
|
||||
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction, InstallLocalExtensionsInRemoteAction
|
||||
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction
|
||||
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionEnablementService, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
@@ -323,7 +323,8 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
|
||||
|
||||
export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensionsViewlet {
|
||||
|
||||
private onSearchChange: EventOf<string>;
|
||||
private readonly _onSearchChange: Emitter<string> = this._register(new Emitter<string>());
|
||||
private readonly onSearchChange: EventOf<string> = this._onSearchChange.event;
|
||||
private nonEmptyWorkspaceContextKey: IContextKey<boolean>;
|
||||
private defaultViewsContextKey: IContextKey<boolean>;
|
||||
private searchMarketplaceExtensionsContextKey: IContextKey<boolean>;
|
||||
@@ -337,12 +338,10 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
private defaultRecommendedExtensionsContextKey: IContextKey<boolean>;
|
||||
|
||||
private searchDelayer: Delayer<void>;
|
||||
private root: HTMLElement;
|
||||
|
||||
private searchBox: SuggestEnabledInput;
|
||||
private extensionsBox: HTMLElement;
|
||||
private primaryActions: IAction[];
|
||||
private secondaryActions: IAction[] | null;
|
||||
private root: HTMLElement | undefined;
|
||||
private searchBox: SuggestEnabledInput | undefined;
|
||||
private primaryActions: IAction[] | undefined;
|
||||
private secondaryActions: IAction[] | null = null;
|
||||
private readonly searchViewletState: MementoObject;
|
||||
|
||||
constructor(
|
||||
@@ -352,7 +351,6 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@@ -422,32 +420,35 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
|
||||
this._register(attachSuggestEnabledInputBoxStyler(this.searchBox, this.themeService));
|
||||
|
||||
const _searchChange = new Emitter<string>();
|
||||
this.onSearchChange = _searchChange.event;
|
||||
this._register(this.searchBox.onInputDidChange(() => {
|
||||
this.triggerSearch();
|
||||
_searchChange.fire(this.searchBox.getValue());
|
||||
this._onSearchChange.fire(this.searchBox!.getValue());
|
||||
}, this));
|
||||
|
||||
this._register(this.searchBox.onShouldFocusResults(() => this.focusListView(), this));
|
||||
|
||||
this._register(this.onDidChangeVisibility(visible => {
|
||||
if (visible) {
|
||||
this.searchBox.focus();
|
||||
this.searchBox!.focus();
|
||||
}
|
||||
}));
|
||||
|
||||
this.extensionsBox = append(this.root, $('.extensions'));
|
||||
super.create(this.extensionsBox);
|
||||
super.create(append(this.root, $('.extensions')));
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
this.searchBox.focus();
|
||||
if (this.searchBox) {
|
||||
this.searchBox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): void {
|
||||
toggleClass(this.root, 'narrow', dimension.width <= 300);
|
||||
this.searchBox.layout({ height: 20, width: dimension.width - 34 });
|
||||
if (this.root) {
|
||||
toggleClass(this.root, 'narrow', dimension.width <= 300);
|
||||
}
|
||||
if (this.searchBox) {
|
||||
this.searchBox.layout({ height: 20, width: dimension.width - 34 });
|
||||
}
|
||||
super.layout(new Dimension(dimension.width, dimension.height - 38));
|
||||
}
|
||||
|
||||
@@ -458,7 +459,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
getActions(): IAction[] {
|
||||
if (!this.primaryActions) {
|
||||
this.primaryActions = [
|
||||
this.instantiationService.createInstance(ClearExtensionsInputAction, ClearExtensionsInputAction.ID, ClearExtensionsInputAction.LABEL, this.onSearchChange, this.searchBox.getValue())
|
||||
this.instantiationService.createInstance(ClearExtensionsInputAction, ClearExtensionsInputAction.ID, ClearExtensionsInputAction.LABEL, this.onSearchChange, this.searchBox ? this.searchBox.getValue() : '')
|
||||
];
|
||||
}
|
||||
return this.primaryActions;
|
||||
@@ -484,7 +485,6 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
this.instantiationService.createInstance(CheckForUpdatesAction, CheckForUpdatesAction.ID, CheckForUpdatesAction.LABEL),
|
||||
...(this.configurationService.getValue(AutoUpdateConfigurationKey) ? [this.instantiationService.createInstance(DisableAutoUpdateAction, DisableAutoUpdateAction.ID, DisableAutoUpdateAction.LABEL)] : [this.instantiationService.createInstance(UpdateAllAction, UpdateAllAction.ID, UpdateAllAction.LABEL), this.instantiationService.createInstance(EnableAutoUpdateAction, EnableAutoUpdateAction.ID, EnableAutoUpdateAction.LABEL)]),
|
||||
this.instantiationService.createInstance(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL),
|
||||
...(this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer ? [this.instantiationService.createInstance(InstallLocalExtensionsInRemoteAction)] : []),
|
||||
new Separator(),
|
||||
this.instantiationService.createInstance(DisableAllAction, DisableAllAction.ID, DisableAllAction.LABEL),
|
||||
this.instantiationService.createInstance(EnableAllAction, EnableAllAction.ID, EnableAllAction.LABEL)
|
||||
@@ -495,22 +495,24 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
}
|
||||
|
||||
search(value: string): void {
|
||||
const event = new Event('input', { bubbles: true }) as SearchInputEvent;
|
||||
event.immediate = true;
|
||||
if (this.searchBox) {
|
||||
const event = new Event('input', { bubbles: true }) as SearchInputEvent;
|
||||
event.immediate = true;
|
||||
|
||||
this.searchBox.setValue(value);
|
||||
this.searchBox.setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
private triggerSearch(immediate = false): void {
|
||||
this.searchDelayer.trigger(() => this.doSearch(), immediate || !this.searchBox.getValue() ? 0 : 500).then(undefined, err => this.onError(err));
|
||||
private triggerSearch(): void {
|
||||
this.searchDelayer.trigger(() => this.doSearch(), this.searchBox && this.searchBox.getValue() ? 500 : 0).then(undefined, err => this.onError(err));
|
||||
}
|
||||
|
||||
private normalizedQuery(): string {
|
||||
return this.searchBox.getValue().replace(/@category/g, 'category').replace(/@tag:/g, 'tag:').replace(/@ext:/g, 'ext:');
|
||||
return this.searchBox ? this.searchBox.getValue().replace(/@category/g, 'category').replace(/@tag:/g, 'tag:').replace(/@ext:/g, 'ext:') : '';
|
||||
}
|
||||
|
||||
protected saveState(): void {
|
||||
const value = this.searchBox.getValue();
|
||||
const value = this.searchBox ? this.searchBox.getValue() : '';
|
||||
if (ExtensionsListView.isLocalExtensionsQuery(value)) {
|
||||
this.searchViewletState['query.value'] = value;
|
||||
} else {
|
||||
|
||||
@@ -14,11 +14,11 @@ import { IExtensionManagementServer, IExtensionManagementServerService, IExtensi
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { append, $, toggleClass } from 'vs/base/browser/dom';
|
||||
import { append, $, toggleClass, addClass } from 'vs/base/browser/dom';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Delegate, Renderer, IExtensionsViewState } from 'vs/workbench/contrib/extensions/browser/extensionsList';
|
||||
import { IExtension, IExtensionsWorkbenchService, ExtensionState } from '../common/extensions';
|
||||
import { Query } from '../common/extensionQuery';
|
||||
import { IExtension, IExtensionsWorkbenchService, ExtensionState } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { attachBadgeStyler } from 'vs/platform/theme/common/styler';
|
||||
@@ -27,8 +27,8 @@ import { OpenGlobalSettingsAction } from 'vs/workbench/contrib/preferences/brows
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
||||
import { ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, ManageExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, ManageExtensionAction, InstallLocalExtensionsInRemoteAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { WorkbenchPagedList } from 'vs/platform/list/browser/listService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
@@ -74,15 +74,16 @@ class ExtensionListViewWarning extends Error { }
|
||||
|
||||
export class ExtensionsListView extends ViewletPanel {
|
||||
|
||||
private readonly server: IExtensionManagementServer | undefined;
|
||||
private messageContainer: HTMLElement;
|
||||
private messageSeverityIcon: HTMLElement;
|
||||
private messageBox: HTMLElement;
|
||||
private extensionsList: HTMLElement;
|
||||
private badge: CountBadge;
|
||||
protected badgeContainer: HTMLElement;
|
||||
private list: WorkbenchPagedList<IExtension> | null;
|
||||
private queryRequest: { query: string, request: CancelablePromise<IPagedModel<IExtension>> } | null;
|
||||
protected readonly server: IExtensionManagementServer | undefined;
|
||||
private bodyTemplate: {
|
||||
messageContainer: HTMLElement;
|
||||
messageSeverityIcon: HTMLElement;
|
||||
messageBox: HTMLElement;
|
||||
extensionsList: HTMLElement;
|
||||
} | undefined;
|
||||
private badge: CountBadge | undefined;
|
||||
private list: WorkbenchPagedList<IExtension> | null = null;
|
||||
private queryRequest: { query: string, request: CancelablePromise<IPagedModel<IExtension>> } | null = null;
|
||||
|
||||
constructor(
|
||||
options: ExtensionsListViewOptions,
|
||||
@@ -104,31 +105,27 @@ export class ExtensionsListView extends ViewletPanel {
|
||||
@IProductService protected readonly productService: IProductService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
) {
|
||||
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService);
|
||||
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: options.title, showActionsAlways: true }, keybindingService, contextMenuService, configurationService, contextKeyService);
|
||||
this.server = options.server;
|
||||
}
|
||||
|
||||
protected renderHeader(container: HTMLElement): void {
|
||||
this.renderHeaderTitle(container);
|
||||
}
|
||||
addClass(container, 'extension-view-header');
|
||||
super.renderHeader(container);
|
||||
|
||||
renderHeaderTitle(container: HTMLElement): void {
|
||||
super.renderHeaderTitle(container, this.title);
|
||||
|
||||
this.badgeContainer = append(container, $('.count-badge-wrapper'));
|
||||
this.badge = new CountBadge(this.badgeContainer);
|
||||
this.badge = new CountBadge(append(container, $('.count-badge-wrapper')));
|
||||
this._register(attachBadgeStyler(this.badge, this.themeService));
|
||||
}
|
||||
|
||||
renderBody(container: HTMLElement): void {
|
||||
this.extensionsList = append(container, $('.extensions-list'));
|
||||
this.messageContainer = append(container, $('.message-container'));
|
||||
this.messageSeverityIcon = append(this.messageContainer, $(''));
|
||||
this.messageBox = append(this.messageContainer, $('.message'));
|
||||
const extensionsList = append(container, $('.extensions-list'));
|
||||
const messageContainer = append(container, $('.message-container'));
|
||||
const messageSeverityIcon = append(messageContainer, $(''));
|
||||
const messageBox = append(messageContainer, $('.message'));
|
||||
const delegate = new Delegate();
|
||||
const extensionsViewState = new ExtensionsViewState();
|
||||
const renderer = this.instantiationService.createInstance(Renderer, extensionsViewState);
|
||||
this.list = this.instantiationService.createInstance(WorkbenchPagedList, this.extensionsList, delegate, [renderer], {
|
||||
this.list = this.instantiationService.createInstance(WorkbenchPagedList, extensionsList, delegate, [renderer], {
|
||||
ariaLabel: localize('extensions', "Extensions"),
|
||||
multipleSelectionSupport: false,
|
||||
setRowLineHeight: false,
|
||||
@@ -148,10 +145,19 @@ export class ExtensionsListView extends ViewletPanel {
|
||||
.map(e => e.elements[0])
|
||||
.filter(e => !!e)
|
||||
.on(this.pin, this));
|
||||
|
||||
this.bodyTemplate = {
|
||||
extensionsList,
|
||||
messageBox,
|
||||
messageContainer,
|
||||
messageSeverityIcon
|
||||
};
|
||||
}
|
||||
|
||||
protected layoutBody(height: number, width: number): void {
|
||||
this.extensionsList.style.height = height + 'px';
|
||||
if (this.bodyTemplate) {
|
||||
this.bodyTemplate.extensionsList.style.height = height + 'px';
|
||||
}
|
||||
if (this.list) {
|
||||
this.list.layout(height, width);
|
||||
}
|
||||
@@ -501,7 +507,7 @@ export class ExtensionsListView extends ViewletPanel {
|
||||
|
||||
}
|
||||
|
||||
private _searchExperiments: Promise<IExperiment[]>;
|
||||
private _searchExperiments: Promise<IExperiment[]> | undefined;
|
||||
private getSearchExperiments(): Promise<IExperiment[]> {
|
||||
if (!this._searchExperiments) {
|
||||
this._searchExperiments = this.experimentService.getExperimentsByType(ExperimentActionType.ExtensionSearchResults);
|
||||
@@ -773,24 +779,27 @@ export class ExtensionsListView extends ViewletPanel {
|
||||
this.list.scrollTop = 0;
|
||||
const count = this.count();
|
||||
|
||||
toggleClass(this.extensionsList, 'hidden', count === 0);
|
||||
toggleClass(this.messageContainer, 'hidden', count > 0);
|
||||
this.badge.setCount(count);
|
||||
if (this.bodyTemplate && this.badge) {
|
||||
|
||||
if (count === 0 && this.isBodyVisible()) {
|
||||
if (error) {
|
||||
if (error instanceof ExtensionListViewWarning) {
|
||||
this.messageSeverityIcon.className = SeverityIcon.className(Severity.Warning);
|
||||
this.messageBox.textContent = getErrorMessage(error);
|
||||
toggleClass(this.bodyTemplate.extensionsList, 'hidden', count === 0);
|
||||
toggleClass(this.bodyTemplate.messageContainer, 'hidden', count > 0);
|
||||
this.badge.setCount(count);
|
||||
|
||||
if (count === 0 && this.isBodyVisible()) {
|
||||
if (error) {
|
||||
if (error instanceof ExtensionListViewWarning) {
|
||||
this.bodyTemplate.messageSeverityIcon.className = SeverityIcon.className(Severity.Warning);
|
||||
this.bodyTemplate.messageBox.textContent = getErrorMessage(error);
|
||||
} else {
|
||||
this.bodyTemplate.messageSeverityIcon.className = SeverityIcon.className(Severity.Error);
|
||||
this.bodyTemplate.messageBox.textContent = localize('error', "Error while loading extensions. {0}", getErrorMessage(error));
|
||||
}
|
||||
} else {
|
||||
this.messageSeverityIcon.className = SeverityIcon.className(Severity.Error);
|
||||
this.messageBox.textContent = localize('error', "Error while loading extensions. {0}", getErrorMessage(error));
|
||||
this.bodyTemplate.messageSeverityIcon.className = '';
|
||||
this.bodyTemplate.messageBox.textContent = localize('no extensions found', "No extensions found.");
|
||||
}
|
||||
} else {
|
||||
this.messageSeverityIcon.className = '';
|
||||
this.messageBox.textContent = localize('no extensions found', "No extensions found.");
|
||||
alert(this.bodyTemplate.messageBox.textContent);
|
||||
}
|
||||
alert(this.messageBox.textContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -949,6 +958,15 @@ export class ServerExtensionsView extends ExtensionsListView {
|
||||
}
|
||||
return super.show(query.trim());
|
||||
}
|
||||
|
||||
getActions(): IAction[] {
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer === this.server) {
|
||||
const installLocalExtensionsInRemoteAction = this._register(this.instantiationService.createInstance(InstallLocalExtensionsInRemoteAction, false));
|
||||
installLocalExtensionsInRemoteAction.class = 'octicon octicon-cloud-download';
|
||||
return [installLocalExtensionsInRemoteAction];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export class EnabledExtensionsView extends ExtensionsListView {
|
||||
@@ -1030,7 +1048,7 @@ export class RecommendedExtensionsView extends ExtensionsListView {
|
||||
|
||||
export class WorkspaceRecommendedExtensionsView extends ExtensionsListView {
|
||||
private readonly recommendedExtensionsQuery = '@recommended:workspace';
|
||||
private installAllAction: InstallWorkspaceRecommendedExtensionsAction;
|
||||
private installAllAction: InstallWorkspaceRecommendedExtensionsAction | undefined;
|
||||
|
||||
renderBody(container: HTMLElement): void {
|
||||
super.renderBody(container);
|
||||
@@ -1040,25 +1058,15 @@ export class WorkspaceRecommendedExtensionsView extends ExtensionsListView {
|
||||
this._register(this.contextService.onDidChangeWorkbenchState(() => this.update()));
|
||||
}
|
||||
|
||||
renderHeader(container: HTMLElement): void {
|
||||
super.renderHeader(container);
|
||||
getActions(): IAction[] {
|
||||
if (!this.installAllAction) {
|
||||
this.installAllAction = this._register(this.instantiationService.createInstance(InstallWorkspaceRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction.ID, InstallWorkspaceRecommendedExtensionsAction.LABEL, []));
|
||||
this.installAllAction.class = 'octicon octicon-cloud-download';
|
||||
}
|
||||
|
||||
const listActionBar = $('.list-actionbar-container');
|
||||
container.insertBefore(listActionBar, this.badgeContainer);
|
||||
|
||||
const actionbar = this._register(new ActionBar(listActionBar, {
|
||||
animated: false
|
||||
}));
|
||||
actionbar.onDidRun(({ error }) => error && this.notificationService.error(error));
|
||||
|
||||
this.installAllAction = this._register(this.instantiationService.createInstance(InstallWorkspaceRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction.ID, InstallWorkspaceRecommendedExtensionsAction.LABEL, []));
|
||||
const configureWorkspaceFolderAction = this._register(this.instantiationService.createInstance(ConfigureWorkspaceFolderRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction.ID, ConfigureWorkspaceFolderRecommendedExtensionsAction.LABEL));
|
||||
|
||||
this.installAllAction.class = 'octicon octicon-cloud-download';
|
||||
configureWorkspaceFolderAction.class = 'octicon octicon-pencil';
|
||||
|
||||
actionbar.push([this.installAllAction], { icon: true, label: false });
|
||||
actionbar.push([configureWorkspaceFolderAction], { icon: true, label: false });
|
||||
return [this.installAllAction, configureWorkspaceFolderAction];
|
||||
}
|
||||
|
||||
async show(query: string): Promise<IPagedModel<IExtension>> {
|
||||
@@ -1073,9 +1081,11 @@ export class WorkspaceRecommendedExtensionsView extends ExtensionsListView {
|
||||
this.setRecommendationsToInstall();
|
||||
}
|
||||
|
||||
private setRecommendationsToInstall(): Promise<void> {
|
||||
return this.getRecommendationsToInstall()
|
||||
.then(recommendations => { this.installAllAction.recommendations = recommendations; });
|
||||
private async setRecommendationsToInstall(): Promise<void> {
|
||||
const recommendations = await this.getRecommendationsToInstall();
|
||||
if (this.installAllAction) {
|
||||
this.installAllAction.recommendations = recommendations;
|
||||
}
|
||||
}
|
||||
|
||||
private getRecommendationsToInstall(): Promise<IExtensionRecommendation[]> {
|
||||
|
||||
@@ -18,9 +18,9 @@ import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export abstract class ExtensionWidget extends Disposable implements IExtensionContainer {
|
||||
private _extension: IExtension;
|
||||
get extension(): IExtension { return this._extension; }
|
||||
set extension(extension: IExtension) { this._extension = extension; this.update(); }
|
||||
private _extension: IExtension | null = null;
|
||||
get extension(): IExtension | null { return this._extension; }
|
||||
set extension(extension: IExtension | null) { this._extension = extension; this.update(); }
|
||||
update(): void { this.render(); }
|
||||
abstract render(): void;
|
||||
}
|
||||
@@ -183,7 +183,7 @@ export class RecommendationWidget extends ExtensionWidget {
|
||||
private element?: HTMLElement;
|
||||
private readonly disposables = this._register(new DisposableStore());
|
||||
|
||||
private _tooltip: string;
|
||||
private _tooltip: string = '';
|
||||
get tooltip(): string { return this._tooltip; }
|
||||
set tooltip(tooltip: string) {
|
||||
if (this._tooltip !== tooltip) {
|
||||
@@ -314,4 +314,4 @@ class RemoteBadge extends Disposable {
|
||||
updateTitle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
|
||||
private readonly _onChange: Emitter<IExtension | undefined> = new Emitter<IExtension | undefined>();
|
||||
get onChange(): Event<IExtension | undefined> { return this._onChange.event; }
|
||||
|
||||
private _extensionAllowedBadgeProviders: string[];
|
||||
private _extensionAllowedBadgeProviders: string[] | undefined;
|
||||
private installing: IExtension[] = [];
|
||||
|
||||
constructor(
|
||||
@@ -1151,12 +1151,12 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
|
||||
}
|
||||
|
||||
|
||||
private _ignoredAutoUpdateExtensions: string[];
|
||||
private _ignoredAutoUpdateExtensions: string[] | undefined;
|
||||
private get ignoredAutoUpdateExtensions(): string[] {
|
||||
if (!this._ignoredAutoUpdateExtensions) {
|
||||
this._ignoredAutoUpdateExtensions = JSON.parse(this.storageService.get('extensions.ignoredAutoUpdateExtension', StorageScope.GLOBAL, '[]') || '[]');
|
||||
}
|
||||
return this._ignoredAutoUpdateExtensions;
|
||||
return this._ignoredAutoUpdateExtensions!;
|
||||
}
|
||||
|
||||
private set ignoredAutoUpdateExtensions(extensionIds: string[]) {
|
||||
|
||||
@@ -6,8 +6,3 @@
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-label.extensions {
|
||||
-webkit-mask: url('extensions-activity-bar.svg') no-repeat 50% 50%;
|
||||
}
|
||||
|
||||
.extensions .split-view-view .panel-header .count-badge-wrapper {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
}
|
||||
@@ -27,13 +27,16 @@
|
||||
height: calc(100% - 38px);
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .list-actionbar-container .monaco-action-bar .action-item > .octicon {
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
margin-right: 10px;
|
||||
.extensions-viewlet > .extensions .extension-view-header .monaco-action-bar {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .list-actionbar-container .monaco-action-bar .action-item.disabled {
|
||||
.extensions-viewlet > .extensions .extension-view-header .monaco-action-bar .action-item > .action-label.icon.octicon {
|
||||
vertical-align: middle;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension-view-header .monaco-action-bar .action-item.disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -44,7 +47,7 @@
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .panel-header {
|
||||
padding-right: 28px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .panel-header > .title {
|
||||
|
||||
@@ -22,7 +22,7 @@ export class RemoteExtensionsInstaller extends Disposable implements IWorkbenchC
|
||||
) {
|
||||
super();
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
const installLocalExtensionsInRemoteAction = instantiationService.createInstance(InstallLocalExtensionsInRemoteAction);
|
||||
const installLocalExtensionsInRemoteAction = instantiationService.createInstance(InstallLocalExtensionsInRemoteAction, true);
|
||||
CommandsRegistry.registerCommand('workbench.extensions.installLocalExtensions', () => installLocalExtensionsInRemoteAction.run());
|
||||
let disposable = Disposable.None;
|
||||
const appendMenuItem = () => {
|
||||
|
||||
@@ -44,7 +44,7 @@ import { CLOSE_EDITORS_AND_GROUP_COMMAND_ID } from 'vs/workbench/browser/parts/e
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { AsyncDataTree } from 'vs/base/browser/ui/tree/asyncDataTree';
|
||||
import { ExplorerItem, NewExplorerItem } from 'vs/workbench/contrib/files/common/explorerModel';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { onUnexpectedError, getErrorMessage } from 'vs/base/common/errors';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
||||
@@ -1140,7 +1140,7 @@ export const pasteFileHandler = async (accessor: ServicesAccessor) => {
|
||||
return await fileService.copy(fileToPaste, targetFile);
|
||||
}
|
||||
} catch (e) {
|
||||
onError(notificationService, new Error(nls.localize('fileDeleted', "File to paste was deleted or moved meanwhile")));
|
||||
onError(notificationService, new Error(nls.localize('fileDeleted', "File to paste was deleted or moved meanwhile. {0}", getErrorMessage(e))));
|
||||
return undefined;
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -14,14 +14,11 @@ import { EditorOptions } from 'vs/workbench/common/editor';
|
||||
import { IOutputChannelDescriptor, IOutputChannel, IOutputService, Extensions, OUTPUT_PANEL_ID, IOutputChannelRegistry, OUTPUT_SCHEME, LOG_SCHEME, CONTEXT_ACTIVE_LOG_OUTPUT, LOG_MIME, OUTPUT_MIME } from 'vs/workbench/contrib/output/common/output';
|
||||
import { OutputPanel } from 'vs/workbench/contrib/output/browser/outputPanel';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { OutputLinkProvider } from 'vs/workbench/contrib/output/common/outputLinkProvider';
|
||||
import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/services/resolverService';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IPanel } from 'vs/workbench/common/panel';
|
||||
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
@@ -77,10 +74,7 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IPanelService private readonly panelService: IPanelService,
|
||||
@IWorkspaceContextService contextService: IWorkspaceContextService,
|
||||
@ITextModelService textModelResolverService: ITextModelService,
|
||||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
@IWindowService windowService: IWindowService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
|
||||
@@ -854,7 +854,7 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
|
||||
this._register(model.onDidChangeGroups(() => this.onConfigUpdate()));
|
||||
this.defaultSettingsEditorModel = model;
|
||||
return this.onConfigUpdate();
|
||||
return this.onConfigUpdate(undefined, true);
|
||||
});
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
|
||||
@@ -36,7 +36,8 @@ export class LabelContribution implements IWorkbenchContribution {
|
||||
formatting: {
|
||||
label: '${path}',
|
||||
separator: remoteEnvironment.os === OperatingSystem.Windows ? '\\' : '/',
|
||||
tildify: remoteEnvironment.os !== OperatingSystem.Windows
|
||||
tildify: remoteEnvironment.os !== OperatingSystem.Windows,
|
||||
normalizeDriveLetter: remoteEnvironment.os === OperatingSystem.Windows
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -179,10 +179,10 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
|
||||
|
||||
private static nextHandle: number = 0;
|
||||
|
||||
private _schemaVersion: JsonSchemaVersion;
|
||||
private _executionEngine: ExecutionEngine;
|
||||
private _workspaceFolders: IWorkspaceFolder[];
|
||||
private _ignoredWorkspaceFolders: IWorkspaceFolder[];
|
||||
private _schemaVersion: JsonSchemaVersion | undefined;
|
||||
private _executionEngine: ExecutionEngine | undefined;
|
||||
private _workspaceFolders: IWorkspaceFolder[] | undefined;
|
||||
private _ignoredWorkspaceFolders: IWorkspaceFolder[] | undefined;
|
||||
private _showIgnoreMessage?: boolean;
|
||||
private _providers: Map<number, ITaskProvider>;
|
||||
private _providerTypes: Map<number, string>;
|
||||
@@ -192,7 +192,7 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
|
||||
|
||||
protected _taskSystem?: ITaskSystem;
|
||||
protected _taskSystemListener?: IDisposable;
|
||||
private _recentlyUsedTasks: LinkedMap<string, string>;
|
||||
private _recentlyUsedTasks: LinkedMap<string, string> | undefined;
|
||||
|
||||
protected _taskRunningState: IContextKey<boolean>;
|
||||
|
||||
@@ -375,28 +375,28 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
|
||||
if (!this._workspaceFolders) {
|
||||
this.updateSetup();
|
||||
}
|
||||
return this._workspaceFolders;
|
||||
return this._workspaceFolders!;
|
||||
}
|
||||
|
||||
private get ignoredWorkspaceFolders(): IWorkspaceFolder[] {
|
||||
if (!this._ignoredWorkspaceFolders) {
|
||||
this.updateSetup();
|
||||
}
|
||||
return this._ignoredWorkspaceFolders;
|
||||
return this._ignoredWorkspaceFolders!;
|
||||
}
|
||||
|
||||
protected get executionEngine(): ExecutionEngine {
|
||||
if (this._executionEngine === undefined) {
|
||||
this.updateSetup();
|
||||
}
|
||||
return this._executionEngine;
|
||||
return this._executionEngine!;
|
||||
}
|
||||
|
||||
private get schemaVersion(): JsonSchemaVersion {
|
||||
if (this._schemaVersion === undefined) {
|
||||
this.updateSetup();
|
||||
}
|
||||
return this._schemaVersion;
|
||||
return this._schemaVersion!;
|
||||
}
|
||||
|
||||
private get showIgnoreMessage(): boolean {
|
||||
|
||||
@@ -155,9 +155,10 @@ export class TerminalTaskSystem implements ITaskSystem {
|
||||
private idleTaskTerminals: LinkedMap<string, string>;
|
||||
private sameTaskTerminals: IStringDictionary<string>;
|
||||
private taskSystemInfoResolver: TaskSystemInfoResolver;
|
||||
private lastTask: VerifiedTask;
|
||||
private currentTask: VerifiedTask;
|
||||
private isRerun: boolean;
|
||||
private lastTask: VerifiedTask | undefined;
|
||||
// Should always be set in run
|
||||
private currentTask!: VerifiedTask;
|
||||
private isRerun: boolean = false;
|
||||
|
||||
private readonly _onDidStateChange: Emitter<TaskEvent>;
|
||||
|
||||
@@ -485,28 +486,32 @@ export class TerminalTaskSystem implements ITaskSystem {
|
||||
}
|
||||
|
||||
private reexecuteCommand(task: CustomTask | ContributedTask, trigger: string): Promise<ITaskSummary> {
|
||||
const workspaceFolder = this.currentTask.workspaceFolder = this.lastTask.workspaceFolder;
|
||||
const lastTask = this.lastTask;
|
||||
if (!lastTask) {
|
||||
return Promise.reject(new Error('No task previously run'));
|
||||
}
|
||||
const workspaceFolder = this.currentTask.workspaceFolder = lastTask.workspaceFolder;
|
||||
let variables = new Set<string>();
|
||||
this.collectTaskVariables(variables, task);
|
||||
|
||||
// Check that the task hasn't changed to include new variables
|
||||
let hasAllVariables = true;
|
||||
variables.forEach(value => {
|
||||
if (value.substring(2, value.length - 1) in this.lastTask.getVerifiedTask().resolvedVariables) {
|
||||
if (value.substring(2, value.length - 1) in lastTask.getVerifiedTask().resolvedVariables) {
|
||||
hasAllVariables = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!hasAllVariables) {
|
||||
return this.resolveVariablesFromSet(this.lastTask.getVerifiedTask().systemInfo, this.lastTask.getVerifiedTask().workspaceFolder, task, variables).then((resolvedVariables) => {
|
||||
return this.resolveVariablesFromSet(lastTask.getVerifiedTask().systemInfo, lastTask.getVerifiedTask().workspaceFolder, task, variables).then((resolvedVariables) => {
|
||||
this.currentTask.resolvedVariables = resolvedVariables;
|
||||
return this.executeInTerminal(task, trigger, new VariableResolver(this.lastTask.getVerifiedTask().workspaceFolder, this.lastTask.getVerifiedTask().systemInfo, resolvedVariables.variables, this.configurationResolverService), workspaceFolder!);
|
||||
return this.executeInTerminal(task, trigger, new VariableResolver(lastTask.getVerifiedTask().workspaceFolder, lastTask.getVerifiedTask().systemInfo, resolvedVariables.variables, this.configurationResolverService), workspaceFolder!);
|
||||
}, reason => {
|
||||
return Promise.reject(reason);
|
||||
});
|
||||
} else {
|
||||
this.currentTask.resolvedVariables = this.lastTask.getVerifiedTask().resolvedVariables;
|
||||
return this.executeInTerminal(task, trigger, new VariableResolver(this.lastTask.getVerifiedTask().workspaceFolder, this.lastTask.getVerifiedTask().systemInfo, this.lastTask.getVerifiedTask().resolvedVariables.variables, this.configurationResolverService), workspaceFolder!);
|
||||
this.currentTask.resolvedVariables = lastTask.getVerifiedTask().resolvedVariables;
|
||||
return this.executeInTerminal(task, trigger, new VariableResolver(lastTask.getVerifiedTask().workspaceFolder, lastTask.getVerifiedTask().systemInfo, lastTask.getVerifiedTask().resolvedVariables.variables, this.configurationResolverService), workspaceFolder!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -923,7 +928,7 @@ export class TerminalTaskSystem implements ITaskSystem {
|
||||
args = resolvedResult.args;
|
||||
commandExecutable = CommandString.value(command);
|
||||
|
||||
this.currentTask.shellLaunchConfig = launchConfigs = this.isRerun ? this.lastTask.getVerifiedTask().shellLaunchConfig : await this.createShellLaunchConfig(task, workspaceFolder, resolver, platform, options, command, args, waitOnExit);
|
||||
this.currentTask.shellLaunchConfig = launchConfigs = (this.isRerun && this.lastTask) ? this.lastTask.getVerifiedTask().shellLaunchConfig : await this.createShellLaunchConfig(task, workspaceFolder, resolver, platform, options, command, args, waitOnExit);
|
||||
if (launchConfigs === undefined) {
|
||||
return [undefined, undefined, new TaskError(Severity.Error, nls.localize('TerminalTaskSystem', 'Can\'t execute a shell command on an UNC drive using cmd.exe.'), TaskErrors.UnknownError)];
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@ export abstract class AbstractProblemCollector implements IDisposable {
|
||||
private bufferLength: number;
|
||||
private openModels: IStringDictionary<boolean>;
|
||||
private readonly modelListeners = new DisposableStore();
|
||||
private tail: Promise<void>;
|
||||
private tail: Promise<void> | undefined;
|
||||
|
||||
// [owner] -> ApplyToKind
|
||||
private applyToByOwner: Map<string, ApplyToKind>;
|
||||
protected applyToByOwner: Map<string, ApplyToKind>;
|
||||
// [owner] -> [resource] -> URI
|
||||
private resourcesToClean: Map<string, Map<string, URI>>;
|
||||
// [owner] -> [resource] -> [markerkey] -> markerData
|
||||
@@ -278,9 +278,14 @@ export abstract class AbstractProblemCollector implements IDisposable {
|
||||
markersPerResource = new Map<string, IMarkerData>();
|
||||
markersPerOwner.set(resourceAsString, markersPerResource);
|
||||
}
|
||||
let key = IMarkerData.makeKey(marker);
|
||||
let key = IMarkerData.makeKeyOptionalMessage(marker, false);
|
||||
let existingMarker;
|
||||
if (!markersPerResource.has(key)) {
|
||||
markersPerResource.set(key, marker);
|
||||
} else if (((existingMarker = markersPerResource.get(key)) !== undefined) && existingMarker.message.length < marker.message.length) {
|
||||
// Most likely https://github.com/microsoft/vscode/issues/77475
|
||||
// Heuristic dictates that when the key is the same and message is smaller, we have hit this limitation.
|
||||
markersPerResource.set(key, marker);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,8 +349,8 @@ export const enum ProblemHandlingStrategy {
|
||||
export class StartStopProblemCollector extends AbstractProblemCollector implements IProblemMatcher {
|
||||
private owners: string[];
|
||||
|
||||
private currentOwner: string;
|
||||
private currentResource: string;
|
||||
private currentOwner: string | undefined;
|
||||
private currentResource: string | undefined;
|
||||
|
||||
constructor(problemMatchers: ProblemMatcher[], markerService: IMarkerService, modelService: IModelService, _strategy: ProblemHandlingStrategy = ProblemHandlingStrategy.Clean, fileService?: IFileService) {
|
||||
super(problemMatchers, markerService, modelService, fileService);
|
||||
@@ -397,8 +402,8 @@ export class WatchingProblemCollector extends AbstractProblemCollector implement
|
||||
private _activeBackgroundMatchers: Set<string>;
|
||||
|
||||
// Current State
|
||||
private currentOwner: string | null;
|
||||
private currentResource: string | null;
|
||||
private currentOwner: string | undefined;
|
||||
private currentResource: string | undefined;
|
||||
|
||||
constructor(problemMatchers: ProblemMatcher[], markerService: IMarkerService, modelService: IModelService, fileService?: IFileService) {
|
||||
super(problemMatchers, markerService, modelService, fileService);
|
||||
@@ -503,8 +508,8 @@ export class WatchingProblemCollector extends AbstractProblemCollector implement
|
||||
|
||||
private resetCurrentResource(): void {
|
||||
this.reportMarkersForCurrentResource();
|
||||
this.currentOwner = null;
|
||||
this.currentResource = null;
|
||||
this.currentOwner = undefined;
|
||||
this.currentResource = undefined;
|
||||
}
|
||||
|
||||
private reportMarkersForCurrentResource(): void {
|
||||
@@ -512,4 +517,11 @@ export class WatchingProblemCollector extends AbstractProblemCollector implement
|
||||
this.deliverMarkersPerOwnerAndResource(this.currentOwner, this.currentResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public done(): void {
|
||||
[...this.applyToByOwner.keys()].forEach(owner => {
|
||||
this.recordResourcesToClean(owner);
|
||||
});
|
||||
super.done();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ abstract class AbstractLineMatcher implements ILineMatcher {
|
||||
|
||||
public abstract get matchLength(): number;
|
||||
|
||||
protected fillProblemData(data: ProblemData | null, pattern: ProblemPattern, matches: RegExpExecArray): data is ProblemData {
|
||||
protected fillProblemData(data: ProblemData | undefined, pattern: ProblemPattern, matches: RegExpExecArray): data is ProblemData {
|
||||
if (data) {
|
||||
this.fillProperty(data, 'file', pattern, matches, true);
|
||||
this.appendProperty(data, 'message', pattern, matches, true);
|
||||
@@ -449,7 +449,7 @@ class SingleLineMatcher extends AbstractLineMatcher {
|
||||
class MultiLineMatcher extends AbstractLineMatcher {
|
||||
|
||||
private patterns: ProblemPattern[];
|
||||
private data: ProblemData | null;
|
||||
private data: ProblemData | undefined;
|
||||
|
||||
constructor(matcher: ProblemMatcher, fileService?: IFileService) {
|
||||
super(matcher, fileService);
|
||||
@@ -480,7 +480,7 @@ class MultiLineMatcher extends AbstractLineMatcher {
|
||||
}
|
||||
let loop = !!this.patterns[this.patterns.length - 1].loop;
|
||||
if (!loop) {
|
||||
this.data = null;
|
||||
this.data = undefined;
|
||||
}
|
||||
const markerMatch = data ? this.getMarkerMatch(data) : null;
|
||||
return { match: markerMatch ? markerMatch : null, continue: loop };
|
||||
@@ -491,7 +491,7 @@ class MultiLineMatcher extends AbstractLineMatcher {
|
||||
Assert.ok(pattern.loop === true && this.data !== null);
|
||||
let matches = pattern.regexp.exec(line);
|
||||
if (!matches) {
|
||||
this.data = null;
|
||||
this.data = undefined;
|
||||
return null;
|
||||
}
|
||||
let data = Objects.deepClone(this.data);
|
||||
@@ -794,7 +794,7 @@ export namespace Config {
|
||||
fileLocation?: string | string[];
|
||||
|
||||
/**
|
||||
* The name of a predefined problem pattern, the inline definintion
|
||||
* The name of a predefined problem pattern, the inline definition
|
||||
* of a problem pattern or an array of problem patterns to match
|
||||
* problems spread over multiple lines.
|
||||
*/
|
||||
|
||||
@@ -681,7 +681,7 @@ export namespace RunOptions {
|
||||
}
|
||||
}
|
||||
|
||||
class ParseContext {
|
||||
interface ParseContext {
|
||||
workspaceFolder: IWorkspaceFolder;
|
||||
problemReporter: IProblemReporter;
|
||||
namedProblemMatchers: IStringDictionary<NamedProblemMatcher>;
|
||||
|
||||
@@ -89,7 +89,7 @@ class TaskDefinitionRegistryImpl implements ITaskDefinitionRegistry {
|
||||
|
||||
private taskTypes: IStringDictionary<Tasks.TaskDefinition>;
|
||||
private readyPromise: Promise<void>;
|
||||
private _schema: IJSONSchema;
|
||||
private _schema: IJSONSchema | undefined;
|
||||
|
||||
constructor() {
|
||||
this.taskTypes = Object.create(null);
|
||||
|
||||
@@ -518,7 +518,7 @@ export abstract class CommonTask {
|
||||
/**
|
||||
* The cached label.
|
||||
*/
|
||||
_label: string;
|
||||
_label: string = '';
|
||||
|
||||
type?: string;
|
||||
|
||||
@@ -614,7 +614,7 @@ export abstract class CommonTask {
|
||||
|
||||
export class CustomTask extends CommonTask {
|
||||
|
||||
type: '$customized'; // CUSTOMIZED_TASK_TYPE
|
||||
type!: '$customized'; // CUSTOMIZED_TASK_TYPE
|
||||
|
||||
/**
|
||||
* Indicated the source of the task (e.g. tasks.json or extension)
|
||||
@@ -626,7 +626,7 @@ export class CustomTask extends CommonTask {
|
||||
/**
|
||||
* The command configuration
|
||||
*/
|
||||
command: CommandConfiguration;
|
||||
command: CommandConfiguration = {};
|
||||
|
||||
public constructor(id: string, source: WorkspaceTaskSource, label: string, type: string, command: CommandConfiguration | undefined,
|
||||
hasDefinedMatchers: boolean, runOptions: RunOptions, configurationProperties: ConfigurationProperties) {
|
||||
@@ -754,8 +754,9 @@ export class ContributedTask extends CommonTask {
|
||||
|
||||
/**
|
||||
* Indicated the source of the task (e.g. tasks.json or extension)
|
||||
* Set in the super constructor
|
||||
*/
|
||||
_source: ExtensionTaskSource;
|
||||
_source!: ExtensionTaskSource;
|
||||
|
||||
defines: KeyedTaskIdentifier;
|
||||
|
||||
@@ -824,7 +825,7 @@ export class InMemoryTask extends CommonTask {
|
||||
*/
|
||||
_source: InMemoryTaskSource;
|
||||
|
||||
type: 'inMemory';
|
||||
type!: 'inMemory';
|
||||
|
||||
public constructor(id: string, source: InMemoryTaskSource, label: string, type: string,
|
||||
runOptions: RunOptions, configurationProperties: ConfigurationProperties) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./watermark';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { assign } from 'vs/base/common/objects';
|
||||
import { isMacintosh, OS } from 'vs/base/common/platform';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
@@ -42,65 +42,21 @@ interface WatermarkEntry {
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
const showServers: WatermarkEntry = {
|
||||
text: nls.localize('watermark.showServers', "Show Servers"),
|
||||
id: OpenDataExplorerViewletAction.ID
|
||||
};
|
||||
const showServers: WatermarkEntry = { text: nls.localize('watermark.showServers', "Show Servers"), id: OpenDataExplorerViewletAction.ID };
|
||||
const newSqlFile: WatermarkEntry = { text: nls.localize('watermark.newSqlFile', "New SQL File"), id: GlobalNewUntitledFileAction.ID };
|
||||
const newNotebook: WatermarkEntry = { text: nls.localize('watermark.newNotebook', "New Notebook"), id: NewNotebookAction.ID };
|
||||
|
||||
const newSqlFile: WatermarkEntry = {
|
||||
text: nls.localize('watermark.newSqlFile', "New SQL File"),
|
||||
id: GlobalNewUntitledFileAction.ID
|
||||
};
|
||||
const newNotebook: WatermarkEntry = {
|
||||
text: nls.localize('watermark.newNotebook', "New Notebook"),
|
||||
id: NewNotebookAction.ID
|
||||
};
|
||||
|
||||
const showCommands: WatermarkEntry = {
|
||||
text: nls.localize('watermark.showCommands', "Show All Commands"),
|
||||
id: ShowAllCommandsAction.ID
|
||||
};
|
||||
const quickOpen: WatermarkEntry = {
|
||||
text: nls.localize('watermark.quickOpen', "Go to File"),
|
||||
id: QUICKOPEN_ACTION_ID
|
||||
};
|
||||
const openFileNonMacOnly: WatermarkEntry = {
|
||||
text: nls.localize('watermark.openFile', "Open File"),
|
||||
id: OpenFileAction.ID,
|
||||
mac: false
|
||||
};
|
||||
const openFolderNonMacOnly: WatermarkEntry = {
|
||||
text: nls.localize('watermark.openFolder', "Open Folder"),
|
||||
id: OpenFolderAction.ID,
|
||||
mac: false
|
||||
};
|
||||
const openFileOrFolderMacOnly: WatermarkEntry = {
|
||||
text: nls.localize('watermark.openFileFolder', "Open File or Folder"),
|
||||
id: OpenFileFolderAction.ID,
|
||||
mac: true
|
||||
};
|
||||
const openRecent: WatermarkEntry = {
|
||||
text: nls.localize('watermark.openRecent', "Open Recent"),
|
||||
id: 'workbench.action.openRecent'
|
||||
};
|
||||
const newUntitledFile: WatermarkEntry = {
|
||||
text: nls.localize('watermark.newUntitledFile', "New Untitled File"),
|
||||
id: GlobalNewUntitledFileAction.ID
|
||||
};
|
||||
const showCommands: WatermarkEntry = { text: nls.localize('watermark.showCommands', "Show All Commands"), id: ShowAllCommandsAction.ID };
|
||||
const quickOpen: WatermarkEntry = { text: nls.localize('watermark.quickOpen', "Go to File"), id: QUICKOPEN_ACTION_ID };
|
||||
const openFileNonMacOnly: WatermarkEntry = { text: nls.localize('watermark.openFile', "Open File"), id: OpenFileAction.ID, mac: false };
|
||||
const openFolderNonMacOnly: WatermarkEntry = { text: nls.localize('watermark.openFolder', "Open Folder"), id: OpenFolderAction.ID, mac: false };
|
||||
const openFileOrFolderMacOnly: WatermarkEntry = { text: nls.localize('watermark.openFileFolder', "Open File or Folder"), id: OpenFileFolderAction.ID, mac: true };
|
||||
const openRecent: WatermarkEntry = { text: nls.localize('watermark.openRecent', "Open Recent"), id: 'workbench.action.openRecent' };
|
||||
const newUntitledFile: WatermarkEntry = { text: nls.localize('watermark.newUntitledFile', "New Untitled File"), id: GlobalNewUntitledFileAction.ID };
|
||||
const newUntitledFileMacOnly: WatermarkEntry = assign({ mac: true }, newUntitledFile);
|
||||
const toggleTerminal: WatermarkEntry = {
|
||||
text: nls.localize({ key: 'watermark.toggleTerminal', comment: ['toggle is a verb here'] }, "Toggle Terminal"),
|
||||
id: TERMINAL_COMMAND_ID.TOGGLE
|
||||
};
|
||||
|
||||
const findInFiles: WatermarkEntry = {
|
||||
text: nls.localize('watermark.findInFiles', "Find in Files"),
|
||||
id: FindInFilesActionId
|
||||
};
|
||||
const startDebugging: WatermarkEntry = {
|
||||
text: nls.localize('watermark.startDebugging', "Start Debugging"),
|
||||
id: StartAction.ID
|
||||
};
|
||||
const toggleTerminal: WatermarkEntry = { text: nls.localize({ key: 'watermark.toggleTerminal', comment: ['toggle is a verb here'] }, "Toggle Terminal"), id: TERMINAL_COMMAND_ID.TOGGLE };
|
||||
const findInFiles: WatermarkEntry = { text: nls.localize('watermark.findInFiles', "Find in Files"), id: FindInFilesActionId };
|
||||
const startDebugging: WatermarkEntry = { text: nls.localize('watermark.startDebugging', "Start Debugging"), id: StartAction.ID };
|
||||
|
||||
// {{SQL CARBON EDIT}} - Replace noFolderEntries and folderEntries
|
||||
const noFolderEntries = [
|
||||
@@ -121,13 +77,13 @@ const folderEntries = [
|
||||
const WORKBENCH_TIPS_ENABLED_KEY = 'workbench.tips.enabled';
|
||||
|
||||
export class WatermarkContribution extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
private watermark: HTMLElement;
|
||||
private watermarkDisposable = this._register(new DisposableStore());
|
||||
private enabled: boolean;
|
||||
private workbenchState: WorkbenchState;
|
||||
|
||||
constructor(
|
||||
@ILifecycleService lifecycleService: ILifecycleService,
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@@ -135,13 +91,20 @@ export class WatermarkContribution extends Disposable implements IWorkbenchContr
|
||||
@IEditorGroupsService private readonly editorGroupsService: IEditorGroupsService
|
||||
) {
|
||||
super();
|
||||
this.workbenchState = contextService.getWorkbenchState();
|
||||
|
||||
lifecycleService.onShutdown(this.dispose, this);
|
||||
this.workbenchState = contextService.getWorkbenchState();
|
||||
this.enabled = this.configurationService.getValue<boolean>(WORKBENCH_TIPS_ENABLED_KEY);
|
||||
|
||||
this.registerListeners();
|
||||
|
||||
if (this.enabled) {
|
||||
this.create();
|
||||
}
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this.lifecycleService.onShutdown(this.dispose, this);
|
||||
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(WORKBENCH_TIPS_ENABLED_KEY)) {
|
||||
const enabled = this.configurationService.getValue<boolean>(WORKBENCH_TIPS_ENABLED_KEY);
|
||||
@@ -155,6 +118,7 @@ export class WatermarkContribution extends Disposable implements IWorkbenchContr
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this.contextService.onDidChangeWorkbenchState(e => {
|
||||
const previousWorkbenchState = this.workbenchState;
|
||||
this.workbenchState = this.contextService.getWorkbenchState();
|
||||
@@ -175,6 +139,7 @@ export class WatermarkContribution extends Disposable implements IWorkbenchContr
|
||||
const selected = folder ? folderEntries : noFolderEntries
|
||||
.filter(entry => !('mac' in entry) || entry.mac === isMacintosh)
|
||||
.filter(entry => !!CommandsRegistry.getCommand(entry.id));
|
||||
|
||||
const update = () => {
|
||||
dom.clearNode(box);
|
||||
selected.map(entry => {
|
||||
@@ -187,10 +152,14 @@ export class WatermarkContribution extends Disposable implements IWorkbenchContr
|
||||
dd.innerHTML = keybinding.element.outerHTML;
|
||||
});
|
||||
};
|
||||
|
||||
update();
|
||||
|
||||
dom.prepend(container.firstElementChild as HTMLElement, this.watermark);
|
||||
this._register(this.keybindingService.onDidUpdateKeybindings(update));
|
||||
this._register(this.editorGroupsService.onDidLayout(dimension => this.handleEditorPartSize(container, dimension)));
|
||||
|
||||
this.watermarkDisposable.add(this.keybindingService.onDidUpdateKeybindings(update));
|
||||
this.watermarkDisposable.add(this.editorGroupsService.onDidLayout(dimension => this.handleEditorPartSize(container, dimension)));
|
||||
|
||||
this.handleEditorPartSize(container, this.editorGroupsService.contentDimension);
|
||||
}
|
||||
|
||||
@@ -205,9 +174,11 @@ export class WatermarkContribution extends Disposable implements IWorkbenchContr
|
||||
private destroy(): void {
|
||||
if (this.watermark) {
|
||||
this.watermark.remove();
|
||||
|
||||
const container = this.layoutService.getContainer(Parts.EDITOR_PART);
|
||||
container.classList.remove('has-watermark');
|
||||
this.dispose();
|
||||
|
||||
this.watermarkDisposable.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,16 +47,16 @@ export class WebviewPortMappingManager extends Disposable {
|
||||
if (this.extensionLocation && this.extensionLocation.scheme === REMOTE_HOST_SCHEME) {
|
||||
const tunnel = await this.getOrCreateTunnel(mapping.extensionHostPort);
|
||||
if (tunnel) {
|
||||
return uri.with({
|
||||
return encodeURI(uri.with({
|
||||
authority: `127.0.0.1:${tunnel.tunnelLocalPort}`,
|
||||
}).toString();
|
||||
}).toString(true));
|
||||
}
|
||||
}
|
||||
|
||||
if (mapping.webviewPort !== mapping.extensionHostPort) {
|
||||
return uri.with({
|
||||
return encodeURI(uri.with({
|
||||
authority: `${requestLocalHostInfo.address}:${mapping.extensionHostPort}`
|
||||
}).toString();
|
||||
}).toString(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,4 +84,4 @@ export class WebviewPortMappingManager extends Disposable {
|
||||
}
|
||||
return tunnel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user