Config window: every setting in config.toml, Hyprland options from Hyprland
All tunable values (sizes, timings, text sizes, colours, polls, equalizer presets and bands, hotspot, extra output) are settings declared once in config.rs, read from ~/.config/amane/config.toml, applied live on save. shell.conf's four values move over on first start. settings.rs: a normal window (control centre gear, or ipc config) with a page per part, a page per Hyprland category, search and reset per row. hypr.rs: Hyprland's options from hyprctl descriptions/getoption, applied with hl.config and kept in ~/.config/hypr/amane.lua.
This commit is contained in:
+53
-55
@@ -6,13 +6,14 @@ use std::{env, fs, thread};
|
||||
|
||||
use amane::{Animation, Blend, Color, Service};
|
||||
|
||||
use crate::parse;
|
||||
use crate::{config, parse};
|
||||
|
||||
/*
|
||||
* the shell's colours. they come from the wallpaper: skwd-wall runs matugen with
|
||||
* matugen/amane.colors, which writes ~/.config/amane/theme. ~/.config/amane/shell.conf
|
||||
* says whether the open media card takes the song cover's colours instead, and how long
|
||||
* a change cross-fades. without a theme file the shell keeps its original pink on purple
|
||||
* matugen/amane.colors, which writes ~/.config/amane/theme. config.toml (config.rs) says
|
||||
* whether the open media card takes the song cover's colours instead, how long a change
|
||||
* cross-fades, and the colours used until there is a theme file. Theme also stands for
|
||||
* config.toml: every view reads it, so a saved setting redraws the whole shell
|
||||
*/
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct Colors {
|
||||
@@ -28,18 +29,23 @@ pub struct Colors {
|
||||
pub surface_low: Color,
|
||||
}
|
||||
|
||||
const PINK_ON_PURPLE: Colors = Colors {
|
||||
accent: Color::rgb(247, 168, 200),
|
||||
on_accent: Color::rgb(40, 18, 32),
|
||||
accent_soft: Color::rgb(150, 82, 122),
|
||||
flame: Color::rgb(255, 228, 240),
|
||||
text: Color::rgb(241, 236, 246),
|
||||
dim: Color::rgba(205, 192, 218, 160),
|
||||
outline: Color::rgba(255, 255, 255, 26),
|
||||
surface: Color::rgb(24, 18, 30),
|
||||
surface_high: Color::rgb(35, 26, 44),
|
||||
surface_low: Color::rgb(13, 10, 18),
|
||||
};
|
||||
// the colours without a theme file, from config.toml
|
||||
fn fallback() -> Colors {
|
||||
use config::appearance::fallback as colors;
|
||||
|
||||
Colors {
|
||||
accent: colors::accent(),
|
||||
on_accent: colors::on_accent(),
|
||||
accent_soft: colors::accent_soft(),
|
||||
flame: colors::flame(),
|
||||
text: colors::text(),
|
||||
dim: colors::dim(),
|
||||
outline: colors::outline(),
|
||||
surface: colors::surface(),
|
||||
surface_high: colors::surface_high(),
|
||||
surface_low: colors::surface_low(),
|
||||
}
|
||||
}
|
||||
|
||||
impl Colors {
|
||||
// the background gradient's three stops, light to dark
|
||||
@@ -70,42 +76,33 @@ impl Blend for Colors {
|
||||
|
||||
pub struct Theme {
|
||||
colors: Animation<Colors>,
|
||||
|
||||
// the open media card and the equalizer take the cover's colours as their background
|
||||
pub cover_colors: bool,
|
||||
|
||||
// the iwd access point profile the control centre's hotspot starts (/var/lib/iwd/ap/<name>.ap); empty: none
|
||||
pub hotspot: String,
|
||||
|
||||
// a second Sound slider in the control centre, for the output whose name contains this; empty: none
|
||||
pub extra_output: String,
|
||||
}
|
||||
|
||||
impl Service for Theme {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
colors: Animation::new(PINK_ON_PURPLE),
|
||||
cover_colors: false,
|
||||
hotspot: String::new(),
|
||||
extra_output: String::new(),
|
||||
}
|
||||
Self { colors: Animation::new(fallback()) }
|
||||
}
|
||||
|
||||
/*
|
||||
* waits on the kernel instead of polling: amane::watch_file watches the folder, so
|
||||
* matugen writing a new file and renaming it over the old one is seen too.
|
||||
* shell.conf on its own thread, the theme here; either change re-reads both
|
||||
* config.toml on its own thread, the theme here; either change re-reads both
|
||||
*/
|
||||
fn listen() {
|
||||
reload();
|
||||
|
||||
thread::spawn(|| follow("shell.conf"));
|
||||
thread::spawn(|| follow("config.toml"));
|
||||
|
||||
follow("theme");
|
||||
}
|
||||
}
|
||||
|
||||
// what was read last, (theme, shell.conf); none until the first read
|
||||
// redraws every view, for a setting changed in the config window
|
||||
pub fn touch() {
|
||||
let _ = Theme::write();
|
||||
}
|
||||
|
||||
// what was read last, (theme, config.toml); none until the first read
|
||||
static LAST: Mutex<Option<(String, String)>> = Mutex::new(None);
|
||||
|
||||
fn follow(name: &str) {
|
||||
@@ -119,7 +116,7 @@ fn follow(name: &str) {
|
||||
|
||||
// a deleted theme file sends no event: the defaults come back at the next start
|
||||
fn reload() {
|
||||
let read = (read("theme"), read("shell.conf"));
|
||||
let read = (read("theme"), read("config.toml"));
|
||||
|
||||
let mut last = LAST.lock().unwrap_or_else(PoisonError::into_inner);
|
||||
|
||||
@@ -128,8 +125,12 @@ fn reload() {
|
||||
return;
|
||||
}
|
||||
|
||||
if last.as_ref().is_none_or(|(_, config)| *config != read.1) {
|
||||
config::apply_text(&read.1);
|
||||
}
|
||||
|
||||
// the colours at startup show at once, later changes cross-fade
|
||||
apply(&read.0, &read.1, last.is_none());
|
||||
apply(&read.0, last.is_none());
|
||||
|
||||
*last = Some(read);
|
||||
}
|
||||
@@ -138,18 +139,21 @@ fn read(name: &str) -> String {
|
||||
fs::read_to_string(config_file(name)).unwrap_or_default()
|
||||
}
|
||||
|
||||
// ~/.config/amane/<name>, or under $XDG_CONFIG_HOME
|
||||
pub fn config_file(name: &str) -> PathBuf {
|
||||
let config = env::var_os("XDG_CONFIG_HOME")
|
||||
// $XDG_CONFIG_HOME, or ~/.config
|
||||
pub fn config_home() -> PathBuf {
|
||||
env::var_os("XDG_CONFIG_HOME")
|
||||
.map(PathBuf::from)
|
||||
.or_else(|| env::var_os("HOME").map(|home| PathBuf::from(home).join(".config")))
|
||||
.unwrap_or_default();
|
||||
|
||||
config.join("amane").join(name)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn apply(theme: &str, config: &str, startup: bool) {
|
||||
let mut colors = PINK_ON_PURPLE;
|
||||
// ~/.config/amane/<name>, or under $XDG_CONFIG_HOME
|
||||
pub fn config_file(name: &str) -> PathBuf {
|
||||
config_home().join("amane").join(name)
|
||||
}
|
||||
|
||||
fn apply(theme: &str, startup: bool) {
|
||||
let mut colors = fallback();
|
||||
|
||||
// a missing or broken line keeps that colour's default
|
||||
for (key, value) in parse::settings(theme) {
|
||||
@@ -174,17 +178,10 @@ fn apply(theme: &str, config: &str, startup: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
let settings = parse::settings(config);
|
||||
let setting = |name: &str| settings.iter().find(|(key, _)| key == name).map(|(_, value)| value.as_str());
|
||||
|
||||
let fade = if startup { 0 } else { setting("transition_ms").and_then(|ms| ms.parse().ok()).unwrap_or(400) };
|
||||
let fade = if startup { 0 } else { config::appearance::colors::transition_ms() };
|
||||
|
||||
let mut theme = Theme::write();
|
||||
|
||||
theme.cover_colors = setting("cover_colors") == Some("true");
|
||||
theme.hotspot = setting("hotspot").unwrap_or("").to_string();
|
||||
theme.extra_output = setting("extra_output").unwrap_or("").to_string();
|
||||
|
||||
// a change in the middle of a fade starts from the colours on screen now
|
||||
let now = theme.colors.value();
|
||||
|
||||
@@ -194,19 +191,20 @@ fn apply(theme: &str, config: &str, startup: bool) {
|
||||
|
||||
// the colours of the frame being drawn, set by the view that draws it
|
||||
thread_local! {
|
||||
static NOW: Cell<Colors> = const { Cell::new(PINK_ON_PURPLE) };
|
||||
static NOW: Cell<Colors> = Cell::new(fallback());
|
||||
}
|
||||
|
||||
/*
|
||||
* a view's first line: everything it draws this frame uses these colours (and
|
||||
* reading Theme redraws it when they change). says whether the media card takes the cover's
|
||||
* reading Theme redraws it when they or config.toml change). says whether the media
|
||||
* card takes the cover's
|
||||
*/
|
||||
pub fn begin() -> bool {
|
||||
let theme = Theme::read();
|
||||
|
||||
NOW.set(theme.colors.value());
|
||||
|
||||
theme.cover_colors
|
||||
config::appearance::colors::cover_colors()
|
||||
}
|
||||
|
||||
pub fn now() -> Colors {
|
||||
|
||||
Reference in New Issue
Block a user