generated from tpl/obsidian-sample-plugin
71 lines
1.7 KiB
TypeScript
71 lines
1.7 KiB
TypeScript
import { searchBooks } from "@data-sources/goodreads/scraper";
|
|
import { SearchResult } from "@data-sources/goodreads/types";
|
|
import { App, Modal, Notice, TextComponent } from "obsidian";
|
|
|
|
export class GoodreadsSearchModal extends Modal {
|
|
private query: string;
|
|
|
|
constructor(
|
|
app: App,
|
|
private readonly onSearch: (error: any, results: SearchResult[]) => void
|
|
) {
|
|
super(app);
|
|
}
|
|
|
|
async doSearch(): Promise<void> {
|
|
if (!this.query || this.query.trim() === "") {
|
|
this.onSearch(new Error("Search query cannot be empty."), []);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const results = await searchBooks(this.query);
|
|
if (results.length === 0) {
|
|
this.onSearch(
|
|
new Error("No results found for the given query."),
|
|
[]
|
|
);
|
|
return;
|
|
}
|
|
|
|
this.onSearch(null, results);
|
|
} catch (error) {
|
|
this.onSearch(error, []);
|
|
}
|
|
}
|
|
|
|
onOpen(): void {
|
|
const { contentEl } = this;
|
|
contentEl.createEl("h2", { text: "Goodreads Search" });
|
|
contentEl.createDiv({ cls: "obt-goodreads-search__input" }, (el) => {
|
|
new TextComponent(el)
|
|
.setValue(this.query || "")
|
|
.setPlaceholder("Search for books on Goodreads")
|
|
.onChange((value) => {
|
|
this.query = value;
|
|
})
|
|
.inputEl.addEventListener("keydown", (event) => {
|
|
if (event.key === "Enter" && !event.isComposing) {
|
|
event.preventDefault();
|
|
this.doSearch();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
static createAndOpen(app: App): Promise<SearchResult[]> {
|
|
return new Promise((resolve, reject) => {
|
|
const modal = new GoodreadsSearchModal(app, (error, results) => {
|
|
if (error) {
|
|
new Notice(`Error: ${error.message}`);
|
|
reject(error);
|
|
} else {
|
|
resolve(results);
|
|
}
|
|
modal.close();
|
|
});
|
|
modal.open();
|
|
});
|
|
}
|
|
}
|