generated from tpl/obsidian-sample-plugin
			Change how book covers are styled
This commit is contained in:
		
							parent
							
								
									080074511a
								
							
						
					
					
						commit
						791fa96d19
					
				| 
						 | 
					@ -12,8 +12,10 @@
 | 
				
			||||||
	import OpenFileLink from "@ui/components/OpenFileLink.svelte";
 | 
						import OpenFileLink from "@ui/components/OpenFileLink.svelte";
 | 
				
			||||||
	import DateFilter from "@ui/components/DateFilter.svelte";
 | 
						import DateFilter from "@ui/components/DateFilter.svelte";
 | 
				
			||||||
	import BookCover from "@ui/components/BookCover.svelte";
 | 
						import BookCover from "@ui/components/BookCover.svelte";
 | 
				
			||||||
 | 
						import { setAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const { plugin }: SvelteCodeBlockProps = $props();
 | 
						const { plugin }: SvelteCodeBlockProps = $props();
 | 
				
			||||||
 | 
						setAppContext(plugin.app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const settingsStore = createSettings(plugin);
 | 
						const settingsStore = createSettings(plugin);
 | 
				
			||||||
	setSettingsContext(settingsStore);
 | 
						setSettingsContext(settingsStore);
 | 
				
			||||||
| 
						 | 
					@ -88,7 +90,7 @@
 | 
				
			||||||
				{#if metadata[letter]}
 | 
									{#if metadata[letter]}
 | 
				
			||||||
					{@const meta = metadata[letter]}
 | 
										{@const meta = metadata[letter]}
 | 
				
			||||||
					<OpenFileLink file={meta.file}>
 | 
										<OpenFileLink file={meta.file}>
 | 
				
			||||||
						<BookCover app={plugin.app} book={meta.book} />
 | 
											<BookCover book={meta.book} size="fill" />
 | 
				
			||||||
					</OpenFileLink>
 | 
										</OpenFileLink>
 | 
				
			||||||
				{:else}
 | 
									{:else}
 | 
				
			||||||
					<div class="placeholder">{letter}</div>
 | 
										<div class="placeholder">{letter}</div>
 | 
				
			||||||
| 
						 | 
					@ -139,13 +141,6 @@
 | 
				
			||||||
					font-weight: bold;
 | 
										font-weight: bold;
 | 
				
			||||||
					font-style: italic;
 | 
										font-style: italic;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					 | 
				
			||||||
				:global(img) {
 | 
					 | 
				
			||||||
					width: 100%;
 | 
					 | 
				
			||||||
					height: 100%;
 | 
					 | 
				
			||||||
					object-fit: cover;
 | 
					 | 
				
			||||||
					border-radius: var(--radius-l);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,8 +19,10 @@
 | 
				
			||||||
	import OpenFileLink from "@ui/components/OpenFileLink.svelte";
 | 
						import OpenFileLink from "@ui/components/OpenFileLink.svelte";
 | 
				
			||||||
	import moment from "@external/moment";
 | 
						import moment from "@external/moment";
 | 
				
			||||||
	import BookCover from "@ui/components/BookCover.svelte";
 | 
						import BookCover from "@ui/components/BookCover.svelte";
 | 
				
			||||||
 | 
						import { setAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const { plugin }: SvelteCodeBlockProps = $props();
 | 
						const { plugin }: SvelteCodeBlockProps = $props();
 | 
				
			||||||
 | 
						setAppContext(plugin.app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const settingsStore = createSettings(plugin);
 | 
						const settingsStore = createSettings(plugin);
 | 
				
			||||||
	setSettingsContext(settingsStore);
 | 
						setSettingsContext(settingsStore);
 | 
				
			||||||
| 
						 | 
					@ -228,8 +230,8 @@
 | 
				
			||||||
										<div class="cover">
 | 
															<div class="cover">
 | 
				
			||||||
											<OpenFileLink file={meta.file}>
 | 
																<OpenFileLink file={meta.file}>
 | 
				
			||||||
												<BookCover
 | 
																	<BookCover
 | 
				
			||||||
													app={plugin.app}
 | 
					 | 
				
			||||||
													book={meta.book}
 | 
																		book={meta.book}
 | 
				
			||||||
 | 
																		size="fill"
 | 
				
			||||||
												/>
 | 
																	/>
 | 
				
			||||||
											</OpenFileLink>
 | 
																</OpenFileLink>
 | 
				
			||||||
										</div>
 | 
															</div>
 | 
				
			||||||
| 
						 | 
					@ -298,6 +300,7 @@
 | 
				
			||||||
				display: flex;
 | 
									display: flex;
 | 
				
			||||||
				justify-content: space-between;
 | 
									justify-content: space-between;
 | 
				
			||||||
				align-items: center;
 | 
									align-items: center;
 | 
				
			||||||
 | 
									margin-bottom: -12px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				.total-pages-read {
 | 
									.total-pages-read {
 | 
				
			||||||
					font-size: var(--font-smallest);
 | 
										font-size: var(--font-smallest);
 | 
				
			||||||
| 
						 | 
					@ -322,15 +325,6 @@
 | 
				
			||||||
						width: 100%;
 | 
											width: 100%;
 | 
				
			||||||
						height: 100%;
 | 
											height: 100%;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
					 | 
				
			||||||
					:global(img) {
 | 
					 | 
				
			||||||
						border-radius: var(--radius-l);
 | 
					 | 
				
			||||||
						width: 100%;
 | 
					 | 
				
			||||||
						height: 100%;
 | 
					 | 
				
			||||||
						min-width: 100%;
 | 
					 | 
				
			||||||
						min-height: 100%;
 | 
					 | 
				
			||||||
						object-fit: cover;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				&:has(.cover:first-child:nth-last-child(2)) {
 | 
									&:has(.cover:first-child:nth-last-child(2)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,10 @@
 | 
				
			||||||
	import DetailsView from "@ui/components/DetailsView.svelte";
 | 
						import DetailsView from "@ui/components/DetailsView.svelte";
 | 
				
			||||||
	import { setAppContext } from "@ui/stores/app";
 | 
						import { setAppContext } from "@ui/stores/app";
 | 
				
			||||||
	import type { SvelteCodeBlockProps } from "./SvelteCodeBlockRenderer";
 | 
						import type { SvelteCodeBlockProps } from "./SvelteCodeBlockRenderer";
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							createReadingLog,
 | 
				
			||||||
 | 
							setReadingLogContext,
 | 
				
			||||||
 | 
						} from "@ui/stores/reading-log.svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const { plugin, source }: SvelteCodeBlockProps = $props();
 | 
						const { plugin, source }: SvelteCodeBlockProps = $props();
 | 
				
			||||||
	setAppContext(plugin.app);
 | 
						setAppContext(plugin.app);
 | 
				
			||||||
| 
						 | 
					@ -32,6 +36,11 @@
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	setMetadataContext(metadataStore);
 | 
						setMetadataContext(metadataStore);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const readingLog = createReadingLog(plugin.readingLog, {
 | 
				
			||||||
 | 
							disableAllFiltering: true,
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						setReadingLogContext(readingLog);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let view = $state(settings.defaultView);
 | 
						let view = $state(settings.defaultView);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	onDestroy(() => metadataStore.destroy());
 | 
						onDestroy(() => metadataStore.destroy());
 | 
				
			||||||
| 
						 | 
					@ -54,11 +63,11 @@
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	{#if view === "bookshelf"}
 | 
						{#if view === "bookshelf"}
 | 
				
			||||||
		<BookshelfView {plugin} />
 | 
							<BookshelfView />
 | 
				
			||||||
	{:else if view === "table"}
 | 
						{:else if view === "table"}
 | 
				
			||||||
		<TableView {plugin} {settings} />
 | 
							<TableView {settings} />
 | 
				
			||||||
	{:else if view === "details"}
 | 
						{:else if view === "details"}
 | 
				
			||||||
		<DetailsView {plugin} {settings} />
 | 
							<DetailsView {settings} />
 | 
				
			||||||
	{/if}
 | 
						{/if}
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,14 +1,49 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import type { BookMetadata } from "@src/types";
 | 
						import type { BookMetadata } from "@src/types";
 | 
				
			||||||
	import type { App } from "obsidian";
 | 
						import { getAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						type NumberUnit =
 | 
				
			||||||
 | 
							| "cap"
 | 
				
			||||||
 | 
							| "ch"
 | 
				
			||||||
 | 
							| "em"
 | 
				
			||||||
 | 
							| "ex"
 | 
				
			||||||
 | 
							| "ic"
 | 
				
			||||||
 | 
							| "lh"
 | 
				
			||||||
 | 
							| "rcap"
 | 
				
			||||||
 | 
							| "rch"
 | 
				
			||||||
 | 
							| "rem"
 | 
				
			||||||
 | 
							| "rex"
 | 
				
			||||||
 | 
							| "ric"
 | 
				
			||||||
 | 
							| "rlh"
 | 
				
			||||||
 | 
							| "vh"
 | 
				
			||||||
 | 
							| "vw"
 | 
				
			||||||
 | 
							| "vmax"
 | 
				
			||||||
 | 
							| "vmin"
 | 
				
			||||||
 | 
							| "vb"
 | 
				
			||||||
 | 
							| "vi"
 | 
				
			||||||
 | 
							| "cqw"
 | 
				
			||||||
 | 
							| "cqh"
 | 
				
			||||||
 | 
							| "cqi"
 | 
				
			||||||
 | 
							| "cqb"
 | 
				
			||||||
 | 
							| "cqmin"
 | 
				
			||||||
 | 
							| "cqmax"
 | 
				
			||||||
 | 
							| "px"
 | 
				
			||||||
 | 
							| "cm"
 | 
				
			||||||
 | 
							| "mm"
 | 
				
			||||||
 | 
							| "Q"
 | 
				
			||||||
 | 
							| "in"
 | 
				
			||||||
 | 
							| "pc"
 | 
				
			||||||
 | 
							| "pt"
 | 
				
			||||||
 | 
							| "%";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interface Props {
 | 
						interface Props {
 | 
				
			||||||
		app: App;
 | 
					 | 
				
			||||||
		book: BookMetadata;
 | 
							book: BookMetadata;
 | 
				
			||||||
		size?: number;
 | 
							size?: "fill" | number | `${number}${NumberUnit}`;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const { app, book, size }: Props = $props();
 | 
						const { book, size = 500 }: Props = $props();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const app = getAppContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const coverPath = $derived(book.localCoverPath);
 | 
						const coverPath = $derived(book.localCoverPath);
 | 
				
			||||||
	const coverFile = $derived(app.vault.getFileByPath(coverPath));
 | 
						const coverFile = $derived(app.vault.getFileByPath(coverPath));
 | 
				
			||||||
| 
						 | 
					@ -16,12 +51,54 @@
 | 
				
			||||||
		coverFile ? app.vault.getResourcePath(coverFile) : "",
 | 
							coverFile ? app.vault.getResourcePath(coverFile) : "",
 | 
				
			||||||
	);
 | 
						);
 | 
				
			||||||
	const coverAlt = $derived(book.title);
 | 
						const coverAlt = $derived(book.title);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const coverWidth = $derived.by(() => {
 | 
				
			||||||
 | 
							if (size === "fill") {
 | 
				
			||||||
 | 
								return "100%";
 | 
				
			||||||
 | 
							} else if (typeof size === "string") {
 | 
				
			||||||
 | 
								return size;
 | 
				
			||||||
 | 
							} else if (typeof size === "number") {
 | 
				
			||||||
 | 
								return `${size}px`;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return undefined;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const coverHeight = $derived.by(() => {
 | 
				
			||||||
 | 
							if (size === "fill") {
 | 
				
			||||||
 | 
								return "100%";
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return undefined;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<img src={coverSrc} alt={coverAlt} width={size} />
 | 
					<div
 | 
				
			||||||
 | 
						class="book-cover"
 | 
				
			||||||
 | 
						style:--book-cover-width={coverWidth}
 | 
				
			||||||
 | 
						style:--book-cover-height={coverHeight}
 | 
				
			||||||
 | 
					>
 | 
				
			||||||
 | 
						<img src={coverSrc} alt={coverAlt} />
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="scss">
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
						:global(:root) {
 | 
				
			||||||
 | 
							--book-cover-aspect-ratio: 2 / 3;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.book-cover {
 | 
				
			||||||
 | 
							width: var(--book-cover-width);
 | 
				
			||||||
 | 
							height: var(
 | 
				
			||||||
 | 
								--book-cover-height,
 | 
				
			||||||
 | 
								calc(var(--book-cover-width) / (var(--book-cover-aspect-ratio)))
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		img {
 | 
							img {
 | 
				
			||||||
			border-radius: var(--radius-l);
 | 
								border-radius: var(--radius-l);
 | 
				
			||||||
 | 
								height: 100%;
 | 
				
			||||||
 | 
								width: 100%;
 | 
				
			||||||
 | 
								object-fit: cover;
 | 
				
			||||||
 | 
								object-position: center;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,10 +12,7 @@
 | 
				
			||||||
	import { v4 as uuidv4 } from "uuid";
 | 
						import { v4 as uuidv4 } from "uuid";
 | 
				
			||||||
	import memoize from "just-memoize";
 | 
						import memoize from "just-memoize";
 | 
				
			||||||
	import type { TFile } from "obsidian";
 | 
						import type { TFile } from "obsidian";
 | 
				
			||||||
 | 
						import { getAppContext } from "@ui/stores/app";
 | 
				
			||||||
	interface Props {
 | 
					 | 
				
			||||||
		plugin: BookTrackerPlugin;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interface BookData {
 | 
						interface BookData {
 | 
				
			||||||
		id: string;
 | 
							id: string;
 | 
				
			||||||
| 
						 | 
					@ -34,7 +31,7 @@
 | 
				
			||||||
		books: BookData[];
 | 
							books: BookData[];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const { plugin }: Props = $props();
 | 
						const app = getAppContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const metadataStore = getMetadataContext();
 | 
						const metadataStore = getMetadataContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,7 +125,7 @@
 | 
				
			||||||
						design={bookData.design}
 | 
											design={bookData.design}
 | 
				
			||||||
						orientation="flat"
 | 
											orientation="flat"
 | 
				
			||||||
						onClick={() =>
 | 
											onClick={() =>
 | 
				
			||||||
							plugin.app.workspace
 | 
												app.workspace
 | 
				
			||||||
								.getLeaf(false)
 | 
													.getLeaf(false)
 | 
				
			||||||
								.openFile(bookData.file)}
 | 
													.openFile(bookData.file)}
 | 
				
			||||||
					/>
 | 
										/>
 | 
				
			||||||
| 
						 | 
					@ -143,8 +140,7 @@
 | 
				
			||||||
				color={book.color}
 | 
									color={book.color}
 | 
				
			||||||
				design={book.design}
 | 
									design={book.design}
 | 
				
			||||||
				orientation={book.orientation}
 | 
									orientation={book.orientation}
 | 
				
			||||||
				onClick={() =>
 | 
									onClick={() => app.workspace.getLeaf(false).openFile(book.file)}
 | 
				
			||||||
					plugin.app.workspace.getLeaf(false).openFile(book.file)}
 | 
					 | 
				
			||||||
			/>
 | 
								/>
 | 
				
			||||||
		{/if}
 | 
							{/if}
 | 
				
			||||||
	{/each}
 | 
						{/each}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,27 +1,27 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { STATUS_IN_PROGRESS, STATUS_READ } from "@src/const";
 | 
						import { STATUS_IN_PROGRESS, STATUS_READ } from "@src/const";
 | 
				
			||||||
	import type BookTrackerPlugin from "@src/main";
 | 
					 | 
				
			||||||
	import { getMetadataContext } from "@ui/stores/metadata.svelte";
 | 
						import { getMetadataContext } from "@ui/stores/metadata.svelte";
 | 
				
			||||||
	import type { ShelfSettings } from "@ui/code-blocks/ShelfCodeBlock";
 | 
						import type { ShelfSettings } from "@ui/code-blocks/ShelfCodeBlock";
 | 
				
			||||||
	import { Dot, Flame, Star, StarHalf } from "lucide-svelte";
 | 
						import { Dot, Flame, Star, StarHalf } from "lucide-svelte";
 | 
				
			||||||
	import RatingInput from "./RatingInput.svelte";
 | 
						import RatingInput from "./RatingInput.svelte";
 | 
				
			||||||
	import OpenFileLink from "./OpenFileLink.svelte";
 | 
						import OpenFileLink from "./OpenFileLink.svelte";
 | 
				
			||||||
	import BookCover from "./BookCover.svelte";
 | 
						import BookCover from "./BookCover.svelte";
 | 
				
			||||||
 | 
						import { getReadingLogContext } from "@ui/stores/reading-log.svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interface Props {
 | 
						interface Props {
 | 
				
			||||||
		plugin: BookTrackerPlugin;
 | 
					 | 
				
			||||||
		settings: ShelfSettings;
 | 
							settings: ShelfSettings;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const { plugin, settings }: Props = $props();
 | 
						const { settings }: Props = $props();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const metadataStore = getMetadataContext();
 | 
						const metadataStore = getMetadataContext();
 | 
				
			||||||
 | 
						const readingLog = getReadingLogContext();
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="book-details-list">
 | 
					<div class="book-details-list">
 | 
				
			||||||
	{#each metadataStore.metadata as meta}
 | 
						{#each metadataStore.metadata as meta}
 | 
				
			||||||
		<div class="book-details">
 | 
							<div class="book-details">
 | 
				
			||||||
			<BookCover app={plugin.app} book={meta.book} />
 | 
								<BookCover book={meta.book} />
 | 
				
			||||||
			<div class="book-info">
 | 
								<div class="book-info">
 | 
				
			||||||
				<OpenFileLink file={meta.file}>
 | 
									<OpenFileLink file={meta.file}>
 | 
				
			||||||
					<h2 class="book-title">
 | 
										<h2 class="book-title">
 | 
				
			||||||
| 
						 | 
					@ -59,11 +59,18 @@
 | 
				
			||||||
						</p>
 | 
											</p>
 | 
				
			||||||
					{/if}
 | 
										{/if}
 | 
				
			||||||
					{#if settings.statusFilter === STATUS_IN_PROGRESS}
 | 
										{#if settings.statusFilter === STATUS_IN_PROGRESS}
 | 
				
			||||||
 | 
											{@const logEntryIndex =
 | 
				
			||||||
 | 
												readingLog.entries.findLastIndex(
 | 
				
			||||||
 | 
													(e) => e.book === meta.file.basename,
 | 
				
			||||||
 | 
												)}
 | 
				
			||||||
 | 
											{@const logEntry =
 | 
				
			||||||
 | 
												logEntryIndex !== -1
 | 
				
			||||||
 | 
													? readingLog.entries[logEntryIndex]
 | 
				
			||||||
 | 
													: null}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						<Dot color="var(--text-muted)" />
 | 
											<Dot color="var(--text-muted)" />
 | 
				
			||||||
						<p class="current-page">
 | 
											<p class="current-page">
 | 
				
			||||||
							Current Page: {plugin.readingLog.getLastEntryForBook(
 | 
												Current Page: {logEntry?.pagesReadTotal ?? 0}
 | 
				
			||||||
								meta.file.basename,
 | 
					 | 
				
			||||||
							)?.pagesReadTotal ?? 0}
 | 
					 | 
				
			||||||
						</p>
 | 
											</p>
 | 
				
			||||||
					{/if}
 | 
										{/if}
 | 
				
			||||||
					{#if settings.statusFilter === STATUS_READ}
 | 
										{#if settings.statusFilter === STATUS_READ}
 | 
				
			||||||
| 
						 | 
					@ -144,16 +151,20 @@
 | 
				
			||||||
			background-color: var(--background-secondary);
 | 
								background-color: var(--background-secondary);
 | 
				
			||||||
			border-radius: var(--radius-l);
 | 
								border-radius: var(--radius-l);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			:global(img) {
 | 
								:global(.book-cover) {
 | 
				
			||||||
				border-radius: var(--radius-l);
 | 
									width: 100%;
 | 
				
			||||||
 | 
									height: auto;
 | 
				
			||||||
 | 
									max-height: 100%;
 | 
				
			||||||
				max-width: 30%;
 | 
									max-width: 30%;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			@container (width < 600px) {
 | 
								@container (width < 700px) {
 | 
				
			||||||
				flex-direction: column;
 | 
									flex-direction: column;
 | 
				
			||||||
				align-items: center;
 | 
									align-items: center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				:global(img) {
 | 
									:global(.book-cover) {
 | 
				
			||||||
 | 
										height: 100%;
 | 
				
			||||||
 | 
										width: auto;
 | 
				
			||||||
					max-height: 30rem;
 | 
										max-height: 30rem;
 | 
				
			||||||
					max-width: 100%;
 | 
										max-width: 100%;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,5 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { STATUS_IN_PROGRESS, STATUS_READ } from "@src/const";
 | 
						import { STATUS_IN_PROGRESS, STATUS_READ } from "@src/const";
 | 
				
			||||||
	import type BookTrackerPlugin from "@src/main";
 | 
					 | 
				
			||||||
	import { getMetadataContext } from "@ui/stores/metadata.svelte";
 | 
						import { getMetadataContext } from "@ui/stores/metadata.svelte";
 | 
				
			||||||
	import Rating from "@ui/components/Rating.svelte";
 | 
						import Rating from "@ui/components/Rating.svelte";
 | 
				
			||||||
	import type { ShelfSettings } from "@ui/code-blocks/ShelfCodeBlock";
 | 
						import type { ShelfSettings } from "@ui/code-blocks/ShelfCodeBlock";
 | 
				
			||||||
| 
						 | 
					@ -8,11 +7,10 @@
 | 
				
			||||||
	import BookCover from "./BookCover.svelte";
 | 
						import BookCover from "./BookCover.svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interface Props {
 | 
						interface Props {
 | 
				
			||||||
		plugin: BookTrackerPlugin;
 | 
					 | 
				
			||||||
		settings: ShelfSettings;
 | 
							settings: ShelfSettings;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const { plugin, settings }: Props = $props();
 | 
						const { settings }: Props = $props();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const metadataStore = getMetadataContext();
 | 
						const metadataStore = getMetadataContext();
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					@ -38,7 +36,7 @@
 | 
				
			||||||
		{#each metadataStore.metadata as meta}
 | 
							{#each metadataStore.metadata as meta}
 | 
				
			||||||
			<tr>
 | 
								<tr>
 | 
				
			||||||
				<td class="cover">
 | 
									<td class="cover">
 | 
				
			||||||
					<BookCover app={plugin.app} book={meta.book} size={50} />
 | 
										<BookCover book={meta.book} size={50} />
 | 
				
			||||||
				</td>
 | 
									</td>
 | 
				
			||||||
				<td>
 | 
									<td>
 | 
				
			||||||
					<OpenFileLink file={meta.file}>
 | 
										<OpenFileLink file={meta.file}>
 | 
				
			||||||
| 
						 | 
					@ -96,6 +94,10 @@
 | 
				
			||||||
			&.cover {
 | 
								&.cover {
 | 
				
			||||||
				padding: 0;
 | 
									padding: 0;
 | 
				
			||||||
				margin: 0;
 | 
									margin: 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									:global(.book-cover) {
 | 
				
			||||||
 | 
										margin: 0 auto;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,20 +1,18 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import type { ComponentProps } from "svelte";
 | 
						import type { ComponentProps } from "svelte";
 | 
				
			||||||
	import Item from "./Item.svelte";
 | 
						import Item from "./Item.svelte";
 | 
				
			||||||
	import type { App, TFile } from "obsidian";
 | 
					 | 
				
			||||||
	import FileSuggest from "../suggesters/FileSuggest.svelte";
 | 
						import FileSuggest from "../suggesters/FileSuggest.svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type Props = Omit<ComponentProps<typeof Item>, "control"> & {
 | 
						type Props = Omit<ComponentProps<typeof Item>, "control"> & {
 | 
				
			||||||
		app: App;
 | 
					 | 
				
			||||||
		id: string;
 | 
							id: string;
 | 
				
			||||||
		value?: string;
 | 
							value?: string;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { name, description, app, id, value = $bindable() }: Props = $props();
 | 
						let { name, description, id, value = $bindable() }: Props = $props();
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<Item {name} {description}>
 | 
					<Item {name} {description}>
 | 
				
			||||||
	{#snippet control()}
 | 
						{#snippet control()}
 | 
				
			||||||
		<FileSuggest {id} {app} asString bind:value />
 | 
							<FileSuggest {id} asString bind:value />
 | 
				
			||||||
	{/snippet}
 | 
						{/snippet}
 | 
				
			||||||
</Item>
 | 
					</Item>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,20 +1,18 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import type { ComponentProps } from "svelte";
 | 
						import type { ComponentProps } from "svelte";
 | 
				
			||||||
	import Item from "./Item.svelte";
 | 
						import Item from "./Item.svelte";
 | 
				
			||||||
	import type { App, TFolder } from "obsidian";
 | 
					 | 
				
			||||||
	import FolderSuggest from "../suggesters/FolderSuggest.svelte";
 | 
						import FolderSuggest from "../suggesters/FolderSuggest.svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type Props = Omit<ComponentProps<typeof Item>, "control"> & {
 | 
						type Props = Omit<ComponentProps<typeof Item>, "control"> & {
 | 
				
			||||||
		app: App;
 | 
					 | 
				
			||||||
		id: string;
 | 
							id: string;
 | 
				
			||||||
		value?: string;
 | 
							value?: string;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { name, description, app, id, value = $bindable() }: Props = $props();
 | 
						let { name, description, id, value = $bindable() }: Props = $props();
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<Item {name} {description}>
 | 
					<Item {name} {description}>
 | 
				
			||||||
	{#snippet control()}
 | 
						{#snippet control()}
 | 
				
			||||||
		<FolderSuggest {id} {app} asString bind:value />
 | 
							<FolderSuggest {id} asString bind:value />
 | 
				
			||||||
	{/snippet}
 | 
						{/snippet}
 | 
				
			||||||
</Item>
 | 
					</Item>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,18 +1,15 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import type { ComponentProps } from "svelte";
 | 
						import type { ComponentProps } from "svelte";
 | 
				
			||||||
	import Item from "./Item.svelte";
 | 
						import Item from "./Item.svelte";
 | 
				
			||||||
	import type { App } from "obsidian";
 | 
					 | 
				
			||||||
	import PropertySuggest from "../suggesters/PropertySuggest.svelte";
 | 
						import PropertySuggest from "../suggesters/PropertySuggest.svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type Props = Omit<ComponentProps<typeof Item>, "control"> & {
 | 
						type Props = Omit<ComponentProps<typeof Item>, "control"> & {
 | 
				
			||||||
		app: App;
 | 
					 | 
				
			||||||
		id: string;
 | 
							id: string;
 | 
				
			||||||
		value?: string;
 | 
							value?: string;
 | 
				
			||||||
		accepts?: string[];
 | 
							accepts?: string[];
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let {
 | 
						let {
 | 
				
			||||||
		app,
 | 
					 | 
				
			||||||
		name,
 | 
							name,
 | 
				
			||||||
		description,
 | 
							description,
 | 
				
			||||||
		id,
 | 
							id,
 | 
				
			||||||
| 
						 | 
					@ -23,6 +20,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<Item {name} {description}>
 | 
					<Item {name} {description}>
 | 
				
			||||||
	{#snippet control()}
 | 
						{#snippet control()}
 | 
				
			||||||
		<PropertySuggest {app} {id} asString bind:value {accepts} />
 | 
							<PropertySuggest {id} asString bind:value {accepts} />
 | 
				
			||||||
	{/snippet}
 | 
						{/snippet}
 | 
				
			||||||
</Item>
 | 
					</Item>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,10 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import type { App, TFile } from "obsidian";
 | 
						import type { TFile } from "obsidian";
 | 
				
			||||||
	import TextInputSuggest, { type Item } from "./TextInputSuggest.svelte";
 | 
						import TextInputSuggest, { type Item } from "./TextInputSuggest.svelte";
 | 
				
			||||||
	import type { StringKeys } from "@utils/types";
 | 
						import type { StringKeys } from "@utils/types";
 | 
				
			||||||
 | 
						import { getAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type Props = {
 | 
						type Props = {
 | 
				
			||||||
		app: App;
 | 
					 | 
				
			||||||
		id: string;
 | 
							id: string;
 | 
				
			||||||
		asString?: boolean;
 | 
							asString?: boolean;
 | 
				
			||||||
		property?: StringKeys<TFile>;
 | 
							property?: StringKeys<TFile>;
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,6 @@
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let {
 | 
						let {
 | 
				
			||||||
		app,
 | 
					 | 
				
			||||||
		id,
 | 
							id,
 | 
				
			||||||
		asString,
 | 
							asString,
 | 
				
			||||||
		property = "path",
 | 
							property = "path",
 | 
				
			||||||
| 
						 | 
					@ -24,6 +23,7 @@
 | 
				
			||||||
		disabled,
 | 
							disabled,
 | 
				
			||||||
		onSelected,
 | 
							onSelected,
 | 
				
			||||||
	}: Props = $props();
 | 
						}: Props = $props();
 | 
				
			||||||
 | 
						const app = getAppContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let items: Item<TFile | string>[] = $state([]);
 | 
						let items: Item<TFile | string>[] = $state([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,10 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { TFolder, type App } from "obsidian";
 | 
						import { TFolder } from "obsidian";
 | 
				
			||||||
	import TextInputSuggest, { type Item } from "./TextInputSuggest.svelte";
 | 
						import TextInputSuggest, { type Item } from "./TextInputSuggest.svelte";
 | 
				
			||||||
	import type { StringKeys } from "@utils/types";
 | 
						import type { StringKeys } from "@utils/types";
 | 
				
			||||||
 | 
						import { getAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type Props = {
 | 
						type Props = {
 | 
				
			||||||
		app: App;
 | 
					 | 
				
			||||||
		id: string;
 | 
							id: string;
 | 
				
			||||||
		asString?: boolean;
 | 
							asString?: boolean;
 | 
				
			||||||
		property?: StringKeys<TFolder>;
 | 
							property?: StringKeys<TFolder>;
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,6 @@
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let {
 | 
						let {
 | 
				
			||||||
		app,
 | 
					 | 
				
			||||||
		id,
 | 
							id,
 | 
				
			||||||
		asString,
 | 
							asString,
 | 
				
			||||||
		property = "path",
 | 
							property = "path",
 | 
				
			||||||
| 
						 | 
					@ -24,6 +23,7 @@
 | 
				
			||||||
		disabled,
 | 
							disabled,
 | 
				
			||||||
		onSelected,
 | 
							onSelected,
 | 
				
			||||||
	}: Props = $props();
 | 
						}: Props = $props();
 | 
				
			||||||
 | 
						const app = getAppContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let items: Item<TFolder | string>[] = $state([]);
 | 
						let items: Item<TFolder | string>[] = $state([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,11 +6,11 @@
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import type { App } from "obsidian";
 | 
						import { getAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	import TextInputSuggest, { type Item } from "./TextInputSuggest.svelte";
 | 
						import TextInputSuggest, { type Item } from "./TextInputSuggest.svelte";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type Props = {
 | 
						type Props = {
 | 
				
			||||||
		app: App;
 | 
					 | 
				
			||||||
		id: string;
 | 
							id: string;
 | 
				
			||||||
		asString?: boolean;
 | 
							asString?: boolean;
 | 
				
			||||||
		value?: Property | string;
 | 
							value?: Property | string;
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,6 @@
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let {
 | 
						let {
 | 
				
			||||||
		app,
 | 
					 | 
				
			||||||
		id,
 | 
							id,
 | 
				
			||||||
		asString,
 | 
							asString,
 | 
				
			||||||
		value = $bindable(),
 | 
							value = $bindable(),
 | 
				
			||||||
| 
						 | 
					@ -28,6 +27,7 @@
 | 
				
			||||||
		disabled,
 | 
							disabled,
 | 
				
			||||||
		onSelected,
 | 
							onSelected,
 | 
				
			||||||
	}: Props = $props();
 | 
						}: Props = $props();
 | 
				
			||||||
 | 
						const app = getAppContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let items: Item<Property | string>[] = $state([]);
 | 
						let items: Item<Property | string>[] = $state([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ export class GoodreadsSearchModal extends SvelteModal<
 | 
				
			||||||
		goodreads: Goodreads,
 | 
							goodreads: Goodreads,
 | 
				
			||||||
		onSearch: (error: any, results: SearchResult[]) => void = () => {}
 | 
							onSearch: (error: any, results: SearchResult[]) => void = () => {}
 | 
				
			||||||
	) {
 | 
						) {
 | 
				
			||||||
		super(app, GoodreadsSearchModalView, { goodreads, onSearch });
 | 
							super(app, GoodreadsSearchModalView, { app, goodreads, onSearch });
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static createAndOpen(
 | 
						static createAndOpen(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,16 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { Goodreads, type SearchResult } from "@data-sources/Goodreads";
 | 
						import { Goodreads, type SearchResult } from "@data-sources/Goodreads";
 | 
				
			||||||
 | 
						import { setAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
						import type { App } from "obsidian";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interface Props {
 | 
						interface Props {
 | 
				
			||||||
 | 
							app: App;
 | 
				
			||||||
		goodreads: Goodreads;
 | 
							goodreads: Goodreads;
 | 
				
			||||||
		onSearch: (error: any, results?: SearchResult[]) => void;
 | 
							onSearch: (error: any, results?: SearchResult[]) => void;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { goodreads, onSearch }: Props = $props();
 | 
						let { app, goodreads, onSearch }: Props = $props();
 | 
				
			||||||
 | 
						setAppContext(app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let query = $state("");
 | 
						let query = $state("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ export class GoodreadsSearchSuggestModal extends SuggestModal<SearchResult> {
 | 
				
			||||||
	renderSuggestion(searchResult: SearchResult, el: HTMLElement): void {
 | 
						renderSuggestion(searchResult: SearchResult, el: HTMLElement): void {
 | 
				
			||||||
		mount(GoodreadsSearchSuggestion, {
 | 
							mount(GoodreadsSearchSuggestion, {
 | 
				
			||||||
			target: el,
 | 
								target: el,
 | 
				
			||||||
			props: { searchResult },
 | 
								props: { app: this.app, searchResult },
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,15 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import type { SearchResult } from "@data-sources/Goodreads";
 | 
						import type { SearchResult } from "@data-sources/Goodreads";
 | 
				
			||||||
 | 
						import { setAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
						import type { App } from "obsidian";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interface Props {
 | 
						interface Props {
 | 
				
			||||||
 | 
							app: App;
 | 
				
			||||||
		searchResult: SearchResult;
 | 
							searchResult: SearchResult;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { searchResult }: Props = $props();
 | 
						let { app, searchResult }: Props = $props();
 | 
				
			||||||
 | 
						setAppContext(app);
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="obt-goodreads-search-suggestion">
 | 
					<div class="obt-goodreads-search-suggestion">
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ export class RatingModal extends SvelteModal<typeof RatingModalView> {
 | 
				
			||||||
		spiceConfigured: boolean,
 | 
							spiceConfigured: boolean,
 | 
				
			||||||
		onSubmit: (rating: number, spice: number) => void = () => {}
 | 
							onSubmit: (rating: number, spice: number) => void = () => {}
 | 
				
			||||||
	) {
 | 
						) {
 | 
				
			||||||
		super(app, RatingModalView, { spiceConfigured, onSubmit });
 | 
							super(app, RatingModalView, { app, spiceConfigured, onSubmit });
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static createAndOpen(
 | 
						static createAndOpen(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,16 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import RatingInput from "@ui/components/RatingInput.svelte";
 | 
						import RatingInput from "@ui/components/RatingInput.svelte";
 | 
				
			||||||
 | 
						import { setAppContext } from "@ui/stores/app";
 | 
				
			||||||
	import { Flame } from "lucide-svelte";
 | 
						import { Flame } from "lucide-svelte";
 | 
				
			||||||
 | 
						import type { App } from "obsidian";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interface Props {
 | 
						interface Props {
 | 
				
			||||||
 | 
							app: App;
 | 
				
			||||||
		spiceConfigured?: boolean;
 | 
							spiceConfigured?: boolean;
 | 
				
			||||||
		onSubmit: (rating: number, spice: number) => void;
 | 
							onSubmit: (rating: number, spice: number) => void;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	let { spiceConfigured = false, onSubmit }: Props = $props();
 | 
						let { app, spiceConfigured = false, onSubmit }: Props = $props();
 | 
				
			||||||
 | 
						setAppContext(app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let rating = $state(0);
 | 
						let rating = $state(0);
 | 
				
			||||||
	let spice = $state(0);
 | 
						let spice = $state(0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@
 | 
				
			||||||
		setSettingsContext,
 | 
							setSettingsContext,
 | 
				
			||||||
	} from "@ui/stores/settings.svelte";
 | 
						} from "@ui/stores/settings.svelte";
 | 
				
			||||||
	import moment from "@external/moment";
 | 
						import moment from "@external/moment";
 | 
				
			||||||
 | 
						import { setAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const INPUT_DATETIME_FORMAT = "YYYY-MM-DDTHH:mm";
 | 
						const INPUT_DATETIME_FORMAT = "YYYY-MM-DDTHH:mm";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +21,7 @@
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let { plugin, entry, onSubmit }: Props = $props();
 | 
						let { plugin, entry, onSubmit }: Props = $props();
 | 
				
			||||||
 | 
						setAppContext(plugin.app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const settingsStore = createSettings(plugin);
 | 
						const settingsStore = createSettings(plugin);
 | 
				
			||||||
	setSettingsContext(settingsStore);
 | 
						setSettingsContext(settingsStore);
 | 
				
			||||||
| 
						 | 
					@ -80,7 +82,6 @@
 | 
				
			||||||
			<label for="book">Book</label>
 | 
								<label for="book">Book</label>
 | 
				
			||||||
			<FileSuggest
 | 
								<FileSuggest
 | 
				
			||||||
				id="book"
 | 
									id="book"
 | 
				
			||||||
				app={plugin.app}
 | 
					 | 
				
			||||||
				asString
 | 
									asString
 | 
				
			||||||
				property="basename"
 | 
									property="basename"
 | 
				
			||||||
				inFolder={plugin.settings.bookFolder}
 | 
									inFolder={plugin.settings.bookFolder}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ export class ReadingProgressModal extends SvelteModal<
 | 
				
			||||||
		pageCount: number,
 | 
							pageCount: number,
 | 
				
			||||||
		onSubmit: (pageNumber: number) => void = () => {}
 | 
							onSubmit: (pageNumber: number) => void = () => {}
 | 
				
			||||||
	) {
 | 
						) {
 | 
				
			||||||
		super(app, ReadingProgressModalView, { pageCount, onSubmit });
 | 
							super(app, ReadingProgressModalView, { app, pageCount, onSubmit });
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static createAndOpen(app: App, pageCount: number): Promise<number> {
 | 
						static createAndOpen(app: App, pageCount: number): Promise<number> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,14 @@
 | 
				
			||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
	import { Notice } from "obsidian";
 | 
						import { setAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
						import { App, Notice } from "obsidian";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	interface Props {
 | 
						interface Props {
 | 
				
			||||||
 | 
							app: App;
 | 
				
			||||||
		pageCount: number;
 | 
							pageCount: number;
 | 
				
			||||||
		onSubmit: (pageNumber: number) => void;
 | 
							onSubmit: (pageNumber: number) => void;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	let { pageCount, onSubmit }: Props = $props();
 | 
						let { app, pageCount, onSubmit }: Props = $props();
 | 
				
			||||||
 | 
						setAppContext(app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let value = $state(0);
 | 
						let value = $state(0);
 | 
				
			||||||
	let mode: "page-number" | "percentage" = $state("page-number");
 | 
						let mode: "page-number" | "percentage" = $state("page-number");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,13 +9,14 @@
 | 
				
			||||||
	import { createSettings } from "@ui/stores/settings.svelte";
 | 
						import { createSettings } from "@ui/stores/settings.svelte";
 | 
				
			||||||
	import { onMount } from "svelte";
 | 
						import { onMount } from "svelte";
 | 
				
			||||||
	import type { BookTrackerSettings } from "./types";
 | 
						import type { BookTrackerSettings } from "./types";
 | 
				
			||||||
 | 
						import { setAppContext } from "@ui/stores/app";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type Props = {
 | 
						type Props = {
 | 
				
			||||||
		plugin: BookTrackerPlugin;
 | 
							plugin: BookTrackerPlugin;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const { plugin }: Props = $props();
 | 
						const { plugin }: Props = $props();
 | 
				
			||||||
	const { app } = plugin;
 | 
						setAppContext(plugin.app);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const settingsStore = createSettings(plugin);
 | 
						const settingsStore = createSettings(plugin);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -168,21 +169,18 @@
 | 
				
			||||||
<div class="obt-settings">
 | 
					<div class="obt-settings">
 | 
				
			||||||
	<Header title="Folders" />
 | 
						<Header title="Folders" />
 | 
				
			||||||
	<FolderSuggestItem
 | 
						<FolderSuggestItem
 | 
				
			||||||
		{app}
 | 
					 | 
				
			||||||
		id="book-folder"
 | 
							id="book-folder"
 | 
				
			||||||
		name="Book Folder"
 | 
							name="Book Folder"
 | 
				
			||||||
		description="Select the folder where book entries are stored."
 | 
							description="Select the folder where book entries are stored."
 | 
				
			||||||
		bind:value={settingsStore.settings.bookFolder}
 | 
							bind:value={settingsStore.settings.bookFolder}
 | 
				
			||||||
	/>
 | 
						/>
 | 
				
			||||||
	<FolderSuggestItem
 | 
						<FolderSuggestItem
 | 
				
			||||||
		{app}
 | 
					 | 
				
			||||||
		id="tbr-folder"
 | 
							id="tbr-folder"
 | 
				
			||||||
		name="To Be Read Folder"
 | 
							name="To Be Read Folder"
 | 
				
			||||||
		description="Select the folder to use for To Be Read entries"
 | 
							description="Select the folder to use for To Be Read entries"
 | 
				
			||||||
		bind:value={settingsStore.settings.tbrFolder}
 | 
							bind:value={settingsStore.settings.tbrFolder}
 | 
				
			||||||
	/>
 | 
						/>
 | 
				
			||||||
	<FolderSuggestItem
 | 
						<FolderSuggestItem
 | 
				
			||||||
		{app}
 | 
					 | 
				
			||||||
		id="read-folder"
 | 
							id="read-folder"
 | 
				
			||||||
		name="Read Books Folder"
 | 
							name="Read Books Folder"
 | 
				
			||||||
		description="Select the folder to use for Read entries."
 | 
							description="Select the folder to use for Read entries."
 | 
				
			||||||
| 
						 | 
					@ -196,7 +194,6 @@
 | 
				
			||||||
	/>
 | 
						/>
 | 
				
			||||||
	<Header title="Book Creation" />
 | 
						<Header title="Book Creation" />
 | 
				
			||||||
	<FileSuggestItem
 | 
						<FileSuggestItem
 | 
				
			||||||
		{app}
 | 
					 | 
				
			||||||
		id="template-file"
 | 
							id="template-file"
 | 
				
			||||||
		name="Template File"
 | 
							name="Template File"
 | 
				
			||||||
		description="Select the template file to use for new book entries."
 | 
							description="Select the template file to use for new book entries."
 | 
				
			||||||
| 
						 | 
					@ -218,7 +215,6 @@
 | 
				
			||||||
		bind:checked={settingsStore.settings.downloadCovers}
 | 
							bind:checked={settingsStore.settings.downloadCovers}
 | 
				
			||||||
	/>
 | 
						/>
 | 
				
			||||||
	<FolderSuggestItem
 | 
						<FolderSuggestItem
 | 
				
			||||||
		{app}
 | 
					 | 
				
			||||||
		id="cover-folder"
 | 
							id="cover-folder"
 | 
				
			||||||
		name="Cover Folder"
 | 
							name="Cover Folder"
 | 
				
			||||||
		description="Select the folder to download covers to."
 | 
							description="Select the folder to download covers to."
 | 
				
			||||||
| 
						 | 
					@ -240,7 +236,6 @@
 | 
				
			||||||
	<Header title="Book Properties" />
 | 
						<Header title="Book Properties" />
 | 
				
			||||||
	{#each properties as property}
 | 
						{#each properties as property}
 | 
				
			||||||
		<PropertySuggestItem
 | 
							<PropertySuggestItem
 | 
				
			||||||
			{app}
 | 
					 | 
				
			||||||
			id={property.key}
 | 
								id={property.key}
 | 
				
			||||||
			name={`${property.label} Property`}
 | 
								name={`${property.label} Property`}
 | 
				
			||||||
			description={property.description}
 | 
								description={property.description}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,13 @@ export interface DateFilterStoreOptions {
 | 
				
			||||||
	 * @default false
 | 
						 * @default false
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	disableMonthFilter?: boolean;
 | 
						disableMonthFilter?: boolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * If true, the year filter will be disabled
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @default false
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						disableAllFiltering?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function createDateFilter<T>(
 | 
					export function createDateFilter<T>(
 | 
				
			||||||
| 
						 | 
					@ -41,6 +48,7 @@ export function createDateFilter<T>(
 | 
				
			||||||
		initialMonth = false,
 | 
							initialMonth = false,
 | 
				
			||||||
		initialYear = true,
 | 
							initialYear = true,
 | 
				
			||||||
		disableMonthFilter = false,
 | 
							disableMonthFilter = false,
 | 
				
			||||||
 | 
							disableAllFiltering = false,
 | 
				
			||||||
	}: DateFilterStoreOptions
 | 
						}: DateFilterStoreOptions
 | 
				
			||||||
): DateFilterStore & {
 | 
					): DateFilterStore & {
 | 
				
			||||||
	filteredData: T[];
 | 
						filteredData: T[];
 | 
				
			||||||
| 
						 | 
					@ -64,7 +72,7 @@ export function createDateFilter<T>(
 | 
				
			||||||
		return data()
 | 
							return data()
 | 
				
			||||||
			.filter((item) => {
 | 
								.filter((item) => {
 | 
				
			||||||
				const date = selector(item);
 | 
									const date = selector(item);
 | 
				
			||||||
				if (filterYear !== ALL_TIME) {
 | 
									if (filterYear !== ALL_TIME && !disableAllFiltering) {
 | 
				
			||||||
					if (date.year() !== filterYear) {
 | 
										if (date.year() !== filterYear) {
 | 
				
			||||||
						return false;
 | 
											return false;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue