feat(colors): share the custom HEX history across every picker - #502
Merged
Conversation
A colour typed into a picker's HEX field was remembered only by the Badges settings tab, which kept its own reuse list inside the portable badges.json. Every other picker -- core colour, strategy colour fields, order lines, chart figures, labels, the arbitrage editor, News tags -- made the user retype the same shade from its code each time, so a personal colour scheme drifted apart across the surfaces it exists to tie together. The history now lives in its own cfg/custom_colors.json, owned by moon-core, and every picker seeds from and writes to one app-global entity. It stays most-recent-first, de-duped, and capped at 20 to match MoonUI's own MAX_CUSTOM_COLORS, above which a seeded list is silently trimmed. It is deliberately not an AppConfig field: remembering a colour is immediate app-local state, so pressing Cancel in Settings cannot roll it back and pressing Save is not required to keep it. An existing badges.json list is imported once, the first time the new file is absent, and is left in place afterwards so a downgrade still finds it. BadgesConfig::custom_colors therefore survives as migration-only data rather than a live reuse list. A corrupt badges.json imports as empty rather than failing, because the new file is never created on the error path and a hard error would leave the history unpersisted on every later launch too. Claude-Session: https://claude.ai/code/session_017mwXJTSXLJdEMfjXSvWpS4
Picks up Moonbot-Tech/MoonUI#65, which gives MoonColorPicker's swatch grid a visible scrollbar. The terminal hands that picker 65 swatches plus up to 20 remembered custom colours -- 17 rows against a budget of about five -- so without it the palette looked like only the rows that happened to fit. Only the MoonUI packages move; the MoonProtoBeta pin is unchanged. Claude-Session: https://claude.ai/code/session_017mwXJTSXLJdEMfjXSvWpS4
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.
Closes #488.
What & why
A colour typed into a picker's HEX field was remembered only by the Badges settings tab, which
kept its own reuse list inside the portable
badges.json. Every other picker — core colour,strategy colour fields, order lines, chart figures, labels, the arbitrage editor, News tags —
made the user retype the same shade from its code each time. That is what the tester was actually
asking for: the palette is already identical everywhere, but only badges remembers.
The history now lives in its own
cfg/custom_colors.json, owned bymoon-core, and every pickerseeds from and writes to one app-global entity. Most-recent-first, de-duped, capped at 20 to match
MoonUI's own
MAX_CUSTOM_COLORS, above which a seeded list is silently trimmed anyway.Notes for review:
AppConfigfield, on purpose. Remembering a colour is immediate app-local state, soCancel in Settings cannot roll it back and Save is not required to keep it. That is also why it
is a standalone file rather than a key in
settings.toml, which goes through the draft/previewmachinery.
badges.jsonkeeps its list and is imported once, the first time the new file is absent, soa downgrade still finds it.
BadgesConfig::custom_colorstherefore survives as migration-onlydata;
parse_sharestill preserves it across a paste, for the same reason it always did.badges.jsonimports as empty rather than failing — the new file is never createdon the error path, so a hard error would have left the history unpersisted on every later launch
too.
BadgesConfig::loadalready tolerates that same corruption.precisely to avoid tearing down every row's
MoonInputState, including the hex field beingedited; the shared subscription only pushes swatches.
the swatch grid now shows that it scrolls.
How to verify
cargo test -p moon-core— 1919 passing.cargo fmt --all -- --checkandcargo check -p moon-core -p moon-ui-gpui --lockedclean.Checked in a live debug build against real cores: typing a HEX in the Connections tab's core-colour
picker writes
cfg/custom_colors.json, and the same colour then leads the grid in the Lines tab'sorder-line picker, which has its own unrelated value. The scrollbar is visible on open without
interaction.
Not verified: migration of a non-empty legacy list (the test profile's was empty) and the
corrupt-config path — both are named in the branch notes as unproven, with the mutations that would
catch a regression.
https://claude.ai/code/session_017mwXJTSXLJdEMfjXSvWpS4