Skip to content

Commit

Permalink
feat(config): add support for configurable parameters in RON format
Browse files Browse the repository at this point in the history
- Bumped version from 0.1.10-alpha to 0.1.11-alpha in Cargo.toml
- Added new dependency `ron = "0.8"` to Cargo.toml
- Introduced a new configuration file format (`config.ron`) with various parameters like `expire_timeout`, `icon_size`, `log_level`, and more
- Created a `Config` struct to manage application settings and implement defaults
- Replaced various hard-coded configuration values with dynamic values from the new configuration
- Updated README.md to include information on the new configuration file
- Made GUI components configurable based on user-defined settings in `config.ron`
  • Loading branch information
bzglve committed Sep 3, 2024
1 parent fa331fc commit 9fde284
Show file tree
Hide file tree
Showing 11 changed files with 391 additions and 83 deletions.
24 changes: 23 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rustyfications"
version = "0.1.10-alpha"
version = "0.1.11-alpha"
edition = "2021"
authors = ["bzglve"]

Expand All @@ -16,6 +16,7 @@ sys_logger = { version = "2.1", package = "systemd-journal-logger" }

# common
futures = "0.3"
ron = "0.8"
serde = { version = "1.0", features = ["derive"] }
time = { version = "0.3", features = ["local-offset"] }
zbus = "4.4"
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,17 @@ sudo cp target/release/rustyfications /usr/bin/rustyfications

From now you don't need to manually start daemon. It will be activated automatically on any client request

## Configuration

Default configuration provided in example [config.ron](examples/config/config.ron). It should be placed in user config dir either systems ( `~/.config/rustyfications/config.ron` / `/etc/xdg/rustyfications/config.ron` )

## Planning

