diff --git a/src/data-sources/goodreads.ts b/src/data-sources/goodreads.ts index ac538f4..5e664a4 100644 --- a/src/data-sources/goodreads.ts +++ b/src/data-sources/goodreads.ts @@ -175,7 +175,7 @@ export function createBookFromNextData( publishedAt: new Date(bookData.details.publicationTime), genres: bookData.bookGenres.map((genre) => genre.genre.name), coverImageUrl: bookData.imageUrl, - pageLength: bookData.details.numPages, + pageCount: bookData.details.numPages, isbn: bookData.details.isbn, isbn13: bookData.details.isbn13, }; diff --git a/src/main.ts b/src/main.ts index a364142..65589c7 100644 --- a/src/main.ts +++ b/src/main.ts @@ -64,7 +64,7 @@ export default class BookTrackerPlugin extends Plugin { callback: () => this.resetReadingStatus(), }); - this.addSettingTab(new BookTrackerSettingTab(this.app, this)); + this.addSettingTab(new BookTrackerSettingTab(this)); registerReadingLogCodeBlockProcessor(this); } @@ -94,7 +94,7 @@ export default class BookTrackerPlugin extends Plugin { throw new Error("Unsupported content type: " + contentType); } - let filePath = this.settings.coverDirectory + "/"; + let filePath = this.settings.coverFolder + "/"; if (this.settings.groupCoversByFirstLetter) { let groupName = fileName.charAt(0).toUpperCase(); if (!/^[A-Z]$/.test(groupName)) { @@ -150,7 +150,7 @@ export default class BookTrackerPlugin extends Plugin { if (renderedContent) { await this.app.vault.create( - this.settings.tbrDirectory + "/" + fileName + ".md", + this.settings.tbrFolder + "/" + fileName + ".md", renderedContent ); } @@ -228,17 +228,17 @@ export default class BookTrackerPlugin extends Plugin { } const fileName = activeFile.basename; - if (!this.settings.pageLengthProperty) { - new Notice("Page length property is not set in settings."); + if (!this.settings.pageCountProperty) { + new Notice("Page count property is not set in settings."); return; } - const pageLength = + const pageCount = (this.app.metadataCache.getFileCache(activeFile)?.frontmatter?.[ - this.settings.pageLengthProperty + this.settings.pageCountProperty ] as number | undefined) ?? 0; - if (pageLength <= 0) { + if (pageCount <= 0) { new Notice( "Page length property is not set or is invalid in the active file." ); @@ -247,19 +247,19 @@ export default class BookTrackerPlugin extends Plugin { const pageNumber = await ReadingProgressModal.createAndOpen( this.app, - pageLength + pageCount ); - if (pageNumber <= 0 || pageNumber > pageLength) { + if (pageNumber <= 0 || pageNumber > pageCount) { new Notice( - `Invalid page number: ${pageNumber}. It must be between 1 and ${pageLength}.` + `Invalid page number: ${pageNumber}. It must be between 1 and ${pageCount}.` ); return; } - await this.readingLog.addEntry(fileName, pageNumber, pageLength); + await this.readingLog.addEntry(fileName, pageNumber, pageCount); new Notice( - `Logged reading progress for ${fileName}: Page ${pageNumber} of ${pageLength}.` + `Logged reading progress for ${fileName}: Page ${pageNumber} of ${pageCount}.` ); } @@ -290,14 +290,14 @@ export default class BookTrackerPlugin extends Plugin { return; } - const pageLength = + const pageCount = (this.app.metadataCache.getFileCache(activeFile)?.frontmatter?.[ - this.settings.pageLengthProperty + this.settings.pageCountProperty ] as number | undefined) ?? 0; - if (pageLength <= 0) { + if (pageCount <= 0) { new Notice( - "Page length property is not set or is invalid in the active file." + "Page count property is not set or is invalid in the active file." ); return; } @@ -306,8 +306,8 @@ export default class BookTrackerPlugin extends Plugin { await this.readingLog.addEntry( activeFile.basename, - pageLength, - pageLength + pageCount, + pageCount ); // @ts-expect-error Moment is provided by Obsidian diff --git a/src/types.ts b/src/types.ts index a4d62b2..d05c42e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,7 +17,7 @@ export interface Book { publishedAt: Date; genres: string[]; coverImageUrl: string; - pageLength: number; + pageCount: number; isbn: string; isbn13: string; } diff --git a/src/ui/components/RatingInput.svelte b/src/ui/components/RatingInput.svelte index ee9d558..307875f 100644 --- a/src/ui/components/RatingInput.svelte +++ b/src/ui/components/RatingInput.svelte @@ -38,10 +38,6 @@ })); }); - $effect(() => { - console.log(items); - }); - function calcSliderPos(e: MouseEvent) { return (e.offsetX / (e.target as HTMLElement).clientWidth) * maxV; } diff --git a/src/ui/components/setting/FieldSuggestItem.svelte b/src/ui/components/setting/FieldSuggestItem.svelte new file mode 100644 index 0000000..e19f340 --- /dev/null +++ b/src/ui/components/setting/FieldSuggestItem.svelte @@ -0,0 +1,28 @@ + + + + {#snippet control()} + + {/snippet} + diff --git a/src/ui/components/setting/FileSuggestItem.svelte b/src/ui/components/setting/FileSuggestItem.svelte new file mode 100644 index 0000000..bf41573 --- /dev/null +++ b/src/ui/components/setting/FileSuggestItem.svelte @@ -0,0 +1,20 @@ + + + + {#snippet control()} + + {/snippet} + diff --git a/src/ui/components/setting/FolderSuggestItem.svelte b/src/ui/components/setting/FolderSuggestItem.svelte new file mode 100644 index 0000000..ac96c24 --- /dev/null +++ b/src/ui/components/setting/FolderSuggestItem.svelte @@ -0,0 +1,20 @@ + + + + {#snippet control()} + + {/snippet} + diff --git a/src/ui/components/setting/Header.svelte b/src/ui/components/setting/Header.svelte new file mode 100644 index 0000000..09a5536 --- /dev/null +++ b/src/ui/components/setting/Header.svelte @@ -0,0 +1,29 @@ + + +
+

+ {#if typeof title === "string"} + {title} + {:else} + {@render title()} + {/if} +

+ {#if description} +

+ {#if typeof description === "string"} + {description} + {:else} + {@render description()} + {/if} +

+ {/if} +
diff --git a/src/ui/components/setting/Item.svelte b/src/ui/components/setting/Item.svelte new file mode 100644 index 0000000..adc09ba --- /dev/null +++ b/src/ui/components/setting/Item.svelte @@ -0,0 +1,39 @@ + + +
+
+
+ {#if typeof name === "string"} + {name} + {:else} + {@render name()} + {/if} +
+ {#if description} +
+ {#if typeof description === "string"} + {#each descriptionLines as line} +
{line}
+ {/each} + {:else} + {@render description()} + {/if} +
+ {/if} +
+
{@render control()}
+
diff --git a/src/ui/components/setting/TextInputItem.svelte b/src/ui/components/setting/TextInputItem.svelte new file mode 100644 index 0000000..9b78123 --- /dev/null +++ b/src/ui/components/setting/TextInputItem.svelte @@ -0,0 +1,17 @@ + + + + {#snippet control()} + + {/snippet} + diff --git a/src/ui/components/setting/ToggleItem.svelte b/src/ui/components/setting/ToggleItem.svelte new file mode 100644 index 0000000..9d71ea4 --- /dev/null +++ b/src/ui/components/setting/ToggleItem.svelte @@ -0,0 +1,26 @@ + + + + {#snippet control()} + + + +
(checked = !checked)} + > + +
+ {/snippet} +
diff --git a/src/ui/components/suggesters/FieldSuggest.svelte b/src/ui/components/suggesters/FieldSuggest.svelte new file mode 100644 index 0000000..107b1fa --- /dev/null +++ b/src/ui/components/suggesters/FieldSuggest.svelte @@ -0,0 +1,60 @@ + + + + + diff --git a/src/ui/components/suggesters/FileSuggest.svelte b/src/ui/components/suggesters/FileSuggest.svelte new file mode 100644 index 0000000..50a24f1 --- /dev/null +++ b/src/ui/components/suggesters/FileSuggest.svelte @@ -0,0 +1,38 @@ + + + diff --git a/src/ui/components/suggesters/FolderSuggest.svelte b/src/ui/components/suggesters/FolderSuggest.svelte new file mode 100644 index 0000000..885e4a6 --- /dev/null +++ b/src/ui/components/suggesters/FolderSuggest.svelte @@ -0,0 +1,38 @@ + + + diff --git a/src/ui/components/suggesters/TextInputSuggest.svelte b/src/ui/components/suggesters/TextInputSuggest.svelte new file mode 100644 index 0000000..430d96f --- /dev/null +++ b/src/ui/components/suggesters/TextInputSuggest.svelte @@ -0,0 +1,235 @@ + + + + +
(expanded = false)} +> +
+ (expanded = true)} + aria-controls={`${id}-list`} + aria-autocomplete="list" + aria-expanded={expanded} + /> + +
e.key === "Enter" && clearSearch()} + >
+
+ {#if expanded} +
+
    + {#each items as item, index} +
  • selectItem(index)} + onkeydown={(event) => + event.key === "Enter" && selectItem(index)} + onmouseover={() => (selectedIndex = index)} + onfocus={() => (selectedIndex = index)} + role="option" + aria-selected={index === selectedIndex} + > + {#if suggestion} + {@render suggestion(item)} + {:else} + {item.text} + {/if} +
  • + {/each} +
+
+ {/if} +
diff --git a/src/ui/directives/clickOutside.ts b/src/ui/directives/clickOutside.ts new file mode 100644 index 0000000..9c2454a --- /dev/null +++ b/src/ui/directives/clickOutside.ts @@ -0,0 +1,18 @@ +export function clickOutside(node: Node, cb: () => void) { + function handleClick(event: MouseEvent) { + if ( + node && + !node.contains(event.target as Node) && + !event.defaultPrevented + ) { + cb(); + } + } + document.addEventListener("click", handleClick, true); + return { + update() {}, + destroy() { + document.removeEventListener("click", handleClick, true); + }, + }; +} diff --git a/src/ui/directives/index.ts b/src/ui/directives/index.ts new file mode 100644 index 0000000..7ff8d3d --- /dev/null +++ b/src/ui/directives/index.ts @@ -0,0 +1 @@ +export { clickOutside } from "./clickOutside"; diff --git a/src/ui/modals/ReadingProgressModal.ts b/src/ui/modals/ReadingProgressModal.ts index 0e2a906..7935a7f 100644 --- a/src/ui/modals/ReadingProgressModal.ts +++ b/src/ui/modals/ReadingProgressModal.ts @@ -7,19 +7,19 @@ export class ReadingProgressModal extends SvelteModal< > { constructor( app: App, - pageLength: number, + pageCount: number, onSubmit: (pageNumber: number) => void = () => {} ) { super(app, ReadingProgressModalView, { - props: { pageLength, onSubmit }, + props: { pageCount, onSubmit }, }); } - static createAndOpen(app: App, pageLength: number): Promise { + static createAndOpen(app: App, pageCount: number): Promise { return new Promise((resolve) => { const modal = new ReadingProgressModal( app, - pageLength, + pageCount, (pageNumber: number) => { modal.close(); resolve(pageNumber); diff --git a/src/ui/modals/ReadingProgressModalView.svelte b/src/ui/modals/ReadingProgressModalView.svelte index 1e121c4..a0065c2 100644 --- a/src/ui/modals/ReadingProgressModalView.svelte +++ b/src/ui/modals/ReadingProgressModalView.svelte @@ -1,112 +1,136 @@
-

Log Reading Progress

-
-
- - -
-
- - -
- -
+

Log Reading Progress

+
+
+ + +
+
+ + +
+ +
\ No newline at end of file + &.percentage { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + } + } + } + } + diff --git a/src/ui/settings/BookTrackerSettingTab.ts b/src/ui/settings/BookTrackerSettingTab.ts index b45c7c3..0efbbf1 100644 --- a/src/ui/settings/BookTrackerSettingTab.ts +++ b/src/ui/settings/BookTrackerSettingTab.ts @@ -1,303 +1,30 @@ import BookTrackerPlugin from "@src/main"; -import { App, PluginSettingTab, Setting } from "obsidian"; -import { FileSuggest, FolderSuggest, FieldSuggest } from "@ui/suggesters"; +import { App, PluginSettingTab } from "obsidian"; +import BookTrackerSettingTabView from "./BookTrackerSettingTabView.svelte"; +import { mount, unmount } from "svelte"; export class BookTrackerSettingTab extends PluginSettingTab { - constructor(app: App, private plugin: BookTrackerPlugin) { - super(app, plugin); - } + private component: ReturnType | undefined; - heading(text: string): void { - const header = document.createDocumentFragment(); - header.createEl("h2", { text }); - new Setting(this.containerEl).setHeading().setName(text); + constructor(private readonly plugin: BookTrackerPlugin) { + super(plugin.app, plugin); } display(): void { this.containerEl.empty(); - this.containerEl.classList.add("obt-settings"); - - this.heading("Book Creation Settings"); - this.templateFileSetting(); - this.tbrDirectorySetting(); - this.fileNameFormatSetting(); - - this.heading("Cover Download Settings"); - this.downloadCoversSetting(); - this.coverDirectorySetting(); - this.groupCoversByFirstLetterSetting(); - this.overwriteExistingCoversSetting(); - - this.heading("Reading Progress Settings"); - this.statusPropertySetting(); - this.startDatePropertySetting(); - this.endDatePropertySetting(); - this.ratingPropertySetting(); - this.pageLengthPropertySetting(); - this.readingLogDirectorySetting(); - } - - readingLogDirectorySetting() { - return new Setting(this.containerEl) - .setName("Reading Log Directory") - .setDesc("Select the directory where reading logs will be stored") - .addSearch((cb) => { - try { - new FolderSuggest(this.app, cb.inputEl); - } catch { - // If the suggest fails, we can just ignore it. - // This might happen if the plugin is not fully loaded yet. - } - - cb.setPlaceholder("reading-logs") - .setValue(this.plugin.settings.readingLogDirectory) - .onChange(async (value) => { - this.plugin.settings.readingLogDirectory = value; - await this.plugin.saveSettings(); - }); - }); - } - - pageLengthPropertySetting() { - return new Setting(this.containerEl) - .setName("Page Length Property") - .setDesc( - "Property used to track the total number of pages in a book." - ) - .addSearch((cb) => { - try { - new FieldSuggest(this.app, cb.inputEl, ["number"]); - } catch { - // If the suggest fails, we can just ignore it. - // This might happen if the plugin is not fully loaded yet. - } - - cb.setPlaceholder("pageLength") - .setValue(this.plugin.settings.pageLengthProperty) - .onChange(async (value) => { - this.plugin.settings.pageLengthProperty = value; - await this.plugin.saveSettings(); - }); - }); - } - - ratingPropertySetting() { - return new Setting(this.containerEl) - .setName("Rating Property") - .setDesc("Property used to track the rating of a book.") - .addSearch((cb) => { - try { - new FieldSuggest(this.app, cb.inputEl, ["number"]); - } catch { - // If the suggest fails, we can just ignore it. - // This might happen if the plugin is not fully loaded yet. - } - - cb.setPlaceholder("rating") - .setValue(this.plugin.settings.ratingProperty) - .onChange(async (value) => { - this.plugin.settings.ratingProperty = value; - await this.plugin.saveSettings(); - }); - }); - } - - endDatePropertySetting() { - return new Setting(this.containerEl) - .setName("End Date Property") - .setDesc("Property used to track the end date of reading a book.") - .addSearch((cb) => { - try { - new FieldSuggest(this.app, cb.inputEl, ["date"]); - } catch { - // If the suggest fails, we can just ignore it. - // This might happen if the plugin is not fully loaded yet. - } - - cb.setPlaceholder("endDate") - .setValue(this.plugin.settings.endDateProperty) - .onChange(async (value) => { - this.plugin.settings.endDateProperty = value; - await this.plugin.saveSettings(); - }); - }); - } - - startDatePropertySetting() { - return new Setting(this.containerEl) - .setName("Start Date Property") - .setDesc("Property used to track the start date of reading a book.") - .addSearch((cb) => { - try { - new FieldSuggest(this.app, cb.inputEl, ["date"]); - } catch { - // If the suggest fails, we can just ignore it. - // This might happen if the plugin is not fully loaded yet. - } - - cb.setPlaceholder("startDate") - .setValue(this.plugin.settings.startDateProperty) - .onChange(async (value) => { - this.plugin.settings.startDateProperty = value; - await this.plugin.saveSettings(); - }); - }); - } - - statusPropertySetting() { - return new Setting(this.containerEl) - .setName("Status Property") - .setDesc("Property used to track the reading status of a book.") - .addSearch((cb) => { - try { - new FieldSuggest(this.app, cb.inputEl, ["text"]); - } catch { - // If the suggest fails, we can just ignore it. - // This might happen if the plugin is not fully loaded yet. - } - - cb.setPlaceholder("status") - .setValue(this.plugin.settings.statusProperty) - .onChange(async (value) => { - this.plugin.settings.statusProperty = value; - await this.plugin.saveSettings(); - }); - }); - } - - overwriteExistingCoversSetting() { - return new Setting(this.containerEl) - .setName("Overwrite Existing Covers") - .setDesc("Overwrite existing book covers when downloading new ones") - .addToggle((cb) => { - cb.setValue( - this.plugin.settings.overwriteExistingCovers - ).onChange(async (value) => { - this.plugin.settings.overwriteExistingCovers = value; - await this.plugin.saveSettings(); - }); - }); - } - - groupCoversByFirstLetterSetting() { - return new Setting(this.containerEl) - .setName("Group Covers by First Letter") - .setDesc( - "Organize downloaded book covers into subdirectories based on the first letter of the book title" - ) - .addToggle((cb) => { - cb.setValue( - this.plugin.settings.groupCoversByFirstLetter - ).onChange(async (value) => { - this.plugin.settings.groupCoversByFirstLetter = value; - await this.plugin.saveSettings(); - }); - }); - } - - coverDirectorySetting() { - return new Setting(this.containerEl) - .setName("Cover Directory") - .setDesc( - "Select the directory where downloaded book covers will be stored" - ) - .addSearch((cb) => { - try { - new FolderSuggest(this.app, cb.inputEl); - } catch { - // If the suggest fails, we can just ignore it. - // This might happen if the plugin is not fully loaded yet. - } - - cb.setPlaceholder("images/covers") - .setValue(this.plugin.settings.coverDirectory) - .onChange(async (value) => { - this.plugin.settings.coverDirectory = value; - await this.plugin.saveSettings(); - }); - }); - } - - downloadCoversSetting() { - return new Setting(this.containerEl) - .setName("Download Covers") - .setDesc( - "Automatically download book covers when creating new entries" - ) - .addToggle((cb) => { - cb.setValue(this.plugin.settings.downloadCovers).onChange( - async (value) => { - this.plugin.settings.downloadCovers = value; - await this.plugin.saveSettings(); - } - ); - }); - } - - fileNameFormatSetting() { - const fileNameFormatDesc = document.createDocumentFragment(); - fileNameFormatDesc.createDiv({ - text: "Format for the file name of new book entries.", + this.component = mount(BookTrackerSettingTabView, { + target: this.containerEl, + props: { plugin: this.plugin }, }); - fileNameFormatDesc.createDiv({ - text: "Use {{title}} and {{authors}} as placeholders.", - }); - - new Setting(this.containerEl) - .setName("File Name Format") - .setDesc(fileNameFormatDesc) - .addText((cb) => { - cb.setPlaceholder("{{title}} - {{authors}}") - .setValue(this.plugin.settings.fileNameFormat) - .onChange(async (value) => { - this.plugin.settings.fileNameFormat = value; - await this.plugin.saveSettings(); - }); - }); } - tbrDirectorySetting() { - return new Setting(this.containerEl) - .setName("To Be Read Directory") - .setDesc( - "Select the directory where new book entries will be created" - ) - .addSearch((cb) => { - try { - new FolderSuggest(this.app, cb.inputEl); - } catch { - // If the suggest fails, we can just ignore it. - // This might happen if the plugin is not fully loaded yet. - } - const { containerEl } = this; + hide(): void { + super.hide(); - cb.setPlaceholder("books/tbr") - .setValue(this.plugin.settings.tbrDirectory) - .onChange(async (value) => { - this.plugin.settings.tbrDirectory = value; - await this.plugin.saveSettings(); - }); - }); - } - - templateFileSetting() { - return new Setting(this.containerEl) - .setName("Template File") - .setDesc("Select the template file to use for new book entries") - .addSearch((cb) => { - try { - new FileSuggest(this.app, cb.inputEl); - } catch { - // If the suggest fails, we can just ignore it. - // This might happen if the plugin is not fully loaded yet. - } - - cb.setPlaceholder("templates/book-template") - .setValue(this.plugin.settings.templateFile) - .onChange(async (value) => { - this.plugin.settings.templateFile = value; - await this.plugin.saveSettings(); - }); - }); + if (this.component) { + unmount(this.component); + this.component = undefined; + } + this.containerEl.empty(); } } diff --git a/src/ui/settings/BookTrackerSettingTabView.svelte b/src/ui/settings/BookTrackerSettingTabView.svelte new file mode 100644 index 0000000..74330fe --- /dev/null +++ b/src/ui/settings/BookTrackerSettingTabView.svelte @@ -0,0 +1,118 @@ + + +
+
+ + + + +
+ + + + + +
+ + + + + +
diff --git a/src/ui/settings/index.ts b/src/ui/settings/index.ts index 2528393..6eddd24 100644 --- a/src/ui/settings/index.ts +++ b/src/ui/settings/index.ts @@ -1,2 +1,5 @@ export { BookTrackerSettingTab } from "./BookTrackerSettingTab"; -export { type BookTrackerPluginSettings, DEFAULT_SETTINGS } from "./types"; +export { + type BookTrackerSettings as BookTrackerPluginSettings, + DEFAULT_SETTINGS, +} from "./types"; diff --git a/src/ui/settings/store.ts b/src/ui/settings/store.ts new file mode 100644 index 0000000..d551913 --- /dev/null +++ b/src/ui/settings/store.ts @@ -0,0 +1,39 @@ +import type BookTrackerPlugin from "@src/main"; +import { writable, type Writable } from "svelte/store"; +import { type BookTrackerSettings, DEFAULT_SETTINGS } from "./types"; + +type SettingsStore = Writable & { + load: () => Promise; +}; + +export function createSettingsStore(plugin: BookTrackerPlugin): SettingsStore { + const { subscribe, set, update } = + writable(DEFAULT_SETTINGS); + + async function load() { + const settings = await plugin.loadData(); + + update((currentSettings) => { + return { + ...currentSettings, + ...settings, + }; + }); + } + + subscribe((settings) => { + if (settings === DEFAULT_SETTINGS) { + return; + } + + plugin.settings = settings; + plugin.saveSettings(); + }); + + return { + subscribe, + set, + update, + load, + }; +} diff --git a/src/ui/settings/types.ts b/src/ui/settings/types.ts index ef0b343..9f9b78a 100644 --- a/src/ui/settings/types.ts +++ b/src/ui/settings/types.ts @@ -1,31 +1,29 @@ -export interface BookTrackerPluginSettings { +export interface BookTrackerSettings { templateFile: string; - tbrDirectory: string; + tbrFolder: string; fileNameFormat: string; downloadCovers: boolean; - coverDirectory: string; + coverFolder: string; groupCoversByFirstLetter: boolean; overwriteExistingCovers: boolean; statusProperty: string; startDateProperty: string; endDateProperty: string; ratingProperty: string; - pageLengthProperty: string; - readingLogDirectory: string; + pageCountProperty: string; } -export const DEFAULT_SETTINGS: BookTrackerPluginSettings = { +export const DEFAULT_SETTINGS: BookTrackerSettings = { templateFile: "", - tbrDirectory: "books/tbr", + tbrFolder: "books/tbr", fileNameFormat: "{{title}} - {{authors}}", downloadCovers: false, - coverDirectory: "images/covers", + coverFolder: "images/covers", groupCoversByFirstLetter: true, overwriteExistingCovers: false, statusProperty: "status", startDateProperty: "startDate", endDateProperty: "endDate", ratingProperty: "rating", - pageLengthProperty: "pageLength", - readingLogDirectory: "reading-logs", + pageCountProperty: "pageCount", }; diff --git a/src/utils/storage.ts b/src/utils/storage.ts index fa91ed3..96546ea 100644 --- a/src/utils/storage.ts +++ b/src/utils/storage.ts @@ -57,7 +57,7 @@ export class ReadingLog { private sortEntries() { this.entries = this.entries.sort( - (a, b) => b.createdAt.getTime() - a.createdAt.getTime() + (a, b) => a.createdAt.getTime() - b.createdAt.getTime() ); } @@ -83,7 +83,7 @@ export class ReadingLog { public async addEntry( book: string, pageEnded: number, - pageLength: number + pageCount: number ): Promise { const latestEntry = this.getLatestEntry(book); @@ -93,7 +93,7 @@ export class ReadingLog { ? pageEnded - latestEntry.pagesReadTotal : pageEnded, pagesReadTotal: pageEnded, - pagesRemaining: pageLength - pageEnded, + pagesRemaining: pageCount - pageEnded, createdAt: new Date(), };