refactor!: start migration to latest ags

This commit is contained in:
2025-12-05 17:00:22 -08:00
parent 1759e2d976
commit 42b4f99c37
12 changed files with 191 additions and 147 deletions

34
app.ts
View File

@@ -1,29 +1,25 @@
import { App, Gdk } from "astal/gtk3"; import app from "ags/gtk4/app"
import style from "./style.scss"; import style from "./style.scss"
import Bar from "./widget/Bar"; import Bar from "./widget/Bar"
import { GLib } from "astal"; import { interval } from "ags/time"
App.start({ app.start({
css: style, css: style,
icons: "icons", icons: "icons",
main() {}, main() {
}); checkMonitors()
interval(10000, () => checkMonitors())
},
})
let knownMonitors = new Set(); let knownMonitors = new Set()
function checkMonitors() { function checkMonitors() {
const currentMonitors = App.get_monitors(); const currentMonitors = app.get_monitors()
currentMonitors.forEach((monitor) => { currentMonitors.forEach((monitor) => {
if (!knownMonitors.has(monitor.model)) { if (!knownMonitors.has(monitor.model)) {
knownMonitors.add(monitor.model); knownMonitors.add(monitor.model)
Bar(monitor); Bar(monitor)
} }
}); })
} }
checkMonitors();
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 10, () => {
checkMonitors();
return true;
});

View File

@@ -1,14 +0,0 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"name": "astal-shell",
"dependencies": {
"astal": "/nix/store/pvb3x021mr6xknm91gqq76gy32n96vj0-astal-gjs/share/astal/gjs",
},
},
},
"packages": {
"astal": ["astal@file:../../../../nix/store/pvb3x021mr6xknm91gqq76gy32n96vj0-astal-gjs/share/astal/gjs", {}],
}
}

21
flake.lock generated
View File

@@ -42,6 +42,26 @@
"type": "github" "type": "github"
} }
}, },
"astal_2": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1764173295,
"narHash": "sha256-Jh4VtPcK2Ov+RTcV9FtyQRsxiJmXFQGfqX6jjM7/mgc=",
"owner": "aylur",
"repo": "astal",
"rev": "7d1fac8a4b2a14954843a978d2ddde86168c75ef",
"type": "github"
},
"original": {
"owner": "aylur",
"repo": "astal",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1764667669, "lastModified": 1764667669,
@@ -61,6 +81,7 @@
"root": { "root": {
"inputs": { "inputs": {
"ags": "ags", "ags": "ags",
"astal": "astal_2",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
} }
} }

View File

@@ -4,6 +4,11 @@
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
astal = {
url = "github:aylur/astal";
inputs.nixpkgs.follows = "nixpkgs";
};
ags = { ags = {
url = "github:aylur/ags"; url = "github:aylur/ags";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
@@ -15,6 +20,7 @@
self, self,
nixpkgs, nixpkgs,
ags, ags,
astal,
}: }:
let let
system = "x86_64-linux"; system = "x86_64-linux";
@@ -28,20 +34,52 @@
]; ];
in in
{ {
packages.${system} = { # packages.${system} = {
status-bar = ags.lib.bundle { # status-bar = ags.lib.bundle {
inherit pkgs; # inherit pkgs;
src = ./.; # src = ./.;
# name = "status-bar";
# entry = "app.ts";
#
# extraPackages =
# with pkgs;
# extraPkgs
# ++ [
# libgtop
# ];
# };
# };
packages.${system}.default = pkgs.stdenv.mkDerivation rec {
pname = "status-bar";
name = "status-bar"; name = "status-bar";
entry = "app.ts";
extraPackages = src = ./.;
with pkgs;
extraPkgs nativeBuildInputs = with pkgs; [
++ [ wrapGAppsHook3
libgtop gobject-introspection
ags.packages.${system}.default
]; ];
};
buildInputs = [
pkgs.glib
pkgs.libgtop
pkgs.gjs
astal.packages.${system}.io
astal.packages.${system}.astal4
astal.packages.${system}.battery
astal.packages.${system}.hyprland
astal.packages.${system}.network
astal.packages.${system}.wireplumber
];
installPhase = ''
mkdir -p $out/bin
mkdir -p $out/share
cp -r * $out/share
jj
ags bundle app.ts $out/bin/${pname} -d "SRC='$out/share'"
'';
}; };
devShells.${system} = { devShells.${system} = {

21
package-lock.json generated
View File

@@ -1,21 +0,0 @@
{
"name": "astal-shell",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "astal-shell",
"dependencies": {
"astal": "/nix/store/pvb3x021mr6xknm91gqq76gy32n96vj0-astal-gjs/share/astal/gjs"
}
},
"../../../../nix/store/pvb3x021mr6xknm91gqq76gy32n96vj0-astal-gjs/share/astal/gjs": {
"name": "astal",
"license": "LGPL-2.1"
},
"node_modules/astal": {
"resolved": "../../../../nix/store/pvb3x021mr6xknm91gqq76gy32n96vj0-astal-gjs/share/astal/gjs",
"link": true
}
}
}

View File

@@ -1,6 +1,10 @@
{ {
"name": "astal-shell",
"dependencies": { "dependencies": {
"astal": "/nix/store/pvb3x021mr6xknm91gqq76gy32n96vj0-astal-gjs/share/astal/gjs" "ags": "*",
"gnim": "*"
},
"prettier": {
"semi": false,
"tabWidth": 2
} }
} }

View File

@@ -1,14 +1,14 @@
{ {
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": { "compilerOptions": {
"experimentalDecorators": true, "jsx": "react-jsx",
"strict": false, "jsxImportSource": "ags/gtk4",
"target": "ES2022", "lib": [
"ES2023"
],
"module": "ES2022", "module": "ES2022",
"moduleResolution": "Bundler", "moduleResolution": "Bundler",
// "checkJs": true, "strict": true,
// "allowJs": true, "target": "ES2020"
"jsx": "react-jsx",
"jsxImportSource": "astal/gtk3",
} }
} }

