mirror of
https://github.com/dergigi/boris.git
synced 2025-12-20 16:14:20 +01:00
fix: move progress indicator outside reader and fix position tracking
- Move ReadingProgressIndicator outside reader div for true fixed positioning - Replace position-indicator library with custom scroll tracking - Track document scroll position instead of content scroll - Remove unused position-indicator dependency - Ensure progress indicator is always visible and shows correct percentage
This commit is contained in:
7
package-lock.json
generated
7
package-lock.json
generated
@@ -22,7 +22,6 @@
|
||||
"applesauce-relay": "^4.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"nostr-tools": "^2.4.0",
|
||||
"position-indicator": "^0.0.12",
|
||||
"prismjs": "^1.30.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
@@ -8973,12 +8972,6 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/position-indicator": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/position-indicator/-/position-indicator-0.0.12.tgz",
|
||||
"integrity": "sha512-qHQejEylblB7rZ3MfXSI5hu1+Dq7EBv1BYwUIVWzJ3nZ8d6V7LFBi1zC5/XwT/01Wxddf9kaFoOy3L70/5tC+A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/possible-typed-array-names": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
"applesauce-relay": "^4.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"nostr-tools": "^2.4.0",
|
||||
"position-indicator": "^0.0.12",
|
||||
"prismjs": "^1.30.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
||||
@@ -374,8 +374,8 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
|
||||
const highlightRgb = hexToRgb(highlightColor)
|
||||
|
||||
return (
|
||||
<div className="reader" style={{ '--highlight-rgb': highlightRgb } as React.CSSProperties}>
|
||||
{/* Reading Progress Indicator */}
|
||||
<>
|
||||
{/* Reading Progress Indicator - Outside reader for fixed positioning */}
|
||||
{isTextContent && (
|
||||
<ReadingProgressIndicator
|
||||
progress={progressPercentage}
|
||||
@@ -384,6 +384,7 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="reader" style={{ '--highlight-rgb': highlightRgb } as React.CSSProperties}>
|
||||
{/* Hidden markdown preview to convert markdown to HTML */}
|
||||
{markdown && (
|
||||
<div ref={markdownPreviewRef} style={{ display: 'none' }}>
|
||||
@@ -591,6 +592,7 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
// @ts-ignore - position-indicator types issue
|
||||
import { createPositionIndicator } from 'position-indicator'
|
||||
|
||||
interface ReadingPositionData {
|
||||
position: number // 0 to 1
|
||||
prevPosition: number
|
||||
hasUpdated: boolean
|
||||
hasScroll: boolean
|
||||
eventType: 'scroll' | 'resize' | 'heightChange' | 'init'
|
||||
eventDate: number
|
||||
}
|
||||
|
||||
interface UseReadingPositionOptions {
|
||||
enabled?: boolean
|
||||
onPositionChange?: (data: ReadingPositionData) => void
|
||||
onPositionChange?: (position: number) => void
|
||||
onReadingComplete?: () => void
|
||||
readingCompleteThreshold?: number // Default 0.9 (90%)
|
||||
}
|
||||
@@ -26,44 +15,45 @@ export const useReadingPosition = ({
|
||||
}: UseReadingPositionOptions = {}) => {
|
||||
const [position, setPosition] = useState(0)
|
||||
const [isReadingComplete, setIsReadingComplete] = useState(false)
|
||||
const positionIndicatorRef = useRef<any>(null)
|
||||
const hasTriggeredComplete = useRef(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (!enabled) return
|
||||
|
||||
const handleInit = (data: ReadingPositionData) => {
|
||||
setPosition(data.position)
|
||||
onPositionChange?.(data)
|
||||
}
|
||||
const handleScroll = () => {
|
||||
// Get the main content area (reader content)
|
||||
const readerContent = document.querySelector('.reader-html, .reader-markdown')
|
||||
if (!readerContent) return
|
||||
|
||||
const handleUpdate = (data: ReadingPositionData) => {
|
||||
setPosition(data.position)
|
||||
onPositionChange?.(data)
|
||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop
|
||||
const windowHeight = window.innerHeight
|
||||
const documentHeight = document.documentElement.scrollHeight
|
||||
|
||||
// Calculate position based on how much of the content has been scrolled through
|
||||
const scrollProgress = Math.min(scrollTop / (documentHeight - windowHeight), 1)
|
||||
const clampedProgress = Math.max(0, Math.min(1, scrollProgress))
|
||||
|
||||
setPosition(clampedProgress)
|
||||
onPositionChange?.(clampedProgress)
|
||||
|
||||
// Check if reading is complete
|
||||
if (data.position >= readingCompleteThreshold && !hasTriggeredComplete.current) {
|
||||
if (clampedProgress >= readingCompleteThreshold && !hasTriggeredComplete.current) {
|
||||
setIsReadingComplete(true)
|
||||
hasTriggeredComplete.current = true
|
||||
onReadingComplete?.()
|
||||
}
|
||||
}
|
||||
|
||||
const positionIndicator = createPositionIndicator({
|
||||
onInit: handleInit,
|
||||
onUpdate: handleUpdate,
|
||||
useResizeListener: true,
|
||||
useResizeObserver: true
|
||||
})
|
||||
// Initial calculation
|
||||
handleScroll()
|
||||
|
||||
positionIndicator.init()
|
||||
positionIndicatorRef.current = positionIndicator
|
||||
// Add scroll listener
|
||||
window.addEventListener('scroll', handleScroll, { passive: true })
|
||||
window.addEventListener('resize', handleScroll, { passive: true })
|
||||
|
||||
return () => {
|
||||
if (positionIndicatorRef.current) {
|
||||
positionIndicatorRef.current.destroy()
|
||||
positionIndicatorRef.current = null
|
||||
}
|
||||
window.removeEventListener('scroll', handleScroll)
|
||||
window.removeEventListener('resize', handleScroll)
|
||||
}
|
||||
}, [enabled, onPositionChange, onReadingComplete, readingCompleteThreshold])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user