Files
readest/apps/readest-app/src/store/readerStore.ts
T

107 lines
2.7 KiB
TypeScript

import { create } from 'zustand';
import { BookNote, BookContent, Book, BookConfig, PageInfo } from '@/types/book';
import { AppService } from '@/types/system';
interface BookState {
loading?: boolean;
error?: string | null;
book?: Book | null;
file?: File | null;
config?: BookConfig | null;
fraction?: number;
}
interface ReaderStore {
library: Book[];
books: Record<string, BookState>;
setLibrary: (books: Book[]) => void;
fetchBook: (appService: AppService, id: string) => Promise<Book | null>;
setProgress: (id: string, progress: number, location: string, pageinfo: PageInfo) => void;
addBookmark: (id: string, bookmark: BookNote) => void;
}
export const useReaderStore = create<ReaderStore>((set) => ({
library: [],
books: {},
setLibrary: (books: Book[]) => set({ library: books }),
fetchBook: async (appService: AppService, id: string) => {
set((state) => ({
books: {
...state.books,
[id]: { loading: true, file: null, book: null, config: null, error: null, notes: [] },
},
}));
try {
const library = await appService.loadLibraryBooks();
const book = library.find((b) => b.hash === id);
if (!book) {
throw new Error('Book not found');
}
const content = (await appService.loadBookContent(book)) as BookContent;
const { file, config } = content;
set((state) => ({
books: {
...state.books,
[id]: { ...state.books[id], loading: false, book, file, config },
},
}));
return book;
} catch (error) {
console.error(error);
set((state) => ({
books: {
...state.books,
[id]: { ...state.books[id], loading: false, error: 'Failed to load book.' },
},
}));
return null;
}
},
setProgress: (id: string, progress: number, location: string, pageinfo: PageInfo) =>
set((state) => {
const book = state.books[id];
if (!book) return state;
return {
books: {
...state.books,
[id]: {
...book,
config: {
...book.config,
lastUpdated: Date.now(),
progress,
location,
pageinfo,
},
},
},
};
}),
addBookmark: (id: string, bookmark: BookNote) =>
set((state) => {
const book = state.books[id];
if (!book) return state;
return {
books: {
...state.books,
[id]: {
...book,
config: {
...book.config,
lastUpdated: Date.now(),
bookmarks: [...(book.config?.bookmarks || []), bookmark],
},
},
},
};
}),
}));