feat(control-center/page): add bottom-buttons prop to add page-bottom buttons easily

also, no need for widgets, you just use a jsobject to create a button inside the prop array
This commit is contained in:
retrozinndev
2025-05-25 14:55:37 -03:00
parent 73b2e96c93
commit a25468e54a
4 changed files with 114 additions and 41 deletions
+14 -5
View File
@@ -121,7 +121,7 @@
& .sub-header { & .sub-header {
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
margin-bottom: 6px; margin-bottom: 4px;
} }
& button { & button {
@@ -135,6 +135,19 @@
} }
} }
& .bottom-buttons button {
& label.title {
font-size: 14px;
font-weight: 500;
}
& label.description {
font-size: 10px;
margin-top: -1px;
font-weight: 400;
color: colors.$fg-disabled;
}
}
& .extra-buttons { & .extra-buttons {
margin-left: 2px; margin-left: 2px;
& > button { & > button {
@@ -251,10 +264,6 @@ box.history {
button.connected { button.connected {
background: colors.$bg-tertiary; background: colors.$bg-tertiary;
} }
&.paired {
margin-bottom: 20px;
}
} }
} }
+8 -17
View File
@@ -2,7 +2,6 @@ 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, PageButton } from "./Page"; import { Page, PageButton } from "./Page";
import { Separator, SeparatorProps } from "../../Separator";
import { tr } from "../../../i18n/intl"; import { tr } from "../../../i18n/intl";
import AstalHyprland from "gi://AstalHyprland"; import AstalHyprland from "gi://AstalHyprland";
import { Windows } from "../../../windows"; import { Windows } from "../../../windows";
@@ -33,6 +32,13 @@ export const BluetoothPage: (() => Page) = () => new Page({
], ],
onClose: () => AstalBluetooth.get_default().adapter.discovering && onClose: () => AstalBluetooth.get_default().adapter.discovering &&
AstalBluetooth.get_default().adapter.stop_discovery(), AstalBluetooth.get_default().adapter.stop_discovery(),
bottomButtons: [{
title: tr("control_center.pages.more_settings"),
onClick: () => {
Windows.close("control-center");
AstalHyprland.get_default().dispatch("exec", "[float; animation slide right] overskride");
}
}],
spacing: 2, spacing: 2,
children: [ children: [
new Widget.Box({ new Widget.Box({
@@ -98,22 +104,7 @@ export const BluetoothPage: (() => Page) = () => new Page({
...discoveredDevices.map((dev: AstalBluetooth.Device) => DeviceWidget(dev)) ...discoveredDevices.map((dev: AstalBluetooth.Device) => DeviceWidget(dev))
] ]
}) })
} as Widget.BoxProps), } as Widget.BoxProps)
Separator({
size: .2,
orientation: Gtk.Orientation.VERTICAL,
cssColor: "gray",
alpha: .2
} as SeparatorProps),
new Widget.Button({
className: "more",
label: tr("control_center.pages.more_settings"),
onClick: () => {
Windows.close("control-center");
AstalHyprland.get_default().dispatch("exec", "[float; animation slide right] overskride");
},
setup: (self) => self.set_alignment(0, 0.5)
} as Widget.ButtonProps)
] ]
} as Widget.BoxProps) } as Widget.BoxProps)
] ]
+9 -16
View File
@@ -3,9 +3,8 @@ import { Page, PageButton } 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 NM from "gi://NM";
import { Separator, SeparatorProps } from "../../Separator";
import { Windows } from "../../../windows"; import { Windows } from "../../../windows";
import AstalHyprland from "gi://AstalHyprland?version=0.1"; import AstalHyprland from "gi://AstalHyprland";
import { tr } from "../../../i18n/intl"; import { tr } from "../../../i18n/intl";
export const PageNetwork: (() => Page) = () => new Page({ export const PageNetwork: (() => Page) = () => new Page({
@@ -23,6 +22,13 @@ export const PageNetwork: (() => Page) = () => new Page({
onClick: () => AstalNetwork.get_default().wifi.scan() onClick: () => AstalNetwork.get_default().wifi.scan()
} as Widget.ButtonProps) } as Widget.ButtonProps)
], ],
bottomButtons: [{
title: tr("control_center.pages.more_settings"),
onClick: () => {
Windows.close("control-center");
AstalHyprland.get_default().dispatch("exec", "[animationstyle gnomed] nm-connection-editor");
}
}],
children: [ children: [
new Widget.Box({ new Widget.Box({
className: "devices", className: "devices",
@@ -93,20 +99,7 @@ export const PageNetwork: (() => Page) = () => 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: tr("control_center.pages.more_settings"),
setup: (self) => self.set_alignment(0, 0.5),
onClick: () => {
Windows.close("control-center");
AstalHyprland.get_default().dispatch("exec", "[animationstyle gnomed] nm-connection-editor");
}
} as Widget.ButtonProps)
] ]
}); });
+83 -3
View File
@@ -1,32 +1,44 @@
import { Binding, register } from "astal"; import { Binding, register } from "astal";
import { Gtk, Widget } from "astal/gtk3"; import { Gtk, Widget } from "astal/gtk3";
import { Separator, SeparatorProps } from "../../Separator";
export type PageProps = { export type PageProps = {
setup?: () => void; setup?: () => void;
onClose?: () => void; onClose?: () => void;
onOpen?: () => void;
id: string; id: string;
className?: string | Binding<string>; className?: string | Binding<string>;
title: string | Binding<string>; title: string | Binding<string>;
description?: string | Binding<string>; description?: string | Binding<string>;
headerButtons?: Array<Gtk.Button> | Binding<Array<Gtk.Button>>; headerButtons?: Array<Gtk.Button> | Binding<Array<Gtk.Button>>;
bottomButtons?: Array<BottomButton> | Binding<Array<BottomButton>>;
orientation?: Gtk.Orientation | Binding<Gtk.Orientation>; orientation?: Gtk.Orientation | Binding<Gtk.Orientation>;
spacing?: number; spacing?: number;
child?: Gtk.Widget | Binding<Gtk.Widget>; child?: Gtk.Widget | Binding<Gtk.Widget>;
children?: Array<Gtk.Widget> | Binding<Array<Gtk.Widget>>; children?: Array<Gtk.Widget> | Binding<Array<Gtk.Widget>>;
}; };
export type BottomButton = {
title: string | Binding<string>;
description?: string | Binding<string>;
tooltipText?: string | Binding<string>;
tooltipMarkup?: string | Binding<string>;
onClick?: () => void;
};
export { Page }; export { Page };
@register({ GTypeName: "Page" }) @register({ GTypeName: "Page" })
class Page extends Widget.Box { class Page extends Widget.Box {
readonly #id: string; readonly #id: string | number;
readonly bottomButtons?: Array<BottomButton>;
#title: string | Binding<string>; #title: string | Binding<string>;
#description: string | undefined | Binding<string>; #description?: string | Binding<string>;
public get title() { return this.#title; } public get title() { return this.#title; }
public get description() { return this.#description; } public get description() { return this.#description; }
public get id() { return this.#id; } public get id() { return this.#id; }
public onClose?: () => void;
constructor(props: PageProps) { constructor(props: PageProps) {
super({ super({
@@ -35,6 +47,7 @@ class Page extends Widget.Box {
className: (props.className instanceof Binding) ? className: (props.className instanceof Binding) ?
props.className.as((clsName) => `page ${ clsName ?? "" }`) props.className.as((clsName) => `page ${ clsName ?? "" }`)
: `page ${props.className ?? ""}`, : `page ${props.className ?? ""}`,
setup: props.setup,
children: [ children: [
new Widget.Box({ new Widget.Box({
className: "header", className: "header",
@@ -83,6 +96,70 @@ class Page extends Widget.Box {
setup: props.setup, setup: props.setup,
child: props.child, child: props.child,
children: props.children children: props.children
} as Widget.BoxProps),
Separator({
alpha: .2,
spacing: 6,
orientation: Gtk.Orientation.VERTICAL,
visible: (props.bottomButtons instanceof Binding) ?
props.bottomButtons.as(buttons => buttons.length > 0)
: (!props.bottomButtons ? false : props.bottomButtons.length > 0)
} as SeparatorProps),
new Widget.Box({
className: "bottom-buttons",
orientation: Gtk.Orientation.VERTICAL,
visible: (props.bottomButtons instanceof Binding) ?
props.bottomButtons.as(buttons => buttons.length > 0)
: (!props.bottomButtons ? false : props.bottomButtons.length > 0),
spacing: 2,
children: (props.bottomButtons instanceof Binding) ?
props.bottomButtons.as(buttons => buttons.map(button =>
new Widget.Button({
onClicked: button.onClick,
tooltipMarkup: button.tooltipMarkup,
tooltipText: button.tooltipText,
child: new Widget.Box({
orientation: Gtk.Orientation.VERTICAL,
children: [
new Widget.Label({
className: "title",
label: button.title,
xalign: 0
} as Widget.LabelProps),
new Widget.Label({
className: "description",
label: button.description,
visible: Boolean(button.description),
xalign: 0
} as Widget.LabelProps)
]
} as Widget.BoxProps)
} as Widget.ButtonProps)
)
)
: (!props.bottomButtons ? [] : props.bottomButtons.map(button =>
new Widget.Button({
onClicked: button.onClick,
tooltipMarkup: button.tooltipMarkup,
tooltipText: button.tooltipText,
child: new Widget.Box({
orientation: Gtk.Orientation.VERTICAL,
children: [
new Widget.Label({
className: "title",
label: button.title,
xalign: 0
} as Widget.LabelProps),
new Widget.Label({
className: "description",
label: button.description,
visible: Boolean(button.description),
xalign: 0
} as Widget.LabelProps)
]
} as Widget.BoxProps)
} as Widget.ButtonProps)
))
} as Widget.BoxProps) } as Widget.BoxProps)
] ]
}); });
@@ -90,6 +167,9 @@ class Page extends Widget.Box {
this.#id = props.id; this.#id = props.id;
this.#title = props.title; this.#title = props.title;
this.#description = props.description; this.#description = props.description;
if(props.onClose)
this.onClose = props.onClose;
} }
} }