Add AppearanceSettings to ely_domain

Introduces a small persistent appearance contract: WallpaperTheme
(Dawn/Violet/Mint/Slate), ThemeMode (System/Light/Dark), reduce_motion.
Defaults to Dawn + System + motion-on. Field accessors and setters live
on the struct so the core can mutate without exposing internals; serde
support uses kebab-case so the on-disk form matches the design CSS
naming.

Tests cover defaults, mutation independence, and a JSON round-trip with
the kebab-case names. serde_json is added as a dev-dependency only —
the production crate does not depend on it.
This commit is contained in:
2026-05-09 18:46:58 -04:00
parent db70ca142c
commit 71088bccb0
4 changed files with 111 additions and 0 deletions
Generated
+1
View File
@@ -2281,6 +2281,7 @@ version = "0.1.0"
dependencies = [
"semver",
"serde",
"serde_json",
"thiserror 2.0.18",
"toml 1.1.2+spec-1.1.0",
"url",
+3
View File
@@ -13,5 +13,8 @@ toml.workspace = true
url.workspace = true
uuid.workspace = true
[dev-dependencies]
serde_json.workspace = true
[lints]
workspace = true
+105
View File
@@ -0,0 +1,105 @@
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum WallpaperTheme {
#[default]
Dawn,
Violet,
Mint,
Slate,
}
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum ThemeMode {
#[default]
System,
Light,
Dark,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
pub struct AppearanceSettings {
wallpaper: WallpaperTheme,
theme_mode: ThemeMode,
reduce_motion: bool,
}
impl Default for AppearanceSettings {
fn default() -> Self {
Self {
wallpaper: WallpaperTheme::default(),
theme_mode: ThemeMode::default(),
reduce_motion: false,
}
}
}
impl AppearanceSettings {
pub fn wallpaper(&self) -> WallpaperTheme {
self.wallpaper
}
pub fn theme_mode(&self) -> ThemeMode {
self.theme_mode
}
pub fn reduce_motion(&self) -> bool {
self.reduce_motion
}
pub fn set_wallpaper(&mut self, wallpaper: WallpaperTheme) {
self.wallpaper = wallpaper;
}
pub fn set_theme_mode(&mut self, theme_mode: ThemeMode) {
self.theme_mode = theme_mode;
}
pub fn set_reduce_motion(&mut self, reduce_motion: bool) {
self.reduce_motion = reduce_motion;
}
}
#[cfg(test)]
mod tests {
use super::{AppearanceSettings, ThemeMode, WallpaperTheme};
#[test]
fn default_settings_use_dawn_and_system_mode() {
let settings = AppearanceSettings::default();
assert_eq!(settings.wallpaper(), WallpaperTheme::Dawn);
assert_eq!(settings.theme_mode(), ThemeMode::System);
assert!(!settings.reduce_motion());
}
#[test]
fn setters_update_each_field_independently() {
let mut settings = AppearanceSettings::default();
settings.set_wallpaper(WallpaperTheme::Violet);
settings.set_theme_mode(ThemeMode::Dark);
settings.set_reduce_motion(true);
assert_eq!(settings.wallpaper(), WallpaperTheme::Violet);
assert_eq!(settings.theme_mode(), ThemeMode::Dark);
assert!(settings.reduce_motion());
}
#[test]
fn json_round_trip_preserves_kebab_case_variants() {
let settings = AppearanceSettings {
wallpaper: WallpaperTheme::Mint,
theme_mode: ThemeMode::Light,
reduce_motion: true,
};
let json = serde_json::to_string(&settings).unwrap();
assert!(json.contains("\"wallpaper\":\"mint\""));
assert!(json.contains("\"theme_mode\":\"light\""));
let restored: AppearanceSettings = serde_json::from_str(&json).unwrap();
assert_eq!(restored, settings);
}
}
+2
View File
@@ -1,3 +1,4 @@
mod appearance;
mod archive;
mod bookmark;
mod command;
@@ -23,6 +24,7 @@ mod tab_group;
mod update;
mod url_text;
pub use appearance::{AppearanceSettings, ThemeMode, WallpaperTheme};
pub use archive::{ArchiveSource, ArchivedTab};
pub use bookmark::BookmarkEntry;
pub use command::{CommandIntent, CommandScope};