diff --git a/src/vs/editor/browser/services/hoverService/hoverWidget.ts b/src/vs/editor/browser/services/hoverService/hoverWidget.ts index 15bda1211ac93..c33296a34e65b 100644 --- a/src/vs/editor/browser/services/hoverService/hoverWidget.ts +++ b/src/vs/editor/browser/services/hoverService/hoverWidget.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import './hover.css'; -import { DisposableStore, MutableDisposable } from '../../../../base/common/lifecycle.js'; +import { DisposableStore, MutableDisposable, toDisposable } from '../../../../base/common/lifecycle.js'; import { Event, Emitter } from '../../../../base/common/event.js'; import * as dom from '../../../../base/browser/dom.js'; import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js'; @@ -165,7 +165,7 @@ export class HoverWidget extends Widget implements IHoverWidget { { codeBlockFontFamily: this._configurationService.getValue('editor').fontFamily || EDITOR_FONT_DEFAULTS.fontFamily } ); - const { element } = mdRenderer.render(markdown, { + const { element, dispose } = mdRenderer.render(markdown, { actionHandler: { callback: (content) => this._linkHandler(content), disposables: this._messageListeners @@ -178,6 +178,7 @@ export class HoverWidget extends Widget implements IHoverWidget { } }); contentsElement.appendChild(element); + this._register(toDisposable(dispose)); } rowElement.appendChild(contentsElement); this._hover.contentsDomNode.appendChild(rowElement); @@ -188,7 +189,7 @@ export class HoverWidget extends Widget implements IHoverWidget { options.actions.forEach(action => { const keybinding = this._keybindingService.lookupKeybinding(action.commandId); const keybindingLabel = keybinding ? keybinding.getLabel() : null; - HoverAction.render(actionsElement, { + this._register(HoverAction.render(actionsElement, { label: action.label, commandId: action.commandId, run: e => { @@ -196,7 +197,7 @@ export class HoverWidget extends Widget implements IHoverWidget { this.dispose(); }, iconClass: action.iconClass - }, keybindingLabel); + }, keybindingLabel)); }); statusBarElement.appendChild(actionsElement); this._hover.containerDomNode.appendChild(statusBarElement); diff --git a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts index 50e6831865081..142f360c1dd9d 100644 --- a/src/vs/workbench/browser/parts/titlebar/menubarControl.ts +++ b/src/vs/workbench/browser/parts/titlebar/menubarControl.ts @@ -565,6 +565,7 @@ export class CustomMenubarControl extends MenubarControl { } private readonly reinstallDisposables = this._register(new DisposableStore()); + private readonly updateActionsDisposables = this._register(new DisposableStore()); private setupCustomMenubar(firstTime: boolean): void { // If there is no container, we cannot setup the menubar if (!this.container) { @@ -620,7 +621,7 @@ export class CustomMenubarControl extends MenubarControl { } // Update the menu actions - const updateActions = (menuActions: readonly IAction[], target: IAction[], topLevelTitle: string) => { + const updateActions = (menuActions: readonly IAction[], target: IAction[], topLevelTitle: string, store: DisposableStore) => { target.splice(0); for (const menuItem of menuActions) { @@ -636,7 +637,7 @@ export class CustomMenubarControl extends MenubarControl { if (menuItem instanceof SubmenuItemAction) { const submenuActions: SubmenuAction[] = []; - updateActions(menuItem.actions, submenuActions, topLevelTitle); + updateActions(menuItem.actions, submenuActions, topLevelTitle, store); if (submenuActions.length > 0) { target.push(new SubmenuAction(menuItem.id, mnemonicMenuLabel(title), submenuActions)); @@ -646,7 +647,7 @@ export class CustomMenubarControl extends MenubarControl { title = menuItem.item.toggled.mnemonicTitle ?? menuItem.item.toggled.title ?? title; } - const newAction = new Action(menuItem.id, mnemonicMenuLabel(title), menuItem.class, menuItem.enabled, () => this.commandService.executeCommand(menuItem.id)); + const newAction = store.add(new Action(menuItem.id, mnemonicMenuLabel(title), menuItem.class, menuItem.enabled, () => this.commandService.executeCommand(menuItem.id))); newAction.tooltip = menuItem.tooltip; newAction.checked = menuItem.checked; target.push(newAction); @@ -667,20 +668,24 @@ export class CustomMenubarControl extends MenubarControl { for (const title of Object.keys(this.topLevelTitles)) { const menu = this.menus[title]; if (firstTime && menu) { + const menuChangedDisposable = this.reinstallDisposables.add(new DisposableStore()); this.reinstallDisposables.add(menu.onDidChange(() => { if (!this.focusInsideMenubar) { const actions: IAction[] = []; - updateActions(this.toActionsArray(menu), actions, title); + menuChangedDisposable.clear(); + updateActions(this.toActionsArray(menu), actions, title, menuChangedDisposable); this.menubar?.updateMenu({ actions, label: mnemonicMenuLabel(this.topLevelTitles[title]) }); } })); // For the file menu, we need to update if the web nav menu updates as well if (menu === this.menus.File) { + const webMenuChangedDisposable = this.reinstallDisposables.add(new DisposableStore()); this.reinstallDisposables.add(this.webNavigationMenu.onDidChange(() => { if (!this.focusInsideMenubar) { const actions: IAction[] = []; - updateActions(this.toActionsArray(menu), actions, title); + webMenuChangedDisposable.clear(); + updateActions(this.toActionsArray(menu), actions, title, webMenuChangedDisposable); this.menubar?.updateMenu({ actions, label: mnemonicMenuLabel(this.topLevelTitles[title]) }); } })); @@ -689,7 +694,8 @@ export class CustomMenubarControl extends MenubarControl { const actions: IAction[] = []; if (menu) { - updateActions(this.toActionsArray(menu), actions, title); + this.updateActionsDisposables.clear(); + updateActions(this.toActionsArray(menu), actions, title, this.updateActionsDisposables); } if (this.menubar) { diff --git a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts index 7e18e20482c26..810f79817671c 100644 --- a/src/vs/workbench/contrib/timeline/browser/timelinePane.ts +++ b/src/vs/workbench/contrib/timeline/browser/timelinePane.ts @@ -1234,6 +1234,10 @@ class TimelineTreeRenderer implements ITreeRenderer, index: number, templateData: TimelineElementTemplate, height: number | undefined): void { + templateData.actionBar.actionRunner.dispose(); + } + disposeTemplate(template: TimelineElementTemplate): void { template.dispose(); }