- configuration
- more capabilities and hints support
- styling customization
- ipc like stuff to call already running daemon
- [SwayNotificationCcenter](https://github.com/ErikReider/SwayNotificationCenter)-like sidebar window
- [SwayNotificationCenter](https://github.com/ErikReider/SwayNotificationCenter)-like sidebar window
- packaging

## Motivation
Expand All @@ -70,4 +75,4 @@ Practice myself and write something that I will use every day.

Other tools don't quite meet my needs.

Highly inspired by [SwayNotificationCcenter](https://github.com/ErikReider/SwayNotificationCenter)
Highly inspired by [SwayNotificationCenter](https://github.com/ErikReider/SwayNotificationCenter)
42 changes: 42 additions & 0 deletions examples/config/config.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
(
// we are respect freedesktop timeouts
// this parameter is for notification with undefined expiration
expire_timeout: 5000,

icon_size: 72,

// Off, Error, Warn, Info, Debug, Trace
log_level: Info,

show_app_name: false,

// that icon is used in upper right corner
window_close_icon: "window-close",

// some action keys can not have matching icon names
// that map used as an alias for buttons icons
icon_redefines: {
"inline-reply": "mail-reply",
"dismiss": "window-close",
},

// most recent notifications appears from anchored edge
new_on_top: true,

// (width, height)
// (410, 30) - optimal size for display 40 characters in 12px font with 5px window "padding"
window_size: (410, 30),

// window anchors (position)
// Left, Right, Top, Bottom
// using two opposite anchors to stretch window(s) is not allowed
edges: [Top, Right],

// margins is used for spacing between windows
// the order is just like in `edges` field
margins: [5, 5],

// paddings is used for spacing all notifications from the edges
// the order is just like in `edges` field
paddings: [5, 0],
)
221 changes: 221 additions & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
use std::{
collections::HashMap,
fs,
sync::{LazyLock, Mutex},
};

use defaults::*;
use edge::Edge;
use gtk::glib;
use level_filter::LevelFilter;
use serde::{Deserialize, Serialize};

pub mod level_filter {
use super::*;

use log::LevelFilter as LogLevelFilter;

#[derive(Debug, Deserialize, Serialize, Clone, Copy)]
pub enum LevelFilter {
Off,
Error,
Warn,
Info,
Debug,
Trace,
}

impl Default for LevelFilter {
fn default() -> Self {
Self::Info
}
}

impl From<LevelFilter> for LogLevelFilter {
fn from(value: LevelFilter) -> Self {
match value {
LevelFilter::Off => Self::Off,
LevelFilter::Error => Self::Error,
LevelFilter::Warn => Self::Warn,
LevelFilter::Info => Self::Info,
LevelFilter::Debug => Self::Debug,
LevelFilter::Trace => Self::Trace,
}
}
}
}

pub mod edge {
use serde::{Deserialize, Serialize};

#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Edge {
Left,
Right,
Top,
Bottom,
}

impl From<Edge> for gtk_layer_shell::Edge {
fn from(value: Edge) -> Self {
match value {
Edge::Left => gtk_layer_shell::Edge::Left,
Edge::Right => gtk_layer_shell::Edge::Right,
Edge::Top => gtk_layer_shell::Edge::Top,
Edge::Bottom => gtk_layer_shell::Edge::Bottom,
}
}
}
}

mod defaults {
use std::collections::HashMap;

use super::{edge::Edge, level_filter::LevelFilter};

pub fn expire_timeout() -> u64 {
5000
}

pub fn new_on_top() -> bool {
true
}

pub fn icon_size() -> i32 {
72
}

pub fn log_level() -> LevelFilter {
LevelFilter::Info
}

pub fn window_close_icon() -> String {
"window-close".to_owned()
}

pub fn show_app_name() -> bool {
false
}

pub fn window_size() -> (i32, i32) {
(410, 30)
}

pub fn icon_redefines() -> HashMap<String, String> {
HashMap::new()
}

pub fn edges() -> Vec<Edge> {
vec![Edge::Top, Edge::Right]
}

pub fn margins() -> Vec<i32> {
vec![5, 5]
}

pub fn paddings() -> Vec<i32> {
vec![5, 0]
}
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Config {
#[serde(default = "expire_timeout")]
pub expire_timeout: u64,

#[serde(default = "new_on_top")]
pub new_on_top: bool,

#[serde(default = "icon_size")]
pub icon_size: i32,

#[serde(default = "log_level")]
pub log_level: LevelFilter,

#[serde(default = "window_close_icon")]
pub window_close_icon: String,

#[serde(default = "show_app_name")]
pub show_app_name: bool,

#[serde(default = "window_size")]
pub window_size: (i32, i32),

#[serde(default = "icon_redefines")]
pub icon_redefines: HashMap<String, String>,

#[serde(default = "edges")]
pub edges: Vec<Edge>,

#[serde(default = "margins")]
pub margins: Vec<i32>,

#[serde(default = "paddings")]
pub paddings: Vec<i32>,
}

impl Config {
pub fn new() -> Option<Config> {
let path;

let user_config = glib::user_config_dir()
.join("rustyfications")
.join("config.ron");

if user_config.exists() {
path = user_config;
} else if let Some(system_config) = glib::system_config_dirs().first() {
let system_config = system_config
.to_path_buf()
.join("rustyfications")
.join("config.ron");
if system_config.exists() {
path = system_config;
} else {
return None;
}
} else {
return None;
}

println!("Found config file {:?}", path);
match ron::from_str::<Self>(&fs::read_to_string(path.clone()).unwrap()) {
Ok(r) => {
if r.edges.contains(&Edge::Left) && r.edges.contains(&Edge::Right)
|| r.edges.contains(&Edge::Top) && r.edges.contains(&Edge::Bottom)
{
eprintln!("Using two opposite edges is not allowed");
println!("Using default configuration");
return None;
}
Some(r)
}
Err(e) => {
eprintln!("{}", e);
println!("Using default configuration");
None
}
}
}
}

impl Default for Config {
fn default() -> Self {
Self {
expire_timeout: expire_timeout(),
new_on_top: new_on_top(),
icon_size: icon_size(),
log_level: log_level(),
window_close_icon: window_close_icon(),
show_app_name: show_app_name(),
window_size: window_size(),
icon_redefines: icon_redefines(),
edges: edges(),
margins: margins(),
paddings: paddings(),
}
}
}

pub static CONFIG: LazyLock<Mutex<Config>> =
LazyLock::new(|| Mutex::new(Config::new().unwrap_or_default()));
4 changes: 2 additions & 2 deletions src/dbus/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use zbus::{
zvariant::{OwnedValue as Value, Type},
};

use crate::DEFAULT_EXPIRE_TIMEOUT;
use crate::config::CONFIG;

static BUS_NAME: &str = "org.freedesktop.Notifications";
static BUS_OBJECT_PATH: &str = "/org/freedesktop/Notifications";
Expand Down Expand Up @@ -144,7 +144,7 @@ impl IFace {
.collect(),
hints,
expire_timeout: match expire_timeout.cmp(&0) {
Ordering::Less => DEFAULT_EXPIRE_TIMEOUT,
Ordering::Less => Duration::from_millis(CONFIG.lock().unwrap().expire_timeout),
Ordering::Equal => Duration::MAX,
Ordering::Greater => Duration::from_millis(expire_timeout as u64),
},
Expand Down
Loading

0 comments on commit 9fde284

Please sign in to comment.