Skip to content

Commit

Permalink
Closes #44 adds Explorer toggle button
Browse files Browse the repository at this point in the history
  • Loading branch information
eamodio committed Mar 5, 2023
1 parent 17abae8 commit 287b611
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 36 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,21 @@ Quickly toggles excluded (hidden) files visibility in the file explorer.
- Adds a `Toggle Excluded Files` command (`toggleexcludedfiles.toggle`) with a shortcut of `ctrl+shift+a` (`cmd+shift+a` on macOS) to either show or restore the current visibility of excluded files in the file explorer
- Adds a **Explorer view button** to toggle the excluded file visibility ([optional](#extension-settings), on by default)
- Adds a **status bar button** to toggle the excluded file visibility ([optional](#extension-settings), on by default)
- An indicator icon will show when the exclude visibility is currently toggled
- Adds a `Show Excluded Files` command (`toggleexcludedfiles.show`) to show excluded files in the file explorer
- Adds a `Restore Excluded Files` command (`toggleexcludedfiles.restore`) to restore (hide) excluded files in the file explorer
- Adds a `Hide Excluded Files` command (`toggleexcludedfiles.restore`) to hide (restore) excluded files in the file explorer
## Extension Settings
| Name | Description |
| --------------------------------------- | ------------------------------------------------------------- |
| `toggleexcludedfiles.statusBar.enabled` | Specifies whether to show the toggle button in the status bar |
| Name | Description |
| --------------------------------------- | ---------------------------------------------------------------- |
| `toggleexcludedfiles.explorer.enabled` | Specifies whether to show the toggle button in the Explorer view |
| `toggleexcludedfiles.statusBar.enabled` | Specifies whether to show the toggle button in the status bar |
## Known Issues
Expand Down
40 changes: 36 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@
"type": "object",
"title": "Toggle Excluded Files configuration",
"properties": {
"toggleexcludedfiles.explorer.enabled": {
"type": "boolean",
"default": true,
"markdownDescription": "Specifies whether to show the toggle button in the Explorer view",
"scope": "window"
},
"toggleexcludedfiles.statusBar.enabled": {
"type": "boolean",
"default": true,
Expand Down Expand Up @@ -89,12 +95,14 @@
{
"command": "toggleexcludedfiles.show",
"title": "Show Excluded Files",
"category": "Files"
"category": "Files",
"icon": "$(eye)"
},
{
"command": "toggleexcludedfiles.restore",
"title": "Restore Excluded Files",
"category": "Files"
"title": "Hide Excluded Files",
"category": "Files",
"icon": "$(eye-closed)"
},
{
"command": "toggleexcludedfiles.toggle",
Expand All @@ -109,7 +117,31 @@
"mac": "cmd+shift+a",
"when": "filesExplorerFocus"
}
]
],
"menus": {
"commandPalette": [
{
"command": "toggleexcludedfiles.show",
"when": "toggleexcludedfiles:loaded && !toggleexcludedfiles:toggled"
},
{
"command": "toggleexcludedfiles.restore",
"when": "toggleexcludedfiles:loaded && toggleexcludedfiles:toggled"
}
],
"view/title": [
{
"command": "toggleexcludedfiles.show",
"group": "navigation@21",
"when": "view == 'workbench.explorer.fileView' && toggleexcludedfiles:loaded && !toggleexcludedfiles:toggled && config.toggleexcludedfiles.explorer.enabled"
},
{
"command": "toggleexcludedfiles.restore",
"group": "navigation@21",
"when": "view == 'workbench.explorer.fileView' && toggleexcludedfiles:loaded && toggleexcludedfiles:toggled && config.toggleexcludedfiles.explorer.enabled"
}
]
}
},
"scripts": {
"analyze:bundle": "webpack --mode production --env analyzeBundle",
Expand Down
11 changes: 6 additions & 5 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ export enum OutputLevel {
Debug = 'debug',
}

export interface StatusBarConfig {
enabled: boolean;
}

export interface Config {
explorer: {
enabled: boolean;
};
outputLevel: OutputLevel;
statusBar: StatusBarConfig;
statusBar: {
enabled: boolean;
};
}

export function fromOutputLevel(level: LogLevel | OutputLevel): LogLevel {
Expand Down
5 changes: 4 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
export const commandPrefix = 'toggleexcludedfiles';
export const configPrefix = 'toggleexcludedfiles';

export const extensionId = 'toggleexcludedfiles';
export const enum ContextKeys {
Loaded = 'toggleexcludedfiles:loaded',
Toggled = 'toggleexcludedfiles:toggled',
}

export enum CoreCommands {
Open = 'vscode.open',
Expand Down
22 changes: 22 additions & 0 deletions src/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { commands, EventEmitter } from 'vscode';
import type { ContextKeys } from './constants';
import { CoreCommands } from './constants';

const contextStorage = new Map<string, unknown>();

type AllContextKeys = ContextKeys;

const _onDidChangeContext = new EventEmitter<AllContextKeys>();
export const onDidChangeContext = _onDidChangeContext.event;

export function getContext<T>(key: AllContextKeys): T | undefined;
export function getContext<T>(key: AllContextKeys, defaultValue: T): T;
export function getContext<T>(key: AllContextKeys, defaultValue?: T): T | undefined {
return (contextStorage.get(key) as T | undefined) ?? defaultValue;
}

export async function setContext(key: AllContextKeys, value: unknown): Promise<void> {
contextStorage.set(key, value);
void (await commands.executeCommand(CoreCommands.SetContext, key, value));
_onDidChangeContext.fire(key);
}
50 changes: 30 additions & 20 deletions src/excludeController.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { Event } from 'vscode';
import { ConfigurationTarget, Disposable, EventEmitter, workspace } from 'vscode';
import { WorkspaceState } from './constants';
import type { ConfigurationChangeEvent, Disposable, Event } from 'vscode';
import { ConfigurationTarget, EventEmitter } from 'vscode';
import { ContextKeys, WorkspaceState } from './constants';
import type { Container } from './container';
import { setContext } from './context';
import { configuration } from './system/configuration';
import { Logger } from './system/logger';
import { areEqual } from './system/object';
Expand All @@ -20,13 +21,8 @@ export class FilesExcludeController implements Disposable {
private _working: boolean = false;

constructor(private readonly container: Container) {
this._disposable = configuration.onDidChangeAny(this.onConfigurationChanged, this);
this.onConfigurationChanged();

const subscriptions: Disposable[] = [];

subscriptions.push(configuration.onDidChangeAny(this.onConfigurationChanged, this));

this._disposable = Disposable.from(...subscriptions);
}

dispose() {
Expand All @@ -41,17 +37,18 @@ export class FilesExcludeController implements Disposable {
return WorkspaceState.SavedState;
}

private onConfigurationChanged() {
private onConfigurationChanged(e?: ConfigurationChangeEvent) {
if (this._working) return;
if (e != null && !e.affectsConfiguration(this._section)) return;

const savedExclude = this.getSavedExcludeConfiguration();
if (savedExclude === undefined) return;
if (savedExclude == null) return;

Logger.log('ExcludeController.onConfigurationChanged');

const newExclude = this.getExcludeConfiguration();
if (
newExclude !== undefined &&
newExclude != null &&
areEqual(savedExclude.globalValue, newExclude.globalValue) &&
areEqual(savedExclude.workspaceValue, newExclude.workspaceValue)
) {
Expand All @@ -60,8 +57,8 @@ export class FilesExcludeController implements Disposable {

const appliedExclude = this.getAppliedExcludeConfiguration();
if (
newExclude !== undefined &&
appliedExclude !== undefined &&
newExclude != null &&
appliedExclude != null &&
areEqual(appliedExclude.globalValue, newExclude.globalValue) &&
areEqual(appliedExclude.workspaceValue, newExclude.workspaceValue)
) {
Expand Down Expand Up @@ -150,13 +147,19 @@ export class FilesExcludeController implements Disposable {

const promises: Thenable<void>[] = [];

if (savedExclude !== undefined) {
if (savedExclude.globalValue !== undefined) {
promises.push(workspace.getConfiguration().update(this._section, savedExclude.globalValue, true));
if (savedExclude != null) {
if (savedExclude.globalValue != null) {
promises.push(
configuration.updateAny(this._section, savedExclude.globalValue, ConfigurationTarget.Global),
);
}
if (savedExclude.workspaceValue !== undefined) {
if (savedExclude.workspaceValue != null) {
promises.push(
workspace.getConfiguration().update(this._section, savedExclude.workspaceValue, false),
configuration.updateAny(
this._section,
savedExclude.workspaceValue,
ConfigurationTarget.Workspace,
),
);
}
}
Expand Down Expand Up @@ -212,8 +215,15 @@ export class FilesExcludeController implements Disposable {
return this.container.context.workspaceState.get<FilesExcludeInspect>(this.appliedState);
}

private _loaded = false;
private getSavedExcludeConfiguration(): FilesExcludeInspect | undefined {
return this.container.context.workspaceState.get<FilesExcludeInspect>(this.savedState);
const state = this.container.context.workspaceState.get<FilesExcludeInspect>(this.savedState);
void setContext(ContextKeys.Toggled, state != null);
if (!this._loaded) {
this._loaded = true;
void setContext(ContextKeys.Loaded, true);
}
return state;
}

private hasSavedExcludeConfiguration(): boolean {
Expand Down
4 changes: 2 additions & 2 deletions src/statusBarController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class StatusBarController implements Disposable {
if (e == null || configuration.changed(e, 'statusBar.enabled') || e.affectsConfiguration('files.exclude')) {
this._statusBarItem?.dispose();

const canToggle = this.container.filesExclude.canToggle;
const { canToggle } = this.container.filesExclude;
if (configuration.get('statusBar.enabled') && canToggle) {
this._statusBarItem = window.createStatusBarItem(StatusBarAlignment.Right, 0);
this._statusBarItem.command = `${commandPrefix}.toggle`;
Expand All @@ -41,7 +41,7 @@ export class StatusBarController implements Disposable {
if (this._statusBarItem == null) return;

this._statusBarItem.text = toggled ? '$(eye-closed)' : '$(eye)';
this._statusBarItem.tooltip = `${toggled ? 'Restore' : 'Show'} Excluded Files`;
this._statusBarItem.tooltip = `${toggled ? 'Hide' : 'Show'} Excluded Files`;
}

private _onExcludeToggled() {
Expand Down

0 comments on commit 287b611

Please sign in to comment.