From a0a144cdbd16f41ab27e411d5d314b5e2e4604e5 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Fri, 10 Mar 2023 14:50:45 +0800 Subject: [PATCH] set reading progress percent to bottom position --- .../components/templates/article/Article.tsx | 33 +++++++------------ .../lib/hooks/useReadingProgressAnchor.tsx | 28 ++++++++++++++++ .../articleReadingProgressMutation.ts | 4 +-- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/packages/web/components/templates/article/Article.tsx b/packages/web/components/templates/article/Article.tsx index fbeb3173f..71b1794a4 100644 --- a/packages/web/components/templates/article/Article.tsx +++ b/packages/web/components/templates/article/Article.tsx @@ -1,5 +1,8 @@ import { Box } from '../../elements/LayoutPrimitives' -import { useReadingProgressAnchor } from '../../../lib/hooks/useReadingProgressAnchor' +import { + getTopOmnivoreAnchorElement, + useReadingProgressAnchor, +} from '../../../lib/hooks/useReadingProgressAnchor' import { ScrollOffsetChangeset, useScrollWatcher, @@ -26,25 +29,24 @@ export function Article(props: ArticleProps): JSX.Element { props.initialReadingProgress ) - const [readingAnchorIndex, setReadingAnchorIndex] = useState( - props.initialAnchorIndex - ) - const [shouldScrollToInitialPosition, setShouldScrollToInitialPosition] = useState(true) const articleContentRef = useRef(null) - useReadingProgressAnchor(articleContentRef, setReadingAnchorIndex) - useEffect(() => { ;(async () => { if (!readingProgress) return + if (!articleContentRef.current) return + const anchor = getTopOmnivoreAnchorElement(articleContentRef.current) + const anchorIndex = Number(anchor) + await props.articleMutations.articleReadingProgressMutation({ id: props.articleId, // round reading progress to 100% if more than that readingProgressPercent: readingProgress > 100 ? 100 : readingProgress, - readingProgressAnchorIndex: readingAnchorIndex, + readingProgressAnchorIndex: + anchorIndex == Number.NaN ? undefined : anchorIndex, }) })() @@ -65,24 +67,13 @@ export function Article(props: ArticleProps): JSX.Element { useScrollWatcher((changeset: ScrollOffsetChangeset) => { if (window && window.document.scrollingElement) { - const newReadingProgress = + const topProgress = window.scrollY / window.document.scrollingElement.scrollHeight - const adjustedReadingProgress = - newReadingProgress > 0.92 ? 1 : newReadingProgress - const bottomProgress = (window.scrollY + window.document.scrollingElement.clientHeight) / window.document.scrollingElement.scrollHeight - console.log( - 'newOffset Top: ', - newReadingProgress, - 'newOffset Bottom: ', - bottomProgress, - window.scrollY, - window.document.scrollingElement.scrollHeight - ) - setReadingProgress(adjustedReadingProgress * 100) + setReadingProgress(bottomProgress * 100) } }, 2500) diff --git a/packages/web/lib/hooks/useReadingProgressAnchor.tsx b/packages/web/lib/hooks/useReadingProgressAnchor.tsx index cdac3c552..3165f5cb3 100644 --- a/packages/web/lib/hooks/useReadingProgressAnchor.tsx +++ b/packages/web/lib/hooks/useReadingProgressAnchor.tsx @@ -6,6 +6,34 @@ const ANCHOR_ELEMENTS_BLOCKED_ATTRIBUTES = [ 'data-instagram-id', ] +// We search in reverse so we can find the last element +// that is visible on the page +export const getTopOmnivoreAnchorElement = ( + articleContentElement: HTMLElement +): string | undefined => { + let lastVisibleAnchor: Element | undefined = undefined + const anchors = Array.from( + articleContentElement.querySelectorAll(`[data-omnivore-anchor-idx]`) + ).reverse() + + for (const anchor of anchors) { + const rect = anchor.getBoundingClientRect() + if ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= articleContentElement.clientHeight + ) { + lastVisibleAnchor = anchor + } else if (lastVisibleAnchor) { + break + } + } + + return ( + lastVisibleAnchor?.getAttribute(`data-omnivore-anchor-idx`) ?? undefined + ) +} + export const useReadingProgressAnchor = ( articleContentRef: React.MutableRefObject, setReadingAnchorIndex: React.Dispatch> diff --git a/packages/web/lib/networking/mutations/articleReadingProgressMutation.ts b/packages/web/lib/networking/mutations/articleReadingProgressMutation.ts index e8a81eebf..e02f6e9c7 100644 --- a/packages/web/lib/networking/mutations/articleReadingProgressMutation.ts +++ b/packages/web/lib/networking/mutations/articleReadingProgressMutation.ts @@ -3,8 +3,8 @@ import { gqlFetcher } from '../networkHelpers' export type ArticleReadingProgressMutationInput = { id: string - readingProgressPercent: number - readingProgressAnchorIndex: number + readingProgressPercent?: number + readingProgressAnchorIndex?: number } export async function articleReadingProgressMutation(