Remove book folder setting and only rely on the tbr folder and read folder settings

This commit is contained in:
Evan Fiordeliso 2025-08-23 16:14:38 -04:00
parent 1191347105
commit 0ef651d661
14 changed files with 57 additions and 61 deletions

View File

@ -1,7 +1,7 @@
{ {
"id": "obsidian-book-tracker", "id": "obsidian-book-tracker",
"name": "Book Tracker", "name": "Book Tracker",
"version": "1.6.1", "version": "1.7.0",
"minAppVersion": "0.15.0", "minAppVersion": "0.15.0",
"description": "Simplifies tracking your reading progress and managing your book collection in Obsidian.", "description": "Simplifies tracking your reading progress and managing your book collection in Obsidian.",
"author": "FiFiTiDo", "author": "FiFiTiDo",

View File

@ -1,6 +1,6 @@
{ {
"name": "obsidian-book-tracker", "name": "obsidian-book-tracker",
"version": "1.6.1", "version": "1.7.0",
"description": "Simplifies tracking your reading progress and managing your book collection in Obsidian.", "description": "Simplifies tracking your reading progress and managing your book collection in Obsidian.",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {

View File

@ -13,6 +13,6 @@
<Item {name} {description}> <Item {name} {description}>
{#snippet control()} {#snippet control()}
<FileSuggest {id} asString bind:value /> <FileSuggest {id} bind:value />
{/snippet} {/snippet}
</Item> </Item>

View File

@ -13,6 +13,6 @@
<Item {name} {description}> <Item {name} {description}>
{#snippet control()} {#snippet control()}
<FolderSuggest {id} asString bind:value /> <FolderSuggest {id} bind:value />
{/snippet} {/snippet}
</Item> </Item>

View File

@ -20,6 +20,6 @@
<Item {name} {description}> <Item {name} {description}>
{#snippet control()} {#snippet control()}
<PropertySuggest {id} asString bind:value {accepts} /> <PropertySuggest {id} bind:value {accepts} />
{/snippet} {/snippet}
</Item> </Item>

View File

@ -3,42 +3,39 @@
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"; import { getAppContext } from "@ui/stores/app";
import { isInAnyFolder } from "@utils/fs";
type Props = { type Props = {
id: string; id: string;
asString?: boolean;
property?: StringKeys<TFile>; property?: StringKeys<TFile>;
inFolder?: string; folderFilter?: string[];
value?: TFile | string; value?: string;
disabled?: boolean; disabled?: boolean;
onSelected?: (fileOrPath: TFile | string) => void; onSelected?: (propertyValue: string) => void;
}; };
let { let {
id, id,
asString,
property = "path", property = "path",
inFolder, folderFilter,
value = $bindable(), value = $bindable(),
disabled, disabled,
onSelected, onSelected,
}: Props = $props(); }: Props = $props();
const app = getAppContext(); const app = getAppContext();
let items: Item<TFile | string>[] = $state([]); let items: Item<string>[] = $state([]);
function handleChange(query: string) { function handleChange(query: string) {
items = app.vault items = app.vault
.getMarkdownFiles() .getMarkdownFiles()
.filter( .filter(
(f) => (f) =>
(inFolder === undefined || f.path.startsWith(inFolder)) && (folderFilter === undefined ||
isInAnyFolder(f, folderFilter)) &&
f[property].toLowerCase().includes(query.toLowerCase()), f[property].toLowerCase().includes(query.toLowerCase()),
) )
.map((f) => ({ .map((f) => f[property]);
text: f[property],
value: asString ? f[property] : f,
}));
} }
</script> </script>

View File

@ -3,22 +3,21 @@
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"; import { getAppContext } from "@ui/stores/app";
import { isInAnyFolder } from "@utils/fs";
type Props = { type Props = {
id: string; id: string;
asString?: boolean;
property?: StringKeys<TFolder>; property?: StringKeys<TFolder>;
inFolder?: string; folderFilter?: string[];
value?: TFolder | string; value?: string;
disabled?: boolean; disabled?: boolean;
onSelected?: (folderOrPath: TFolder | string) => void; onSelected?: (propertyValue: string) => void;
}; };
let { let {
id, id,
asString,
property = "path", property = "path",
inFolder, folderFilter,
value = $bindable(), value = $bindable(),
disabled, disabled,
onSelected, onSelected,
@ -32,13 +31,11 @@
.getAllFolders() .getAllFolders()
.filter( .filter(
(f) => (f) =>
(inFolder === undefined || f.path.startsWith(inFolder)) && (folderFilter === undefined ||
isInAnyFolder(f, folderFilter)) &&
f[property].toLowerCase().includes(query.toLowerCase()), f[property].toLowerCase().includes(query.toLowerCase()),
) )
.map((f) => ({ .map((f) => f[property]);
text: f[property],
value: asString ? f[property] : f,
}));
} }
</script> </script>

View File

@ -12,16 +12,14 @@
type Props = { type Props = {
id: string; id: string;
asString?: boolean; value?: string;
value?: Property | string;
accepts?: string[]; accepts?: string[];
disabled?: boolean; disabled?: boolean;
onSelected?: (propertyOrName: Property | string) => void; onSelected?: (propertyName: string) => void;
}; };
let { let {
id, id,
asString,
value = $bindable(), value = $bindable(),
accepts, accepts,
disabled, disabled,
@ -29,7 +27,7 @@
}: Props = $props(); }: Props = $props();
const app = getAppContext(); const app = getAppContext();
let items: Item<Property | string>[] = $state([]); let items: Item<string>[] = $state([]);
async function handleChange(query: string) { async function handleChange(query: string) {
const typesContent = await app.vault.adapter.read( const typesContent = await app.vault.adapter.read(
@ -45,10 +43,7 @@
return name.toLowerCase().includes(query.toLowerCase()); return name.toLowerCase().includes(query.toLowerCase());
}) })
.map(([name, type]) => ({ .map(([name, _]) => name);
text: name,
value: asString ? name : { name, type },
}));
} }
</script> </script>

View File

@ -1,8 +1,10 @@
<script lang="ts" module> <script lang="ts" module>
export type Item<T> = { export type Item<T> =
text: string; | {
label: string;
value: T; value: T;
}; }
| (T extends string ? T : never);
</script> </script>
<script lang="ts"> <script lang="ts">
@ -26,7 +28,7 @@
let { let {
id, id,
items, items: itemsProp,
value = $bindable(), value = $bindable(),
loading = false, loading = false,
suggestion, suggestion,
@ -35,6 +37,12 @@
onSelected, onSelected,
}: Props = $props(); }: Props = $props();
const items = $derived(
itemsProp.map((item) =>
typeof item === "string" ? { label: item, value: item } : item,
),
);
let query = $state(""); let query = $state("");
let expanded = $state(false); let expanded = $state(false);
let selectedIndex = $state(0); let selectedIndex = $state(0);
@ -53,7 +61,7 @@
const idx = findIndex(value); const idx = findIndex(value);
if (idx !== -1) { if (idx !== -1) {
const item = items[idx]; const item = items[idx];
query = item.text; query = item.label;
selectedIndex = idx; selectedIndex = idx;
} }
}); });
@ -99,7 +107,7 @@
async function selectItem(index: number) { async function selectItem(index: number) {
const item = items[index]; const item = items[index];
if (!item) return; if (!item) return;
const { text: newQuery, value: newValue } = item; const { label: newQuery, value: newValue } = item;
selectedIndex = index; selectedIndex = index;
expanded = false; expanded = false;
query = newQuery; query = newQuery;
@ -195,7 +203,7 @@
{#if suggestion} {#if suggestion}
{@render suggestion(item)} {@render suggestion(item)}
{:else} {:else}
{item.text} {item.label}
{/if} {/if}
</li> </li>
{/each} {/each}

View File

@ -108,9 +108,11 @@
<label for="book">Book</label> <label for="book">Book</label>
<FileSuggest <FileSuggest
id="book" id="book"
asString
property="basename" property="basename"
inFolder={plugin.settings.bookFolder} folderFilter={[
plugin.settings.tbrFolder,
plugin.settings.readBooksFolder,
]}
bind:value={book} bind:value={book}
/> />
<label for="pagesRead">Pages Read</label> <label for="pagesRead">Pages Read</label>

View File

@ -170,35 +170,29 @@
<div class="obt-settings"> <div class="obt-settings">
<Header title="Folders" /> <Header title="Folders" />
<FolderSuggestItem
id="book-folder"
name="Book Folder"
description="Select the folder where book entries are stored."
bind:value={settingsStore.settings.bookFolder}
/>
<FolderSuggestItem <FolderSuggestItem
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="The folder to use for To Be Read or Currently Reading book entries."
bind:value={settingsStore.settings.tbrFolder} bind:value={settingsStore.settings.tbrFolder}
/> />
<FolderSuggestItem <FolderSuggestItem
id="read-folder" id="read-folder"
name="Read Books Folder" name="Read Books Folder"
description="Select the folder to use for Read entries." description="The folder to use for Read book entries."
bind:value={settingsStore.settings.readBooksFolder} bind:value={settingsStore.settings.readBooksFolder}
/> />
<ToggleItem <ToggleItem
id="organize-read-books" id="organize-read-books"
name="Organize Read Books" name="Organize Read Books"
description="Organize read books into folders based on the date read." description="Whether to automatically organize read books into folders, based on the date read, when finishing a book."
bind:checked={settingsStore.settings.organizeReadBooks} bind:checked={settingsStore.settings.organizeReadBooks}
/> />
<Header title="Book Creation" /> <Header title="Book Creation" />
<FileSuggestItem <FileSuggestItem
id="template-file" id="template-file"
name="Template File" name="Template File"
description="Select the template file to use for new book entries." description="The template file to use when creating new book entries."
bind:value={settingsStore.settings.templateFile} bind:value={settingsStore.settings.templateFile}
/> />
<TextInputItem <TextInputItem

View File

@ -1,5 +1,4 @@
export interface BookTrackerSettings { export interface BookTrackerSettings {
bookFolder: string;
tbrFolder: string; tbrFolder: string;
readBooksFolder: string; readBooksFolder: string;
organizeReadBooks: boolean; organizeReadBooks: boolean;
@ -34,7 +33,6 @@ export interface BookTrackerSettings {
} }
export const DEFAULT_SETTINGS: BookTrackerSettings = { export const DEFAULT_SETTINGS: BookTrackerSettings = {
bookFolder: "books",
tbrFolder: "books/tbr", tbrFolder: "books/tbr",
readBooksFolder: "books/read", readBooksFolder: "books/read",
organizeReadBooks: true, organizeReadBooks: true,

View File

@ -1,4 +1,4 @@
import { normalizePath, type Vault } from "obsidian"; import { normalizePath, TAbstractFile, type Vault } from "obsidian";
/** /**
* A simple analog of Node.js's `path.join(...)`. * A simple analog of Node.js's `path.join(...)`.
@ -52,3 +52,7 @@ export async function mkdirRecursive(
await vault.adapter.mkdir(stack.pop()!); await vault.adapter.mkdir(stack.pop()!);
} }
} }
export function isInAnyFolder(file: TAbstractFile, folders: string[]): boolean {
return folders.some((folder) => file.path.startsWith(folder));
}

View File

@ -10,5 +10,6 @@
"1.4.2": "0.15.0", "1.4.2": "0.15.0",
"1.5.0": "0.15.0", "1.5.0": "0.15.0",
"1.6.0": "0.15.0", "1.6.0": "0.15.0",
"1.6.1": "0.15.0" "1.6.1": "0.15.0",
"1.7.0": "0.15.0"
} }