aboutsummaryrefslogtreecommitdiff
path: root/ags
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ags/config.js41
-rw-r--r--ags/modules/applauncher.js107
-rw-r--r--ags/modules/bar.js131
3 files changed, 241 insertions, 38 deletions
diff --git a/ags/config.js b/ags/config.js
index bc50aa8..cc69e2e 100644
--- a/ags/config.js
+++ b/ags/config.js
@@ -1,41 +1,6 @@
-// @ts-ignore
-const battery = await Service.import("battery")
-
-const BatteryPercent = () => Widget.Label()
- .hook(battery, self => {
- self.label = `${battery.percent}%`
- self.visible = battery.available
- }, "changed")
-
-const MyButton = () => Widget.Button()
- .on("clicked", self => {
- print(self, "is clicked")
- })
-
-const MyDate = () => Widget.Label({
- css: "color:blue; padding: 1em;",
-})
- .poll(1000, self => {
- self.label = Utils.exec("date +'%_H:%_M:%S'")
- })
-
-const MyKeybind = () => Widget.Button()
- .keybind(["MOD1", "CONTROL"], "a", (_self, _event) => {
- print("alt+control+a was pressed")
- })
-
-const Bar = () => Widget.Window({
- name: 'bar',
- anchor: ['top', 'left', 'right'],
- child: MyDate(),
-})
-
-const scss = `${App.configDir}/style.scss`
-const css = "/tmp/my-style.css"
-Utils.exec(`sassc ${scss} ${css}`)
+import { applauncher } from "./modules/applauncher.js"
+import { Bar } from "./modules/bar.js"
App.config({
- style: css,
- windows: [Bar()],
+ windows: [applauncher, Bar(0)],
})
-
diff --git a/ags/modules/applauncher.js b/ags/modules/applauncher.js
new file mode 100644
index 0000000..f380185
--- /dev/null
+++ b/ags/modules/applauncher.js
@@ -0,0 +1,107 @@
+const { query } = await Service.import("applications")
+const WINDOW_NAME = "applauncher"
+
+/** @param {import('resource:///com/github/Aylur/ags/service/applications.js').Application} app */
+const AppItem = app => Widget.Button({
+ on_clicked: () => {
+ App.closeWindow(WINDOW_NAME)
+ app.launch()
+ },
+ attribute: { app },
+ child: Widget.Box({
+ children: [
+ Widget.Icon({
+ icon: app.icon_name || "",
+ size: 42,
+ }),
+ Widget.Label({
+ class_name: "title",
+ label: app.name,
+ xalign: 0,
+ vpack: "center",
+ truncate: "end",
+ }),
+ ],
+ }),
+})
+
+const Applauncher = ({ width = 500, height = 500, spacing = 12 }) => {
+ // list of application buttons
+ let applications = query("").map(AppItem)
+
+ // container holding the buttons
+ const list = Widget.Box({
+ vertical: true,
+ children: applications,
+ spacing,
+ })
+
+ // repopulate the box, so the most frequent apps are on top of the list
+ function repopulate() {
+ applications = query("").map(AppItem)
+ list.children = applications
+ }
+
+ // search entry
+ const entry = Widget.Entry({
+ hexpand: true,
+ css: `margin-bottom: ${spacing}px;`,
+
+ // to launch the first item on Enter
+ on_accept: () => {
+ // make sure we only consider visible (searched for) applications
+ const results = applications.filter((item) => item.visible);
+ if (results[0]) {
+ App.toggleWindow(WINDOW_NAME)
+ results[0].attribute.app.launch()
+ }
+ },
+
+ // filter out the list
+ on_change: ({ text }) => applications.forEach(item => {
+ item.visible = item.attribute.app.match(text ?? "")
+ }),
+ })
+
+ return Widget.Box({
+ vertical: true,
+ css: `margin: ${spacing * 2}px;`,
+ children: [
+ entry,
+
+ // wrap the list in a scrollable
+ Widget.Scrollable({
+ hscroll: "never",
+ css: `min-width: ${width}px;`
+ + `min-height: ${height}px;`,
+ child: list,
+ }),
+ ],
+ setup: self => self.hook(App, (_, windowName, visible) => {
+ if (windowName !== WINDOW_NAME)
+ return
+
+ // when the applauncher shows up
+ if (visible) {
+ repopulate()
+ entry.text = ""
+ entry.grab_focus()
+ }
+ }),
+ })
+}
+
+// there needs to be only one instance
+export const applauncher = Widget.Window({
+ name: WINDOW_NAME,
+ setup: self => self.keybind("Escape", () => {
+ App.closeWindow(WINDOW_NAME)
+ }),
+ visible: false,
+ keymode: "exclusive",
+ child: Applauncher({
+ width: 500,
+ height: 500,
+ spacing: 12,
+ }),
+})
diff --git a/ags/modules/bar.js b/ags/modules/bar.js
new file mode 100644
index 0000000..28fdaee
--- /dev/null
+++ b/ags/modules/bar.js
@@ -0,0 +1,131 @@
+const hyprland = await Service.import("hyprland")
+const audio = await Service.import("audio")
+const battery = await Service.import("battery")
+const network = await Service.import("network")
+
+const hour = Variable("", {
+ poll: [60000, 'date "+%H:%M"']
+})
+
+function IconLabel(icon, label) {
+ return [
+ Widget.Icon({ icon }),
+ Widget.Label({ label }),
+ ]
+}
+
+function Workspaces() {
+ const active = hyprland.active.workspace.bind("id")
+ const workspaces = hyprland.bind("workspaces")
+ .as(ws => ws.map(({ id }) => Widget.Button({
+ on_clicked: () => hyprland.messageAsync(`dispatch workspace ${id}`),
+ child: Widget.Label(`${id}`),
+ class_name: active.as(i => `${i === id ? "focused" : ""}`)
+ })))
+ return Widget.Box({
+ class_name: "workspaces",
+ children: workspaces,
+ })
+}
+
+//function SysTray() {
+//
+//}
+
+function Clock() {
+ return Widget.Label({
+ class_name: "clock",
+ label: hour.bind(),
+ })
+}
+
+function Network() {
+ const label = network.wifi.bind("strength").as(s => ` ${s}`)
+ return Widget.Box({
+ class_name: "network",
+ children: [
+ Widget.Label({ label })
+ ]
+ })
+}
+
+function Volume() {
+ const icons = {
+ 101: "overamplified",
+ 67: "high",
+ 34: "medium",
+ 1: "low",
+ 0: "muted",
+ }
+ function getIcon() {
+ const icon = audio.speaker.is_muted ? 0 : [101, 67, 34, 1, 0].find(
+ threshold => threshold <= audio.speaker.volume * 100)
+
+ return `audio-volume-${icons[icon]}-symbolic`
+ }
+
+ const icon = Utils.watch(getIcon(), audio.speaker, getIcon)
+ const label = audio.speaker.bind("volume").as(v => ` ${Math.floor(v * 100 + 0.01)}%`)
+
+ return Widget.Box({
+ class_name: "volume",
+ children: IconLabel(icon, label)
+ })
+}
+
+function Battery() {
+ const label = battery.bind("percent").as(p => ` ${p}%`)
+ const icon = battery.bind("percent").as(p =>
+ `battery-level-${Math.floor(p / 10) * 10}-symbolic`
+ )
+
+ return Widget.Box({
+ class_name: "battery",
+ children: IconLabel(icon, label)
+ })
+}
+
+function Left() {
+ return Widget.Box({
+ spacing: 10,
+ children: [
+ Workspaces(),
+ //SysTray(),
+ ]
+ })
+}
+function Center() {
+ return Widget.Box({
+ spacing: 10,
+ children: [
+ Clock(),
+ ]
+ })
+}
+function Right() {
+ return Widget.Box({
+ hpack: "end",
+ spacing: 10,
+ children: [
+ Network(),
+ Volume(),
+ Battery(),
+ ]
+ })
+}
+
+export function Bar(monitor = 0) {
+ return Widget.Window({
+ name: `bar-${monitor}`,
+ class_name: "bar",
+ monitor,
+ anchor: ["top", "left", "right"],
+ exclusivity: "exclusive",
+ child: Widget.CenterBox({
+ start_widget: Left(),
+ center_widget: Center(),
+ end_widget: Right(),
+ }),
+ })
+}
+