mirror of
https://github.com/dergigi/boris.git
synced 2026-02-17 04:54:56 +01:00
- Add image prop to ContentPanel to display hero images - Extract image tag from kind:30023 bookmark tags - Display article images in Card, Large, and Compact views - Show hero image at top of article reader view - Add CSS styling for article-hero-image and reader-hero-image - Article images clickable to open article in reader - Per NIP-23: image tag contains header/preview image URL
87 lines
3.0 KiB
TypeScript
87 lines
3.0 KiB
TypeScript
import React from 'react'
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
import { faBookmark, faUserLock } from '@fortawesome/free-solid-svg-icons'
|
|
import { IndividualBookmark } from '../../types/bookmarks'
|
|
import { formatDate } from '../../utils/bookmarkUtils'
|
|
import ContentWithResolvedProfiles from '../ContentWithResolvedProfiles'
|
|
import { IconGetter } from './shared'
|
|
|
|
interface CompactViewProps {
|
|
bookmark: IndividualBookmark
|
|
index: number
|
|
hasUrls: boolean
|
|
extractedUrls: string[]
|
|
onSelectUrl?: (url: string, bookmark?: { id: string; kind: number; tags: string[][]; pubkey: string }) => void
|
|
getIconForUrlType: IconGetter
|
|
firstUrlClassification: { buttonText: string } | null
|
|
articleImage?: string
|
|
}
|
|
|
|
export const CompactView: React.FC<CompactViewProps> = ({
|
|
bookmark,
|
|
index,
|
|
hasUrls,
|
|
extractedUrls,
|
|
onSelectUrl,
|
|
getIconForUrlType,
|
|
firstUrlClassification
|
|
}) => {
|
|
const isArticle = bookmark.kind === 30023
|
|
const isClickable = hasUrls || isArticle
|
|
|
|
const handleCompactClick = () => {
|
|
if (!onSelectUrl) return
|
|
|
|
if (isArticle) {
|
|
onSelectUrl('', { id: bookmark.id, kind: bookmark.kind, tags: bookmark.tags, pubkey: bookmark.pubkey })
|
|
} else if (hasUrls) {
|
|
onSelectUrl(extractedUrls[0])
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div key={`${bookmark.id}-${index}`} className={`individual-bookmark compact ${bookmark.isPrivate ? 'private-bookmark' : ''}`}>
|
|
<div
|
|
className={`compact-row ${isClickable ? 'clickable' : ''}`}
|
|
onClick={handleCompactClick}
|
|
role={isClickable ? 'button' : undefined}
|
|
tabIndex={isClickable ? 0 : undefined}
|
|
>
|
|
<span className="bookmark-type-compact">
|
|
{bookmark.isPrivate ? (
|
|
<>
|
|
<FontAwesomeIcon icon={faBookmark} className="bookmark-visibility public" />
|
|
<FontAwesomeIcon icon={faUserLock} className="bookmark-visibility private" />
|
|
</>
|
|
) : (
|
|
<FontAwesomeIcon icon={faBookmark} className="bookmark-visibility public" />
|
|
)}
|
|
</span>
|
|
{bookmark.content && (
|
|
<div className="compact-text">
|
|
<ContentWithResolvedProfiles content={bookmark.content.slice(0, 60) + (bookmark.content.length > 60 ? '…' : '')} />
|
|
</div>
|
|
)}
|
|
<span className="bookmark-date-compact">{formatDate(bookmark.created_at)}</span>
|
|
{isClickable && (
|
|
<button
|
|
className="compact-read-btn"
|
|
onClick={(e) => {
|
|
e.stopPropagation()
|
|
if (isArticle) {
|
|
onSelectUrl?.('', { id: bookmark.id, kind: bookmark.kind, tags: bookmark.tags, pubkey: bookmark.pubkey })
|
|
} else {
|
|
onSelectUrl?.(extractedUrls[0])
|
|
}
|
|
}}
|
|
title={isArticle ? 'Read Article' : firstUrlClassification?.buttonText}
|
|
>
|
|
<FontAwesomeIcon icon={isArticle ? getIconForUrlType('') : getIconForUrlType(extractedUrls[0])} />
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|