Fix settings not updating in svelte views and add fixed width calendar setting

This commit is contained in:
Evan Fiordeliso 2025-08-20 11:44:40 -04:00
parent ae4b924616
commit 8462dbab57
12 changed files with 161 additions and 10 deletions

View File

@ -1,7 +1,7 @@
{ {
"id": "obsidian-book-tracker", "id": "obsidian-book-tracker",
"name": "Book Tracker", "name": "Book Tracker",
"version": "1.5.0", "version": "1.6.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.5.0", "version": "1.6.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

@ -43,6 +43,14 @@ export default class BookTrackerPlugin extends Plugin {
public readingLog: ReadingLog; public readingLog: ReadingLog;
public goodreads: Goodreads = new Goodreads(); public goodreads: Goodreads = new Goodreads();
private onSettingsSavedHandlers: ((
settings: BookTrackerPluginSettings
) => void)[] = [];
private onSettingsChangedHandlers: ((
settings: BookTrackerPluginSettings
) => void)[] = [];
async onload() { async onload() {
await this.loadSettings(); await this.loadSettings();
@ -100,12 +108,41 @@ export default class BookTrackerPlugin extends Plugin {
DEFAULT_SETTINGS, DEFAULT_SETTINGS,
await this.loadData() await this.loadData()
); );
this.onSettingsChangedHandlers.forEach((handler) =>
handler(this.settings)
);
} }
async saveSettings() { async saveSettings() {
this.onSettingsSavedHandlers.forEach((handler) =>
handler(this.settings)
);
await this.saveData(this.settings); await this.saveData(this.settings);
} }
onSettingsChanged(
handler: (settings: BookTrackerPluginSettings) => void
): () => void {
this.onSettingsChangedHandlers.push(handler);
return () => {
this.onSettingsChangedHandlers =
this.onSettingsChangedHandlers.filter((h) => h !== handler);
};
}
onSettingsSaved(
handler: (settings: BookTrackerPluginSettings) => void
): () => void {
this.onSettingsSavedHandlers.push(handler);
return () => {
this.onSettingsSavedHandlers = this.onSettingsSavedHandlers.filter(
(h) => h !== handler
);
};
}
async downloadCoverImage( async downloadCoverImage(
coverImageUrl: string, coverImageUrl: string,
fileName: string, fileName: string,

View File

@ -14,6 +14,7 @@
import BookCover from "@ui/components/BookCover.svelte"; import BookCover from "@ui/components/BookCover.svelte";
import { setAppContext } from "@ui/stores/app"; import { setAppContext } from "@ui/stores/app";
import { titleSortValue } from "@utils/text"; import { titleSortValue } from "@utils/text";
import { onDestroy } from "svelte";
const { plugin }: SvelteCodeBlockProps = $props(); const { plugin }: SvelteCodeBlockProps = $props();
setAppContext(plugin.app); setAppContext(plugin.app);
@ -67,6 +68,11 @@
return dates[0]; return dates[0];
}); });
onDestroy(() => {
settingsStore.destroy();
metadataStore.destroy();
});
</script> </script>
<div class="reading-bingo"> <div class="reading-bingo">

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { TFile } from "obsidian"; import { Platform, TFile } from "obsidian";
import type { SvelteCodeBlockProps } from "./SvelteCodeBlockRenderer"; import type { SvelteCodeBlockProps } from "./SvelteCodeBlockRenderer";
import { import {
createSettings, createSettings,
@ -86,6 +86,7 @@
}); });
onDestroy(() => { onDestroy(() => {
settingsStore.destroy();
metadataStore.destroy(); metadataStore.destroy();
readingLog.destroy(); readingLog.destroy();
}); });
@ -147,7 +148,11 @@
); );
</script> </script>
<div class="reading-calendar"> <div
class="reading-calendar"
class:fixed-width={settingsStore.settings.fixedWidthCalendar ||
(settingsStore.settings.fixedWidthCalendarMobile && Platform.isMobile)}
>
<div class="controls"> <div class="controls">
<div class="left"> <div class="left">
<button <button
@ -191,7 +196,7 @@
<ArrowRight /> <ArrowRight />
</button> </button>
</div> </div>
<table> <table id="calendar">
<thead> <thead>
<tr> <tr>
{#each daysOfWeek as day} {#each daysOfWeek as day}
@ -215,7 +220,7 @@
(month + 1) % 12} (month + 1) % 12}
> >
<div class="header"> <div class="header">
<span>{day.date()}</span> <span class="date">{day.date()}</span>
{#if isThisMonth && date in bookMap} {#if isThisMonth && date in bookMap}
{@const data = bookMap[date]} {@const data = bookMap[date]}
<span class="total-pages-read"> <span class="total-pages-read">
@ -250,6 +255,9 @@
$cell-padding: var(--size-4-2); $cell-padding: var(--size-4-2);
.reading-calendar { .reading-calendar {
container-name: reading-calendar;
container-type: inline-size;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: auto; overflow: auto;
@ -272,9 +280,62 @@
align-items: center; align-items: center;
} }
} }
&.fixed-width {
--table-width: 600px;
table#calendar,
.controls {
min-width: unset;
width: var(--table-width) !important;
margin-left: auto;
margin-right: auto;
}
table#calendar th {
width: calc(var(--table-width) / 7);
}
@container reading-calendar (max-width: 800px) {
table#calendar {
th {
font-size: 0.75em;
}
.date {
font-size: 0.8em;
}
.total-pages-read {
font-size: 0.6em;
}
}
}
@container reading-calendar (min-width: 800px) {
table#calendar,
.controls {
--table-width: 800px;
}
}
@container reading-calendar (min-width: 1000px) {
table#calendar,
.controls {
--table-width: 1000px;
}
}
@container reading-calendar (min-width: 1200px) {
table#calendar,
.controls {
--table-width: 1200px;
}
}
}
} }
table { table#calendar {
table-layout: fixed; table-layout: fixed;
border-collapse: collapse; border-collapse: collapse;
min-width: 800px; min-width: 800px;

View File

@ -78,6 +78,7 @@
}); });
onDestroy(() => { onDestroy(() => {
settingsStore.destroy();
metadataStore.destroy(); metadataStore.destroy();
readingLogStore.destroy(); readingLogStore.destroy();
}); });

