diff --git a/src/commands/toggleVisibility.ts b/src/commands/toggleVisibility.ts new file mode 100644 index 0000000..7c8b242 --- /dev/null +++ b/src/commands/toggleVisibility.ts @@ -0,0 +1,18 @@ +import FileHider from "../main"; +import { findStyleSheet } from "../utils"; + +// The command used to toggle the visibility. +export class VisibilityToggleCommand { + constructor(plugin: FileHider) { + plugin.addCommand({ + id: 'oa-fh-toggle-visibility', + name: 'Toggle Visibility', + callback: () => { + if (!plugin.style) { + plugin.style = findStyleSheet(); + }; + plugin.toggleVisibility(); + } + }); + }; +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 5c5f1c2..b45578e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,112 +1,138 @@ -import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; +import { ManageHiddenDirectories } from './settings/manageHiddenFolders'; +import { VisibilityToggleCommand } from './commands/toggleVisibility'; +import { VisibilityToggleSetting } from './settings/hiddenToggle'; +import { App, Plugin, PluginSettingTab, TFolder } from 'obsidian'; +import { ManageHiddenFiles } from './settings/manageHiddenFiles'; +import { createStyleLine, findStyleSheet } from './utils'; interface FileHiderSettings { ribbonIcon: boolean; + hidden: boolean; + hiddenFiles: string[]; + hiddenFolders: string[]; }; -const DEFAULT_SETTINGS: FileHiderSettings = { - ribbonIcon: false, -}; export default class FileHider extends Plugin { - settings: FileHiderSettings; + settings: FileHiderSettings = { + ribbonIcon: true, + hidden: true, + hiddenFiles: [], + hiddenFolders: [], + }; + + style: CSSStyleSheet|null = null; + + hasRibbon: boolean = false; async onload() { await this.loadSettings(); - // This creates an icon in the left ribbon. - - const ribbonIconEl = this.addRibbonIcon('dice', 'Toggle Hiding', (evt: MouseEvent) => { - new Notice('This is a notice!'); - }); - // Perform additional things with the ribbon - ribbonIconEl.addClass('my-plugin-ribbon-class'); - - // This adds a status bar item to the bottom of the app. Does not work on mobile apps. - const statusBarItemEl = this.addStatusBarItem(); - statusBarItemEl.setText('Status Bar Text'); - - // This adds a simple command that can be triggered anywhere - this.addCommand({ - id: 'open-sample-modal-simple', - name: 'Open sample modal (simple)', - callback: () => { - new FilesModal(this.app).open(); - } - }); - // This adds an editor command that can perform some operation on the current editor instance - this.addCommand({ - id: 'sample-editor-command', - name: 'Sample editor command', - editorCallback: (editor: Editor, view: MarkdownView) => { - console.log(editor.getSelection()); - editor.replaceSelection('Sample Editor Command'); - } - }); + this.registerEvent( + this.app.workspace.on(`file-menu`, (menu, file) => { + if (!this.style) { + this.style = findStyleSheet(); + }; + if (file instanceof TFolder) { + menu.addItem((i) => { + i.setTitle(`Hide Folder`) + .setIcon(`minus-with-circle`) + .onClick(() => { + let rule = createStyleLine(`folder`, file.path); + this.style.insertRule(rule); + this.settings.hiddenFolders.push(file.path); + }); + }); + } else { + menu.addItem((i) => { + i.setTitle(`Hide File`) + .setIcon(`minus-with-circle`) + .onClick((e) => { + let rule = createStyleLine(`file`, file.path); + this.style.insertRule(rule); + this.settings.hiddenFiles.push(file.path); + }); + }); + }; + }) + ); + new VisibilityToggleCommand(this); + this.initialLoadStyle(); this.addSettingTab(new FileHiderSettingsTab(this.app, this)); } onunload() { + this.saveSettings(); + }; - } + /* + This is the method that handles re-hiding files when Obsidian starts, or + when the plugin is reloaded after being unloaded/disabled. + */ + async initialLoadStyle() { + console.log(`attempting to get the stylesheet`) + this.style = findStyleSheet(); + if (this.style) { + for (var file of this.settings.hiddenFiles) { + let r = createStyleLine(`file`, file); + this.style.insertRule(r); + }; + for (var folder of this.settings.hiddenFolders) { + let r = createStyleLine(`folder`, folder); + this.style.insertRule(r); + }; + return + }; + setTimeout(() => this.initialLoadStyle(), 1_000); + }; + /* + Loads the config settings, with defaults created where needed. + */ async loadSettings() { - this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); - } + this.settings = Object.assign({}, this.settings, await this.loadData()); + }; + /* Saves the setting data */ async saveSettings() { await this.saveData(this.settings); + }; - // Remove/Add the ribbon icon if the user wants it - } -} - -class FilesModal extends Modal { - constructor(app: App) { - super(app); - } - - onOpen() { - const {contentEl} = this; - contentEl.setText('Woah!'); - } - - onClose() { - const {contentEl} = this; - contentEl.empty(); - } + /* + Enables/Disables the file visibility based. (gets the stylesheet if needed) + */ + toggleVisibility() { + if (!this.style) { + this.style = findStyleSheet(); + }; + if (this.settings.hidden) { + this.style.disabled = true; + } else { + this.style.disabled = false; + }; + this.settings.hidden = !this.settings.hidden; + }; }; -class DirectoryModal extends Modal { - constructor(app: App) { - super(app); - } - - onOpen() { - const {contentEl} = this; - contentEl.setText('Woah!'); - } - - onClose() { - const {contentEl} = this; - contentEl.empty(); - } -} +/** + * All of the settings for the FileHider + */ class FileHiderSettingsTab extends PluginSettingTab { plugin: FileHider; constructor(app: App, plugin: FileHider) { super(app, plugin); this.plugin = plugin; - } + }; display(): void { - const {containerEl} = this; + const { containerEl: container } = this; - containerEl.empty(); - - containerEl.createEl('h2', {text: 'Settings for my awesome plugin.'}); - } + container.empty(); + VisibilityToggleSetting.create(this.plugin, container); + ManageHiddenFiles.create(this.plugin, container); + ManageHiddenDirectories.create(this.plugin, container); + }; } diff --git a/src/modals/DirectoryModal.ts b/src/modals/DirectoryModal.ts new file mode 100644 index 0000000..698f98b --- /dev/null +++ b/src/modals/DirectoryModal.ts @@ -0,0 +1,35 @@ +import { Modal, Setting } from "obsidian"; +import FileHider from "../main"; + +export class DirectoryModal extends Modal { + private plugin: FileHider; + + constructor(plugin: FileHider) { + super(plugin.app); + this.plugin = plugin; + } + + onOpen() { + const {contentEl: content} = this; + content.createEl(`h1`, { text: `Folder List` }); + content.createEl(`hr`); + let body = content.createEl(`div`, { cls: `folder-list-modal-body` }); + this.plugin.settings.hiddenFolders.forEach(folder => { + let c = body.createEl(`div`); + new Setting(c) + .setName(folder) + .addButton(btn => { + btn.setIcon(`cross`) + .setTooltip(`Remove Folder`) + .onClick((e) => { + console.log(folder); + }); + }); + }); + } + + onClose() { + const {contentEl} = this; + contentEl.empty(); + } +} \ No newline at end of file diff --git a/src/modals/FileModal.ts b/src/modals/FileModal.ts new file mode 100644 index 0000000..db23a33 --- /dev/null +++ b/src/modals/FileModal.ts @@ -0,0 +1,35 @@ +import { Modal, Setting } from "obsidian"; +import FileHider from "../main"; + +export class FileModal extends Modal { + private plugin: FileHider; + + constructor(plugin: FileHider) { + super(plugin.app); + this.plugin = plugin; + }; + + onOpen() { + const {contentEl: content} = this; + content.createEl(`h1`, { text: `File List` }); + content.createEl(`hr`); + let body = content.createEl(`div`, { cls: `file-list-modal-body` }); + this.plugin.settings.hiddenFiles.forEach(file => { + let c = body.createEl(`div`); + new Setting(c) + .setName(file) + .addButton(btn => { + btn.setIcon(`cross`) + .setTooltip(`Remove File`) + .onClick((e) => { + console.log(file); + }); + }); + }); + }; + + onClose() { + const {contentEl} = this; + contentEl.empty(); + }; +}; \ No newline at end of file diff --git a/src/settings/hiddenToggle.ts b/src/settings/hiddenToggle.ts new file mode 100644 index 0000000..00a8657 --- /dev/null +++ b/src/settings/hiddenToggle.ts @@ -0,0 +1,18 @@ +import { Setting } from "obsidian"; +import FileHider from "../main"; + +export class VisibilityToggleSetting { + + public static create(plugin: FileHider, container: HTMLElement) { + return new Setting(container) + .setName(`Hidden File Visibility`) + .setDesc(`Toggle whether or not files and folders that are told to be hidden will be hidden or not.`) + .addToggle(toggle => { + toggle + .setValue(plugin.settings.hidden) + .onChange(() => { + plugin.toggleVisibility(); + }); + }); + }; +}; \ No newline at end of file diff --git a/src/settings/manageHiddenFiles.ts b/src/settings/manageHiddenFiles.ts new file mode 100644 index 0000000..ba2c63f --- /dev/null +++ b/src/settings/manageHiddenFiles.ts @@ -0,0 +1,21 @@ +import { Setting } from "obsidian"; +import FileHider from "../main"; +import { FileModal } from "../modals/FileModal"; + +export class ManageHiddenFiles { + + public static create(plugin: FileHider, container: HTMLElement) { + return new Setting(container) + .setName(`Hidden Files`) + .setDesc(`Add or remove files from the list that are being hidden`) + .addButton(b => { + b.setButtonText(`Manage File List`) + .onClick(event => { + // sanity check to prevent other code from opening the modal + if (!event.isTrusted) { return } + + new FileModal(plugin).open(); + }); + }); + }; +}; \ No newline at end of file diff --git a/src/settings/manageHiddenFolders.ts b/src/settings/manageHiddenFolders.ts new file mode 100644 index 0000000..56744bd --- /dev/null +++ b/src/settings/manageHiddenFolders.ts @@ -0,0 +1,21 @@ +import { DirectoryModal } from "../modals/DirectoryModal"; +import { Setting } from "obsidian"; +import FileHider from "../main"; + +export class ManageHiddenDirectories { + + public static create(plugin: FileHider, container: HTMLElement) { + return new Setting(container) + .setName(`Hidden Folders`) + .setDesc(`Add or remove folders from the list that are being hidden`) + .addButton(b => { + b.setButtonText(`Manage Folder List`) + .onClick(event => { + // sanity check to prevent other code from opening the modal + if (!event.isTrusted) { return } + + new DirectoryModal(plugin).open(); + }); + }); + }; +}; \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..46f24be --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,32 @@ +import { Notice } from "obsidian"; + +/** + * Creates a CSS rule that is used to hide the file or folder from the file + * explorer when it is enabled. + * + * @param type The type of file it is + * @param path The full filepath of the file/folder from the root of the vault + * @returns The CSS string that is used to target the file or folder + */ +export function createStyleLine(type: string, path: string) { + return `.nav-${type} > [data-path="${path}"] { display: none; }`; +}; + + +/** + * Locates the File Hider stylesheet within Obsidian to allow us to modify it + * dynamically, for enabling and disabling it in order to show/hide the files + * and directories in the file explorer + * + * @returns The stylesheet if it was found + */ +export function findStyleSheet() { + for (var i in document.styleSheets) { + let style = document.styleSheets[i]; + //@ts-ignore + let content = style?.ownerNode?.innerText; + if (content && content.startsWith(`/* FILE HIDER */`)) { + return style; + }; + }; +}; \ No newline at end of file