feat: check for matcha availability

We want to check if matcha will be available both as a binary and as a
daemon, as it needs to be running in the background. If those are not
met, the idle inhibitor cannot be shown.
This commit is contained in:
Anthony Rodriguez 2025-02-16 13:05:34 +01:00
parent 5a918d507a
commit eb7c276914
Signed by: nezia
SSH key fingerprint: SHA256:R/ue1eTzTHUoo77lJD/3fSUsyL4AwvcHImU5BAZai+8
7 changed files with 63 additions and 21 deletions

2
app.ts
View file

@ -1,6 +1,6 @@
import { App } from "astal/gtk4";
import style from "./style.scss";
import Bar from "./widget/Bar";
import Bar from "@/widget/Bar";
App.start({
css: style,

View file

@ -31,6 +31,8 @@
network
tray
wireplumber
pkgs.brightnessctl
matcha.packages.${pkgs.system}.default
];
in {
packages.${system} = {

19
src/lib/utils.ts Normal file
View file

@ -0,0 +1,19 @@
import { execAsync } from "astal";
// https://github.com/andre-brandao/hyprshell/blob/bb26e6a1f9afa924b3bb4acfbf822e8fed37221e/src/lib/utils.ts
/**
* @returns true if all of the `bins` are found
*/
export function dependencies(...bins: string[]) {
const missing = bins.filter((bin) => {
execAsync(`which ${bin}`)
.then(() => true)
.catch(() => false);
});
if (missing.length > 0) {
console.warn(Error(`missing dependencies: ${missing.join(", ")}`));
}
return missing.length === 0;
}

View file

@ -1,11 +1,12 @@
import { Astal, Gtk, Gdk } from "astal/gtk4";
import { Variable, GLib, bind, execAsync, exec } from "astal";
import { Variable, GLib, bind, exec } from "astal";
import Battery from "gi://AstalBattery";
import Bluetooth from "gi://AstalBluetooth";
import Wp from "gi://AstalWp";
import Network from "gi://AstalNetwork";
import Hyprland from "gi://AstalHyprland";
import Brightness from "../service/brightness";
import Brightness from "@/service/brightness";
import { dependencies } from "@/lib/utils";
const network = Network.get_default();
const wifi = bind(network, "wifi");
@ -102,25 +103,41 @@ function Time({ format = "%H:%M - %A %e." }) {
);
}
function IdleInhibitor() {
const icon = Variable(getIcon());
type IdleState = "active" | "inactive" | "unknown";
function getIcon() {
const state = exec("matcha --status");
const enabled = state.match(/on/g);
return enabled ? "my-caffeine-on-symbolic" : "my-caffeine-off-symbolic";
function IdleInhibitor() {
/*
* matcha needs additional checking to ensure the daemon is properly running
*/
function isDaemonRunning() {
try {
exec("matcha --status");
return true;
} catch {
return false;
}
}
if (!dependencies("matcha") || !isDaemonRunning()) return <></>;
const state = Variable<IdleState>("unknown");
function toggle() {
exec("matcha --toggle");
icon.set(getIcon());
const response = exec("matcha --status");
const enabled = response.match(/on/g);
state.set(enabled ? "active" : "inactive");
}
return (
<box cssName="IdleInhibitor">
<button
onClicked={() => toggle()}
iconName={bind(icon).as((iconName) => iconName)}
iconName={bind(state).as((s) =>
s === "active"
? "my-caffeine-on-symbolic"
: "my-caffeine-off-symbolic",
)}
/>
</box>
);

View file

@ -1,12 +1,16 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"experimentalDecorators": true,
"jsx": "react-jsx",
"jsxImportSource": "astal/gtk4",
"module": "ES2022",
"moduleResolution": "Bundler",
"strict": true,
"target": "ES2022"
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"experimentalDecorators": true,
"jsx": "react-jsx",
"jsxImportSource": "astal/gtk4",
"module": "ES2022",
"moduleResolution": "Bundler",
"strict": true,
"target": "ES2022",
"paths": {
"@": ["./src"],
"@/*": ["./src/*"]
}
}
}
}