Settings, took care of warnings
This commit is contained in:
parent
14ee1e69bc
commit
a060161c64
|
@ -1,3 +1,8 @@
|
||||||
[target.aarch64-unknown-linux-gnu]
|
[target.aarch64-unknown-linux-gnu]
|
||||||
linker="aarch64-linux-gnu-gcc"
|
linker="aarch64-linux-gnu-gcc"
|
||||||
|
|
||||||
|
[env]
|
||||||
|
XMPD_MANIFEST_PATH="./manifest.json"
|
||||||
|
XMPD_SETTINGS_PATH="./settings.toml"
|
||||||
|
XMPD_CACHE_PATH="./cache"
|
||||||
|
|
||||||
|
|
87
Cargo.lock
generated
87
Cargo.lock
generated
|
@ -1032,6 +1032,27 @@ dependencies = [
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "5.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"option-ext",
|
||||||
|
"redox_users",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dispatch"
|
name = "dispatch"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -2406,6 +2427,12 @@ version = "1.20.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "option-ext"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "orbclient"
|
name = "orbclient"
|
||||||
version = "0.3.48"
|
version = "0.3.48"
|
||||||
|
@ -2687,6 +2714,17 @@ dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libredox",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.11.1"
|
version = "1.11.1"
|
||||||
|
@ -2920,6 +2958,15 @@ dependencies = [
|
||||||
"syn 2.0.87",
|
"syn 2.0.87",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1"
|
name = "sha1"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
|
@ -3255,11 +3302,26 @@ dependencies = [
|
||||||
"syn 2.0.87",
|
"syn 2.0.87",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit 0.22.22",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.8"
|
version = "0.6.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
|
@ -3279,6 +3341,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
|
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"winnow 0.6.20",
|
"winnow 0.6.20",
|
||||||
]
|
]
|
||||||
|
@ -4322,19 +4386,13 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"camino",
|
"camino",
|
||||||
"clap",
|
"clap",
|
||||||
|
"dirs",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"log",
|
"log",
|
||||||
"xmpd-cli",
|
"xmpd-cli",
|
||||||
"xmpd-gui",
|
"xmpd-gui",
|
||||||
"xmpd-manifest",
|
"xmpd-manifest",
|
||||||
]
|
"xmpd-settings",
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "xmpd-derive"
|
|
||||||
version = "2.0.0"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.87",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4354,8 +4412,8 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"tokio",
|
"tokio",
|
||||||
"uuid",
|
"uuid",
|
||||||
"xmpd-derive",
|
|
||||||
"xmpd-manifest",
|
"xmpd-manifest",
|
||||||
|
"xmpd-settings",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4369,6 +4427,17 @@ dependencies = [
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xmpd-settings"
|
||||||
|
version = "2.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"egui 0.27.2",
|
||||||
|
"lazy_static",
|
||||||
|
"serde",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus"
|
name = "zbus"
|
||||||
version = "3.15.2"
|
version = "3.15.2"
|
||||||
|
|
|
@ -4,7 +4,9 @@ members=[
|
||||||
"xmpd-core",
|
"xmpd-core",
|
||||||
"xmpd-manifest",
|
"xmpd-manifest",
|
||||||
"xmpd-gui",
|
"xmpd-gui",
|
||||||
"xmpd-cli", "xmpd-dl", "xmpd-derive",
|
#"xmpd-cli",
|
||||||
|
"xmpd-dl",
|
||||||
|
"xmpd-settings",
|
||||||
# "xmpd-tui"
|
# "xmpd-tui"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -25,7 +27,7 @@ bitflags = { version = "2.6.0", features = ["serde"] }
|
||||||
camino = "1.1.6"
|
camino = "1.1.6"
|
||||||
clap = { version = "4.5.4", features = ["derive"] }
|
clap = { version = "4.5.4", features = ["derive"] }
|
||||||
eframe = "0.27.2"
|
eframe = "0.27.2"
|
||||||
egui = { version = "0.27.2", features = ["color-hex"] }
|
egui = { version = "0.27.2", features = ["color-hex", "serde"] }
|
||||||
egui_extras = { version = "0.27.2", features = ["all_loaders"] }
|
egui_extras = { version = "0.27.2", features = ["all_loaders"] }
|
||||||
env_logger = "0.11.3"
|
env_logger = "0.11.3"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
@ -44,4 +46,5 @@ tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread", "process"
|
||||||
url = { version = "2.5.0", features = ["serde"] }
|
url = { version = "2.5.0", features = ["serde"] }
|
||||||
uuid = { version = "1.11.0", features = ["serde", "v4"] }
|
uuid = { version = "1.11.0", features = ["serde", "v4"] }
|
||||||
windows = { version = "0.56.0", features = ["Win32_Foundation", "Win32_Storage_FileSystem", "Win32_System_Console"] }
|
windows = { version = "0.56.0", features = ["Win32_Foundation", "Win32_Storage_FileSystem", "Win32_System_Console"] }
|
||||||
zip-extensions = "0.6.2"
|
zip-extensions = "0.6.20"
|
||||||
|
dirs="5.0.1"
|
||||||
|
|
|
@ -21,11 +21,13 @@ name="xmpd"
|
||||||
path="src/main.rs"
|
path="src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
xmpd-cli={ path="../xmpd-cli" }
|
xmpd-cli.path="../xmpd-cli"
|
||||||
xmpd-gui={ path="../xmpd-gui" }
|
xmpd-gui.path="../xmpd-gui"
|
||||||
xmpd-manifest={ path="../xmpd-manifest" }
|
xmpd-manifest.path="../xmpd-manifest"
|
||||||
|
xmpd-settings.path = "../xmpd-settings"
|
||||||
clap.workspace=true
|
clap.workspace=true
|
||||||
camino.workspace = true
|
camino.workspace = true
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
|
dirs.workspace = true
|
||||||
|
|
|
@ -1,18 +1,75 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::{path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, clap::Parser)]
|
#[derive(Debug, clap::Parser)]
|
||||||
pub struct CliArgs {
|
pub struct CliArgs {
|
||||||
/// Manifest path
|
/// Manifest path
|
||||||
#[arg(long, short)]
|
#[arg(long, short, default_value_t=get_default_manifest_path())]
|
||||||
manifest: Option<camino::Utf8PathBuf>,
|
manifest: camino::Utf8PathBuf,
|
||||||
|
/// settings file path
|
||||||
|
#[arg(long, short, default_value_t=get_default_settings_path())]
|
||||||
|
settings: camino::Utf8PathBuf,
|
||||||
|
/// Cache dir path
|
||||||
|
#[arg(long, short, default_value_t=get_default_cache_path())]
|
||||||
|
cache: camino::Utf8PathBuf,
|
||||||
/// Debug mode
|
/// Debug mode
|
||||||
#[arg(long, short)]
|
#[arg(long, short)]
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliArgs {
|
impl CliArgs {
|
||||||
pub fn manifest_path(&self) -> Option<PathBuf> {
|
pub fn manifest_path(&self) -> PathBuf {
|
||||||
Some(self.manifest.clone()?.into_std_path_buf())
|
self.manifest.clone().into_std_path_buf()
|
||||||
|
}
|
||||||
|
pub fn settings_path(&self) -> PathBuf {
|
||||||
|
self.settings.clone().into_std_path_buf()
|
||||||
|
}
|
||||||
|
pub fn cache_path(&self) -> PathBuf {
|
||||||
|
self.cache.clone().into_std_path_buf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(irrefutable_let_patterns)] // Broken?
|
||||||
|
fn get_default_settings_path() -> camino::Utf8PathBuf {
|
||||||
|
if let Ok(p) = std::env::var("XMPD_SETTINGS_PATH") {
|
||||||
|
if let Ok(p) = camino::Utf8PathBuf::from_str(&p) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(mut p) = dirs::config_dir() {
|
||||||
|
p.push("xmpd");
|
||||||
|
p.push("config.toml");
|
||||||
|
return camino::Utf8PathBuf::from_path_buf(p).expect("Invalid os path");
|
||||||
|
}
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(irrefutable_let_patterns)] // Broken?
|
||||||
|
fn get_default_manifest_path() -> camino::Utf8PathBuf {
|
||||||
|
if let Ok(p) = std::env::var("XMPD_MANIFEST_PATH") {
|
||||||
|
if let Ok(p) = camino::Utf8PathBuf::from_str(&p) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(mut p) = dirs::config_dir() {
|
||||||
|
p.push("xmpd");
|
||||||
|
p.push("manifest.json");
|
||||||
|
return camino::Utf8PathBuf::from_path_buf(p).expect("Invalid os path");
|
||||||
|
}
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(irrefutable_let_patterns)] // Broken?
|
||||||
|
fn get_default_cache_path() -> camino::Utf8PathBuf {
|
||||||
|
if let Ok(p) = std::env::var("XMPD_CACHE_PATH") {
|
||||||
|
if let Ok(p) = camino::Utf8PathBuf::from_str(&p) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(mut p) = dirs::cache_dir() {
|
||||||
|
p.push("xmpd");
|
||||||
|
return camino::Utf8PathBuf::from_path_buf(p).expect("Invalid os path");
|
||||||
|
}
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
|
@ -8,10 +8,11 @@ pub fn init(cliargs: &CliArgs) {
|
||||||
let level = if cliargs.debug { LevelFilter::Debug } else { LevelFilter::Info };
|
let level = if cliargs.debug { LevelFilter::Debug } else { LevelFilter::Info };
|
||||||
env_logger::builder()
|
env_logger::builder()
|
||||||
.format_timestamp(None)
|
.format_timestamp(None)
|
||||||
.filter(Some("xmpd_core"), level)
|
.filter(Some("xmpd"), level)
|
||||||
.filter(Some("xmpd_cli"), level)
|
.filter(Some("xmpd_cli"), level)
|
||||||
.filter(Some("xmpd_gui"), level)
|
.filter(Some("xmpd_gui"), level)
|
||||||
.filter(Some("xmpd_manifest"), level)
|
.filter(Some("xmpd_manifest"), level)
|
||||||
|
.filter(Some("xmpd_config"), level)
|
||||||
.filter(Some("xmpd_dl"), level)
|
.filter(Some("xmpd_dl"), level)
|
||||||
.init();
|
.init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
@ -10,12 +8,8 @@ type Result<T> = anyhow::Result<T>;
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let cliargs = cli::CliArgs::parse();
|
let cliargs = cli::CliArgs::parse();
|
||||||
logger::init(&cliargs);
|
logger::init(&cliargs);
|
||||||
let manifest_path;
|
log::debug!("Cli: {cliargs:?}");
|
||||||
if let Some(mp) = cliargs.manifest_path() {
|
xmpd_settings::Settings::get()?.load(Some(cliargs.settings_path()))?;
|
||||||
manifest_path = mp;
|
xmpd_gui::start(cliargs.manifest_path())?;
|
||||||
} else {
|
|
||||||
manifest_path = PathBuf::from("manifest.json");
|
|
||||||
};
|
|
||||||
xmpd_gui::start(manifest_path)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
use proc_macro::TokenStream;
|
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate quote;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate syn;
|
|
||||||
extern crate proc_macro;
|
|
||||||
|
|
||||||
|
|
||||||
#[proc_macro_derive(UiComponent)]
|
|
||||||
pub fn ui_comp_impl(input: TokenStream) -> TokenStream {
|
|
||||||
let ast: syn::DeriveInput = syn::parse(input).unwrap();
|
|
||||||
|
|
||||||
let name = &ast.ident;
|
|
||||||
let vis = &ast.vis;
|
|
||||||
let attr = &ast.attrs;
|
|
||||||
let data = &ast.data;
|
|
||||||
let generics = &ast.generics;
|
|
||||||
|
|
||||||
let gen = quote! {
|
|
||||||
impl xmp
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
gen.into()
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("Hello, world!");
|
|
||||||
}
|
|
|
@ -19,7 +19,7 @@ bench = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
xmpd-manifest.path = "../xmpd-manifest"
|
xmpd-manifest.path = "../xmpd-manifest"
|
||||||
xmpd-derive.path = "../xmpd-derive"
|
xmpd-settings.path = "../xmpd-settings"
|
||||||
egui.workspace = true
|
egui.workspace = true
|
||||||
eframe.workspace = true
|
eframe.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
|
|
|
@ -43,12 +43,13 @@ impl CompUi for LeftNav {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_playlist_tab(ui: &mut egui::Ui, pid: &Option<uuid::Uuid>, title: &str, author: Option<&str>, song_count: usize, width: f32) {
|
fn add_playlist_tab(ui: &mut egui::Ui, pid: &Option<uuid::Uuid>, title: &str, author: Option<&str>, song_count: usize, width: f32) {
|
||||||
|
let theme = handle_error_ui!(xmpd_settings::Settings::get()).theme.clone();
|
||||||
let wdg_rect = ui.horizontal(|ui| {
|
let wdg_rect = ui.horizontal(|ui| {
|
||||||
ui.set_width(width);
|
ui.set_width(width);
|
||||||
ui.add_space(5.0);
|
ui.add_space(5.0);
|
||||||
ui.add(
|
ui.add(
|
||||||
egui::Image::new(crate::data::NOTE_ICON)
|
egui::Image::new(crate::data::NOTE_ICON)
|
||||||
.tint(crate::data::C_ACCENT)
|
.tint(theme.accent_color)
|
||||||
.fit_to_exact_size(egui::Vec2::new(32.0, 32.0))
|
.fit_to_exact_size(egui::Vec2::new(32.0, 32.0))
|
||||||
);
|
);
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
|
@ -57,7 +58,7 @@ fn add_playlist_tab(ui: &mut egui::Ui, pid: &Option<uuid::Uuid>, title: &str, au
|
||||||
ui.label(
|
ui.label(
|
||||||
RichText::new(title)
|
RichText::new(title)
|
||||||
.size(10.0)
|
.size(10.0)
|
||||||
.color(crate::data::C_ACCENT)
|
.color(theme.accent_color)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
ui.label(
|
ui.label(
|
||||||
|
@ -69,13 +70,13 @@ fn add_playlist_tab(ui: &mut egui::Ui, pid: &Option<uuid::Uuid>, title: &str, au
|
||||||
if let Some(author) = author {
|
if let Some(author) = author {
|
||||||
ui.monospace(
|
ui.monospace(
|
||||||
RichText::new(format!("By {author}"))
|
RichText::new(format!("By {author}"))
|
||||||
.color(crate::data::C_TEXT_DIM)
|
.color(theme.dim_text_color)
|
||||||
.size(8.0)
|
.size(8.0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ui.monospace(
|
ui.monospace(
|
||||||
RichText::new(format!("{song_count} songs"))
|
RichText::new(format!("{song_count} songs"))
|
||||||
.color(crate::data::C_TEXT_DIM)
|
.color(theme.dim_text_color)
|
||||||
.size(8.0)
|
.size(8.0)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::{MutexGuard, PoisonError};
|
use std::sync::MutexGuard;
|
||||||
|
|
||||||
use crate::GuiState;
|
use crate::GuiState;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@ component_register!(Player);
|
||||||
|
|
||||||
|
|
||||||
impl CompUi for Player {
|
impl CompUi for Player {
|
||||||
fn draw(ui: &mut egui::Ui, state: &mut crate::GuiState) -> crate::Result<()> {
|
fn draw(ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> {
|
||||||
|
let theme = xmpd_settings::Settings::get()?.theme.clone();
|
||||||
let avail = ui.available_size();
|
let avail = ui.available_size();
|
||||||
ui.vertical_centered_justified(|ui| {
|
ui.vertical_centered_justified(|ui| {
|
||||||
ui.add_space(3.0);
|
ui.add_space(3.0);
|
||||||
|
@ -25,7 +26,7 @@ impl CompUi for Player {
|
||||||
.show_value(false);
|
.show_value(false);
|
||||||
ui.style_mut().spacing.slider_width = avail.x * 0.90;
|
ui.style_mut().spacing.slider_width = avail.x * 0.90;
|
||||||
let s = Stroke {
|
let s = Stroke {
|
||||||
color: crate::data::C_ACCENT,
|
color: theme.accent_color,
|
||||||
width: 2.0
|
width: 2.0
|
||||||
};
|
};
|
||||||
ui.style_mut().visuals.widgets.inactive.fg_stroke = s;
|
ui.style_mut().visuals.widgets.inactive.fg_stroke = s;
|
||||||
|
@ -45,15 +46,15 @@ impl CompUi for Player {
|
||||||
|
|
||||||
|
|
||||||
let prev = egui::Image::new(crate::data::PREV_ICON)
|
let prev = egui::Image::new(crate::data::PREV_ICON)
|
||||||
.tint(crate::data::C_ACCENT)
|
.tint(theme.accent_color)
|
||||||
.sense(Sense::click())
|
.sense(Sense::click())
|
||||||
.max_size(Vec2::new(16.0, 16.0));
|
.max_size(Vec2::new(16.0, 16.0));
|
||||||
let pp = egui::Image::new(pp)
|
let pp = egui::Image::new(pp)
|
||||||
.tint(crate::data::C_ACCENT)
|
.tint(theme.accent_color)
|
||||||
.sense(Sense::click())
|
.sense(Sense::click())
|
||||||
.max_size(Vec2::new(16.0, 16.0));
|
.max_size(Vec2::new(16.0, 16.0));
|
||||||
let next = egui::Image::new(crate::data::NEXT_ICON)
|
let next = egui::Image::new(crate::data::NEXT_ICON)
|
||||||
.tint(crate::data::C_ACCENT)
|
.tint(theme.accent_color)
|
||||||
.sense(Sense::click())
|
.sense(Sense::click())
|
||||||
.max_size(Vec2::new(16.0, 16.0));
|
.max_size(Vec2::new(16.0, 16.0));
|
||||||
if ui.add(prev).clicked() {}
|
if ui.add(prev).clicked() {}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use egui::{Color32, RichText, Vec2};
|
use egui::{RichText, Vec2};
|
||||||
use song_list_nav::SearchType;
|
use song_list_nav::SearchType;
|
||||||
use xmpd_manifest::{query::QueryType, song::Song, store::BaseStore};
|
use xmpd_manifest::{song::Song, store::BaseStore};
|
||||||
use super::{CompGetter, CompUi};
|
use super::{CompGetter, CompUi};
|
||||||
|
|
||||||
pub mod song_list_nav;
|
pub mod song_list_nav;
|
||||||
|
@ -79,23 +79,23 @@ impl CompUi for SongList {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_song_tab(ui: &mut egui::Ui, sid: &uuid::Uuid, song: &Song) {
|
fn display_song_tab(ui: &mut egui::Ui, sid: &uuid::Uuid, song: &Song) {
|
||||||
|
let theme = handle_error_ui!(xmpd_settings::Settings::get()).theme.clone();
|
||||||
let rct = ui.horizontal(|ui| {
|
let rct = ui.horizontal(|ui| {
|
||||||
ui.add(
|
ui.add(
|
||||||
egui::Image::new(crate::data::NOTE_ICON)
|
egui::Image::new(crate::data::NOTE_ICON)
|
||||||
.tint(crate::data::C_ACCENT)
|
.tint(theme.accent_color)
|
||||||
.fit_to_exact_size(Vec2::new(32.0, 32.0))
|
.fit_to_exact_size(Vec2::new(32.0, 32.0))
|
||||||
);
|
);
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
let selected_song_id = {handle_error_ui!(SongList::get()).selected_song_id};
|
let selected_song_id = {handle_error_ui!(SongList::get()).selected_song_id};
|
||||||
if selected_song_id == *sid {
|
if selected_song_id == *sid {
|
||||||
ui.label(RichText::new(song.name()).color(crate::data::C_ACCENT));
|
ui.label(RichText::new(song.name()).color(theme.accent_color));
|
||||||
} else {
|
} else {
|
||||||
ui.label(song.name());
|
ui.label(song.name());
|
||||||
};
|
};
|
||||||
ui.monospace(
|
ui.monospace(
|
||||||
RichText::new(format!("By {}", song.author()))
|
RichText::new(format!("By {}", song.author()))
|
||||||
.color(crate::data::C_TEXT_DIM)
|
.color(theme.dim_text_color)
|
||||||
.size(10.0)
|
.size(10.0)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,10 +16,11 @@ component_register!(SongListNav);
|
||||||
|
|
||||||
impl CompUi for SongListNav {
|
impl CompUi for SongListNav {
|
||||||
fn draw(ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> {
|
fn draw(ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> {
|
||||||
|
let theme = xmpd_settings::Settings::get()?.theme.clone();
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let search_icon = egui::Image::new(crate::data::SEARCH_ICON)
|
let search_icon = egui::Image::new(crate::data::SEARCH_ICON)
|
||||||
.fit_to_exact_size(egui::Vec2::new(16.0, 16.0))
|
.fit_to_exact_size(egui::Vec2::new(16.0, 16.0))
|
||||||
.tint(crate::data::C_ACCENT);
|
.tint(theme.accent_color);
|
||||||
ui.add(search_icon);
|
ui.add(search_icon);
|
||||||
{
|
{
|
||||||
ui.text_edit_singleline(&mut handle_error_ui!(SongListNav::get()).text);
|
ui.text_edit_singleline(&mut handle_error_ui!(SongListNav::get()).text);
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
use super::CompUi;
|
use super::CompUi;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct TopNav;
|
pub struct TopNav;
|
||||||
|
|
||||||
component_register!(TopNav);
|
|
||||||
|
|
||||||
impl CompUi for TopNav {
|
impl CompUi for TopNav {
|
||||||
fn draw(ui: &mut egui::Ui, state: &mut crate::GuiState) -> crate::Result<()> {
|
fn draw(ui: &mut egui::Ui, state: &mut crate::GuiState) -> crate::Result<()> {
|
||||||
ui.add_space(3.0);
|
ui.add_space(3.0);
|
||||||
|
@ -14,7 +10,15 @@ impl CompUi for TopNav {
|
||||||
ui.add_space(3.0);
|
ui.add_space(3.0);
|
||||||
egui::menu::bar(ui, |ui| {
|
egui::menu::bar(ui, |ui| {
|
||||||
ui.menu_button("File", |ui| {
|
ui.menu_button("File", |ui| {
|
||||||
// TBD
|
if ui.button("Settings").clicked() {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ui.menu_button("Manifest", |ui| {
|
||||||
|
if ui.button("Save").clicked() {
|
||||||
|
handle_error_ui!(state.manifest.save());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
ui.menu_button("Help", |ui| {
|
ui.menu_button("Help", |ui| {
|
||||||
if ui.button("Source").clicked() {
|
if ui.button("Source").clicked() {
|
||||||
|
@ -22,14 +26,9 @@ impl CompUi for TopNav {
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
ui.menu_button("Manifest", |ui| {
|
|
||||||
if ui.button("Save").clicked() {
|
|
||||||
handle_error_ui!(state.manifest.save());
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
// pub const APP_ICON: egui::ImageSource = egui::include_image!("../../assets/app_icon.png");
|
// pub const APP_ICON: egui::ImageSource = egui::include_image!("../../assets/app_icon.png");
|
||||||
pub const APP_ICON_BYTES: &[u8] = include_bytes!("../../assets/app_icon.png");
|
// pub const APP_ICON_BYTES: &[u8] = include_bytes!("../../assets/app_icon.png");
|
||||||
pub const NOTE_ICON: egui::ImageSource = egui::include_image!("../../assets/note.svg");
|
pub const NOTE_ICON: egui::ImageSource = egui::include_image!("../../assets/note.svg");
|
||||||
pub const SEARCH_ICON: egui::ImageSource = egui::include_image!("../../assets/search.svg");
|
pub const SEARCH_ICON: egui::ImageSource = egui::include_image!("../../assets/search.svg");
|
||||||
pub const PREV_ICON: egui::ImageSource = egui::include_image!("../../assets/prev.svg");
|
pub const PREV_ICON: egui::ImageSource = egui::include_image!("../../assets/prev.svg");
|
||||||
pub const NEXT_ICON: egui::ImageSource = egui::include_image!("../../assets/next.svg");
|
pub const NEXT_ICON: egui::ImageSource = egui::include_image!("../../assets/next.svg");
|
||||||
pub const PLAY_ICON: egui::ImageSource = egui::include_image!("../../assets/play.svg");
|
pub const PLAY_ICON: egui::ImageSource = egui::include_image!("../../assets/play.svg");
|
||||||
pub const PAUSE_ICON: egui::ImageSource = egui::include_image!("../../assets/pause.svg");
|
pub const PAUSE_ICON: egui::ImageSource = egui::include_image!("../../assets/pause.svg");
|
||||||
|
|
||||||
|
|
||||||
// TODO: Replace this with config for theming
|
|
||||||
// pub const C_ACCENT: egui::Color32 = egui::Color32::from_rgb(51, 51, 119);
|
|
||||||
pub const C_ACCENT: egui::Color32 = egui::Color32::from_rgb(5, 102, 146); // #0566F6
|
|
||||||
pub const C_PRIM_BG: egui::Color32 = egui::Color32::from_rgb(31, 34, 40); // #1F2228
|
|
||||||
pub const C_SEC_BG: egui::Color32 = egui::Color32::from_rgb(47, 53, 61); // #2f353d
|
|
||||||
pub const C_TEXT: egui::Color32 = egui::Color32::from_rgb(223, 223, 223); // #dfdfdf
|
|
||||||
pub const C_TEXT_DIM: egui::Color32 = egui::Color32::from_rgb(175, 175, 175 ); // #afafaf
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#![feature(async_closure)]
|
#![feature(async_closure)]
|
||||||
|
|
||||||
use std::{path::{Path, PathBuf}, time::Duration};
|
use std::{path::{Path, PathBuf}, time::Duration};
|
||||||
use egui::TextStyle;
|
|
||||||
use windows::WindowId;
|
|
||||||
use xmpd_manifest::{store::JsonStore, Manifest};
|
use xmpd_manifest::{store::JsonStore, Manifest};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -20,21 +18,21 @@ type Result<T> = anyhow::Result<T>;
|
||||||
pub fn start(manifest_path: PathBuf) -> Result<()> {
|
pub fn start(manifest_path: PathBuf) -> Result<()> {
|
||||||
let options = eframe::NativeOptions::default();
|
let options = eframe::NativeOptions::default();
|
||||||
let mut state = GuiState::new(&manifest_path)?;
|
let mut state = GuiState::new(&manifest_path)?;
|
||||||
|
let theme = xmpd_settings::Settings::get()?.theme.clone();
|
||||||
let res = eframe::run_simple_native(W_NAME, options, move |ctx, _frame| {
|
let res = eframe::run_simple_native(W_NAME, options, move |ctx, _frame| {
|
||||||
egui_extras::install_image_loaders(ctx);
|
egui_extras::install_image_loaders(ctx);
|
||||||
state.windows.clone().draw_all(ctx, &mut state);
|
state.windows.clone().draw_all(ctx, &mut state);
|
||||||
egui::CentralPanel::default()
|
egui::CentralPanel::default()
|
||||||
.frame(
|
.frame(
|
||||||
egui::Frame::none()
|
egui::Frame::none()
|
||||||
.fill(data::C_PRIM_BG)
|
.fill(theme.primary_bg_color)
|
||||||
.stroke(egui::Stroke::new(
|
.stroke(egui::Stroke::new(
|
||||||
1.0,
|
1.0,
|
||||||
data::C_SEC_BG,
|
theme.secondary_bg_color,
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
ui.style_mut().visuals.override_text_color = Some(crate::data::C_TEXT);
|
ui.style_mut().visuals.override_text_color = Some(theme.text_color);
|
||||||
main_window::draw(ui, &mut state)
|
main_window::draw(ui, &mut state)
|
||||||
});
|
});
|
||||||
ctx.request_repaint_after(Duration::from_millis(500));
|
ctx.request_repaint_after(Duration::from_millis(500));
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
use egui::ViewportId;
|
use crate::{components::CompUi, GuiState};
|
||||||
use xmpd_manifest::store::JsonStore;
|
|
||||||
|
|
||||||
use crate::{components::{CompGetter, CompUi}, GuiState};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn draw(ui: &mut egui::Ui, state: &mut GuiState) -> crate::Result<()> {
|
pub fn draw(ui: &mut egui::Ui, state: &mut GuiState) -> crate::Result<()> {
|
||||||
// The central panel the region left after adding TopPanel's and SidePanel's
|
// The central panel the region left after adding TopPanel's and SidePanel's
|
||||||
// ui.heading(format!("Songs ({})", self.manifest.get_song_count()));
|
// ui.heading(format!("Songs ({})", self.manifest.get_song_count()));
|
||||||
|
let theme = xmpd_settings::Settings::get()?.theme.clone();
|
||||||
let avail = ui.available_size();
|
let avail = ui.available_size();
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
handle_error_ui!(crate::components::top_nav::TopNav::draw(ui, state));
|
handle_error_ui!(crate::components::top_nav::TopNav::draw(ui, state));
|
||||||
crate::utils::super_separator(ui, crate::data::C_ACCENT, avail.x, 2.0);
|
crate::utils::super_separator(ui, theme.accent_color, avail.x, 2.0);
|
||||||
let avail = ui.available_size();
|
let avail = ui.available_size();
|
||||||
let main_height = avail.y * 0.91;
|
let main_height = avail.y * 0.91;
|
||||||
|
|
||||||
|
@ -35,15 +31,15 @@ pub fn draw(ui: &mut egui::Ui, state: &mut GuiState) -> crate::Result<()> {
|
||||||
egui::TopBottomPanel::new(egui::panel::TopBottomSide::Bottom, "player")
|
egui::TopBottomPanel::new(egui::panel::TopBottomSide::Bottom, "player")
|
||||||
.frame(
|
.frame(
|
||||||
egui::Frame::none()
|
egui::Frame::none()
|
||||||
.fill(crate::data::C_PRIM_BG)
|
.fill(theme.primary_bg_color)
|
||||||
.stroke(egui::Stroke::new(
|
.stroke(egui::Stroke::new(
|
||||||
1.0,
|
1.0,
|
||||||
crate::data::C_SEC_BG,
|
theme.secondary_bg_color,
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
.show(ui.ctx(), |ui| {
|
.show(ui.ctx(), |ui| {
|
||||||
|
|
||||||
ui.style_mut().visuals.override_text_color = Some(crate::data::C_TEXT);
|
ui.style_mut().visuals.override_text_color = Some(theme.accent_color);
|
||||||
handle_error_ui!(crate::components::player::Player::draw(ui, state));
|
handle_error_ui!(crate::components::player::Player::draw(ui, state));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
pub fn super_separator(ui: &mut egui::Ui, color: egui::Color32, width: f32, height: f32) {
|
pub fn super_separator(ui: &mut egui::Ui, color: egui::Color32, width: f32, height: f32) {
|
||||||
egui::Frame::none()
|
egui::Frame::none()
|
||||||
.fill(color)
|
.fill(color)
|
||||||
// .stroke(egui::Stroke { color: crate::data::C_ACCENT, width: 1.0 })
|
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
ui.set_width(width);
|
ui.set_width(width);
|
||||||
ui.set_height(height);
|
ui.set_height(height);
|
||||||
|
|
|
@ -7,7 +7,7 @@ pub struct ErrorW {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window for ErrorW {
|
impl Window for ErrorW {
|
||||||
fn draw(&self, ui: &mut egui::Ui, state: &mut crate::GuiState) -> crate::Result<()> {
|
fn draw(&self, ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> {
|
||||||
ui.label("Hello from other window!");
|
ui.label("Hello from other window!");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use std::{collections::{HashMap, HashSet}, ops::Deref, sync::{Arc, Mutex}};
|
use std::{collections::{HashMap, HashSet}, sync::{Arc, Mutex}};
|
||||||
use egui::{ViewportBuilder, ViewportId};
|
use egui::{ViewportBuilder, ViewportId};
|
||||||
use crate::GuiState;
|
use crate::GuiState;
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
|
mod settings;
|
||||||
|
|
||||||
lazy_static::lazy_static!(
|
lazy_static::lazy_static!(
|
||||||
static ref WINDOWS: Arc<Mutex<HashMap<WindowId, Box<dyn Window>>>> = Arc::new(Mutex::new(HashMap::new()));
|
static ref WINDOWS: Arc<Mutex<HashMap<WindowId, Box<dyn Window>>>> = Arc::new(Mutex::new(HashMap::new()));
|
||||||
|
@ -16,6 +17,7 @@ pub trait Window: std::fmt::Debug + Send {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)]
|
#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)]
|
||||||
pub enum WindowId {
|
pub enum WindowId {
|
||||||
|
Settings,
|
||||||
Error
|
Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +51,6 @@ impl Windows {
|
||||||
if self.is_open(&win_id) {
|
if self.is_open(&win_id) {
|
||||||
ctx.show_viewport_immediate(vp_id.clone(), builder.clone(), |ctx, _vp_class| {
|
ctx.show_viewport_immediate(vp_id.clone(), builder.clone(), |ctx, _vp_class| {
|
||||||
ctx.input(|inp| {
|
ctx.input(|inp| {
|
||||||
// println!("CLose requested: {}",inp.viewport().close_requested() );
|
|
||||||
self.toggle(win_id, !inp.viewport().close_requested());
|
self.toggle(win_id, !inp.viewport().close_requested());
|
||||||
});
|
});
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
|
14
xmpd-gui/src/windows/settings.rs
Normal file
14
xmpd-gui/src/windows/settings.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
use super::Window;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SettingsW {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Window for SettingsW {
|
||||||
|
fn draw(&self, ui: &mut egui::Ui, _: &mut crate::GuiState) -> crate::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,14 @@
|
||||||
[package]
|
[package]
|
||||||
name = "xmpd-derive"
|
name = "xmpd-settings"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
repository.workspace = true
|
repository.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
|
|
||||||
[lib]
|
|
||||||
proc-macro=true
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quote = "1.0.37"
|
anyhow.workspace = true
|
||||||
syn = "2.0.87"
|
egui.workspace = true
|
||||||
# xmpd-gui.path = "../xmpd-gui"
|
lazy_static.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
toml = "0.8.19"
|
49
xmpd-settings/src/lib.rs
Normal file
49
xmpd-settings/src/lib.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
use std::{path::PathBuf, sync::{Arc, Mutex, MutexGuard}};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use theme::Theme;
|
||||||
|
|
||||||
|
mod theme;
|
||||||
|
|
||||||
|
lazy_static::lazy_static!(
|
||||||
|
static ref SETTINGS: Arc<Mutex<Settings>> = Arc::new(Mutex::new(Settings::default()));
|
||||||
|
);
|
||||||
|
|
||||||
|
pub type Result<T> = anyhow::Result<T>;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct Settings {
|
||||||
|
#[serde(skip)]
|
||||||
|
settings_path: PathBuf,
|
||||||
|
pub theme: Theme,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Settings {
|
||||||
|
pub fn get() -> crate::Result<MutexGuard<'static, Self>> {
|
||||||
|
match SETTINGS.lock() {
|
||||||
|
Ok(l) => Ok(l),
|
||||||
|
Err(e) => Err(anyhow::anyhow!(format!("{e:?}"))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn load(&mut self, path: Option<PathBuf>) -> Result<()> {
|
||||||
|
let path = path.unwrap_or(self.settings_path.clone());
|
||||||
|
if !path.exists() {
|
||||||
|
std::fs::write(&path, "[theme]")?;
|
||||||
|
self.save(Some(path.clone()))?;
|
||||||
|
}
|
||||||
|
let data = std::fs::read_to_string(&path)?;
|
||||||
|
let data: Self = toml::from_str(&data)?;
|
||||||
|
*self = data;
|
||||||
|
self.settings_path = path;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&mut self, path: Option<PathBuf>) -> Result<()> {
|
||||||
|
let path = path.unwrap_or(self.settings_path.clone());
|
||||||
|
let data = toml::to_string_pretty(&self)?;
|
||||||
|
std::fs::write(&path, data)?;
|
||||||
|
self.settings_path = path;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
47
xmpd-settings/src/theme.rs
Normal file
47
xmpd-settings/src/theme.rs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Theme {
|
||||||
|
#[serde(default="Theme::default_accent_color")]
|
||||||
|
pub accent_color: egui::Color32,
|
||||||
|
#[serde(default="Theme::default_primary_bg_color")]
|
||||||
|
pub primary_bg_color: egui::Color32,
|
||||||
|
#[serde(default="Theme::default_secondary_bg_color")]
|
||||||
|
pub secondary_bg_color: egui::Color32,
|
||||||
|
#[serde(default="Theme::default_text_color")]
|
||||||
|
pub text_color: egui::Color32,
|
||||||
|
#[serde(default="Theme::default_dim_text_color")]
|
||||||
|
pub dim_text_color: egui::Color32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Theme {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
accent_color: Self::default_accent_color(),
|
||||||
|
primary_bg_color: Self::default_primary_bg_color(),
|
||||||
|
secondary_bg_color: Self::default_secondary_bg_color(),
|
||||||
|
text_color: Self::default_text_color(),
|
||||||
|
dim_text_color: Self::default_dim_text_color(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Theme {
|
||||||
|
fn default_accent_color() -> egui::Color32 {
|
||||||
|
egui::Color32::from_rgb(5, 102, 146) // #0566F6
|
||||||
|
}
|
||||||
|
fn default_primary_bg_color() -> egui::Color32 {
|
||||||
|
egui::Color32::from_rgb(31, 34, 40) // #1F2228
|
||||||
|
}
|
||||||
|
fn default_secondary_bg_color() -> egui::Color32 {
|
||||||
|
egui::Color32::from_rgb(47, 53, 61) // #2f353d
|
||||||
|
}
|
||||||
|
fn default_text_color() -> egui::Color32 {
|
||||||
|
egui::Color32::from_rgb(223, 223, 223) // #dfdfdf
|
||||||
|
}
|
||||||
|
fn default_dim_text_color() -> egui::Color32 {
|
||||||
|
egui::Color32::from_rgb(175, 175, 175 ) // #afafaf
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user