Commit Graph

363 Commits

Author SHA1 Message Date
TerryM
2a702f4e12 feat(header): make nav-vs-burger decision per-language by measuring fit
Some checks failed
Deploy to Frontend Servers / deploy (push) Failing after 38s
Each translation gives the nav a different natural width: Malay's 6 labels
total ~594px while Chinese is ~508px. With a fixed Tailwind breakpoint
(`xl:flex`) some languages either clipped at viewports where the nav
technically didn't fit, or collapsed too early to a burger on wide screens.

Drive the toggle from runtime measurement instead:

- Always render a hidden ghost nav (`absolute invisible`) so the browser
  can report the inline nav's true scrollWidth for the active locale,
  even while we're showing the burger.
- Add refs on the header row, brand block, and right-side actions; a
  useLayoutEffect + ResizeObserver compares ghost.scrollWidth against
  (rowWidth - brandWidth - rightWidth - 2*rowGap).
- 60px hysteresis on burger -> inline so the layout doesn't oscillate
  when the favorites label / burger button swap changes right-side width.
- Drop the now-unused `xl:flex`, `xl:hidden`, `xl:flex-none`,
  `xl:inline` classes from the affected elements.
- Close the burger drawer automatically when the row grows wide enough
  to show the inline nav again, so the menu doesn't get stuck without
  a toggle.

Verified via puppeteer/eval across en / zh-CN / zh-TW / ms / ru / de at
800-2000px: each language switches to burger at its own threshold and
the inline nav never overflows or clips its labels.
2026-06-08 01:01:33 +08:00
TerryM
6aaa9573e7 ci(deploy): wipe every non-current act workspace before npm ci
Some checks failed
Deploy to Frontend Servers / deploy (push) Failing after 2s
The previous run still hit ENOSPC, this time during `npm ci` while
extracting node_modules. The earlier cleanup left the just-failed act
workspace on disk (mtime < 10min threshold), and its half-extracted
node_modules took the runner past the limit before `npm ci` finished.

- Drop the mtime threshold for act workspaces; instead detect the
  currently-running job's directory and rm -rf every sibling. The
  current job is preserved by path comparison so we never delete files
  the running step needs.
- Blow away ~/.npm/_cacache, ~/.npm/_logs, ~/.cache/setup-node entirely.
  `npm ci` re-populates what it needs and the cache is the easiest GB
  to reclaim on a tight runner.
- Tighten actions-runner workspace retention from 24h to 30min.
- Drop the docker prune --filter; use `docker system prune -af --volumes`
  to reclaim builder cache and volumes too.
- Hard-fail with a clear error if <3.5GB free after cleanup, instead of
  letting `npm ci` half-write an unusable node_modules and failing
  obscurely. Codebase needs ~3GB for hoisted deps.
2026-06-08 00:39:31 +08:00
TerryM
9b6539ff71 feat(category): add branded icons for contract-address and data-records
Some checks failed
Deploy to Frontend Servers / deploy (push) Failing after 41s
Backend zh-CN /api/categories now returns two new categories:
  id=17 slug=contract-address  (合约地址)
  id=18 slug=data-records      (数据收录)

Export the matching gold-tone PNGs from Figma and wire them into
slugToAsset so CategoryIcon serves the branded artwork instead of
falling back to the lucide iconKey (folder / play). en locale still
returns 13 categories, so English users will pick this up once the
backend ships translations for the two new entries.
2026-06-08 00:35:27 +08:00
TerryM
8c1dd8189e ci(deploy): make runner cleanup more aggressive to prevent ENOSPC
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 1m0s
A previous deploy failed at the vite chunk-writing stage with
"ENOSPC: no space left on device". The cleanup step ran at the start
of the job but left enough stale data behind that the runner filled up
before `npm run build` could finish.

- Drop the act workspace retention from 60min to 10min. Closely-spaced
  pushes used to keep multiple stale jobs around; 10min still preserves
  any currently-running job because its mtime keeps advancing.
- Drop _work / setup-node / npm cacache retention from 24h to 60min.
- Drop the `until=24h` filter on docker prune so dangling images,
  containers, and builder cache get reclaimed every run.
- Add a second "Ensure free space before build" guard right before the
  Build step. If <3GB is free, aggressively prune act caches, npm
  cacache, and docker volumes before vite starts writing chunks.
