FeedEventHandlers.ts raw
1 import {
2 FeedSwitched,
3 ContentFilterUpdated,
4 FeedRefreshed,
5 NoteCreated,
6 NoteDeleted,
7 NoteReplied,
8 UsersMentioned,
9 TimelineEventsReceived,
10 TimelineEOSED
11 } from '@/domain/feed/events'
12 import { EventHandler, eventDispatcher } from '@/domain/shared'
13
14 /**
15 * Handlers for Feed domain events
16 *
17 * These handlers coordinate cross-context updates when feed events occur.
18 * They enable coordination between Feed, Social, Content, and UI contexts.
19 */
20
21 /**
22 * Handler for feed switched events
23 * Can be used to:
24 * - Clear timeline caches for the old feed
25 * - Prefetch content for the new feed
26 * - Update URL/navigation state
27 * - Log analytics
28 */
29 export const handleFeedSwitched: EventHandler<FeedSwitched> = async (event) => {
30 console.debug('[FeedEventHandler] Feed switched:', {
31 owner: event.owner?.formatted,
32 fromType: event.fromType?.value ?? 'none',
33 toType: event.toType.value,
34 relaySetId: event.relaySetId
35 })
36
37 // Future: Clear old timeline cache
38 // Future: Trigger new timeline fetch
39 // Future: Update analytics
40 }
41
42 /**
43 * Handler for content filter updated events
44 * Can be used to:
45 * - Re-filter current timeline with new settings
46 * - Persist filter preferences
47 * - Update filter indicators in UI
48 */
49 export const handleContentFilterUpdated: EventHandler<ContentFilterUpdated> = async (event) => {
50 console.debug('[FeedEventHandler] Content filter updated:', {
51 owner: event.owner.formatted,
52 hideRepliesChanged: event.previousFilter.hideReplies !== event.newFilter.hideReplies,
53 hideRepostsChanged: event.previousFilter.hideReposts !== event.newFilter.hideReposts,
54 nsfwPolicyChanged: event.previousFilter.nsfwPolicy !== event.newFilter.nsfwPolicy
55 })
56
57 // Future: Trigger timeline re-filter
58 // Future: Persist filter preferences
59 }
60
61 /**
62 * Handler for feed refreshed events
63 * Can be used to:
64 * - Update last refresh timestamp display
65 * - Trigger background data fetch
66 * - Reset scroll position indicators
67 */
68 export const handleFeedRefreshed: EventHandler<FeedRefreshed> = async (event) => {
69 console.debug('[FeedEventHandler] Feed refreshed:', {
70 owner: event.owner?.formatted,
71 feedType: event.feedType.value
72 })
73
74 // Future: Update refresh timestamp in UI
75 // Future: Trigger stale data cleanup
76 }
77
78 /**
79 * Handler for note created events
80 * Can be used to:
81 * - Add note to local timeline immediately (optimistic UI)
82 * - Create notifications for mentioned users
83 * - Update post count displays
84 */
85 export const handleNoteCreated: EventHandler<NoteCreated> = async (event) => {
86 console.debug('[FeedEventHandler] Note created:', {
87 author: event.author.formatted,
88 noteId: event.noteId.hex,
89 mentionCount: event.mentions.length,
90 isReply: event.isReply,
91 isQuote: event.isQuote
92 })
93
94 // Future: Add to local timeline if author is self
95 // Future: Create mention notifications
96 }
97
98 /**
99 * Handler for note deleted events
100 * Can be used to:
101 * - Remove note from all timelines
102 * - Update reply counts on parent notes
103 * - Clean up cached data
104 */
105 export const handleNoteDeleted: EventHandler<NoteDeleted> = async (event) => {
106 console.debug('[FeedEventHandler] Note deleted:', {
107 author: event.author.formatted,
108 noteId: event.noteId.hex
109 })
110
111 // Future: Remove from timeline display
112 // Future: Remove from caches
113 }
114
115 /**
116 * Handler for note replied events
117 * Can be used to:
118 * - Increment reply count on parent note
119 * - Create notification for parent note author
120 * - Update thread view if open
121 */
122 export const handleNoteReplied: EventHandler<NoteReplied> = async (event) => {
123 console.debug('[FeedEventHandler] Note replied:', {
124 replier: event.replier.formatted,
125 replyNoteId: event.replyNoteId.hex,
126 originalNoteId: event.originalNoteId.hex,
127 originalAuthor: event.originalAuthor.formatted
128 })
129
130 // Future: Increment reply count
131 // Future: Create reply notification for parent author
132 // Future: Update thread view
133 }
134
135 /**
136 * Handler for users mentioned events
137 * Can be used to:
138 * - Create mention notifications for each mentioned user
139 * - Highlight mentions in the source note
140 */
141 export const handleUsersMentioned: EventHandler<UsersMentioned> = async (event) => {
142 console.debug('[FeedEventHandler] Users mentioned:', {
143 author: event.author.formatted,
144 noteId: event.noteId.hex,
145 mentionedCount: event.mentionedPubkeys.length
146 })
147
148 // Future: Create mention notifications
149 }
150
151 /**
152 * Handler for timeline events received
153 * Can be used to:
154 * - Update event cache
155 * - Trigger profile/metadata fetches for new authors
156 * - Update unread counts
157 */
158 export const handleTimelineEventsReceived: EventHandler<TimelineEventsReceived> = async (event) => {
159 console.debug('[FeedEventHandler] Timeline events received:', {
160 feedType: event.feedType.value,
161 eventCount: event.eventCount,
162 newestTimestamp: event.newestTimestamp.unix,
163 isHistorical: event.isHistorical
164 })
165
166 // Future: Prefetch profiles for new authors
167 // Future: Update new post indicators
168 }
169
170 /**
171 * Handler for timeline EOSE (end of stored events)
172 * Can be used to:
173 * - Mark initial load as complete
174 * - Switch from loading to live mode
175 * - Update loading indicators
176 */
177 export const handleTimelineEOSED: EventHandler<TimelineEOSED> = async (event) => {
178 console.debug('[FeedEventHandler] Timeline EOSE:', {
179 feedType: event.feedType.value,
180 totalEvents: event.totalEvents
181 })
182
183 // Future: Update loading state
184 // Future: Show "up to date" indicator
185 }
186
187 /**
188 * Register all feed event handlers with the event dispatcher
189 */
190 export function registerFeedEventHandlers(): void {
191 eventDispatcher.on('feed.switched', handleFeedSwitched)
192 eventDispatcher.on('feed.content_filter_updated', handleContentFilterUpdated)
193 eventDispatcher.on('feed.refreshed', handleFeedRefreshed)
194 eventDispatcher.on('feed.note_created', handleNoteCreated)
195 eventDispatcher.on('feed.note_deleted', handleNoteDeleted)
196 eventDispatcher.on('feed.note_replied', handleNoteReplied)
197 eventDispatcher.on('feed.users_mentioned', handleUsersMentioned)
198 eventDispatcher.on('feed.timeline_events_received', handleTimelineEventsReceived)
199 eventDispatcher.on('feed.timeline_eosed', handleTimelineEOSED)
200 }
201
202 /**
203 * Unregister all feed event handlers
204 */
205 export function unregisterFeedEventHandlers(): void {
206 eventDispatcher.off('feed.switched', handleFeedSwitched)
207 eventDispatcher.off('feed.content_filter_updated', handleContentFilterUpdated)
208 eventDispatcher.off('feed.refreshed', handleFeedRefreshed)
209 eventDispatcher.off('feed.note_created', handleNoteCreated)
210 eventDispatcher.off('feed.note_deleted', handleNoteDeleted)
211 eventDispatcher.off('feed.note_replied', handleNoteReplied)
212 eventDispatcher.off('feed.users_mentioned', handleUsersMentioned)
213 eventDispatcher.off('feed.timeline_events_received', handleTimelineEventsReceived)
214 eventDispatcher.off('feed.timeline_eosed', handleTimelineEOSED)
215 }
216