refactor: make the whole thing more generic

This commit is contained in:
2024-04-02 16:28:57 +02:00
parent 7b648e1955
commit 651f3ad808
193 changed files with 763 additions and 521 deletions

View File

@@ -0,0 +1,142 @@
import App from "resource:///com/github/Aylur/ags/app.js";
import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js";
import Applications from "resource:///com/github/Aylur/ags/service/applications.js";
import Widget from "resource:///com/github/Aylur/ags/widget.js";
import icons from "../icons.js";
import options from "../options.js";
import { launchApp, range } from "../utils.js";
const focus = ({ address }) =>
Hyprland.sendMessage(`dispatch focuswindow address:${address}`);
/** @param {import('types/widgets/button').ButtonProps & { icon: string, pinned?: boolean }} o */
const AppButton = ({ icon, pinned = false, ...rest }) => {
const indicators = Widget.Box({
vpack: "end",
hpack: "center",
children: range(5, 0).map(() =>
Widget.Box({
class_name: "indicator",
visible: false,
}),
),
});
return Widget.Button({
...rest,
attribute: indicators,
child: Widget.Box({
class_name: "box",
child: Widget.Overlay({
child: Widget.Icon({
icon,
size: options.desktop.dock.icon_size.bind("value"),
}),
pass_through: true,
overlays: pinned ? [indicators] : [],
}),
}),
});
};
const Taskbar = () =>
Widget.Box({
children: Hyprland.bind("clients").transform((c) =>
c.map((client) => {
for (const appName of options.desktop.dock.pinned_apps.value) {
if (client.class.toLowerCase().includes(appName.toLowerCase()))
return null;
}
for (const app of Applications.list) {
if (
(client.title && app.match(client.title)) ||
(client.class && app.match(client.class))
) {
return AppButton({
icon: app.icon_name || "",
tooltip_text: app.name,
on_primary_click: () => focus(client),
on_middle_click: () => launchApp(app),
});
}
}
}),
),
});
const PinnedApps = () =>
Widget.Box({
class_name: "pins",
homogeneous: true,
children: options.desktop.dock.pinned_apps.bind("value").transform((v) =>
v
.map((term) => ({ app: Applications.query(term)?.[0], term }))
.filter(({ app }) => app)
.map(({ app, term }) =>
AppButton({
pinned: true,
icon: app.icon_name || "",
on_primary_click: () => {
for (const client of Hyprland.clients) {
if (client.class.toLowerCase().includes(term))
return focus(client);
}
launchApp(app);
},
on_middle_click: () => launchApp(app),
tooltip_text: app.name,
setup: (button) =>
button.hook(Hyprland, () => {
const running = Hyprland.clients.filter((client) =>
client.class.toLowerCase().includes(term),
);
const focused = running.find(
(client) => client.address === Hyprland.active.client.address,
);
const index = running.findIndex((c) => c === focused);
for (let i = 0; i < 5; ++i) {
const indicator = button.attribute.children[i];
indicator.visible = i < running.length;
indicator.toggleClassName("focused", i === index);
}
button.set_tooltip_text(
running.length === 1 ? running[0].title : app.name,
);
}),
}),
),
),
});
export default () => {
const pinnedapps = PinnedApps();
const taskbar = Taskbar();
const applauncher = AppButton({
class_name: "launcher nonrunning",
icon: icons.apps.apps,
tooltip_text: "Applications",
on_clicked: () => App.toggleWindow("applauncher"),
});
const separator = Widget.Separator({
vpack: "center",
hpack: "center",
orientation: 1,
setup: (self) =>
self.hook(
taskbar,
() => {
self.visible = taskbar.children.length > 0;
},
"notify::children",
),
});
return Widget.Box({
class_name: "dock",
children: [applauncher, pinnedapps, separator, taskbar],
});
};

View File

@@ -0,0 +1,44 @@
import Widget from "resource:///com/github/Aylur/ags/widget.js";
import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js";
import Dock from "./Dock.js";
import options from "../options.js";
/** @param {number} monitor */
export default (monitor) => {
const revealer = Widget.Revealer({
transition: "slide_up",
child: Dock(),
setup: (self) => {
const update = () => {
const ws = Hyprland.getWorkspace(Hyprland.active.workspace.id);
if (Hyprland.getMonitor(monitor)?.name === ws?.monitor)
self.reveal_child = ws?.windows === 0;
};
self
.hook(Hyprland, update, "client-added")
.hook(Hyprland, update, "client-removed")
.hook(Hyprland.active.workspace, update);
},
});
return Widget.Window({
monitor,
name: `dock${monitor}`,
class_name: "floating-dock",
anchor: ["bottom"],
child: Widget.Box({
children: [
revealer,
Widget.Box({
class_name: "padding",
css: "padding: 2px;",
}),
],
}),
setup: (self) =>
self
.on("enter-notify-event", () => (revealer.reveal_child = true))
.on("leave-notify-event", () => (revealer.reveal_child = false))
.bind("visible", options.bar.position, "value", (v) => v !== "bottom"),
});
};