Favorites are stored regardless of language but the card click was navigating to /browse?post=<id>&single=1 in the current UI language. When the user switched languages (e.g. zh→en) and tapped a zh-only favorite, the /browse stream couldn't find the post in its English view and showed "Couldn't find this post in the current view".
Make Favorites navigate via /resource/<id> instead. PostRedirect already tries the current UI language first, then falls back to the post's source language and shows a toast. Renamed PopularRankRow's seldom-used `singlePostLink` to `linkToResource` to make the intent obvious; Favorites passes the new prop.
After dropping the fixed width, the language pill still got truncated because its flex parent could shrink it below content size. Add `shrink-0` to the wrapper and switch the trigger button from `w-full` to `w-auto` with `whitespace-nowrap`, so the button always sizes to fit the longest label like "Bahasa Indonesia".
The desktop language pill had a fixed width (md:w-36 lg:w-40) that truncated long labels like "Bahasa Indonesia". Drop the fixed width so the button sizes to content, remove the truncate on the label, and let the dropdown menu match parent width with a sensible min-width. Same `truncate` was hiding the full label inside the mobile drawer dropdown — bumped its width to fit too.
Drop the visible URL box from the modal — only the Copy link button remains. Copy still writes the absolute file download URL to the clipboard so the user can paste it into Chrome/Safari to trigger the download.
On compact cards the user cannot see which file is attached, especially for multi-attachment posts. Make the small download button on PopularRankRow, RecommendedCard, and LatestUpdateCard navigate to the post detail page instead of triggering an immediate download, so the user lands in the full post and picks the exact attachment to download.
Stop exposing the internal /apnew/api/.../download URL in the guide. The dialog no longer renders the file URL or copies it to the clipboard; instead the user copies the current page link (window.location.href) and opens it in their system browser, then taps download again — which uses the real fetch+blob path. Updated step copy and intro in all 7 locales to match the new flow.
Production builds the frontend with VITE_API_URL="" so attachmentDownloadUrl() returns a relative path like /apnew/api/.../download. Pasting that into Safari from another origin fails. Convert the URL to an absolute one (window.location.origin + path) before showing it in the in-app browser guide, and update the modal text in all 7 locales to make clear the copied link is the direct file download URL that, when opened in the system browser, triggers the download automatically.
- Detect in-app WebViews (WeChat / TokenPocket / imToken / Telegram / iOS WKWebView, etc.) and show a guide modal asking the user to open the link in their system browser, with a copy-link action.
- For normal browsers, fetch the attachment as a Blob and trigger download from a same-origin object URL so the file always lands in the user's Downloads folder with the original filename, even when the browser would otherwise inline-preview the response.
- Fall back to the anchor download for files larger than 50MB (avoid loading them entirely into memory) or when fetch fails.
- Pass `sizeBytes` from known call sites so the threshold actually applies.
- Add localized strings for the guide modal in all 7 locales.
See .unipi/docs/debug/2026-06-05-in-app-browser-download-debug.md.
Disconnected state (Figma 4476-15287): bump the compact CTA to the
spec'd dimensions — h-12 (48px), text-[15px], font-medium — so the
yellow 链接钱包 button matches the Figma pill exactly while leaving
the desktop header pill (compact=false) untouched.
Connected state (Figma 4476-15669/16024): rebuild the compact branch as
the spec'd info card + danger button:
- A transparent 登录地址 label (text-[13px] font-bold #E5E5E5) with an
8px gap to the full 0x… address, which uses Figma's character-level
styling: first 5 and last 5 chars rendered bold white, middle 32
chars rendered #A8A9AE / font-medium, replicating Figma's
characterStyleOverrides.
- A full-width 48px disconnect pill at bg-[#2A1B20] with #F36161 text
and the LogOut glyph on the right at 15px font-medium.
Add a new walletLoginAddress i18n key across all 7 locales (en, zh-CN,
ja, ko, vi, id, ms) for the new 登录地址 label.
Both the categories page grid and the home categories carousel now
filter out the 'general' slug before sorting. The full backend list is
still kept in state so posts that resolve their label via the
categories lookup don't lose their name. Backend will follow up by
dropping the slug from /api/categories; this client-side filter then
becomes a defensive no-op.
Rename the localized URL prefixes from full English names to short
ISO-style codes:
/chinese -> /cn
/japanese -> /ja
/korean -> /ko
/vietnamese -> /vi
/indonesian -> /id
/malay -> /ms
Add legacyLanguageRedirects mapping and a LegacyLangRedirect component
in App.tsx so links shared on WeChat (and elsewhere) that still use the
long-form paths keep landing on the right page. The redirect preserves
the sub-path, query string, and hash, e.g.
/malay/browse?post=42#x -> /ms/browse?post=42#x
Also refresh doc-comment examples in i18n.tsx, FigmaBanner.tsx,
PublicLayout.tsx, and useLocalizedPath.ts so future readers see the new
prefixes.
Drawer top: drop nav pt-2 so the first menu item sits flush with the
drawer top edge per Figma frame 173 (first item y matches drawer y).
Drawer bottom: raise CTA bottom inset from 20px to 34px so the gap
between the 链接钱包 button and the drawer's bottom edge matches the
Figma measurement (Btn Primary bottom y=25041 vs drawer bottom y=25075).
The safe-area-inset env() still wins on devices with a larger inset.
Figma 4164-5336 frame 173 specifies the drawer body as #14131A at 90%
opacity with a 24px background blur. Switch bg-ark-bg to bg-ark-bg/90
backdrop-blur-xl so the underlying page bleeds through softly rather
than being fully masked.
The 链接钱包 CTA was using the lucide outline Wallet icon. Replace it
with a local WalletIcon component built from the exact Figma path
(filled body, currentColor fill) so the icon paints in dark on the
yellow CTA, matching Figma's #08070C fill via the button's text-black
utility.