From afc0a5dacfde09ccab2e8090555074649d509554 Mon Sep 17 00:00:00 2001 From: retrozinndev Date: Thu, 10 Apr 2025 16:32:53 -0300 Subject: [PATCH] =?UTF-8?q?:sparkles:=20ags(pages):=20add=20=C2=B4show=20m?= =?UTF-8?q?ore=C2=B4=20kind=20of=20button=20to=20pages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ags/widget/control-center/pages/Bluetooth.ts | 112 +++++++++++-------- ags/widget/control-center/pages/Network.ts | 77 ++++++++++--- 2 files changed, 128 insertions(+), 61 deletions(-) diff --git a/ags/widget/control-center/pages/Bluetooth.ts b/ags/widget/control-center/pages/Bluetooth.ts index 4e828e6..13261bf 100644 --- a/ags/widget/control-center/pages/Bluetooth.ts +++ b/ags/widget/control-center/pages/Bluetooth.ts @@ -1,21 +1,32 @@ -import { AstalIO, bind, timeout } from "astal"; +import { bind, Variable } 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); + +const watchingDevices = new Variable(false); export const BluetoothPage: Page = new Page({ title: "Bluetooth Devices", description: "Manage your Bluetooth devices and add new ones.", className: "bluetooth", - setup: () => { - watchingDevices = true; - watchNewDevices(); - }, - onClose: stopBluetoothDevicesWatch, + headerButtons: () => [ + new Widget.Button({ + className: "discover nf", + label: watchingDevices(watching => !watching ? '󰑓' : '󰙦'), + tooltipText: watchingDevices(watching => !watching ? "Start discovering" : "Stop discovery"), + onClick: () => { + if(watchingDevices.get()) { + stopBluetoothDevicesWatch(); + return; + } + + watchNewDevices(); + } + } as Widget.ButtonProps) + ], + onClose: () => stopBluetoothDevicesWatch(), pageChild: () => new Widget.Box({ className: "connections", orientation: Gtk.Orientation.VERTICAL, @@ -25,28 +36,49 @@ export const BluetoothPage: Page = new Page({ new Widget.Box({ className: "paired", orientation: Gtk.Orientation.VERTICAL, - children: bind(AstalBluetooth.get_default(), "devices").as((devices: Array) => - devices.filter((device: AstalBluetooth.Device) => device.connected || device.paired) - .map((dev: AstalBluetooth.Device) => - DeviceWidget(dev) - ) - ) + visible: bind(AstalBluetooth.get_default(), "devices").as((devs) => + devs.filter(dev => dev.paired || dev.connected).length > 0), + children: bind(AstalBluetooth.get_default(), "devices").as((devs: Array) => { + const connectedDevices = devs.filter((dev: AstalBluetooth.Device) => dev.connected || dev.paired) + + return [ + new Widget.Label({ + className: "sub-header", + label: "Paired Devices", + xalign: 0, + } as Widget.LabelProps), + ...connectedDevices.map((dev: AstalBluetooth.Device) => DeviceWidget(dev)) + ] + }) } as Widget.BoxProps), - Separator({ - size: .5, - orientation: Gtk.Orientation.VERTICAL, - alpha: .7 - } as SeparatorProps), new Widget.Box({ className: "discovered", orientation: Gtk.Orientation.VERTICAL, - children: bind(AstalBluetooth.get_default(), "devices").as((devices: Array) => - devices.filter((device: AstalBluetooth.Device) => !device.connected && !device.paired) - .map((dev: AstalBluetooth.Device) => - DeviceWidget(dev) - ) - ) - } as Widget.BoxProps) + visible: bind(AstalBluetooth.get_default(), "devices").as((devs) => + devs.filter((dev) => !dev.connected && !dev.paired).length > 0), + children: bind(AstalBluetooth.get_default(), "devices").as((devices: Array) => { + const discoveredDevices = devices.filter((dev: AstalBluetooth.Device) => !dev.connected && !dev.paired); + + return [ + new Widget.Label({ + className: "sub-header", + label: "Others", + xalign: 0 + } as Widget.LabelProps), + ...discoveredDevices.map((dev: AstalBluetooth.Device) => DeviceWidget(dev)) + ] + }) + } as Widget.BoxProps), + Separator({ + size: .2, + orientation: Gtk.Orientation.VERTICAL, + alpha: .2 + } as SeparatorProps), + new Widget.Button({ + className: "more", + label: "More settings", + xalign: 0 + } as Widget.ButtonProps) ] } as Widget.BoxProps) }); @@ -70,7 +102,8 @@ function DeviceWidget(dev: AstalBluetooth.Device): Gtk.Widget { className: "alias", halign: Gtk.Align.START, hexpand: true, - label: bind(dev, "alias") + label: bind(dev, "alias").as((alias) => alias.split('-').length === 6 ? + `Unknown (${alias})` : alias) } as Widget.LabelProps), new Widget.Label({ className: "battery", @@ -86,30 +119,13 @@ function DeviceWidget(dev: AstalBluetooth.Device): Gtk.Widget { } function watchNewDevices(): void { - if(!watchTimeout) { - watchTimeout = timeout(5000, () => { - reloadBluetoothDevicesList(2500); - watchNewDevices(); - watchTimeout = undefined; - }); - - return; - } - - stopBluetoothDevicesWatch(); + watchingDevices.set(true); + !AstalBluetooth.get_default().adapter.discovering && + AstalBluetooth.get_default().adapter.start_discovery(); } export function stopBluetoothDevicesWatch(): void { - watchingDevices = false; - watchTimeout?.cancel(); - watchTimeout = undefined; - + watchingDevices.set(false); AstalBluetooth.get_default().adapter.discovering && AstalBluetooth.get_default().adapter.stop_discovery(); } - -export function reloadBluetoothDevicesList(discoveryTimeout?: number): void { - AstalBluetooth.get_default().adapter.start_discovery(); - timeout(discoveryTimeout || 2500, () => - AstalBluetooth.get_default().adapter.stop_discovery()); -} diff --git a/ags/widget/control-center/pages/Network.ts b/ags/widget/control-center/pages/Network.ts index 36c2e6e..3d3a947 100644 --- a/ags/widget/control-center/pages/Network.ts +++ b/ags/widget/control-center/pages/Network.ts @@ -2,6 +2,10 @@ import { Gtk, Widget } from "astal/gtk3"; import { Page } from "./Page"; import AstalNetwork from "gi://AstalNetwork"; import { bind } from "astal"; +import NM from "gi://NM"; +import { Separator, SeparatorProps } from "../../Separator"; +import { Windows } from "../../../windows"; +import AstalHyprland from "gi://AstalHyprland?version=0.1"; export const PageNetwork = new Page({ title: "Network", @@ -19,27 +23,61 @@ export const PageNetwork = new Page({ ], pageChild: () => new Widget.Box({ expand: true, + orientation: Gtk.Orientation.VERTICAL, children: [ new Widget.Box({ className: "devices", hexpand: true, orientation: Gtk.Orientation.VERTICAL, visible: bind(AstalNetwork.get_default().get_client(), "devices").as((devs) => devs.length > 0), - children: bind(AstalNetwork.get_default().get_client(), "devices").as((devices) => [ - new Widget.Label({ - label: "Devices", - xalign: 0, - className: "sub-header", - } as Widget.LabelProps), - ...devices.map(dev => new Widget.Button({ - className: "device", - child: new Widget.Label({ - className: "interface name", + children: bind(AstalNetwork.get_default().get_client(), "devices").as((devices) => { + devices = devices.filter(dev => dev.interface !== "lo"); + + return [ + new Widget.Label({ + label: "Devices", xalign: 0, - label: dev.interface + className: "sub-header", } as Widget.LabelProps), - } as Widget.ButtonProps)) - ]) + ...devices.filter(device => device.real).map(dev => new Widget.Button({ + className: "device", + child: bind(AstalNetwork.get_default(), "client").as((client) => new Widget.Box({ + children: [ + new Widget.Icon({ + className: "icon", + icon: bind(dev, "deviceType").as(deviceType => + deviceType === NM.DeviceType.WIFI ? + "network-wireless-symbolic" + : "network-wired-symbolic"), + css: "font-size: 20px; margin-right: 6px;" + } as Widget.IconProps), + new Widget.Label({ + className: "interface name", + xalign: 0, + hexpand: true, + label: bind(dev, "interface").as(iface => iface ?? "Unknown Interface") + } as Widget.LabelProps), + new Widget.Icon({ + icon: "object-select-symbolic", + halign: Gtk.Align.END, + visible: bind(client, "primaryConnection").as((primaryConn) => + primaryConn.devices.filter(device => device === dev)?.[0]).as(Boolean) + } as Widget.IconProps), + new Widget.EventBox({ + child: new Widget.Icon({ + icon: "view-more-symbolic" + } as Widget.IconProps), + onClick: () => { + Windows.close("control-center"); + AstalHyprland.get_default().dispatch("exec", + `[animationstyle gnomed] nm-connection-editor --edit ${dev.get_udi()}`); + } + } as Widget.EventBoxProps) + ] + } as Widget.BoxProps)) + } as Widget.ButtonProps)) + ] + }) } as Widget.BoxProps), new Widget.Box({ className: "wireless-aps", @@ -70,6 +108,19 @@ export const PageNetwork = new Page({ } as Widget.BoxProps) } as Widget.ButtonProps))) : [], } as Widget.BoxProps), + Separator({ + orientation: Gtk.Orientation.VERTICAL, + alpha: .2, + size: .2 + } as SeparatorProps), + new Widget.Button({ + label: "More settings", + xalign: 0, + onClick: () => { + Windows.close("control-center"); + AstalHyprland.get_default().dispatch("exec", "[animationstyle gnomed] nm-connection-editor"); + } + } as Widget.ButtonProps) ] } as Widget.BoxProps) });