Skip to content

Take the theme, the palettes and the filesystem layout from colony-ui - #76

Merged
MotherSphere merged 7 commits into
mainfrom
migrate-to-colony-ui
Sep 1, 2026
Merged

Take the theme, the palettes and the filesystem layout from colony-ui#76
MotherSphere merged 7 commits into
mainfrom
migrate-to-colony-ui

Conversation

@MotherSphere

Copy link
Copy Markdown
Member

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

before after
src/ui/theme.rs 2935 lines 14, plus Colony’s button helpers
theme picker a 367-line hand-kept vec! iterates colony_ui::THEME_FAMILIES
directory paths computed here colony_ui::paths

Adding 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-docs and repo-icons moved 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_dirs isolated XDG_CONFIG_HOME and XDG_DATA_HOME but not XDG_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 in main() 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.rs and fr.rs each 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, and set_language propagates the locale so the picker does not sit in English inside a French page.

Also

The docs were already wrong before this branch — faq.md and architecture.md claimed preferences lived at ~/.config/colony/preferences.json while the code wrote ~/.config/Colony/Colony/preferences/preferences.json. Both tables now match the code and state the Windows and macOS roots.

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
MotherSphere merged commit 9d05974 into main Sep 1, 2026
5 checks passed
@MotherSphere
MotherSphere deleted the migrate-to-colony-ui branch September 1, 2026 22:16
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.
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