feat(battery): add option to show charge percentage next to the icon (#994)
* feat(battery): add option to show charge percentage next to the icon * feat: proper padding and text sizing * chore: use from_vec instead of from_children * chore: remove battery percentage setting from applet dropdown * chore: move config config definition to cosmic-applets-config * feat: add subscription for config * chore: revert unnecessary config module change * fix: correctly scale battery icon size * chore: change battery applet id * feat: better battery text sizing --------- Co-authored-by: Levi Portenier <levi@system76.com>
This commit is contained in:
parent
fe2ebe7a89
commit
a1a6caf5e5
6 changed files with 106 additions and 10 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
|
@ -1243,6 +1243,8 @@ name = "cosmic-applet-battery"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"cosmic-applets-config",
|
||||||
|
"cosmic-config",
|
||||||
"cosmic-settings-daemon-subscription",
|
"cosmic-settings-daemon-subscription",
|
||||||
"cosmic-settings-upower-subscription",
|
"cosmic-settings-upower-subscription",
|
||||||
"cosmic-time",
|
"cosmic-time",
|
||||||
|
|
@ -1253,6 +1255,7 @@ dependencies = [
|
||||||
"libcosmic",
|
"libcosmic",
|
||||||
"rust-embed",
|
"rust-embed",
|
||||||
"rustc-hash 2.1.1",
|
"rustc-hash 2.1.1",
|
||||||
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ license = "GPL-3.0-only"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
cosmic-time.workspace = true
|
cosmic-time.workspace = true
|
||||||
|
cosmic-config.workspace = true
|
||||||
|
cosmic-applets-config.workspace = true
|
||||||
drm = "0.14.1"
|
drm = "0.14.1"
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
i18n-embed-fl.workspace = true
|
i18n-embed-fl.workspace = true
|
||||||
|
|
@ -20,6 +22,7 @@ tracing-subscriber.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
udev = "0.9"
|
udev = "0.9"
|
||||||
zbus.workspace = true
|
zbus.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
|
||||||
[dependencies.cosmic-settings-upower-subscription]
|
[dependencies.cosmic-settings-upower-subscription]
|
||||||
git = "https://github.com/pop-os/cosmic-settings"
|
git = "https://github.com/pop-os/cosmic-settings"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ use crate::{
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
Element, Task, app,
|
Element, Task, app,
|
||||||
applet::{
|
applet::{
|
||||||
cosmic_panel_config::PanelAnchor,
|
Size,
|
||||||
|
cosmic_panel_config::{PanelAnchor, PanelSize},
|
||||||
menu_button, padded_control,
|
menu_button, padded_control,
|
||||||
token::subscription::{TokenRequest, TokenUpdate, activation_token_subscription},
|
token::subscription::{TokenRequest, TokenUpdate, activation_token_subscription},
|
||||||
},
|
},
|
||||||
|
|
@ -22,13 +23,16 @@ use cosmic::{
|
||||||
iced::{
|
iced::{
|
||||||
Length, Subscription,
|
Length, Subscription,
|
||||||
platform_specific::shell::wayland::commands::popup::{destroy_popup, get_popup},
|
platform_specific::shell::wayland::commands::popup::{destroy_popup, get_popup},
|
||||||
widget::{Column, Row, column, container, row},
|
widget::{Column, column, container, row},
|
||||||
window,
|
window,
|
||||||
},
|
},
|
||||||
iced_core::{Alignment, Background, Border, Color, Shadow},
|
iced_core::{Alignment, Background, Border, Color, Shadow},
|
||||||
surface, theme,
|
surface,
|
||||||
widget::{divider, horizontal_space, icon, scrollable, slider, text, vertical_space},
|
theme::{self, Button},
|
||||||
|
widget::{button, divider, horizontal_space, icon, scrollable, slider, text, vertical_space},
|
||||||
};
|
};
|
||||||
|
use cosmic_applets_config::battery::BatteryAppletConfig;
|
||||||
|
use cosmic_config::{Config, CosmicConfigEntry};
|
||||||
use cosmic_settings_daemon_subscription as settings_daemon;
|
use cosmic_settings_daemon_subscription as settings_daemon;
|
||||||
use cosmic_settings_upower_subscription::{
|
use cosmic_settings_upower_subscription::{
|
||||||
device::{DeviceDbusEvent, device_subscription},
|
device::{DeviceDbusEvent, device_subscription},
|
||||||
|
|
@ -73,6 +77,7 @@ struct GPUData {
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
struct CosmicBatteryApplet {
|
struct CosmicBatteryApplet {
|
||||||
core: cosmic::app::Core,
|
core: cosmic::app::Core,
|
||||||
|
config: BatteryAppletConfig,
|
||||||
icon_name: String,
|
icon_name: String,
|
||||||
display_icon_name: String,
|
display_icon_name: String,
|
||||||
charging_limit: Option<bool>,
|
charging_limit: Option<bool>,
|
||||||
|
|
@ -193,6 +198,7 @@ enum Message {
|
||||||
Profile(Power),
|
Profile(Power),
|
||||||
SelectProfile(Power),
|
SelectProfile(Power),
|
||||||
Frame(Instant),
|
Frame(Instant),
|
||||||
|
ConfigChanged(BatteryAppletConfig),
|
||||||
Token(TokenUpdate),
|
Token(TokenUpdate),
|
||||||
OpenSettings,
|
OpenSettings,
|
||||||
SettingsDaemon(settings_daemon::Event),
|
SettingsDaemon(settings_daemon::Event),
|
||||||
|
|
@ -207,6 +213,11 @@ impl cosmic::Application for CosmicBatteryApplet {
|
||||||
const APP_ID: &'static str = config::APP_ID;
|
const APP_ID: &'static str = config::APP_ID;
|
||||||
|
|
||||||
fn init(core: cosmic::app::Core, _flags: Self::Flags) -> (Self, app::Task<Self::Message>) {
|
fn init(core: cosmic::app::Core, _flags: Self::Flags) -> (Self, app::Task<Self::Message>) {
|
||||||
|
let config = Config::new(Self::APP_ID, BatteryAppletConfig::VERSION)
|
||||||
|
.ok()
|
||||||
|
.and_then(|c| BatteryAppletConfig::get_entry(&c).ok())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let zbus_session_cmd = Task::perform(zbus::Connection::session(), |res| {
|
let zbus_session_cmd = Task::perform(zbus::Connection::session(), |res| {
|
||||||
cosmic::Action::App(Message::ZbusConnection(res))
|
cosmic::Action::App(Message::ZbusConnection(res))
|
||||||
});
|
});
|
||||||
|
|
@ -216,6 +227,7 @@ impl cosmic::Application for CosmicBatteryApplet {
|
||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
core,
|
core,
|
||||||
|
config,
|
||||||
icon_name: "battery-symbolic".to_string(),
|
icon_name: "battery-symbolic".to_string(),
|
||||||
display_icon_name: "display-brightness-symbolic".to_string(),
|
display_icon_name: "display-brightness-symbolic".to_string(),
|
||||||
token_tx: None,
|
token_tx: None,
|
||||||
|
|
@ -421,6 +433,9 @@ impl cosmic::Application for CosmicBatteryApplet {
|
||||||
self.popup = None;
|
self.popup = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Message::ConfigChanged(config) => {
|
||||||
|
self.config = config;
|
||||||
|
}
|
||||||
Message::OpenSettings => {
|
Message::OpenSettings => {
|
||||||
let exec = "cosmic-settings power".to_string();
|
let exec = "cosmic-settings power".to_string();
|
||||||
if let Some(tx) = self.token_tx.as_ref() {
|
if let Some(tx) = self.token_tx.as_ref() {
|
||||||
|
|
@ -499,12 +514,69 @@ impl cosmic::Application for CosmicBatteryApplet {
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self) -> Element<'_, Message> {
|
fn view(&self) -> Element<Message> {
|
||||||
let btn: Element<'_, Message> = self
|
let is_horizontal = match self.core.applet.anchor {
|
||||||
.core
|
PanelAnchor::Top | PanelAnchor::Bottom => true,
|
||||||
.applet
|
PanelAnchor::Left | PanelAnchor::Right => false,
|
||||||
.icon_button(&self.icon_name)
|
};
|
||||||
|
|
||||||
|
let suggested_size = self.core.applet.suggested_size(true);
|
||||||
|
let applet_padding = self.core.applet.suggested_padding(true);
|
||||||
|
|
||||||
|
let mut children = vec![
|
||||||
|
icon::from_name(self.icon_name.as_str())
|
||||||
|
.size(suggested_size.0)
|
||||||
|
.into(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if self.config.show_percentage {
|
||||||
|
let text = format!("{:.0}%", self.battery_percent);
|
||||||
|
|
||||||
|
let t = if is_horizontal {
|
||||||
|
self.core.applet.text(text)
|
||||||
|
} else {
|
||||||
|
match &self.core.applet.size {
|
||||||
|
Size::Hardcoded(_) => text::text(text),
|
||||||
|
Size::PanelSize(PanelSize::XS) => text::caption(text),
|
||||||
|
Size::PanelSize(PanelSize::S) => text::body(text),
|
||||||
|
Size::PanelSize(PanelSize::M) => text::title4(text),
|
||||||
|
Size::PanelSize(PanelSize::L) => text::title3(text),
|
||||||
|
_ => text::title2(text),
|
||||||
|
}
|
||||||
|
.width(Length::Fixed(suggested_size.0 as f32))
|
||||||
|
};
|
||||||
|
|
||||||
|
children.push(
|
||||||
|
t.font(cosmic::font::default())
|
||||||
|
.height(Length::Fixed(suggested_size.1 as f32))
|
||||||
|
.align_x(Alignment::Center)
|
||||||
|
.align_y(Alignment::Center)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let btn_content: Element<_> = if is_horizontal {
|
||||||
|
row(children)
|
||||||
|
.spacing(applet_padding.1)
|
||||||
|
.align_y(Alignment::Center)
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
column(children)
|
||||||
|
.spacing(applet_padding.1)
|
||||||
|
.align_x(Alignment::Center)
|
||||||
|
.into()
|
||||||
|
};
|
||||||
|
|
||||||
|
let (horizontal_padding, vertical_padding) = if is_horizontal {
|
||||||
|
(applet_padding.0, applet_padding.1)
|
||||||
|
} else {
|
||||||
|
(applet_padding.1, applet_padding.0)
|
||||||
|
};
|
||||||
|
|
||||||
|
let btn: Element<'_, Message> = button::custom(btn_content)
|
||||||
.on_press_down(Message::TogglePopup)
|
.on_press_down(Message::TogglePopup)
|
||||||
|
.class(Button::AppletIcon)
|
||||||
|
.padding([vertical_padding, horizontal_padding])
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let content = if self.gpus.is_empty() {
|
let content = if self.gpus.is_empty() {
|
||||||
|
|
@ -884,6 +956,12 @@ impl cosmic::Application for CosmicBatteryApplet {
|
||||||
.as_subscription()
|
.as_subscription()
|
||||||
.map(|(_, now)| Message::Frame(now)),
|
.map(|(_, now)| Message::Frame(now)),
|
||||||
activation_token_subscription(0).map(Message::Token),
|
activation_token_subscription(0).map(Message::Token),
|
||||||
|
self.core.watch_config(Self::APP_ID).map(|u| {
|
||||||
|
for err in u.errors {
|
||||||
|
tracing::error!(?err, "Error watching config");
|
||||||
|
}
|
||||||
|
Message::ConfigChanged(u.config)
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
if let Some(conn) = self.zbus_connection.clone() {
|
if let Some(conn) = self.zbus_connection.clone() {
|
||||||
subscriptions.push(settings_daemon::subscription(conn).map(Message::SettingsDaemon));
|
subscriptions.push(settings_daemon::subscription(conn).map(Message::SettingsDaemon));
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2023 System76 <info@system76.com>
|
// Copyright 2023 System76 <info@system76.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
pub const APP_ID: &str = "com.system76.CosmicAppletButton";
|
pub const APP_ID: &str = "com.system76.CosmicAppletBattery";
|
||||||
|
|
|
||||||
11
cosmic-applets-config/src/battery.rs
Normal file
11
cosmic-applets-config/src/battery.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2026 System76 <info@system76.com>
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use cosmic_config::{CosmicConfigEntry, cosmic_config_derive::CosmicConfigEntry};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, CosmicConfigEntry, Default)]
|
||||||
|
#[version = 1]
|
||||||
|
pub struct BatteryAppletConfig {
|
||||||
|
pub show_percentage: bool,
|
||||||
|
}
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
pub mod battery;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue