mirror of
https://github.com/lostpaul/obsidian-folder-notes.git
synced 2026-07-22 07:40:24 +00:00
Make folder overview an independent plugin progress
This commit is contained in:
parent
62c4b5e149
commit
2e2d343aed
14 changed files with 62 additions and 56 deletions
|
|
@ -6,7 +6,9 @@
|
|||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json",
|
||||
"folder-overview": "node ./src/folderOverview/esbuild.config.mjs",
|
||||
"fv": "npm run folder-overview"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Alan Grainger",
|
||||
|
|
|
|||
0
src/folderOverview/FolderOverview.ts
Normal file
0
src/folderOverview/FolderOverview.ts
Normal file
|
|
@ -15,7 +15,7 @@ esbuild.build({
|
|||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
entryPoints: ['./src/main.ts'],
|
||||
entryPoints: ['./src/folderOverview/src/main.ts'],
|
||||
bundle: true,
|
||||
external: [
|
||||
'obsidian',
|
||||
|
|
@ -38,6 +38,6 @@ esbuild.build({
|
|||
logLevel: 'info',
|
||||
sourcemap: prod ? false : 'inline',
|
||||
treeShaking: true,
|
||||
outfile: 'main.js',
|
||||
outfile: './src/folderOverview/main.js',
|
||||
conditions: ['types'],
|
||||
}).catch(() => process.exit(1));
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ export class FileExplorerOverview {
|
|||
}
|
||||
if (excludedFolder?.excludeFromFolderOverview) { return; }
|
||||
|
||||
const svg = '<svg xmlns='http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon right-triangle"><path d="M3 8L12 17L21 8'></path></svg>';
|
||||
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon right-triangle"><path d="M3 8L12 17L21 8"></path></svg>';
|
||||
if (yaml.includeTypes.includes('folder')) {
|
||||
folderElement = childrenElement.createDiv({
|
||||
cls: 'tree-item nav-folder',
|
||||
|
|
|
|||
|
|
@ -50,13 +50,10 @@ export class FolderOverview {
|
|||
|
||||
eventListeners: (() => void)[] = [];
|
||||
constructor(plugin: FolderNotesPlugin | FolderOverviewPlugin, ctx: MarkdownPostProcessorContext, source: string, el: HTMLElement, defaultSettings: overviewSettings) {
|
||||
console.log('creating folder overview');
|
||||
console.log('defaultSettings', defaultSettings);
|
||||
this.plugin = plugin;
|
||||
this.emitter = new CustomEventEmitter();
|
||||
let yaml: overviewSettings = parseYaml(source);
|
||||
if (!yaml) { yaml = {} as overviewSettings; }
|
||||
console.log('yaml', yaml);
|
||||
const includeTypes = yaml?.includeTypes || defaultSettings.includeTypes || ['folder', 'markdown'];
|
||||
this.ctx = ctx;
|
||||
this.source = source;
|
||||
|
|
@ -82,7 +79,6 @@ export class FolderOverview {
|
|||
disableCollapseIcon: yaml?.disableCollapseIcon ?? defaultSettings.disableCollapseIcon,
|
||||
alwaysCollapse: yaml?.alwaysCollapse ?? defaultSettings.alwaysCollapse,
|
||||
};
|
||||
console.log('this.yaml', this.yaml);
|
||||
|
||||
|
||||
const customChild = new CustomMarkdownRenderChild(el, this);
|
||||
|
|
@ -174,7 +170,7 @@ export class FolderOverview {
|
|||
if (!sourceFolder && sourceFolderPath == '') {
|
||||
sourceFolderPath = '/';
|
||||
}
|
||||
if (!(sourceFolder instanceof TFolder)) { return; }
|
||||
if (!(sourceFolder instanceof TFolder) && sourceFolderPath !== '/') { return; }
|
||||
|
||||
if (sourceFolderPath == '/') {
|
||||
const rootFiles: TAbstractFile[] = [];
|
||||
|
|
@ -184,11 +180,10 @@ export class FolderOverview {
|
|||
}
|
||||
});
|
||||
files = rootFiles;
|
||||
} else if (sourceFolder) {
|
||||
} else if (sourceFolder instanceof TFolder) {
|
||||
files = sourceFolder.children;
|
||||
}
|
||||
|
||||
|
||||
files = await this.filterFiles(files, plugin, sourceFolderPath, this.yaml.depth, this.pathBlacklist);
|
||||
|
||||
if (!this.yaml.includeTypes.includes('folder')) {
|
||||
|
|
@ -252,20 +247,19 @@ export class FolderOverview {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (this.yaml.includeTypes.length > 1 && (!this.yaml.showEmptyFolders || this.yaml.onlyIncludeSubfolders) && this.yaml.style === 'list') {
|
||||
this.removeEmptyFolders(ul, 1, this.yaml);
|
||||
}
|
||||
|
||||
// if (this.yaml.includeTypes.length > 1 && (!this.yaml.showEmptyFolders || this.yaml.onlyIncludeSubfolders) && this.yaml.style === 'list') {
|
||||
// this.removeEmptyFolders(ul, 1, this.yaml);
|
||||
// }
|
||||
}
|
||||
|
||||
addEditButton(root: HTMLElement) {
|
||||
console.log('adding edit button');
|
||||
const editButton = root.createEl('button', { cls: 'folder-overview-edit-button' });
|
||||
editButton.innerText = 'Edit overview';
|
||||
editButton.addEventListener('click', (e) => {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
console.log({ 'this.plugin': this.plugin, 'this.yaml': this.yaml, 'this.ctx': this.ctx, 'this.el': this.el });
|
||||
new FolderOverviewSettings(this.plugin.app as App, this.plugin, this.yaml, this.ctx, this.el, this.plugin.settings as overviewSettings).open();
|
||||
}, { capture: true });
|
||||
}
|
||||
|
|
@ -274,9 +268,10 @@ export class FolderOverview {
|
|||
const filteredFiles = await Promise.all(files.map(async (file) => {
|
||||
const folderPath = getFolderPathFromString(file.path);
|
||||
const isBlacklisted = pathBlacklist.includes(file.path);
|
||||
const isSubfolder = folderPath.startsWith(sourceFolderPath) && sourceFolderPath !== '/';
|
||||
const isSubfolder = sourceFolderPath === '/' || folderPath.startsWith(sourceFolderPath);
|
||||
const isSourceFile = file.path === this.sourceFilePath;
|
||||
let isExcludedFromOverview = false;
|
||||
|
||||
if (plugin instanceof FolderNotesPlugin) {
|
||||
isExcludedFromOverview = (await getExcludedFolder(plugin, file.path, true))?.excludeFromFolderOverview ?? false;
|
||||
}
|
||||
|
|
@ -285,7 +280,7 @@ export class FolderOverview {
|
|||
return null;
|
||||
}
|
||||
|
||||
const fileDepth = file.path.split('/').length - sourceFolderPath.split('/').length;
|
||||
const fileDepth = file.path.split('/').length - (sourceFolderPath === '/' ? 0 : sourceFolderPath.split('/').length);
|
||||
return fileDepth <= depth ? file : null;
|
||||
}));
|
||||
|
||||
|
|
@ -293,6 +288,7 @@ export class FolderOverview {
|
|||
}
|
||||
|
||||
|
||||
|
||||
sortFiles(files: TAbstractFile[]): TAbstractFile[] {
|
||||
const yaml = this.yaml;
|
||||
|
||||
|
|
@ -333,24 +329,6 @@ export class FolderOverview {
|
|||
return files;
|
||||
}
|
||||
|
||||
removeEmptyFolders(ul: HTMLUListElement | HTMLLIElement, depth: number, yaml: overviewSettings) {
|
||||
const childrensToRemove: ChildNode[] = [];
|
||||
ul.childNodes.forEach((el) => {
|
||||
if ((el.childNodes[0] as HTMLElement)?.classList && (el.childNodes[0] as HTMLElement)?.classList.contains('internal-link')) { return; }
|
||||
const childrens = (el as Element).querySelector('ul');
|
||||
if (!childrens || childrens === null) { return; }
|
||||
if (childrens && !childrens?.hasChildNodes() && !(el instanceof HTMLUListElement)) {
|
||||
childrensToRemove.push(el);
|
||||
} else if (el instanceof HTMLUListElement || el instanceof HTMLLIElement) {
|
||||
this.removeEmptyFolders(el, depth + 1, yaml);
|
||||
}
|
||||
});
|
||||
childrensToRemove.forEach((el) => {
|
||||
if (yaml.onlyIncludeSubfolders && depth === 1) { return; }
|
||||
el.remove();
|
||||
});
|
||||
}
|
||||
|
||||
getAllFiles(files: TAbstractFile[], sourceFolderPath: string, depth: number) {
|
||||
const allFiles: TAbstractFile[] = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { MarkdownPostProcessorContext, TFolder, TFile, Plugin } from 'obsidian';
|
||||
import { getFolderNote } from '../../functions/folderNoteFunctions';
|
||||
import { extractFolderName, getFolderNote } from '../../functions/folderNoteFunctions';
|
||||
import { FolderOverview, overviewSettings } from './FolderOverview';
|
||||
import { getFolderPathFromString } from '../../functions/utils';
|
||||
import FolderOverviewPlugin from 'src/main';
|
||||
|
|
@ -41,6 +41,14 @@ export function renderListOverview(plugin: FolderOverviewPlugin | FolderNotesPlu
|
|||
}
|
||||
|
||||
export function addFolderList(plugin: FolderOverviewPlugin | FolderNotesPlugin | FolderNotesPlugin, list: HTMLUListElement | HTMLLIElement, pathBlacklist: string[], folder: TFolder, folderOverview: FolderOverview) {
|
||||
const isFirstLevelSub = folder.path.split('/').length === folderOverview.yaml.folderPath.split('/').length + 1;
|
||||
if (!folderOverview.yaml.showEmptyFolders && folder.children.length === 0 && !folderOverview.yaml.onlyIncludeSubfolders) {
|
||||
return;
|
||||
} else if (folderOverview.yaml.onlyIncludeSubfolders && !isFirstLevelSub && folder.children.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const folderItem = list.createEl('li', { cls: 'folder-overview-list folder-list' });
|
||||
if (plugin instanceof FolderNotesPlugin) {
|
||||
const folderNote = getFolderNote(plugin, folder.path);
|
||||
|
|
@ -115,6 +123,9 @@ function addFileList(plugin: FolderOverviewPlugin | FolderNotesPlugin, list: HTM
|
|||
|
||||
if (!folderOverview.yaml.showFolderNotes) {
|
||||
if (pathBlacklist.includes(file.path)) return;
|
||||
if (plugin instanceof FolderNotesPlugin && extractFolderName(plugin.settings.folderNoteName, file.basename) === file.parent?.name) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const listItem = list.createEl('li', { cls: 'folder-overview-list file-link' });
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ export class FolderOverviewSettings extends Modal {
|
|||
if (!yaml) {
|
||||
this.yaml = this.defaultSettings;
|
||||
} else if (ctx) {
|
||||
console.log('yaml 3: ', yaml);
|
||||
console.log('settings: ', defaultSettings);
|
||||
const includeTypes = yaml?.includeTypes || defaultSettings.includeTypes || ['folder', 'markdown'];
|
||||
this.yaml = {
|
||||
id: yaml?.id ?? crypto.randomUUID(),
|
||||
|
|
@ -55,8 +53,6 @@ export class FolderOverviewSettings extends Modal {
|
|||
|
||||
onOpen() {
|
||||
const { contentEl } = this;
|
||||
console.log('yaml 6: ', this.yaml);
|
||||
console.log('settings: ', this.defaultSettings);
|
||||
this.display(contentEl, this.yaml, this.plugin, this.defaultSettings, this.display, this.el, this.ctx);
|
||||
}
|
||||
|
||||
|
|
@ -75,8 +71,6 @@ export class FolderOverviewSettings extends Modal {
|
|||
contentEl.createEl('h2', { text: 'Default folder overview settings' });
|
||||
}
|
||||
|
||||
console.log('yaml 4: ', yaml);
|
||||
console.log('settings: ', defaultSettings);
|
||||
createOverviewSettings(contentEl, yaml, plugin, defaultSettings, display, el, ctx, undefined, undefined, modal);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { MarkdownPostProcessorContext, Plugin, PluginSettingTab, Setting, TFile, TFolder } from 'obsidian';
|
||||
import { MarkdownPostProcessorContext, Plugin, Plugin$1, PluginSettingTab, Setting, TFile, TFolder } from 'obsidian';
|
||||
import { updateYaml, updateYamlById, overviewSettings, includeTypes } from './FolderOverview';
|
||||
import { FolderSuggest } from './suggesters/FolderSuggester';
|
||||
import { ListComponent } from './utils/ListComponent';
|
||||
|
|
@ -29,8 +29,25 @@ export const DEFAULT_SETTINGS: overviewSettings = {
|
|||
alwaysCollapse: false,
|
||||
}
|
||||
|
||||
export class SettingsTab extends PluginSettingTab {
|
||||
plugin: FolderOverviewPlugin;
|
||||
|
||||
constructor(plugin: FolderOverviewPlugin) {
|
||||
super(plugin.app, plugin);
|
||||
}
|
||||
|
||||
display() {
|
||||
const { containerEl } = this;
|
||||
|
||||
this.display = this.display.bind(this);
|
||||
|
||||
containerEl.empty();
|
||||
createOverviewSettings(containerEl, this.plugin.settings, this.plugin, this.plugin.settings, this.display, undefined, undefined, undefined, this);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export async function createOverviewSettings(contentEl: HTMLElement, yaml: overviewSettings, plugin: FolderOverviewPlugin | FolderNotesPlugin, defaultSettings: overviewSettings, display: CallableFunction, el?: HTMLElement, ctx?: MarkdownPostProcessorContext, file?: TFile | null, settingsTab?: PluginSettingTab, modal?: FolderOverviewSettings) {
|
||||
console.log('yaml 5: ', yaml);
|
||||
new Setting(contentEl)
|
||||
.setName('Show the title')
|
||||
.setDesc('Choose if the title should be shown')
|
||||
|
|
@ -242,7 +259,7 @@ export async function createOverviewSettings(contentEl: HTMLElement, yaml: overv
|
|||
|
||||
if (yaml.showEmptyFolders) {
|
||||
new Setting(contentEl)
|
||||
.setName('Only show first empty subfolders of current folder')
|
||||
.setName('Only show empty folders which are on the first level of the folder overview')
|
||||
.addToggle((toggle) => {
|
||||
toggle
|
||||
.setValue(yaml.onlyIncludeSubfolders)
|
||||
|
|
@ -282,7 +299,7 @@ export async function createOverviewSettings(contentEl: HTMLElement, yaml: overv
|
|||
}
|
||||
|
||||
async function updateSettings(contentEl: HTMLElement, yaml: overviewSettings, plugin: FolderOverviewPlugin | FolderNotesPlugin, defaultSettings: overviewSettings, el?: HTMLElement, ctx?: MarkdownPostProcessorContext, file?: TFile | null) {
|
||||
if (defaultSettings) {
|
||||
if (!yaml.id) {
|
||||
return plugin.saveSettings();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export class ListComponent {
|
|||
}
|
||||
span.setAttribute('extension', value);
|
||||
const removeSpan = span.createEl('span', { cls: 'ofn-list-item-remove setting-hotkey-icon' });
|
||||
const svg = '<svg xmlns='http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18'></line></svg>';
|
||||
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
|
||||
const svgElement = removeSpan.createEl('span', { cls: 'ofn-list-item-remove-icon' });
|
||||
svgElement.innerHTML = svg;
|
||||
removeSpan.onClickEvent((e) => {
|
||||
|
|
@ -73,7 +73,7 @@ export class ListComponent {
|
|||
|
||||
addResetButton() {
|
||||
const resetButton = this.controlEl.createEl('span', { cls: 'clickable-icon setting-restore-hotkey-button' });
|
||||
const svg = '<svg xmlns='http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-rotate-ccw"><path d="M3 2v6h6"></path><path d="M3 13a9 9 0 1 0 3-7.7L3 8'></path></svg>';
|
||||
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-rotate-ccw"><path d="M3 2v6h6"></path><path d="M3 13a9 9 0 1 0 3-7.7L3 8"></path></svg>';
|
||||
resetButton.innerHTML = svg;
|
||||
resetButton.onClickEvent((e) => {
|
||||
this.setValues(this.defaultValues);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ export class FolderOverviewView extends ItemView {
|
|||
this.plugin = plugin;
|
||||
|
||||
this.display = this.display.bind(this);
|
||||
if (plugin instanceof FolderOverviewPlugin) {
|
||||
this.defaultSettings = this.plugin.settings as overviewSettings;
|
||||
} else {
|
||||
this.defaultSettings = plugin.settings.defaultOverview;
|
||||
}
|
||||
|
||||
this.registerEvent(
|
||||
this.plugin.app.workspace.on('file-open', (file) => {
|
||||
|
|
@ -95,9 +100,8 @@ export class FolderOverviewView extends ItemView {
|
|||
|
||||
cb.addOption('default', 'Default');
|
||||
cb.setValue(yaml?.id ?? 'default');
|
||||
console.log(yaml);
|
||||
|
||||
if (cb.getValue() === 'default' || defaultSettings) {
|
||||
if (cb.getValue() === 'default' || !yaml?.id.trim()) {
|
||||
yaml = defaultSettings;
|
||||
cb.setValue('default');
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export class ListComponent {
|
|||
}
|
||||
span.setAttribute('extension', value);
|
||||
const removeSpan = span.createEl('span', { cls: 'ofn-list-item-remove setting-hotkey-icon' });
|
||||
const svg = '<svg xmlns='http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18'></line></svg>';
|
||||
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
|
||||
const svgElement = removeSpan.createEl('span', { cls: 'ofn-list-item-remove-icon' });
|
||||
svgElement.innerHTML = svg;
|
||||
removeSpan.onClickEvent((e) => {
|
||||
|
|
@ -73,7 +73,7 @@ export class ListComponent {
|
|||
|
||||
addResetButton() {
|
||||
const resetButton = this.controlEl.createEl('span', { cls: 'clickable-icon setting-restore-hotkey-button' });
|
||||
const svg = '<svg xmlns='http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-rotate-ccw"><path d="M3 2v6h6"></path><path d="M3 13a9 9 0 1 0 3-7.7L3 8'></path></svg>';
|
||||
const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-rotate-ccw"><path d="M3 2v6h6"></path><path d="M3 13a9 9 0 1 0 3-7.7L3 8"></path></svg>';
|
||||
resetButton.innerHTML = svg;
|
||||
resetButton.onClickEvent((e) => {
|
||||
this.setValues(this.defaultValues);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export default class AddSupportedFileModal extends Modal {
|
|||
});
|
||||
contentEl.createEl('h2', { text: 'Extension name' });
|
||||
new Setting(contentEl)
|
||||
.setName('Enter the name of the extension (only the short form, e.g. 'md')')
|
||||
.setName('Enter the name of the extension (only the short form, e.g. "md")')
|
||||
.addText((text) =>
|
||||
text
|
||||
.setValue('')
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export default class DeleteConfirmationModal extends Modal {
|
|||
modalContent.createEl('p', { text: 'It will be moved to your system trash.' });
|
||||
break;
|
||||
case 'obsidianTrash':
|
||||
modalContent.createEl('p', { text: 'It will be moved to your Obsidian trash, which is located in the '.trash' hidden folder in your vault.' });
|
||||
modalContent.createEl('p', { text: 'It will be moved to your Obsidian trash, which is located in the ".trash" hidden folder in your vault.' });
|
||||
break;
|
||||
case 'delete':
|
||||
modalContent.createEl('p', { text: 'It will be permanently deleted.' }).setCssStyles({ color: 'red' });
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export async function renderGeneral(settingsTab: SettingsTab) {
|
|||
if (settingsTab.plugin.settings.newFolderNoteName !== '{{folder_name}}') {
|
||||
new Setting(containerEl)
|
||||
.setName('Use folder name instead of folder note name in the tab title')
|
||||
.setDesc('When you\'re using a folder note name like 'folder note' and have multiple folder notes open you can\'t separate them anymore by their name. This setting uses the folder name instead and allows you to indentify the different files.')
|
||||
.setDesc('When you\'re using a folder note name like "folder note" and have multiple folder notes open you can\'t separate them anymore by their name. This setting uses the folder name instead and allows you to indentify the different files.')
|
||||
.addToggle((toggle) =>
|
||||
toggle
|
||||
.setValue(settingsTab.plugin.settings.tabManagerEnabled)
|
||||
|
|
|
|||
Loading…
Reference in a new issue