Get rid of unnecessary data fields in BookConfig
This commit is contained in:
@@ -26,7 +26,7 @@ const BookmarkToggler: React.FC<BookmarkTogglerProps> = ({ bookKey }) => {
|
||||
|
||||
const toggleBookmark = () => {
|
||||
const { booknotes: bookmarks = [] } = config;
|
||||
const { location: cfi, sectionHref: href, range } = progress;
|
||||
const { location: cfi, range } = progress;
|
||||
if (!cfi) return;
|
||||
if (!isBookmarked) {
|
||||
setIsBookmarked(true);
|
||||
@@ -36,7 +36,6 @@ const BookmarkToggler: React.FC<BookmarkTogglerProps> = ({ bookKey }) => {
|
||||
id: uniqueId(),
|
||||
type: 'bookmark',
|
||||
cfi,
|
||||
href,
|
||||
text: truncatedText,
|
||||
note: '',
|
||||
created: Date.now(),
|
||||
|
||||
@@ -217,14 +217,12 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
|
||||
const { booknotes: annotations = [] } = config;
|
||||
if (selection) navigator.clipboard.writeText(selection.text);
|
||||
const { sectionHref: href } = progress;
|
||||
const cfi = view?.getCFI(selection.index, selection.range);
|
||||
if (!cfi) return;
|
||||
const annotation: BookNote = {
|
||||
id: uniqueId(),
|
||||
type: 'excerpt',
|
||||
cfi,
|
||||
href,
|
||||
text: selection.text,
|
||||
note: '',
|
||||
created: Date.now(),
|
||||
@@ -250,7 +248,6 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
if (!selection || !selection.text) return;
|
||||
setHighlightOptionsVisible(true);
|
||||
const { booknotes: annotations = [] } = config;
|
||||
const { sectionHref: href } = progress;
|
||||
const cfi = view?.getCFI(selection.index, selection.range);
|
||||
if (!cfi) return;
|
||||
const style = settings.globalReadSettings.highlightStyle;
|
||||
@@ -259,7 +256,6 @@ const Annotator: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
id: uniqueId(),
|
||||
type: 'annotation',
|
||||
cfi,
|
||||
href,
|
||||
style,
|
||||
color,
|
||||
text: selection.text,
|
||||
|
||||
@@ -72,7 +72,6 @@ const Notebook: React.FC = ({}) => {
|
||||
type: 'annotation',
|
||||
cfi,
|
||||
note,
|
||||
href: selection.href || '',
|
||||
text: selection.text,
|
||||
created: Date.now(),
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
|
||||
import * as CFI from 'foliate-js/epubcfi.js';
|
||||
import { useBookDataStore } from '@/store/bookDataStore';
|
||||
import { findParentPath } from '@/utils/toc';
|
||||
import { findTocItemBS } from '@/utils/toc';
|
||||
import { TOCItem } from '@/libs/document';
|
||||
import { BookNote, BookNoteType } from '@/types/book';
|
||||
import BooknoteItem from './BooknoteItem';
|
||||
@@ -26,17 +26,14 @@ const BooknoteView: React.FC<{
|
||||
|
||||
const booknoteGroups: { [href: string]: BooknoteGroup } = {};
|
||||
for (const booknote of booknotes) {
|
||||
const parentPath = findParentPath(toc, booknote.href);
|
||||
if (parentPath.length > 0) {
|
||||
const href = parentPath[0]!.href || '';
|
||||
const label = parentPath[0]!.label || '';
|
||||
const id = toc.findIndex((item) => item.href === href) || Infinity;
|
||||
booknote.href = href;
|
||||
if (!booknoteGroups[href]) {
|
||||
booknoteGroups[href] = { id, href, label, booknotes: [] };
|
||||
}
|
||||
booknoteGroups[href].booknotes.push(booknote);
|
||||
const tocItem = findTocItemBS(toc, booknote.cfi);
|
||||
const href = tocItem?.href || '';
|
||||
const label = tocItem?.label || '';
|
||||
const id = tocItem?.id || 0;
|
||||
if (!booknoteGroups[href]) {
|
||||
booknoteGroups[href] = { id, href, label, booknotes: [] };
|
||||
}
|
||||
booknoteGroups[href].booknotes.push(booknote);
|
||||
}
|
||||
|
||||
Object.values(booknoteGroups).forEach((group) => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BookFormat } from '@/types/book';
|
||||
import * as epubcfi from 'foliate-js/epubcfi.js';
|
||||
|
||||
// A groupBy polyfill for foliate-js
|
||||
Object.groupBy ??= (iterable, callbackfn) => {
|
||||
@@ -30,15 +31,24 @@ Map.groupBy ??= (iterable, callbackfn) => {
|
||||
return map;
|
||||
};
|
||||
|
||||
export const CFI = epubcfi;
|
||||
|
||||
export type DocumentFile = File;
|
||||
|
||||
export interface TOCItem {
|
||||
id: number;
|
||||
label: string;
|
||||
href: string;
|
||||
cfi?: string;
|
||||
subitems?: TOCItem[];
|
||||
}
|
||||
|
||||
export interface SectionItem {
|
||||
id: string;
|
||||
cfi: string;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export interface BookDoc {
|
||||
metadata: {
|
||||
title: string;
|
||||
@@ -48,6 +58,7 @@ export interface BookDoc {
|
||||
publisher?: string;
|
||||
};
|
||||
toc: Array<TOCItem>;
|
||||
sections: Array<SectionItem>;
|
||||
getCover(): Promise<Blob | null>;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ import { create } from 'zustand';
|
||||
import { BookContent, BookConfig, PageInfo, BookProgress, ViewSettings } from '@/types/book';
|
||||
import { EnvConfigType } from '@/services/environment';
|
||||
import { FoliateView } from '@/app/reader/components/FoliateViewer';
|
||||
import { BookDoc, DocumentLoader, TOCItem } from '@/libs/document';
|
||||
import { updateTocID } from '@/utils/toc';
|
||||
import { BookDoc, DocumentLoader, SectionItem, TOCItem } from '@/libs/document';
|
||||
import { updateTocCFI, updateTocID } from '@/utils/toc';
|
||||
import { useSettingsStore } from './settingsStore';
|
||||
import { useBookDataStore } from './bookDataStore';
|
||||
import { useLibraryStore } from './libraryStore';
|
||||
@@ -114,8 +114,13 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
|
||||
console.log('Loading book', key);
|
||||
const { book: loadedBookDoc } = await new DocumentLoader(file).open();
|
||||
const bookDoc = loadedBookDoc as BookDoc;
|
||||
if (bookDoc.toc) {
|
||||
if (bookDoc.toc && bookDoc.sections) {
|
||||
updateTocID(bookDoc.toc);
|
||||
const sections = bookDoc.sections.reduce((map: Record<string, SectionItem>, section) => {
|
||||
map[section.id] = section;
|
||||
return map;
|
||||
}, {});
|
||||
updateTocCFI(bookDoc.toc, sections);
|
||||
}
|
||||
useBookDataStore.setState((state) => ({
|
||||
booksData: {
|
||||
|
||||
@@ -27,7 +27,6 @@ export interface BookNote {
|
||||
id: string;
|
||||
type: BookNoteType;
|
||||
cfi: string;
|
||||
href: string;
|
||||
text?: string;
|
||||
style?: HighlightStyle;
|
||||
color?: HighlightColor;
|
||||
@@ -111,10 +110,7 @@ export interface BookConfig {
|
||||
lastUpdated: number;
|
||||
progress?: [number, number];
|
||||
location?: string;
|
||||
|
||||
booknotes?: BookNote[];
|
||||
removedNotesTimestamps?: Record<string, number>;
|
||||
|
||||
searchConfig?: BookSearchConfig;
|
||||
viewSettings?: Partial<ViewSettings>;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TOCItem } from '@/libs/document';
|
||||
import { SectionItem, TOCItem, CFI } from '@/libs/document';
|
||||
|
||||
export const findParentPath = (toc: TOCItem[], href: string): TOCItem[] => {
|
||||
for (const item of toc) {
|
||||
@@ -15,6 +15,28 @@ export const findParentPath = (toc: TOCItem[], href: string): TOCItem[] => {
|
||||
return [];
|
||||
};
|
||||
|
||||
export const findTocItemBS = (toc: TOCItem[], cfi: string): TOCItem | null => {
|
||||
let left = 0;
|
||||
let right = toc.length - 1;
|
||||
let result: TOCItem | null = null;
|
||||
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
const currentCfi = toc[mid]!.cfi || '';
|
||||
const comparison = CFI.compare(currentCfi, cfi);
|
||||
if (comparison === 0) {
|
||||
return toc[mid]!;
|
||||
} else if (comparison < 0) {
|
||||
result = toc[mid]!;
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const updateTocID = (items: TOCItem[], index = 0): number => {
|
||||
items.forEach((item) => {
|
||||
item.id ??= index++;
|
||||
@@ -24,3 +46,18 @@ export const updateTocID = (items: TOCItem[], index = 0): number => {
|
||||
});
|
||||
return index;
|
||||
};
|
||||
|
||||
export const updateTocCFI = (items: TOCItem[], sections: { [id: string]: SectionItem }): void => {
|
||||
items.forEach((item) => {
|
||||
if (item.href) {
|
||||
const id = item.href.split('#')[0]!;
|
||||
const section = sections[id];
|
||||
if (section) {
|
||||
item.cfi = section.cfi;
|
||||
}
|
||||
}
|
||||
if (item.subitems) {
|
||||
updateTocCFI(item.subitems, sections);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
+1
-1
Submodule packages/foliate-js updated: cfdc02069d...bb8d44cc04
Reference in New Issue
Block a user