2026-06-07 19:59:18 +08:00
TerryM
915d88b3ac feat(video): show filled white track left of the volume slider thumb
Some checks failed
Deploy to Frontend Servers / deploy (push) Failing after 58s
Add a hard-stop linear-gradient background to the volume <input> so the
portion of the track left of the thumb is solid white while the right
portion stays at the previous translucent white. The user can now see
at a glance how loud the level is set, instead of only inferring it
from the thumb position.
2026-06-07 19:56:17 +08:00
TerryM
f97e367dde fix(header): expand public header full-width and stop nav text clipping
Some checks failed
Deploy to Frontend Servers / deploy (push) Failing after 58s
- Drop max-w-[1280px] on the desktop header inner row so the header
  expands with wider viewports instead of staying capped.
- Move the inline nav / burger toggle from min-[1000px] to xl (1280px)
  so the nav only appears when all six items have enough room. The old
  threshold relied on overflow-x-auto, which clipped the first/last
  characters ("ll assets", "Popula").
- Remove the now-unused .header-nav-scroll CSS along with the scroll
  fallback wiring on the nav element.

Mid-width viewports (1000–1280px) now show the burger drawer instead
of a horizontally-scrolled nav. main content stays at max-w-[1280px]
on purpose.
2026-06-07 19:53:58 +08:00
TerryM
9821f03929 feat(video): add inline volume control to MessageInlineVideo
- Add mute toggle button (Volume2/VolumeX icons) to the custom control bar.
- Add an always-visible inline straight-line volume slider on desktop;
  mobile keeps mute toggle only and relies on system volume keys.
- Slider at 0 auto-mutes; unmuting from zero restores volume to 1.
- Sync isMuted/volume state via the video volumechange event.

Verified in browser at /browse?type=video: drag slider updates
video.volume, mute toggle preserves volume across on/off.
2026-06-07 19:53:49 +08:00
TerryM
a4cb4f496d fix: show BSC wallet prompt for TokenPocket
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 1m0s
2026-06-06 01:27:28 +08:00
TerryM
24e22a3f25 fix: improve imToken wallet error prompts
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 1m8s
2026-06-06 01:24:27 +08:00
TerryM
2b5ec54896 fix: fallback when imToken returns empty accounts
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 59s
2026-06-06 01:00:44 +08:00
TerryM
fe8dcee9a1 fix: auto-login imToken in-app browser without query
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 1m0s
2026-06-06 00:52:19 +08:00
TerryM
5408a86cc9 docs: record imToken production login fix 2026-06-06 00:49:26 +08:00
TerryM
9c4b8a4df7 fix: support imToken in-app browser login
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 1m2s
2026-06-06 00:45:24 +08:00
cbaa06f77d Merge pull request 'terry-staging' (#16) from terry-staging into main
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 1m0s
Reviewed-on: #16
2026-06-05 16:33:11 +00:00
85a24ef982 Merge pull request 'terry-wallet-login' (#15) from terry-wallet-login into terry-staging
Reviewed-on: #15
2026-06-05 16:32:43 +00:00
TerryM
ae84e73736 fix: keep popular card hover ring inset
All checks were successful
Deploy Staging (terry-wallet-login) / deploy (push) Successful in 1m5s
2026-06-06 00:30:18 +08:00
TerryM
bd48fded30 fix: add favorites to public navigation
All checks were successful
Deploy Staging (terry-wallet-login) / deploy (push) Successful in 1m10s
2026-06-06 00:25:12 +08:00
TerryM
fd1a3f4b3e fix: favorites click opens isolated single-post view
When `linkToResource` is set, PopularRankRow now navigates to /resource/<id>?single=1 and PostRedirect propagates the `single=1` flag to the /browse?post=... target. MessageStream already supports singlePostMode (no filter bar, no sentinel, only the target post in the list), so favorites cards open the post in isolation instead of dropping the user into the surrounding stream.
2026-06-06 00:23:46 +08:00
TerryM
37e6e4901f fix: route favorites cards through /resource so they survive language switch
All checks were successful
Deploy Staging (terry-wallet-login) / deploy (push) Successful in 1m18s
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.
2026-06-06 00:04:19 +08:00
TerryM
e80330b13c fix: stop language picker shrinking in flex header
All checks were successful
Deploy Staging (terry-wallet-login) / deploy (push) Successful in 1m5s
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".
2026-06-05 21:39:05 +08:00
TerryM
b38b28f175 fix: show full language name in the picker
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.
2026-06-05 21:31:43 +08:00
TerryM
ec8ef5b774 fix: hide URL preview in in-app download guide
All checks were successful
Deploy Staging (terry-wallet-login) / deploy (push) Successful in 1m8s
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.
2026-06-05 21:17:34 +08:00
TerryM
4c684d75a3 Revert "fix: hide download URL in in-app browser guide"
All checks were successful
Deploy Staging (terry-wallet-login) / deploy (push) Successful in 1m18s
This reverts commit 3275aff121.
2026-06-05 21:09:42 +08:00
TerryM
ee3f2c43eb Revert "fix: download button on cards opens the post page"
This reverts commit 75ccfd78ed.
2026-06-05 21:09:42 +08:00
TerryM
75ccfd78ed fix: download button on cards opens the post page
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.
2026-06-05 19:36:54 +08:00
TerryM
69bef7ee6e fix: hide download button on favorites cards
All checks were successful
Deploy Staging (terry-wallet-login) / deploy (push) Successful in 1m8s
Add `showDownload` prop to PopularRankRow (default true to keep Home popular cards unchanged) and pass `showDownload={false}` from the favorites list.
2026-06-05 19:31:27 +08:00
TerryM
3275aff121 fix: hide download URL in in-app browser guide
All checks were successful
Deploy Staging (terry-wallet-login) / deploy (push) Successful in 1m3s
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.
2026-06-05 19:15:10 +08:00
TerryM
356d8a0207 fix: use absolute URL in in-app download guide
All checks were successful
Deploy Staging (terry-wallet-login) / deploy (push) Successful in 1m10s
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.
2026-06-05 19:10:44 +08:00
TerryM
7a33a62c8f fix: in-app browser download opens file inline
- 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.
2026-06-05 19:06:53 +08:00
TerryM
abfd92b16a fix: avoid unnecessary favorites reloads
All checks were successful
Deploy Staging (terry-wallet-login) / deploy (push) Successful in 1m20s
2026-06-05 18:56:11 +08:00
TerryM
9f5367ae12 fix: show only selected post from favorites 2026-06-05 18:52:25 +08:00
TerryM
2d003c6fef fix: unify home download button sizing 2026-06-05 18:47:04 +08:00
TerryM
908f89ac24 fix: clarify multi-document downloads 2026-06-05 18:45:32 +08:00
TerryM
aae7faf9dd fix: adjust mobile popular card layout 2026-06-05 18:39:32 +08:00
TerryM
4e459aa4be fix: hide rank badges on favorites 2026-06-05 18:25:17 +08:00
TerryM
5d550e0342 fix: show download per document attachment 2026-06-05 18:20:27 +08:00
TerryM
a9ec46e008 fix: refresh favorites after unfavorite 2026-06-05 18:16:33 +08:00
TerryM
486c09dd39 fix: simplify mobile favorite button state 2026-06-05 18:14:48 +08:00
TerryM
292c745549 feat(wallet): redesign drawer wallet states to match Figma 4476-15287/15669
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.
2026-06-05 12:22:41 +08:00
TerryM
e73e25077e Merge branch 'main' into terry-wallet-login
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 34s
2026-06-05 01:08:47 +08:00
TerryM
36ab5be3c2 feat(categories): hide the 综合 (general) category from the UI
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 33s
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.
2026-06-05 01:07:40 +08:00
TerryM
062f630798 fix: dedupe post redirect language fallback
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 30s
2026-06-04 18:07:51 +08:00
TerryM
1fcf2ea46d fix: fall back to original language on post redirect 2026-06-04 17:50:03 +08:00
TerryM
ec98ff5a03 fix: align favorites page with post adapter
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 28s
2026-06-04 17:46:09 +08:00
TerryM
4f6cbbc314 fix: simplify favorites display
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 38s
2026-06-04 17:25:55 +08:00
TerryM
6471559b3b fix: stabilize favorites page loading 2026-06-04 17:15:14 +08:00
TerryM
efaf92c4e4 fix: limit visible toasts 2026-06-04 17:10:11 +08:00
TerryM
01eab88c0f feat: connect wallet favorites to backend 2026-06-04 17:06:29 +08:00
TerryM
fd19ed438e fix: hide imtoken on desktop wallet login
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 30s
2026-06-04 15:29:22 +08:00
TerryM
53dc35e7dc fix: restore mobile wallet login feedback
Some checks failed
Deploy Staging (terry-wallet-login) / deploy (push) Failing after 37s
2026-06-04 15:19:50 +08:00