mirror of
https://github.com/dergigi/boris.git
synced 2025-12-29 04:24:34 +01:00
Make relay indicator icons clickable to trigger manual rebroadcast to all connected relays: - Click plane icon (local/offline) to rebroadcast to remote relays - Click server icon to rebroadcast to all relays - Show spinner while rebroadcasting - Update icon from plane to server on successful rebroadcast - Keep plane icon on failure - Pass relayPool and eventStore through component chain - Add local state management for highlight updates in HighlightsPanel - Enhance CSS with scale animation on hover/active
140 lines
4.2 KiB
TypeScript
140 lines
4.2 KiB
TypeScript
import React, { useState } from 'react'
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
import { faHighlighter } from '@fortawesome/free-solid-svg-icons'
|
|
import { Highlight } from '../types/highlights'
|
|
import { HighlightItem } from './HighlightItem'
|
|
import { useFilteredHighlights } from '../hooks/useFilteredHighlights'
|
|
import HighlightsPanelCollapsed from './HighlightsPanel/HighlightsPanelCollapsed'
|
|
import HighlightsPanelHeader from './HighlightsPanel/HighlightsPanelHeader'
|
|
import { RelayPool } from 'applesauce-relay'
|
|
import { IEventStore } from 'applesauce-core'
|
|
|
|
export interface HighlightVisibility {
|
|
nostrverse: boolean
|
|
friends: boolean
|
|
mine: boolean
|
|
}
|
|
|
|
interface HighlightsPanelProps {
|
|
highlights: Highlight[]
|
|
loading: boolean
|
|
isCollapsed: boolean
|
|
onToggleCollapse: () => void
|
|
onSelectUrl?: (url: string) => void
|
|
selectedUrl?: string
|
|
onToggleHighlights?: (show: boolean) => void
|
|
selectedHighlightId?: string
|
|
onRefresh?: () => void
|
|
onHighlightClick?: (highlightId: string) => void
|
|
currentUserPubkey?: string
|
|
highlightVisibility?: HighlightVisibility
|
|
onHighlightVisibilityChange?: (visibility: HighlightVisibility) => void
|
|
followedPubkeys?: Set<string>
|
|
relayPool?: RelayPool | null
|
|
eventStore?: IEventStore | null
|
|
}
|
|
|
|
export const HighlightsPanel: React.FC<HighlightsPanelProps> = ({
|
|
highlights,
|
|
loading,
|
|
isCollapsed,
|
|
onToggleCollapse,
|
|
onSelectUrl,
|
|
selectedUrl,
|
|
onToggleHighlights,
|
|
selectedHighlightId,
|
|
onRefresh,
|
|
onHighlightClick,
|
|
currentUserPubkey,
|
|
highlightVisibility = { nostrverse: true, friends: true, mine: true },
|
|
onHighlightVisibilityChange,
|
|
followedPubkeys = new Set(),
|
|
relayPool,
|
|
eventStore
|
|
}) => {
|
|
const [showHighlights, setShowHighlights] = useState(true)
|
|
const [localHighlights, setLocalHighlights] = useState(highlights)
|
|
|
|
const handleToggleHighlights = () => {
|
|
const newValue = !showHighlights
|
|
setShowHighlights(newValue)
|
|
onToggleHighlights?.(newValue)
|
|
}
|
|
|
|
// Keep track of highlight updates
|
|
React.useEffect(() => {
|
|
setLocalHighlights(highlights)
|
|
}, [highlights])
|
|
|
|
const handleHighlightUpdate = (updatedHighlight: Highlight) => {
|
|
setLocalHighlights(prev =>
|
|
prev.map(h => h.id === updatedHighlight.id ? updatedHighlight : h)
|
|
)
|
|
}
|
|
|
|
const filteredHighlights = useFilteredHighlights({
|
|
highlights: localHighlights,
|
|
selectedUrl,
|
|
highlightVisibility,
|
|
currentUserPubkey,
|
|
followedPubkeys
|
|
})
|
|
|
|
if (isCollapsed) {
|
|
return (
|
|
<HighlightsPanelCollapsed
|
|
hasHighlights={filteredHighlights.length > 0}
|
|
onToggleCollapse={onToggleCollapse}
|
|
/>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="highlights-container">
|
|
<HighlightsPanelHeader
|
|
loading={loading}
|
|
hasHighlights={filteredHighlights.length > 0}
|
|
showHighlights={showHighlights}
|
|
highlightVisibility={highlightVisibility}
|
|
currentUserPubkey={currentUserPubkey}
|
|
onToggleHighlights={handleToggleHighlights}
|
|
onRefresh={onRefresh}
|
|
onToggleCollapse={onToggleCollapse}
|
|
onHighlightVisibilityChange={onHighlightVisibilityChange}
|
|
/>
|
|
|
|
{loading && filteredHighlights.length === 0 ? (
|
|
<div className="highlights-loading">
|
|
<FontAwesomeIcon icon={faHighlighter} spin />
|
|
</div>
|
|
) : filteredHighlights.length === 0 ? (
|
|
<div className="highlights-empty">
|
|
<FontAwesomeIcon icon={faHighlighter} size="2x" />
|
|
<p>No highlights for this article.</p>
|
|
<p className="empty-hint">
|
|
{selectedUrl
|
|
? 'Create highlights for this article using a Nostr client that supports NIP-84.'
|
|
: 'Select an article to view its highlights.'}
|
|
</p>
|
|
</div>
|
|
) : (
|
|
<div className="highlights-list">
|
|
{filteredHighlights.map((highlight) => (
|
|
<HighlightItem
|
|
key={highlight.id}
|
|
highlight={highlight}
|
|
onSelectUrl={onSelectUrl}
|
|
isSelected={highlight.id === selectedHighlightId}
|
|
onHighlightClick={onHighlightClick}
|
|
relayPool={relayPool}
|
|
eventStore={eventStore}
|
|
onHighlightUpdate={handleHighlightUpdate}
|
|
/>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|