Repository navigation
Conversation
First part of the Feeds tab (#230): FeedGroup, Feed and FeedItemState domain types, Azure Table storage (FeedGroups, Feeds, FeedItemStates) and api/feeds endpoints for groups, feeds and Added/Skipped item state. Skipped records older than 60 days are pruned when states are listed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RmvEuU4c1z8w9onm9taU73
GET api/feeds/items returns pending items, newest first, for all feeds, one group or one feed. Feeds download in parallel (max 8) with a 10 s timeout each and a 15 minute in-memory cache; refresh=true bypasses it. A failing feed reports its error while the others still load. Items older than 30 days, already Added/Skipped, already saved as Posts, or duplicated across feeds are hidden. Feed HTML is sanitized with an allow-list before it reaches the UI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RmvEuU4c1z8w9onm9taU73
API: GET api/feeds/discover finds the feed behind a feed or site URL (<link rel="alternate">); POST api/feeds/import-opml imports a Feedly style OPML (top-level folders become groups, nested folders flatten into their top-level group, known feeds are skipped). UI: IFeedService/FeedClient in SharedUI (registered in the web app only) and a /feeds/manage page to add feeds, create/rename/delete groups, move or delete feeds and upload an OPML file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RmvEuU4c1z8w9onm9taU73
New /feeds page in SharedUI, linked from the web app's nav menu only. Left pane: "All" and the groups with pending counts, expandable to their feeds; failing feeds show a warning icon with the error as tooltip. Right pane: items newest first with title, feed, age and a one-line excerpt. Refresh bypasses the API cache for the current selection; "Mark all as skipped" skips the selected group or feed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RmvEuU4c1z8w9onm9taU73
Clicking an item on the Feeds tab opens a FluentUI dialog with the feed-provided content (source, date, author, lead image, sanitized body). Add saves the article through ExtractPostDetailsAndSave (same path as Search suggestions and QuickAdd) and marks it Added; Skip marks it Skipped; both remove it from the list. Close leaves it, and Open original opens the real URL in a new browser tab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RmvEuU4c1z8w9onm9taU73
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Frank · project thread
Implements #230 in one PR, one commit per sub-issue.
Closes #231
Closes #232
Closes #233
Closes #234
Closes #235
Commits
FeedGroup,Feed,FeedItemState(Added/Skipped by URL) in Domain, tablesFeedGroups,FeedsandFeedItemStates, and theapi/feedsCRUD endpoints. A group can't be deleted while it still has feeds (409). Feed URLs and item URLs are compared after normalizing them (FeedItemState.NormalizeUrl), and item-state keys are a SHA-256 hash of that. Skipped records older than 60 days are pruned when states are listed.GET api/feeds/items?groupId=&feedId=&refresh=. Feeds are fetched in parallel (8 at a time), with a 10 s timeout per feed and a 15 min in-memory cache.refresh=trueskips the cache. A failing feed returns its error and the other feeds still load. Items older than 30 days are hidden, and so are Added/Skipped items, items already saved as Posts, and the same article appearing in two feeds. The parser (FeedParser) reads RSS 2.0, RSS 1.0/RDF and Atom, ignores DTDs, and handles odd date formats. Feed HTML goes through an allow-listHtmlSanitizer(HtmlAgilityPack, already a dependency) before it reaches the UI.GET api/feeds/discover(works with a feed URL or a site URL, via<link rel="alternate">) andPOST api/feeds/import-opml(Feedly export: top-level folders become groups, nested folders go into their top-level group, feeds you already follow are skipped)./feeds/managepage to add feeds, create/rename/delete groups, move or delete feeds, and upload an OPML file. TheIFeedService/FeedClientinterface and client are kept separate fromIDataService, so the MAUI app'sOfflineDataServiceneeded no changes./feedspage plus a nav link in the web app'sNavMenuonly. On the left: "All" and the groups with pending counts, expandable to their feeds, with a warning icon and the error as tooltip on failing feeds. On the right: items newest first. Refresh re-fetches the current selection. "Mark all as skipped" works on the selected group or feed (disabled on "All").ExtractPostDetailsAndSave, then marks the item Added and shows a toast. Skip marks it Skipped. Both remove the item from the list. Close does nothing else. Open original opens the URL in a new tab throughIUrlLauncher.Not in this PR (per #230)
MAUI support, background polling, a feed in several groups, authenticated feeds. The new pages live in SharedUI but
IFeedServiceis only registered in the web app, so they aren't reachable from MAUI.Tests
FeedClientand the nav link.ExtractPostDetails_WithValidUrl_ReturnsOkWithPost, which fetches docs.microsoft.com; my sandbox can't reach it, and the test also fails without this PR there./feedsa quick click-through.🤖 Generated with Claude Code
https://claude.ai/code/session_01RmvEuU4c1z8w9onm9taU73