refactor(reader): extract ReaderHeader to keep ContentPanel concise (<210 lines)

This commit is contained in:
Gigi
2025-10-05 21:46:31 +01:00
parent d148433fcc
commit d3ad08dd61
2 changed files with 61 additions and 25 deletions

View File

@@ -2,12 +2,13 @@ import React, { useMemo, useEffect, useRef, useState } from 'react'
import ReactMarkdown from 'react-markdown' import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm' import remarkGfm from 'remark-gfm'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSpinner, faHighlighter, faClock } from '@fortawesome/free-solid-svg-icons' import { faSpinner } from '@fortawesome/free-solid-svg-icons'
import { Highlight } from '../types/highlights' import { Highlight } from '../types/highlights'
import { applyHighlightsToHTML } from '../utils/highlightMatching' import { applyHighlightsToHTML } from '../utils/highlightMatching'
import { readingTime } from 'reading-time-estimator' import { readingTime } from 'reading-time-estimator'
import { filterHighlightsByUrl } from '../utils/urlHelpers' import { filterHighlightsByUrl } from '../utils/urlHelpers'
import { hexToRgb } from '../utils/colorHelpers' import { hexToRgb } from '../utils/colorHelpers'
import ReaderHeader from './ReaderHeader'
interface ContentPanelProps { interface ContentPanelProps {
loading: boolean loading: boolean
@@ -162,30 +163,13 @@ const ContentPanel: React.FC<ContentPanelProps> = ({
</div> </div>
)} )}
{image && ( <ReaderHeader
<div className="reader-hero-image"> title={title}
<img src={image} alt={title || 'Article image'} /> image={image}
</div> readingTimeText={readingStats ? readingStats.text : null}
)} hasHighlights={hasHighlights}
{title && ( highlightCount={relevantHighlights.length}
<div className="reader-header"> />
<h2 className="reader-title">{title}</h2>
<div className="reader-meta">
{readingStats && (
<div className="reading-time">
<FontAwesomeIcon icon={faClock} />
<span>{readingStats.text}</span>
</div>
)}
{hasHighlights && (
<div className="highlight-indicator">
<FontAwesomeIcon icon={faHighlighter} />
<span>{relevantHighlights.length} highlight{relevantHighlights.length !== 1 ? 's' : ''}</span>
</div>
)}
</div>
</div>
)}
{markdown || html ? ( {markdown || html ? (
markdown ? ( markdown ? (
finalHtml ? ( finalHtml ? (

View File

@@ -0,0 +1,52 @@
import React from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faHighlighter, faClock } from '@fortawesome/free-solid-svg-icons'
interface ReaderHeaderProps {
title?: string
image?: string
readingTimeText?: string | null
hasHighlights: boolean
highlightCount: number
}
const ReaderHeader: React.FC<ReaderHeaderProps> = ({
title,
image,
readingTimeText,
hasHighlights,
highlightCount
}) => {
return (
<>
{image && (
<div className="reader-hero-image">
<img src={image} alt={title || 'Article image'} />
</div>
)}
{title && (
<div className="reader-header">
<h2 className="reader-title">{title}</h2>
<div className="reader-meta">
{readingTimeText && (
<div className="reading-time">
<FontAwesomeIcon icon={faClock} />
<span>{readingTimeText}</span>
</div>
)}
{hasHighlights && (
<div className="highlight-indicator">
<FontAwesomeIcon icon={faHighlighter} />
<span>{highlightCount} highlight{highlightCount !== 1 ? 's' : ''}</span>
</div>
)}
</div>
</div>
)}
</>
)
}
export default ReaderHeader