generated from tpl/obsidian-sample-plugin
			Add error handling for create entry errors
This commit is contained in:
		
							parent
							
								
									09d1b08f7d
								
							
						
					
					
						commit
						e64e28cbe3
					
				| 
						 | 
				
			
			@ -8,7 +8,7 @@ const GOODREADS_URL_PATTERN = /https:\/\/www.goodreads.com\/book\/show\/(\d+)/;
 | 
			
		|||
export class CreateBookFromGoodreadsUrlCommand extends Command {
 | 
			
		||||
	constructor(
 | 
			
		||||
		private readonly goodreads: Goodreads,
 | 
			
		||||
		private readonly cb: (book: Book) => void | PromiseLike<void>
 | 
			
		||||
		private readonly createEntry: (book: Book) => void | PromiseLike<void>
 | 
			
		||||
	) {
 | 
			
		||||
		super(
 | 
			
		||||
			"create-book-from-goodreads-url",
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +40,14 @@ export class CreateBookFromGoodreadsUrlCommand extends Command {
 | 
			
		|||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		await this.cb(book);
 | 
			
		||||
		try {
 | 
			
		||||
			await this.createEntry(book);
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			console.error("Failed to create book:", error);
 | 
			
		||||
			new Notice("Failed to create book. Check console for details.");
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		new Notice("Book created from Goodreads URL.");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ export class SearchGoodreadsCommand extends Command {
 | 
			
		|||
	constructor(
 | 
			
		||||
		private readonly app: App,
 | 
			
		||||
		private readonly goodreads: Goodreads,
 | 
			
		||||
		private readonly cb: (book: Book) => void
 | 
			
		||||
		private readonly createEntry: (book: Book) => void | PromiseLike<void>
 | 
			
		||||
	) {
 | 
			
		||||
		super("search-goodreads", "Search Goodreads");
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +50,14 @@ export class SearchGoodreadsCommand extends Command {
 | 
			
		|||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.cb(book);
 | 
			
		||||
		try {
 | 
			
		||||
			await this.createEntry(book);
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			console.error("Failed to create book:", error);
 | 
			
		||||
			new Notice("Failed to create book. Check console for details.");
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		new Notice("Book created from search result.");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										46
									
								
								src/main.ts
								
								
								
								
							
							
						
						
									
										46
									
								
								src/main.ts
								
								
								
								
							| 
						 | 
				
			
			@ -140,34 +140,30 @@ export default class BookTrackerPlugin extends Plugin {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	async createEntry(book: Book): Promise<void> {
 | 
			
		||||
		try {
 | 
			
		||||
			const fileName = this.templater
 | 
			
		||||
				.renderTemplate(this.settings.fileNameFormat, {
 | 
			
		||||
					title: book.title,
 | 
			
		||||
					authors: book.authors.map((a) => a.name).join(", "),
 | 
			
		||||
				})
 | 
			
		||||
				.replace(/[/:*?<>|""]/g, "");
 | 
			
		||||
		const fileName = this.templater
 | 
			
		||||
			.renderTemplate(this.settings.fileNameFormat, {
 | 
			
		||||
				title: book.title,
 | 
			
		||||
				authors: book.authors.map((a) => a.name).join(", "),
 | 
			
		||||
			})
 | 
			
		||||
			.replace(/[/:*?<>|""]/g, "");
 | 
			
		||||
 | 
			
		||||
			const data: Record<string, unknown> = { book };
 | 
			
		||||
		const data: Record<string, unknown> = { book };
 | 
			
		||||
 | 
			
		||||
			if (this.settings.downloadCovers && book.coverImageUrl) {
 | 
			
		||||
				const coverImageFile = await this.downloadCoverImage(
 | 
			
		||||
					book.coverImageUrl,
 | 
			
		||||
					fileName
 | 
			
		||||
				);
 | 
			
		||||
				data.coverImagePath = coverImageFile.path;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			const renderedContent = await this.templater.renderTemplateFile(
 | 
			
		||||
				this.settings.templateFile,
 | 
			
		||||
				data
 | 
			
		||||
		if (this.settings.downloadCovers && book.coverImageUrl) {
 | 
			
		||||
			const coverImageFile = await this.downloadCoverImage(
 | 
			
		||||
				book.coverImageUrl,
 | 
			
		||||
				fileName
 | 
			
		||||
			);
 | 
			
		||||
 | 
			
		||||
			const filePath = this.settings.tbrFolder + "/" + fileName + ".md";
 | 
			
		||||
			const file = await this.app.vault.create(filePath, renderedContent);
 | 
			
		||||
			await this.app.workspace.getLeaf().openFile(file);
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			console.error("Failed to create book entry:", error);
 | 
			
		||||
			data.coverImagePath = coverImageFile.path;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const renderedContent = await this.templater.renderTemplateFile(
 | 
			
		||||
			this.settings.templateFile,
 | 
			
		||||
			data
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		const filePath = this.settings.tbrFolder + "/" + fileName + ".md";
 | 
			
		||||
		const file = await this.app.vault.create(filePath, renderedContent);
 | 
			
		||||
		await this.app.workspace.getLeaf().openFile(file);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,14 +8,12 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
	import { clickOutside } from "@ui/directives";
 | 
			
		||||
 | 
			
		||||
	import { App, Scope } from "obsidian";
 | 
			
		||||
	import { onMount, type Snippet } from "svelte";
 | 
			
		||||
	import { createPopperActions } from "svelte-popperjs";
 | 
			
		||||
 | 
			
		||||
	type T = $$Generic;
 | 
			
		||||
 | 
			
		||||
	type Props = {
 | 
			
		||||
		app: App;
 | 
			
		||||
		id: string;
 | 
			
		||||
		items: Item<T>[];
 | 
			
		||||
		value?: T;
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +24,6 @@
 | 
			
		|||
	};
 | 
			
		||||
 | 
			
		||||
	let {
 | 
			
		||||
		app,
 | 
			
		||||
		id,
 | 
			
		||||
		items,
 | 
			
		||||
		value = $bindable(),
 | 
			
		||||
| 
						 | 
				
			
			@ -41,8 +38,8 @@
 | 
			
		|||
	let selectedIndex = $state(0);
 | 
			
		||||
	let listEl: HTMLUListElement | null = $state(null);
 | 
			
		||||
 | 
			
		||||
	onMount(async () => {
 | 
			
		||||
		await onChange?.(query);
 | 
			
		||||
	$effect(() => {
 | 
			
		||||
		onChange?.(query);
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	$effect.root(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +98,6 @@
 | 
			
		|||
		const item = items[index];
 | 
			
		||||
		if (!item) return;
 | 
			
		||||
		const { text: newQuery, value: newValue } = item;
 | 
			
		||||
 | 
			
		||||
		selectedIndex = index;
 | 
			
		||||
		expanded = false;
 | 
			
		||||
		query = newQuery;
 | 
			
		||||
| 
						 | 
				
			
			@ -110,11 +106,6 @@
 | 
			
		|||
		await onSelected?.(newValue);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async function handleInput() {
 | 
			
		||||
		expanded = true;
 | 
			
		||||
		await onChange?.(query);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async function clearSearch() {
 | 
			
		||||
		query = "";
 | 
			
		||||
		value = undefined;
 | 
			
		||||
| 
						 | 
				
			
			@ -159,7 +150,6 @@
 | 
			
		|||
	class:is-loading={loading}
 | 
			
		||||
	aria-busy={loading}
 | 
			
		||||
	use:clickOutside={() => (expanded = false)}
 | 
			
		||||
	onfocusout={() => (expanded = false)}
 | 
			
		||||
>
 | 
			
		||||
	<div class="search-input-container">
 | 
			
		||||
		<input
 | 
			
		||||
| 
						 | 
				
			
			@ -171,7 +161,7 @@
 | 
			
		|||
			spellcheck="false"
 | 
			
		||||
			role="combobox"
 | 
			
		||||
			bind:value={query}
 | 
			
		||||
			oninput={handleInput}
 | 
			
		||||
			oninput={() => (expanded = true)}
 | 
			
		||||
			onfocusin={() => (expanded = true)}
 | 
			
		||||
			aria-controls={`${id}-list`}
 | 
			
		||||
			aria-autocomplete="list"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,6 @@
 | 
			
		|||
	import type BookTrackerPlugin from "@src/main";
 | 
			
		||||
	import { createSettingsStore } from "./store";
 | 
			
		||||
	import { onMount } from "svelte";
 | 
			
		||||
	import FieldSuggest from "@ui/components/suggesters/FieldSuggest.svelte";
 | 
			
		||||
 | 
			
		||||
	type Props = {
 | 
			
		||||
		plugin: BookTrackerPlugin;
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +44,7 @@
 | 
			
		|||
		id="read-folder"
 | 
			
		||||
		name="Read Books Folder"
 | 
			
		||||
		description="Select the folder to use for Read entries."
 | 
			
		||||
		bind:value={$settings.tbrFolder}
 | 
			
		||||
		bind:value={$settings.readBooksFolder}
 | 
			
		||||
	/>
 | 
			
		||||
	<ToggleItem
 | 
			
		||||
		id="organize-read-books"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue