The WalletConnect relay (wss://relay.walletconnect.org) is unreliable/blocked
in mainland China. Every wallet flow (desktop QR, mobile deeplink, mobile QR)
depends on it, so Chinese users see the login button hang forever and the
QR code never appears. When RainbowKit's render fails, the whole site goes
white because nothing catches the error.
Changes:
- Add WalletStackErrorBoundary around <RainbowWalletProvider> + modal so
RainbowKit init failures no longer blank the entire app.
- Hoist <WalletProvider> above the boundary; it only depends on the injected
provider, so useWallet keeps working for header / favorites / etc. even
when the WC stack is dead.
- On mobile, the TP/imToken 'Open Wallet App' button now navigates directly
to tpdapp://open / imtokenv2://navigate/DappView with an ?autoLogin=<kind>
query, pulling the site into the wallet's in-app browser without ever
touching the WC relay. MetaMask still uses the WC path (no equivalent
deeplink).
- Add AutoInjectedLogin: when the page loads with ?autoLogin=<kind>, wait
up to 8s for window.ethereum, then connectInjectedWallet + completeLogin.
Strips the param via history.replaceState to avoid re-firing on reload.
- Guard against the in-app-browser disconnect/reconnect case: if
getInjectedWallet(kind) is already truthy, skip the deeplink and let
useWalletConnectLogin's deeplink mode take the injected fast path
(avoids TP trying to open TP recursively).
Image bubbles previously used the raw filename as alt text, so a failed
asset load exposed the file name in the broken-image box. Add a reusable
BubbleImage that renders an empty alt and falls back to a neutral
placeholder (ImageOff icon) on error; use it in the album, image, and
image-with-text bubbles, and drop the filename from their aria-labels.
Also add a global ScrollToTop that resets the window on route change so
desktop navigation matches mobile (e.g. clicking a category card no
longer lands at the bottom of the new page). Hash navigations are skipped
so #post-<id> deep-link scrolling still works.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Recommended cards already routed to /browse#post-<id>, but the stream had
no logic to scroll to the target bubble — and the post might not be paged
in yet. MessageStream now resolves the #post-<id> hash, auto-loads more
pages until the bubble renders, scrolls to it, and gives it a brief gold
highlight. Bubbles get scroll-mt so they clear the sticky header.
Also adds a global floating back-to-top button (BackToTop) mounted in
PublicLayout, shown after scrolling past 400px.
Bundles related staging UI work already present in the working tree.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>