Archived
feat: uv config other feats
- add uv configuration for the backend - update frontend to make auth work - add new auth endpoints - add bookmars feat - add reader feat
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import type { EpubRendition } from "./epubRendition";
|
||||
import { normalizeHighlightColor } from "@/constants/bookmarkHighlightColors";
|
||||
|
||||
export interface BookmarkHighlight {
|
||||
id: string;
|
||||
epub_cfi: string;
|
||||
highlight_color?: string | null;
|
||||
}
|
||||
|
||||
type EpubAnnotations = {
|
||||
highlight?: (
|
||||
cfiRange: string,
|
||||
data: Record<string, unknown>,
|
||||
callback?: () => void,
|
||||
id?: string,
|
||||
styles?: Record<string, string>,
|
||||
) => void;
|
||||
remove?: (cfiRange: string, type: string) => void;
|
||||
};
|
||||
|
||||
export type EpubRenditionWithHighlights = EpubRendition & {
|
||||
annotations?: EpubAnnotations;
|
||||
on?: (event: string, handler: () => void) => void;
|
||||
off?: (event: string, handler: () => void) => void;
|
||||
};
|
||||
|
||||
function annotationId(bookmarkId: string): string {
|
||||
return `bookmark-hl-${bookmarkId}`;
|
||||
}
|
||||
|
||||
export function applyBookmarkHighlight(
|
||||
rendition: EpubRenditionWithHighlights,
|
||||
bookmark: BookmarkHighlight,
|
||||
): void {
|
||||
const cfi = (bookmark.epub_cfi || "").trim();
|
||||
if (!cfi || !rendition.annotations?.highlight) return;
|
||||
|
||||
const color = normalizeHighlightColor(bookmark.highlight_color);
|
||||
try {
|
||||
rendition.annotations.highlight(
|
||||
cfi,
|
||||
{},
|
||||
undefined,
|
||||
annotationId(bookmark.id),
|
||||
{
|
||||
fill: color,
|
||||
"fill-opacity": "0.45",
|
||||
"mix-blend-mode": "multiply",
|
||||
},
|
||||
);
|
||||
} catch {
|
||||
/* CFI may not be in the current spine slice */
|
||||
}
|
||||
}
|
||||
|
||||
export function removeBookmarkHighlight(
|
||||
rendition: EpubRenditionWithHighlights,
|
||||
bookmark: BookmarkHighlight,
|
||||
): void {
|
||||
const cfi = (bookmark.epub_cfi || "").trim();
|
||||
if (!cfi || !rendition.annotations?.remove) return;
|
||||
try {
|
||||
rendition.annotations.remove(cfi, "highlight");
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
export function syncBookmarkHighlights(
|
||||
rendition: EpubRenditionWithHighlights | null,
|
||||
bookmarks: BookmarkHighlight[],
|
||||
applied: Map<string, string>,
|
||||
): void {
|
||||
if (!rendition?.annotations?.highlight) return;
|
||||
|
||||
const nextById = new Map(bookmarks.map((b) => [b.id, b]));
|
||||
|
||||
for (const [id, cfi] of applied) {
|
||||
if (!nextById.has(id)) {
|
||||
removeBookmarkHighlight(rendition, { id, epub_cfi: cfi });
|
||||
applied.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (const bookmark of bookmarks) {
|
||||
const prevCfi = applied.get(bookmark.id);
|
||||
if (prevCfi && prevCfi !== bookmark.epub_cfi) {
|
||||
removeBookmarkHighlight(rendition, { id: bookmark.id, epub_cfi: prevCfi });
|
||||
applied.delete(bookmark.id);
|
||||
}
|
||||
if (applied.has(bookmark.id)) continue;
|
||||
applyBookmarkHighlight(rendition, bookmark);
|
||||
applied.set(bookmark.id, bookmark.epub_cfi);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user