Commit Graph

12 Commits

Author SHA1 Message Date
k 90cccd422b style(feed): compact, recessed layout for off-topic posts
Off-topic posts are the bulk of the Trump feed but carry no signal. Before,
each rendered as a full-size card identical to real signals, making the feed
long and sparse and burying the ~15 actionable posts.

Now noise posts (.post-row.noise) render as a compact, recessed two-column
row: sunk background, 22px dimmed avatar, no aside column, tight padding,
smaller text. The lone floating 'SKIPPED' tag is gone (the meta-line
'off-topic · not crypto' chip already conveys it). Real signal cards are
unchanged — they now visually pop against the muted noise rows.

Verified in the browser: ~6 noise rows per screen (was ~3 cards), and the
'Hide off-topic' toggle collapses to a clean signal-only stream.

tsc clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 03:32:24 +08:00
k c8dd7176fa feat(ui): one-click 'Hide off-topic' toggle on the Trump feed
Lets the user collapse every post the AI judged off-topic (not crypto-related,
never scored) so the feed shows only real signals.

- PostCards exports isAiScored(post) as the single source of truth for what
  counts as noise — the card de-emphasis and the list filter now share it, so
  they can never disagree.
- TrumpPageClient: 'Hide off-topic (N)' toggle in the filter row (only shown
  when N>0), with live noise count. Resets to page 1 on toggle.

tsc + build clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 03:23:03 +08:00
k 3f35a3fba2 feat(ui): visually de-emphasise off-topic Trump posts in the feed
Follow-up to fe88acb. Noise posts (not crypto-relevant, never AI-scored) now
read as 'skip me' at a glance in the list — no need to open them:

- sentiment chip → muted 'off-topic · not crypto' tag (was a colored chip)
- post text → dimmer (ink-4) + shorter preview (90 vs 180 chars)
- aside → single muted 'SKIPPED' tag instead of HOLD pill + empty AI metric

Scored posts (real crypto signals) are visually unchanged — full signal pill,
target chip, impact, and AI confidence.

tsc + build clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 03:19:31 +08:00
k fe88acb5a0 fix(ui): don't show misleading 0% AI bar on off-topic Trump posts
Most Trump posts aren't crypto-related, so the entry filter / AI marks them
relevant=false with ai_confidence=0 and no reasoning (never AI-scored). The
post card still rendered 'AI confidence 0%' with an empty progress bar, which
reads as 'AI looked and was 0% confident' rather than the truth: 'skipped as
not crypto-relevant'.

Added an aiScored guard (ai_confidence > 0 || ai_reasoning present):
- collapsed row: shows AI '—' instead of '0%' for unscored posts
- expanded detail: shows 'Not crypto-relevant — skipped AI scoring' instead
  of an empty 0% confidence bar

Scored posts (the ~80 with confidence>0 in test data, and all real signals
once live) are unchanged — full bar + reasoning shown.

tsc + build clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 03:16:35 +08:00
k d50c05b120 fix: pre-launch UI hardening + KOL reduce-action type, proxy IP relay, settings redesign
Frontend half of the pre-launch audit campaign:

- types/index.ts + kol/KolPageClient.tsx: add missing 'reduce' KolAction
  (backend emits it; frontend lacked the type + color/label maps → undefined
  styling). Adds ACTION_COLOR/actionLabel/postActionLabel entries.
- proxy/[...path]/route.ts: relay real client IP (x-forwarded-for / x-real-ip)
  so the backend rate limiter buckets per-user instead of per-Next-server (BUG-02).
- Settings/BotConfigPanel redesign, paper-mode clarity, copy cleanup.
- Assorted page/display fixes, loading states, Pagination component.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 11:57:43 +08:00
k 02b2aebbb7 fix(chart): MACRO BOTTOM marker now follows candles on pan / zoom / resize
User report: the dashed vertical line + "MACRO BOTTOM" label could be
visually "dragged" — it wasn't actually draggable, but it stayed glued
to a fixed pixel column on screen while the candles slid out from under
it on pan, so the label ended up pointing at unrelated candles.

