Implement feedback from PR - making use of built-ins

This commit is contained in:
Alejandro Daniel Noel 2024-06-11 20:51:40 +02:00
parent 86d9722d68
commit e1659137bd
4 changed files with 20 additions and 220 deletions

View file

@ -175,7 +175,7 @@ class Node {
const child = this.children.find(child => child.tagComponent() === nextComponent);
return child ? child.findChildNode(tagPath) : undefined;
}
console.log("ERROR: did not find node at path \"" + tagPath + "\"");
console.error("Did not find node at path \"" + tagPath + "\"");
return undefined;
}
@ -204,7 +204,7 @@ class Node {
const newNode = new Node(nextTagPath, this.settings, this.app);
const success = newNode.addNoteWithPath(tagPath, note, hasPriority, isIndex);
if (!success) {
console.log("ERROR: could not add path for note: ", tagPath + "|" + nextTagPath, this);
console.error("Could not add path for note: ", tagPath + "|" + nextTagPath, this);
}
this.children.push(newNode);
return success;
@ -343,7 +343,7 @@ export class IndexUpdater {
fileTags = fileTags.split(',').map(tag => tag.trim());
}
if (!fileTags || !Array.isArray(fileTags)) {
console.log("File tags are not an array: ", fileTags);
console.error("File tags are not an array: ", fileTags);
return;
}
const hasPriorityTag = fileTags.includes(this.settings.priority_tag);

View file

@ -1,11 +1,12 @@
// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes
// @ts-ignore
import { App, TAbstractFile, TFolder, TFile, AbstractInputSuggest } from "obsidian";
import { TAbstractFile, TFolder } from "obsidian";
import { TextInputSuggest } from "./suggest";
export class FolderSuggest extends AbstractInputSuggest<TFolder> {
textInputEl: HTMLInputElement;
export class FolderSuggest extends TextInputSuggest<TFolder> {
getSuggestions(inputStr: string): TFolder[] {
const abstractFiles = app.vault.getAllLoadedFiles();
// @ts-ignore
const abstractFiles = this.app.vault.getAllLoadedFiles();
const folders: TFolder[] = [];
const lowerCaseInputStr = inputStr.toLowerCase();
@ -26,8 +27,9 @@ export class FolderSuggest extends TextInputSuggest<TFolder> {
}
selectSuggestion(file: TFolder): void {
this.inputEl.value = file.path;
this.inputEl.trigger("input");
this.textInputEl.value = file.path;
this.textInputEl.trigger("input");
// @ts-ignore
this.close();
}
}
}

View file

@ -1,7 +1,6 @@
import { App, Notice, PluginSettingTab, Setting, TFile } from 'obsidian';
import { App, Notice, PluginSettingTab, Setting, parseYaml } from 'obsidian';
import IndexNotesPlugin from "main";
import { FolderSuggest } from "./suggesters/FolderSuggester";
import YAML from 'yaml'
import { FolderSuggest } from "./FolderSuggester";
export interface IndexNotesSettings {
update_interval_seconds: number;
@ -33,7 +32,6 @@ export class IndexNotesSettingTab extends PluginSettingTab {
display(): void {
this.containerEl.empty();
this.containerEl.createEl('h2', { text: 'Settings for Index Notes plugin' });
this.add_index_tag_setting();
this.add_meta_index_tag_setting();
this.add_priority_tag_setting();
@ -127,18 +125,20 @@ export class IndexNotesSettingTab extends PluginSettingTab {
}
add_exclude_folders_setting() {
this.containerEl.createEl("h2", { text: "Excluded folders from indexing" });
new Setting(this.containerEl).setName("Add excluded folder").setHeading();
this.plugin.settings.exclude_folders.forEach((template, index) => {
const s = new Setting(this.containerEl)
.addSearch((cb) => {
new FolderSuggest(cb.inputEl);
// @ts-ignore
new FolderSuggest(this.plugin.app, cb.inputEl);
cb.setPlaceholder("Example: folder1/template_file")
.setValue(template)
.onChange((new_template) => {
try {
if (new_template && this.plugin.settings.exclude_folders.includes(new_template)) {
new Notice("Folder is already excluded");
cb.setValue("");
} else {
this.plugin.settings.exclude_folders[index] = new_template;
this.plugin.saveSettings();
@ -191,7 +191,7 @@ export class IndexNotesSettingTab extends PluginSettingTab {
cb.setValue(this.plugin.settings.metadata_template)
.onChange(async (value) => {
try {
YAML.parse(value.replace(/{{/g, '"{{').replace(/}}/g, '}}"'));
parseYaml(value.replace(/{{/g, '"{{').replace(/}}/g, '}}"'));
cb.inputEl.removeClass("index-notes-metadata-template-error");
this.plugin.settings.metadata_template = value;
await this.plugin.saveSettings();

View file

@ -1,202 +0,0 @@
// Adapted from Templater plugin https://github.com/SilentVoid13/Templater
// Credits go to Liam's Periodic Notes Plugin: https://github.com/liamcain/obsidian-periodic-notes
import { ISuggestOwner, Scope } from "obsidian";
import { createPopper, Instance as PopperInstance } from "@popperjs/core";
const wrapAround = (value: number, size: number): number => {
return ((value % size) + size) % size;
};
class Suggest<T> {
private owner: ISuggestOwner<T>;
private values: T[];
private suggestions: HTMLDivElement[];
private selectedItem: number;
private containerEl: HTMLElement;
constructor(
owner: ISuggestOwner<T>,
containerEl: HTMLElement,
scope: Scope
) {
this.owner = owner;
this.containerEl = containerEl;
containerEl.on(
"click",
".suggestion-item",
this.onSuggestionClick.bind(this)
);
containerEl.on(
"mousemove",
".suggestion-item",
this.onSuggestionMouseover.bind(this)
);
scope.register([], "ArrowUp", (event) => {
if (!event.isComposing) {
this.setSelectedItem(this.selectedItem - 1, true);
return false;
}
});
scope.register([], "ArrowDown", (event) => {
if (!event.isComposing) {
this.setSelectedItem(this.selectedItem + 1, true);
return false;
}
});
scope.register([], "Enter", (event) => {
if (!event.isComposing) {
this.useSelectedItem(event);
return false;
}
});
}
onSuggestionClick(event: MouseEvent, el: HTMLDivElement): void {
event.preventDefault();
const item = this.suggestions.indexOf(el);
this.setSelectedItem(item, false);
this.useSelectedItem(event);
}
onSuggestionMouseover(_event: MouseEvent, el: HTMLDivElement): void {
const item = this.suggestions.indexOf(el);
this.setSelectedItem(item, false);
}
setSuggestions(values: T[]) {
this.containerEl.empty();
const suggestionEls: HTMLDivElement[] = [];
values.forEach((value) => {
const suggestionEl = this.containerEl.createDiv("suggestion-item");
this.owner.renderSuggestion(value, suggestionEl);
suggestionEls.push(suggestionEl);
});
this.values = values;
this.suggestions = suggestionEls;
this.setSelectedItem(0, false);
}
useSelectedItem(event: MouseEvent | KeyboardEvent) {
const currentValue = this.values[this.selectedItem];
if (currentValue) {
this.owner.selectSuggestion(currentValue, event);
}
}
setSelectedItem(selectedIndex: number, scrollIntoView: boolean) {
const normalizedIndex = wrapAround(
selectedIndex,
this.suggestions.length
);
const prevSelectedSuggestion = this.suggestions[this.selectedItem];
const selectedSuggestion = this.suggestions[normalizedIndex];
prevSelectedSuggestion?.removeClass("is-selected");
selectedSuggestion?.addClass("is-selected");
this.selectedItem = normalizedIndex;
if (scrollIntoView) {
selectedSuggestion.scrollIntoView(false);
}
}
}
export abstract class TextInputSuggest<T> implements ISuggestOwner<T> {
protected inputEl: HTMLInputElement | HTMLTextAreaElement;
private popper: PopperInstance;
private scope: Scope;
private suggestEl: HTMLElement;
private suggest: Suggest<T>;
constructor(inputEl: HTMLInputElement | HTMLTextAreaElement) {
this.inputEl = inputEl;
this.scope = new Scope();
this.suggestEl = createDiv("suggestion-container");
const suggestion = this.suggestEl.createDiv("suggestion");
this.suggest = new Suggest(this, suggestion, this.scope);
this.scope.register([], "Escape", this.close.bind(this));
this.inputEl.addEventListener("input", this.onInputChanged.bind(this));
this.inputEl.addEventListener("focus", this.onInputChanged.bind(this));
this.inputEl.addEventListener("blur", this.close.bind(this));
this.suggestEl.on(
"mousedown",
".suggestion-container",
(event: MouseEvent) => {
event.preventDefault();
}
);
}
onInputChanged(): void {
const inputStr = this.inputEl.value;
const suggestions = this.getSuggestions(inputStr);
if (!suggestions) {
this.close();
return;
}
if (suggestions.length > 0) {
this.suggest.setSuggestions(suggestions);
this.open(app.dom.appContainerEl, this.inputEl);
app
} else {
this.close();
}
}
open(container: HTMLElement, inputEl: HTMLElement): void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
app.keymap.pushScope(this.scope);
container.appendChild(this.suggestEl);
this.popper = createPopper(inputEl, this.suggestEl, {
placement: "bottom-start",
modifiers: [
{
name: "sameWidth",
enabled: true,
fn: ({ state, instance }) => {
// Note: positioning needs to be calculated twice -
// first pass - positioning it according to the width of the popper
// second pass - position it with the width bound to the reference element
// we need to early exit to avoid an infinite loop
const targetWidth = `${state.rects.reference.width}px`;
if (state.styles.popper.width === targetWidth) {
return;
}
state.styles.popper.width = targetWidth;
instance.update();
},
phase: "beforeWrite",
requires: ["computeStyles"],
},
],
});
}
close(): void {
app.keymap.popScope(this.scope);
this.suggest.setSuggestions([]);
if (this.popper) this.popper.destroy();
this.suggestEl.detach();
}
abstract getSuggestions(inputStr: string): T[];
abstract renderSuggestion(item: T, el: HTMLElement): void;
abstract selectSuggestion(item: T): void;
}