View File

@ -43,7 +43,10 @@
let view = $state(settings.defaultView); let view = $state(settings.defaultView);
onDestroy(() => metadataStore.destroy()); onDestroy(() => {
settingsStore.destroy();
metadataStore.destroy();
});
</script> </script>
<div <div

View File

@ -15,6 +15,7 @@
createReadingLog, createReadingLog,
setReadingLogContext, setReadingLogContext,
} from "@ui/stores/reading-log.svelte"; } from "@ui/stores/reading-log.svelte";
import { onDestroy } from "svelte";
const INPUT_DATETIME_FORMAT = "YYYY-MM-DDTHH:mm"; const INPUT_DATETIME_FORMAT = "YYYY-MM-DDTHH:mm";
@ -92,6 +93,12 @@
createdAt: moment(createdAt), createdAt: moment(createdAt),
}); });
} }
onDestroy(() => {
settingsStore.destroy();
metadataStore.destroy();
readingLogStore.destroy();
});
</script> </script>
<div class="obt-reading-log-entry-editor"> <div class="obt-reading-log-entry-editor">

View File

@ -7,7 +7,7 @@
import ToggleItem from "@ui/components/setting/ToggleItem.svelte"; import ToggleItem from "@ui/components/setting/ToggleItem.svelte";
import type BookTrackerPlugin from "@src/main"; import type BookTrackerPlugin from "@src/main";
import { createSettings } from "@ui/stores/settings.svelte"; import { createSettings } from "@ui/stores/settings.svelte";
import { onMount } from "svelte"; import { onDestroy, onMount } from "svelte";
import type { BookTrackerSettings } from "./types"; import type { BookTrackerSettings } from "./types";
import { setAppContext } from "@ui/stores/app"; import { setAppContext } from "@ui/stores/app";
@ -164,6 +164,8 @@
type: "text", type: "text",
}, },
]; ];
onDestroy(() => settingsStore.destroy());
</script> </script>
<div class="obt-settings"> <div class="obt-settings">
@ -233,6 +235,22 @@
bind:checked={settingsStore.settings.overwriteExistingCovers} bind:checked={settingsStore.settings.overwriteExistingCovers}
/> />
<Header title="Reading Calendar" />
<ToggleItem
id="fixed-width-calendar"
name="Fixed Width Calendar"
description={`Use a fixed with for the reading calendar
Useful on mobile where the images rely on a fixed width for proper sizing.`}
bind:checked={settingsStore.settings.fixedWidthCalendar}
/>
<ToggleItem
id="fixed-width-calendar-mobile"
name="Fixed Width Calendar (Mobile)"
description={`Use a fixed with for the reading calendar on the mobile app
Useful on mobile where the images rely on a fixed width for proper sizing.`}
bind:checked={settingsStore.settings.fixedWidthCalendarMobile}
/>
<Header title="Book Properties" /> <Header title="Book Properties" />
{#each properties as property} {#each properties as property}
<PropertySuggestItem <PropertySuggestItem

View File

@ -9,6 +9,8 @@ export interface BookTrackerSettings {
coverFolder: string; coverFolder: string;
groupCoversByFirstLetter: boolean; groupCoversByFirstLetter: boolean;
overwriteExistingCovers: boolean; overwriteExistingCovers: boolean;
fixedWidthCalendar: boolean;
fixedWidthCalendarMobile: boolean;
titleProperty: string; titleProperty: string;
subtitleProperty: string; subtitleProperty: string;
descriptionProperty: string; descriptionProperty: string;
@ -42,6 +44,8 @@ export const DEFAULT_SETTINGS: BookTrackerSettings = {
coverFolder: "images/covers", coverFolder: "images/covers",
groupCoversByFirstLetter: true, groupCoversByFirstLetter: true,
overwriteExistingCovers: false, overwriteExistingCovers: false,
fixedWidthCalendar: false,
fixedWidthCalendarMobile: true,
titleProperty: "title", titleProperty: "title",
subtitleProperty: "subtitle", subtitleProperty: "subtitle",
descriptionProperty: "description", descriptionProperty: "description",

View File

@ -5,6 +5,7 @@ import { getContext, setContext } from "svelte";
export interface SettingsStore { export interface SettingsStore {
settings: BookTrackerSettings; settings: BookTrackerSettings;
load(): Promise<void>; load(): Promise<void>;
destroy(): void;
} }
export function createSettings(plugin: BookTrackerPlugin) { export function createSettings(plugin: BookTrackerPlugin) {
@ -19,6 +20,14 @@ export function createSettings(plugin: BookTrackerPlugin) {
plugin.saveSettings(); plugin.saveSettings();
}); });
const savedHandlerCleanup = plugin.onSettingsSaved((newSettings) => {
settings = newSettings;
});
const changedHandlerCleanup = plugin.onSettingsChanged((newSettings) => {
settings = newSettings;
});
return { return {
get settings() { get settings() {
return settings; return settings;
@ -31,6 +40,10 @@ export function createSettings(plugin: BookTrackerPlugin) {
...newSettings, ...newSettings,
}; };
}, },
destroy() {
savedHandlerCleanup();
changedHandlerCleanup();
},
}; };
} }

View File

@ -8,5 +8,6 @@
"1.4.0": "0.15.0", "1.4.0": "0.15.0",
"1.4.1": "0.15.0", "1.4.1": "0.15.0",
"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"
} }