Skip to content

Swipe between a profile's commits and replies under a header that scrolls away - #11

Merged
simonhamp merged 1 commit into
mainfrom
feat/profile-pager
Oct 18, 2026
Merged

simonhamp merged 1 commit into
mainfrom
feat/profile-pager

Conversation

@simonhamp

@simonhamp simonhamp commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

A profile's Commits and Replies now swipe, with the pager's own tabs underlined in your lane colour, as on the Log and Notifications. The header (avatar, facts, counts, activity, streaks and achievements) scrolls up with the tab you're on, the tabs pin under the nav bar once it has gone, and the pages swipe under the tabs while the header stays still. Your own profile and someone else's work the same.

This needs NativePHP/mobile-ui#139, which adds a header slot and an overlay slot to the pager. It's merged into combined/dev-null-app and the lock points at it (ca9b7ef).

What changed

  • Profile follows the Log's pattern: showPage and backToTop from the pager, a list key per tab, and only the tab you're on is live. The other tab shows the first five commits kept for it, so the frame stays small (about 1,550 nodes with 30 commits on the live tab). Your own profile still opens on the tab you last had (ShownTabs).
  • The header moved to partials/profile-header and goes in <native:pager-header>. Each tab's page is partials/profile-page.
  • The new commits pill goes in <native:pager-overlay>, which hangs it just under the tabs wherever the header has scrolled them. On the profile that replaces Put the new commits pill under the composer, and pin it when you scroll #9's sticky header between the tabs and the commits; the Log keeps the sticky header.
  • Profile now sends every frame in full, like the Log. Without it, tapping the tab you're on did nothing on the phone: only the list's key changes, and EDGE's subtree reuse ignores keys.
  • partials/page-tabs is gone, since nothing uses it now.

What I tried

Header rows in each page's list, with PHP tabs or the pager's tabs above, would have slid the header sideways with every swipe, and the tabs couldn't pin. Laying the header over the pages left drags on it scrolling nothing. So the mobile-ui change has each page's list draw the header and pin the tabs, holds them still during a swipe, and keeps the two lists level while any of the header shows. Details are in NativePHP/mobile-ui#139.

What to check

Known rough edges

On a real iPhone it can be a little glitchy at times. Simon tested it on his phone and is happy to ship it as it is. These are the spots I know of or suspect, for anyone who wants to pick them up.

Seen in the simulator:

  • A sideways swipe that starts on the achievements chips scrolls the chips, not the tabs.
  • The pill doesn't move during a swipe. It hangs over the other tab until the swipe settles, then hides.
  • A swipe made while the profile is still opening sometimes doesn't change tab.
  • The tab you leave starts again at its top when you come back, as on the Log.
  • A short tab has blank space at its end, so the header can still scroll away above it.

Suspected, since the simulator looked fine:

  • The header is held still by moving it against the pager's position every frame. On a device it may shimmer sideways for a frame during a fast swipe.
  • The other tab is scrolled to the same height through its UIKit scroll view. A list that was only just made, or rows whose heights are still estimates, can land a little off. Then the two halves of the header don't quite meet mid-swipe, or the header jumps when the swipe settles.
  • The pill is placed from where the tabs were last measured, so it can trail them by a frame when you scroll fast.
  • The profile now sends every frame in full. A refresh that lands mid-scroll may cause a hitch.
  • VoiceOver reads the header on both tabs.

The pager side of these is in NativePHP/mobile-ui#139.

Verified

php artisan test (775 passed) and Pint. On an iPhone 17 Pro simulator (iOS 26.2) against the local API: swipe both ways, tap both tabs, tap the tab you're on to go back to the top, scroll the header part way and swipe (the other tab is level), scroll it away and swipe to a short tab, pull to refresh, the pill under the tabs and following them up, dark mode, my own profile and someone else's. After the rebase, on a fresh simulator: swipes, tab taps, reselect, the header scrolled away, the badge shelf opening the achievements sheet, the followers count opening the list (the shared API site has no followers endpoint, so the list itself 404s there), the ⋯ menu on someone else's profile, and deleting my own commit from my profile. Android was checked with a test screen in NativePHP/mobile-ui#139.

Header at the top Tabs pinned Mid-swipe, header still
Someone else's Pill under the tabs Pill with the tabs pinned

Recording: ios-profile-pager.mp4

🤖 Generated with Claude Code

…olls away

The profile's Commits and Replies are now pages of a pager, with the tabs
the pager draws, as on the Log and Notifications, underlined in your lane
colour. The header (avatar, facts, counts, activity, streaks, achievements)
goes in the pager's new header slot from NativePHP/mobile-ui#139. It scrolls
up with the tab you're on, the tabs pin under the nav bar once it has gone,
and the pages swipe under the tabs while the header stays put. Each tab has
its own list, cache and pull to refresh.

Only the tab you're on is live. The other shows the first five commits kept
for it, so the frame stays small. The tab you leave starts again at the top
of a fresh list, and tapping the tab you're on takes it back to the top.
Your own profile still opens on the tab you last had.

The new commits pill hangs under the tabs wherever they are, in the pager's
overlay slot, instead of the sticky header between the tabs and the commits.
The Log keeps its sticky header. The profile now sends every frame in full,
like the Log: a reselect only changes a list's key, and EDGE's subtree reuse
never sent it.

The PHP-drawn page tabs partial is gone, since nothing uses it now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@simonhamp
simonhamp merged commit 5758923 into main Oct 18, 2026
1 check passed
@simonhamp
simonhamp deleted the feat/profile-pager branch October 19, 2026 09:25
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.

1 participant