✨ ags(bar, notifications, control-center): add status icons to bar, notification history fixed, notification history below control-center
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user