feat(brand): swap in the MoonTerminal lockup - #411
Merged
Conversation
The header and the empty-chart placeholder drew the Moonbot wordmark. Both now draw the MoonTerminal one, shipped as two cuts under assets/brand — dark and light — so the scheme picks a FILE instead of patching a fill, and a custom palette can no longer repaint the brand. MoonWindowFrame hardcodes MoonUI's own lockup and has no variant for a foreign one, so the main header assembles its brand cluster from the frame's drag handle plus design::header_logo. The geometry matches brand_cluster; the rule is the terminal's own chrome_divider rather than MoonUI's fainter border copy of it, since the terminal now owns that seam. docs/WINDOWING.md records the exception and its exit condition, and the windowing contract test names both the helper and the asset path so no other screen can follow. Every lockup size is ported through one LOGO_PORT_SCALE factor: the new artwork is 283.23 wide against 199, and the port keeps the ICON at its drawn size rather than the box it sat in, so only the wordmark gets longer. The header buys its room in width (86 -> 122.4) because its strip is height-constrained; the chart placeholder keeps its share of the pane, floor and ceiling scaled alike. Both surfaces now take their image from a two-entry LazyLock table instead of building one per frame: the colour scheme is the document's only input, so the header stopped copying and hashing 6.9KB of asset on every frame and the glow stopped re-composing 7.5KB per empty pane.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
A user reported "I cannot save the
Ctrl+Lefthotkey for Place Long". The hotkey was never theproblem: pressing Save produced
out-of-range value for u64 type, and nothing in Settingscould be saved.
TOML has no unsigned integer.
toml_edit's value serializer converts everyu64throughi64::try_fromand refuses anything abovei64::MAX. Moonbot cores issue strategy ids across thewhole
u64range —read_u64straight off the wire — and two persisted fields carry one:ServerMeta::default_alert_strategyandManualStratState::id. A core whose pinned strategy hadthe top bit set therefore aborted
toml::to_string_prettyfor the entiresettings.toml, which isAppConfig::save, which is every settings write in the application. Roughly half of all idsqualify; one already in a live config reads
7394783480262116308, four fifths of the way to theceiling.
It left durable damage too:
save_implwritesservers.encfirst andsettings.tomlsecond, sothe abort landed between them with
finish_pair_writenever reached — and while that pendingmarker exists,
backup.rsrefuses the daily config snapshot. The first successful save clears it.Both fields now go through the new
config::wire_id.Notable decisions
fits
i64, so a typicalsettings.tomlstays byte-identical and no user's ids are rewritteninto a shape an older build cannot read. The string form is confined to values that build could
never have written in the first place, because writing them is precisely what was impossible.
0("no strategy"), not as an error. Rejectingwould quarantine the whole file to
.bakand replace every core's group, market, colour and feedflags with defaults — the same disproportion this fix removes, pointed the other way.
0landsin the field's own documented recovery:
ManualStratStatere-pins from the strategy NAME.strat_db's bit-castas i64is deliberate. There the signedness is imposedby the join to
orders_rep.strategyid, which the core writes Delphi-signed.settings.tomlhasno such join, and a negative number in a hand-editable file is a trap.
#[serde(untagged)] enum { Number, Text, Other(IgnoredAny) }, as inlayout::serde_compat) rather than a hand-writtenVisitor.IgnoredAnyabsorbs every remaining shape by construction, so no future TOML type can arrive ata missing
visit_*arm and take the file down through a gap nobody closed.every_persisted_u64_field_is_adapted_or_marked_exemptreads the config sources and fails when a persisted
u64carries neither the adapter nor a// wire-id-exemptmarker. It immediately found a third persistedu64nobody had considered —CoreGroup::cores— and three more inlayout.rs. All are terminal-issued uids and are marked assuch. A companion fixture test pins the guard's own ability to go red.
Known limitations
settings.tomlcarrying the string form is unreadable to a build without this change: itquarantines to
.bakand continues on defaults. Only a config that currently cannot be saved atall can contain that shape, so no working setup regresses, but a downgrade on an affected machine
is not lossless.
core or the field, because a serde adapter has no field context.
ServerConfig::default_alert_strategycarries the adapter although nothing encodes that structtoday (
reconcile::splitsends only uid/name/key intoservers.enc) — it is a publicSerializederive on a core-issued
u64, and leaving it bare would arm the same failure for the firstencoder that reaches it.
CoreId, or in a config file outside that list, is still on the author's honour.How to verify
moon-core1526 + 42 across its other targets,moon-ui-gpui1375 + 261 (theme_contract) — 0 failed.layout.rs:1613,:1631,mem_replace_option_with_some); the identical lines sit at1610/1628onorigin/main, and thisPR's whole
layout.rsdiff is three comment lines.cfg/settings.tomlfrom a dev machine was round-tripped throughto_string_prettywith an id ofu64::MAXinjected — it serialises, reads back identically, and theexisting
7394783480262116308stays a bare integer. The unhappy inputs (-5,"","7e18",1.5,true,[1,2],{a=1}, a datetime) all read as0with the file intact.