ags(bar, notifications, control-center): add status icons to bar, notification history fixed, notification history below control-center

This commit is contained in:
retrozinndev
2025-03-23 10:17:22 -03:00
parent 30d1fded84
commit 3db477598f
29 changed files with 746 additions and 363 deletions
+51 -15
View File
@@ -1,19 +1,55 @@
import { bind } from "astal";
import { Gtk, Widget } from "astal/gtk3";
import AstalNotifd from "gi://AstalNotifd";
import { Notifications } from "../../scripts/notifications";
import { HistoryNotification, Notifications } from "../../scripts/notifications";
import { NotificationWidget } from "../Notification";
export const NotifHistory: Gtk.Widget = new Widget.Scrollable({
hscroll: Gtk.PolicyType.NEVER,
vscroll: Gtk.PolicyType.AUTOMATIC,
vexpand: true,
hexpand: true,
child: new Widget.Box({
className: "notifications",
children: bind(Notifications.getDefault(), "history").as((history: Array<AstalNotifd.Notification>) =>
history.map((notification: AstalNotifd.Notification) => NotificationWidget(notification,
() => Notifications.getDefault().removeHistory(notification.id))
))
} as Widget.BoxProps)
} as Widget.ScrollableProps)
export const NotifHistory: Gtk.Widget = new Widget.Box({
orientation: Gtk.Orientation.VERTICAL,
className: "history",
expand: true,
visible: bind(Notifications.getDefault(), "history").as(history => history.length > 0),
children: [
new Widget.Scrollable({
className: "history",
hscroll: Gtk.PolicyType.NEVER,
vscroll: Gtk.PolicyType.AUTOMATIC,
expand: true,
visible: bind(Notifications.getDefault(), "history").as(history => history.length > 0),
child: new Widget.Box({
className: "notifications",
hexpand: true,
orientation: Gtk.Orientation.VERTICAL,
homogeneous: false,
children: bind(Notifications.getDefault(), "history").as((history: Array<HistoryNotification>) =>
history.map((notification: HistoryNotification) => NotificationWidget(notification,
() => Notifications.getDefault().removeHistory(notification.id))
))
} as Widget.BoxProps)
} as Widget.ScrollableProps),
new Widget.Box({
vexpand: false,
hexpand: true,
halign: Gtk.Align.END,
className: "button-row",
children: [
new Widget.Button({
className: "clear-all",
child: new Widget.Box({
children: [
new Widget.Label({
className: "nf",
css: "margin-right: 6px",
label: "󰎟"
} as Widget.LabelProps),
new Widget.Label({
label: "Clear"
} as Widget.LabelProps)
]
} as Widget.BoxProps),
onClick: () => Notifications.getDefault().clearHistory(),
} as Widget.ButtonProps)
]
})
]
} as Widget.BoxProps);
+2 -2
View File
@@ -1,12 +1,12 @@
import { Gtk, Widget } from "astal/gtk3";
import { TileNetwork } from "./tiles/Network";
import { TileBluetooth } from "./tiles/Bluetooth";
import { TileRecording } from "./tiles/Recording";
import { TileDND } from "./tiles/DoNotDisturb";
export const tileList: Array<any> = [
TileNetwork,
TileBluetooth,
TileRecording
TileDND
];
export function TilesWidget(): Gtk.Widget {
+14 -7
View File
@@ -1,10 +1,11 @@
import { bind, timeout } from "astal";
import { AstalIO, bind, timeout } from "astal";
import { Gtk, Widget } from "astal/gtk3";
import AstalBluetooth from "gi://AstalBluetooth";
import { Page } from "./Page";
import { Separator, SeparatorProps } from "../../Separator";
let watchingDevices: boolean = false;
let watchTimeout: (AstalIO.Time|undefined);
export const BluetoothPage: Page = new Page({
title: "Bluetooth Devices",
@@ -48,7 +49,7 @@ export const BluetoothPage: Page = new Page({
} as Widget.BoxProps)
]
} as Widget.BoxProps)
})
});
function DeviceWidget(dev: AstalBluetooth.Device): Gtk.Widget {
return new Widget.Button({
@@ -85,11 +86,13 @@ function DeviceWidget(dev: AstalBluetooth.Device): Gtk.Widget {
}
function watchNewDevices(): void {
if(watchingDevices) {
timeout(8000, () => {
reloadBluetoothDevicesList();
if(!watchTimeout) {
watchTimeout = timeout(5000, () => {
reloadBluetoothDevicesList(2500);
watchNewDevices();
watchTimeout = undefined;
});
return;
}
@@ -98,11 +101,15 @@ function watchNewDevices(): void {
export function stopBluetoothDevicesWatch(): void {
watchingDevices = false;
watchTimeout?.cancel();
watchTimeout = undefined;
AstalBluetooth.get_default().adapter.discovering &&
AstalBluetooth.get_default().adapter.stop_discovery();
}
export function reloadBluetoothDevicesList(): void {
export function reloadBluetoothDevicesList(discoveryTimeout?: number): void {
AstalBluetooth.get_default().adapter.start_discovery();
timeout(4000, () => AstalBluetooth.get_default().adapter.stop_discovery());
timeout(discoveryTimeout || 2500, () =>
AstalBluetooth.get_default().adapter.stop_discovery());
}
+4 -2
View File
@@ -6,8 +6,10 @@ import { BluetoothPage } from "../pages/Bluetooth";
export const TileBluetooth = Tile({
title: "Bluetooth",
description: bind(AstalBluetooth.get_default(), "devices").as((devices: Array<AstalBluetooth.Device>) =>
devices.filter((dev: AstalBluetooth.Device) => dev.connected)[0]?.get_alias()),
description: bind(AstalBluetooth.get_default(), "isConnected").as((connected) => {
const connectedDev = AstalBluetooth.get_default().devices.filter(dev => dev.connected)?.[0];
return connected && connectedDev ? connectedDev.get_alias() : ""
}),
onToggledOn: () => AstalBluetooth.get_default().adapter.set_powered(true),
onToggledOff: () => AstalBluetooth.get_default().adapter.set_powered(false),
onClickMore: () => togglePage(BluetoothPage),
@@ -0,0 +1,15 @@
import { bind } from "astal";
import { Notifications } from "../../../scripts/notifications";
import { Tile } from "./Tile";
import { tr } from "../../../i18n/intl";
export const TileDND = Tile({
title: tr("control_center.tiles.dnd.title"),
description: bind(Notifications.getDefault().getNotifd(), "dontDisturb").as(
(dnd: boolean) => dnd ? tr("control_center.tiles.enabled") : tr("control_center.tiles.disabled")),
onToggledOff: () => Notifications.getDefault().getNotifd().dontDisturb = false,
onToggledOn: () => Notifications.getDefault().getNotifd().dontDisturb = true,
icon: "󰍶",
iconSize: 16,
toggleState: Notifications.getDefault().getNotifd().dontDisturb
});
@@ -0,0 +1,10 @@
import { Tile, TileProps } from "./Tile";
export const TileNightLight = Tile({
title: "Luz Noturna",
icon: "󰖔",
iconSize: 16,
onToggledOff: () => false,
onToggledOn: () => true,
toggleState: false
} as TileProps);
+7 -15
View File
@@ -56,7 +56,7 @@ export function Tile(props: TileProps): Widget.EventBox {
new Widget.Label({
className: "icon nf",
label: props.icon || "icon",
css: `label { font-size: ${props.iconSize || "12"}px; }`
css: `label { font-size: ${props.iconSize || 12}px; }`
} as Widget.LabelProps),
new Widget.Box({
className: "text",
@@ -74,23 +74,15 @@ export function Tile(props: TileProps): Widget.EventBox {
} as Widget.LabelProps),
new Widget.Label({
className: "description",
visible: Boolean(props.description),
setup: (label: Widget.Label) => {
if(props.description instanceof Binding) {
const sub = props.description.subscribe((value) => {
label.set_visible(Boolean(value));
});
const destroyId = label.connect("destroy-event", () => {
label.disconnect(destroyId);
sub();
});
}
},
visible: (props.description instanceof Binding) ?
props.description.as(Boolean)
: Boolean(props.description),
halign: Gtk.Align.START,
truncate: true,
xalign: 0,
label: props.description
label: (props.description instanceof Binding) ?
props.description.as((desc) => desc ? desc : "")
: (props.description || "")
} as Widget.LabelProps)
]
} as Widget.BoxProps)