Convert two clean detail-view dialogs to the BlurFloat style (floating content on
the blur, plain h6 heading, no glass card) — the "float for large" half of the
plan, applied conservatively: keep each dialog's authored card width so its
width-coupled content (absolute SameLine positions, GetWindowWidth math) is
unchanged, and rely on the footer Close + outside-click for dismissal (the plain
heading drops the title-bar close X, matching the portfolio modal). Auto-height
preserved. A representative pair to GUI-review before rolling the treatment out to
the other large dialogs (or reverting if the card-on-blur reads better).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Grep-verified dead, zero live callers (the live paths all go through
BeginOverlayDialog and already got the blur backdrop):
- App::renderAboutDialog (app.cpp/app.h) — dispatch uses ui::RenderAboutDialog.
- src/ui/windows/import_key_dialog.{h,cpp} (ImportKeyDialog class) — live path is
App::renderImportKeyDialog.
- src/ui/windows/backup_wallet_dialog.{h,cpp} (BackupWalletDialog class) — live
path is App::renderBackupDialog.
Drop the two dead files from CMakeLists. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Flip the positional BeginOverlayDialog overload's default to blurBackdrop=true, so
every app dialog (~43 call sites) now renders its card on the live-blur backdrop
instead of the opaque scrim — matching the Manage-Portfolio look. Cards stay
auto-height (small dialogs stay small = "card for small") and render opaque via
the existing sole-consumer fallback (a translucent glass card would thrash the
single-slot blur cache against the radius-64 backdrop). Nested dialogs (address
book edit) already pass a distinct idSuffix, so their blur windows/capture keys
don't collide. A dialog that wants the old scrim can pass a spec with
blurBackdrop=false. Big visual change — needs a GUI sweep; trivially reverted.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The adversarial review found the ModalRenderGuard lagged the old
PortfolioEditorActive() signal by one extra frame on CLOSE (a possible 1-frame
"opaque panels" flash). Latch the overlay's open flag (already available via
spec.p_open) — "drew this frame AND still open after Esc/Close/outside handling" —
instead of just "drew last frame", so the guard drops and the acrylic re-capture
fire on the same frame the overlay closes, matching the old inline behavior on
both edges.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dogfood the Phase 0 framework: RenderPortfolioEditor now opens via
material::BeginOverlayDialog(BlurFloat) + EndOverlayDialog instead of its own
inline overlay scaffold, and uses the promoted material:: SegmentedControl /
RightAlignX / BeginFadeScrollChild helpers (overlay_scroll.h). Delete the
portfolio's inline backdrop/capture-once state machine + its PfEditState capture
statics + the four local helper copies. App::render's ModalRenderGuard is now
driven by the modal-agnostic AnyBlurOverlayActiveLastFrame() (timing-equivalent),
and LatchBlurOverlayActive() at frame end handles the acrylic re-capture on close.
Framework tweak: floating cards pop the card WindowPadding after BeginChild (so
nested children don't inherit it) and center button labels, keeping the net
style-var count at 2 so EndOverlayDialog is unchanged and GlassCard stays
byte-identical. RenderPortfolioEditor: 357 -> 282 lines. Needs GUI verification
that the portfolio modal is visually/behaviourally unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Refactor BeginOverlayDialog to run through an OverlayDialogSpec + OverlayStyle
(GlassCard vs BlurFloat) with orthogonal flags (blurBackdrop / floatingContent /
plainHeading, fixed vs auto card height). The classic look is now GlassCard with
all flags off; the existing positional overload forwards to it → all ~43 current
dialogs are byte-identical (verified line-by-line). The BlurFloat path — live-blur
backdrop with per-overlay capture-once (frame-gap arming), floating content, plain
h6 heading — is implemented but unused until Phase 1 dogfoods it on the portfolio.
Also replace the unusable open-refcount with a per-frame drawn flag + last-frame
latch that invalidates the acrylic capture on the overlay's close transition.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First step toward unifying all app modals on the Manage-Portfolio visual style.
Add, as shared material:: helpers (additive — no caller yet, no visible change):
- blur-overlay open refcount + 1-frame latch (Push/Pop/AnyBlurOverlayActive[LastFrame],
LatchBlurOverlayActive) so App::render's effect guard can be modal-agnostic;
- capture-frame query (IsCapturingBlurBackdrop) for scroll-fade suppression;
- RightAlignX and SegmentedControl (promoted verbatim from market_tab);
- BeginFadeScrollChild/EndFadeScrollChild in a dedicated overlay_scroll.h (kept
out of the widely-included draw_helpers.h because effects::ScrollFadeShader's GL
headers clash with SDL's in some TUs).
Also fix IsCurrentWindowOverlayDialog to prefix-match "##OverlayScrim" so suffixed
overlay windows are recognized by the modal-aware hover check.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add market_iv_1h/1d/1w/1m and market_updated ("· Updated %s") keys and use them
in the chart interval strip (previously hardcoded "1H"/"1D"/"1W"/"1M") and the
pair-selector attribution line (previously a literal "· Updated %s"). Closes the
audit's i18n gaps in the market tab.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the balance summary (fiat/DRGX/BTC + shielded ratio bar) and the
draggable/resizable custom-group card grid (drag/resize gestures, dot grid,
click-to-edit) out of RenderMarketTab into mktDrawPortfolio(MktCtx); the local
x-coord `cx` renamed `cx0` (ctx param is `cx`). Drop the now-unused
gap/dl/glassSpec/buf locals. RenderMarketTab is now ~150 lines (from 962) — a
thin orchestrator: precompute -> build MktCtx -> hero/chart/pair/portfolio.
Verbatim bodies. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the ~250-line chart block (interval strip + 24h stats + refresh, plotted
curve with grid/area-fill/hi-lo+time labels/hover crosshair+tooltip, empty
state) out of RenderMarketTab into mktDrawPriceChart(MktCtx), recomputing cheap
locals and reading the precomputed series via the ctx. Drop the now-unused
hs/pad locals. Verbatim body. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Introduce a MktCtx struct holding RenderMarketTab's precomputed geometry/series,
built once after the precompute, and extract the combined hero card (glass panel
spanning header + chart, price/ticker/period-badge/trade button) into
mktDrawPriceHero(MktCtx). Cheap locals (dl/fonts/dp/market) recomputed in the
helper; the hero's local x-coord `cx` renamed `cx0` (the ctx param is `cx`).
Verbatim body. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the exchange/pair chip grid (wrapping flat chips + click-to-switch +
attribution line) out of RenderMarketTab into mktDrawPairSelector(app, registry,
availWidth), recomputing its own schema/fonts/market. Drop the now-unused ovFont
local. Verbatim body. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lift the ~90-line [&]-capturing drawCard closure out of RenderMarketTab's grid
code into a file-static mktDrawCard(MktCardCtx, min, max, entry, hov). The
captured locals (dl/state/market/mktDp/pfInset/pfCardPad/sub1/capFont) are
bundled into a MktCardCtx bound once per frame. Verbatim body. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pull the ~30-line row-major cell placement (honor stored placement else
auto-place) out of RenderMarketTab into a pure, deterministic helper taking
(entries, cols, minW, minH). Also bump the grid resize-readout buffer 16->32 to
silence a worst-case -Wformat-truncation the extraction surfaced. No behavior
change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pull the three detail-pane section blocks out of RenderPortfolioEditor into
pfDrawAppearanceSection / pfDrawPriceSection / pfDrawAddressSection (each
recomputes its own dp/fonts/state; the section dispatch is a 3-line switch).
Verbatim move — same widgets, IDs and drawing. RenderPortfolioEditor drops from
~760 to ~357 lines. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Convert the four [&]-capturing lambdas (persist / buildWorking / workingMatches /
commitIfNeeded) into file-static pfPersist / pfBuildWorking / pfWorkingMatches /
pfCommitIfNeeded that operate on the s_pfEdit struct + take Settings*. Removes
the per-frame closure setup and lets the upcoming section helpers reuse them.
No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the loose market_tab.cpp statics into MarketViewState (s_mkt),
PfEditState (s_pfEdit) and PfGridDrag (s_grid). Pure mechanical rename
(compile-verified, no behavior change) that shrinks the global surface and gives
the upcoming function decompositions a single state handle per concern instead
of ~35 free names.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move the no-I/O, no-ImGui series helpers (resampleHistory, bucketBySeconds,
sparklineSeries, chartSeries) out of market_tab.cpp into an inline header under
data/ (mirroring data/portfolio.h) and cover them with a testMarketSeries()
group in test_phase4.cpp (resample block averaging + partial blocks, window
bucketing + guards, sparkline fallback, chart time-window filtering + live
timestamp synthesis). market_tab now calls data::sparklineSeries/chartSeries.
No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the two identical equal-width segmented controls (the detail section
switcher Appearance/Price/Addresses and the address type filter
All/Shielded/Transparent) into one pfSegmentedControl(dl, origin, w, h, labels,
count, selected, font, idBase, dp) that returns the clicked index. Same track /
active-pill / centered-label drawing and per-cell hit-test as before; the
variable-width chart-interval strip is left as-is. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dedup the identical min/max→rect projection shared by pfDrawSparkline and
pfDrawSparklineFilled into pfProjectSeries, and the repeated right-align cursor
math (footer Close, detail Revert/Save, summary Manage button) into
pfRightAlignX. No behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Audit cleanup of market_tab.cpp:
- Remove the write-only statics s_history_initialized and s_last_refresh_time
(assigned in several places, never read) and their now-dead assignments.
- Align the portfolio grid card's BTC value to %.8f to match the editor preview
(pfBuildDisplay) and the summary rows; it was the lone %.6f, so the same
balance rendered with different precision in the preview vs the card.
- Fix the stale s_pf_sel comment (no "-2 = unsaved draft" state exists).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merge the two address-section rows into one: the All/Shielded/Transparent
segmented type filter sits on the left and Select all / Clear / Funded are
right-aligned on the same line, both vertically centered. Select-all is deferred
to a flag applied after the filtered set is built, so it still targets the
current filter (and stays idempotent via PortfolioEntryAdd's dedup).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Complete the explicit-save model: leaving the Manage-portfolio modal via Esc or
an outside-click now discards the current group's uncommitted edits (matching
the discard-on-switch behavior), while the Close button still commits. Only the
Save and Close buttons persist; every other exit path is a cancel.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switching to another group in the Manage-portfolio list (or adding/deleting a
group) now discards the current group's uncommitted working edits instead of
auto-saving them — only the Save button (and closing the modal) persists. This
matches the explicit-save model signalled by the Revert/Save buttons and the
unsaved-changes dot: navigating between drafts is ephemeral until saved.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Move the group-scoped Revert/Save buttons into the detail container (sized to
the Add-entry height) so they read as lower-hierarchy than the modal-level
Close, which now stands alone in the footer. The detail body is wrapped in a
child that reserves the bottom row.
- Add an amber "unsaved changes" dot on the selected group row while its working
copy differs from the stored entry; also gate the detail Revert/Save on that
dirty state.
- Addresses: narrow the All/Shielded/Transparent segmented control (360px) and
right-align Select all / Clear / Funded on one line; give the Select all /
Clear pills more text padding.
- Appearance: shrink the icon search field and right-align it on the heading
line, with a "Search icons…" hint.
- Price: move the sparkline toggle onto the 24h line; the interval radios stay
below, enabled only when the sparkline is shown.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rework the Manage-portfolio detail pane's Appearance and Addresses sections:
- Icon picker: search field inline with the "Icon" heading (filters by name,
hides the "None" slot while searching); grid now always fits 12 icons per
row, scaling cell size to width and centering the block.
- Both the icon grid and the address list scroll via a shared helper
(pfBeginScrollChild/pfEndScrollChild): smooth scrolling + the Settings-tab
edge-fade shader + a thicker, rounded scrollbar inset from the container edge
(bordered outer frame wrapping an inner scrolling child). Smaller container
radius. Fade gates off in low-spec and while the acrylic backdrop is being
captured — latched per-frame so the last capture frame no longer clashes with
the render-state reset.
- Addresses: All/Shielded/Transparent segmented control moved to its own row,
capped at 580px; Select all / Clear pills moved left of the Funded checkbox
on one left-aligned row (Funded vertically centered against the pills).
- Custom colour "+" swatch inset a few px so its selection outline no longer
clips at the modal's right edge.
- Remove the divider above the footer Revert/Save/Close buttons.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Appearance: icon-picker cells doubled (56px, iconXL glyphs); color swatches back to a
single row that hides overflow but always keeps the custom "+" cell visible at the right.
- Price: basis radios are now horizontal, matching the sparkline-interval radios.
- Addresses: All/Shielded/Transparent segmented control shrinks to sit on one line with
the Funded toggle to its right; Select all / Clear are rounded (pill) buttons with
padding, right-aligned on their own row.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Price: the basis and sparkline-interval dropdowns become radio groups (all options
visible), now that the segmented layout gives the section full height.
- Addresses: the All/Shielded/Transparent chips become a rounded segmented control
matching the top switcher. "Select shown" renamed to "Select all"; Select all + Clear
moved onto the Funded row, right-aligned. Address list gets inner WindowPadding.
- Appearance: 17 more preset colors (25 total), and the swatches now wrap into a grid
(with the custom-color cell) instead of a single overflowing row.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Swap the collapsible Appearance/Price/Addresses dropdown sections for a single
segmented pill control (one section shown at a time) — no dropdown headers. The
active section now owns the full detail height, so the icon grid and address list
fill the available space instead of fixed heights. State: s_pf_section (0/1/2)
replaces the three accordion open-flags.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Raising the backdrop radius alone would thrash the shared radius-keyed blur cache (the
glass panels blur at ~30). Instead, while a full-window blur overlay is active, glass
panels use their opaque fallback (IsFullWindowBlurOverlayActive) — they're covered by the
backdrop anyway — so the backdrop is the SOLE applyBlur caller and can use a strong custom
radius (64) with the cache staying coherent and frozen. The flag is toggled alongside the
theme-effect suppression by a RAII guard in App::render().
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch the live-blur behind the modal from a per-frame capture (which flickered from
per-frame re-blur non-determinism) to capture-once-on-open, re-captured only on resize.
- Insert the acrylic live-capture callback into the overlay draw list ONLY for a few
frames on open and whenever the viewport size changes; other frames reuse the frozen
blurred snapshot (blurCacheValid_), so there's no per-frame capture/re-blur cost. State:
s_pf_was_open (reset on close), s_pf_capture_frames, s_pf_capture_w/h.
Two fixes from an adversarial review of the timing/pipeline interaction:
- Do NOT override the backdrop blurRadius to 40. applyBlur caches one blurred buffer
keyed on radius, shared with every glass panel (market cards + the modal preview card,
radius ~30). A different radius thrashed that cache every frame and made the backdrop
sample the wrong blur, defeating the frozen-blur guarantee. Using the theme card's
radius keeps one blur serving all surfaces, frozen.
- Skip the blur on the overlay's first frame (allowBlur=false) — the live content isn't
captured until that frame's render, so blurring then would show stale/background pixels
for one frame; draw the plain opaque scrim instead.
Compiles on OpenGL (Linux) + DX11 (Windows). Needs on-device visual verification.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Fix the ImGui error on hovering a group row: the per-row delete was an
overlapping InvisibleButton + SetCursorScreenPos over the row Selectable. Replace
it with a manual IsMouseHoveringRect / IsMouseClicked hit-test (no overlapping
ImGui item, no cursor manipulation).
- Delete icon is larger (iconMed) and inset from the row edge (spacingMd).
- Footer no longer clipped: reserve 56px for the 40px buttons + separator.
- Manage-portfolio heading is now plain text (h6) with no title-bar background or
divider — content floats on the backdrop.
- Sidebar theme-effect borders no longer bleed through the overlay: suppress panel
theme-effects frame-wide (RAII guard in App::render via ui::PortfolioEditorActive)
while the modal is open, instead of only during the market render.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The acrylic system only blurred a frozen snapshot of the static app background. Add
an overlay-time re-capture so the Manage-portfolio modal blurs the LIVE tab content
behind it.
- AcrylicMaterial::captureLiveFramebuffer() (GL blit of FB 0 / DX11 CopyResource of the
backbuffer + no-backend stub) mirrors captureBackgroundDirect but bypasses the
dirtyFrames_ gate so it refreshes every frame the overlay is open, forcing a re-blur.
- ImGuiAcrylic::GetLiveCaptureCallback() returns a draw callback for it.
- market_tab: the modal inserts that callback (+ ImDrawCallback_ResetRenderState) at the
START of its overlay draw list, before the backdrop, so the capture holds the app UI
drawn below and the backdrop blurs it. On close, InvalidateCapture() re-captures the
background so other glass panels don't keep blurring the stale live capture.
- Panel theme-effects are suppressed during the market render while the modal is open
(their foreground-draw-list borders draw above all windows and would otherwise bleed
over the overlay). Market tab body is rendered again (no longer skipped).
- Backdrop draws the acrylic at full strength (fallbackColor.w=1) over an opaque base so
the blurred content reads clearly; lighter dim.
Design mapped via an Explore investigation of the capture/blur pipeline; compiles on
both OpenGL (Linux) and DX11 (Windows cross-build). Needs on-device visual verification.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- The per-row delete icon's SetCursorScreenPos left the ImGui cursor at the icon,
so the next group row started too high and rows overlapped. Capture the row's
end cursor after the Selectable and restore it after drawing the delete icon.
- Force centered button-label alignment for the modal (ButtonTextAlign 0.5,0.5)
so the footer/Add buttons read consistently.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Delete moved from the footer to a per-row trash icon on each group (shown on
hover/selected), with deferred deletion + selection fix-up.
- Removed the title-bar X; the footer is now right-aligned Revert / Save / Close
(larger buttons), Close commits + dismisses. Esc and outside-click still close.
- Add entry now immediately creates a persisted "Untitled" group and selects it
(no more invisible draft state); the -2 draft path is gone.
- Backdrop bleed-through fixed: when the modal is open the Market tab body is not
rendered, so its content and foreground theme-effect borders no longer show over
the overlay — the modal floats on the app's blurred/opaque backdrop.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add button can no longer be cut off: it's now a normal widget below the group
list (in a group with the scroll child) instead of nested inside the list child.
- Stop the modal's 28x20 WindowPadding from cascading into the nested master/detail/
list children (pop it right after the card child begins) — that double-padding
was squeezing the master column and the Add button.
- Right pane navigability: collapsed accordion sections now show a compact summary
on the right (Appearance -> icon, Price -> basis, Addresses -> N selected), so a
group's state is readable without expanding. Section titles are consistent
title-case ("Appearance"/"Price"/"Addresses").
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove the centered glass card behind the Manage-portfolio content so it floats
directly on the blurred/opaque full-window backdrop. The little live-preview card
keeps its panel (it previews the actual group card).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop ImGuiWindowFlags_NoBringToFrontOnFocus on the overlay window — it stopped
the per-frame SetNextWindowFocus() from raising the modal, so it rendered behind
the market chart/cards. Now matches the proven BeginOverlayDialog behavior.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Combine the old list/edit modes into one master-detail view rendered as a
full-window overlay instead of a floating dialog.
- Backdrop: new material::DrawFullWindowBlurBackdrop draws an opaque base first
(so the sheet is opaque regardless of the UI-opacity slider — the acrylic path
multiplies its alpha by GetUIOpacity), then a strong full-window blur of the
backdrop, gated exactly like DrawGlassPanel so low-performance mode skips the
blur entirely (just the opaque scrim).
- Frame: bespoke full-window overlay (not BeginOverlayDialog) that mirrors the
scrim plumbing and preserves both overlay popup gotchas verbatim (no focus-steal
and no outside-click dismiss while a combo / color picker is open). Title-bar X,
Esc, and outside-click all dismiss.
- Left (master): selectable group list with accent bar + icon + name + value line,
and a pinned "Add group" button.
- Right (detail): live preview + label header, then a single-open accordion
(Appearance = color + outline opacity + icon; Price; Addresses) so only one
control group shows at a time — far less cluttered than the old two-column form.
- Footer: Delete / Revert / Save. Editing auto-commits named groups on navigation
and on close (preserving grid geometry); unnamed drafts are dropped.
- s_pf_editing tri-state replaced by s_pf_sel (+ accordion open-state); the Manage
button and grid-card click open with a valid selection.
Design + adversarial review done via multi-agent workflows (understand/design, then
a 3-lens ImGui-lifecycle / state-safety / backdrop review; zero confirmed defects).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Drop the extra gap the hero header reserved below the price row, so the interval
buttons sit closer to the top of the chart area.
- Place the divider just below the buttons with a comfortable gap (spacingMd)
between it and the plot, instead of centering it in the strip gap.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Default the price chart to the 1M range on open (was 1D).
- Move the hero divider from below the price row to below the interval buttons
(centered in the gap between the buttons and the plot).
- Remove the dot markers on the chart: no per-point dots, no current-price dot,
and no high/low dot anchors — just the clean line + area fill (the high/low
price labels and the hover crosshair remain).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Portfolio group cards:
- Always show the secondary DRGX amount, including on 2-cell cards.
- Larger group icon + label (subtitle1); value stays subtitle1 for consistency.
- Minimum group width is now 8 cells (default width 8).
Price chart:
- Area fill is now a flat translucent fill matching the group-card sparklines
(dropped the vertical gradient + its primitive-API helper).
- Interval buttons sit near the top of the chart area (removed the empty gap
above them) with a comfortable gap below before the plot.
- The change badge's suffix now matches the SELECTED range (1H->1h, 1D->24h,
1W->7d, 1M->30d) instead of the raw data span (which read 23h / 6d).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Chart interval buttons are now time RANGES, not bucket sizes: 1H = last hour,
1D = last 24h (5-min intraday), 1W = last 7 days, 1M = last 30 days (daily).
pfChartSeries filters the timestamped series to the window; X-axis "ago" labels
and the period-change span now derive from the real timestamps.
- Portfolio group cards redesigned: name (+ secondary DRGX) on the left; the value
with its % change stacked in the top-right corner; the sparkline fills the card
body. The sparkline now renders on 2-cell cards too (down to ~8px of body), with
tighter padding on short cards.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Builds on the timestamped historical series (pfChartSeries returns [time,price]):
- Gradient area fill: replace the flat translucent fill with a true vertical
gradient (solid at the line, fading to transparent) via the draw-list primitive
API (pfFillGradientArea).
- Period-aware change: the price badge now reports the change over the DISPLAYED
chart period with a span label derived from real timestamps (e.g. "+42% 1.0y"),
falling back to 24h for Live. Line/fill/marker colors follow that direction.
- Timestamped hover: the crosshair tooltip shows the real date/time at the hovered
point (time for Live/1H, date for day+ intervals) alongside the price.
- High/low markers: hollow dot + price label at the range's extremes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Portfolio group minimum height is now 2 cells (was 3). Added a 2-cell card tier
that also drops the sparkline (not just the footer) so a ~58px card keeps the
header + hero value legible.
- Price chart: stop drawing a dot on every point — for a dense historical series
(>40 points) just the clean line + fill, and always mark the latest point
(current price) with a dot + ring.
- Y-axis labels use the shared adaptive price formatter (e.g. $0.0143) instead of
a fixed 6 decimals, so they're cleaner and narrower.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Chart:
- The price chart now plots the historical CoinGecko series with a Live/1H/1D/1W/1M
interval selector (top-left of the chart). Live = in-session buffer; 1H uses the
intraday 5-min series, 1D/1W/1M the daily series (via pfSparklineSeries). X-axis
labels are interval-aware ("~5h"/"~3d"/"~2w"/"~4mo"). Market-tab open kicks the
self-throttled market_chart fetch so history populates promptly.
- 24H volume + market cap moved from their own row onto the chart's top strip
(right side, next to the refresh button), reclaiming the empty band above the
chart; the hero header now holds just the price row + separator.
- More bottom padding under the plot so the time labels and the DRGX/USDT pair
buttons aren't crowded against the card edges.
Portfolio groups:
- Accent-outline opacity is now configurable per group (0-100%, default 25%) via a
slider in the editor's Appearance column; applied to the card + preview outline.
- Resize grip enlarged (14->20px) and a live "W x H" size readout is drawn while
resizing, so shrinking a group to the 4x3 minimum is reliable and visible.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Portfolio groups now default to the 3-cell minimum height (was 4). The card
design adapts: below ~112px it drops the redundant DRGX footer and uses the
compact hero font so a 3-cell card stays legible.
- Group accent color is now a colored outline around the whole card (and the
editor's live preview) instead of a stripe on the left edge; the text no longer
reserves the old left-stripe offset.
- Price chart: trim the empty band between the 24H VOLUME stats and the chart
(smaller hero-header bottom pad), and keep the Y-axis price labels inside the
card on narrow windows (clamp to the card's left edge + bump min y-axis padding
40->54) so they no longer spill onto the tab background.
- Market tab no longer draws a scrollbar (NoScrollbar); the portfolio grid still
scrolls via the mouse wheel.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
While rearranging, the dot grid only reached two rows below the lowest card, so
the empty space beneath the cards showed no dots even though a card can be
dropped there. Fill the grid down to the bottom of the visible scroll viewport
(dl clip rect), keeping the two-row buffer as a minimum. The drop-target row is
already unclamped, so dropping into that lower area places the card and grows the
scrollable content.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Portfolio-group sparklines previously resampled the ~24-minute in-session price
buffer, so the hour/day/week/month intervals could never fill. Fetch real
historical USD series from CoinGecko /market_chart and back each interval with
appropriately-grained data.
- MarketInfo gains two timestamped series: price_chart_intraday (days=1, 5-min)
and price_chart_daily (days=365, daily), plus a fetch timestamp.
- App::refreshMarketChart() fetches both on the RPC worker via the TLS-verifying
util::httpGetString helper, self-throttled to ~30 min (historical data moves
slowly). Gated by getFetchPrices(); triggered on connect and each price tick.
- Pure NetworkRefreshService::parseCoinGeckoMarketChart() parses {"prices":
[[ms,price],...]} into (unix-seconds, price); malformed rows skipped. Unit-tested.
- market_tab pfSparklineSeries() maps interval -> series+bucket: minute = live
buffer; hour = intraday bucketed to 1h; day/week/month = daily bucketed to
1d/7d/30d. Falls back to the in-session buffer until the fetch populates.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>