From 3d849dc01cb23298acdfbfecead84c084bd4b1b2 Mon Sep 17 00:00:00 2001 From: Matt Rice Date: Mon, 30 Sep 2024 16:39:26 -0400 Subject: [PATCH] fix(web): estimate the totalProgression if it is not provided --- web/hooks/useLocationObserver.ts | 4 ++- web/hooks/useReaderRef.ts | 53 ++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/web/hooks/useLocationObserver.ts b/web/hooks/useLocationObserver.ts index fd07a31..354f967 100644 --- a/web/hooks/useLocationObserver.ts +++ b/web/hooks/useLocationObserver.ts @@ -13,7 +13,9 @@ export const useLocationObserver = ( reader.goTo(location as R2Locator); } }, [ - location, + location?.href, + //@ts-ignore + location?.locations, !!reader, ]); }; diff --git a/web/hooks/useReaderRef.ts b/web/hooks/useReaderRef.ts index 8568475..514565f 100644 --- a/web/hooks/useReaderRef.ts +++ b/web/hooks/useReaderRef.ts @@ -1,4 +1,4 @@ -import { useEffect, useRef } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import type { ReadiumProps } from '../../src/components/ReadiumView'; import type { Locator } from '../../src/interfaces'; @@ -9,6 +9,34 @@ export const useReaderRef = ({ onTableOfContents, }: Pick) => { const readerRef = useRef(null); + const readingOrder = useRef([]); + + const onLocationChangeWithTotalProgression = useCallback( + (newLocation: Locator) => { + if ( + !onLocationChange || + !readingOrder.current || + !newLocation.locations + ) { + return; + } + if (!newLocation.locations.totalProgression) { + const newLocationIndex = readingOrder.current.findIndex( + (entry) => entry.href === newLocation.href + ); + const readingOrderCount = readingOrder.current.length; + const chapterTotalProgression = + readingOrder.current[newLocationIndex].locations?.totalProgression || + 0; + const intraChapterTotalProgression = + newLocation.locations.progression / readingOrderCount; + newLocation.locations.totalProgression = + chapterTotalProgression + intraChapterTotalProgression; + } + onLocationChange(newLocation); + }, + [onLocationChange] + ); useEffect(() => { async function run() { @@ -19,7 +47,7 @@ export const useReaderRef = ({ userSettings: { verticalScroll: false }, api: { updateCurrentLocation: async (location: Locator) => { - if (onLocationChange) onLocationChange(location); + onLocationChangeWithTotalProgression(location); return location; }, }, @@ -29,10 +57,29 @@ export const useReaderRef = ({ if (onTableOfContents) { onTableOfContents(ref.tableOfContents); } + + // This way of estimating the totalProgression treats all reading order + // entries as equal in length. + // It is based on the implementation in the Readium Go toolkit + // https://github.com/readium/go-toolkit/blob/31c6a65b588f825ffb6b4f2445337ffdc53af685/pkg/pub/service_positions.go#L66 + const oldReadingOrder: Locator[] = ref.readingOrder; + const readingOrderCount = oldReadingOrder.length; + readingOrder.current = oldReadingOrder.map((item, index) => { + const totalProgression = index / readingOrderCount; + return { + ...item, + locations: { + ...item.locations, + progression: 0, + totalProgression: totalProgression, + }, + }; + }); + readerRef.current = ref; } run(); - }, []); + }, [file.url]); return readerRef };