fix(editor): prune chapter positions on delete and guard quota

Saved cursor/scroll and active-chapter entries accumulated per book
forever and were never removed when a book was deleted. Add
clearPositions and call it from the delete flow, and guard localStorage
writes against quota or unavailable storage.

Claude-Session: https://claude.ai/code/session_01RzTWrLiy4zGuw2hZSQGamk
This commit is contained in:
pj committed 2026-06-22 13:33:23 -04:00
1 parent 608ba2f21b
commit 2f98f5ec1c
2 files changed
+21 -2

No files matched your search

+2
View File
@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
import { type BookSummary, createAndOpenBook, deleteBook, exampleBook, listBooks, loadBook, saveBook } from "../library";
import type { Book } from "../model/book";
import { importEpub } from "../import/epub";
import { clearPositions } from "../editor/positions";
import { isDesktop } from "../ipc";
import { ConfirmDialog } from "./ConfirmDialog";
import { Icon } from "./Icon";
@@ -38,6 +39,7 @@ export function Library({ onOpen }: { onOpen: (book: Book) => void }) {
const removeBook = async () => {
if (!pendingDelete) return;
await deleteBook(pendingDelete.id);
clearPositions(pendingDelete.id);
setPendingDelete(null);
refresh();
};
+19 -2
View File
@@ -16,6 +16,14 @@ function readAll(): Store {
}
}
function write(key: string, value: unknown): void {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch {
return;
}
}
export function loadPosition(bookId: string, chapterId: string): ChapterPosition | null {
return readAll()[bookId]?.[chapterId] ?? null;
}
@@ -23,7 +31,7 @@ export function loadPosition(bookId: string, chapterId: string): ChapterPosition
export function savePosition(bookId: string, chapterId: string, position: ChapterPosition): void {
const all = readAll();
(all[bookId] ||= {})[chapterId] = position;
localStorage.setItem(KEY, JSON.stringify(all));
write(KEY, all);
}
const ACTIVE_KEY = "margin-active-chapter";
@@ -43,5 +51,14 @@ export function loadActiveChapter(bookId: string): string | null {
export function saveActiveChapter(bookId: string, chapterId: string): void {
const all = readActive();
all[bookId] = chapterId;
localStorage.setItem(ACTIVE_KEY, JSON.stringify(all));
write(ACTIVE_KEY, all);
}
export function clearPositions(bookId: string): void {
const positions = readAll();
const active = readActive();
delete positions[bookId];
delete active[bookId];
write(KEY, positions);
write(ACTIVE_KEY, active);
}