Files
feresaria/shell/ferese-shell/src/status_ui/battery.rs
T

187 lines
6.1 KiB
Rust

use cosmic::iced::{Alignment, Color, Length};
use cosmic::widget::{button, column, container, row};
use cosmic::{Element, theme};
use super::bar::status_icon;
use super::controls::{control_card, level_meter, slider_row};
use super::{Menu, MenuRows, MenuStyle};
use crate::status::Action;
use crate::{FereseShell, Message, ShellTheme, accented_icon, bar_icon, color_with_opacity, motion, shell_font, text};
pub(super) fn view<'a>(shell: &'a FereseShell, mut rows: MenuRows<'a>, style: MenuStyle) -> MenuRows<'a> {
let MenuStyle {
theme,
primary,
muted,
opacity: p,
} = style;
if let Some(b) = &shell.status.battery {
let battery_color = if b.percent < shell.config.status.low_battery_threshold && b.status != "Charging" {
Color {
a: p,
..Color::from_rgb8(230, 172, 90)
}
} else {
primary
};
rows = rows.push(
container(
row![
text(format!("{}%", b.percent)).size(24).width(Length::Fill),
accented_icon(
status_icon(Menu::Battery, &shell.status).0,
24,
battery_color,
color_with_opacity(theme.accent, p),
),
]
.align_y(Alignment::Center),
)
.padding([2, 0])
.class(theme::Container::custom(move |_| container::Style {
text_color: Some(battery_color),
icon_color: Some(battery_color),
..Default::default()
})),
);
rows = rows.push(level_meter(b.percent, battery_color, p));
rows = rows.push(
text(match b.status.as_str() {
"Charging" => "Connected to power",
"Discharging" => "Running on battery power",
"Full" => "Battery fully charged",
_ => "Battery status reported by the system",
})
.size(12)
.class(theme::Text::Color(muted)),
);
}
rows = rows.push(ferese_theme::menus::section_label("Power mode", shell_font(), muted));
if let Some(profiles) = &shell.status.power_profiles {
let mut modes = row::with_capacity(3).spacing(6).width(Length::Fill);
for (index, (label, icon, profile)) in [
("Power saver", ferese_theme::icons::POWER_SAVER, "power-saver"),
("Balanced", ferese_theme::icons::POWER_BALANCED, "balanced"),
("Performance", ferese_theme::icons::POWER_PERFORMANCE, "performance"),
]
.into_iter()
.enumerate()
{
if profiles.available[index] {
modes = modes.push(power_tile(label, icon, profile, profiles.active == profile, theme, p));
}
}
rows = rows.push(modes);
} else {
rows = rows.push(
text("Power Profiles service unavailable")
.size(12)
.class(theme::Text::Color(muted)),
);
}
let mut power = row::with_capacity(3).spacing(6).width(Length::Fill);
for (enabled, label, icon, action) in [
(
shell.status.reboot,
"Restart",
ferese_theme::icons::RESTART,
Action::Reboot,
),
(
shell.status.poweroff,
"Power off",
ferese_theme::icons::POWER_OFF,
Action::Poweroff,
),
(
shell.status.suspend,
"Suspend",
ferese_theme::icons::SUSPEND,
Action::Suspend,
),
] {
if enabled {
power = power.push(power_tile_action(label, icon, action, theme, p));
}
}
if shell.status.reboot || shell.status.poweroff || shell.status.suspend {
rows = rows.push(ferese_theme::menus::section_label("Power", shell_font(), muted));
rows = rows.push(power);
}
rows
}
pub(super) fn brightness<'a>(shell: &'a FereseShell, mut rows: MenuRows<'a>, style: MenuStyle) -> MenuRows<'a> {
let MenuStyle {
theme,
primary,
muted: _,
opacity: p,
} = style;
if let Some(value) = shell.status.brightness {
let brightness = column![
text("Brightness").size(13),
slider_row(
ferese_theme::icons::BRIGHTNESS,
value,
true,
primary,
color_with_opacity(theme.accent, p),
p,
)
]
.spacing(6);
rows = rows.push(control_card(brightness.into(), primary, p));
}
rows
}
fn power_tile<'a>(
label: &'static str,
icon: &'static [u8],
profile: &'static str,
selected: bool,
theme: ShellTheme,
opacity: f32,
) -> Element<'a, cosmic::Action<Message>> {
let foreground = color_with_opacity(if selected { theme.accent } else { theme.text_primary }, opacity);
let tile = container(
column![bar_icon(icon, 19, foreground), text(label).size(11)]
.spacing(3)
.align_x(Alignment::Center),
)
.width(Length::Fill)
.center_x(Length::Fill);
let btn = button::custom(tile)
.width(Length::FillPortion(1))
.padding([8, 2])
.on_press(cosmic::Action::App(Message::Control(Action::PowerProfile(profile))));
motion::button(btn, foreground, selected, opacity)
}
fn power_tile_action<'a>(
label: &'static str,
icon: &'static [u8],
action: Action,
theme: ShellTheme,
opacity: f32,
) -> Element<'a, cosmic::Action<Message>> {
let foreground = color_with_opacity(theme.text_primary, opacity);
let tile = container(
column![bar_icon(icon, 19, foreground), text(label).size(11)]
.spacing(3)
.align_x(Alignment::Center),
)
.width(Length::Fill)
.center_x(Length::Fill);
let btn = button::custom(tile)
.width(Length::FillPortion(1))
.padding([8, 2])
.on_press(cosmic::Action::App(Message::ConfirmPower(action)));
motion::button(btn, foreground, false, opacity)
}