提交 1876b518 编写于 作者: I isidor

Explorer should show hidden files and their path if they are opened

fixes #92090
上级 849aadb7
......@@ -354,6 +354,7 @@ export class ExplorerView extends ViewPane {
private createTree(container: HTMLElement): void {
this.filter = this.instantiationService.createInstance(FilesFilter);
this._register(this.filter);
this._register(this.filter.onDidChange(() => this.refresh(true)));
const explorerLabels = this.instantiationService.createInstance(ResourceLabels, { onDidChangeVisibility: this.onDidChangeBodyVisibility });
this._register(explorerLabels);
......@@ -458,18 +459,7 @@ export class ExplorerView extends ViewPane {
this.autoReveal = configuration?.explorer?.autoReveal;
// Push down config updates to components of viewer
let needsRefresh = false;
if (this.filter) {
needsRefresh = this.filter.updateConfiguration();
}
if (event && !needsRefresh) {
needsRefresh = event.affectsConfiguration('explorer.decorations.colors')
|| event.affectsConfiguration('explorer.decorations.badges');
}
// Refresh viewer as needed if this originates from a config event
if (event && needsRefresh) {
if (event && (event.affectsConfiguration('explorer.decorations.colors') || event.affectsConfiguration('explorer.decorations.badges'))) {
this.refresh(true);
}
}
......@@ -672,19 +662,23 @@ export class ExplorerView extends ViewPane {
}
if (item && item.parent) {
if (reveal) {
if (item.isDisposed) {
return this.onSelectResource(resource, reveal, retry + 1);
}
try {
if (reveal) {
if (item.isDisposed) {
return this.onSelectResource(resource, reveal, retry + 1);
}
// Don't scroll to the item if it's already visible
if (this.tree.getRelativeTop(item) === null) {
this.tree.reveal(item, 0.5);
// Don't scroll to the item if it's already visible
if (this.tree.getRelativeTop(item) === null) {
this.tree.reveal(item, 0.5);
}
}
}
this.tree.setFocus([item]);
this.tree.setSelection([item]);
this.tree.setFocus([item]);
this.tree.setSelection([item]);
} catch (e) {
// Element might not be in the tree, silently fail
}
}
}
......
......@@ -55,6 +55,7 @@ import { ILabelService } from 'vs/platform/label/common/label';
import { isNumber } from 'vs/base/common/types';
import { domEvent } from 'vs/base/browser/event';
import { IEditableData } from 'vs/workbench/common/views';
import { IEditorInput } from 'vs/workbench/common/editor';
export class ExplorerDelegate implements IListVirtualDelegate<ExplorerItem> {
......@@ -472,28 +473,70 @@ interface CachedParsedExpression {
parsed: glob.ParsedExpression;
}
/**
* Respectes files.exclude setting in filtering out content from the explorer.
* Makes sure that visible editors are always shown in the explorer even if they are filtered out by settings.
*/
export class FilesFilter implements ITreeFilter<ExplorerItem, FuzzyScore> {
private hiddenExpressionPerRoot: Map<string, CachedParsedExpression>;
private workspaceFolderChangeListener: IDisposable;
private hiddenUris = new Set<URI>();
private editorsAffectingFilter = new Set<IEditorInput>();
private _onDidChange = new Emitter<void>();
private toDispose: IDisposable[] = [];
constructor(
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IExplorerService private readonly explorerService: IExplorerService
@IExplorerService private readonly explorerService: IExplorerService,
@IEditorService private readonly editorService: IEditorService,
) {
this.hiddenExpressionPerRoot = new Map<string, CachedParsedExpression>();
this.workspaceFolderChangeListener = this.contextService.onDidChangeWorkspaceFolders(() => this.updateConfiguration());
this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateConfiguration()));
this.toDispose.push(this.configurationService.onDidChangeConfiguration((e) => {
if (e.affectsConfiguration('files.exclude')) {
this.updateConfiguration();
}
}));
this.toDispose.push(this.editorService.onDidVisibleEditorsChange(() => {
const editors = this.editorService.visibleEditors;
let shouldFire = false;
this.hiddenUris.forEach(u => {
editors.forEach(e => {
if (e.resource && isEqualOrParent(e.resource, u)) {
// A filtered resource suddenly became visible since user opened an editor
shouldFire = true;
}
});
});
this.editorsAffectingFilter.forEach(e => {
if (editors.indexOf(e) === -1) {
// Editor that was affecting filtering is no longer visible
shouldFire = true;
}
});
if (shouldFire) {
this.editorsAffectingFilter.clear();
this.hiddenUris.clear();
this._onDidChange.fire();
}
}));
this.updateConfiguration();
}
updateConfiguration(): boolean {
let needsRefresh = false;
get onDidChange(): Event<void> {
return this._onDidChange.event;
}
private updateConfiguration(): void {
let shouldFire = false;
this.contextService.getWorkspace().folders.forEach(folder => {
const configuration = this.configurationService.getValue<IFilesConfiguration>({ resource: folder.uri });
const excludesConfig: glob.IExpression = configuration?.files?.exclude || Object.create(null);
if (!needsRefresh) {
if (!shouldFire) {
const cached = this.hiddenExpressionPerRoot.get(folder.uri.toString());
needsRefresh = !cached || !equals(cached.original, excludesConfig);
shouldFire = !cached || !equals(cached.original, excludesConfig);
}
const excludesConfigCopy = deepClone(excludesConfig); // do not keep the config, as it gets mutated under our hoods
......@@ -501,10 +544,25 @@ export class FilesFilter implements ITreeFilter<ExplorerItem, FuzzyScore> {
this.hiddenExpressionPerRoot.set(folder.uri.toString(), { original: excludesConfigCopy, parsed: glob.parse(excludesConfigCopy) });
});
return needsRefresh;
if (shouldFire) {
this.editorsAffectingFilter.clear();
this.hiddenUris.clear();
this._onDidChange.fire();
}
}
filter(stat: ExplorerItem, parentVisibility: TreeVisibility): TreeFilterResult<FuzzyScore> {
const isVisible = this.isVisible(stat, parentVisibility);
if (isVisible) {
this.hiddenUris.delete(stat.resource);
} else {
this.hiddenUris.add(stat.resource);
}
return isVisible;
}
private isVisible(stat: ExplorerItem, parentVisibility: TreeVisibility): boolean {
if (parentVisibility === TreeVisibility.Hidden) {
return false;
}
......@@ -515,14 +573,21 @@ export class FilesFilter implements ITreeFilter<ExplorerItem, FuzzyScore> {
// Hide those that match Hidden Patterns
const cached = this.hiddenExpressionPerRoot.get(stat.root.resource.toString());
if (cached && cached.parsed(path.relative(stat.root.resource.path, stat.resource.path), stat.name, name => !!(stat.parent && stat.parent.getChild(name)))) {
const editors = this.editorService.visibleEditors;
const editor = editors.filter(e => e.resource && isEqualOrParent(e.resource, stat.resource)).pop();
if (editor) {
this.editorsAffectingFilter.add(editor);
return true; // Show all opened files and their parents
}
return false; // hidden through pattern
}
return true;
}
public dispose(): void {
dispose(this.workspaceFolderChangeListener);
dispose(): void {
dispose(this.toDispose);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册