Skip to content

Align the look of Startup-Scripts settings with core CSS snippets #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion jsEngine/api/Internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ export class InternalAPI {
* Runs all startup scripts defined in the plugins settings.
*/
public async executeStartupScripts(): Promise<void> {
for (const script of this.apiInstance.plugin.settings.startupScripts ?? []) {
for (const script of this.apiInstance.plugin.settings.startupScripts) {
await this.executeFileSimple(script);
}
}
Expand Down
6 changes: 6 additions & 0 deletions jsEngine/obsidian-ex.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ declare module 'obsidian' {
plugins: Record<string, Plugin>;
getPlugin: (plugin: string) => Plugin;
};

/**
* Open a file or folder with the systems default app for it.
* @param path a normalized path to open
*/
openWithDefaultApp(path: string): void;
}

interface MenuItem {
Expand Down
129 changes: 119 additions & 10 deletions jsEngine/settings/Settings.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import type JsEnginePlugin from 'jsEngine/main';
import { StartupScriptsModal } from 'jsEngine/settings/StartupScriptModal';
import type { App } from 'obsidian';
import { PluginSettingTab, Setting } from 'obsidian';
import { normalizePath, PluginSettingTab, Setting, TFile, TFolder } from 'obsidian';

export interface JsEnginePluginSettings {
startupScripts?: string[];
startupScriptsDirectory: string | undefined;
startupScripts: string[];
}

export const JS_ENGINE_DEFAULT_SETTINGS: JsEnginePluginSettings = {
startupScriptsDirectory: undefined,
startupScripts: [],
};

Expand All @@ -20,18 +21,126 @@ export class JsEnginePluginSettingTab extends PluginSettingTab {
}

display(): void {
this.containerEl.empty();
const containerEl = this.containerEl;
const vault = this.app.vault;
const settings = this.plugin.settings;
containerEl.empty();

if (!this.plugin.settings) {
if (!settings) {
return;
}

// this.containerEl.createEl('p', { text: 'Currently Empty, but there will be stuff here later.' });
new Setting(containerEl)
.setName('JS snippets (loaded on startup)')
.setHeading()
.addExtraButton(el => {
el.setTooltip('Reload snippets')
.setIcon('refresh-cw')
.onClick(() => this.display());
})
.addExtraButton(el => {
el.setTooltip('Open snippets folder')
.setIcon('folder-open')
.onClick(async () => await this.openStartupScriptsDirectory());
});

new Setting(this.containerEl).setName('Startup scripts').addButton(button => {
button.setButtonText('Manage').onClick(() => {
new StartupScriptsModal(this.plugin).open();
new Setting(containerEl)
.setName('Custom JS Snippets Folder')
.setDesc('The folder to search for JavaScript files to load')
.addText(el => {
el.setPlaceholder('Folder')
.setValue(settings.startupScriptsDirectory ?? '')
.inputEl.addEventListener('focusout', ev => {
const target = ev.currentTarget as HTMLInputElement;
settings.startupScriptsDirectory = target.value ? normalizePath(target.value) : JS_ENGINE_DEFAULT_SETTINGS.startupScriptsDirectory;
void this.plugin.saveSettings();
this.display();
});
});
});

const startupScriptsDirectory = vault.getFolderByPath(settings.startupScriptsDirectory ?? '/');
let startupScripts: TFile[] = [];
if (startupScriptsDirectory != null) {
startupScripts = this.listJSfilesInDirectory(startupScriptsDirectory);
}
if (startupScripts.length == 0) {
new Setting(containerEl).setName('No JS snippets found').setDesc(`JS snippets are stored in "vault/${settings.startupScriptsDirectory ?? ''}"`);
} else {
for (const file of startupScripts) {
new Setting(containerEl)
.setName(file.basename)
.setDesc(`Apply JS snippet from "vault/${file.path}"`)
.addToggle(el => {
el.setValue(settings.startupScripts.contains(file.path)).onChange(async val => this.toggleStartupScript(file, val));
});
}
}

const oldScripts = settings.startupScripts
.map(file => vault.getFileByPath(file)!)
.filter(file => !this.isParentDir(file, settings.startupScriptsDirectory ?? '/'));
if (oldScripts.length > 0) {
this.containerEl.createEl('div', { cls: 'callout js-engine-settings-warning', text: 'These scripts are not in the Snippets Folder' });
for (const file of oldScripts) {
new Setting(containerEl)
.setName(file.basename)
.setDesc(`Apply JS snippet from "vault/${file.path}"`)
.addExtraButton(el => {
el.setTooltip('Move to current Snippets Folder')
.setIcon('archive-restore')
.onClick(async () => await this.moveStartupScriptToNewDirectory(file));
})
.addToggle(el => {
el.setValue(settings.startupScripts.contains(file.path)).onChange(async val => this.toggleStartupScript(file, val));
});
}
}
}

async openStartupScriptsDirectory(): Promise<void> {
const vault = this.app.vault;
const directory = this.plugin.settings.startupScriptsDirectory ?? '/';
if (!(await vault.adapter.exists(directory))) {
await vault.createFolder(directory);
}
this.app.openWithDefaultApp(directory);
}

listJSfilesInDirectory(directory: TFolder): TFile[] {
const files = directory.children.filter(el => el instanceof TFile);
const folders = directory.children.filter(el => el instanceof TFolder);
return files.filter(f => f.extension == 'js').concat(folders.flatMap(dir => this.listJSfilesInDirectory(dir)));
}

isParentDir(pathnode: TFile | TFolder, parent: string): boolean {
if (pathnode.parent == null) return false;
if (pathnode.parent.path == parent) return true;
return this.isParentDir(pathnode.parent, parent);
}

async toggleStartupScript(file: TFile, enable: boolean): Promise<void> {
const settings = this.plugin.settings;
if (enable) {
settings.startupScripts.push(file.path);
void this.plugin.api.internal.executeFileSimple(file.path);
} else {
settings.startupScripts.remove(file.path);
}
await this.plugin.saveSettings();
}

async moveStartupScriptToNewDirectory(script: TFile): Promise<void> {
const settings = this.plugin.settings;
const vault = this.app.vault;
const startupScriptsDirectory = settings.startupScriptsDirectory ?? '/';
const newPath = startupScriptsDirectory.concat('/', script.name);
if ((await vault.adapter.exists(startupScriptsDirectory)) == false) {
await vault.createFolder(startupScriptsDirectory);
}
settings.startupScripts.remove(script.path);
await this.app.vault.rename(script, newPath);
settings.startupScripts.push(newPath);
await this.plugin.saveSettings();
this.display();
}
}
37 changes: 0 additions & 37 deletions jsEngine/settings/StartupScriptModal.ts

This file was deleted.

91 changes: 0 additions & 91 deletions jsEngine/settings/StartupScripts.svelte

This file was deleted.

9 changes: 9 additions & 0 deletions styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,12 @@ If your plugin does not need CSS, delete this file.
left: 0;
right: 0;
}

.js-engine-settings-warning {
--callout-color: var(--callout-warning);
color: rgb(var(--callout-color));
margin-bottom: 0;
padding-block: 0.25em;
border-bottom-left-radius: unset;
border-bottom-right-radius: unset;
}