61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
import Gtk from "gi://Gtk?version=3.0"
|
|
import AstalBattery from "gi://AstalBattery"
|
|
import { type Binding, Variable, bind } from "astal"
|
|
|
|
const battery = AstalBattery.get_default()
|
|
|
|
const CHARGING = 1
|
|
const DISCHARGING = 2
|
|
const FULLY_CHARGED = 4
|
|
|
|
function fmtTime(seconds: number) {
|
|
if (!seconds || seconds <= 0) return null
|
|
const h = Math.floor(seconds / 3600)
|
|
const m = Math.round((seconds % 3600) / 60)
|
|
return h > 0 ? `${h}h ${m}m` : `${m}m`
|
|
}
|
|
|
|
const status = Variable.derive(
|
|
[bind(battery, "state"), bind(battery, "time-to-empty"), bind(battery, "time-to-full")],
|
|
(state, toEmpty, toFull) => {
|
|
if (state === FULLY_CHARGED) return "fully charged"
|
|
if (state === CHARGING) {
|
|
const t = fmtTime(toFull)
|
|
return t ? `charging · ${t} to full` : "charging"
|
|
}
|
|
if (state === DISCHARGING) {
|
|
const t = fmtTime(toEmpty)
|
|
return t ? `${t} left` : "on battery"
|
|
}
|
|
return ""
|
|
},
|
|
)
|
|
|
|
export const batteryIcon: Binding<string> | null = battery.isBattery
|
|
? bind(battery, "icon-name")
|
|
: null
|
|
|
|
export const batteryPercent: Binding<string> | null = battery.isBattery
|
|
? bind(battery, "percentage").as((p) => `${Math.round(p * 100)}%`)
|
|
: null
|
|
|
|
export function BatterySection() {
|
|
if (!battery.isBattery) return <box />
|
|
|
|
return (
|
|
<box className="battery-section">
|
|
<icon icon={bind(battery, "icon-name")} />
|
|
<label
|
|
className="battery-percent"
|
|
label={bind(battery, "percentage").as((p) => `${Math.round(p * 100)}%`)}
|
|
/>
|
|
<label
|
|
className="battery-status"
|
|
label={status()}
|
|
visible={status().as((text) => text !== "")}
|
|
hexpand
|
|
halign={Gtk.Align.START}
|
|
/>
|
|
</box>
|
|
)
|
|
} |