Skip to content

Commit

Permalink
Configuration modifications
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Brue <[email protected]>
  • Loading branch information
ryanabx committed Sep 22, 2024
1 parent f14f9f4 commit fa083bf
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 87 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ wayland-protocols-wlr = { version = "0.3.3", features = ["client"] }
smithay-client-toolkit = "0.19.2"
wayland-protocols-plasma = { version = "0.3.3", features = ["client"] }
async-std = "1.13.0"
anyhow = "1.0.89"
4 changes: 3 additions & 1 deletion res/rbshell.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"app_tray": {
"favorites": [
"org.mozilla.firefox"
"org.mozilla.firefox",
"org.mozilla.Thunderbird",
"im.riot.Riot"
]
}
}
31 changes: 19 additions & 12 deletions src/app_tray/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::{collections::HashMap, rc::Rc};
use std::{
collections::HashMap,
rc::Rc,
sync::{Arc, Mutex},
};

use super::freedesktop::desktop_entry::DesktopEntryCache;
use cctk::wayland_client::protocol::wl_seat::WlSeat;
Expand All @@ -8,9 +12,11 @@ use compositor::{
use iced::{Element, Task};

use crate::{
config::AppTrayConfig,
design::component_theme::{button_style, PANEL_SIZE},
design::components::app_tray_button,
config::PanelConfig,
design::{
component_theme::{button_style, PANEL_SIZE},
components::app_tray_button,
},
freedesktop::desktop_entry::EntryInfo,
};

Expand All @@ -20,7 +26,7 @@ pub mod compositor;
pub struct AppTray<'a> {
de_cache: Rc<DesktopEntryCache<'a>>,
backend: CompositorBackend,
config: AppTrayConfig,
config: Arc<Mutex<PanelConfig>>,
}

#[derive(Clone, Debug)]
Expand All @@ -33,7 +39,7 @@ pub enum AppTrayMessage {
}

