mirror of
https://github.com/dergigi/boris.git
synced 2026-01-28 11:14:22 +01:00
feat: add listener for markedAsReadChanged events
Implemented event listener pattern in readingProgressController: - Added onMarkedAsReadChanged() method for subscribers - Added emitMarkedAsReadChanged() to notify when marked IDs update - Call emitMarkedAsReadChanged() after loading reactions In Me.tsx: - Subscribe to onMarkedAsReadChanged() in new useEffect - When fired, rebuild reads list with new marked-as-read items - Include marked-only items (no progress event) Now when reactions finish loading in background, /me/reads/completed will update automatically with newly marked articles.
This commit is contained in:
@@ -192,6 +192,46 @@ const Me: React.FC<MeProps> = ({
|
||||
unsubProgress()
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Subscribe to marked-as-read changes and rebuild reads list
|
||||
useEffect(() => {
|
||||
const unsubMarkedAsRead = readingProgressController.onMarkedAsReadChanged(() => {
|
||||
// Rebuild reads list including marked-as-read-only items
|
||||
const progressMap = readingProgressController.getProgressMap()
|
||||
const readItems: ReadItem[] = Array.from(progressMap.entries()).map(([id, progress]) => ({
|
||||
id,
|
||||
source: 'reading-progress',
|
||||
type: 'article',
|
||||
readingProgress: progress,
|
||||
markedAsRead: readingProgressController.isMarkedAsRead(id),
|
||||
readingTimestamp: Math.floor(Date.now() / 1000)
|
||||
}))
|
||||
|
||||
// Include items that are only marked-as-read (no progress event yet)
|
||||
const markedIds = readingProgressController.getMarkedAsReadIds()
|
||||
for (const id of markedIds) {
|
||||
if (!readItems.find(i => i.id === id)) {
|
||||
const isArticle = id.startsWith('naddr1')
|
||||
readItems.push({
|
||||
id,
|
||||
source: 'marked-as-read',
|
||||
type: isArticle ? 'article' : 'external',
|
||||
url: isArticle ? undefined : id,
|
||||
markedAsRead: true,
|
||||
readingTimestamp: Math.floor(Date.now() / 1000)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const readsMap = new Map(readItems.map(item => [item.id, item]))
|
||||
setReadsMap(readsMap)
|
||||
setReads(readItems)
|
||||
})
|
||||
|
||||
return () => {
|
||||
unsubMarkedAsRead()
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Load reading progress data for writings tab
|
||||
useEffect(() => {
|
||||
|
||||
@@ -24,6 +24,7 @@ const PROGRESS_CACHE_KEY = 'reading_progress_cache_v1'
|
||||
class ReadingProgressController {
|
||||
private progressListeners: ProgressMapCallback[] = []
|
||||
private loadingListeners: LoadingCallback[] = []
|
||||
private markedAsReadListeners: (() => void)[] = []
|
||||
|
||||
private currentProgressMap: Map<string, number> = new Map()
|
||||
private markedAsReadIds: Set<string> = new Set()
|
||||
@@ -46,6 +47,13 @@ class ReadingProgressController {
|
||||
}
|
||||
}
|
||||
|
||||
onMarkedAsReadChanged(cb: () => void): () => void {
|
||||
this.markedAsReadListeners.push(cb)
|
||||
return () => {
|
||||
this.markedAsReadListeners = this.markedAsReadListeners.filter(l => l !== cb)
|
||||
}
|
||||
}
|
||||
|
||||
private setLoading(loading: boolean): void {
|
||||
this.loadingListeners.forEach(cb => cb(loading))
|
||||
}
|
||||
@@ -54,6 +62,10 @@ class ReadingProgressController {
|
||||
this.progressListeners.forEach(cb => cb(new Map(progressMap)))
|
||||
}
|
||||
|
||||
private emitMarkedAsReadChanged(): void {
|
||||
this.markedAsReadListeners.forEach(cb => cb())
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current reading progress map without triggering a reload
|
||||
*/
|
||||
@@ -378,6 +390,7 @@ class ReadingProgressController {
|
||||
}
|
||||
|
||||
console.log('[readingProgress] Mark-as-read reactions complete. Total:', Array.from(this.markedAsReadIds).length)
|
||||
this.emitMarkedAsReadChanged()
|
||||
} catch (err) {
|
||||
console.warn('[readingProgress] Failed to load mark-as-read reactions:', err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user