mirror of
https://github.com/dergigi/boris.git
synced 2026-01-18 22:34:34 +01:00
refactor: simplify highlights state management - remove prop drilling
Remove unnecessary prop drilling of myHighlights/myHighlightsLoading. Components now subscribe directly to highlightsController (DRY principle). Changes: - Explore: Subscribe to controller directly, no props needed - Me: Subscribe to controller directly, no props needed - Bookmarks: Remove myHighlights props (no longer passes through) - App: Remove highlights state, controller manages it internally Benefits: - ✅ Simpler code (no prop drilling through 3 layers) - ✅ More DRY (single source of truth in controller) - ✅ Consistent with applesauce patterns (like useActiveAccount) - ✅ Less boilerplate (removed ~30 lines of prop passing) - ✅ Controller encapsulates all state management Pattern: Components import and subscribe to controller directly, just like they use Hooks.useActiveAccount() or other applesauce hooks.
This commit is contained in:
@@ -14,7 +14,6 @@ import { useBookmarksUI } from '../hooks/useBookmarksUI'
|
||||
import { useRelayStatus } from '../hooks/useRelayStatus'
|
||||
import { useOfflineSync } from '../hooks/useOfflineSync'
|
||||
import { Bookmark } from '../types/bookmarks'
|
||||
import { Highlight } from '../types/highlights'
|
||||
import ThreePaneLayout from './ThreePaneLayout'
|
||||
import Explore from './Explore'
|
||||
import Me from './Me'
|
||||
@@ -29,8 +28,6 @@ interface BookmarksProps {
|
||||
bookmarks: Bookmark[]
|
||||
bookmarksLoading: boolean
|
||||
onRefreshBookmarks: () => Promise<void>
|
||||
myHighlights: Highlight[]
|
||||
myHighlightsLoading: boolean
|
||||
}
|
||||
|
||||
const Bookmarks: React.FC<BookmarksProps> = ({
|
||||
@@ -38,9 +35,7 @@ const Bookmarks: React.FC<BookmarksProps> = ({
|
||||
onLogout,
|
||||
bookmarks,
|
||||
bookmarksLoading,
|
||||
onRefreshBookmarks,
|
||||
myHighlights,
|
||||
myHighlightsLoading
|
||||
onRefreshBookmarks
|
||||
}) => {
|
||||
const { naddr, npub } = useParams<{ naddr?: string; npub?: string }>()
|
||||
const location = useLocation()
|
||||
@@ -327,10 +322,10 @@ const Bookmarks: React.FC<BookmarksProps> = ({
|
||||
onCreateHighlight={handleCreateHighlight}
|
||||
hasActiveAccount={!!(activeAccount && relayPool)}
|
||||
explore={showExplore ? (
|
||||
relayPool ? <Explore relayPool={relayPool} eventStore={eventStore} settings={settings} activeTab={exploreTab} myHighlights={myHighlights} myHighlightsLoading={myHighlightsLoading} /> : null
|
||||
relayPool ? <Explore relayPool={relayPool} eventStore={eventStore} settings={settings} activeTab={exploreTab} /> : null
|
||||
) : undefined}
|
||||
me={showMe ? (
|
||||
relayPool ? <Me relayPool={relayPool} activeTab={meTab} bookmarks={bookmarks} bookmarksLoading={bookmarksLoading} myHighlights={myHighlights} myHighlightsLoading={myHighlightsLoading} /> : null
|
||||
relayPool ? <Me relayPool={relayPool} activeTab={meTab} bookmarks={bookmarks} bookmarksLoading={bookmarksLoading} /> : null
|
||||
) : undefined}
|
||||
profile={showProfile && profilePubkey ? (
|
||||
relayPool ? <Me relayPool={relayPool} activeTab={profileTab} pubkey={profilePubkey} bookmarks={bookmarks} bookmarksLoading={bookmarksLoading} /> : null
|
||||
|
||||
@@ -13,6 +13,7 @@ import { fetchBlogPostsFromAuthors, BlogPostPreview } from '../services/exploreS
|
||||
import { fetchHighlightsFromAuthors } from '../services/highlightService'
|
||||
import { fetchProfiles } from '../services/profileService'
|
||||
import { fetchNostrverseBlogPosts, fetchNostrverseHighlights } from '../services/nostrverseService'
|
||||
import { highlightsController } from '../services/highlightsController'
|
||||
import { Highlight } from '../types/highlights'
|
||||
import { UserSettings } from '../services/settingsService'
|
||||
import BlogPostCard from './BlogPostCard'
|
||||
@@ -28,13 +29,11 @@ interface ExploreProps {
|
||||
eventStore: IEventStore
|
||||
settings?: UserSettings
|
||||
activeTab?: TabType
|
||||
myHighlights?: Highlight[] // From highlightsController in App.tsx
|
||||
myHighlightsLoading?: boolean // Loading state from highlightsController
|
||||
}
|
||||
|
||||
type TabType = 'writings' | 'highlights'
|
||||
|
||||
const Explore: React.FC<ExploreProps> = ({ relayPool, eventStore, settings, activeTab: propActiveTab, myHighlights = [], myHighlightsLoading = false }) => {
|
||||
const Explore: React.FC<ExploreProps> = ({ relayPool, eventStore, settings, activeTab: propActiveTab }) => {
|
||||
const activeAccount = Hooks.useActiveAccount()
|
||||
const navigate = useNavigate()
|
||||
const [activeTab, setActiveTab] = useState<TabType>(propActiveTab || 'highlights')
|
||||
@@ -44,6 +43,10 @@ const Explore: React.FC<ExploreProps> = ({ relayPool, eventStore, settings, acti
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [refreshTrigger, setRefreshTrigger] = useState(0)
|
||||
|
||||
// Get myHighlights directly from controller
|
||||
const [myHighlights, setMyHighlights] = useState<Highlight[]>([])
|
||||
const [myHighlightsLoading, setMyHighlightsLoading] = useState(false)
|
||||
|
||||
// Visibility filters (defaults from settings, or friends only)
|
||||
const [visibility, setVisibility] = useState<HighlightVisibility>({
|
||||
nostrverse: settings?.defaultHighlightVisibilityNostrverse ?? false,
|
||||
@@ -51,6 +54,16 @@ const Explore: React.FC<ExploreProps> = ({ relayPool, eventStore, settings, acti
|
||||
mine: settings?.defaultHighlightVisibilityMine ?? false
|
||||
})
|
||||
|
||||
// Subscribe to highlights controller
|
||||
useEffect(() => {
|
||||
const unsubHighlights = highlightsController.onHighlights(setMyHighlights)
|
||||
const unsubLoading = highlightsController.onLoading(setMyHighlightsLoading)
|
||||
return () => {
|
||||
unsubHighlights()
|
||||
unsubLoading()
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Update local state when prop changes
|
||||
useEffect(() => {
|
||||
if (propActiveTab) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { Highlight } from '../types/highlights'
|
||||
import { HighlightItem } from './HighlightItem'
|
||||
import { fetchHighlights } from '../services/highlightService'
|
||||
import { highlightsController } from '../services/highlightsController'
|
||||
import { fetchAllReads, ReadItem } from '../services/readsService'
|
||||
import { fetchLinks } from '../services/linksService'
|
||||
import { BlogPostPreview, fetchBlogPostsFromAuthors } from '../services/exploreService'
|
||||
@@ -38,8 +39,6 @@ interface MeProps {
|
||||
pubkey?: string // Optional pubkey for viewing other users' profiles
|
||||
bookmarks: Bookmark[] // From centralized App.tsx state
|
||||
bookmarksLoading?: boolean // From centralized App.tsx state (reserved for future use)
|
||||
myHighlights?: Highlight[] // From highlightsController (for own profile)
|
||||
myHighlightsLoading?: boolean // Loading state from highlightsController
|
||||
}
|
||||
|
||||
type TabType = 'highlights' | 'reading-list' | 'reads' | 'links' | 'writings'
|
||||
@@ -51,9 +50,7 @@ const Me: React.FC<MeProps> = ({
|
||||
relayPool,
|
||||
activeTab: propActiveTab,
|
||||
pubkey: propPubkey,
|
||||
bookmarks,
|
||||
myHighlights = [],
|
||||
myHighlightsLoading = false
|
||||
bookmarks
|
||||
}) => {
|
||||
const activeAccount = Hooks.useActiveAccount()
|
||||
const navigate = useNavigate()
|
||||
@@ -71,6 +68,10 @@ const Me: React.FC<MeProps> = ({
|
||||
const [writings, setWritings] = useState<BlogPostPreview[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [loadedTabs, setLoadedTabs] = useState<Set<TabType>>(new Set())
|
||||
|
||||
// Get myHighlights directly from controller
|
||||
const [myHighlights, setMyHighlights] = useState<Highlight[]>([])
|
||||
const [myHighlightsLoading, setMyHighlightsLoading] = useState(false)
|
||||
const [viewMode, setViewMode] = useState<ViewMode>('cards')
|
||||
const [refreshTrigger, setRefreshTrigger] = useState(0)
|
||||
const [bookmarkFilter, setBookmarkFilter] = useState<BookmarkFilterType>('all')
|
||||
@@ -91,6 +92,16 @@ const Me: React.FC<MeProps> = ({
|
||||
: 'all'
|
||||
const [readingProgressFilter, setReadingProgressFilter] = useState<ReadingProgressFilterType>(initialFilter)
|
||||
|
||||
// Subscribe to highlights controller
|
||||
useEffect(() => {
|
||||
const unsubHighlights = highlightsController.onHighlights(setMyHighlights)
|
||||
const unsubLoading = highlightsController.onLoading(setMyHighlightsLoading)
|
||||
return () => {
|
||||
unsubHighlights()
|
||||
unsubLoading()
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Update local state when prop changes
|
||||
useEffect(() => {
|
||||
if (propActiveTab) {
|
||||
|
||||
Reference in New Issue
Block a user