Take the theme, the palettes and the filesystem layout from colony-ui - #76
Merged
Conversation
src/ui/theme.rs was 2935 lines, 100 KB of it hand-maintained colour constants. It is now 14 lines that re-export colony-ui, whose palettes are generated from the design tokens in Project-Colony-Resources. That file was the reason the Resources repository exists: SphereCord downloaded it over HTTP and regex-parsed the Rust source to recover the palettes, because there was no other way to reach them. There is now. Every call site keeps working — the module re-exports the same ThemePalette, Palette façade, active_palette, app_tint and contrast_on that were defined here, so this is an import-level change rather than a rewrite. 119 tests still pass. Adding a theme family no longer touches this repository at all: add the TOML upstream, regenerate, bump the tag. colony-ui is pinned to v0.1.0 rather than tracking main, so an upstream change cannot break this build without a deliberate bump.
The picker held a 367-line vec listing every family, its Nerd Font glyph, its i18n key, and every variant's swatch colours — the same facts colony-ui already generates from the design tokens, written out a second time by hand. It now iterates colony_ui::THEME_FAMILIES. The card-drawing code below is untouched: the loop binds the same names it did before, so the diff is the catalog disappearing rather than the rendering changing. Swatch colours come typed from the crate now too, which removes two hand-rolled hex-to-Color conversions that did what colony-ui's swatch_bg_color() does. Together with the previous commit this is what the migration was for: adding a theme family used to mean four edits in this repository — a palette const, a resolver arm, an entry in this vec, and both locale files. It now means none. 119 tests still pass.
…yout
Colony resolved its own directories, and got Windows wrong: dirs::config_dir()
is Roaming there, while Digger and Grape both used Local. On Linux the two are
the same function, so nobody could see the disagreement. The layout is defined
once in colony-ui now — see design/filesystem.md upstream — and Local is what it
picks.
Two things move, both handled by migrate_legacy_paths() at startup:
- the config directory, on Windows only (Roaming -> Local); a no-op on Linux
and macOS, where the old and new resolvers return the same path
- the caches, on every platform: repos_cache.json and scan_cache.json lived
inside the config directory and belong in the cache root
The migration never deletes the source. It renames when it can, falls back to a
recursive copy across filesystems (~/.config and ~/.cache are not guaranteed to
share one), and on failure removes the half-written destination so the next
start retries instead of finding an empty directory and skipping. A user who
ends up with a copy in both places has lost nothing; a user whose preferences
were deleted by a half-finished migration has.
Also fixes real test pollution this exposed: with_temp_dirs isolated
XDG_CONFIG_HOME and XDG_DATA_HOME but not XDG_CACHE_HOME, so once the caches
moved, the update tests read and wrote the developer's actual ~/.cache — and
github_error_only_toasts_when_the_catalog_is_empty started failing depending on
what an earlier run had left there. That was a latent hole in the isolation, not
a consequence of the move.
125 tests pass, up from 119.
…cache root repo-docs, repo-icons and update-staging were still under the config directory. All three are re-fetched or recreated when missing — cached documentation, downloaded icons, and a download staging area — so they belong in the cache root with repos_cache and scan_cache. Leaving them behind would have meant a program that half-follows its own documented layout. This surfaced a bug that compiled cleanly: both orphan-pruning functions walked `<config>/repo-docs` and `<config>/repo-icons` to delete caches for repos that no longer exist. Once those directories moved, the pruners would have found nothing and silently stopped reclaiming anything, growing the cache forever. Colony's own test caught the second one after the first was fixed. Also corrects the documentation, which was already wrong before this change and which the move would have made worse. docs/faq.md and docs/architecture.md claimed preferences lived at ~/.config/colony/preferences.json; the code has written ~/.config/Colony/Colony/preferences/preferences.json for some time. Both tables now match the code, and say what the Windows and macOS roots are instead of implying Linux is the only platform. docs/release-signing.md keeps ~/.config/colony/release-signing/ deliberately: that is where a maintainer keeps their own signing key, not state the program owns, and it is the default sign-release.sh already looks for.
colony-ui 0.1.1 is published, so the dependency is a version rather than a repository URL and a tag. Same crate, same API; what changes is that anyone building Colony resolves it from the registry like every other dependency, with no special-cased git fetch and no question of whether the source repository is reachable. 125 tests still pass.
main had moved ten commits ahead — two releases and #68, which touched the same files this branch does. Resolving it properly meant more than picking sides. What #68 added and this branch had to absorb: - An HTTP ETag cache at <config>/cache/http_etags.json and a diagnostics log at ~/.cache/colony/colony.log. Both are regenerable and both were outside the shared layout, so they move to <cache>/Colony/Colony/ with the rest. - button_colors() and action_button_style() in theme.rs. Those are Colony's own — styling built on the palette, not part of the shared vocabulary — so they stay here alongside the re-export rather than being lost to it. - A doc-parity test that parsed theme.rs's own source counting `=> ThemePalette::` arms, written because the docs claimed 24 families when there were 25. With the palettes gone from this file it would have parsed a 14-line shim. It now counts colony_ui::THEME_FAMILIES directly, which is what the picker actually renders and therefore what the docs describe. - A test that flags locale keys nothing looks up. It failed, correctly: the picker reads its label keys from the catalog now, so they are no longer literal strings here. That last one forced the i18n de-duplication this branch had been deferring. Colony's en.rs and fr.rs each carried 62 theme and accent labels that colony-ui also ships, generated from the same tokens. Verified identical on both sides before deleting them, and `t()` now falls back to colony-ui for keys that name shared design objects. set_language propagates the locale, or the theme picker would have stayed English inside a French page. Also serializes the two tests that swap the process-wide locale. They raced — one read whatever language the other had just set — which is the same class of bug as the XDG_CACHE_HOME isolation gap this branch already fixed. Ran the suite three times to confirm. 149 tests pass, up from 125.
…ed root Two gaps CI cannot see, because migrate_legacy_paths() only runs from main() and the suite never calls it. The OAuth token's fallback path still spelled the layout out by hand with dirs::config_dir(), which is Roaming on Windows — the one root the shared layout says the token must not be in. It is only reached when creating the config directory failed, so it would have gone unnoticed until someone hit that path on Windows and found their token in the other tree. It now asks colony-ui for the same path without creating it, so both branches agree on the layout and only the creation differs. And migrate_legacy_paths() itself had no test. relocate() and copy_tree() were covered in isolation, but not the thing that wires them together and actually runs on a user's machine. The new test plants a complete legacy profile — preferences, token, both caches, repo-docs, repo-icons, staging — runs the migration, and asserts the regenerable state moved, that what the user chose stayed put and readable, that nothing regenerable is left behind to be read again by mistake, and that a second run is inert. Linux only: it drives the XDG variables, and Linux is where the config root is unchanged, so what it proves is the cache move — the part that relocates real files for most users. 150 tests. Ran the suite four times: the new test manipulates process-wide environment variables, which is exactly how the two races already fixed on this branch were introduced.
MotherSphere
added a commit
that referenced
this pull request
Sep 1, 2026
Empty on purpose: the code landed in #76, but that PR was merged with a merge commit, and release-please reads the merge commit's own message rather than the commits inside it. "Merge pull request #76 from ..." is not a conventional commit, so the release automation saw nothing to release and the change would have reached users with no changelog entry. That was a mistake in how #76 was merged, not in what it contained. This repo squashes, and it squashes for a reason. What #76 did, so it appears where users look: - src/ui/theme.rs went from 2935 lines to 103. The 57 palettes now come from the colony-ui crate, generated from shared design tokens. - The theme picker renders from the generated catalog instead of a 367-line hand-kept list, so adding a theme family no longer touches this repository. - Config, data and cache directories follow the shared Colony/<Program>/ layout. Existing files are migrated on first start, without ever deleting the originals. On Windows the config root moves from Roaming to Local, where it always should have been. - Caches, cached docs, cached icons and update staging move out of the config directory into the cache root. 3604 lines removed, 150 tests passing.
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.
Colony carried 2935 lines of
src/ui/theme.rs, 100 KB of it hand-maintained colour constants. That file is the reason Project-Colony-Resources exists: SphereCord downloaded it over HTTP and regex-parsed the Rust source to recover the palettes, because there was no other way to reach them.It is now 14 lines of re-export plus Colony’s own button styling. The palettes come from
colony-ui, generated from design tokens.3376 lines removed. 149 tests pass, up from 119.
What changes
src/ui/theme.rsvec!colony_ui::THEME_FAMILIEScolony_ui::pathsAdding a theme family no longer touches this repository. It used to mean four edits — a palette const, a resolver arm, an entry in the picker vec, and both locale files. It now means none.
Bugs this surfaced
Both orphan-pruning functions walked the wrong directory. After
repo-docsandrepo-iconsmoved to the cache root, they kept scanning the old one. That compiles, raises nothing, and silently stops reclaiming space — the cache would have grown forever. Colony’s own test caught the second after the first was fixed.with_temp_dirsisolatedXDG_CONFIG_HOMEandXDG_DATA_HOMEbut notXDG_CACHE_HOME. Once the caches moved, the update tests read and wrote the developer’s real~/.cache, and one passed or failed depending on what an earlier run had left there. A pre-existing hole, revealed by the move.Two i18n tests raced on the process-wide locale, each reading whatever language the other had just set.
Windows was on the wrong root.
dirs::config_dir()is Roaming; Digger and Grape both used Local. On Linux the two are the same function, so the disagreement was invisible here.User data
migrate_legacy_paths()runs first inmain()and never deletes the source: rename where possible, recursive copy across filesystems, and on failure it removes the half-written destination so the next start retries rather than finding an empty directory and skipping. Linux config does not move at all — the old and new resolvers return the same path there.i18n
en.rsandfr.rseach carried 62 theme and accent labels that colony-ui also ships from the same tokens. Verified identical on both sides before deleting;t()falls back to colony-ui for keys naming shared design objects, andset_languagepropagates the locale so the picker does not sit in English inside a French page.Also
The docs were already wrong before this branch —
faq.mdandarchitecture.mdclaimed preferences lived at~/.config/colony/preferences.jsonwhile the code wrote~/.config/Colony/Colony/preferences/preferences.json. Both tables now match the code and state the Windows and macOS roots.