testing ags

This commit is contained in:
cnst
2024-07-15 14:39:56 +02:00
parent 91e09c461b
commit 2f32e46601
55 changed files with 2218 additions and 22 deletions

View File

@@ -0,0 +1,62 @@
import { App, Widget } from "../../imports.js";
import Battery from "./modules/battery.js";
import Bluetooth from "./modules/bluetooth.js";
import Date from "./modules/date.js";
import Music from "./modules/music.js";
import Net from "./modules/net.js";
import CpuRam from "./modules/cpu_ram.js";
import Tray from "./modules/tray.js";
import Workspaces from "./modules/workspaces.js";
const SystemInfo = () =>
Widget.EventBox({
className: "system-menu-toggler",
onPrimaryClick: () => App.toggleWindow("system-menu"),
child: Widget.Box({
children: [Net(), Bluetooth(), Battery()],
}),
}).hook(App, (self, window, visible) => {
if (window === "system-menu") {
self.toggleClassName("active", visible);
}
});
const Start = () =>
Widget.Box({
hexpand: true,
hpack: "start",
children: [
Workspaces(),
// Indicators
],
});
const Center = () =>
Widget.Box({
children: [Music()],
});
const End = () =>
Widget.Box({
hexpand: true,
hpack: "end",
children: [Tray(), CpuRam(), SystemInfo(), Date()],
});
export default () =>
Widget.Window({
monitor: 0,
name: `bar`,
anchor: ["bottom", "left", "right"],
exclusivity: "exclusive",
child: Widget.CenterBox({
className: "bar",
startWidget: Start(),
centerWidget: Center(),
endWidget: End(),
}),
});

View File

@@ -0,0 +1,6 @@
import { Battery, Widget } from "../../../imports.js";
export default () =>
Widget.Icon({ className: "battery module" })
.bind("icon", Battery, "icon-name")
.bind("tooltip-text", Battery, "percent", (p) => `Battery on ${p}%`);

View File

@@ -0,0 +1,10 @@
import { Bluetooth, Widget } from "../../../imports.js";
import {
getBluetoothIcon,
getBluetoothText,
} from "../../../utils/bluetooth.js";
export default () =>
Widget.Icon({ className: "bluetooth module" })
.bind("icon", Bluetooth, "connected-devices", getBluetoothIcon)
.bind("tooltip-text", Bluetooth, "connected-devices", getBluetoothText);

View File

@@ -0,0 +1,70 @@
import { Utils, Widget } from "../../../imports.js";
const Indicator = (props) =>
Widget.Box({
vertical: true,
vexpand: true,
vpack: "center",
children: [
Widget.Label({
className: "type",
label: props.type,
}),
Widget.Label({ className: "value" }).poll(2000, props.poll),
],
}).poll(2000, props.boxpoll);
const cpu = {
type: "CPU",
poll: (self) =>
Utils.execAsync([
"sh",
"-c",
`top -bn1 | rg '%Cpu' | tail -1 | awk '{print 100-$8}'`,
])
.then((r) => (self.label = Math.round(Number(r)) + "%"))
.catch((err) => print(err)),
boxpoll: (self) =>
Utils.execAsync(["sh", "-c", "lscpu --parse=MHZ"])
.then((r) => {
const mhz = r.split("\n").slice(4);
const freq = mhz.reduce((acc, e) => acc + Number(e), 0) / mhz.length;
self.tooltipText = Math.round(freq) + " MHz";
})
.catch((err) => print(err)),
};
const ram = {
type: "MEM",
poll: (self) =>
Utils.execAsync([
"sh",
"-c",
`free | tail -2 | head -1 | awk '{print $3/$2*100}'`,
])
.then((r) => (self.label = Math.round(Number(r)) + "%"))
.catch((err) => print(err)),
boxpoll: (self) =>
Utils.execAsync([
"sh",
"-c",
"free --si -h | tail -2 | head -1 | awk '{print $3}'",
])
.then((r) => (self.tooltipText = r))
.catch((err) => print(err)),
};
export default () =>
Widget.EventBox({
onPrimaryClick: () => Utils.execAsync(["missioncenter"]),
child: Widget.Box({
className: "system-info module",
children: [Indicator(cpu), Indicator(ram)],
}),
});

View File

@@ -0,0 +1,10 @@
import { Utils, Widget } from "../../../imports.js";
export default () =>
Widget.EventBox({
child: Widget.Label({ className: "date module" }).poll(1000, (self) =>
Utils.execAsync(["date", "+%a %b %d %H:%M"]).then(
(r) => (self.label = r),
),
),
});

