Skip to content

fix(ui): fourteen reviewed panel, settings and strategies fixes - #407

Merged
kirillDevPro merged 17 commits into
mainfrom
feat/verified-ui-fixes
Sep 3, 2026
Merged

fix(ui): fourteen reviewed panel, settings and strategies fixes#407
kirillDevPro merged 17 commits into
mainfrom
feat/verified-ui-fixes

Conversation

@kirillDevPro

Copy link
Copy Markdown
Collaborator

What & why

Fourteen small, independent UI fixes across the dock panels, Settings and the Strategies
window, each reviewed on a live build before landing here. One commit per fix:

  • connections: keep the scrollbar off the status dots; the table's chrome explains itself
    (group header, window icon, Charts placeholder, capped Key column).
  • report: a real icon on the column picker instead of tofu; the spent column printed as
    money; realized profit stated as a percent of the average order when one core is selected.
  • chart: the chart tab row painted on one surface in the dark theme.
  • analytics: each KPI delta coloured by what is good for that metric; chart value labels no
    longer collide.
  • assets: the wallets roster sized to the core names it must show.
  • strategies: the Auto rail's auto-expanded core is no longer remembered; core counters
    lined up in a right column.
  • detects: an empty feed says why instead of a blank pane.
  • orders: the footer explains its real and emulated counts.
  • ui: one real icon on every column picker.

How to verify

cargo test --workspace and cargo fmt --all -- --check are green per commit. Each fix was
checked by eye on a debug build: Settings › Connections, Report toolbar and footer, Analytics
summary, Assets, Strategies tree, Detects and Orders panels.

In Settings -> Connections the vertical scrollbar track is drawn over
the right end of every core row: the status dot, the reconnect glyph
and the delete button sit under it, and the "+ core" button at the
right edge of a group header loses clicks to the track.

MoonUI paints a MoonVirtualList's scrollbar as an absolute sibling
overlay that reserves no layout width, so a w_full row ends exactly
where the track begins. The column header lives outside the scroller,
which is why only the rows looked wrong.

Every item renderer of that list (server row, group header,
subsection header) and the column header now subtract the shared
design::MOON_SCROLLBAR_OVERLAY_W through design::ui_px, so the gutter
follows the same UI-geometry scale as the track itself and the header
stays aligned with the rows at every scale.
The button at the right end of the Report toolbar that opens the
column-visibility menu showed two hollow squares: its label was the
U+25A6 glyph, which the default Windows font stack does not carry, so
the renderer drew tofu where an icon was meant to be.

The trigger now draws MoonUI's embedded icons/settings-2.svg asset
through MoonDropdown::trigger_icon, the same call the Orders options
dropdown already uses. MoonUI's icon set has no filter or columns
glyph, so the settings icon is reused deliberately; the doc comment
states that choice and the scale rule the icon follows.
The Report's spent column showed 98.9518728 and 4994.83290803 beside a
profit USDT column that reads +2.12: the value fell through to the
generic text path and printed the raw float with eight decimals.

The cell formatter had one money arm, listing profitbtc, gainedbtc,
profitpct and the valuation column; spentbtc was not in it. spent and
gained are amounts rather than results, so they get an arm of their
own: the same per-quote precision the profit cells resolve, without
the sign prefix and without profit colouring. gained moves out of the
profit arm for the same reason, since proceeds rendered as a green
+4994.83. No thousands grouping, because no other money cell in this
table groups and one column must not disagree with its neighbours.
In the dark theme the chart tab row shows a black band around the
figure combo and the gear: the tab strip is its normal dark-grey
surface, but the toolbar cluster to its right sits on nothing.

MoonUI's MoonTabStrip paints its own shell_high fill. Until #371 the
strip was an absolute element stretched across the viewport, so that
fill covered the whole row and the toolbar was drawn on top of it.
Laying the strip in-flow with the cluster as a flex sibling left the
fill covering only the strip's slot, and the unpainted ancestors show
through behind the cluster: near-black in the dark theme, light in
the light one, which is why light-theme screenshots never showed it.

The row container now paints shell_high once, with the token the
strip uses, and continues the strip's 1px bottom rule across the
full width so the hairline no longer stops at the toolbar seam. A
theme contract pins the row's fill.
With one core selected in the Report, the footer shows only the
realized total and the traded volume. A trader reads a core's result
against the size of its orders, and that figure was nowhere on the
screen.

When the snapshot's own filter names exactly one core, the footer's
tail now states realized profit as a percent of the average order:
the sum of spent capital over the counted closed rows divided by
their count, then the profit total against that average. Both sums
run over the same rows by construction, take the settled amount
through one expression so a coin-margined liquidation divides like
for like, and skip funding rows and rows without a usable spend. The
percent follows the head figure's currency rule, so it can never be
denominated differently from the money it qualifies; the tooltip
carries the exact average and the counted and excluded order counts.
With several cores selected the fact is absent, since an average
across differently sized cores would mislead.

