Skip to content

feat: catch up on the Following log after time away - #1043

Open
ashkesarmaa wants to merge 1 commit into
dev-null-sh:productionfrom
ashkesarmaa:feat/catch-up
Open

ashkesarmaa wants to merge 1 commit into
dev-null-sh:productionfrom
ashkesarmaa:feat/catch-up

Conversation

@ashkesarmaa

@ashkesarmaa ashkesarmaa commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

After a few days away, the Following log greets you with everything newest first. The commits people actually cared about while you were gone are buried somewhere in there, so you either scroll through all of it or miss them.

Now, when you open Following after at least two days away, the log starts with a catch-up:

  • $ git log --since="Tue, Oct 20", then While you were away, 9 commits came in from 7 people you follow. The most starred:
  • The three most starred of them, each linking to its commit, and Show 3 more for up to six.
  • I'm caught up folds it into a single line, caught up · 9 commits since Tue, Oct 20, with Show again and an × to hide the line too.
  • It stays at the top until you're caught up, so opening one of its commits and coming back keeps it there. Once you're caught up, it doesn't come back until the next time you've been away.
  • It only shows when more than three commits came in, leaves out your own commits and replies, respects mutes, blocks and moderation like the log itself, and looks back a week at most.

Changes

  • CatchUpQuery reuses FollowingLogQuery's builder, so visibility, blocks, mutes, pending commits and star counts all come from the same place as the log. It ranks by stars, then recency.
  • LogController adds a lazy catchUp prop for the Following log only. Polls and infinite scroll use partial reloads, so they never compute it.
  • Away since: the log page remembers when the newest Following commit you saw was committed in a following_seen_at cookie, and only moves it forward while there's nothing to catch up on, or once you're caught up. It's a cookie rather than the localStorage entry behind the last-visit marker because the server needs it on the very first load: the catch-up is rendered with the page, so there's no extra request and no layout shift. Like who_to_follow and replies_per_page, it's a plain cookie the page writes, so it's excluded from encryption. ShowLogRequest::followingSeenAt() only accepts the exact timestamp format the page writes.
  • No new column or table. The cookie holds one timestamp of a commit the user could already see. Only their browser keeps it, the server never stores it, and it goes away when the browser's cookies are cleared or after a year.
  • CatchUp component reuses the search dialog's CommitResult row (now exported), the staged RailSegment (with its own view-transition name), Button, ActionTooltip, and the number and day-label helpers. CommitFeed gets a small lead slot that renders above the first commit, on the rail that hangs from the composer.
  • Knowledge base: the logs section explains the catch-up, so Tom can too.

Validation

  • vendor/bin/pest --parallel --ci --coverage --exactly=100.0: 4,046 passed. CatchUpQuery, ShowLogRequest and LogController are at 100%. Locally the overall gate came in under 100% only for files this PR doesn't touch, because this machine runs PHP with zend.assertions=-1, which compiles assert() lines away; with assertions on, as in CI, those files read 100%.
  • vendor/bin/pest --type-coverage --min=100: 100%.
  • bun run test:unit: 128 passed.
  • tests/Feature/Controllers/LogControllerTest.php: 75 passed, including 12 new catch-up tests: ranking and counts, own commits, replies and older commits left out, the two-day gate (exactly two days, one day, never seen, relative or unreadable cookie), the one-week limit, no more than three commits, up to six listed, mutes, blocks and pending commits, other logs and guests, and polls leaving it out.
  • bun run test:lint and bun run test:types: pass. vendor/bin/pint --test: pass. Rector on the changed files: pass.
  • PHPStan: 3 errors, all in files this PR doesn't touch (EmbedKnowledgeBaseCommand.php, StressSeeder.php).
  • Checked in the running app: shows after time away; stays after opening a commit and going back, and after leaving and returning; I'm caught up folds it and moves focus to Show again (and back); the × hides the line; a reload after catching up shows nothing.

Visual evidence

Local data: fictional followed accounts without avatars (so initials show), with seeded commits and stars. "Before" is the same Following log with nothing to catch up on, which is what production shows today.

Before

01-before-desktop-light 01-before-desktop-dark 01-before-phone-light 02-after-phone-dark

After: catch-up at the top of Following

02-after-desktop-light 02-after-desktop-dark 02-after-phone-light 02-after-phone-dark

Show 3 more

03-expanded-desktop-light 03-expanded-desktop-dark 03-expanded-phone-light 03-expanded-phone-dark

I'm caught up

04-caught-up-desktop-light 04-caught-up-desktop-dark 04-caught-up-phone-light 04-caught-up-phone-dark

Layout shift on load: 0 at 390×844 and 820×1180. At 1440×900 it's 0.0035 both with and without the catch-up, so it comes from something already on the page.

Device verification

Chromium emulation at 390×844, 820×1180 and 1440×900 in light and dark, plus desktop Chromium on Ubuntu. Not tested on mobile hardware. The catch-up has no inputs, so the on-screen keyboard doesn't apply. On phones the folded line drops the date to fit, and the full text is in its title.

Independent review

Separate read-only review of base f64c78f against this branch, repeated after its findings were addressed: CODE: PASS, VISUAL: PASS. It led to stricter cookie parsing with tests for relative and unreadable values, the two-day boundary and poll tests, the staged-rail view-transition name, and a comment tying the preview count to the query's gate. The points under Limitations were accepted as intended behavior.

Limitations

  • The signed API (mobile app) doesn't return the catch-up yet; this is the web log only.
  • The cookie belongs to the browser, so two accounts that share one browser share the "seen" time.
  • Being caught up, and Show again, belong to that visit: after a reload you're caught up and the catch-up is gone until you've been away again.

Opening Following after at least two days away now starts with the most
starred commits that people you follow made since the newest one you saw,
with how many came in from how many people. It stays until you're caught
up, then folds into a line you can bring back or hide for that visit.
@devzain15

Copy link
Copy Markdown

@ashkesarmaa This needs a rebase first: show.tsx, ShowLogRequest, bootstrap/app.php, LogControllerTest and KNOWLEDGE_BASE no longer apply after #1099 removed newCommitsCount and #1103/#1108 reworked the reading-position code.

Two things on the design: the following_seen_at cookie is a second "newest seen" marker next to useLastVisit's localStorage one, and they advance on different rules, with the cookie per browser rather than per user, so the "where you left off" line and the catch-up can disagree. Could they share one write? And if the reader never presses "I'm caught up", the cookie never moves and the catch-up returns on every Following visit for a week; if that's intended, worth saying in the knowledge base, since it will feel sticky.

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.

2 participants