mirror of
https://github.com/Theaninova/TheaninovOS.git
synced 2026-01-08 00:32:53 +00:00
feat: update ags
This commit is contained in:
108
home/desktops/hyprland/ags/js/bar/buttons/BatteryBar.js
Normal file
108
home/desktops/hyprland/ags/js/bar/buttons/BatteryBar.js
Normal file
@@ -0,0 +1,108 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Battery from "resource:///com/github/Aylur/ags/service/battery.js";
|
||||
import icons from "../../icons.js";
|
||||
import FontIcon from "../../misc/FontIcon.js";
|
||||
import options from "../../options.js";
|
||||
import PanelButton from "../PanelButton.js";
|
||||
|
||||
const Indicator = () =>
|
||||
Widget.Stack({
|
||||
items: [
|
||||
["false", Widget.Icon({ binds: [["icon", Battery, "icon-name"]] })],
|
||||
["true", FontIcon(icons.battery.charging)],
|
||||
],
|
||||
binds: [["visible", options.battery.bar.show_icon]],
|
||||
connections: [
|
||||
[
|
||||
Battery,
|
||||
(stack) => {
|
||||
stack.shown = `${Battery.charging || Battery.charged}`;
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
const PercentLabel = () =>
|
||||
Widget.Revealer({
|
||||
transition: "slide_right",
|
||||
binds: [["reveal-child", options.battery.show_percentage]],
|
||||
child: Widget.Label({
|
||||
binds: [["label", Battery, "percent", (p) => `${p}%`]],
|
||||
}),
|
||||
});
|
||||
|
||||
const LevelBar = () =>
|
||||
Widget.LevelBar({
|
||||
connections: [
|
||||
[
|
||||
options.battery.bar.full,
|
||||
(self) => {
|
||||
const full = options.battery.bar.full.value;
|
||||
self.vpack = full ? "fill" : "center";
|
||||
self.hpack = full ? "fill" : "center";
|
||||
},
|
||||
],
|
||||
],
|
||||
binds: [["value", Battery, "percent", (p) => p / 100]],
|
||||
});
|
||||
|
||||
const WholeButton = () =>
|
||||
Widget.Overlay({
|
||||
class_name: "whole-button",
|
||||
child: LevelBar(),
|
||||
pass_through: true,
|
||||
overlays: [
|
||||
Widget.Box({
|
||||
hpack: "center",
|
||||
children: [
|
||||
FontIcon({
|
||||
icon: icons.battery.charging,
|
||||
binds: [["visible", Battery, "charging"]],
|
||||
}),
|
||||
Widget.Box({
|
||||
hpack: "center",
|
||||
vpack: "center",
|
||||
child: PercentLabel(),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export default () =>
|
||||
PanelButton({
|
||||
class_name: "battery-bar",
|
||||
on_clicked: () => {
|
||||
const v = options.battery.show_percentage.value;
|
||||
options.battery.show_percentage.value = !v;
|
||||
},
|
||||
content: Widget.Box({
|
||||
connections: [
|
||||
[
|
||||
Battery,
|
||||
(w) => {
|
||||
w.toggleClassName("charging", Battery.charging || Battery.charged);
|
||||
w.toggleClassName(
|
||||
"medium",
|
||||
Battery.percent < options.battery.medium.value,
|
||||
);
|
||||
w.toggleClassName(
|
||||
"low",
|
||||
Battery.percent < options.battery.low.value,
|
||||
);
|
||||
w.toggleClassName("half", Battery.percent < 48);
|
||||
},
|
||||
],
|
||||
],
|
||||
binds: [
|
||||
["visible", Battery, "available"],
|
||||
[
|
||||
"children",
|
||||
options.battery.bar.full,
|
||||
"value",
|
||||
(full) =>
|
||||
full ? [WholeButton()] : [Indicator(), PercentLabel(), LevelBar()],
|
||||
],
|
||||
],
|
||||
}),
|
||||
});
|
||||
27
home/desktops/hyprland/ags/js/bar/buttons/ColorPicker.js
Normal file
27
home/desktops/hyprland/ags/js/bar/buttons/ColorPicker.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Colors from "../../services/colorpicker.js";
|
||||
import PanelButton from "../PanelButton.js";
|
||||
import Gdk from "gi://Gdk";
|
||||
|
||||
export default () =>
|
||||
PanelButton({
|
||||
class_name: "color-picker",
|
||||
content: Widget.Icon("color-select-symbolic"),
|
||||
binds: [["tooltip-text", Colors, "colors", (v) => `${v.length} colors`]],
|
||||
on_clicked: () => Colors.pick(),
|
||||
|
||||
on_secondary_click: (btn) => {
|
||||
if (Colors.colors.length === 0) return;
|
||||
|
||||
Widget.Menu({
|
||||
class_name: "colorpicker",
|
||||
children: Colors.colors.map((color) =>
|
||||
Widget.MenuItem({
|
||||
child: Widget.Label(color),
|
||||
css: `background-color: ${color}`,
|
||||
on_activate: () => Colors.wlCopy(color),
|
||||
}),
|
||||
),
|
||||
}).popup_at_widget(btn, Gdk.Gravity.SOUTH, Gdk.Gravity.NORTH, null);
|
||||
},
|
||||
});
|
||||
11
home/desktops/hyprland/ags/js/bar/buttons/DateButton.js
Normal file
11
home/desktops/hyprland/ags/js/bar/buttons/DateButton.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import App from "resource:///com/github/Aylur/ags/app.js";
|
||||
import Clock from "../../misc/Clock.js";
|
||||
import PanelButton from "../PanelButton.js";
|
||||
|
||||
export default ({ format = "%H:%M - %A %e." } = {}) =>
|
||||
PanelButton({
|
||||
class_name: "dashboard panel-button",
|
||||
on_clicked: () => App.toggleWindow("dashboard"),
|
||||
window: "dashboard",
|
||||
content: Clock({ format }),
|
||||
});
|
||||
55
home/desktops/hyprland/ags/js/bar/buttons/FocusedClient.js
Normal file
55
home/desktops/hyprland/ags/js/bar/buttons/FocusedClient.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import PanelButton from "../PanelButton.js";
|
||||
import options from "../../options.js";
|
||||
import { substitute } from "../../utils.js";
|
||||
|
||||
export const ClientLabel = () =>
|
||||
Widget.Label({
|
||||
binds: [
|
||||
[
|
||||
"label",
|
||||
Hyprland.active.client,
|
||||
"class",
|
||||
(c) => {
|
||||
const { titles } = options.substitutions;
|
||||
return substitute(titles, c);
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
export const ClientIcon = () =>
|
||||
Widget.Icon({
|
||||
connections: [
|
||||
[
|
||||
Hyprland.active.client,
|
||||
(self) => {
|
||||
const { icons } = options.substitutions;
|
||||
const { client } = Hyprland.active;
|
||||
|
||||
const classIcon = substitute(icons, client.class) + "-symbolic";
|
||||
const titleIcon = substitute(icons, client.class) + "-symbolic";
|
||||
|
||||
const hasTitleIcon = Utils.lookUpIcon(titleIcon);
|
||||
const hasClassIcon = Utils.lookUpIcon(classIcon);
|
||||
|
||||
if (hasClassIcon) self.icon = classIcon;
|
||||
|
||||
if (hasTitleIcon) self.icon = titleIcon;
|
||||
|
||||
self.visible = !!(hasTitleIcon || hasClassIcon);
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
export default () =>
|
||||
PanelButton({
|
||||
class_name: "focused-client",
|
||||
content: Widget.Box({
|
||||
children: [ClientIcon(), ClientLabel()],
|
||||
binds: [["tooltip-text", Hyprland.active, "client", (c) => c.title]],
|
||||
}),
|
||||
});
|
||||
84
home/desktops/hyprland/ags/js/bar/buttons/MediaIndicator.js
Normal file
84
home/desktops/hyprland/ags/js/bar/buttons/MediaIndicator.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Mpris from "resource:///com/github/Aylur/ags/service/mpris.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import HoverRevealer from "../../misc/HoverRevealer.js";
|
||||
import * as mpris from "../../misc/mpris.js";
|
||||
import options from "../../options.js";
|
||||
|
||||
export const getPlayer = (name = options.mpris.preferred.value) =>
|
||||
Mpris.getPlayer(name) || Mpris.players[0] || null;
|
||||
|
||||
/**
|
||||
* @param {Object} o
|
||||
* @param {import('types/service/mpris').MprisPlayer} o.player
|
||||
* @param {import('../../misc/HoverRevealer').HoverRevealProps['direction']=} o.direction
|
||||
*/
|
||||
const Indicator = ({ player, direction = "right" }) =>
|
||||
HoverRevealer({
|
||||
class_name: `media panel-button ${player.name}`,
|
||||
direction,
|
||||
on_primary_click: () => player.playPause(),
|
||||
on_scroll_up: () => player.next(),
|
||||
on_scroll_down: () => player.previous(),
|
||||
on_secondary_click: () => player.playPause(),
|
||||
indicator: mpris.PlayerIcon(player),
|
||||
child: Widget.Label({
|
||||
vexpand: true,
|
||||
truncate: "end",
|
||||
max_width_chars: 40,
|
||||
connections: [
|
||||
[
|
||||
player,
|
||||
(label) => {
|
||||
label.label = `${player.track_artists.join(", ")} - ${
|
||||
player.track_title
|
||||
}`;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
connections: [
|
||||
[
|
||||
player,
|
||||
(revealer) => {
|
||||
if (revealer._current === player.track_title) return;
|
||||
|
||||
revealer._current = player.track_title;
|
||||
revealer.reveal_child = true;
|
||||
Utils.timeout(3000, () => {
|
||||
revealer.reveal_child = false;
|
||||
});
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Object} o
|
||||
* @param {import('../../misc/HoverRevealer').HoverRevealProps['direction']=} o.direction
|
||||
*/
|
||||
export default ({ direction = "right" } = {}) => {
|
||||
let current = null;
|
||||
|
||||
const update = (box) => {
|
||||
const player = getPlayer();
|
||||
box.visible = !!player;
|
||||
|
||||
if (!player) {
|
||||
current = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (current === player) return;
|
||||
|
||||
current = player;
|
||||
box.children = [Indicator({ player, direction })];
|
||||
};
|
||||
|
||||
return Widget.Box({
|
||||
connections: [
|
||||
[options.mpris.preferred, update],
|
||||
[Mpris, update, "notify::players"],
|
||||
],
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
import App from "resource:///com/github/Aylur/ags/app.js";
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import icons from "../../icons.js";
|
||||
import HoverRevealer from "../../misc/HoverRevealer.js";
|
||||
|
||||
/**
|
||||
* @param {Object} o
|
||||
* @param {import('../../misc/HoverRevealer').HoverRevealProps['direction']=} o.direction
|
||||
*/
|
||||
export default ({ direction = "left" } = {}) =>
|
||||
HoverRevealer({
|
||||
class_name: "notifications panel-button",
|
||||
eventboxConnections: [
|
||||
["button-press-event", () => App.openWindow("dashboard")],
|
||||
[
|
||||
Notifications,
|
||||
(box) =>
|
||||
(box.visible =
|
||||
Notifications.notifications.length > 0 || Notifications.dnd),
|
||||
],
|
||||
],
|
||||
connections: [
|
||||
[
|
||||
Notifications,
|
||||
(revealer) => {
|
||||
const title = Notifications.notifications[0]?.summary;
|
||||
if (revealer._title === title) return;
|
||||
|
||||
revealer._title = title;
|
||||
revealer.reveal_child = true;
|
||||
Utils.timeout(3000, () => {
|
||||
revealer.reveal_child = false;
|
||||
});
|
||||
},
|
||||
],
|
||||
],
|
||||
direction,
|
||||
indicator: Widget.Icon({
|
||||
binds: [
|
||||
[
|
||||
"icon",
|
||||
Notifications,
|
||||
"dnd",
|
||||
(dnd) =>
|
||||
dnd ? icons.notifications.silent : icons.notifications.noisy,
|
||||
],
|
||||
],
|
||||
}),
|
||||
child: Widget.Label({
|
||||
truncate: "end",
|
||||
max_width_chars: 40,
|
||||
binds: [
|
||||
[
|
||||
"label",
|
||||
Notifications,
|
||||
"notifications",
|
||||
(n) => n.reverse()[0]?.summary || "",
|
||||
],
|
||||
],
|
||||
}),
|
||||
});
|
||||
24
home/desktops/hyprland/ags/js/bar/buttons/OverviewButton.js
Normal file
24
home/desktops/hyprland/ags/js/bar/buttons/OverviewButton.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import App from "resource:///com/github/Aylur/ags/app.js";
|
||||
import PanelButton from "../PanelButton.js";
|
||||
import FontIcon from "../../misc/FontIcon.js";
|
||||
import { distroIcon } from "../../variables.js";
|
||||
import options from "../../options.js";
|
||||
|
||||
export default () =>
|
||||
PanelButton({
|
||||
class_name: "overview",
|
||||
window: "overview",
|
||||
on_clicked: () => App.toggleWindow("overview"),
|
||||
content: FontIcon({
|
||||
binds: [
|
||||
[
|
||||
"icon",
|
||||
options.bar.icon,
|
||||
"value",
|
||||
(v) => {
|
||||
return v === "distro-icon" ? distroIcon : v;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
});
|
||||
11
home/desktops/hyprland/ags/js/bar/buttons/PowerMenu.js
Normal file
11
home/desktops/hyprland/ags/js/bar/buttons/PowerMenu.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import App from "resource:///com/github/Aylur/ags/app.js";
|
||||
import icons from "../../icons.js";
|
||||
import PanelButton from "../PanelButton.js";
|
||||
|
||||
export default () =>
|
||||
PanelButton({
|
||||
class_name: "powermenu",
|
||||
content: Widget.Icon(icons.powermenu.shutdown),
|
||||
on_clicked: () => App.openWindow("powermenu"),
|
||||
});
|
||||
30
home/desktops/hyprland/ags/js/bar/buttons/ScreenRecord.js
Normal file
30
home/desktops/hyprland/ags/js/bar/buttons/ScreenRecord.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import PanelButton from "../PanelButton.js";
|
||||
import Recorder from "../../services/screenrecord.js";
|
||||
import icons from "../../icons.js";
|
||||
|
||||
export default () =>
|
||||
PanelButton({
|
||||
class_name: "recorder",
|
||||
on_clicked: () => Recorder.stop(),
|
||||
binds: [["visible", Recorder, "recording"]],
|
||||
content: Widget.Box({
|
||||
children: [
|
||||
Widget.Icon(icons.recorder.recording),
|
||||
Widget.Label({
|
||||
binds: [
|
||||
[
|
||||
"label",
|
||||
Recorder,
|
||||
"timer",
|
||||
(time) => {
|
||||
const sec = time % 60;
|
||||
const min = Math.floor(time / 60);
|
||||
return `${min}:${sec < 10 ? "0" + sec : sec}`;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
72
home/desktops/hyprland/ags/js/bar/buttons/SubMenu.js
Normal file
72
home/desktops/hyprland/ags/js/bar/buttons/SubMenu.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import Variable from "resource:///com/github/Aylur/ags/variable.js";
|
||||
import icons from "../../icons.js";
|
||||
import options from "../../options.js";
|
||||
|
||||
/**
|
||||
* @param {import('types/widgets/revealer').default} revealer
|
||||
* @param {'left' | 'right' | 'up' | 'down'} direction
|
||||
* @param {import('types/variable').Variable} items
|
||||
*/
|
||||
const Arrow = (revealer, direction, items) => {
|
||||
let deg = 0;
|
||||
|
||||
const icon = Widget.Icon({
|
||||
icon: icons.ui.arrow[direction],
|
||||
});
|
||||
|
||||
const animate = () => {
|
||||
const t = options.transition.value / 20;
|
||||
const step = revealer.reveal_child ? 10 : -10;
|
||||
for (let i = 0; i < 18; ++i) {
|
||||
Utils.timeout(t * i, () => {
|
||||
deg += step;
|
||||
icon.setCss(`-gtk-icon-transform: rotate(${deg}deg);`);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return Widget.Button({
|
||||
class_name: "panel-button sub-menu",
|
||||
connections: [
|
||||
[
|
||||
items,
|
||||
(btn) => {
|
||||
btn.tooltip_text = `${items.value} Items`;
|
||||
},
|
||||
],
|
||||
],
|
||||
on_clicked: () => {
|
||||
animate();
|
||||
revealer.reveal_child = !revealer.reveal_child;
|
||||
},
|
||||
child: icon,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Object} o
|
||||
* @param {import('types/widgets/box').default['children']} o.children
|
||||
* @param {'left' | 'right' | 'up' | 'down'=} o.direction
|
||||
* @param {import('types/variable').Variable} o.items
|
||||
*/
|
||||
export default ({ children, direction = "left", items = Variable(0) }) => {
|
||||
const posStart = direction === "up" || direction === "left";
|
||||
const posEnd = direction === "down" || direction === "right";
|
||||
const revealer = Widget.Revealer({
|
||||
transition: `slide_${direction}`,
|
||||
child: Widget.Box({
|
||||
children,
|
||||
}),
|
||||
});
|
||||
|
||||
return Widget.Box({
|
||||
vertical: direction === "up" || direction === "down",
|
||||
children: [
|
||||
posStart && revealer,
|
||||
Arrow(revealer, direction, items),
|
||||
posEnd && revealer,
|
||||
],
|
||||
});
|
||||
};
|
||||
44
home/desktops/hyprland/ags/js/bar/buttons/SysTray.js
Normal file
44
home/desktops/hyprland/ags/js/bar/buttons/SysTray.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import SystemTray from "resource:///com/github/Aylur/ags/service/systemtray.js";
|
||||
import PanelButton from "../PanelButton.js";
|
||||
import Gdk from "gi://Gdk";
|
||||
|
||||
/** @param {import('types/service/systemtray').TrayItem} item */
|
||||
const SysTrayItem = (item) =>
|
||||
PanelButton({
|
||||
class_name: "tray-item",
|
||||
content: Widget.Icon({ icon: item.bind("icon") }),
|
||||
tooltip_markup: item.bind("tooltip_markup"),
|
||||
setup: (self) => {
|
||||
const id = item.menu?.connect("popped-up", (menu) => {
|
||||
self.toggleClassName("active");
|
||||
menu.connect("notify::visible", (menu) => {
|
||||
self.toggleClassName("active", menu.visible);
|
||||
});
|
||||
menu.disconnect(id);
|
||||
});
|
||||
|
||||
if (id) self.connect("destroy", () => item.menu?.disconnect(id));
|
||||
},
|
||||
|
||||
// @ts-expect-error popup_at_widget missing from types?
|
||||
on_primary_click: (btn) =>
|
||||
item.menu?.popup_at_widget(
|
||||
btn,
|
||||
Gdk.Gravity.SOUTH,
|
||||
Gdk.Gravity.NORTH,
|
||||
null,
|
||||
),
|
||||
|
||||
// @ts-expect-error popup_at_widget missing from types?
|
||||
on_secondary_click: (btn) =>
|
||||
item.menu?.popup_at_widget(
|
||||
btn,
|
||||
Gdk.Gravity.SOUTH,
|
||||
Gdk.Gravity.NORTH,
|
||||
null,
|
||||
),
|
||||
});
|
||||
|
||||
export default () =>
|
||||
Widget.Box().bind("children", SystemTray, "items", (i) => i.map(SysTrayItem));
|
||||
57
home/desktops/hyprland/ags/js/bar/buttons/System.js
Normal file
57
home/desktops/hyprland/ags/js/bar/buttons/System.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import PanelButton from "../PanelButton.js";
|
||||
import * as variables from "../../variables.js";
|
||||
import icons from "../../icons.js";
|
||||
|
||||
/** @param {'cpu' | 'ram'} type */
|
||||
const System = (type) => {
|
||||
const icon = Widget.Icon({
|
||||
class_name: "icon",
|
||||
icon: icons.system[type],
|
||||
});
|
||||
|
||||
const progress = Widget.Box({
|
||||
class_name: "progress",
|
||||
child: Widget.CircularProgress({
|
||||
binds: [["value", variables[type]]],
|
||||
}),
|
||||
});
|
||||
|
||||
const revealer = Widget.Revealer({
|
||||
transition: "slide_right",
|
||||
child: Widget.Label({
|
||||
binds: [
|
||||
[
|
||||
"label",
|
||||
variables[type],
|
||||
"value",
|
||||
(v) => {
|
||||
return ` ${type}: ${Math.round(v * 100)}%`;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
return PanelButton({
|
||||
class_name: `system ${type}`,
|
||||
on_clicked: () => (revealer.reveal_child = !revealer.reveal_child),
|
||||
content: Widget.EventBox({
|
||||
on_hover: () => (revealer.reveal_child = true),
|
||||
on_hover_lost: () => (revealer.reveal_child = false),
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
icon,
|
||||
Widget.Box({
|
||||
class_name: "revealer",
|
||||
child: revealer,
|
||||
}),
|
||||
progress,
|
||||
],
|
||||
}),
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
export const CPU = () => System("cpu");
|
||||
export const RAM = () => System("ram");
|
||||
135
home/desktops/hyprland/ags/js/bar/buttons/SystemIndicators.js
Normal file
135
home/desktops/hyprland/ags/js/bar/buttons/SystemIndicators.js
Normal file
@@ -0,0 +1,135 @@
|
||||
import App from "resource:///com/github/Aylur/ags/app.js";
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js";
|
||||
import Bluetooth from "resource:///com/github/Aylur/ags/service/bluetooth.js";
|
||||
import Audio from "resource:///com/github/Aylur/ags/service/audio.js";
|
||||
import Network from "resource:///com/github/Aylur/ags/service/network.js";
|
||||
import HoverRevealer from "../../misc/HoverRevealer.js";
|
||||
import PanelButton from "../PanelButton.js";
|
||||
import Asusctl from "../../services/asusctl.js";
|
||||
import Indicator from "../../services/onScreenIndicator.js";
|
||||
import icons from "../../icons.js";
|
||||
import FontIcon from "../../misc/FontIcon.js";
|
||||
|
||||
const ProfileIndicator = () =>
|
||||
Widget.Icon()
|
||||
.bind("visible", Asusctl, "profile", (p) => p !== "Balanced")
|
||||
.bind("icon", Asusctl, "profile", (i) => icons.asusctl.profile[i]);
|
||||
|
||||
const ModeIndicator = () =>
|
||||
FontIcon()
|
||||
.bind("visible", Asusctl, "mode", (m) => m !== "Hybrid")
|
||||
.bind("icon", Asusctl, "mode", (i) => icons.asusctl.mode[i]);
|
||||
|
||||
const MicrophoneIndicator = () =>
|
||||
Widget.Icon().hook(
|
||||
Audio,
|
||||
(icon) => {
|
||||
if (!Audio.microphone) return;
|
||||
|
||||
const { muted, low, medium, high } = icons.audio.mic;
|
||||
if (Audio.microphone.is_muted) return (icon.icon = muted);
|
||||
|
||||
/** @type {Array<[number, string]>} */
|
||||
const cons = [
|
||||
[67, high],
|
||||
[34, medium],
|
||||
[1, low],
|
||||
[0, muted],
|
||||
];
|
||||
icon.icon =
|
||||
cons.find(([n]) => n <= Audio.microphone.volume * 100)?.[1] || "";
|
||||
|
||||
icon.visible = Audio.recorders.length > 0 || Audio.microphone.is_muted;
|
||||
},
|
||||
"speaker-changed",
|
||||
);
|
||||
|
||||
const DNDIndicator = () =>
|
||||
Widget.Icon({
|
||||
visible: Notifications.bind("dnd"),
|
||||
icon: icons.notifications.silent,
|
||||
});
|
||||
|
||||
const BluetoothDevicesIndicator = () =>
|
||||
Widget.Box().hook(
|
||||
Bluetooth,
|
||||
(box) => {
|
||||
box.children = Bluetooth.connectedDevices.map(({ iconName, name }) =>
|
||||
HoverRevealer({
|
||||
indicator: Widget.Icon(iconName + "-symbolic"),
|
||||
child: Widget.Label(name),
|
||||
}),
|
||||
);
|
||||
|
||||
box.visible = Bluetooth.connectedDevices.length > 0;
|
||||
},
|
||||
"notify::connected-devices",
|
||||
);
|
||||
|
||||
const BluetoothIndicator = () =>
|
||||
Widget.Icon({
|
||||
class_name: "bluetooth",
|
||||
icon: icons.bluetooth.enabled,
|
||||
visible: Bluetooth.bind("enabled"),
|
||||
});
|
||||
|
||||
const NetworkIndicator = () =>
|
||||
Widget.Icon().hook(Network, (self) => {
|
||||
const icon = Network[Network.primary || "wifi"]?.iconName;
|
||||
self.icon = icon || "";
|
||||
self.visible = !!icon;
|
||||
});
|
||||
|
||||
const AudioIndicator = () =>
|
||||
Widget.Icon().hook(
|
||||
Audio,
|
||||
(self) => {
|
||||
if (!Audio.speaker) return;
|
||||
|
||||
const { muted, low, medium, high, overamplified } = icons.audio.volume;
|
||||
if (Audio.speaker.is_muted) return (self.icon = muted);
|
||||
|
||||
/** @type {Array<[number, string]>} */
|
||||
const cons = [
|
||||
[101, overamplified],
|
||||
[67, high],
|
||||
[34, medium],
|
||||
[1, low],
|
||||
[0, muted],
|
||||
];
|
||||
self.icon =
|
||||
cons.find(([n]) => n <= Audio.speaker.volume * 100)?.[1] || "";
|
||||
},
|
||||
"speaker-changed",
|
||||
);
|
||||
|
||||
export default () =>
|
||||
PanelButton({
|
||||
class_name: "quicksettings panel-button",
|
||||
on_clicked: () => App.toggleWindow("quicksettings"),
|
||||
setup: (self) =>
|
||||
self.hook(App, (_, win, visible) => {
|
||||
self.toggleClassName("active", win === "quicksettings" && visible);
|
||||
}),
|
||||
on_scroll_up: () => {
|
||||
Audio.speaker.volume += 0.02;
|
||||
Indicator.speaker();
|
||||
},
|
||||
on_scroll_down: () => {
|
||||
Audio.speaker.volume -= 0.02;
|
||||
Indicator.speaker();
|
||||
},
|
||||
content: Widget.Box({
|
||||
children: [
|
||||
Asusctl?.available && ProfileIndicator(),
|
||||
Asusctl?.available && ModeIndicator(),
|
||||
DNDIndicator(),
|
||||
BluetoothDevicesIndicator(),
|
||||
BluetoothIndicator(),
|
||||
NetworkIndicator(),
|
||||
AudioIndicator(),
|
||||
MicrophoneIndicator(),
|
||||
],
|
||||
}),
|
||||
});
|
||||
34
home/desktops/hyprland/ags/js/bar/buttons/Taskbar.js
Normal file
34
home/desktops/hyprland/ags/js/bar/buttons/Taskbar.js
Normal file
@@ -0,0 +1,34 @@
|
||||
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 PanelButton from "../PanelButton.js";
|
||||
import { launchApp } from "../../utils.js";
|
||||
import icons from "../../icons.js";
|
||||
|
||||
const focus = ({ address }) =>
|
||||
Hyprland.sendMessage(`dispatch focuswindow address:${address}`);
|
||||
|
||||
/** @param {import('types/widgets/box').default} box */
|
||||
const setChildren = (box) =>
|
||||
(box.children = Hyprland.clients.map((client) => {
|
||||
if (Hyprland.active.workspace.id !== client.workspace.id) return;
|
||||
|
||||
for (const app of Applications.list) {
|
||||
if (client.class && app.match(client.class)) {
|
||||
return PanelButton({
|
||||
content: Widget.Icon(app.icon_name || icons.fallback.executable),
|
||||
tooltip_text: app.name,
|
||||
on_primary_click: () => focus(client),
|
||||
on_middle_click: () => launchApp(app),
|
||||
});
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
export default () =>
|
||||
Widget.Box({
|
||||
connections: [
|
||||
[Hyprland, setChildren, "notify::clients"],
|
||||
[Hyprland, setChildren, "notify::active"],
|
||||
],
|
||||
});
|
||||
64
home/desktops/hyprland/ags/js/bar/buttons/Workspaces.js
Normal file
64
home/desktops/hyprland/ags/js/bar/buttons/Workspaces.js
Normal file
@@ -0,0 +1,64 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Hyprland from "resource:///com/github/Aylur/ags/service/hyprland.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import options from "../../options.js";
|
||||
import { range } from "../../utils.js";
|
||||
|
||||
/** @param {any} arg */
|
||||
const dispatch = (arg) => Utils.execAsync(`hyprctl dispatch workspace ${arg}`);
|
||||
|
||||
const Workspaces = () => {
|
||||
const ws = options.workspaces.value;
|
||||
return Widget.Box({
|
||||
children: range(ws || 20).map((i) =>
|
||||
Widget.Button({
|
||||
setup: (btn) => (btn.id = i),
|
||||
on_clicked: () => dispatch(i),
|
||||
child: Widget.Label({
|
||||
label: `${i}`,
|
||||
class_name: "indicator",
|
||||
vpack: "center",
|
||||
}),
|
||||
connections: [
|
||||
[
|
||||
Hyprland,
|
||||
(btn) => {
|
||||
btn.toggleClassName("active", Hyprland.active.workspace.id === i);
|
||||
btn.toggleClassName(
|
||||
"occupied",
|
||||
Hyprland.getWorkspace(i)?.windows > 0,
|
||||
);
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
),
|
||||
connections: ws
|
||||
? []
|
||||
: [
|
||||
[
|
||||
Hyprland.active.workspace,
|
||||
(box) =>
|
||||
box.children.map((btn) => {
|
||||
btn.visible = Hyprland.workspaces.some(
|
||||
(ws) => ws.id === btn.id,
|
||||
);
|
||||
}),
|
||||
],
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
export default () =>
|
||||
Widget.EventBox({
|
||||
class_name: "workspaces panel-button",
|
||||
child: Widget.Box({
|
||||
// its nested like this to keep it consistent with other PanelButton widgets
|
||||
child: Widget.EventBox({
|
||||
on_scroll_up: () => dispatch("m+1"),
|
||||
on_scroll_down: () => dispatch("m-1"),
|
||||
class_name: "eventbox",
|
||||
binds: [["child", options.workspaces, "value", Workspaces]],
|
||||
}),
|
||||
}),
|
||||
});
|
||||
Reference in New Issue
Block a user