Root cause: the line + label are absolutely-positioned DOM nodes (the
lightweight-charts library has no first-class vertical-marker primitive).
The data effect set their `left` ONCE via timeScale.timeToCoordinate()
and then never updated again. Every user interaction that changes the
visible range — pan, wheel zoom, programmatic setVisibleRange, window
resize — invalidates that pixel coordinate.

Fix:
  - Store the signal's bucketTime + label text in refs.
  - Hoist the "project bucketTime → pixel X" logic into a single
    `reposition()` fn captured in repositionMacroRef.
  - Subscribe to `timeScale().subscribeVisibleTimeRangeChange(reposition)`
    so it fires on every pan / zoom / data update.
  - Wire it into the ResizeObserver too (width change ⇒ new pixel space).
  - Re-run from the data effect whenever the signal changes.
  - Hide (opacity: 0) instead of clamping when the signal candle scrolls
    outside the visible range — a clamped label glued to the chart edge
    is actively misleading.
  - Drop `transition: left 160ms` on both nodes — that transition fires
    on every pan frame and makes the marker LAG behind the candles,
    reproducing the original visual bug for fast pans.

Verified via DOM scripting:
  pan right ⇒ label_left 744px → 344px (follows candles ✓)
  big right-pan past signal ⇒ opacity 1 → 0 (hides cleanly ✓)
  zoom out ⇒ opacity 0 → 1, label re-projects to new pixel space ✓

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 11:34:26 +08:00
k d01adc4790 style(dashboard): unify Macro composite into one card + dark-mode fix
for Performance accent

User flagged the macro index box on the overview page as feeling
disjointed. Reshaped it from three stacked elements (band → track →
scale) into a single bordered card so it reads as ONE component.

  - JSX: wrap the three pieces in <div className="overview-macro-card">
  - CSS: new .overview-macro-card with tone-coloured rim (bull/bear/neutral)
  - Solid neutral-gray filled needle (was a hollow ring — looked like a
    placeholder); tone-coloured background + white inner ring + double
    shadow so it stands out on any gradient position
  - Removed the .overview-score-fill overlay — the gradient already
    encodes the spectrum; layering an opaque fill obscured it near 0
  - Thinner track (14px vs 22px), tighter scale labels, smaller pill
  - Added "TODAY · 8 INDICATORS" stamp next to the title — gives users
    a quick anchor of what they're looking at + freshness

Plus: dark-mode override for .overview-stat-card.accent (the Performance
card). It was using a cream gradient that floated as a glaring
out-of-theme block on dark mode. Mirrored the existing .kpi.accent dark
treatment so it stays visually grouped with the rest of the dashboard.

Also includes the in-flight overview rewrite from the other AI tool
(legacy /btc redirect to /macro, middleware.ts replacing proxy.ts for
Next.js routing, refactored several dashboard panels). TypeScript clean,
production build passes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 11:25:59 +08:00
k d72323b1c6 Production polish: i18n shelved, PWA icons, SEO/GEO cleanup, UX fixes
Big-picture changes since 01be8e7:

New routes — /trump /btc /kol /trades /analytics /archive plus four
SEO landing pages (/methodology /glossary /case-studies /contact),
all served under /[locale]. Each has dedicated metadata + JSON-LD.

KOL page (new) — DigestWidget + OnchainWidget + TalkVsTradesWidget,
filter by handle/ticker, click-through to per-post detail with the
original AI-extracted ticker/conviction/quote.

BTC page (new) — tabbed: macro-bottom (AHR999 + 200WMA + Pi Cycle)
and funding-rate reversal, with live sparkline + threshold bands.

Telegram card on Settings — wallet-link code generation, status,
disconnect. Preferences moved into the bot itself (/trump /btc etc.)
so the card stays minimal.

SignalMonitor (new) — ETH/LINK Bollinger breakout monitor in its own
component, shares the singleton WsProvider so no second WS opens.