View File

@@ -0,0 +1,40 @@
import { Mpris, Widget } from "../../../imports.js";
import App from "resource:///com/github/Aylur/ags/app.js";
import { findPlayer } from "../../../utils/mpris.js";
const Cover = (player) =>
Widget.Box({ className: "cover" }).bind(
"css",
player,
"cover-path",
(cover) => `background-image: url('${cover ?? ""}');`,
);
const Title = (player) =>
Widget.Label({ className: "title module" }).bind(
"label",
player,
"track-title",
(title) => ((title ?? "") == "Unknown title" ? "" : title),
);
export const MusicBox = (player) =>
Widget.Box({
children: [Cover(player), Title(player)],
});
export default () =>
Widget.EventBox({
className: "music",
onPrimaryClick: () => App.toggleWindow("music"),
})
.hook(App, (self, window, visible) => {
if (window === "music") {
self.toggleClassName("active", visible);
}
})
.bind("visible", Mpris, "players", (p) => p.length > 0)
.bind("child", Mpris, "players", (players) => {
if (players.length == 0) return Widget.Box();
return MusicBox(findPlayer(players));
});

View File

@@ -0,0 +1,7 @@
import { Network, Widget } from "../../../imports.js";
import { getNetIcon, getNetText } from "../../../utils/net.js";
export default () =>
Widget.Icon({ className: "net module" })
.bind("icon", Network, "connectivity", getNetIcon)
.bind("tooltip-text", Network, "connectivity", getNetText);

View File

@@ -0,0 +1,47 @@
import { SystemTray, Widget } from "../../../imports.js";
import Gdk from "gi://Gdk?version=3.0";
const Item = (item) =>
Widget.Button({
child: Widget.Icon().bind("icon", item, "icon"),
onPrimaryClick: (_, ev) => {
try {
item.activate(ev);
} catch (err) {
print(err);
}
},
setup: (self) => {
const id = item.menu?.connect("popped-up", (menu) => {
self.toggleClassName("active");
menu.connect("notify::visible", (menu) => {
self.toggleClassName("active", menu.visible);
});
menu.disconnect(id);
});
if (id) {
self.connect("destroy", () => item.menu?.disconnect(id));
}
self.bind("tooltip-markup", item, "tooltip-markup");
},
onSecondaryClick: (btn) =>
item.menu?.popup_at_widget(
btn,
Gdk.Gravity.SOUTH,
Gdk.Gravity.NORTH,
null,
),
});
export default () =>
Widget.Box({ className: "tray module" }).bind(
"children",
SystemTray,
"items",
(items) => items.map(Item),
);

View File

@@ -0,0 +1,72 @@
import { Hyprland, Widget } from "../../../imports.js";
import {
added,
changeWorkspace,
DEFAULT_MONITOR,
focusedSwitch,
getLastWorkspaceId,
moveWorkspace,
removed,
workspaceActive,
} from "../../../utils/hyprland.js";
globalThis.hyprland = Hyprland;
const makeWorkspaces = () =>
[...Array(10)].map((_, i) => {
const id = i + 1;
return Widget.Button({
onPrimaryClick: () => changeWorkspace(id),
visible: getLastWorkspaceId() >= id,
setup: (self) => {
const ws = Hyprland.getWorkspace(id);
self.id = id;
self.active = workspaceActive(id);
self.monitor = DEFAULT_MONITOR;
if (self.active) {
self.monitor = {
name: ws?.monitor ?? DEFAULT_MONITOR.name,
id: ws?.monitorID ?? DEFAULT_MONITOR.id,
};
self.toggleClassName(`monitor${self.monitor.id}`, true);
}
},
});
});
export default () =>
Widget.EventBox({
onScrollUp: () => changeWorkspace("+1"),
onScrollDown: () => changeWorkspace("-1"),
child: Widget.Box({
className: "workspaces module",
// The Hyprland service is ready later than ags is done parsing the config,
// so only build the widget when we receive a signal from it.
setup: (self) => {
const connID = Hyprland.connect("notify::workspaces", () => {
Hyprland.disconnect(connID);
self.children = makeWorkspaces();
self.lastFocused = Hyprland.active.workspace.id;
self.biggestId = getLastWorkspaceId();
self
.hook(Hyprland.active.workspace, focusedSwitch)
.hook(Hyprland, added, "workspace-added")
.hook(Hyprland, removed, "workspace-removed")
.hook(
Hyprland,
(self, name, data) => {
if (name === "moveworkspace") moveWorkspace(self, data);
},
"event",
);
});
},
}),
});