✨ ags(pages): add ´show more´ kind of button to pages
This commit is contained in:
@@ -1,21 +1,32 @@
|
|||||||
import { AstalIO, bind, timeout } from "astal";
|
import { bind, Variable } from "astal";
|
||||||
import { Gtk, Widget } from "astal/gtk3";
|
import { Gtk, Widget } from "astal/gtk3";
|
||||||
import AstalBluetooth from "gi://AstalBluetooth";
|
import AstalBluetooth from "gi://AstalBluetooth";
|
||||||
import { Page } from "./Page";
|
import { Page } from "./Page";
|
||||||
import { Separator, SeparatorProps } from "../../Separator";
|
import { Separator, SeparatorProps } from "../../Separator";
|
||||||
|
|
||||||
let watchingDevices: boolean = false;
|
|
||||||
let watchTimeout: (AstalIO.Time|undefined);
|
const watchingDevices = new Variable<boolean>(false);
|
||||||
|
|
||||||
export const BluetoothPage: Page = new Page({
|
export const BluetoothPage: Page = new Page({
|
||||||
title: "Bluetooth Devices",
|
title: "Bluetooth Devices",
|
||||||
description: "Manage your Bluetooth devices and add new ones.",
|
description: "Manage your Bluetooth devices and add new ones.",
|
||||||
className: "bluetooth",
|
className: "bluetooth",
|
||||||
setup: () => {
|
headerButtons: () => [
|
||||||
watchingDevices = true;
|
new Widget.Button({
|
||||||
watchNewDevices();
|
className: "discover nf",
|
||||||
},
|
label: watchingDevices(watching => !watching ? '' : ''),
|
||||||
onClose: stopBluetoothDevicesWatch,
|
tooltipText: watchingDevices(watching => !watching ? "Start discovering" : "Stop discovery"),
|
||||||
|
onClick: () => {
|
||||||
|
if(watchingDevices.get()) {
|
||||||
|
stopBluetoothDevicesWatch();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
watchNewDevices();
|
||||||
|
}
|
||||||
|
} as Widget.ButtonProps)
|
||||||
|
],
|
||||||
|
onClose: () => stopBluetoothDevicesWatch(),
|
||||||
pageChild: () => new Widget.Box({
|
pageChild: () => new Widget.Box({
|
||||||
className: "connections",
|
className: "connections",
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
@@ -25,28 +36,49 @@ export const BluetoothPage: Page = new Page({
|
|||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "paired",
|
className: "paired",
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
children: bind(AstalBluetooth.get_default(), "devices").as((devices: Array<AstalBluetooth.Device>) =>
|
visible: bind(AstalBluetooth.get_default(), "devices").as((devs) =>
|
||||||
devices.filter((device: AstalBluetooth.Device) => device.connected || device.paired)
|
devs.filter(dev => dev.paired || dev.connected).length > 0),
|
||||||
.map((dev: AstalBluetooth.Device) =>
|
children: bind(AstalBluetooth.get_default(), "devices").as((devs: Array<AstalBluetooth.Device>) => {
|
||||||
DeviceWidget(dev)
|
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),
|
} as Widget.BoxProps),
|
||||||
Separator({
|
|
||||||
size: .5,
|
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
|
||||||
alpha: .7
|
|
||||||
} as SeparatorProps),
|
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "discovered",
|
className: "discovered",
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
children: bind(AstalBluetooth.get_default(), "devices").as((devices: Array<AstalBluetooth.Device>) =>
|
visible: bind(AstalBluetooth.get_default(), "devices").as((devs) =>
|
||||||
devices.filter((device: AstalBluetooth.Device) => !device.connected && !device.paired)
|
devs.filter((dev) => !dev.connected && !dev.paired).length > 0),
|
||||||
.map((dev: AstalBluetooth.Device) =>
|
children: bind(AstalBluetooth.get_default(), "devices").as((devices: Array<AstalBluetooth.Device>) => {
|
||||||
DeviceWidget(dev)
|
const discoveredDevices = devices.filter((dev: AstalBluetooth.Device) => !dev.connected && !dev.paired);
|
||||||
)
|
|
||||||
)
|
return [
|
||||||
} as Widget.BoxProps)
|
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)
|
} as Widget.BoxProps)
|
||||||
});
|
});
|
||||||
@@ -70,7 +102,8 @@ function DeviceWidget(dev: AstalBluetooth.Device): Gtk.Widget {
|
|||||||
className: "alias",
|
className: "alias",
|
||||||
halign: Gtk.Align.START,
|
halign: Gtk.Align.START,
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
label: bind(dev, "alias")
|
label: bind(dev, "alias").as((alias) => alias.split('-').length === 6 ?
|
||||||
|
`Unknown (${alias})` : alias)
|
||||||
} as Widget.LabelProps),
|
} as Widget.LabelProps),
|
||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "battery",
|
className: "battery",
|
||||||
@@ -86,30 +119,13 @@ function DeviceWidget(dev: AstalBluetooth.Device): Gtk.Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function watchNewDevices(): void {
|
function watchNewDevices(): void {
|
||||||
if(!watchTimeout) {
|
watchingDevices.set(true);
|
||||||
watchTimeout = timeout(5000, () => {
|
!AstalBluetooth.get_default().adapter.discovering &&
|
||||||
reloadBluetoothDevicesList(2500);
|
AstalBluetooth.get_default().adapter.start_discovery();
|
||||||
watchNewDevices();
|
|
||||||
watchTimeout = undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
stopBluetoothDevicesWatch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stopBluetoothDevicesWatch(): void {
|
export function stopBluetoothDevicesWatch(): void {
|
||||||
watchingDevices = false;
|
watchingDevices.set(false);
|
||||||
watchTimeout?.cancel();
|
|
||||||
watchTimeout = undefined;
|
|
||||||
|
|
||||||
AstalBluetooth.get_default().adapter.discovering &&
|
AstalBluetooth.get_default().adapter.discovering &&
|
||||||
AstalBluetooth.get_default().adapter.stop_discovery();
|
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());
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ import { Gtk, Widget } from "astal/gtk3";
|
|||||||
import { Page } from "./Page";
|
import { Page } from "./Page";
|
||||||
import AstalNetwork from "gi://AstalNetwork";
|
import AstalNetwork from "gi://AstalNetwork";
|
||||||
import { bind } from "astal";
|
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({
|
export const PageNetwork = new Page({
|
||||||
title: "Network",
|
title: "Network",
|
||||||
@@ -19,27 +23,61 @@ export const PageNetwork = new Page({
|
|||||||
],
|
],
|
||||||
pageChild: () => new Widget.Box({
|
pageChild: () => new Widget.Box({
|
||||||
expand: true,
|
expand: true,
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
children: [
|
children: [
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "devices",
|
className: "devices",
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
visible: bind(AstalNetwork.get_default().get_client(), "devices").as((devs) => devs.length > 0),
|
visible: bind(AstalNetwork.get_default().get_client(), "devices").as((devs) => devs.length > 0),
|
||||||
children: bind(AstalNetwork.get_default().get_client(), "devices").as((devices) => [
|
children: bind(AstalNetwork.get_default().get_client(), "devices").as((devices) => {
|
||||||
new Widget.Label({
|
devices = devices.filter(dev => dev.interface !== "lo");
|
||||||
label: "Devices",
|
|
||||||
xalign: 0,
|
return [
|
||||||
className: "sub-header",
|
new Widget.Label({
|
||||||
} as Widget.LabelProps),
|
label: "Devices",
|
||||||
...devices.map(dev => new Widget.Button({
|
|
||||||
className: "device",
|
|
||||||
child: new Widget.Label({
|
|
||||||
className: "interface name",
|
|
||||||
xalign: 0,
|
xalign: 0,
|
||||||
label: dev.interface
|
className: "sub-header",
|
||||||
} as Widget.LabelProps),
|
} 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),
|
} as Widget.BoxProps),
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "wireless-aps",
|
className: "wireless-aps",
|
||||||
@@ -70,6 +108,19 @@ export const PageNetwork = new Page({
|
|||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
} as Widget.ButtonProps))) : [],
|
} as Widget.ButtonProps))) : [],
|
||||||
} as Widget.BoxProps),
|
} 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)
|
} as Widget.BoxProps)
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user