WS singleton refactor (lib/wsContext) — shared WsProvider + useWsSubscribe
hook. Cleanup now actively closes the socket on unmount; previously the
local `ws` couldn't be reached from cleanup and leaked one connection
per StrictMode remount.

OpenPositions polling no longer pops MetaMask in the background —
splits into load('first') for user-initiated and load('poll') that
uses getCachedViewEnvelope without signing.

i18n shelved — proxy.ts (Next 16 middleware rename) wires next-intl
but only Navbar + layout footer have translations. Rest of UI used
isZh ternary scattered across 28 files. All `const isZh = locale === 'zh'`
flipped to `const isZh = false` so every site renders English; Chinese
branches kept as dead code so revival is one regex away.
LanguageSwitch hidden but file kept. zh-CN hreflang removed from
metadata + sitemap to avoid duplicate-content penalties.

Wallet error handling — lib/walletError.ts: isUserRejection walks EIP-1193
code 4001 + .cause chain; previous string-match for "reject"/"denied"
broke for users running MetaMask in non-English UIs. 12 call sites
migrated across 5 components.

PWA icons — app/icon.tsx + app/apple-icon.tsx render the brand "α" via
Next's ImageResponse so no static PNG asset is required. manifest.ts
references /icon and /apple-icon dynamic routes.

OG image + sitemap + robots — dynamic 1200×630 OG card; robots blocks
both /en/settings and /zh/settings; sitemap only emits /en routes;
JSON-LD covers SoftwareApplication + Organization + 10-Q FAQPage.

Landing page polish — Launch Dashboard button stripped of magnetic
hover + shimmer + lift + glow expansion (multiple users found it busy);
hero scramble alphabet swapped to alphanumeric (was block characters);
"15 KOL feeds" copy updated to 19 in 5 places.

PostCards source icons — new entries for btc_bottom_reversal,
funding_reversal, kol_divergence so they no longer fall through to
the generic "first letter" fallback.

Archive page filter — excludes funding_reversal + kol_divergence
(previously only excluded truth + btc_bottom_reversal so new live
signals leaked into the legacy archive).

Cache + skeleton loading — lib/cache.ts SWR module with per-key TTL,
applied across the major pages so navigation feels instant.

SignConfirmSheet — 4 hardcoded Chinese strings translated to English
(English users were seeing zh-only "需要钱包签名" etc).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 00:53:27 +08:00
k 01be8e790b fix: dashboard live price + 24h % + chart tick + null-pnl safety
Five bugs in the same blast radius (places we render a price/percent).

DashboardClient.tsx
  • Hero price read lastCandle.close (REST candle, frozen until user
    changes asset/tf). WebSocket livePrices was set but never read.
    Now: livePrice ?? lastCandle.close.
  • "+21.84% · 4H" was (last_close - first_open) / first_open over
    the entire candle window. limit=200 + tf=4H = 33 days shown as
    "4H". Find candle closest to now-24h, label "24h" consistently.

ChartPanel.tsx
  • Chart only re-rendered on candles prop change. Live WS ticks
    ignored. Added useEffect calling series.update() with
    livePrices[asset] on every tick.

analytics/page.tsx
  • reduce(sum + trade.pnl_usd) when pnl_usd is null → NaN poison.
  • Math.max/min over null cast to 0 → bogus "best/worst trade".
  • Win-rate denominator counted null-pnl trades as losses.
  • calcDrawdownPct had the same null poisoning.
  Fix: gate aggregations on priced subset only.

trades/page.tsx
  • ROI could divide by 0/null; entry/exit crashed on null.toLocaleString().
  Added guards.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 19:57:28 +08:00
k 040e1df685 feat: revamp dashboard, trades, and add landing/legal pages
- Major UI updates across dashboard, analytics, posts, trades, settings
- New landing page, robots/sitemap, contact/privacy/terms pages
- Updated globals.css with extensive styling and new landing.css
- Refactor signedRequest, realtime data hook, and dashboard store

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-25 16:04:57 +08:00
k 83e5892ddf done 2026-04-21 19:32:53 +08:00
k 1747fc489f first day of vibe coding 2026-04-20 22:11:18 +08:00