This commit is contained in:
pj committed 2026-06-20 19:23:28 -04:00
1 parent 20ae0b7387
commit 734ded73ac
14 files changed
+893 -43

No files matched your search

+27 -2
View File
@@ -1,6 +1,15 @@
import { create } from "zustand";
import type { JSONContent } from "@tiptap/core";
import { type Book, type BookMetadata, type BookSettings, createChapter } from "../model/book";
import {
type Book,
type BookMetadata,
type BookSettings,
type Cover,
createChapter,
normalizeBook,
} from "../model/book";
export const COVER_ID = "__cover__";
interface BookState {
book: Book | null;
@@ -12,8 +21,10 @@ interface BookState {
setChapterContent: (id: string, content: JSONContent) => void;
setChapterTitle: (id: string, title: string) => void;
addChapter: () => void;
moveChapter: (from: number, to: number) => void;
setMetadata: (patch: Partial<BookMetadata>) => void;
setSettings: (patch: Partial<BookSettings>) => void;
setCover: (patch: Partial<Cover>) => void;
markSaved: () => void;
}
@@ -21,7 +32,10 @@ export const useBook = create<BookState>((set) => ({
book: null,
activeChapterId: "",
dirty: false,
openBook: (book) => set({ book, activeChapterId: book.chapters[0]?.id ?? "", dirty: false }),
openBook: (book) => {
const normalized = normalizeBook(book);
set({ book: normalized, activeChapterId: normalized.chapters[0]?.id ?? "", dirty: false });
},
closeBook: () => set({ book: null, activeChapterId: "", dirty: false }),
setActiveChapter: (id) => set({ activeChapterId: id }),
setChapterContent: (id, content) =>
@@ -42,9 +56,20 @@ export const useBook = create<BookState>((set) => ({
const chapter = createChapter();
return { activeChapterId: chapter.id, dirty: true, book: { ...s.book, chapters: [...s.book.chapters, chapter] } };
}),
moveChapter: (from, to) =>
set((s) => {
if (!s.book || from === to) return {};
const chapters = [...s.book.chapters];
if (from < 0 || from >= chapters.length || to < 0 || to >= chapters.length) return {};
const [moved] = chapters.splice(from, 1);
chapters.splice(to, 0, moved);
return { dirty: true, book: { ...s.book, chapters } };
}),
setMetadata: (patch) =>
set((s) => (s.book ? { dirty: true, book: { ...s.book, metadata: { ...s.book.metadata, ...patch } } } : {})),
setSettings: (patch) =>
set((s) => (s.book ? { dirty: true, book: { ...s.book, settings: { ...s.book.settings, ...patch } } } : {})),
setCover: (patch) =>
set((s) => (s.book ? { dirty: true, book: { ...s.book, cover: { ...s.book.cover, ...patch } } } : {})),
markSaved: () => set({ dirty: false }),
}));