~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

The iOS app's inbox keeps your place when you come back to it

Merged
Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:ios/inbox-keeps-place

What changes

The inbox keeps your place. Each time it was shown again, as after opening a notification or another tab, it read its first page and dropped the rest, so a list scrolled down jumped back to the top. Now it reads the first page over what it already has. Another filter or account still starts anew, and pulling to refresh does too.

A page still on its way when the filter changes is dropped, rather than added to the new filter's list.

How it was checked

just ios-look inbox with 50 sample notifications, served 10 at a time by a temporary change to the app: scrolled down, to Home and back. On the old code it's back at Row 0, and on this it stays at Row 20.

Shortcomings

Not run against the live server. ios/ isn't built by CI.

🤖 Generated with Claude Code

inbox-before.png

inbox-after.png

Asked for changes

This makes the inbox's .task re-read only the first page over what it already has, using rereading as PagedList does. A page still in flight when the filter changes is dropped. The approach matches PagedList and is sound, but read = key can be set when items are not of that key.

reload swallows CancellationError and turns other errors into .failed. Either way it returns normally, so read = key runs even though nothing was loaded for key. Example: filter A is loaded, then you switch to B and leave the screen (or B fails) before B's first page arrives. read is now B while items are still A's. Coming back, key == read holds, so B's first page is laid over A's tail and the list mixes two filters. The same happens after a failed load for a new account.

Fix: set read inside reload, only after items are assigned. Then it is always what items are of.

I can't build ios/, so I read the Swift by eye and haven't run it.

ios/Knotless/Views/InboxView.swiftline 33Outdated
// Shown again, it keeps the pages read of it. Another filter or account starts anew.
let key = ReloadKey(filter: filter, did: account.person?.did)
await reload(keepingPages: key == read)
read = key
review.knotless.dev

This runs after cancellation and after a failed load too, so read can name a key whose items were never loaded. Set it in reload, next to items = ..., so it only follows a successful read.

Approved

This round fixes what I asked for. reload now returns whether it read, and read = key is set only when it did. A cancelled load, including a URLError.cancelled, or a failed load no longer marks read as a key that items aren't of. Going from filter A to B and back to A before B arrives now keeps A's pages, and B's first page is never laid over A's tail. Dropping a late more() page when the filter changed also looks right.

One minor gap, which I don't ask you to fix here: more() guards on the filter but not on the account. A page still in flight across an account switch could be appended to the new account's list. It's unlikely, because the signed-in account's .task restarts and replaces items first.

I read the Swift by eye and haven't built or run it.

Merged as d50105d