fix(power): alignment of remaining battery

This commit is contained in:
Antoine Colombier 2024-09-05 13:24:02 +01:00 committed by GitHub
parent 090efbfad7
commit 97bcbc64ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 121 additions and 35 deletions

View file

@ -19,6 +19,10 @@ pub static LANGUAGE_LOADER: Lazy<FluentLanguageLoader> = Lazy::new(|| {
.load_fallback_language(&Localizations)
.expect("Error while loading fallback language");
// In test, disable the isolating markers to help with string assertion
#[cfg(test)]
loader.set_use_isolating(false);
loader
});

View file

@ -36,7 +36,7 @@ impl Default for PageInner {
Self {
config_helper: Option::default(),
panel_config: Option::default(),
outputs: vec![fl!("all")],
outputs: vec![fl!("all-displays")],
anchors: vec![
Anchor(PanelAnchor::Left).to_string(),
Anchor(PanelAnchor::Right).to_string(),

View file

@ -1,4 +1,4 @@
use chrono::Duration;
use chrono::{Duration, TimeDelta};
use futures::FutureExt;
use zbus::Connection;
@ -236,7 +236,6 @@ pub struct Battery {
pub percent: f64,
pub on_battery: bool,
pub remaining_duration: Duration,
pub remaining_time: String,
}
async fn get_device_proxy<'a>() -> Result<upower_dbus::DeviceProxy<'a>, zbus::Error> {
@ -321,30 +320,79 @@ impl Battery {
let icon_name =
format!("cosmic-applet-battery-level-{battery_percent}-{charging}symbolic",);
let remaining_time = |duration: Duration| {
let total_seconds = duration.num_seconds();
let hours = total_seconds / 3600;
let minutes = (total_seconds % 3600) / 60;
let seconds = total_seconds % 60;
fl!(
"battery",
"remaining-time",
time = format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
)
};
return Battery {
icon_name,
is_present,
percent,
on_battery,
remaining_duration,
remaining_time: remaining_time(remaining_duration),
};
}
Battery::default()
}
pub fn remaining_time(&self) -> String {
if self.remaining_duration <= TimeDelta::zero() {
return String::new()
}
let total_seconds = self.remaining_duration.num_seconds();
let days = total_seconds / 86400;
let hours = total_seconds % 86400 / 3600;
let minutes = (total_seconds % 3600) / 60;
let mut time: Vec<String> = Vec::new();
if days > 0 {
time.push(fl!("battery", "day", value = days));
}
if hours > 0 {
time.push(fl!("battery", "hour", value = hours));
}
if minutes > 0 {
time.push(fl!("battery", "minute", value = minutes));
}
if time.len() == 3 {
let last = time.pop().unwrap();
time = vec![time.join(", "), last];
}
let time = if time.is_empty() { fl!("battery", "less-than-minute")
} else {time.join(&format!(" {} ", fl!("battery", "and"))) };
fl!(
"battery",
"remaining-time",
time = time,
action = if self.on_battery { "empty" } else { "full" }
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_can_format_battery_remaining() {
let cases = [
(59, "Less than a minute until empty"),
(300, "5 minutes until empty"),
(305, "5 minutes until empty"),
(330, "5 minutes until empty"),
(360, "6 minutes until empty"),
(3660, "1 hour and 1 minute until empty"),
(10800, "3 hours until empty"),
(969400, "11 days, 5 hours and 16 minutes until empty"),
];
for case in cases {
let (actual, expected) = case;
let battery = Battery {
remaining_duration: Duration::new(actual, 0).unwrap(),
on_battery: true,
..Default::default()
};
assert_eq!(battery.remaining_time(), expected);
}
}
}

View file

@ -3,8 +3,7 @@ mod backend;
use self::backend::{GetCurrentPowerProfile, SetPowerProfile};
use backend::{Battery, PowerProfile};
use chrono::TimeDelta;
use cosmic::iced::Length;
use cosmic::iced::{Alignment, Length};
use cosmic::iced_widget::row;
use cosmic::widget::{self, column, radio, settings, text};
use cosmic::Apply;
@ -79,18 +78,19 @@ fn battery_info() -> Section<crate::pages::Message> {
.show_while::<Page>(|page| page.battery.is_present)
.view::<Page>(move |_binder, page, section| {
let battery_icon = widget::icon::from_name(page.battery.icon_name.clone());
let battery_percent = text::body(format!("{}%", page.battery.percent));
let battery_time = text::body(if page.battery.remaining_duration > TimeDelta::zero() {
&page.battery.remaining_time
} else {
""
});
let battery_label = text::body(format!(
"{}% {}",
page.battery.percent,
page.battery.remaining_time()
));
column::with_capacity(2)
.spacing(8)
.push(text::heading(&section.title))
.push(row!(battery_icon, battery_percent, battery_time).spacing(8))
.push(
row!(battery_icon, battery_label)
.align_items(Alignment::Center)
.spacing(cosmic::theme::active().cosmic().space_xxxs()),
)
.into()
})
}

View file

@ -156,8 +156,8 @@ panel-style = Style
.background-opacity = Background opacity
panel-applets = Configuration
.dock-desc = Configure dock applets.
.desc = Configure panel applets.
.dock-desc = Configure dock applets
.desc = Configure panel applets
panel-missing = Panel Configuration is Missing
.desc = The panel configuration file is missing due to use of a custom configuration or it is corrupted.
@ -304,7 +304,24 @@ power = Power & Battery
.desc = Manage power settings
battery = Battery
.remaining-time = ({ $time } left)
.minute = { $value } { $value ->
[one] minute
*[other] minutes
}
.hour = { $value } { $value ->
[one] hour
*[other] hours
}
.day = { $value } { $value ->
[one] day
*[other] days
}
.less-than-minute = Less than a minute
.and = and
.remaining-time = ({ $time } until { $action ->
[full] full
*[other] empty
})
power-mode = Power Mode
.battery = Extended battery life

View file

@ -156,8 +156,8 @@ panel-style = Style
.background-opacity = Opacité de l'arrière-plan
panel-applets = Configuration
.dock-desc = Configuration des applets du dock.
.desc = Configuration des applets du panneau.
.dock-desc = Configuration des applets du dock
.desc = Configuration des applets du panneau
panel-missing = La configuration du panneau est manquante
.desc = Le fichier de configuration du panneau est manquant à cause d'une configuration personnalisée ou il est corrompu.
@ -294,7 +294,24 @@ power = Énergie
.desc = Gérer les paramètres d'alimentation
battery = Batterie
.remaining-time = ({ $time } restant)
.minute = { $value } { $value ->
[one] minute
*[other] minutes
}
.hour = { $value } { $value ->
[one] heure
*[other] heures
}
.day = { $value } { $value ->
[one] jour
*[other] jours
}
.less-than-minute = Moins d'une minute
.and = et
.remaining-time = ({ $time } jusqu'à la { $action ->
[full] charge
*[other] decharge
} complète)
power-profiles = Modes d'énergie
.battery = Économie d'énergie