View File

@@ -1,43 +1,35 @@
import { App, Astal, Gtk, Gdk } from "astal/gtk3"; import { Astal, Gtk, Gdk } from "ags/gtk4";
import Workspaces from "./workspaces"; // import Workspaces from "./workspaces";
import Audio from "./audio"; // import Audio from "./audio";
import NetworkModule from "./network"; // import NetworkModule from "./network";
import Cpu from "./cpu-widget"; // import Cpu from "./cpu-widget";
import Ram from "./ram"; // import Ram from "./ram";
import Disk from "./disk"; // import Disk from "./disk";
import Battery from "./battery"; // import Battery from "./battery";
import Time from "./time"; import Time from "./time";
import Title from "./title"; import Title from "./title";
import app from "ags/gtk4/app";
import Workspaces from "./workspaces";
export default function Bar(gdkmonitor: Gdk.Monitor) { export default function Bar(gdkmonitor: Gdk.Monitor) {
const { TOP, LEFT, RIGHT } = Astal.WindowAnchor; const { TOP, LEFT, RIGHT } = Astal.WindowAnchor;
//@ts-ignore
return ( return (
<window <window
className="Bar" visible
name="bar"
class="Bar"
gdkmonitor={gdkmonitor} gdkmonitor={gdkmonitor}
exclusivity={Astal.Exclusivity.EXCLUSIVE} exclusivity={Astal.Exclusivity.EXCLUSIVE}
anchor={TOP | LEFT | RIGHT} anchor={TOP | LEFT | RIGHT}
application={App} application={app}
> >
<centerbox> <centerbox>
<box hexpand halign={Gtk.Align.START}> <Workspaces $type="start" monitor={gdkmonitor} />
<box className="nix-icon"> <box $type="center" class="client-title">
<icon icon="nixos-3" />
</box>
<Workspaces monitor={gdkmonitor} />
</box>
<box className="client-title">
<Title /> <Title />
</box> </box>
<box hexpand halign={Gtk.Align.END}> <box $type="end">
<Audio />
<NetworkModule />
<Cpu />
<Ram />
<Disk />
<Battery />
<Time /> <Time />
</box> </box>
</centerbox> </centerbox>

View File

@@ -3,15 +3,16 @@ import AstalWp from "gi://AstalWp?version=0.1"
export default function Audio() { export default function Audio() {
const speaker = AstalWp.get_default()?.default_speaker! const speaker = AstalWp.get_default()?.default_speaker!
const derived = Variable.derive([bind(speaker, "volume"), bind(speaker, "mute")], (volume: number, muted: boolean) => { // const derived = Variable.derive([bind(speaker, "volume"), bind(speaker, "mute")], (volume: number, muted: boolean) => {
if (muted) { // if (muted) {
return { label: ` (muted)`, muted } // return { label: ` (muted)`, muted }
} // }
return { label: `${Math.floor(volume * 100)}% ` } // 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>
return <box className={derived((v) => ["status-box", v.muted && "inactive"].filter(Boolean).join(" "))}>
<label
label={derived((v) => v.label)} />
</box>
} }

View File

@@ -1,15 +1,24 @@
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("%b %e (%a) %H:%M"))
// return true
let current_time = Variable(GLib.DateTime.new_now_local().format("%H:%M")) import { createPoll } from "ags/time"
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => {
const now = GLib.DateTime.new_now_local() // })
current_time.set(now.format("%b %e (%a) %H:%M"))
return true
})
export default function Time() { export default function Time() {
const time = createPoll("", 500, () => {
return new Date().toLocaleString(undefined, {
hour12: false
})
})
return <box className="status-box"> return <box class="status-box">
<label label={bind(current_time)} /> <label label={time} />
</box> </box>
// return <box class="status-box">
// <label label={bind(current_time)} />
// </box>
} }

View File

@@ -1,5 +1,6 @@
import { bind, Variable } from "astal" import { createPoll } from "ags/time";
import AstalHyprland from "gi://AstalHyprland?version=0.1"; import AstalHyprland from "gi://AstalHyprland?version=0.1";
import { createState } from "gnim";
const hyprland = AstalHyprland.get_default() const hyprland = AstalHyprland.get_default()
@@ -7,10 +8,15 @@ function get_title() {
return hyprland.focusedClient?.title ?? "" return hyprland.focusedClient?.title ?? ""
} }
const title = Variable(get_title()).poll(200, () => get_title()) // const title = Variable(get_title()).poll(200, () => get_title())
export default function Title() { export default function Title() {
const title = createPoll("", 200, () => get_title())
return ( return (
<label label={title(t => t)} /> <label label={title} />
) )
// return (
// <label label={title(t => t)} />
// )
} }

View File

@@ -1,23 +1,35 @@
import { bind } from "astal" import { Gdk } from "ags/gtk4"
import { Gdk } from "astal/gtk3"
import AstalHyprland from "gi://AstalHyprland?version=0.1" import AstalHyprland from "gi://AstalHyprland?version=0.1"
import { createBinding, For } from "gnim"
export default function Workspaces({ monitor }: { monitor: Gdk.Monitor }) { export default function Workspaces({ monitor }: { monitor: Gdk.Monitor }) {
const hypr = AstalHyprland.get_default() const hypr = AstalHyprland.get_default()
const workspaces = createBinding(hypr, "workspaces").as(wss => wss.sort((a, b) => a.id - b.id))
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 ( return (
<button <box class="workspaces">
className={bind(hypr, "focusedWorkspace").as(fw => <For each={workspaces}>
ws === fw ? "focused" : "")} {(ws) => (
onClicked={() => ws.focus()}> <button class={createBinding(hypr, "focusedWorkspace").as((fw) => ws === fw ? "focused" : "")}>
{ws.id} <label label={ws.id.toString()} />
</button> </button>
) )}
}))} </For>
</box> </box>
)
// 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>
} }