import GObject from "gi://GObject?version=2.0"; import Gtk from "gi://Gtk?version=3.0"; export const opened = Variable(""); App.connect("window-toggled", (_, name, visible) => { if (name === "quicksettings" && !visible) Utils.timeout(500, () => { opened.value = ""; }); }); /** * @param {{ * name: string, * activate?: false | (() => void), * } & import("../types/widgets/button").ButtonProps} props */ export const Arrow = ({ name, activate, ...props }) => { let deg = 0; let iconOpened = false; const icon = Widget.Icon("pan-end-symbolic").hook(opened, () => { if ( (opened.value === name && !iconOpened) || (opened.value !== name && iconOpened) ) { const step = opened.value === name ? 10 : -10; iconOpened = !iconOpened; for (let i = 0; i < 9; ++i) { Utils.timeout(15 * i, () => { deg += step; icon.setCss(`-gtk-icon-transform: rotate(${deg}deg);`); }); } } }); return Widget.Button({ child: icon, className: "qs-icon", onClicked: () => { opened.value = opened.value === name ? "" : name; if (typeof activate === "function") activate(); }, ...props, }); }; /** * @typedef {{ * name: string, * icon: Gtk.Widget, * label: Gtk.Widget, * activate: () => void * deactivate: () => void * activateOnArrow?: boolean * connection: [GObject.Object, () => boolean] * } & import("../types/widgets/box").BoxProps} ArrowToggleButtonProps * @param {ArrowToggleButtonProps} props */ export const ArrowToggleButton = ({ name, icon, label, activate, deactivate, activateOnArrow = true, connection: [service, condition], }) => Widget.Box({ className: "qs-button surface", setup: (self) => self.hook(service, () => { self.toggleClassName("accent", condition()); }), children: [ Widget.Button({ child: Widget.Box({ hexpand: true, children: [icon, label], }), onClicked: () => { if (condition()) { deactivate(); if (opened.value === name) opened.value = ""; } else { activate(); } }, }), Arrow({ name, activate: activateOnArrow && activate }), ], }); /** * @typedef {{ * icon: Gtk.Widget, * label: Gtk.Widget, * activate: () => void * deactivate: () => void * connection: [GObject.Object, () => boolean] * } & import("../types/widgets/box").BoxProps} SimpleToggleButtonProps * @param {SimpleToggleButtonProps} props */ export const SimpleToggleButton = ({ icon, label, activate, deactivate, connection: [service, condition], }) => Widget.Box({ className: "qs-button surface", setup: (self) => self.hook(service, () => { self.toggleClassName("accent", condition()); }), children: [ Widget.Button({ child: Widget.Box({ hexpand: true, children: [icon, label], }), onClicked: () => { if (condition()) { deactivate(); } else { activate(); } }, }), ], }); /** * @typedef {{ * name: string, * icon: Gtk.Widget, * title: string, * content: Gtk.Widget[], * } & import("../types/widgets/revealer").RevealerProps} MenuProps * @param {MenuProps} props */ export const Menu = ({ name, icon, title, content, ...props }) => Widget.Revealer({ transition: "slide_down", reveal_child: opened.bind().as((v) => v === name), child: Widget.Box({ className: "qs-submenu surface", vertical: true, children: [ Widget.Box({ className: "qs-sub-title accent", children: [ icon, Widget.Label({ className: "bold f16", truncate: "end", label: title, }), ], }), Widget.Box({ vertical: true, className: "qs-sub-content", children: content, }), ], }), ...props, }); /** @param {{type?: string, command?: string} & import("../types/widgets/button").ButtonProps} props */ export const SettingsButton = ({ type, command, ...props }) => Widget.Button({ onClicked: () => { Utils.execAsync(command ?? `gnome-control-center ${type}`); App.closeWindow("quicksettings"); }, hexpand: true, child: Widget.Box({ children: [ Widget.Icon("emblem-system-symbolic"), Widget.Label("Settings"), ], }), ...props, });