aboutsummaryrefslogtreecommitdiff
path: root/ags
diff options
context:
space:
mode:
Diffstat (limited to 'ags')
-rw-r--r--ags/README.md15
-rw-r--r--ags/app.ts28
-rw-r--r--ags/config.js6
-rw-r--r--ags/env.d.ts21
-rw-r--r--ags/modules/applauncher.js107
-rw-r--r--ags/modules/bar.js131
-rw-r--r--ags/package.json6
-rw-r--r--ags/style.scss27
-rw-r--r--ags/tsconfig.json28
l---------ags/types1
-rw-r--r--ags/widget/Bar.tsx53
11 files changed, 144 insertions, 279 deletions
diff --git a/ags/README.md b/ags/README.md
deleted file mode 100644
index 71563ed..0000000
--- a/ags/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-
-# Starter Config
-
-if suggestions don't work, first make sure
-you have TypeScript LSP working in your editor
-
-if you do not want typechecking only suggestions
-
-```json
-// tsconfig.json
-"checkJs": false
-```
-
-types are symlinked to:
-/usr/share/com.github.Aylur.ags/types
diff --git a/ags/app.ts b/ags/app.ts
new file mode 100644
index 0000000..b485250
--- /dev/null
+++ b/ags/app.ts
@@ -0,0 +1,28 @@
+import { App } from "astal/gtk3"
+import { exec } from "astal/process"
+
+import Bar from "./widget/Bar"
+
+function updateStyle() {
+ App.reset_css()
+ exec(`sass ./style.scss /tmp/style.css`)
+ App.apply_css("/tmp/style.css")
+}
+
+App.start({
+ requestHandler(request, res) {
+ switch (request) {
+ case "reload":
+ updateStyle()
+ res("style reloaded")
+ break;
+ default:
+ res("unknown command")
+ break;
+ }
+ },
+ main() {
+ updateStyle()
+ App.get_monitors().map(Bar)
+ },
+})
diff --git a/ags/config.js b/ags/config.js
deleted file mode 100644
index cc69e2e..0000000
--- a/ags/config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import { applauncher } from "./modules/applauncher.js"
-import { Bar } from "./modules/bar.js"
-
-App.config({
- windows: [applauncher, Bar(0)],
-})
diff --git a/ags/env.d.ts b/ags/env.d.ts
new file mode 100644
index 0000000..467c0a4
--- /dev/null
+++ b/ags/env.d.ts
@@ -0,0 +1,21 @@
+declare const SRC: string
+
+declare module "inline:*" {
+ const content: string
+ export default content
+}
+
+declare module "*.scss" {
+ const content: string
+ export default content
+}
+
+declare module "*.blp" {
+ const content: string
+ export default content
+}
+
+declare module "*.css" {
+ const content: string
+ export default content
+}
diff --git a/ags/modules/applauncher.js b/ags/modules/applauncher.js
deleted file mode 100644
index f380185..0000000
--- a/ags/modules/applauncher.js
+++ /dev/null
@@ -1,107 +0,0 @@
-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
deleted file mode 100644
index 28fdaee..0000000
--- a/ags/modules/bar.js
+++ /dev/null
@@ -1,131 +0,0 @@
-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(),
- }),
- })
-}
-
diff --git a/ags/package.json b/ags/package.json
new file mode 100644
index 0000000..44226f2
--- /dev/null
+++ b/ags/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "astal-shell",
+ "dependencies": {
+ "astal": "/usr/share/astal/gjs"
+ }
+}
diff --git a/ags/style.scss b/ags/style.scss
index df7b071..7ad03be 100644
--- a/ags/style.scss
+++ b/ags/style.scss
@@ -1,5 +1,26 @@
-$base-color: #c6538c;
+// https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss
+$fg-color: #{"@theme_fg_color"};
+$bg-color: #{"@theme_bg_color"};
-window {
- background-color: $base-color;
+window.Bar {
+ background: transparent;
+ color: $fg-color;
+ font-weight: bold;
+
+ >centerbox {
+ background: $bg-color;
+ border-radius: 10px;
+ margin: 8px;
+ }
+
+ >box {
+ background: $bg-color;
+ border-radius: 10px;
+ margin: 8px;
+ }
+
+ button {
+ border-radius: 8px;
+ margin: 2px;
+ }
}
diff --git a/ags/tsconfig.json b/ags/tsconfig.json
index 6860767..9471e35 100644
--- a/ags/tsconfig.json
+++ b/ags/tsconfig.json
@@ -1,18 +1,14 @@
{
- "compilerOptions": {
- "target": "ES2022",
- "module": "ES2022",
- "lib": [
- "ES2022"
- ],
- "allowJs": true,
- "checkJs": true,
- "strict": true,
- "noImplicitAny": false,
- "baseUrl": ".",
- "typeRoots": [
- "./types"
- ],
- "skipLibCheck": true
- }
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "experimentalDecorators": true,
+ "strict": true,
+ "target": "ES2022",
+ "module": "ES2022",
+ "moduleResolution": "Bundler",
+ // "checkJs": true,
+ // "allowJs": true,
+ "jsx": "react-jsx",
+ "jsxImportSource": "astal/gtk3",
+ }
}
diff --git a/ags/types b/ags/types
deleted file mode 120000
index a8e3f04..0000000
--- a/ags/types
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/com.github.Aylur.ags/types \ No newline at end of file
diff --git a/ags/widget/Bar.tsx b/ags/widget/Bar.tsx
new file mode 100644
index 0000000..d994797
--- /dev/null
+++ b/ags/widget/Bar.tsx
@@ -0,0 +1,53 @@
+import { App, Astal, Gtk, Gdk, Widget } from "astal/gtk3"
+import { Variable } from "astal"
+import { BoxProps, CenterBoxProps } from "astal/gtk3/widget"
+
+const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor
+const { START, CENTER, END } = Gtk.Align
+
+const time = Variable("").poll(1000, "date")
+
+function VerticalCenterBox(props: CenterBoxProps) {
+ return <centerbox
+ {...props}
+ vertical
+ />
+}
+
+function VerticalBox(props: BoxProps) {
+ return <box
+ {...props}
+ vertical
+ />
+}
+
+export default function Bar(gdkmonitor: Gdk.Monitor) {
+ return <window
+ name="Bar"
+ className="Bar"
+ gdkmonitor={gdkmonitor}
+ exclusivity={Astal.Exclusivity.EXCLUSIVE}
+ anchor={TOP | LEFT | BOTTOM}
+ application={App}>
+ <VerticalCenterBox>
+ <button
+ onClicked="echo hello"
+ halign={CENTER}
+ valign={START}
+ >
+ Welcome to AGS!
+ </button>
+ <VerticalBox>
+ <label>CIAO</label>
+ <label>CIAO</label>
+ </VerticalBox>
+ <button
+ onClicked={() => print("hello")}
+ halign={CENTER}
+ valign={END}
+ >
+ <label label={time()} />
+ </button>
+ </VerticalCenterBox>
+ </window>
+}