refactor: reorganize components, add interface to network
This commit is contained in:
@@ -1,134 +1,12 @@
|
|||||||
import { App, Astal, Gtk, Gdk } from "astal/gtk3"
|
import { App, Astal, Gtk, Gdk } from "astal/gtk3"
|
||||||
import { bind, derive, GLib, Variable } from "astal"
|
import Workspaces from "./workspaces"
|
||||||
import Hyprland from "gi://AstalHyprland"
|
import Audio from "./audio"
|
||||||
import Wp from "gi://AstalWp"
|
import NetworkModule from "./network"
|
||||||
import Network from "gi://AstalNetwork"
|
import Cpu from "./cpu-widget"
|
||||||
import GTop from "gi://GTop"
|
import Ram from "./ram"
|
||||||
import { calc_cpu_usage, get_cpu_snapshot, get_disk_space, get_ram_info } from "./cpu"
|
import Disk from "./disk"
|
||||||
import AstalBattery from "gi://AstalBattery"
|
import Battery from "./battery"
|
||||||
|
import Time from "./time"
|
||||||
function Workspaces({ monitor }: { monitor: Gdk.Monitor }) {
|
|
||||||
const hypr = Hyprland.get_default()
|
|
||||||
|
|
||||||
return <box className="workspaces">
|
|
||||||
{bind(hypr, "workspaces").as(wss => wss.filter(ws => !(ws.id >= -99 && ws.id <= -2))
|
|
||||||
.sort((a, b) => a.id - b.id)
|
|
||||||
.map(ws => {
|
|
||||||
if (ws.monitor.model !== monitor.model) return <></>
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
className={bind(hypr, "focusedWorkspace").as(fw =>
|
|
||||||
ws === fw ? "focused" : "")}
|
|
||||||
onClicked={() => ws.focus()}>
|
|
||||||
{ws.id}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
}))}
|
|
||||||
</box>
|
|
||||||
}
|
|
||||||
|
|
||||||
function Audio() {
|
|
||||||
const speaker = Wp.get_default()?.default_speaker!
|
|
||||||
const derived = Variable.derive([bind(speaker, "volume"), bind(speaker, "mute")], (volume: number, muted: boolean) => {
|
|
||||||
if (muted) {
|
|
||||||
return { label: ` (muted)`, muted }
|
|
||||||
}
|
|
||||||
return { label: `${Math.floor(volume * 100)}% ` }
|
|
||||||
})
|
|
||||||
|
|
||||||
return <box className={derived((v) => ["status-box", v.muted && "inactive"].filter(Boolean).join(" "))}>
|
|
||||||
<label
|
|
||||||
label={derived((v) => v.label)} />
|
|
||||||
</box>
|
|
||||||
}
|
|
||||||
|
|
||||||
function NetworkModule() {
|
|
||||||
const network = Network.get_default()
|
|
||||||
const wifi = network.wifi;
|
|
||||||
const wired = network.wired
|
|
||||||
|
|
||||||
const derived = Variable.derive([bind(network, "primary"), bind(wifi, "ssid"), bind(wifi, "strength")], (primary, ssid, strength) => {
|
|
||||||
if (primary === Network.Primary.WIRED) {
|
|
||||||
return { label: "🖧 Wired" }
|
|
||||||
}
|
|
||||||
if (wifi.active_access_point !== null) {
|
|
||||||
return { label: `${ssid} (${strength}%) ` }
|
|
||||||
}
|
|
||||||
return { label: `Disconnected ⚠` }
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
|
||||||
<box className="status-box">
|
|
||||||
<label
|
|
||||||
label={derived((v) => v.label)} />
|
|
||||||
</box>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let s1 = get_cpu_snapshot();
|
|
||||||
let cpu_usage_percent = Variable(0);
|
|
||||||
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
|
|
||||||
const s2 = get_cpu_snapshot();
|
|
||||||
cpu_usage_percent.set(calc_cpu_usage(s1, s2));
|
|
||||||
s1 = s2;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
function Cpu() {
|
|
||||||
return <box className="status-box">
|
|
||||||
<label label={bind(cpu_usage_percent).as((u) => `${u}% `)} />
|
|
||||||
</box>
|
|
||||||
}
|
|
||||||
|
|
||||||
let info = Variable(get_ram_info())
|
|
||||||
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
|
|
||||||
info.set(get_ram_info())
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
function Ram() {
|
|
||||||
return <box className="status-box">
|
|
||||||
<label label={bind(info).as((i) => `${Math.round((i.used / i.total) * 100)}% `)} />
|
|
||||||
</box>
|
|
||||||
}
|
|
||||||
|
|
||||||
let disk_space = Variable(get_disk_space()).poll(5000, () => get_disk_space())
|
|
||||||
function Disk() {
|
|
||||||
return <box className="status-box">
|
|
||||||
<label label={bind(disk_space).as((s) => `${s}`)} />
|
|
||||||
</box>
|
|
||||||
}
|
|
||||||
|
|
||||||
function Battery() {
|
|
||||||
const battery = AstalBattery.get_default()
|
|
||||||
const battery_info = Variable.derive([bind(battery, "percentage"), bind(battery, "charging")], (percentage, charging) => {
|
|
||||||
const full_percentage = Math.floor(percentage * 100)
|
|
||||||
if (charging) {
|
|
||||||
return { label: `${full_percentage == 100 ? "FULL" : "CHR"}: ${full_percentage}%` }
|
|
||||||
}
|
|
||||||
return { label: `${full_percentage == 100 ? "FULL" : "BAT"}: ${full_percentage}%` }
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!battery.is_battery) {
|
|
||||||
return <></>
|
|
||||||
}
|
|
||||||
return <box className="status-box">
|
|
||||||
<label label={battery_info((i) => i.label)} />
|
|
||||||
</box>
|
|
||||||
}
|
|
||||||
|
|
||||||
let current_time = Variable(GLib.DateTime.new_now_local().format("%H:%M"))
|
|
||||||
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
|
|
||||||
const now = GLib.DateTime.new_now_local()
|
|
||||||
current_time.set(now.format("%H:%M"))
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
function Time() {
|
|
||||||
|
|
||||||
return <box className="status-box">
|
|
||||||
<label label={bind(current_time)} />
|
|
||||||
</box>
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Bar(gdkmonitor: Gdk.Monitor) {
|
export default function Bar(gdkmonitor: Gdk.Monitor) {
|
||||||
const { BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor
|
const { BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor
|
||||||
|
|||||||
17
astal/widget/audio.tsx
Normal file
17
astal/widget/audio.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { bind, Variable } from "astal"
|
||||||
|
import AstalWp from "gi://AstalWp?version=0.1"
|
||||||
|
|
||||||
|
export default function Audio() {
|
||||||
|
const speaker = AstalWp.get_default()?.default_speaker!
|
||||||
|
const derived = Variable.derive([bind(speaker, "volume"), bind(speaker, "mute")], (volume: number, muted: boolean) => {
|
||||||
|
if (muted) {
|
||||||
|
return { label: ` (muted)`, muted }
|
||||||
|
}
|
||||||
|
return { label: `${Math.floor(volume * 100)}% ` }
|
||||||
|
})
|
||||||
|
|
||||||
|
return <box className={derived((v) => ["status-box", v.muted && "inactive"].filter(Boolean).join(" "))}>
|
||||||
|
<label
|
||||||
|
label={derived((v) => v.label)} />
|
||||||
|
</box>
|
||||||
|
}
|
||||||
21
astal/widget/battery.tsx
Normal file
21
astal/widget/battery.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { bind, Variable } from "astal"
|
||||||
|
import AstalBattery from "gi://AstalBattery?version=0.1"
|
||||||
|
|
||||||
|
export default function Battery() {
|
||||||
|
const battery = AstalBattery.get_default()
|
||||||
|
const battery_info = Variable.derive([bind(battery, "percentage"), bind(battery, "charging")], (percentage, charging) => {
|
||||||
|
const full_percentage = Math.floor(percentage * 100)
|
||||||
|
if (charging) {
|
||||||
|
return { label: `${full_percentage == 100 ? "FULL" : "CHR"}: ${full_percentage}%` }
|
||||||
|
}
|
||||||
|
return { label: `${full_percentage == 100 ? "FULL" : "BAT"}: ${full_percentage}%` }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!battery.is_battery) {
|
||||||
|
return <></>
|
||||||
|
}
|
||||||
|
return <box className="status-box">
|
||||||
|
<label label={battery_info((i) => i.label)} />
|
||||||
|
</box>
|
||||||
|
}
|
||||||
|
|
||||||
19
astal/widget/cpu-widget.tsx
Normal file
19
astal/widget/cpu-widget.tsx
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { bind, GLib, Variable } from "astal";
|
||||||
|
import { calc_cpu_usage, get_cpu_snapshot } from "./cpu";
|
||||||
|
|
||||||
|
let s1 = get_cpu_snapshot();
|
||||||
|
let cpu_usage_percent = Variable(0);
|
||||||
|
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
|
||||||
|
const s2 = get_cpu_snapshot();
|
||||||
|
cpu_usage_percent.set(calc_cpu_usage(s1, s2));
|
||||||
|
s1 = s2;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function Cpu() {
|
||||||
|
return <box className="status-box">
|
||||||
|
<label label={bind(cpu_usage_percent).as((u) => `${u}% `)} />
|
||||||
|
</box>
|
||||||
|
}
|
||||||
|
|
||||||
10
astal/widget/disk.tsx
Normal file
10
astal/widget/disk.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { bind, Variable } from "astal"
|
||||||
|
import { get_disk_space } from "./cpu"
|
||||||
|
|
||||||
|
let disk_space = Variable(get_disk_space()).poll(5000, () => get_disk_space())
|
||||||
|
export default function Disk() {
|
||||||
|
return <box className="status-box">
|
||||||
|
<label label={bind(disk_space).as((s) => `${s}`)} />
|
||||||
|
</box>
|
||||||
|
}
|
||||||
|
|
||||||
26
astal/widget/network.tsx
Normal file
26
astal/widget/network.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { bind, Variable } from "astal";
|
||||||
|
import AstalNetwork from "gi://AstalNetwork?version=0.1";
|
||||||
|
|
||||||
|
export default function NetworkModule() {
|
||||||
|
const network = AstalNetwork.get_default()
|
||||||
|
const wifi = network.wifi;
|
||||||
|
const wired = network.wired
|
||||||
|
|
||||||
|
const derived = Variable.derive([bind(network, "primary"), bind(wifi, "ssid"), bind(wifi, "strength")], (primary, ssid, strength) => {
|
||||||
|
if (primary === AstalNetwork.Primary.WIRED) {
|
||||||
|
return { label: `🖧 Wired ${wired.device.interface}` }
|
||||||
|
}
|
||||||
|
if (wifi.active_access_point !== null) {
|
||||||
|
return { label: `${ssid} (${strength}%) ` }
|
||||||
|
}
|
||||||
|
return { label: `Disconnected ⚠` }
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<box className="status-box">
|
||||||
|
<label
|
||||||
|
label={derived((v) => v.label)} />
|
||||||
|
</box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
16
astal/widget/ram.tsx
Normal file
16
astal/widget/ram.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { bind, GLib, Variable } from "astal"
|
||||||
|
import { get_ram_info } from "./cpu"
|
||||||
|
|
||||||
|
let info = Variable(get_ram_info())
|
||||||
|
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
|
||||||
|
info.set(get_ram_info())
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
export default function Ram() {
|
||||||
|
return <box className="status-box">
|
||||||
|
<label label={bind(info).as((i) => `${Math.round((i.used / i.total) * 100)}% `)} />
|
||||||
|
</box>
|
||||||
|
}
|
||||||
|
|
||||||
15
astal/widget/time.tsx
Normal file
15
astal/widget/time.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { bind, GLib, Variable } from "astal"
|
||||||
|
|
||||||
|
let current_time = Variable(GLib.DateTime.new_now_local().format("%H:%M"))
|
||||||
|
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
|
||||||
|
const now = GLib.DateTime.new_now_local()
|
||||||
|
current_time.set(now.format("%H:%M"))
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
export default function Time() {
|
||||||
|
|
||||||
|
return <box className="status-box">
|
||||||
|
<label label={bind(current_time)} />
|
||||||
|
</box>
|
||||||
|
}
|
||||||
|
|
||||||
23
astal/widget/workspaces.tsx
Normal file
23
astal/widget/workspaces.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { bind } from "astal"
|
||||||
|
import { Gdk } from "astal/gtk3"
|
||||||
|
import AstalHyprland from "gi://AstalHyprland?version=0.1"
|
||||||
|
|
||||||
|
export default function Workspaces({ monitor }: { monitor: Gdk.Monitor }) {
|
||||||
|
const hypr = AstalHyprland.get_default()
|
||||||
|
|
||||||
|
return <box className="workspaces">
|
||||||
|
{bind(hypr, "workspaces").as(wss => wss.filter(ws => !(ws.id >= -99 && ws.id <= -2))
|
||||||
|
.sort((a, b) => a.id - b.id)
|
||||||
|
.map(ws => {
|
||||||
|
if (ws.monitor.model !== monitor.model) return <></>
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={bind(hypr, "focusedWorkspace").as(fw =>
|
||||||
|
ws === fw ? "focused" : "")}
|
||||||
|
onClicked={() => ws.focus()}>
|
||||||
|
{ws.id}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}))}
|
||||||
|
</box>
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user