A native feed list and item list (#3)

The lists are native now, and the page is a button in the toolbar: it is
still where signing in happens, and it is still the whole of settings, the
admin page, the directory and OPML, which were never going to be rewritten.

LibraryStore holds a page of items and asks for the next, because the
sorting, filtering and searching are the server's work and ten thousand
items have no business being in memory to be sorted here. Read and pinned
are set locally and sent after, as the page's readWrites map does and for
the same reason: a list asked for before the write lands answers with the
old state, which put the dot back on an item just read.

The interface follows the account's light or dark rather than the phone's,
and defaults to dark when nobody has chosen, because that is what ipx's own
theme.ts does. Following the system instead put a light list in front of a
dark page. preferredColorScheme was not enough on its own -- inside a
hosting controller it did not reach the hierarchy -- so the style is
overridden on the controller, which also carries to the page presented over
it.

The sidebar had to be broken into sub-views: the whole list in one
expression was more than the type checker would work through, and it said
so rather than compiling it.

Tested against the real library, 135 feeds and eleven thousand items, and
the playback test now drives the native row rather than the page's button.
Thirteen pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-20 09:27:03 -04:00
parent cacf992b7d
commit 01d8bd936e
10 changed files with 725 additions and 44 deletions

View File

@@ -55,6 +55,17 @@ project had no such setting and the Mac destination simply did not exist.
Set your team under Signing & Capabilities, pick your phone, and run. The project is generated from
`project.yml`, so `.xcodeproj` is not in git — edit the yml, not the project.
## What is native and what is the page
The lists, the player and the car are native. Settings, the admin page, Directory, Popular and
OPML are ipx's own page, opened from the toolbar — they are form-heavy, rarely touched, and they
already work. An item's show notes will stay HTML too, since they are feed-supplied and sanitized
server-side and there is no good native renderer for them.
That split is the point rather than a stage: native where native is better, the page everywhere
else. The page is also still where signing in happens, and its cookies are what authenticate the
API client and the player.
## Which server
The first launch asks, with `https://ipodderx.sdf1.net` filled in. A bare host gets `https://`, so
@@ -86,6 +97,11 @@ For automation, `-ipx.server <url>` as a launch argument overrides the stored va
| `ios/Sources/Events.swift` | the `/api/events` stream, and reconnecting to it |
| `ios/Sources/Glass.swift` | the Glass look: materials, palette, the wash |
| `ios/Sources/PlayerBarView.swift` | the bar along the bottom |
| `ios/Sources/LibraryStore.swift` | what the lists show, and the optimistic writes |
| `ios/Sources/FeedListView.swift` | the sidebar: places, feeds, OPML folders |
| `ios/Sources/ItemListView.swift` | the item table: filter, sort, search, paging |
| `ios/Sources/LibraryView.swift` | the two beside each other, bar underneath |
| `ios/Sources/RootViewController.swift` | the native interface, with the page a button away |
| `ios/Sources/CookieBridge.swift` | `WKHTTPCookieStore` into `HTTPCookieStorage.shared` |
| `ios/Sources/ServerSettings.swift` | which server |