Files
amethyst/commons/plans/2026-05-05-feed-builder-enhancements-plan.md
T
nrobi144 4010a57e68 feat(desktop): add custom feeds system with creation, pinning, and inline switching
- FeedDefinition data model with FeedSource sealed interface (Filter, Following, Global, DVM, PeopleList, InterestSet, SingleRelay)
- FeedDefinitionRepository with StateFlow, groupedFeeds, pin/unpin/reorder (max 3 pinned)
- JSON serialization via Jackson with round-trip tests (18 unit tests)
- SearchQuery.toFeedDefinition() bridge for creating feeds from search
- FeedBuilderDialog with author search (cache lookup + npub decode), hashtag/relay inputs, kind filter checkboxes, exclude authors/keywords, Cmd+S save, Enter to add
- FeedsDrawerTab in app drawer with edit/delete/pin/unpin actions
- Feeds tab in top header (FilterChips) with inline mode switching
- CustomFeedScreen + DesktopCustomFeedFilter + createCustomFeedSubscription for relay-based custom feed content
- FeedDefinitionEvent (kind 31890) in quartz for future publish/import
- Local persistence via java.util.prefs.Preferences (auto-save on change)
- DeckColumnType.CustomFeed for navigation integration
- Renamed Home to Feeds in nav rail
- Fix: AnimatedGifImage race condition (coerceIn on frame index)
- Fix: search results margins (sidePadding applied consistently)
- Fix: app drawer search includes feeds in results

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 09:59:30 +03:00

2.9 KiB

Feed Builder Enhancements

Date: 2026-05-05 Status: Implementation

Scope

Enhance FeedBuilderDialog with 6 items:

  1. npub auto-decode (paste npub -> hex + display name)
  2. Author search (type name -> search LocalCache -> pick)
  3. Kind filter checkboxes (Notes, Reposts, Articles)
  4. Edit + Delete feeds (CRUD completeness)
  5. "Save as Feed" button in search results
  6. Exclude authors field in dialog

Implementation

1. npub Auto-Decode

Where: FeedBuilderDialog.kt ChipInputField for Authors

Logic:

  • On add: if input starts with npub1, decode via decodePublicKeyAsHexOrNull()
  • If decode succeeds, add hex to authors list
  • Show display name in chip (resolve from LocalCache)

Where: New AuthorSearchField composable in FeedBuilderDialog.kt

Flow:

  • Replace plain text field for authors with search field
  • Type >= 2 chars -> filter DesktopLocalCache.users by displayName/nip05
  • Show dropdown with matching profiles (avatar placeholder + name + npub short)
  • Click adds hex to authors list
  • Still allow raw npub/hex paste (falls through to auto-decode)

Data source: DesktopLocalCache.users (already populated from metadata subscriptions)

3. Kind Filter Checkboxes

Where: FeedBuilderDialog.kt, new section between relays and exclude

UI: FlowRow of FilterChips:

  • Notes (kind 1)
  • Reposts (kind 6, 16)
  • Articles (kind 30023)
  • Highlights (kind 9802)
  • Reactions (kind 7)

Default: Notes + Reposts checked. Maps to FeedBuilderState.kinds.

4. Edit + Delete in Drawer

Where: FeedsDrawerTab.kt

Edit: Add edit button on each FeedRow -> opens FeedBuilderDialog(initial = feed)

  • On save: calls feedRepository.update(feed)

Delete: Add delete in context or as swipe action

  • Confirm dialog: "Delete feed X?"
  • Calls feedRepository.delete(feed.id)

Where: SearchScreen.kt or SearchResultsList.kt

UI: Show "Save as Feed" button when query.canBecomeFeed() is true

  • Button appears in the header area, next to the search bar actions
  • Click opens FeedBuilderDialog pre-filled from query.toFeedDefinition()

6. Exclude Authors in Dialog

Where: FeedBuilderDialog.kt

UI: Same chip input pattern as regular authors but for excludes

  • Uses same author search/npub-decode logic
  • Maps to FeedBuilderState.excludeAuthors

File Changes

File Change
FeedBuilderDialog.kt Author search field, npub decode, kind checkboxes, exclude authors
FeedsDrawerTab.kt Edit/delete buttons on feed rows
SearchScreen.kt "Save as Feed" button
FeedBuilderState.kt No changes needed (already has all fields)

Dependencies

  • decodePublicKeyAsHexOrNull from quartz/nip19Bech32
  • DesktopLocalCache.users for profile search
  • SearchQuery.canBecomeFeed() + toFeedDefinition() already exist