mirror of
https://github.com/danbulant/rshell
synced 2026-05-21 13:28:48 +00:00
workspace and memory support
This commit is contained in:
parent
715527b138
commit
ecf63c0e3b
9 changed files with 377 additions and 68 deletions
23
Cargo.lock
generated
23
Cargo.lock
generated
|
|
@ -1,6 +1,6 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "ab_glyph"
|
||||
|
|
@ -724,6 +724,12 @@ version = "1.9.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
|
||||
|
||||
[[package]]
|
||||
name = "bytesize"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc"
|
||||
|
||||
[[package]]
|
||||
name = "cacache"
|
||||
version = "13.1.0"
|
||||
|
|
@ -4323,6 +4329,7 @@ dependencies = [
|
|||
"plotters",
|
||||
"reqwest",
|
||||
"reqwest-middleware",
|
||||
"systemstat",
|
||||
"tokio",
|
||||
"which",
|
||||
]
|
||||
|
|
@ -4905,6 +4912,20 @@ dependencies = [
|
|||
"version-compare",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "systemstat"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "668a4db78b439df482c238f559e4ea869017f9e62ef0a059c8bfcd841a4df544"
|
||||
dependencies = [
|
||||
"bytesize",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"nom",
|
||||
"time",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.16"
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ pipewire = "0.8.0"
|
|||
networkmanager = "0.4"
|
||||
dbus = "0.9"
|
||||
battery = "0.7.8"
|
||||
systemstat = "0.2.4"
|
||||
|
||||
[patch.crates-io]
|
||||
winit = { path = "../winit" }
|
||||
|
|
|
|||
|
|
@ -1,13 +1,39 @@
|
|||
use battery::State;
|
||||
use cushy::{styles::components::TextColor, widget::MakeWidget};
|
||||
use battery::{Battery, State};
|
||||
use cushy::{
|
||||
styles::components::TextColor,
|
||||
value::{Destination, Dynamic},
|
||||
widget::MakeWidget,
|
||||
};
|
||||
|
||||
use crate::theme::{TEXT_BATTERY, WIDGET_PADDING};
|
||||
use crate::{
|
||||
rt::tokio_runtime,
|
||||
theme::{TEXT_BATTERY, WIDGET_PADDING},
|
||||
};
|
||||
|
||||
const BATTERY_LOW: &str = "";
|
||||
|
||||
const BATTERY_CHARGING: [&str; 11] = ["", "", "", "", "", "", "", "", "", "", ""];
|
||||
const BATTERY_NORMAL: [&str; 11] = ["", "", "", "", "", "", "", "", "", "", ""];
|
||||
|
||||
const BATTERY_UNKNOWN: &str = "";
|
||||
const BATTERY_FULL: &str = "";
|
||||
|
||||
fn format_battery(battery: &Battery) -> String {
|
||||
let state = battery.state();
|
||||
let charge = battery.state_of_charge();
|
||||
|
||||
let icon = match state {
|
||||
State::Charging => BATTERY_CHARGING[(charge.value * 10.) as usize],
|
||||
State::Discharging => BATTERY_NORMAL[(charge.value * 10.) as usize],
|
||||
State::Empty => BATTERY_LOW,
|
||||
State::Full => BATTERY_FULL,
|
||||
State::Unknown | _ => BATTERY_UNKNOWN,
|
||||
};
|
||||
|
||||
let percent = (charge.value * 100.) as u8;
|
||||
format!(" {} {}% ", icon, percent)
|
||||
}
|
||||
|
||||
pub fn battery() -> impl MakeWidget {
|
||||
let manager = battery::Manager::new();
|
||||
let Ok(manager) = manager else {
|
||||
|
|
@ -36,22 +62,33 @@ pub fn battery() -> impl MakeWidget {
|
|||
let Some(Ok(battery)) = batteries.next() else {
|
||||
return "".make_widget();
|
||||
};
|
||||
let info = Dynamic::new(format_battery(&battery));
|
||||
|
||||
let state = battery.state();
|
||||
let charge = battery.state_of_charge();
|
||||
tokio_runtime().spawn({
|
||||
let info = info.clone();
|
||||
async move {
|
||||
let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(1));
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
let icon = match state {
|
||||
State::Charging => BATTERY_CHARGING[(charge.value * 10.) as usize],
|
||||
State::Discharging => BATTERY_NORMAL[(charge.value * 10.) as usize],
|
||||
State::Empty => BATTERY_LOW,
|
||||
State::Full => "",
|
||||
State::Unknown | _ => "",
|
||||
};
|
||||
let Ok(manager) = battery::Manager::new() else {
|
||||
info.set(BATTERY_UNKNOWN.to_string());
|
||||
return;
|
||||
};
|
||||
let Ok(mut batteries) = manager.batteries() else {
|
||||
info.set(BATTERY_UNKNOWN.to_string());
|
||||
return;
|
||||
};
|
||||
let Some(Ok(battery)) = batteries.next() else {
|
||||
info.set(BATTERY_UNKNOWN.to_string());
|
||||
return;
|
||||
};
|
||||
info.set(format_battery(&battery));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let percent = (charge.value * 100.) as u8;
|
||||
|
||||
format!(" {} {}% ", icon, percent)
|
||||
.with(&TextColor, TEXT_BATTERY)
|
||||
info.with(&TextColor, TEXT_BATTERY)
|
||||
.pad_by(WIDGET_PADDING)
|
||||
.centered()
|
||||
.make_widget()
|
||||
|
|
|
|||
155
src/bar/hypr.rs
Normal file
155
src/bar/hypr.rs
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use cushy::{
|
||||
styles::{
|
||||
components::{CornerRadius, TextColor, WidgetBackground},
|
||||
Styles,
|
||||
},
|
||||
value::{Destination, Dynamic, Source},
|
||||
widget::{MakeWidget, WidgetList},
|
||||
widgets::Style,
|
||||
};
|
||||
use hyprland::{
|
||||
data::{Clients, Devices, Monitors, Workspaces},
|
||||
event_listener::AsyncEventListener,
|
||||
shared::{HyprData, HyprDataVec, HyprError},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
rt::tokio_runtime,
|
||||
theme::{
|
||||
BG_WORKSPACE_ACTIVE, TEXT_TOOL, TEXT_WORKSPACE_ACTIVE, WIDGET_PADDING,
|
||||
WORKSPACE_CORNER_RADIUS, WORKSPACE_PADDING,
|
||||
},
|
||||
};
|
||||
|
||||
use super::HyprlandState;
|
||||
|
||||
pub fn get_hyprland_state_sync() -> Result<HyprlandState, HyprError> {
|
||||
let monitors = Monitors::get()?.to_vec();
|
||||
let mut workspaces = Workspaces::get()?.to_vec();
|
||||
workspaces.sort_by_key(|a| a.id);
|
||||
let devices = Devices::get()?;
|
||||
let client = Clients::get()?.to_vec();
|
||||
Ok(HyprlandState {
|
||||
monitors,
|
||||
workspaces,
|
||||
devices,
|
||||
clients: client,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_hyprland_state() -> Result<HyprlandState, HyprError> {
|
||||
let monitors = Monitors::get_async().await?.to_vec();
|
||||
let mut workspaces = Workspaces::get_async().await?.to_vec();
|
||||
workspaces.sort_by_key(|a| a.id);
|
||||
let devices = Devices::get_async().await?;
|
||||
let client = Clients::get_async().await?.to_vec();
|
||||
Ok(HyprlandState {
|
||||
monitors,
|
||||
workspaces,
|
||||
devices,
|
||||
clients: client,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn init_callbacks(state: Dynamic<HyprlandState>) {
|
||||
tokio_runtime().spawn({
|
||||
let state = state.clone();
|
||||
async move {
|
||||
let mut event_listener = AsyncEventListener::new();
|
||||
|
||||
let update = Arc::new(move || {
|
||||
let state = state.clone();
|
||||
Box::pin(async move {
|
||||
if let Ok(unwrap) = get_hyprland_state().await {
|
||||
state.set(unwrap);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// I prefer winit-like event loop iterators/single callback with enum...
|
||||
|
||||
event_listener.add_workspace_added_handler({
|
||||
let update = update.clone();
|
||||
move |_| update()
|
||||
});
|
||||
event_listener.add_workspace_changed_handler({
|
||||
let update = update.clone();
|
||||
move |_| update()
|
||||
});
|
||||
event_listener.add_workspace_deleted_handler({
|
||||
let update = update.clone();
|
||||
move |_| update()
|
||||
});
|
||||
event_listener.add_window_opened_handler({
|
||||
let update = update.clone();
|
||||
move |_| update()
|
||||
});
|
||||
event_listener.add_window_closed_handler({
|
||||
let update = update.clone();
|
||||
move |_| update()
|
||||
});
|
||||
event_listener.add_window_title_changed_handler({
|
||||
let update = update.clone();
|
||||
move |_| update()
|
||||
});
|
||||
event_listener.add_urgent_state_changed_handler({
|
||||
let update = update.clone();
|
||||
move |_| update()
|
||||
});
|
||||
event_listener.add_screencast_handler({
|
||||
let update = update.clone();
|
||||
move |_| update()
|
||||
});
|
||||
event_listener.add_layout_changed_handler({
|
||||
let update = update.clone();
|
||||
move |_| update()
|
||||
});
|
||||
|
||||
event_listener.start_listener_async().await.unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn hyprland_workspaces(state: Dynamic<HyprlandState>) -> impl MakeWidget {
|
||||
state.map_each(|state| {
|
||||
let monitor = state.monitors.first().unwrap();
|
||||
let workspaces = &state.workspaces;
|
||||
WidgetList::from_iter(workspaces.iter().map(|w| {
|
||||
let active = monitor.active_workspace.id == w.id;
|
||||
|
||||
let name = w.name.clone();
|
||||
|
||||
if active {
|
||||
name.pad_by(WORKSPACE_PADDING)
|
||||
.centered()
|
||||
.with(&WidgetBackground, BG_WORKSPACE_ACTIVE)
|
||||
.with(&TextColor, TEXT_WORKSPACE_ACTIVE)
|
||||
.with(&CornerRadius, WORKSPACE_CORNER_RADIUS)
|
||||
.make_widget()
|
||||
} else {
|
||||
name.pad_by(WORKSPACE_PADDING).centered().make_widget()
|
||||
}
|
||||
}))
|
||||
.into_columns()
|
||||
.make_widget()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn hyprland_active_title(state: Dynamic<HyprlandState>) -> impl MakeWidget {
|
||||
state.map_each(|state| {
|
||||
let monitor = state.monitors.first().unwrap();
|
||||
let active_workspace = state
|
||||
.workspaces
|
||||
.iter()
|
||||
.find(|w| w.id == monitor.active_workspace.id)
|
||||
.unwrap();
|
||||
|
||||
format!(" {}", active_workspace.last_window_title.clone())
|
||||
.with(&TextColor, TEXT_TOOL)
|
||||
.pad_by(WIDGET_PADDING)
|
||||
.centered()
|
||||
.make_widget()
|
||||
})
|
||||
}
|
||||
45
src/bar/memory.rs
Normal file
45
src/bar/memory.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use cushy::{
|
||||
styles::components::TextColor,
|
||||
value::{Destination, Dynamic, Source},
|
||||
widget::MakeWidget,
|
||||
};
|
||||
use systemstat::{saturating_sub_bytes, Platform, System};
|
||||
|
||||
use crate::{
|
||||
rt::tokio_runtime,
|
||||
theme::{TEXT_MEM, WIDGET_PADDING},
|
||||
};
|
||||
|
||||
fn get_memory_usage() -> f64 {
|
||||
let sys = System::new();
|
||||
sys.memory()
|
||||
.map(|mem| {
|
||||
let used = saturating_sub_bytes(mem.total, mem.free);
|
||||
let used_percentage = (used.as_u64() as f64 / mem.total.as_u64() as f64) * 100.;
|
||||
used_percentage
|
||||
})
|
||||
.unwrap_or(0.)
|
||||
}
|
||||
|
||||
pub fn memory_widget() -> impl MakeWidget {
|
||||
let percentage = Dynamic::new(get_memory_usage());
|
||||
tokio_runtime().spawn({
|
||||
let current_time = percentage.clone();
|
||||
async move {
|
||||
let mut interval = tokio::time::interval(tokio::time::Duration::from_millis(1000));
|
||||
loop {
|
||||
interval.tick().await;
|
||||
current_time.set(get_memory_usage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
percentage
|
||||
.map_each(|percentage| {
|
||||
let icon = "".to_string();
|
||||
format!(" {} {:.0}%", icon, percentage)
|
||||
})
|
||||
.with(&TextColor, TEXT_MEM)
|
||||
.pad_by(WIDGET_PADDING)
|
||||
.centered()
|
||||
}
|
||||
|
|
@ -2,19 +2,22 @@ use battery::battery;
|
|||
use cushy::{
|
||||
figures::{
|
||||
units::{Lp, UPx},
|
||||
Size,
|
||||
Size, Zero,
|
||||
},
|
||||
kludgine::app::winit::{platform::wayland::Anchor, window::WindowLevel},
|
||||
kludgine::app::winit::{error::EventLoopError, platform::wayland::Anchor, window::WindowLevel},
|
||||
styles::{
|
||||
components::{
|
||||
BaseLineHeight, BaseTextSize, CornerRadius, DefaultBackgroundColor, FontWeight,
|
||||
IntrinsicPadding,
|
||||
},
|
||||
FontFamilyList,
|
||||
Dimension, FontFamilyList,
|
||||
},
|
||||
value::Dynamic,
|
||||
widget::MakeWidget,
|
||||
Application, Open,
|
||||
};
|
||||
use hypr::{get_hyprland_state_sync, hyprland_active_title, hyprland_workspaces, init_callbacks};
|
||||
use hyprland::data::{Client, Devices, Monitor, Workspace};
|
||||
|
||||
use crate::{
|
||||
theme::{BG_DEFAULT, CORNER_RADIUS, DEFAULT_FONT_WEIGHT, TEXT_FONT, TEXT_SIZE},
|
||||
|
|
@ -22,38 +25,70 @@ use crate::{
|
|||
};
|
||||
|
||||
mod battery;
|
||||
mod hypr;
|
||||
mod memory;
|
||||
mod spotify;
|
||||
mod time;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct HyprlandState {
|
||||
monitors: Vec<Monitor>,
|
||||
workspaces: Vec<Workspace>,
|
||||
devices: Devices,
|
||||
clients: Vec<Client>,
|
||||
}
|
||||
|
||||
pub fn start_bar(app: &mut impl Application) -> cushy::Result {
|
||||
let state = Dynamic::new(get_hyprland_state_sync().map_err(|err| {
|
||||
dbg!(err);
|
||||
EventLoopError::ExitFailure(1)
|
||||
})?);
|
||||
|
||||
init_callbacks(state.clone());
|
||||
|
||||
let monitors = (app.as_app().monitors()).unwrap();
|
||||
let mut monitor_size: Size<UPx> = monitors.available[0].size().into();
|
||||
monitor_size.height = UPx::new(40);
|
||||
monitor_size.width = UPx::new((monitor_size.width.get() as f64 / 1.25) as _);
|
||||
let size = Dynamic::new(monitor_size);
|
||||
let mut window = ((time::time_widget().bar_pill())
|
||||
|
||||
let left_part = (hyprland_workspaces(state.clone())
|
||||
.and(hyprland_active_title(state.clone()))
|
||||
.into_columns()
|
||||
.bar_pill()
|
||||
.and(memory::memory_widget().bar_pill()))
|
||||
.into_columns();
|
||||
|
||||
let middle_part = time::time_widget()
|
||||
.bar_pill()
|
||||
.and(spotify::spotify_controls().bar_pill())
|
||||
.into_columns()
|
||||
.centered()
|
||||
.expand_horizontally())
|
||||
.and(battery().bar_pill())
|
||||
.into_columns()
|
||||
.expand_horizontally()
|
||||
.width(monitor_size.width)
|
||||
.height(Lp::points(30))
|
||||
.with(&BaseTextSize, TEXT_SIZE)
|
||||
.with(&BaseLineHeight, TEXT_SIZE)
|
||||
.with(&DefaultBackgroundColor, BG_DEFAULT)
|
||||
.with(&CornerRadius, CORNER_RADIUS)
|
||||
.with(&FontWeight, DEFAULT_FONT_WEIGHT)
|
||||
.into_window()
|
||||
.inner_size(size.clone())
|
||||
.titled("rshell")
|
||||
.transparent()
|
||||
.app_name("rshell")
|
||||
.decorated(false)
|
||||
.resize_to_fit(false)
|
||||
.window_level(WindowLevel::AlwaysOnTop);
|
||||
.expand_horizontally();
|
||||
|
||||
let right_part = battery().bar_pill();
|
||||
|
||||
let mut window = left_part
|
||||
.and(middle_part)
|
||||
.and(right_part)
|
||||
.into_columns()
|
||||
.expand_horizontally()
|
||||
.width(monitor_size.width)
|
||||
.height(Lp::points(30))
|
||||
.with(&BaseTextSize, TEXT_SIZE)
|
||||
.with(&BaseLineHeight, TEXT_SIZE)
|
||||
.with(&DefaultBackgroundColor, BG_DEFAULT)
|
||||
.with(&CornerRadius, CORNER_RADIUS)
|
||||
.with(&FontWeight, DEFAULT_FONT_WEIGHT)
|
||||
.with(&IntrinsicPadding, Dimension::ZERO)
|
||||
.into_window()
|
||||
.inner_size(size.clone())
|
||||
.titled("rshell")
|
||||
.transparent()
|
||||
.app_name("rshell")
|
||||
.decorated(false)
|
||||
.resize_to_fit(false)
|
||||
.window_level(WindowLevel::AlwaysOnTop);
|
||||
|
||||
let mut family = FontFamilyList::default();
|
||||
for font in TEXT_FONT.iter() {
|
||||
|
|
|
|||
|
|
@ -125,32 +125,33 @@ fn get_texture_dynamic(
|
|||
let texture = texture.clone();
|
||||
let vibrancy = vibrancy.clone();
|
||||
let client = client.clone();
|
||||
let track_url = track.album_art.clone().unwrap();
|
||||
*prev_request_join = Some(tokio_runtime().spawn(async move {
|
||||
let response = client.get(track_url).send().await.unwrap();
|
||||
let bytes = response.bytes().await.unwrap();
|
||||
let image = image::load_from_memory(&bytes).unwrap();
|
||||
let image = image.resize(128, 128, FilterType::Lanczos3);
|
||||
let image_vibrancy = Vibrancy::new(&image);
|
||||
vibrancy.set(ImageVibrancy {
|
||||
primary: image_vibrancy.primary.map(|c| rgb_to_color(c)),
|
||||
dark: image_vibrancy.dark.map(|c| rgb_to_color(c)),
|
||||
light: image_vibrancy.light.map(|c| rgb_to_color(c)),
|
||||
muted: image_vibrancy.muted.map(|c| rgb_to_color(c)),
|
||||
dark_muted: image_vibrancy.dark_muted.map(|c| rgb_to_color(c)),
|
||||
light_muted: image_vibrancy.light_muted.map(|c| rgb_to_color(c)),
|
||||
});
|
||||
let image_texture = LazyTexture::from_image(
|
||||
image,
|
||||
cushy::kludgine::wgpu::FilterMode::Linear,
|
||||
);
|
||||
let image_texture = AnyTexture::Lazy(image_texture);
|
||||
texture.set(image_texture);
|
||||
}));
|
||||
} else {
|
||||
vibrancy.set(ImageVibrancy::default());
|
||||
texture.set(get_empty_texture());
|
||||
if let Some(track_url) = track.album_art.clone() {
|
||||
*prev_request_join = Some(tokio_runtime().spawn(async move {
|
||||
let response = client.get(track_url).send().await.unwrap();
|
||||
let bytes = response.bytes().await.unwrap();
|
||||
let image = image::load_from_memory(&bytes).unwrap();
|
||||
let image = image.resize(128, 128, FilterType::Lanczos3);
|
||||
let image_vibrancy = Vibrancy::new(&image);
|
||||
vibrancy.set(ImageVibrancy {
|
||||
primary: image_vibrancy.primary.map(|c| rgb_to_color(c)),
|
||||
dark: image_vibrancy.dark.map(|c| rgb_to_color(c)),
|
||||
light: image_vibrancy.light.map(|c| rgb_to_color(c)),
|
||||
muted: image_vibrancy.muted.map(|c| rgb_to_color(c)),
|
||||
dark_muted: image_vibrancy.dark_muted.map(|c| rgb_to_color(c)),
|
||||
light_muted: image_vibrancy.light_muted.map(|c| rgb_to_color(c)),
|
||||
});
|
||||
let image_texture = LazyTexture::from_image(
|
||||
image,
|
||||
cushy::kludgine::wgpu::FilterMode::Linear,
|
||||
);
|
||||
let image_texture = AnyTexture::Lazy(image_texture);
|
||||
texture.set(image_texture);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
}
|
||||
vibrancy.set(ImageVibrancy::default());
|
||||
texture.set(get_empty_texture());
|
||||
}
|
||||
})
|
||||
.persist();
|
||||
|
|
|
|||
16
src/theme.rs
16
src/theme.rs
|
|
@ -12,19 +12,33 @@ pub const WIDGET_PADDING: Edges<Dimension> = Edges {
|
|||
bottom: Dimension::Px(Px::new(4)),
|
||||
};
|
||||
|
||||
pub const WORKSPACE_PADDING: Edges<Dimension> = Edges {
|
||||
left: Dimension::Px(Px::new(15)),
|
||||
right: Dimension::Px(Px::new(15)),
|
||||
top: Dimension::Px(Px::new(4)),
|
||||
bottom: Dimension::Px(Px::new(4)),
|
||||
};
|
||||
pub const WORKSPACE_CORNER_RADIUS: Dimension = Dimension::Px(Px::new(12));
|
||||
|
||||
pub const DEFAULT_FONT_WEIGHT: Weight = Weight::MEDIUM;
|
||||
|
||||
pub const BG_DEFAULT: Color = Color(0x191724FF);
|
||||
pub const TEXT_SPOTIFY: Color = Color(0x1DB954FF);
|
||||
pub const TEXT_CLOCK: Color = Color(0xF6C177FF);
|
||||
pub const TEXT_CPU: Color = Color(0xff671fFF);
|
||||
pub const TEXT_MEM: Color = Color(0x1DB954FF);
|
||||
pub const TEXT_MEM: Color = Color(0xFFFFFFFF);
|
||||
pub const TEXT_TEMP: Color = Color(0x97f993FF);
|
||||
pub const TEXT_RED: Color = Color(0xD81E5BFF);
|
||||
|
||||
pub const TEXT_TOOL: Color = Color(0x4e9dc2ff);
|
||||
|
||||
pub const TEXT_AUDIO: Color = Color(0xF7E733FF);
|
||||
pub const TEXT_AUDIO_MUTED: Color = Color(0xD81E5BFF);
|
||||
pub const TEXT_BATTERY: Color = Color(0x6bb0d9FF);
|
||||
|
||||
pub const BG_WORKSPACE_ACTIVE: Color = Color(0x753a88ff);
|
||||
pub const TEXT_WORKSPACE_ACTIVE: Color = Color(0xebbcbaff);
|
||||
|
||||
pub const TEXT_FONT: [&str; 5] = [
|
||||
"Inter",
|
||||
"Iosevka",
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
use cushy::{styles::components::WidgetBackground, widget::MakeWidget, widgets::Container};
|
||||
|
||||
use crate::theme::BG_DEFAULT;
|
||||
use crate::theme::{BG_DEFAULT, WIDGET_PADDING};
|
||||
|
||||
pub trait WidgetExt: MakeWidget {
|
||||
fn bar_pill(self) -> Container {
|
||||
self.expand_vertically()
|
||||
.with(&WidgetBackground, BG_DEFAULT)
|
||||
.pad()
|
||||
.pad_by(WIDGET_PADDING)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue