generated from tpl/obsidian-sample-plugin
Add sync toggle to reading log editor, use previous entry as opposed to last ever entry, and reorganize files
This commit is contained in:
parent
0ef651d661
commit
8b19f1ea03
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "obsidian-book-tracker",
|
"id": "obsidian-book-tracker",
|
||||||
"name": "Book Tracker",
|
"name": "Book Tracker",
|
||||||
"version": "1.7.0",
|
"version": "1.7.1",
|
||||||
"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",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "obsidian-book-tracker",
|
"name": "obsidian-book-tracker",
|
||||||
"version": "1.7.0",
|
"version": "1.7.1",
|
||||||
"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": {
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<script lang="ts">
|
||||||
|
interface Props {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
value?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { id, name, value = $bindable() }: Props = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<input {id} {name} type="text" bind:value />
|
|
@ -0,0 +1,21 @@
|
||||||
|
<script lang="ts">
|
||||||
|
interface Props {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
checked?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { id, name, checked = $bindable() }: Props = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="checkbox-container"
|
||||||
|
class:is-enabled={checked}
|
||||||
|
onclick={() => (checked = !checked)}
|
||||||
|
onkeypress={(e) => e.key === "Space" && (checked = !checked)}
|
||||||
|
role="switch"
|
||||||
|
aria-checked={checked}
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<input {id} {name} type="checkbox" bind:checked tabindex="0" />
|
||||||
|
</div>
|
|
@ -1,7 +1,7 @@
|
||||||
<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 FileSuggest from "../suggesters/FileSuggest.svelte";
|
import FileSuggest from "../form/suggesters/FileSuggest.svelte";
|
||||||
|
|
||||||
type Props = Omit<ComponentProps<typeof Item>, "control"> & {
|
type Props = Omit<ComponentProps<typeof Item>, "control"> & {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<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 FolderSuggest from "../suggesters/FolderSuggest.svelte";
|
import FolderSuggest from "../form/suggesters/FolderSuggest.svelte";
|
||||||
|
|
||||||
type Props = Omit<ComponentProps<typeof Item>, "control"> & {
|
type Props = Omit<ComponentProps<typeof Item>, "control"> & {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<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 PropertySuggest from "../suggesters/PropertySuggest.svelte";
|
import PropertySuggest from "../form/suggesters/PropertySuggest.svelte";
|
||||||
|
|
||||||
type Props = Omit<ComponentProps<typeof Item>, "control"> & {
|
type Props = Omit<ComponentProps<typeof Item>, "control"> & {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<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 TextControl from "../form/TextControl.svelte";
|
||||||
|
|
||||||
type Props = Omit<ComponentProps<typeof Item>, "control"> & {
|
type Props = Omit<ComponentProps<typeof Item>, "control"> & {
|
||||||
id?: string;
|
id?: string;
|
||||||
|
@ -12,6 +13,6 @@
|
||||||
|
|
||||||
<Item {name} {description}>
|
<Item {name} {description}>
|
||||||
{#snippet control()}
|
{#snippet control()}
|
||||||
<input {id} type="text" bind:value />
|
<TextControl {id} bind:value />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Item>
|
</Item>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<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 ToggleControl from "../form/ToggleControl.svelte";
|
||||||
|
|
||||||
type Props = Omit<ComponentProps<typeof Item>, "control"> & {
|
type Props = Omit<ComponentProps<typeof Item>, "control"> & {
|
||||||
id?: string;
|
id?: string;
|
||||||
|
@ -12,15 +13,6 @@
|
||||||
|
|
||||||
<Item {name} {description}>
|
<Item {name} {description}>
|
||||||
{#snippet control()}
|
{#snippet control()}
|
||||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
<ToggleControl {id} bind:checked />
|
||||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
||||||
<!-- input only covers part of the toggle element. onclick here covers the rest -->
|
|
||||||
<div
|
|
||||||
class="checkbox-container"
|
|
||||||
class:is-enabled={checked}
|
|
||||||
onclick={() => (checked = !checked)}
|
|
||||||
>
|
|
||||||
<input {id} type="checkbox" bind:checked tabindex="0" />
|
|
||||||
</div>
|
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Item>
|
</Item>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type BookTrackerPlugin from "@src/main";
|
import type BookTrackerPlugin from "@src/main";
|
||||||
import type { ReadingLogEntry } from "@utils/ReadingLog";
|
import type { ReadingLogEntry } from "@utils/ReadingLog";
|
||||||
import FileSuggest from "@ui/components/suggesters/FileSuggest.svelte";
|
import FileSuggest from "@ui/components/form/suggesters/FileSuggest.svelte";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { createPrevious } from "@ui/stores/previous.svelte";
|
import { createPrevious } from "@ui/stores/previous.svelte";
|
||||||
import { createMetadata } from "@ui/stores/metadata.svelte";
|
import { createMetadata } from "@ui/stores/metadata.svelte";
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
setReadingLogContext,
|
setReadingLogContext,
|
||||||
} from "@ui/stores/reading-log.svelte";
|
} from "@ui/stores/reading-log.svelte";
|
||||||
import { onDestroy } from "svelte";
|
import { onDestroy } from "svelte";
|
||||||
|
import ToggleControl from "@ui/components/form/ToggleControl.svelte";
|
||||||
|
|
||||||
const INPUT_DATETIME_FORMAT = "YYYY-MM-DDTHH:mm";
|
const INPUT_DATETIME_FORMAT = "YYYY-MM-DDTHH:mm";
|
||||||
|
|
||||||
|
@ -43,13 +44,24 @@
|
||||||
const bookMetadata = $derived(
|
const bookMetadata = $derived(
|
||||||
metadataStore.metadata.find((m) => m.file.basename === book),
|
metadataStore.metadata.find((m) => m.file.basename === book),
|
||||||
);
|
);
|
||||||
const lastEntryIndex = $derived(
|
const previousEntry = $derived.by(() => {
|
||||||
readingLogStore.entries.findLastIndex((e) => e.book === book),
|
const index = readingLogStore.entries.findIndex(
|
||||||
);
|
(e) => e.id === entry?.id,
|
||||||
const lastEntry = $derived(
|
|
||||||
lastEntryIndex !== -1 ? readingLogStore.entries[lastEntryIndex] : null,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let data = readingLogStore.entries;
|
||||||
|
if (index !== -1) {
|
||||||
|
data = data.slice(0, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
const previousEntryIndex = data.findLastIndex((e) => e.book === book);
|
||||||
|
|
||||||
|
return previousEntryIndex !== -1
|
||||||
|
? readingLogStore.entries[previousEntryIndex]
|
||||||
|
: null;
|
||||||
|
});
|
||||||
|
|
||||||
|
let syncPageCounts = $state(true);
|
||||||
const pageCount = $derived(bookMetadata?.book.pageCount ?? 0);
|
const pageCount = $derived(bookMetadata?.book.pageCount ?? 0);
|
||||||
let pagesRead = $state(entry?.pagesRead ?? 0);
|
let pagesRead = $state(entry?.pagesRead ?? 0);
|
||||||
const pagesReadPrev = createPrevious(() => pagesRead);
|
const pagesReadPrev = createPrevious(() => pagesRead);
|
||||||
|
@ -61,20 +73,24 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
pagesReadTotal = (lastEntry?.pagesReadTotal ?? 0) + pagesRead;
|
if (!syncPageCounts) return;
|
||||||
|
pagesReadTotal = (previousEntry?.pagesReadTotal ?? 0) + pagesRead;
|
||||||
});
|
});
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
|
if (!syncPageCounts) return;
|
||||||
const diff = pagesRead - (pagesReadPrev.value ?? 0);
|
const diff = pagesRead - (pagesReadPrev.value ?? 0);
|
||||||
pagesRead = pagesRead;
|
pagesRead = pagesRead;
|
||||||
pagesReadTotal = pagesReadTotal + diff;
|
pagesReadTotal = pagesReadTotal + diff;
|
||||||
});
|
});
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
|
if (!syncPageCounts) return;
|
||||||
pagesRemaining = pageCount - pagesReadTotal;
|
pagesRemaining = pageCount - pagesReadTotal;
|
||||||
});
|
});
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
|
if (!syncPageCounts) return;
|
||||||
pagesReadTotal = Math.max(pagesReadTotal, pagesRead);
|
pagesReadTotal = Math.max(pagesReadTotal, pagesRead);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -138,6 +154,12 @@
|
||||||
id="pagesRemaining"
|
id="pagesRemaining"
|
||||||
bind:value={pagesRemaining}
|
bind:value={pagesRemaining}
|
||||||
/>
|
/>
|
||||||
|
<label for="syncPageCounts">Sync Page Counts</label>
|
||||||
|
<ToggleControl
|
||||||
|
name="syncPageCounts"
|
||||||
|
id="syncPageCounts"
|
||||||
|
bind:checked={syncPageCounts}
|
||||||
|
/>
|
||||||
<label for="createdAt">Created At</label>
|
<label for="createdAt">Created At</label>
|
||||||
<input
|
<input
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
|
|
|
@ -11,5 +11,6 @@
|
||||||
"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"
|
"1.7.0": "0.15.0",
|
||||||
|
"1.7.1": "0.15.0"
|
||||||
}
|
}
|
Loading…
Reference in New Issue