From b4aca729ddae0526b66822698db7066cb09e1682 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sun, 12 Jan 2025 18:00:54 +1100 Subject: bar --- .gitignore | 1 + app.tsx | 28 +++ assets/icons/caelestia-media-generic-symbolic.svg | 2 + assets/icons/caelestia-media-none-symbolic.svg | 19 ++ assets/icons/caelestia-spotify-symbolic.svg | 21 ++ modules/bar.tsx | 283 ++++++++++++++++++++++ scss/_font.scss | 21 ++ scss/_lib.scss | 29 +++ scss/bar.scss | 103 ++++++++ scss/scheme/_mocha.scss | 26 ++ scss/widgets.scss | 120 +++++++++ services/apps.ts | 3 + services/players.ts | 157 ++++++++++++ style.scss | 9 + utils/constants.ts | 3 + utils/icons.ts | 118 +++++++++ utils/mpris.ts | 16 ++ utils/strings.ts | 1 + utils/system.ts | 21 ++ utils/widgets.tsx | 45 ++++ 20 files changed, 1026 insertions(+) create mode 100644 app.tsx create mode 100644 assets/icons/caelestia-media-generic-symbolic.svg create mode 100644 assets/icons/caelestia-media-none-symbolic.svg create mode 100644 assets/icons/caelestia-spotify-symbolic.svg create mode 100644 modules/bar.tsx create mode 100644 scss/_font.scss create mode 100644 scss/_lib.scss create mode 100644 scss/bar.scss create mode 100644 scss/scheme/_mocha.scss create mode 100644 scss/widgets.scss create mode 100644 services/apps.ts create mode 100644 services/players.ts create mode 100644 style.scss create mode 100644 utils/constants.ts create mode 100644 utils/icons.ts create mode 100644 utils/mpris.ts create mode 100644 utils/strings.ts create mode 100644 utils/system.ts create mode 100644 utils/widgets.tsx diff --git a/.gitignore b/.gitignore index c5d317c..89341d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ @girs/ node_modules/ +scss/scheme/_index.scss diff --git a/app.tsx b/app.tsx new file mode 100644 index 0000000..4f61699 --- /dev/null +++ b/app.tsx @@ -0,0 +1,28 @@ +import { execAsync, GLib, writeFileAsync } from "astal"; +import { App } from "astal/gtk3"; +import AstalHyprland from "gi://AstalHyprland"; +import Bar from "./modules/bar"; + +const loadStyleAsync = async () => { + if (!GLib.file_test(`${SRC}/scss/scheme/_index.scss`, GLib.FileTest.EXISTS)) + await writeFileAsync(`${SRC}/scss/scheme/_index.scss`, '@forward "mocha";'); + App.apply_css(await execAsync(`sass ${SRC}/style.scss`), true); +}; + +App.start({ + instanceName: "caelestia", + icons: "assets/icons", + main() { + loadStyleAsync().catch(console.error); + + AstalHyprland.get_default().monitors.forEach(m => ); + + console.log("Caelestia started"); + }, + requestHandler(request, res) { + if (request === "reload css") loadStyleAsync().catch(console.error); + else return res("Unknown command: " + request); + console.log(`Request handled: ${request}`); + res("OK"); + }, +}); diff --git a/assets/icons/caelestia-media-generic-symbolic.svg b/assets/icons/caelestia-media-generic-symbolic.svg new file mode 100644 index 0000000..8ff60ed --- /dev/null +++ b/assets/icons/caelestia-media-generic-symbolic.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/assets/icons/caelestia-media-none-symbolic.svg b/assets/icons/caelestia-media-none-symbolic.svg new file mode 100644 index 0000000..20ea19a --- /dev/null +++ b/assets/icons/caelestia-media-none-symbolic.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/icons/caelestia-spotify-symbolic.svg b/assets/icons/caelestia-spotify-symbolic.svg new file mode 100644 index 0000000..bf01823 --- /dev/null +++ b/assets/icons/caelestia-spotify-symbolic.svg @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/modules/bar.tsx b/modules/bar.tsx new file mode 100644 index 0000000..1db5e82 --- /dev/null +++ b/modules/bar.tsx @@ -0,0 +1,283 @@ +import { GLib, register, Variable } from "astal"; +import { bind, kebabify } from "astal/binding"; +import { App, Astal, astalify, Gdk, Gtk, type ConstructProps } from "astal/gtk3"; +import AstalHyprland from "gi://AstalHyprland"; +import AstalNotifd from "gi://AstalNotifd"; +import AstalTray from "gi://AstalTray"; +import Players from "../services/players"; +import { getAppCategoryIcon } from "../utils/icons"; +import { ellipsize } from "../utils/strings"; +import { osIcon } from "../utils/system"; +import { setupCustomTooltip } from "../utils/widgets"; + +const hyprland = AstalHyprland.get_default(); + +const wsPerGroup = 10; + +const hookFocusedClientProp = ( + self: any, // Ugh why is there no base Widget type + prop: keyof AstalHyprland.Client, + callback: (c: AstalHyprland.Client | null) => void +) => { + let id: number | null = null; + let lastClient: AstalHyprland.Client | null = null; + self.hook(hyprland, "notify::focused-client", () => { + if (id) lastClient?.disconnect(id); + lastClient = hyprland.focusedClient; // Can be null + id = lastClient?.connect(`notify::${kebabify(prop)}`, () => callback(lastClient)); + callback(lastClient); + }); + self.connect("destroy", () => id && lastClient?.disconnect(id)); + callback(lastClient); +}; + +const OSIcon = () =>