From 4cc03601511e4992709e2b8f1eea3366674e2b14 Mon Sep 17 00:00:00 2001 From: MotherSphere Date: Mon, 12 Oct 2026 20:53:22 +0200 Subject: [PATCH 1/6] chore(deps): move locked dependencies to their latest releases --- Cargo.lock | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bf624ee..f972139 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -275,9 +275,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f74872d07caf508b30a21f6836e7d7016a2eaf7d9ff4f48deaa58cd8a0407630" +checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838" dependencies = [ "find-msvc-tools", "shlex", @@ -451,7 +451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d045de693cb712d0b22c6a64be5b953f67b3ce00ab5ad3dd5d8b441886ab8e1a" dependencies = [ "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -480,7 +480,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -491,7 +491,7 @@ checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" dependencies = [ "darling_core", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -617,7 +617,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -803,7 +803,7 @@ checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -861,7 +861,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -2431,7 +2431,7 @@ checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -2652,7 +2652,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -2687,7 +2687,7 @@ checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -2738,7 +2738,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -2809,9 +2809,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.16.2" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" +checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" [[package]] name = "socket2" @@ -2941,9 +2941,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.6" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" dependencies = [ "proc-macro2", "quote", @@ -2967,7 +2967,7 @@ checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -3299,7 +3299,7 @@ checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -3577,9 +3577,9 @@ checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "unicode-ident" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" +checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" [[package]] name = "unicode-segmentation" @@ -3620,9 +3620,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.27.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97277d36b9c3ace13e58fa6e753f8b0bbbf302a18dd193240d70f9e29681059a" +checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606" dependencies = [ "getrandom 0.4.3", "js-sys", @@ -3739,7 +3739,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", "wasm-bindgen-shared", ] @@ -4240,7 +4240,7 @@ checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", "synstructure", ] @@ -4261,7 +4261,7 @@ checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", "synstructure", ] @@ -4295,7 +4295,7 @@ checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] From 7da2845f0e0b5de5ebd0a08e9c0841d9d9dffdca Mon Sep 17 00:00:00 2001 From: MotherSphere Date: Mon, 12 Oct 2026 20:56:23 +0200 Subject: [PATCH 2/6] refactor: open the main window from window_state, keeping main.rs to the entry point --- src/main.rs | 43 +++-------------------------------- src/window_state.rs | 55 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 43 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7947c1c..c788ed4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,8 +11,8 @@ mod paths; mod preferences; mod window_state; -use preferences::{Preferences, Store}; -use tauri::{App, LogicalSize, Manager, WebviewUrl, WebviewWindow, WebviewWindowBuilder}; +use preferences::Store; +use tauri::Manager; fn main() { // Before anything else, and without opening a window: the release @@ -50,7 +50,7 @@ fn main() { } app.manage(store); - let window = open_main_window(app, &preferences)?; + let window = window_state::open_main_window(app, &preferences)?; window_state::attach(&window, config_dir.as_deref()); Ok(()) }) @@ -64,43 +64,6 @@ fn main() { .expect("error while running tauri application"); } -/// Opens the main window, described in tauri.conf.json (where it is not -/// created at startup), on the layout chosen in Preferences. -fn open_main_window(app: &App, preferences: &Preferences) -> tauri::Result { - let mut config = app - .config() - .app - .windows - .iter() - .find(|window| window.label == "main") - .cloned() - .expect("tauri.conf.json describes the main window"); - let layout = preferences.startup_layout; - config.url = WebviewUrl::App(layout.page().into()); - (config.width, config.height) = layout.size(); - - let mut builder = WebviewWindowBuilder::from_config(app.handle(), &config)?; - // The webview profile moves to Colony/orCAL only once the theme the old - // builds kept in its localStorage has been imported (common/prefs.js): - // until then the old profile, Tauri's default, is the only place it is. - // macOS WKWebView has no data directory and keeps its default location. - if preferences.legacy_storage_imported { - match paths::data_dir() { - Ok(data) => builder = builder.data_directory(data.join("webview")), - Err(error) => log::warn!("the webview keeps its default profile: {error}"), - } - } - let window = builder.build()?; - // A floating window manager can map the window before the builder's size - // reaches it (XWayland only saw a 10x10 hint) and pick its own size; - // asking again once the window exists gives the layout's size. - let (width, height) = layout.size(); - if let Err(error) = window.set_size(LogicalSize::new(width, height)) { - log::warn!("the window keeps the size the window manager chose: {error}"); - } - Ok(window) -} - /// Whether the command line, without the program name, asks for the version. fn asks_for_version(args: impl IntoIterator>) -> bool { args.into_iter() diff --git a/src/window_state.rs b/src/window_state.rs index 012ca5b..cfeee14 100644 --- a/src/window_state.rs +++ b/src/window_state.rs @@ -1,5 +1,6 @@ -//! Remembers where the main window was, and puts it back there on the next -//! start when that spot is still on a connected monitor. +//! The main window: opens it on the layout chosen in Preferences, remembers +//! where it was, and puts it back there on the next start when that spot is +//! still on a connected monitor. //! //! The position is written atomically to `/window-position.json`. A //! drag sends a stream of `Moved` events, so a move is saved once the window @@ -13,9 +14,13 @@ use std::time::Duration; use std::{fs, io, thread}; use serde::{Deserialize, Serialize}; -use tauri::{Monitor, PhysicalPosition, Position, WebviewWindow, WindowEvent}; +use tauri::{ + App, LogicalSize, Monitor, PhysicalPosition, Position, WebviewUrl, WebviewWindow, + WebviewWindowBuilder, WindowEvent, +}; use crate::paths; +use crate::preferences::Preferences; /// The file name, in the config folder. pub const FILE: &str = "window-position.json"; @@ -23,6 +28,50 @@ pub const FILE: &str = "window-position.json"; /// How long the window must stay still before a move is saved. const SETTLE: Duration = Duration::from_millis(500); +/// Opens the main window, described in tauri.conf.json (where it is not +/// created at startup), on the layout chosen in Preferences. +pub fn open_main_window(app: &App, preferences: &Preferences) -> tauri::Result { + let mut config = app + .config() + .app + .windows + .iter() + .find(|window| window.label == "main") + .cloned() + .expect("tauri.conf.json describes the main window"); + let layout = preferences.startup_layout; + config.url = WebviewUrl::App(layout.page().into()); + (config.width, config.height) = layout.size(); + + let mut builder = WebviewWindowBuilder::from_config(app.handle(), &config)?; + // The webview profile leaves Tauri's default location only once the theme + // the old builds kept in its localStorage has been imported + // (common/prefs.js): until then the old profile is the only place it is. + // After that orCAL keeps nothing in webview storage, so the profile is + // cache: `/webview` on Linux and Windows, and memory only on macOS, + // where WKWebView cannot be given a folder and would otherwise write to + // ~/Library/WebKit. + if preferences.legacy_storage_imported { + if cfg!(target_os = "macos") { + builder = builder.incognito(true); + } else { + match paths::cache_dir() { + Ok(cache) => builder = builder.data_directory(cache.join("webview")), + Err(error) => log::warn!("the webview keeps its default profile: {error}"), + } + } + } + let window = builder.build()?; + // A floating window manager can map the window before the builder's size + // reaches it (XWayland only saw a 10x10 hint) and pick its own size; + // asking again once the window exists gives the layout's size. + let (width, height) = layout.size(); + if let Err(error) = window.set_size(LogicalSize::new(width, height)) { + log::warn!("the window keeps the size the window manager chose: {error}"); + } + Ok(window) +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] struct WindowPosition { x: i32, From 113a86896f91721bc189ad0877eb00f8b107f3ab Mon Sep 17 00:00:00 2001 From: MotherSphere Date: Mon, 12 Oct 2026 20:56:23 +0200 Subject: [PATCH 3/6] fix: keep the webview profile in the cache folder, and in memory on macOS --- README.md | 14 +++++++++----- src/paths.rs | 12 ++++++------ src/ui/common/prefs.js | 5 +++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f541e94..4f4559a 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,8 @@ French strings complete. - `src/preferences.rs`: `preferences.json` and the commands that read and write it - `src/paths.rs`: the Colony folder layout -- `src/window_state.rs`: remembers the window position between runs +- `src/window_state.rs`: opens the main window on the chosen layout and + remembers its position between runs - `src/migrate.rs`: copies the settings of versions before the Colony layout - `src/linux_display.rs`: turns off WebKitGTK's DMA-BUF renderer and accelerated compositing under Wayland, where they fail on some drivers @@ -233,21 +234,24 @@ roaming) application folders: |---|---|---| | Preferences | stored | `preferences/preferences.json` in the settings folder: theme, accent, text size, accessibility, language and startup layout, saved as soon as they change. A setting with a bad value falls back to its default; a theme orCAL does not ship becomes Gruvbox dark, Colony's fallback, and an unknown accent becomes the theme's own. A file that orCAL reads but that is not a JSON object is moved to `preferences.json.bak` and orCAL starts from the defaults. A file it cannot read (permissions, a lock) or cannot move aside is left untouched: orCAL starts from the defaults and saves nothing over it until the next launch | | Window position | stored | `window-position.json` in the settings folder, so the window opens where you left it. On Wayland the compositor decides where windows open | -| Web view profile | stored | the web view's own storage and cache, in `webview/` in the data folder on Linux and Windows, and in the system's WebKit location on macOS. orCAL keeps nothing of its own there once the old theme below has been imported | +| Migration marker | stored | `.migrated` in the settings folder, written by the first launch of a version with the Colony layout. It records where the settings of older versions were looked for, so the copy below runs only once | +| Web view profile | stored | the web view's own storage and cache. orCAL keeps nothing of its own there once the old theme below has been imported, so it is cache: `webview/` in the cache folder on Linux and Windows. On macOS, where the web view cannot be given a folder, it uses a non-persistent store kept in memory instead of the system's WebKit folder | | Expressions and results | neither | kept only in the open window, gone when you close it | | Folder | Linux | Windows | macOS | |---|---|---|---| | Settings | `~/.config/Colony/orCAL/` | `%LOCALAPPDATA%\Colony\orCAL\` | `~/Library/Application Support/Colony/orCAL/` | -| Data | `~/.local/share/Colony/orCAL/` | `%LOCALAPPDATA%\Colony\orCAL\` | `~/Library/Application Support/Colony/orCAL/` | +| Cache | `~/.cache/Colony/orCAL/` | `%LOCALAPPDATA%\Colony\orCAL\cache\` | not used | Preferences > About shows the exact folders on your machine. Versions before the Colony layout kept these in `com.orcal.app` folders. The first launch of a newer version copies the window position over and imports the theme from the old web view storage; the launch after that switches to the -new web view folder. The old `com.orcal.app` folders are left in place and can -be deleted by hand. +new web view profile. The old `com.orcal.app` folders are left in place and can +be deleted by hand, and so can the `webview/` folder that 0.4.0 kept in the +data folder (`~/.local/share/Colony/orCAL/` on Linux, +`%LOCALAPPDATA%\Colony\orCAL\` on Windows). The interface is drawn by the operating system's web view (Microsoft Edge WebView2 on Windows, WebKit on macOS and Linux), which follows its vendor's own diff --git a/src/paths.rs b/src/paths.rs index 7769c65..70cf7de 100644 --- a/src/paths.rs +++ b/src/paths.rs @@ -86,13 +86,13 @@ pub mod locate { under(dirs::config_local_dir(), "config", PROGRAM) } - /// What orCAL produced: the webview profile. + /// What orCAL produced and could not re-derive. It keeps nothing there + /// yet; the About page still shows where it would go. pub fn data_dir() -> io::Result { under(dirs::data_local_dir(), "data", PROGRAM) } - /// What can be rebuilt. orCAL keeps nothing there yet; the About page - /// still shows where it would go. + /// What can be rebuilt: the webview profile. pub fn cache_dir() -> io::Result { Ok(cache_in( under(dirs::cache_dir(), "cache", PROGRAM)?, @@ -108,9 +108,9 @@ pub fn config_dir() -> io::Result { Ok(dir) } -/// [`locate::data_dir`], created if missing. -pub fn data_dir() -> io::Result { - let dir = locate::data_dir()?; +/// [`locate::cache_dir`], created if missing. +pub fn cache_dir() -> io::Result { + let dir = locate::cache_dir()?; fs::create_dir_all(&dir)?; Ok(dir) } diff --git a/src/ui/common/prefs.js b/src/ui/common/prefs.js index c9c68fc..f39157c 100644 --- a/src/ui/common/prefs.js +++ b/src/ui/common/prefs.js @@ -3,8 +3,9 @@ // // Builds before 0.4 kept the theme in the webview's localStorage. The first // launch after upgrading still opens that old webview profile, imports the -// theme here once, and from the next launch orCAL uses a fresh profile under -// Colony/orCAL (src/main.rs). localStorage is not used for anything else. +// theme here once, and from the next launch orCAL uses a fresh profile in its +// cache folder, or in memory on macOS (src/window_state.rs). localStorage is +// not used for anything else. const invoke = window.__TAURI__?.core?.invoke ?? null; From 679c4f074730f79acae6b2a5e64f2d32a6e83aba Mon Sep 17 00:00:00 2001 From: MotherSphere Date: Mon, 12 Oct 2026 20:56:23 +0200 Subject: [PATCH 4/6] fix(ui): keep the Preferences categories on the left in the phone layout --- src/ui/common/preferences.css | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/ui/common/preferences.css b/src/ui/common/preferences.css index a6eea69..1916f5f 100644 --- a/src/ui/common/preferences.css +++ b/src/ui/common/preferences.css @@ -1,9 +1,8 @@ /* * The Preferences page (common/preferences.js), after colony-ui's preferences - * kit: a header, the category list, the selected category's sections. - * Category list on the left in the tablet layout, above the content in the - * phone one. Every label may wrap: French runs longer, and text goes up to - * 1.68 times its base size. + * kit: a header, the category list on the left, the selected category's + * sections on the right. Every label may wrap: French runs longer, and text + * goes up to 1.68 times its base size. */ .preferences { @@ -94,32 +93,22 @@ padding-right: 4px; } -/* Phone: the categories above the content, wrapping, scrolling with it. */ +/* + * Phone: the same two columns in a 360px window, with a narrower list that + * still grows with the text scale up to 40% of the width. Long names break + * across lines (hyphenated where the web view can) instead of squeezing the + * content further. + */ .calculator-phone-frame .preferences-body { - flex-direction: column; gap: 10px; - overflow-y: auto; -} - -.calculator-phone-frame .preferences-content { - flex: none; - overflow: visible; } .calculator-phone-frame .preferences-nav { - flex: none; - max-width: none; - flex-direction: row; - flex-wrap: wrap; - overflow: visible; + flex-basis: calc(112px * var(--font-scale)); } .calculator-phone-frame .pref-category { - padding: 6px 10px; -} - -.calculator-phone-frame .preferences-title { - font-size: calc(20px * var(--font-scale)); + hyphens: auto; } .pref-heading { From 0788463f077ea8d8baee4e62fa33fee3070a0a12 Mon Sep 17 00:00:00 2001 From: MotherSphere Date: Mon, 12 Oct 2026 21:03:01 +0200 Subject: [PATCH 5/6] fix(ui): take the contrast_on label colours from the Colony tokens instead of literals --- src/ui/common/base.css | 9 +++++---- src/ui/common/theme.js | 11 +++++++---- src/ui/vendor/colony/SOURCE | 2 +- src/ui/vendor/colony/colony-accents.css | 5 +++++ src/ui/vendor/colony/themes.json | 4 ++++ 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/ui/common/base.css b/src/ui/common/base.css index 24a4500..b34f88b 100644 --- a/src/ui/common/base.css +++ b/src/ui/common/base.css @@ -43,13 +43,14 @@ * goes on (common/theme.js), not on : the "blue" override is read * here, where no theme hides it. * - * --ink and --paper are colony-ui's contrast_on() ends: the near-black and - * near-white a label takes on a coloured fill, whichever contrasts more. + * --ink and --paper are colony-ui's contrast_on() ends, which colony-accents.css + * also sets: the near-black and near-white a label takes on a coloured fill, + * whichever contrasts more. */ :root { --accent-override-blue: var(--colony-accent-blue); - --ink: color(srgb 0.08 0.08 0.1); - --paper: color(srgb 0.97 0.98 1); + --ink: var(--colony-ink); + --paper: var(--colony-paper); width: 100%; height: 100%; background: transparent; diff --git a/src/ui/common/theme.js b/src/ui/common/theme.js index 2498a55..6282285 100644 --- a/src/ui/common/theme.js +++ b/src/ui/common/theme.js @@ -32,9 +32,11 @@ const parseHex = (text) => { return hex ? [0, 2, 4].map((i) => Number.parseInt(hex.slice(i, i + 2), 16) / 255) : null; }; -// colony-ui's contrast_on() ends, as in base.css (--ink and --paper). -const INK = [0.08, 0.08, 0.1]; -const PAPER = [0.97, 0.98, 1]; +/** colony-ui's contrast_on() ends, which colony-accents.css sets on :root. */ +const contrastEnds = () => { + const root = getComputedStyle(document.documentElement); + return ["--colony-ink", "--colony-paper"].map((name) => parseHex(root.getPropertyValue(name))); +}; /** * "ink" or "paper": whichever of colony-ui's two label colours contrasts more @@ -42,7 +44,8 @@ const PAPER = [0.97, 0.98, 1]; */ export const contrastOn = (color) => { const rgb = parseHex(color); - return rgb && contrast(INK, rgb) >= contrast(PAPER, rgb) ? "ink" : "paper"; + const [ink, paper] = contrastEnds(); + return rgb && ink && paper && contrast(ink, rgb) >= contrast(paper, rgb) ? "ink" : "paper"; }; /** Whether `color` is a light surface, by YIQ luminance as colony-ui reads it. */ diff --git a/src/ui/vendor/colony/SOURCE b/src/ui/vendor/colony/SOURCE index 24b6cc5..b8f67bb 100644 --- a/src/ui/vendor/colony/SOURCE +++ b/src/ui/vendor/colony/SOURCE @@ -1 +1 @@ -Project-Colony-Resources e35de8d43a0a4067194ab1be3220fff5989babba, generated/, with em and en dashes replaced by hyphens +Project-Colony-Resources c19a39d6e85f4c62e0ce961f76a92c51adbc441a, generated/, with em and en dashes replaced by hyphens diff --git a/src/ui/vendor/colony/colony-accents.css b/src/ui/vendor/colony/colony-accents.css index 367fcdf..63b5f6f 100644 --- a/src/ui/vendor/colony/colony-accents.css +++ b/src/ui/vendor/colony/colony-accents.css @@ -4,6 +4,9 @@ * * Palette-independent. Load alongside a theme; "auto" means no override, * i.e. keep the theme's own --colony-accent-blue. + * + * --colony-ink and --colony-paper are the label colours for text drawn on an + * accent: use whichever contrasts more, as colony-ui's contrast_on() does. */ :root { --colony-accent-red: #e05555; @@ -14,4 +17,6 @@ --colony-accent-indigo: #7b6bd6; --colony-accent-violet: #b06bd6; --colony-accent-amber: #d4a030; + --colony-ink: #14141a; + --colony-paper: #f7faff; } diff --git a/src/ui/vendor/colony/themes.json b/src/ui/vendor/colony/themes.json index c326d11..b3548c8 100644 --- a/src/ui/vendor/colony/themes.json +++ b/src/ui/vendor/colony/themes.json @@ -278,6 +278,10 @@ "cssVar": "--colony-accent-amber" } ], + "contrastEnds": { + "ink": "#14141a", + "paper": "#f7faff" + }, "families": [ { "key": "catppuccin", From f6c10ce0532c66c30645f0a1d36e6803d6abf2e2 Mon Sep 17 00:00:00 2001 From: MotherSphere Date: Mon, 12 Oct 2026 21:20:19 +0200 Subject: [PATCH 6/6] refactor: open the preferences store from migrate, keeping main.rs to wiring main.rs setup now only wires the store, the window and the handlers; the legacy copy and the legacy_storage_imported decision live in migrate::open_store, with a test. The README folder table keeps the Data row, marked not used, so it matches the folders the About page lists. --- README.md | 7 ++++--- src/main.rs | 23 ++++------------------- src/migrate.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 4f4559a..60c7347 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,7 @@ French strings complete. - `src/window_state.rs`: opens the main window on the chosen layout and remembers its position between runs - `src/migrate.rs`: copies the settings of versions before the Colony layout + and opens the preferences store - `src/linux_display.rs`: turns off WebKitGTK's DMA-BUF renderer and accelerated compositing under Wayland, where they fail on some drivers - `src/i18n.rs`: tests that hold the two locale files to the same keys @@ -241,7 +242,8 @@ roaming) application folders: | Folder | Linux | Windows | macOS | |---|---|---|---| | Settings | `~/.config/Colony/orCAL/` | `%LOCALAPPDATA%\Colony\orCAL\` | `~/Library/Application Support/Colony/orCAL/` | -| Cache | `~/.cache/Colony/orCAL/` | `%LOCALAPPDATA%\Colony\orCAL\cache\` | not used | +| Data (not used) | `~/.local/share/Colony/orCAL/` | `%LOCALAPPDATA%\Colony\orCAL\` | `~/Library/Application Support/Colony/orCAL/` | +| Cache | `~/.cache/Colony/orCAL/` | `%LOCALAPPDATA%\Colony\orCAL\cache\` | `~/Library/Caches/Colony/orCAL/` (not used) | Preferences > About shows the exact folders on your machine. @@ -250,8 +252,7 @@ first launch of a newer version copies the window position over and imports the theme from the old web view storage; the launch after that switches to the new web view profile. The old `com.orcal.app` folders are left in place and can be deleted by hand, and so can the `webview/` folder that 0.4.0 kept in the -data folder (`~/.local/share/Colony/orCAL/` on Linux, -`%LOCALAPPDATA%\Colony\orCAL\` on Windows). +data folder on Linux and Windows. The interface is drawn by the operating system's web view (Microsoft Edge WebView2 on Windows, WebKit on macOS and Linux), which follows its vendor's own diff --git a/src/main.rs b/src/main.rs index c788ed4..3c855e8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,6 @@ mod paths; mod preferences; mod window_state; -use preferences::Store; use tauri::Manager; fn main() { @@ -30,24 +29,10 @@ fn main() { let config_dir = paths::config_dir() .inspect_err(|error| log::warn!("orCAL cannot keep its settings: {error}")) .ok(); - let legacy_dir = migrate::legacy_config_dir(); - if let (Some(config), Some(legacy)) = (&config_dir, &legacy_dir) { - if let Err(error) = migrate::run(legacy, config) { - log::warn!("settings from before the Colony layout not copied: {error}"); - } - } - - let store = Store::open(config_dir.as_deref().map(preferences::file_in)); - let mut preferences = store.get(); - // Every build before the Colony layout created its config folder on - // first launch, so without one there is no old webview profile and - // no theme in it to import: start on the new profile straight away. - if !preferences.legacy_storage_imported && legacy_dir.is_some_and(|dir| !dir.exists()) { - preferences.legacy_storage_imported = true; - if let Err(error) = store.set(preferences.clone()) { - log::warn!("preferences not saved: {error}"); - } - } + let (store, preferences) = migrate::open_store( + config_dir.as_deref(), + migrate::legacy_config_dir().as_deref(), + ); app.manage(store); let window = window_state::open_main_window(app, &preferences)?; diff --git a/src/migrate.rs b/src/migrate.rs index e7cdd65..cb3864b 100644 --- a/src/migrate.rs +++ b/src/migrate.rs @@ -13,6 +13,7 @@ use std::fs; use std::io; use std::path::{Path, PathBuf}; +use crate::preferences::{self, Preferences, Store}; use crate::{paths, window_state}; /// Tauri's bundle identifier, the folder name of the pre-Colony layout. @@ -49,6 +50,30 @@ pub fn run(legacy: &Path, config: &Path) -> io::Result<()> { ) } +/// Bring over what the pre-Colony builds kept in `legacy`, then open the +/// preferences store in `config` (`None`: settings last for the session). The +/// preferences returned are the ones to open the window on. +pub fn open_store(config: Option<&Path>, legacy: Option<&Path>) -> (Store, Preferences) { + if let (Some(config), Some(legacy)) = (config, legacy) { + if let Err(error) = run(legacy, config) { + log::warn!("settings from before the Colony layout not copied: {error}"); + } + } + + let store = Store::open(config.map(preferences::file_in)); + let mut preferences = store.get(); + // Every build before the Colony layout created its config folder on first + // launch, so without one there is no old webview profile and no theme in + // it to import: start on the new profile straight away. + if !preferences.legacy_storage_imported && legacy.is_some_and(|dir| !dir.exists()) { + preferences.legacy_storage_imported = true; + if let Err(error) = store.set(preferences.clone()) { + log::warn!("preferences not saved: {error}"); + } + } + (store, preferences) +} + #[cfg(test)] mod tests { use super::*; @@ -126,4 +151,22 @@ mod tests { assert!(legacy.join("orcal").join(window_state::FILE).exists()); fs::remove_dir_all(root).unwrap(); } + + #[test] + fn the_old_profile_is_kept_only_while_an_old_folder_exists() { + let root = temp_dir("migrate-store"); + let config = root.join("new"); + fs::create_dir_all(&config).unwrap(); + + let legacy = root.join(LEGACY_IDENTIFIER); + fs::create_dir_all(&legacy).unwrap(); + let (_, preferences) = open_store(Some(&config), Some(&legacy)); + assert!(!preferences.legacy_storage_imported); + + fs::remove_dir_all(&legacy).unwrap(); + let (store, preferences) = open_store(Some(&config), Some(&legacy)); + assert!(preferences.legacy_storage_imported); + assert!(store.get().legacy_storage_imported); + fs::remove_dir_all(root).unwrap(); + } }