The traded-volume buckets are a two-sided notional, not a spend sum,
so moon-core's closed pass gains an entry-spend aggregate. An infinite
average is rejected rather than passed through as a confident zero.
The Analytics summary tiles paint their "vs previous period" delta
green or orange from a single boolean, so a metric with no good
direction cannot be expressed: average trade duration was forced into
"longer is bad" and passed a verdict the data does not support.

The rule becomes three-state, expressed through the existing
DeltaSign::pick convention: a metric is good going up, good going
down, or neither, and a neutral delta keeps its arrow in the soft
text tone, which clears the contrast floor in both themes where the
muted tone does not. Max drawdown is a magnitude, so a rising delta
stays the bad direction, and the doc says so. The sign and colour now
come from the rounded percentage, so the arrow can never disagree
with the digits printed beside it. Tests pin each tile's tone and the
call-site policy.
The Assets «Кошельки» roster kept a fixed default width, so a long core
name («AWS$22 ~ F-BN / SHOT_FUT (SUB_09)») was cut mid-word while the
three container columns beside it had room to spare.

The roster is a separate column with its own width policy in
roster_width.rs, and that policy was blind to content. Measure the widest
name-plus-figures row once per rebuild (and again when the language or
scale changes), floor it at the shipped 420px so short rosters never
narrow, cap it at MAX_BASE_W, and let the name truncate first with the
full name on hover while the amounts never shrink.
In Auto mode, picking a core on the rail and opening Strategies expanded
that core in the tree, and that expansion was written into the persisted
expanded_cores set. Switching to the full Overview and opening Strategies
there then showed every core ever visited on the rail already expanded.

The rail seed belongs to the rail's current selection, not to the user's
own expand/collapse history. Keep it in a non-persisted rail_expanded_core
overlay instead, and track rail_seen_core so an unrelated workspace
revision cannot resurrect a core the user collapsed by hand.
Four things in Settings > Connections read wrong at a glance: the group
header's window button was labelled "win", the group name pushed the
header's four controls off the row, the empty Charts cell gave no hint
what belongs there, and the masked Key column grew with the window while
Name and Group stayed cramped.

Draw the window button as a window-restore icon with its existing
tooltip, gather the header's controls into one right-aligned cluster
behind a truncating name, put a bundle-name placeholder into the Charts
cell, and cap the Key column so Name and Group absorb the freed width.
The Detects panel's render root had no empty branch, so a feed with
nothing to show painted the gear toolbar over a blank table body, and a
new user could not tell a quiet feed from a broken one.

Draw one centred muted sentence in the Log panel's idiom, choosing among
three reasons the render already knows: no available core, every core
hidden by the scope (routed through the shared scope_empty_text), or
simply nothing fired yet. A card whose core went away is no longer blamed
on the scope.
The Orders footer read «Всего 1023 (923/100)», and the parenthesised pair
meant nothing without reading the locale file: it is the split between
real and emulated orders.

Spell the three counts out in words in ru/en/es, and carry a tooltip
built from the same three facts that states the scope they cover and that
the order-kind filter does not narrow them.
The Strategies tree glued each core's, folder's and Deleted heading's
counters onto the caption, so long names pushed the numbers to ragged
positions and the eye could not scan them down the tree.

Render the counters as a muted, right-aligned column of fixed slots with
a tooltip, reserving the open-orders slot even when it is empty so the
active/total column never shifts. The cluster stays passive: a click on
the numbers still reaches the row's expand/collapse handler.
Five column-visibility selectors (Orders, Figures, Assets, Screener, the
Analytics tuner list) still drew U+25A6, which the default Windows font
stack lacks, so they rendered as two hollow squares. Reusing the Report
picker's settings-2 gear would have put two identical gears side by side
on the Orders bar, where the sort/settings dropdown already draws it.

Introduce design::COLUMN_SELECTOR_ICON (icons/layout-dashboard.svg) and
draw it on all six pickers, the Report one included, so one concept has
one icon and the gear stays the settings control. The tuner's picker also
gets the tooltip it never had.
On the cumulative chart the swing labels overlapped each other and the
per-core curves, and the daily bar chart either drew every value label on
top of its neighbours or none at all, so a busy month showed nothing.

Give the swing labels a real two-axis rectangle collision test after the
existing count back-off, dropping the lower-magnitude swing rather than
nudging a label off its point, and set them on a panel chip where they
cross a curve. Render the daily bar labels at the caption size in a band
derived from it, thinning by keeping the largest days that fit, and
measure the label plot in layout pixels rather than font ones.
@kirillDevPro
kirillDevPro merged commit fd9e6a3 into main Sep 3, 2026
6 checks passed
@kirillDevPro
kirillDevPro deleted the feat/verified-ui-fixes branch September 3, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant