feat: implement rule engine, worker pool, event bus, and readability scraping with enhanced logging and content sanitization.
This commit is contained in:
+22
-30
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user