Skip to content

Reddit Multi Column: rework iOS stacked-flash fix with a navigation veil (v0.3.25)#21

Merged
heyflorin merged 1 commit into
mainfrom
claude/reddit-multi-column-ios-vxnwa1
Jun 27, 2026
Merged

Reddit Multi Column: rework iOS stacked-flash fix with a navigation veil (v0.3.25)#21
heyflorin merged 1 commit into
mainfrom
claude/reddit-multi-column-ios-vxnwa1

Conversation

@heyflorin

Copy link
Copy Markdown
Owner

Why

The previous fix (v0.3.24, #20) caused two problems reported in testing:

  • Left rail / content issues — it tagged each gridded feed with a durable marker and suppressed on it. The marker was never cleared, so when Reddit reused a feed DOM node for a later page the script kept the reused node hidden, blanking content and leaving only the left rail.
  • The flash still happened — the marker approach only ever hid the previous feed, so it never covered a freshly-rendered one (the back-navigation flash).

This reverts that approach and replaces it with something that needs no durable per-node state and makes zero changes to the chrome/sidebar logic (the left-rail handling is byte-for-byte identical to 0.3.23).

What

1. Navigation veil. A class (rmc-veil) is added to <html> synchronously the instant a wide-screen SPA navigation begins (in onNavigate, which runs from the patched pushState/replaceState/popstate). While it's set, a single CSS rule hides every <shreddit-feed>:

html.rmc-veil shreddit-feed { opacity: 0 !important; }
  • Covers both the previous feed lingering through Reddit's slow iOS/iPadOS swap and any feed Reddit renders fresh on the new page — the back-navigation flash that per-node hiding can't catch, since the node doesn't exist yet.
  • Opacity only, so IntersectionObserver lazy-loading (left nav, custom feeds) still runs; !important so it beats the inline opacity the grid manages.
  • Lifted on the first real reveal and unconditionally after MAX_HIDE_MS, so a feed can never get stuck invisible.
  • Gated on viewport width, so phones / portrait tablets — where the script stays fully native — are never veiled.

2. priorFeed memory across a push→replace pair. Reddit opens a post with a pushState immediately followed by a replaceState to the canonical permalink (two path changes in one task). The first nulls parent; the old code then overwrote priorFeed with null on the second and forgot the feed. It's now only refreshed when a feed is actually held, so the post-detail feed stays correctly suppressed past the veil.

No persistent markers, no extra chrome rewriting.

Verification

Headless-browser harness (Playwright + Chromium) serving a mock Reddit SPA, injecting the real userscript, gridding the feed, then driving SPA navigations with the slow iOS-style swap. A MutationObserver (the settled state about to paint) + rAF sampler flag any frame where a feed is effectively visible and un-gridded — path-aware so a genuine profile/search native feed isn't counted.

Scenario 0.3.23 0.3.25
single-nav ok ok
double-nav (push→replace) FLASH 49 ok
double-nav + churn FLASH 87 ok
double-nav + slow swap FLASH 27 ok
triple-nav FLASH 87 ok
post then BACK (fresh feed) FLASH 90 ok — re-grids & reveals
feed→feed (fresh feed) FLASH 2 ok — re-grids & reveals
feed→profile (must stay visible) ok ok — visible native, not blanked
portrait nav (veil must not engage) n/a ok — veil never engages

The back-navigation case (90 flash frames in 0.3.23) is the one the marker approach never touched and is the most likely source of the "still happens" report. Stable across repeated runs (9/9 green).

🤖 Generated with Claude Code


Generated by Claude Code

…eil (v0.3.25)

Reverts the 0.3.24 durable-marker approach and replaces it. The marker was
never cleared, so when Reddit reused a feed DOM node for a later page the script
kept the reused node hidden — blanking content and leaving only the left rail.
It also only ever hid the PREVIOUS feed, so it never covered a freshly-rendered
one (the back-navigation flash).

New approach, with no durable per-node state and no chrome changes (the left
rail handling is untouched):

1. Navigation veil: a class on <html> added synchronously the instant a
   wide-screen SPA navigation begins (in onNavigate). While set, one CSS rule
   hides every <shreddit-feed> (opacity only, so IntersectionObserver lazy-load
   still runs; !important so it beats the inline opacity the grid manages). This
   covers both the previous feed lingering through Reddit's slow iOS/iPadOS swap
   AND any feed Reddit renders fresh on the new page (the back-nav flash a
   per-node hide can't catch). Lifted on the first real reveal and
   unconditionally after MAX_HIDE_MS, so a feed can never get stuck invisible;
   gated on viewport width so phones / portrait tablets stay fully native.

2. priorFeed memory across a push->replace pair: Reddit opens a post with a
   pushState immediately followed by a replaceState to the canonical permalink
   (two path changes in one task). The first nulls `parent`; the old code then
   overwrote priorFeed with null on the second and forgot the feed. priorFeed is
   now only refreshed when a feed is actually held, so the post-detail feed stays
   correctly suppressed past the veil.

Verified in a headless-browser harness modelling the slow swap. Against 0.3.23,
forward double/triple-nav AND "post then BACK with a fresh feed" all flashed
every card at full opacity (the back case 90 frames); after this change every
scenario flashes zero frames, back-navigation and feed-to-feed re-grid and
reveal correctly, a genuine profile/search mixed feed stays visible (not
blanked), and the veil never engages on a narrow/native screen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DLuykcA557aWJq7fCrwToV
@heyflorin heyflorin merged commit 46cee80 into main Jun 27, 2026
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