obsidian-book-tracker/src/utils/ReadingLog.ts

114 lines
2.5 KiB
TypeScript

import type { Storage } from "./Storage";
export interface ReadingLogEntry {
book: string;
pagesRead: number;
pagesReadTotal: number;
pagesRemaining: number;
createdAt: Date;
}
export class ReadingLog {
private entries: ReadingLogEntry[] = [];
public constructor(private readonly storage: Storage) {
this.load().catch((error) => {
console.error("Failed to load reading log entries:", error);
});
}
async load(filename = "reading-log.json") {
const entries = await this.storage.readJSON<ReadingLogEntry[]>(
filename
);
if (entries) {
this.entries = entries.map((entry) => ({
...entry,
createdAt: new Date(entry.createdAt),
}));
}
}
private sortEntries() {
this.entries = this.entries.sort(
(a, b) => a.createdAt.getTime() - b.createdAt.getTime()
);
}
async save(filename = "reading-log.json") {
this.sortEntries();
await this.storage.writeJSON(filename, this.entries);
}
public getEntries(): ReadingLogEntry[] {
return this.entries;
}
public getLatestEntry(book: string): ReadingLogEntry | null {
const entriesForBook = this.entries.filter(
(entry) => entry.book === book
);
return entriesForBook.length > 0
? entriesForBook[entriesForBook.length - 1]
: null;
}
public async addEntry(
book: string,
pageEnded: number,
pageCount: number
): Promise<void> {
const latestEntry = this.getLatestEntry(book);
const newEntry: ReadingLogEntry = {
book,
pagesRead: latestEntry
? pageEnded - latestEntry.pagesReadTotal
: pageEnded,
pagesReadTotal: pageEnded,
pagesRemaining: pageCount - pageEnded,
createdAt: new Date(),
};
await this.addRawEntry(newEntry);
}
public async addRawEntry(entry: ReadingLogEntry) {
this.entries.push(entry);
await this.save();
}
public async removeEntries(book: string): Promise<void> {
this.entries = this.entries.filter((entry) => entry.book !== book);
await this.save();
}
public async removeLastEntry(book: string): Promise<void> {
const latestEntryIndex = this.entries.findLastIndex(
(entry) => entry.book === book
);
if (latestEntryIndex !== -1) {
this.entries.splice(latestEntryIndex, 1);
await this.save();
}
}
public async updateEntry(i: number, entry: ReadingLogEntry): Promise<void> {
this.entries[i] = entry;
await this.save();
}
public async spliceEntry(i: number): Promise<ReadingLogEntry> {
const entry = this.entries.splice(i, 1);
await this.save();
return entry[0];
}
public async clearEntries(): Promise<void> {
this.entries = [];
await this.save();
}
}