impl<'a> AppTray<'a> {
pub fn new(config: AppTrayConfig, de_cache: Rc<DesktopEntryCache<'a>>) -> Self {
pub fn new(config: Arc<Mutex<PanelConfig>>, de_cache: Rc<DesktopEntryCache<'a>>) -> Self {
Self {
de_cache,
backend: CompositorBackend::new(),
Expand All @@ -44,8 +50,10 @@ impl<'a> AppTray<'a> {
pub fn view(&self) -> iced::Element<AppTrayMessage> {
let active_window = self.backend.active_window();
// Get app tray apps
let app_tray_apps = self
.config
let panel_config = self.config.lock().unwrap().clone();
let app_tray_apps = panel_config
.inner
.app_tray
.favorites
.iter()
.map(|x| {
Expand All @@ -64,7 +72,7 @@ impl<'a> AppTray<'a> {
.active_toplevels
.iter()
.filter_map(|(app_id, info)| {
if self.config.favorites.contains(app_id) {
if panel_config.inner.app_tray.favorites.contains(app_id) {
None
} else {
Some((app_id.clone(), info.clone()))
Expand Down Expand Up @@ -112,7 +120,6 @@ impl<'a> AppTray<'a> {
self.backend
.wayland_subscription()
.map(AppTrayMessage::WaylandIn)
// iced::Subscription::none()
}

fn view_tray_item(
Expand All @@ -127,10 +134,10 @@ impl<'a> AppTray<'a> {
}
let is_active = active_window.is_some_and(|window| app_info.contains_key(&window));
let num_toplevels = app_info.len();
let icon_path = entry.and_then(|e| e.icon_path.as_deref());
let image_handle = entry.and_then(|e| e.entry_image.clone());
Some(
iced::widget::mouse_area(
app_tray_button(icon_path, is_active, num_toplevels, false)
app_tray_button(image_handle, is_active, num_toplevels, false)
.on_press_maybe(if num_toplevels == 0 {
entry
.and_then(|entry| entry.desktop_entry.exec())
Expand Down
47 changes: 27 additions & 20 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{
fs::File,
io::{self, Read},
path::Path,
path::{Path, PathBuf},
};

use serde::{Deserialize, Serialize};
Expand All @@ -16,42 +16,49 @@ pub enum ConfigError {
Serde(#[from] serde_json::Error),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone)]
pub struct PanelConfig {
pub app_tray: AppTrayConfig,
pub icon_theme: IconTheme,
pub use_winit: bool,
pub inner: InnerConfig,
file_path: PathBuf,
}

impl Default for PanelConfig {
fn default() -> Self {
Self {
app_tray: Default::default(),
icon_theme: Default::default(),
use_winit: Default::default(),
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct InnerConfig {
pub app_tray: AppTrayConfig,
pub icon_theme: Option<IconTheme>,
pub use_winit: Option<bool>,
}

impl PanelConfig {
pub fn from_file_or_default(path: &Path) -> Self {
File::open(path)
let inner_res = File::open(path)
.map_err(ConfigError::IO)
.and_then(|mut res| {
let mut data = String::new();
res.read_to_string(&mut data)
.map(|_| data)
.map_err(ConfigError::IO)
})
.and_then(|val| -> Result<Self, ConfigError> {
.and_then(|val| -> Result<InnerConfig, ConfigError> {
serde_json::from_str(&val).map_err(ConfigError::Serde)
})
.unwrap_or_default()
});
match inner_res {
Ok(_) => {
log::info!("Successfully loaded config from {}", path.display());
}
Err(ref e) => {
log::warn!("Could not load config from {}: {}", path.display(), e);
}
}
Self {
inner: inner_res.unwrap_or_default(),
file_path: path.to_path_buf(),
}
}

pub fn _save_to_file(&self, path: &Path) -> Result<(), ConfigError> {
let data = serde_json::to_string_pretty(self)?;
std::fs::write(path, data)?;
pub fn save_to_file(&self) -> Result<(), ConfigError> {
let data = serde_json::to_string_pretty(&self.inner)?;
std::fs::write(&self.file_path, data)?;
Ok(())
}
}
Expand Down
25 changes: 12 additions & 13 deletions src/design/components.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use std::path::Path;

use iced::{
widget::{column, Container},
Element, Length, Theme,
Length, Theme,
};

use crate::freedesktop::icons::ImageHandle;

use super::component_theme::app_tray_icon_rule;

pub fn app_tray_button<'a, T: 'a>(
icon_path: Option<&Path>,
icon_path: Option<ImageHandle>,
is_active: bool,
num_toplevels: usize,
is_start_menu: bool,
Expand Down Expand Up @@ -47,20 +47,19 @@ fn app_tray_horizontal_rule<'a, T: 'a>(
.center_x(Length::Fill)
}

pub fn app_icon<'a, T>(icon_path: &Path) -> iced::Element<'a, T> {
if icon_path.extension().is_some_and(|x| x == "svg") {
Element::from(
iced::widget::svg(icon_path)
pub fn app_icon<'a, T>(image_handle: ImageHandle) -> iced::widget::Container<'a, T> {
match image_handle {
ImageHandle::Svg(handle) => iced::widget::container(
iced::widget::svg(handle)
.content_fit(iced::ContentFit::Contain)
.width(Length::Fill)
.height(Length::Fill),
)
} else {
Element::from(
iced::widget::image(icon_path)
),
ImageHandle::Image(handle) => iced::widget::container(
iced::widget::image(handle)
.content_fit(iced::ContentFit::Contain)
.width(Length::Fill)
.height(Length::Fill),
)
),
}
}
30 changes: 17 additions & 13 deletions src/freedesktop/desktop_entry.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use std::{collections::HashMap, path::PathBuf};
use std::collections::HashMap;

use freedesktop_desktop_entry::{
default_paths, get_languages_from_env, DesktopEntry, Iter, Locale, PathSource,
};

use super::icons::{default_icon_path, IconTheme};
use super::icons::{default_icon_path, IconTheme, ImageHandle};

#[derive(Clone, Debug)]
pub struct DesktopEntryCache<'a>(pub HashMap<String, EntryInfo<'a>>);

#[derive(Clone, Debug)]
pub struct EntryInfo<'a> {
pub desktop_entry: DesktopEntry<'a>,
pub icon_path: Option<PathBuf>,
pub entry_image: Option<ImageHandle>,
pub invisible: bool,
}

Expand All @@ -26,18 +26,22 @@ impl<'a> EntryInfo<'a> {
let icon_path = if invisible {
None
} else {
desktop_entry.icon().and_then(|icon| {
freedesktop_icons::lookup(icon)
.with_theme("hicolor")
.force_svg()
.find()
.or_else(|| freedesktop_icons::lookup(icon).with_theme("hicolor").find())
.or_else(|| default_icon_path(&icon_theme))
})
desktop_entry
.icon()
.and_then(|icon| {
freedesktop_icons::lookup(icon)
.with_theme("hicolor")
.force_svg()
.find()
.or_else(|| freedesktop_icons::lookup(icon).with_theme("hicolor").find())
.or_else(|| default_icon_path(icon_theme))
})
.as_deref()
.map(ImageHandle::from_path)
};
Self {
desktop_entry,
icon_path,
entry_image: icon_path,
invisible,
}
}
Expand All @@ -52,7 +56,7 @@ impl<'a> DesktopEntryCache<'a> {
let path_src = PathSource::guess_from(&path);
if let Ok(entry) = DesktopEntry::from_path(path.clone(), &locales) {
log::trace!("{:?}::{}", path_src, &entry.appid);
return Some((entry.appid.to_string(), EntryInfo::new(entry, &icon_theme)));
return Some((entry.appid.to_string(), EntryInfo::new(entry, icon_theme)));
}
None
})
Expand Down
21 changes: 20 additions & 1 deletion src/freedesktop/icons.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::{env, path::PathBuf};
use std::{
env,
path::{Path, PathBuf},
};

use serde::{Deserialize, Serialize};

Expand All @@ -9,6 +12,22 @@ pub enum IconTheme {
None,
}

#[derive(Clone, Debug)]
pub enum ImageHandle {
Svg(iced::widget::svg::Handle),
Image(iced::widget::image::Handle),
}

impl ImageHandle {
pub fn from_path(path: &Path) -> Self {
if path.extension().is_some_and(|extension| extension == "svg") {
Self::Svg(iced::widget::svg::Handle::from_path(path))
} else {
Self::Image(iced::widget::image::Handle::from_path(path))
}
}
}

impl Default for IconTheme {
fn default() -> Self {
// guess icon theme
Expand Down
25 changes: 15 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{
env,
path::{Path, PathBuf},
sync::{Arc, Mutex},
};

use clap::Parser;
Expand Down Expand Up @@ -45,26 +46,30 @@ enum PanelError {
Config(#[from] ConfigError),
#[error("Iced: {0}")]
Iced(#[from] iced::Error),
#[error("Mutex poison on config")]
MutexPoison,
}

fn main() -> Result<(), PanelError> {
fn main() -> anyhow::Result<()> {
env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init();
let args = CliArgs::parse();
log::trace!("Received args: {:?}", args);
let config = PanelConfig::from_file_or_default(
&args
.config
.unwrap_or(Path::new(&env::var("HOME").unwrap()).join(".config/rbshell/config.json")),
);

let config_path = args
.config
.unwrap_or(Path::new(&env::var("HOME").unwrap()).join(".config/rbshell/config.json"));
let config = Arc::new(Mutex::new(PanelConfig::from_file_or_default(&config_path)));
let config_handle = config.clone();
let res = iced::daemon(Panel::title, Panel::update, Panel::view)
// iced::application(Panel::title, Panel::update, Panel::view)
.subscription(Panel::subscription)
// // .window_size((1280.0, 48.0))
.theme(Panel::theme)
// .decorations(false)
.run_with(|| Panel::new(config))
.run_with(|| Panel::new(config_handle))
.map_err(PanelError::Iced);

res
let _ = config
.lock()
.map_err(|_| PanelError::MutexPoison)?
.save_to_file();
Ok(res?)
}
Loading

0 comments on commit fa083bf

Please sign in to comment.