Reduce event listeners created when rendering explorer items (#163394)

Reduce event listeners created when rendering explorer

Every time an explorer item is rendered, we currently hook up a `themeService.onDidFileIconThemeChange` listener for it. This ends up creating a lot of extra event listeners even though this even it pretty rarely fired

Instead, this PR switches us to have a single listener the re-renders the entire tree. Since this should not be a common event, I believe this is reasonable. Profiling also shows that this cuts both the rendering time and amount of garbage generated
This commit is contained in:
Matt Bierner
2022-10-12 10:19:43 -07:00
committed by GitHub
parent 749f480915
commit c56e49670e
2 changed files with 18 additions and 28 deletions
@@ -452,6 +452,7 @@ export class ExplorerView extends ViewPane implements IExplorerView {
}
});
this._register(this.tree);
this._register(this.themeService.onDidColorThemeChange(() => this.tree.rerender()));
// Bind configuration
const onDidChangeCompressionConfiguration = Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('explorer.compactFolders'));
@@ -384,37 +384,26 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
extraClasses.push('cut');
}
const setResourceData = () => {
// Offset nested children unless folders have both chevrons and icons, otherwise alignment breaks
const theme = this.themeService.getFileIconTheme();
// Offset nested children unless folders have both chevrons and icons, otherwise alignment breaks
const theme = this.themeService.getFileIconTheme();
// Hack to always render chevrons for file nests, or else may not be able to identify them.
const twistieContainer = (templateData.container.parentElement?.parentElement?.querySelector('.monaco-tl-twistie') as HTMLElement);
if (twistieContainer) {
if (stat.hasNests && theme.hidesExplorerArrows) {
twistieContainer.classList.add('force-twistie');
} else {
twistieContainer.classList.remove('force-twistie');
}
}
// Hack to always render chevrons for file nests, or else may not be able to identify them.
const twistieContainer = templateData.container.parentElement?.parentElement?.querySelector('.monaco-tl-twistie');
twistieContainer?.classList.toggle('force-twistie', stat.hasNests && theme.hidesExplorerArrows);
// when explorer arrows are hidden or there are no folder icons, nests get misaligned as they are forced to have arrows and files typically have icons
// Apply some CSS magic to get things looking as reasonable as possible.
const themeIsUnhappyWithNesting = theme.hasFileIcons && (theme.hidesExplorerArrows || !theme.hasFolderIcons);
const realignNestedChildren = stat.nestedParent && themeIsUnhappyWithNesting;
// when explorer arrows are hidden or there are no folder icons, nests get misaligned as they are forced to have arrows and files typically have icons
// Apply some CSS magic to get things looking as reasonable as possible.
const themeIsUnhappyWithNesting = theme.hasFileIcons && (theme.hidesExplorerArrows || !theme.hasFolderIcons);
const realignNestedChildren = stat.nestedParent && themeIsUnhappyWithNesting;
templateData.label.setResource({ resource: stat.resource, name: label }, {
fileKind: stat.isRoot ? FileKind.ROOT_FOLDER : stat.isDirectory ? FileKind.FOLDER : FileKind.FILE,
extraClasses: realignNestedChildren ? [...extraClasses, 'align-nest-icon-with-parent-icon'] : extraClasses,
fileDecorations: this.config.explorer.decorations,
matches: createMatches(filterData),
separator: this.labelService.getSeparator(stat.resource.scheme, stat.resource.authority),
domId
});
};
templateData.elementDisposables.add(this.themeService.onDidFileIconThemeChange(() => setResourceData()));
setResourceData();
templateData.label.setResource({ resource: stat.resource, name: label }, {
fileKind: stat.isRoot ? FileKind.ROOT_FOLDER : stat.isDirectory ? FileKind.FOLDER : FileKind.FILE,
extraClasses: realignNestedChildren ? [...extraClasses, 'align-nest-icon-with-parent-icon'] : extraClasses,
fileDecorations: this.config.explorer.decorations,
matches: createMatches(filterData),
separator: this.labelService.getSeparator(stat.resource.scheme, stat.resource.authority),
domId
});
templateData.elementDisposables.add(templateData.label.onDidRender(() => {
try {