obsidian-book-tracker/src/views/goodreads-search-modal.ts

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();
});
}
}