feat: add reading position tracking with visual progress indicator

- Install position-indicator library for scroll position tracking
- Create useReadingPosition hook for position management
- Add ReadingProgressIndicator component with animated progress bar
- Integrate reading progress in ContentPanel for text content only
- Add CSS styles for fixed progress indicator with shimmer animation
- Track reading completion at 90% threshold
- Exclude video content from position tracking
This commit is contained in:
Gigi
2025-10-13 21:01:44 +02:00
parent 1066c43d6c
commit 96ce12b952
6 changed files with 232 additions and 2 deletions

View File

@@ -33,6 +33,8 @@ import { faBooks } from '../icons/customIcons'
import { extractYouTubeId, getYouTubeMeta } from '../services/youtubeMetaService'
import { classifyUrl } from '../utils/helpers'
import { buildNativeVideoUrl } from '../utils/videoHelpers'
import { useReadingPosition } from '../hooks/useReadingPosition'
import { ReadingProgressIndicator } from './ReadingProgressIndicator'
interface ContentPanelProps {
loading: boolean
@@ -115,6 +117,18 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
onClearSelection
})
// Reading position tracking - only for text content, not videos
const isTextContent = !loading && !!(markdown || html) && !selectedUrl?.includes('youtube') && !selectedUrl?.includes('vimeo')
const { isReadingComplete, progressPercentage } = useReadingPosition({
enabled: isTextContent,
onReadingComplete: () => {
// Optional: Auto-mark as read when reading is complete
if (activeAccount && !isMarkedAsRead) {
// Could trigger auto-mark as read here if desired
}
}
})
// Close menu when clicking outside
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
@@ -361,6 +375,15 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
return (
<div className="reader" style={{ '--highlight-rgb': highlightRgb } as React.CSSProperties}>
{/* Reading Progress Indicator */}
{isTextContent && (
<ReadingProgressIndicator
progress={progressPercentage}
isComplete={isReadingComplete}
showPercentage={true}
/>
)}
{/* Hidden markdown preview to convert markdown to HTML */}
{markdown && (
<div ref={markdownPreviewRef} style={{ display: 'none' }}>