Skip to content

Add manual feed reordering, synced via iCloud (#760)#5288

Open
dcaspi wants to merge 1 commit into
Ranchero-Software:mainfrom
dcaspi:feed-reordering
Open

Add manual feed reordering, synced via iCloud (#760)#5288
dcaspi wants to merge 1 commit into
Ranchero-Software:mainfrom
dcaspi:feed-reordering

Conversation

@dcaspi
Copy link
Copy Markdown

@dcaspi dcaspi commented May 14, 2026

I've been an avid NetNewsWire user for several years and love just about
everything about it. The one feature I've kept wishing for is the ability
to order feeds, so the ones I care about stand out from the noise — so I
decided to help. I've tried to stick to the idioms already in the codebase,
keep the change minimal while still working well, and add tests.

Resolves #760.

What

Feeds in the sidebar can now be reordered by dragging them within their
container (an account's top level, or a folder) — on both Mac and iOS. You
can already drag feeds today; previously the drop just snapped back. The
order is per-feed and syncs across devices on an iCloud account.

How

  • Model — a per-feed sortIndex: Int (default 0), stored in a new
    sortIndex column on FeedSettingsDatabase (with an idempotent
    ALTER TABLE migration for existing databases), exposed via
    FeedSettings.sortIndex / Feed.sortIndex — the same pattern as
    editedName, externalID, etc.
  • Sidebar order — a new Node comparator orders feeds by
    (sortIndex, name); folders still come last, alphabetically.
    SidebarTreeControllerDelegate switches to it — one change, both
    platforms. Because every feed defaults to sortIndex 0, the name
    tie-break reproduces today's alphabetical order exactly: no migration
    step, and no behavior change for anyone who never drags a feed.
  • Reorder actionAccount.reorderFeeds(_:in:) assigns 0..<n,
    posts ChildrenDidChange, and calls a new AccountDelegate.reorderFeeds
    (a default no-op; only CloudKitAccountDelegate overrides it — the
    sortIndex setter has already persisted locally for every account type).
  • iCloud sync — a new sortIndex field on the AccountWebFeed CloudKit
    record. CloudKitAccountZone.saveSortIndexes(for:) writes it with a
    changed-keys merge (other fields untouched, same as renameFeed);
    CloudKitAccountZoneDelegate reads it back on incoming records.
  • Drag and drop — extended the existing Mac (SidebarOutlineDataSource)
    and iOS (MainFeedCollectionViewController+Drop) handlers: a feed dropped
    at a new position within its own container now calls reorderFeeds.
    Shared helpers: Array<Feed>.reordered(moving:before:) and
    Container.topLevelFeedsInDisplayOrder().

Scope

v1 reorders feeds — at the top level and inside folders. Folders themselves
still sort alphabetically at the end. Possible follow-ups: reordering
folders (needs a Folder sortIndex + an AccountContainer CloudKit field);
placing newly-added feeds at the bottom of a manually-ordered container
(today they default to 0, so they land near the top); a "Reset to
alphabetical order" command.

Tests

New XCTest coverage in AccountTests: the sortIndex column + migration
from a pre-sortIndex schema, the Feed/FeedSettings proxy + change
notification, Account.reorderFeeds, and Array<Feed>.reordered. All 105
AccountTests pass; both app targets build. Manually verified drag-reorder
(top level and in folders, both platforms) and iCloud sync between devices.

Note on the CloudKit schema

The new sortIndex field on AccountWebFeed auto-creates in the CloudKit
development environment on first write; it'll need a schema deploy to
production before a release. Adding a field is backward compatible — older
clients just ignore it.

🤖 Generated with Claude Code

…e#760)

Add a per-feed sortIndex (default 0) that:
- persists locally in a new sortIndex column on FeedSettingsDatabase
  (with an idempotent ALTER TABLE migration for older databases),
  exposed as FeedSettings.sortIndex / Feed.sortIndex;
- is honored by the shared sidebar — a new Node comparator orders feeds
  by (sortIndex, name), folders still last and alphabetical; with every
  feed at the default 0 this is identical to today's alphabetical order,
  so there's no migration and no behavior change unless the user reorders;
- syncs over CloudKit: a new sortIndex field on the AccountWebFeed record,
  written by CloudKitAccountZone.saveSortIndexes(for:) (changed-keys merge,
  so other fields are untouched) and read back in CloudKitAccountZoneDelegate;
- is set by dragging a feed within its container in the existing sidebars —
  Mac NSOutlineView and iOS collection view — which previously snapped back.
  Account.reorderFeeds(_:in:) applies the new order, posts ChildrenDidChange,
  and routes to AccountDelegate.reorderFeeds (a default no-op; only the
  CloudKit delegate overrides it). Helpers: Array<Feed>.reordered(moving:before:)
  and Container.topLevelFeedsInDisplayOrder().

v1 covers feeds (top level and inside folders); folders themselves still
sort alphabetically at the end. Tests added for the database column +
migration, the Feed/FeedSettings proxy, Account.reorderFeeds, and the
Array<Feed>.reordered helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow reordering of feeds and folders

1 participant