Skip to content

Commit

Permalink
refactor: remove battery conversion step (#1652)
Browse files Browse the repository at this point in the history
* refactor: remove battery conversion step

* also fix a bug with margins in battery

* fixes
  • Loading branch information
ClementTsang authored Dec 23, 2024
1 parent 4a4d53d commit cd6c60c
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 154 deletions.
4 changes: 2 additions & 2 deletions src/app/data_farmer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ pub struct DataCollection {
pub io_labels: Vec<(String, String)>,
pub temp_harvest: Vec<temperature::TempHarvest>,
#[cfg(feature = "battery")]
pub battery_harvest: Vec<batteries::BatteryHarvest>,
pub battery_harvest: Vec<batteries::BatteryData>,
#[cfg(feature = "zfs")]
pub arc_harvest: memory::MemHarvest,
#[cfg(feature = "gpu")]
Expand Down Expand Up @@ -451,7 +451,7 @@ impl DataCollection {
}

#[cfg(feature = "battery")]
fn eat_battery(&mut self, list_of_batteries: Vec<batteries::BatteryHarvest>) {
fn eat_battery(&mut self, list_of_batteries: Vec<batteries::BatteryData>) {
self.battery_harvest = list_of_batteries;
}

Expand Down
8 changes: 4 additions & 4 deletions src/app/states.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct AppWidgetStates {
pub proc_state: ProcState,
pub temp_state: TempState,
pub disk_state: DiskState,
pub battery_state: BatteryState,
pub battery_state: AppBatteryState,
pub basic_table_widget_state: Option<BasicTableWidgetState>,
}

Expand Down Expand Up @@ -381,13 +381,13 @@ pub struct BasicTableWidgetState {
pub right_brc: Option<(u16, u16)>,
}

pub struct BatteryState {
pub struct AppBatteryState {
pub widget_states: HashMap<u64, BatteryWidgetState>,
}

impl BatteryState {
impl AppBatteryState {
pub fn init(widget_states: HashMap<u64, BatteryWidgetState>) -> Self {
BatteryState { widget_states }
AppBatteryState { widget_states }
}

pub fn get_mut_widget_state(&mut self, widget_id: u64) -> Option<&mut BatteryWidgetState> {
Expand Down
3 changes: 1 addition & 2 deletions src/canvas/components/data_table/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,10 @@ where
&mut self, f: &mut Frame<'_>, draw_info: &DrawInfo, widget: Option<&mut BottomWidget>,
painter: &Painter,
) {
let draw_horizontal = !self.props.is_basic || draw_info.is_on_widget();
let draw_loc = draw_info.loc;
let margined_draw_loc = Layout::default()
.constraints([Constraint::Percentage(100)])
.horizontal_margin(u16::from(!draw_horizontal))
.horizontal_margin(u16::from(self.props.is_basic && !draw_info.is_on_widget()))
.direction(Direction::Horizontal)
.split(draw_loc)[0];

Expand Down
65 changes: 34 additions & 31 deletions src/canvas/widgets/battery_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
Painter,
},
constants::*,
data_conversion::BatteryDuration,
data_collection::batteries::BatteryState,
};

impl Painter {
Expand All @@ -27,8 +27,8 @@ impl Painter {
.widget_states
.get_mut(&widget_id)
{
let is_on_widget = widget_id == app_state.current_widget.widget_id;
let border_style = if is_on_widget {
let is_selected = widget_id == app_state.current_widget.widget_id;
let border_style = if is_selected {
self.styles.highlighted_border_style
} else {
self.styles.border_style
Expand All @@ -42,7 +42,7 @@ impl Painter {
let block = {
let mut block = widget_block(
app_state.app_config_fields.use_basic_mode,
is_on_widget,
is_selected,
self.styles.border_type,
)
.border_style(border_style)
Expand Down Expand Up @@ -113,7 +113,7 @@ impl Painter {

let margined_draw_loc = Layout::default()
.constraints([Constraint::Percentage(100)])
.horizontal_margin(u16::from(!(is_on_widget || is_basic)))
.horizontal_margin(u16::from(is_basic && !is_selected))
.direction(Direction::Horizontal)
.split(draw_loc)[0];

Expand All @@ -124,73 +124,76 @@ impl Painter {
{
let full_width = draw_loc.width.saturating_sub(2);
let bar_length = usize::from(full_width.saturating_sub(6));
let charge_percentage = battery_details.charge_percentage;
let num_bars = calculate_basic_use_bars(charge_percentage, bar_length);
let charge_percent = battery_details.charge_percent;

let num_bars = calculate_basic_use_bars(charge_percent, bar_length);
let bars = format!(
"[{}{}{:3.0}%]",
"|".repeat(num_bars),
" ".repeat(bar_length - num_bars),
charge_percentage,
charge_percent,
);

let mut battery_charge_rows = Vec::with_capacity(2);
battery_charge_rows.push(Row::new([
Cell::from("Charge").style(self.styles.text_style)
]));
battery_charge_rows.push(Row::new([Cell::from(bars).style(
if charge_percentage < 10.0 {
if charge_percent < 10.0 {
self.styles.low_battery
} else if charge_percentage < 50.0 {
} else if charge_percent < 50.0 {
self.styles.medium_battery
} else {
self.styles.high_battery
},
)]));

let mut battery_rows = Vec::with_capacity(3);
let watt_consumption = battery_details.watt_consumption();
let health = battery_details.health();

battery_rows.push(Row::new([""]).bottom_margin(table_gap + 1));
battery_rows.push(
Row::new(["Rate", &battery_details.watt_consumption])
.style(self.styles.text_style),
);
battery_rows
.push(Row::new(["Rate", &watt_consumption]).style(self.styles.text_style));

battery_rows.push(
Row::new(["State", &battery_details.state]).style(self.styles.text_style),
Row::new(["State", battery_details.state.as_str()])
.style(self.styles.text_style),
);

let mut time: String; // Keep string lifetime in scope.
{
let style = self.styles.text_style;
match &battery_details.battery_duration {
BatteryDuration::ToEmpty(secs) => {
match &battery_details.state {
BatteryState::Charging {
time_to_full: Some(secs),
} => {
time = long_time(*secs);

if full_width as usize > time.len() {
battery_rows.push(Row::new(["Time to empty", &time]).style(style));
battery_rows.push(Row::new(["Time to full", &time]).style(style));
} else {
time = short_time(*secs);
battery_rows.push(Row::new(["To empty", &time]).style(style));
battery_rows.push(Row::new(["To full", &time]).style(style));
}
}
BatteryDuration::ToFull(secs) => {
BatteryState::Discharging {
time_to_empty: Some(secs),
} => {
time = long_time(*secs);

if full_width as usize > time.len() {
battery_rows.push(Row::new(["Time to full", &time]).style(style));
battery_rows.push(Row::new(["Time to empty", &time]).style(style));
} else {
time = short_time(*secs);
battery_rows.push(Row::new(["To full", &time]).style(style));
battery_rows.push(Row::new(["To empty", &time]).style(style));
}
}
BatteryDuration::Empty
| BatteryDuration::Full
| BatteryDuration::Unknown => {}
_ => {}
}
}

battery_rows.push(
Row::new(["Health", &battery_details.health]).style(self.styles.text_style),
);
battery_rows.push(Row::new(["Health", &health]).style(self.styles.text_style));

let header = if app_state.converted_data.battery_data.len() > 1 {
Row::new([""]).bottom_margin(table_gap)
Expand Down Expand Up @@ -241,15 +244,15 @@ impl Painter {
}
}

fn get_hms(secs: i64) -> (i64, i64, i64) {
fn get_hms(secs: u32) -> (u32, u32, u32) {
let hours = secs / (60 * 60);
let minutes = (secs / 60) - hours * 60;
let seconds = secs - minutes * 60 - hours * 60 * 60;

(hours, minutes, seconds)
}

fn long_time(secs: i64) -> String {
fn long_time(secs: u32) -> String {
let (hours, minutes, seconds) = get_hms(secs);

if hours > 0 {
Expand All @@ -266,7 +269,7 @@ fn long_time(secs: i64) -> String {
}
}

fn short_time(secs: i64) -> String {
fn short_time(secs: u32) -> String {
let (hours, minutes, seconds) = get_hms(secs);

if hours > 0 {
Expand Down
4 changes: 1 addition & 3 deletions src/data_collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ pub mod nvidia;
#[cfg(all(target_os = "linux", feature = "gpu"))]
pub mod amd;

#[cfg(feature = "battery")]
pub mod batteries;

pub mod cpu;
pub mod disks;
pub mod error;
Expand Down Expand Up @@ -45,7 +43,7 @@ pub struct Data {
pub disks: Option<Vec<disks::DiskHarvest>>,
pub io: Option<disks::IoHarvest>,
#[cfg(feature = "battery")]
pub list_of_batteries: Option<Vec<batteries::BatteryHarvest>>,
pub list_of_batteries: Option<Vec<batteries::BatteryData>>,
#[cfg(feature = "zfs")]
pub arc: Option<memory::MemHarvest>,
#[cfg(feature = "gpu")]
Expand Down
107 changes: 100 additions & 7 deletions src/data_collection/batteries.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,104 @@
//! Data collection for batteries.
//! Uses the battery crate.
//!
//! For Linux, macOS, Windows, FreeBSD, Dragonfly, and iOS, this is handled by
//! the battery crate.
//! Covers battery usage for:
//! - Linux 2.6.39+
//! - MacOS 10.10+
//! - iOS
//! - Windows 7+
//! - FreeBSD
//! - DragonFlyBSD
//!
//! For more information, refer to the [starship_battery](https://github.com/starship/rust-battery) repo/docs.
#[cfg(feature = "battery")]
use starship_battery::{
units::{power::watt, ratio::percent, time::second},
Battery, Manager, State,
};

/// Battery state.
#[derive(Debug, Default, Clone)]
pub enum BatteryState {
Charging {
/// Time to full in seconds.
time_to_full: Option<u32>,
},
Discharging {
/// Time to empty in seconds.
time_to_empty: Option<u32>,
},
Empty,
Full,
#[default]
Unknown,
}

cfg_if::cfg_if! {
if #[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "ios"))] {
pub mod battery;
pub use self::battery::*;
impl BatteryState {
/// Return the string representation.
pub fn as_str(&self) -> &'static str {
match self {
BatteryState::Charging { .. } => "Charging",
BatteryState::Discharging { .. } => "Discharging",
BatteryState::Empty => "Empty",
BatteryState::Full => "Full",
BatteryState::Unknown => "Unknown",
}
}
}

#[derive(Debug, Clone)]
pub struct BatteryData {
/// Current charge percent.
pub charge_percent: f64,
/// Power consumption, in watts.
pub power_consumption: f64,
/// Reported battery health.
pub health_percent: f64,
/// The current battery "state" (e.g. is it full, charging, etc.).
pub state: BatteryState,
}

impl BatteryData {
pub fn watt_consumption(&self) -> String {
format!("{:.2}W", self.power_consumption)
}

pub fn health(&self) -> String {
format!("{:.2}%", self.health_percent)
}
}

#[cfg(feature = "battery")]
pub fn refresh_batteries(manager: &Manager, batteries: &mut [Battery]) -> Vec<BatteryData> {
batteries
.iter_mut()
.filter_map(|battery| {
if manager.refresh(battery).is_ok() {
Some(BatteryData {
charge_percent: f64::from(battery.state_of_charge().get::<percent>()),
power_consumption: f64::from(battery.energy_rate().get::<watt>()),
health_percent: f64::from(battery.state_of_health().get::<percent>()),
state: match battery.state() {
State::Unknown => BatteryState::Unknown,
State::Charging => BatteryState::Charging {
time_to_full: {
let optional_time = battery.time_to_full();
optional_time.map(|time| f64::from(time.get::<second>()) as u32)
},
},
State::Discharging => BatteryState::Discharging {
time_to_empty: {
let optional_time = battery.time_to_empty();
optional_time.map(|time| f64::from(time.get::<second>()) as u32)
},
},
State::Empty => BatteryState::Empty,
State::Full => BatteryState::Full,
},
})
} else {
None
}
})
.collect::<Vec<_>>()
}
Loading

0 comments on commit cd6c60c

Please sign in to comment.