feat: implement rule engine, worker pool, event bus, and readability scraping with enhanced logging and content sanitization.

This commit is contained in:
2026-08-25 00:31:32 -07:00
parent 5ea176d5ad
commit d440728ca5
29 changed files with 2788 additions and 204 deletions
+22 -30
View File
@@ -159,6 +159,19 @@ export const App: React.FC = () => {
setFocusedIndex(entries.findIndex((e) => e.id === selectedEntryId));
return;
}
// If not found in current list, load directly so reading pane stays populated
api.getEntry(selectedEntryId).then((entry) => {
setActiveArticle(entry);
}).catch(() => {
// fallback to top
if (entries[0]) {
setFocusedIndex(0);
setActiveArticle(entries[0]);
setSelectedEntryId(entries[0].id);
localStorage.setItem('rsspipe_selected_entry_id', entries[0].id);
}
});
return;
}
setFocusedIndex(0);
@@ -177,36 +190,7 @@ export const App: React.FC = () => {
}
};
// Auto-Refresh & Background Polling (Every 30s + on focus / visibility change)
useEffect(() => {
if (!currentUser) return;
const interval = setInterval(() => {
loadSidebarData();
loadEntries();
}, 30000);
const handleWindowFocus = () => {
loadSidebarData();
loadEntries();
};
const handleVisibilityChange = () => {
if (document.visibilityState === 'visible') {
loadSidebarData();
loadEntries();
}
};
window.addEventListener('focus', handleWindowFocus);
document.addEventListener('visibilitychange', handleVisibilityChange);
return () => {
clearInterval(interval);
window.removeEventListener('focus', handleWindowFocus);
document.removeEventListener('visibilitychange', handleVisibilityChange);
};
}, [currentUser, loadSidebarData, loadEntries]);
// Refresh data only on initial mount or when user clicks refresh / changes filter
// Toggle Read Action with optimistic update
const handleToggleRead = async (entry: FeedEntry, e?: React.MouseEvent) => {
@@ -516,6 +500,10 @@ export const App: React.FC = () => {
onToggleRead={handleToggleRead}
onToggleStar={handleToggleStar}
onMarkAllRead={handleMarkAllRead}
onUpdateEntry={(updated) => {
setActiveArticle(updated);
setEntries((prev) => prev.map((e) => (e.id === updated.id ? updated : e)));
}}
sidebarCollapsed={sidebarCollapsed}
/>
) : viewMode === 'waterfall' ? (
@@ -526,6 +514,10 @@ export const App: React.FC = () => {
entries={entries}
onToggleRead={handleToggleRead}
onToggleStar={handleToggleStar}
onUpdateEntry={(updated) => {
setActiveArticle(updated);
setEntries((prev) => prev.map((e) => (e.id === updated.id ? updated : e)));
}}
/>
) : (
<SettingsView